From 82e212e771017d111285238d472945641006aa41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Thu, 3 Aug 2017 13:05:46 +0200 Subject: [PATCH] [poincare] Template for double Change-Id: I7404bd5cefc9ef78a5dbd572c3874a557cded28e --- apps/calculation/calculation.cpp | 8 +- apps/calculation/calculation.h | 4 +- apps/calculation/local_context.cpp | 6 +- apps/calculation/local_context.h | 6 +- apps/graph/app.h | 2 +- apps/graph/cartesian_function.cpp | 6 +- apps/graph/cartesian_function.h | 2 +- apps/graph/graph/graph_controller.cpp | 4 +- .../hardware_test/battery_test_controller.cpp | 6 +- apps/probability/calculation_controller.cpp | 10 +- apps/probability/law_curve_view.h | 2 +- apps/regression/calculation_controller.cpp | 10 +- apps/regression/graph_controller.cpp | 16 +- apps/regression/graph_view.h | 4 +- apps/sequence/app.h | 2 +- apps/sequence/graph/term_sum_controller.cpp | 16 +- apps/sequence/local_context.cpp | 30 +- apps/sequence/local_context.h | 9 +- apps/sequence/sequence.cpp | 100 +-- apps/sequence/sequence.h | 52 +- apps/shared/curve_view.cpp | 6 +- .../editable_cell_table_view_controller.cpp | 6 +- apps/shared/float_parameter_controller.cpp | 6 +- apps/shared/function.cpp | 12 +- apps/shared/function.h | 8 +- apps/shared/function_graph_controller.cpp | 6 +- apps/shared/function_graph_view.h | 4 +- apps/shared/values_controller.cpp | 4 +- apps/statistics/box_controller.cpp | 4 +- apps/statistics/box_view.h | 2 +- apps/statistics/calculation_controller.cpp | 4 +- apps/statistics/histogram_controller.cpp | 10 +- apps/statistics/histogram_view.h | 2 +- apps/variable_box_controller.cpp | 24 +- apps/variable_box_controller.h | 8 +- ion/src/device/bench/command/adc.cpp | 4 +- poincare/Makefile | 1 - poincare/include/poincare/absolute_value.h | 8 +- poincare/include/poincare/addition.h | 11 +- poincare/include/poincare/arc_cosine.h | 8 +- poincare/include/poincare/arc_sine.h | 8 +- poincare/include/poincare/arc_tangent.h | 8 +- poincare/include/poincare/binary_operation.h | 36 +- .../include/poincare/binomial_coefficient.h | 4 +- poincare/include/poincare/ceiling.h | 8 +- poincare/include/poincare/complex.h | 88 ++- poincare/include/poincare/complex_argument.h | 8 +- poincare/include/poincare/complex_matrix.h | 20 +- .../include/poincare/confidence_interval.h | 4 +- poincare/include/poincare/conjugate.h | 8 +- poincare/include/poincare/context.h | 6 +- poincare/include/poincare/cosine.h | 14 +- poincare/include/poincare/derivative.h | 15 +- poincare/include/poincare/determinant.h | 4 +- poincare/include/poincare/division_quotient.h | 4 +- .../include/poincare/division_remainder.h | 4 +- poincare/include/poincare/evaluation.h | 18 +- poincare/include/poincare/expression.h | 15 +- poincare/include/poincare/expression_matrix.h | 5 +- poincare/include/poincare/factorial.h | 8 +- poincare/include/poincare/floor.h | 8 +- poincare/include/poincare/frac_part.h | 8 +- poincare/include/poincare/fraction.h | 26 +- poincare/include/poincare/function.h | 12 +- poincare/include/poincare/global_context.h | 19 +- .../include/poincare/great_common_divisor.h | 4 +- .../include/poincare/hyperbolic_arc_cosine.h | 9 +- .../include/poincare/hyperbolic_arc_sine.h | 8 +- .../include/poincare/hyperbolic_arc_tangent.h | 8 +- poincare/include/poincare/hyperbolic_cosine.h | 7 +- poincare/include/poincare/hyperbolic_sine.h | 7 +- .../include/poincare/hyperbolic_tangent.h | 7 +- poincare/include/poincare/imaginary_part.h | 8 +- poincare/include/poincare/integer.h | 3 +- poincare/include/poincare/integral.h | 17 +- .../include/poincare/least_common_multiple.h | 4 +- poincare/include/poincare/logarithm.h | 12 +- poincare/include/poincare/matrix_data.h | 3 +- poincare/include/poincare/matrix_dimension.h | 4 +- poincare/include/poincare/matrix_inverse.h | 4 +- poincare/include/poincare/matrix_trace.h | 4 +- poincare/include/poincare/matrix_transpose.h | 4 +- poincare/include/poincare/multiplication.h | 18 +- .../include/poincare/naperian_logarithm.h | 8 +- poincare/include/poincare/nth_root.h | 6 +- poincare/include/poincare/opposite.h | 8 +- poincare/include/poincare/parenthesis.h | 4 +- .../include/poincare/permute_coefficient.h | 4 +- poincare/include/poincare/power.h | 33 +- .../include/poincare/prediction_interval.h | 4 +- poincare/include/poincare/product.h | 10 +- poincare/include/poincare/reel_part.h | 8 +- poincare/include/poincare/round.h | 4 +- poincare/include/poincare/sequence.h | 9 +- poincare/include/poincare/sine.h | 14 +- poincare/include/poincare/square_root.h | 8 +- poincare/include/poincare/store.h | 4 +- poincare/include/poincare/subtraction.h | 17 +- poincare/include/poincare/sum.h | 10 +- poincare/include/poincare/symbol.h | 4 +- poincare/include/poincare/tangent.h | 13 +- .../include/poincare/trigonometric_function.h | 19 - poincare/include/poincare/variable_context.h | 7 +- poincare/src/absolute_value.cpp | 5 +- poincare/src/addition.cpp | 22 +- poincare/src/arc_cosine.cpp | 13 +- poincare/src/arc_sine.cpp | 13 +- poincare/src/arc_tangent.cpp | 13 +- poincare/src/binary_operation.cpp | 30 +- poincare/src/binomial_coefficient.cpp | 21 +- poincare/src/ceiling.cpp | 9 +- poincare/src/complex.cpp | 732 +++++++++--------- poincare/src/complex_argument.cpp | 5 +- poincare/src/complex_matrix.cpp | 57 +- poincare/src/confidence_interval.cpp | 23 +- poincare/src/conjugate.cpp | 3 +- poincare/src/cosine.cpp | 24 +- poincare/src/derivative.cpp | 97 +-- poincare/src/determinant.cpp | 8 +- poincare/src/division_quotient.cpp | 15 +- poincare/src/division_remainder.cpp | 15 +- poincare/src/evaluation.cpp | 81 +- poincare/src/expression.cpp | 25 +- poincare/src/expression_lexer.l | 4 +- poincare/src/expression_matrix.cpp | 16 +- poincare/src/expression_parser.y | 18 +- poincare/src/factorial.cpp | 19 +- poincare/src/floor.cpp | 9 +- poincare/src/frac_part.cpp | 9 +- poincare/src/fraction.cpp | 23 +- poincare/src/function.cpp | 19 +- poincare/src/global_context.cpp | 28 +- 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 | 17 +- poincare/src/hyperbolic_sine.cpp | 17 +- poincare/src/hyperbolic_tangent.cpp | 11 +- poincare/src/imaginary_part.cpp | 5 +- poincare/src/integer.cpp | 81 +- poincare/src/integral.cpp | 139 ++-- poincare/src/least_common_multiple.cpp | 15 +- poincare/src/logarithm.cpp | 24 +- poincare/src/matrix_data.cpp | 4 +- poincare/src/matrix_dimension.cpp | 13 +- poincare/src/matrix_inverse.cpp | 7 +- poincare/src/matrix_trace.cpp | 7 +- poincare/src/matrix_transpose.cpp | 7 +- poincare/src/multiplication.cpp | 31 +- poincare/src/naperian_logarithm.cpp | 9 +- poincare/src/nth_root.cpp | 20 +- poincare/src/opposite.cpp | 26 +- poincare/src/parenthesis.cpp | 5 +- poincare/src/permute_coefficient.cpp | 19 +- poincare/src/power.cpp | 57 +- poincare/src/prediction_interval.cpp | 23 +- poincare/src/product.cpp | 9 +- poincare/src/reel_part.cpp | 5 +- poincare/src/round.cpp | 17 +- poincare/src/sequence.cpp | 25 +- poincare/src/sine.cpp | 27 +- poincare/src/square_root.cpp | 9 +- poincare/src/store.cpp | 11 +- poincare/src/subtraction.cpp | 14 +- poincare/src/sum.cpp | 9 +- poincare/src/symbol.cpp | 7 +- poincare/src/tangent.cpp | 15 +- poincare/src/trigonometric_function.cpp | 31 - poincare/src/variable_context.cpp | 22 +- poincare/test/addition.cpp | 12 +- poincare/test/complex.cpp | 65 +- poincare/test/fraction.cpp | 14 +- poincare/test/function.cpp | 74 +- poincare/test/helper.cpp | 8 +- poincare/test/helper.h | 3 +- poincare/test/integer.cpp | 11 +- poincare/test/matrix.cpp | 5 +- poincare/test/parser.cpp | 26 +- poincare/test/power.cpp | 8 +- poincare/test/product.cpp | 12 +- poincare/test/subtraction.cpp | 16 +- poincare/test/symbol.cpp | 6 +- poincare/test/trigo.cpp | 24 +- 184 files changed, 2062 insertions(+), 1475 deletions(-) delete mode 100644 poincare/include/poincare/trigonometric_function.h delete mode 100644 poincare/src/trigonometric_function.cpp diff --git a/apps/calculation/calculation.cpp b/apps/calculation/calculation.cpp index 348ad9f4e..21066e263 100644 --- a/apps/calculation/calculation.cpp +++ b/apps/calculation/calculation.cpp @@ -52,7 +52,7 @@ void Calculation::reset() { void Calculation::setContent(const char * c, Context * context) { reset(); strlcpy(m_inputText, c, sizeof(m_inputText)); - Expression * evaluation = input()->evaluate(*context); + Evaluation * evaluation = input()->evaluate(*context); evaluation->writeTextInBuffer(m_outputText, sizeof(m_outputText)); delete evaluation; } @@ -79,15 +79,15 @@ ExpressionLayout * Calculation::inputLayout() { return m_inputLayout; } -Evaluation * 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'. */ Expression * exp = Expression::parse(m_outputText); if (exp != nullptr) { - m_output = exp->evaluate(*context); + m_output = exp->evaluate(*context); } else { - m_output = new Complex(Complex::Float(NAN)); + m_output = new Complex(Complex::Float(NAN)); } } return m_output; diff --git a/apps/calculation/calculation.h b/apps/calculation/calculation.h index f7a41335a..ffda27608 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::Evaluation * 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::Evaluation * 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 1eb6f2512..1f9983d1e 100644 --- a/apps/calculation/local_context.cpp +++ b/apps/calculation/local_context.cpp @@ -10,7 +10,7 @@ LocalContext::LocalContext(GlobalContext * parentContext, CalculationStore * cal { } -Evaluation * LocalContext::ansValue() { +Evaluation * LocalContext::ansValue() { if (m_calculationStore->numberOfCalculations() == 0) { return m_parentContext->defaultExpression(); } @@ -18,13 +18,13 @@ Evaluation * LocalContext::ansValue() { return lastCalculation->output(m_parentContext); } -void LocalContext::setExpressionForSymbolName(Evaluation * expression, const Symbol * symbol) { +void LocalContext::setExpressionForSymbolName(Expression * expression, const Symbol * symbol) { if (symbol->name() != Symbol::SpecialSymbols::Ans) { m_parentContext->setExpressionForSymbolName(expression, symbol); } } -const Evaluation * LocalContext::expressionForSymbol(const Symbol * symbol) { +const Expression * 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 1d3de885d..d8791577a 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::Evaluation * expression, const Poincare::Symbol * symbol) override; - const Poincare::Evaluation * expressionForSymbol(const Poincare::Symbol * symbol) override; + void setExpressionForSymbolName(Poincare::Expression * expression, const Poincare::Symbol * symbol) override; + const Poincare::Expression * expressionForSymbol(const Poincare::Symbol * symbol) override; private: - Poincare::Evaluation * ansValue(); + Poincare::Evaluation * ansValue(); CalculationStore * m_calculationStore; Poincare::GlobalContext * m_parentContext; }; diff --git a/apps/graph/app.h b/apps/graph/app.h index b0140fd64..2f8bd7cc7 100644 --- a/apps/graph/app.h +++ b/apps/graph/app.h @@ -40,7 +40,7 @@ public: Poincare::Context * localContext() override; private: App(Container * container, Snapshot * snapshot); - Poincare::VariableContext m_xContext; + Poincare::VariableContext m_xContext; ListController m_listController; ButtonRowController m_listFooter; ButtonRowController m_listHeader; diff --git a/apps/graph/cartesian_function.cpp b/apps/graph/cartesian_function.cpp index b28a05929..a9bb025b8 100644 --- a/apps/graph/cartesian_function.cpp +++ b/apps/graph/cartesian_function.cpp @@ -16,12 +16,12 @@ void CartesianFunction::setDisplayDerivative(bool display) { m_displayDerivative = display; } -float CartesianFunction::approximateDerivative(float x, Poincare::Context * context) const { - Poincare::Complex abscissa = Poincare::Complex::Float(x); +double CartesianFunction::approximateDerivative(double x, Poincare::Context * context) const { + Poincare::Complex abscissa = Poincare::Complex::Float(x); Poincare::Expression * args[2] = {expression(), &abscissa}; Poincare::Derivative derivative; derivative.setArgument(args, 2, true); - return derivative.approximate(*context); + return derivative.approximate(*context); } char CartesianFunction::symbol() const { diff --git a/apps/graph/cartesian_function.h b/apps/graph/cartesian_function.h index 2cb0984f4..42ee9e508 100644 --- a/apps/graph/cartesian_function.h +++ b/apps/graph/cartesian_function.h @@ -11,7 +11,7 @@ public: CartesianFunction(const char * text = nullptr, KDColor color = KDColorBlack); bool displayDerivative(); void setDisplayDerivative(bool display); - float approximateDerivative(float x, Poincare::Context * context) const; + double approximateDerivative(double x, Poincare::Context * context) const; char symbol() const override; private: bool m_displayDerivative; diff --git a/apps/graph/graph/graph_controller.cpp b/apps/graph/graph/graph_controller.cpp index 3b91c1000..309b3711e 100644 --- a/apps/graph/graph/graph_controller.cpp +++ b/apps/graph/graph/graph_controller.cpp @@ -32,7 +32,7 @@ void GraphController::reloadBannerView() { if (!m_bannerView.displayDerivative()) { return; } - char buffer[k_maxNumberOfCharacters+Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; + char buffer[k_maxNumberOfCharacters+PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; const char * legend = "00(x)="; int legendLength = strlen(legend); strlcpy(buffer, legend, legendLength+1); @@ -44,7 +44,7 @@ void GraphController::reloadBannerView() { buffer[1] = '\''; TextFieldDelegateApp * myApp = (TextFieldDelegateApp *)app(); float y = f->approximateDerivative(m_cursor->x(), myApp->localContext()); - Complex::convertFloatToText(y, buffer + legendLength, Complex::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits), Constant::MediumNumberOfSignificantDigits); + Complex::convertFloatToText(y, buffer + legendLength, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits), Constant::MediumNumberOfSignificantDigits); m_bannerView.setLegendAtIndex(buffer, 2); } diff --git a/apps/hardware_test/battery_test_controller.cpp b/apps/hardware_test/battery_test_controller.cpp index d760bd5ce..322e0dbd1 100644 --- a/apps/hardware_test/battery_test_controller.cpp +++ b/apps/hardware_test/battery_test_controller.cpp @@ -41,14 +41,14 @@ void BatteryTestController::viewWillAppear() { } void BatteryTestController::updateBatteryState(float batteryLevel, bool batteryCharging) { - char bufferLevel[ContentView::k_maxNumberOfCharacters + Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; + char bufferLevel[ContentView::k_maxNumberOfCharacters + PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; const char * legend = "Battery level: "; int legendLength = strlen(legend); strlcpy(bufferLevel, legend, legendLength+1); - Complex::convertFloatToText(batteryLevel, bufferLevel+legendLength, Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); + Complex::convertFloatToText(batteryLevel, bufferLevel+legendLength, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); m_view.batteryLevelTextView()->setText(bufferLevel); - char bufferCharging[ContentView::k_maxNumberOfCharacters + Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; + char bufferCharging[ContentView::k_maxNumberOfCharacters + PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; int numberOfChars = 0; legend = "Battery charging: "; legendLength = strlen(legend); diff --git a/apps/probability/calculation_controller.cpp b/apps/probability/calculation_controller.cpp index 551b47b07..699d998d3 100644 --- a/apps/probability/calculation_controller.cpp +++ b/apps/probability/calculation_controller.cpp @@ -65,8 +65,8 @@ View * CalculationController::ContentView::subviewAtIndex(int index) { } void CalculationController::ContentView::willDisplayEditableCellAtIndex(int index) { - char buffer[Complex::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)]; - Complex::convertFloatToText(m_calculation->parameterAtIndex(index), buffer, Complex::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits), Constant::ShortNumberOfSignificantDigits, Expression::FloatDisplayMode::Decimal); + char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)]; + Complex::convertFloatToText(m_calculation->parameterAtIndex(index), buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits), Constant::ShortNumberOfSignificantDigits, Expression::FloatDisplayMode::Decimal); m_calculationCell[index].setText(buffer); } @@ -218,7 +218,7 @@ bool CalculationController::textFieldShouldFinishEditing(TextField * textField, bool CalculationController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) { App * probaApp = (App *)app(); Context * globalContext = probaApp->container()->globalContext(); - float floatBody = Expression::approximate(text, *globalContext); + double floatBody = Expression::approximate(text, *globalContext); if (isnan(floatBody) || isinf(floatBody)) { app()->displayWarning(I18n::Message::UndefinedValue); return false; @@ -286,8 +286,8 @@ void CalculationController::updateTitle() { m_titleBuffer[currentChar++] = I18n::translate(m_law->parameterNameAtIndex(index))[0]; strlcpy(m_titleBuffer+currentChar, " = ", 4); currentChar += 3; - char buffer[Complex::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)]; - Complex::convertFloatToText(m_law->parameterValueAtIndex(index), buffer, Complex::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits), Constant::ShortNumberOfSignificantDigits, Expression::FloatDisplayMode::Decimal); + char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)]; + Complex::convertFloatToText(m_law->parameterValueAtIndex(index), buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits), Constant::ShortNumberOfSignificantDigits, Expression::FloatDisplayMode::Decimal); strlcpy(m_titleBuffer+currentChar, buffer, strlen(buffer)+1); currentChar += strlen(buffer); m_titleBuffer[currentChar++] = ' '; diff --git a/apps/probability/law_curve_view.h b/apps/probability/law_curve_view.h index 46d92afdf..402c54ea1 100644 --- a/apps/probability/law_curve_view.h +++ b/apps/probability/law_curve_view.h @@ -17,7 +17,7 @@ public: protected: char * label(Axis axis, int index) const override; private: - char m_labels[k_maxNumberOfXLabels][Poincare::Complex::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)]; + char m_labels[k_maxNumberOfXLabels][Poincare::PrintFloat::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)]; float evaluateModelWithParameter(Model * law, float abscissa) const override; Law * m_law; Calculation * m_calculation; diff --git a/apps/regression/calculation_controller.cpp b/apps/regression/calculation_controller.cpp index b4c16065d..d8fdefc79 100644 --- a/apps/regression/calculation_controller.cpp +++ b/apps/regression/calculation_controller.cpp @@ -156,10 +156,10 @@ void CalculationController::willDisplayCellAtLocation(HighlightCell * cell, int float calculation1 = (m_store->*calculationMethods[j-1])(0); float calculation2 = (m_store->*calculationMethods[j-1])(1); EvenOddDoubleBufferTextCell * myCell = (EvenOddDoubleBufferTextCell *)cell; - char buffer[Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; - Complex::convertFloatToText(calculation1, buffer, Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); + char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; + Complex::convertFloatToText(calculation1, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); myCell->setFirstText(buffer); - Complex::convertFloatToText(calculation2, buffer, Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); + Complex::convertFloatToText(calculation2, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); myCell->setSecondText(buffer); return; } @@ -174,8 +174,8 @@ void CalculationController::willDisplayCellAtLocation(HighlightCell * cell, int &Store::columnProductSum, nullptr, &Store::slope, &Store::yIntercept, &Store::correlationCoefficient, &Store::squaredCorrelationCoefficient}; float calculation = (m_store->*calculationMethods[j-k_totalNumberOfDoubleBufferRows-1])(); EvenOddBufferTextCell * myCell = (EvenOddBufferTextCell *)cell; - char buffer[Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; - Complex::convertFloatToText(calculation, buffer, Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); + char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; + Complex::convertFloatToText(calculation, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); myCell->setText(buffer); return; } diff --git a/apps/regression/graph_controller.cpp b/apps/regression/graph_controller.cpp index 6567c7bb0..e1b5c537a 100644 --- a/apps/regression/graph_controller.cpp +++ b/apps/regression/graph_controller.cpp @@ -61,7 +61,7 @@ bool GraphController::handleEnter() { void GraphController::reloadBannerView() { m_bannerView.setMessageAtIndex(I18n::Message::RegressionFormula, 3); - char buffer[k_maxNumberOfCharacters + Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; + char buffer[k_maxNumberOfCharacters + PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; int numberOfChar = 0; const char * legend = " P("; int legendLength = strlen(legend); @@ -78,7 +78,7 @@ void GraphController::reloadBannerView() { strlcpy(buffer+numberOfChar, legend, legendLength+1); numberOfChar += legendLength; } else { - numberOfChar += Complex::convertFloatToText(std::round((float)*m_selectedDotIndex+1.0f), buffer+numberOfChar, Complex::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits), Constant::ShortNumberOfSignificantDigits, Expression::FloatDisplayMode::Decimal); + numberOfChar += Complex::convertFloatToText(std::round((float)*m_selectedDotIndex+1.0f), buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits), Constant::ShortNumberOfSignificantDigits, Expression::FloatDisplayMode::Decimal); } legend = ") "; legendLength = strlen(legend); @@ -98,7 +98,7 @@ void GraphController::reloadBannerView() { legendLength = strlen(legend); strlcpy(buffer, legend, legendLength+1); numberOfChar += legendLength; - numberOfChar += Complex::convertFloatToText(x, buffer+numberOfChar, Complex::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits), Constant::MediumNumberOfSignificantDigits); + numberOfChar += Complex::convertFloatToText(x, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits), Constant::MediumNumberOfSignificantDigits); legend = " "; legendLength = strlen(legend); strlcpy(buffer+numberOfChar, legend, legendLength+1); @@ -116,7 +116,7 @@ void GraphController::reloadBannerView() { legendLength = strlen(legend); strlcpy(buffer, legend, legendLength+1); numberOfChar += legendLength; - numberOfChar += Complex::convertFloatToText(y, buffer+numberOfChar, Complex::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits), Constant::MediumNumberOfSignificantDigits); + numberOfChar += Complex::convertFloatToText(y, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits), Constant::MediumNumberOfSignificantDigits); legend = " "; legendLength = strlen(legend); strlcpy(buffer+numberOfChar, legend, legendLength+1); @@ -129,7 +129,7 @@ void GraphController::reloadBannerView() { legendLength = strlen(legend); strlcpy(buffer, legend, legendLength+1); numberOfChar += legendLength; - numberOfChar += Complex::convertFloatToText(slope, buffer+numberOfChar, Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); + numberOfChar += Complex::convertFloatToText(slope, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); legend = " "; legendLength = strlen(legend); strlcpy(buffer+numberOfChar, legend, legendLength+1); @@ -142,7 +142,7 @@ void GraphController::reloadBannerView() { legendLength = strlen(legend); strlcpy(buffer, legend, legendLength+1); numberOfChar += legendLength; - numberOfChar += Complex::convertFloatToText(yIntercept, buffer+numberOfChar, Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); + numberOfChar += Complex::convertFloatToText(yIntercept, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); legend = " "; legendLength = strlen(legend); strlcpy(buffer+numberOfChar, legend, legendLength+1); @@ -155,7 +155,7 @@ void GraphController::reloadBannerView() { legendLength = strlen(legend); strlcpy(buffer, legend, legendLength+1); numberOfChar += legendLength; - numberOfChar += Complex::convertFloatToText(r, buffer+numberOfChar, Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); + numberOfChar += Complex::convertFloatToText(r, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); legend = " "; legendLength = strlen(legend); strlcpy(buffer+numberOfChar, legend, legendLength+1); @@ -168,7 +168,7 @@ void GraphController::reloadBannerView() { legendLength = strlen(legend); strlcpy(buffer, legend, legendLength+1); numberOfChar += legendLength; - numberOfChar += Complex::convertFloatToText(r2, buffer+numberOfChar, Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); + numberOfChar += Complex::convertFloatToText(r2, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); legend = " "; legendLength = strlen(legend); strlcpy(buffer+numberOfChar, legend, legendLength+1); diff --git a/apps/regression/graph_view.h b/apps/regression/graph_view.h index c92c34bca..7b34dc9ad 100644 --- a/apps/regression/graph_view.h +++ b/apps/regression/graph_view.h @@ -16,8 +16,8 @@ private: char * label(Axis axis, int index) const override; float evaluateModelWithParameter(Model * curve, float t) const override; Store * m_store; - char m_xLabels[k_maxNumberOfXLabels][Poincare::Complex::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)]; - char m_yLabels[k_maxNumberOfYLabels][Poincare::Complex::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)]; + char m_xLabels[k_maxNumberOfXLabels][Poincare::PrintFloat::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)]; + char m_yLabels[k_maxNumberOfYLabels][Poincare::PrintFloat::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)]; }; } diff --git a/apps/sequence/app.h b/apps/sequence/app.h index a9d6cb51a..920572dff 100644 --- a/apps/sequence/app.h +++ b/apps/sequence/app.h @@ -39,7 +39,7 @@ public: const char * XNT() override; private: App(Container * container, Snapshot * snapshot); - LocalContext m_nContext; + LocalContext m_nContext; ListController m_listController; ButtonRowController m_listFooter; ButtonRowController m_listHeader; diff --git a/apps/sequence/graph/term_sum_controller.cpp b/apps/sequence/graph/term_sum_controller.cpp index 9b607a678..09ef52fcf 100644 --- a/apps/sequence/graph/term_sum_controller.cpp +++ b/apps/sequence/graph/term_sum_controller.cpp @@ -198,8 +198,8 @@ void TermSumController::LegendView::setSumSubscript(float start) { m_sumLayout = nullptr; } const char sigma[3] = {' ',Ion::Charset::CapitalSigma, 0}; - char buffer[Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; - Complex::convertFloatToText(start, buffer, Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, Expression::FloatDisplayMode::Decimal); + char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; + Complex::convertFloatToText(start, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, Expression::FloatDisplayMode::Decimal); m_sumLayout = new CondensedSumLayout(new StringLayout(sigma, 2), new StringLayout(buffer, strlen(buffer), KDText::FontSize::Small), nullptr); m_sum.setExpression(m_sumLayout); m_sum.setAlignment(0.0f, 0.5f); @@ -211,10 +211,10 @@ void TermSumController::LegendView::setSumSuperscript(float start, float end) { m_sumLayout = nullptr; } const char sigma[3] = {' ', Ion::Charset::CapitalSigma, 0}; - char bufferStart[Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; - Complex::convertFloatToText(start, bufferStart, Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, Expression::FloatDisplayMode::Decimal); - char bufferEnd[Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; - Complex::convertFloatToText(end, bufferEnd, Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, Expression::FloatDisplayMode::Decimal); + char bufferStart[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; + Complex::convertFloatToText(start, bufferStart, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, Expression::FloatDisplayMode::Decimal); + char bufferEnd[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; + Complex::convertFloatToText(end, bufferEnd, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, Expression::FloatDisplayMode::Decimal); m_sumLayout = new CondensedSumLayout(new StringLayout(sigma, 2), new StringLayout(bufferStart, strlen(bufferStart), KDText::FontSize::Small), new StringLayout(bufferEnd, strlen(bufferEnd), KDText::FontSize::Small)); m_sum.setExpression(m_sumLayout); m_sum.setAlignment(0.0f, 0.5f); @@ -222,9 +222,9 @@ void TermSumController::LegendView::setSumSuperscript(float start, float end) { void TermSumController::LegendView::setSumResult(const char * sequenceName, float result) { ExpressionLayout * childrenLayouts[3]; - char buffer[2+Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; + char buffer[2+PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; strlcpy(buffer, "= ", 3); - Complex::convertFloatToText(result, buffer+2, Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); + Complex::convertFloatToText(result, buffer+2, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); childrenLayouts[2] = new StringLayout(buffer, strlen(buffer), KDText::FontSize::Small); childrenLayouts[1] = new BaselineRelativeLayout(new StringLayout(sequenceName, 1, KDText::FontSize::Small), new StringLayout("n", 1, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript); childrenLayouts[0] = m_sumLayout; diff --git a/apps/sequence/local_context.cpp b/apps/sequence/local_context.cpp index 7218eddc2..efd1791aa 100644 --- a/apps/sequence/local_context.cpp +++ b/apps/sequence/local_context.cpp @@ -5,33 +5,35 @@ using namespace Poincare; namespace Sequence { -LocalContext::LocalContext(Context * parentContext) : - VariableContext('n', parentContext), - m_values{{Complex::Float(NAN), Complex::Float(NAN)}, - {Complex::Float(NAN), Complex::Float(NAN)} - //, {Complex::Float(NAN), Complex::Float(NAN)} - } +template +LocalContext::LocalContext(Context * parentContext) : + VariableContext('n', parentContext), + m_values{{Complex::Float(NAN), Complex::Float(NAN)}, + {Complex::Float(NAN), Complex::Float(NAN)}} { } -const Evaluation * LocalContext::expressionForSymbol(const Symbol * symbol) { +template +const Expression * 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) { return &m_values[nameIndexForSymbol(symbol)][rankIndexForSymbol(symbol)]; } - return VariableContext::expressionForSymbol(symbol); + return VariableContext::expressionForSymbol(symbol); } -void LocalContext::setValueForSequenceRank(float value, const char * sequenceName, int rank) { +template +void LocalContext::setValueForSequenceRank(T value, const char * sequenceName, int rank) { for (int i = 0; i < SequenceStore::k_maxNumberOfSequences; i++) { if (strcmp(sequenceName, SequenceStore::k_sequenceNames[i]) == 0) { - m_values[i][rank] = Complex::Float(value); + m_values[i][rank] = Complex::Float(value); } } } -int LocalContext::nameIndexForSymbol(const Poincare::Symbol * symbol) { +template +int LocalContext::nameIndexForSymbol(const Poincare::Symbol * symbol) { switch (symbol->name()) { case Symbol::SpecialSymbols::un: return 0; @@ -50,7 +52,8 @@ int LocalContext::nameIndexForSymbol(const Poincare::Symbol * symbol) { } } -int LocalContext::rankIndexForSymbol(const Poincare::Symbol * symbol) { +template +int LocalContext::rankIndexForSymbol(const Poincare::Symbol * symbol) { switch (symbol->name()) { case Symbol::SpecialSymbols::un: return 0; @@ -69,4 +72,7 @@ int LocalContext::rankIndexForSymbol(const Poincare::Symbol * symbol) { } } +template class LocalContext; +template class LocalContext; + } diff --git a/apps/sequence/local_context.h b/apps/sequence/local_context.h index e05512b7f..6b1e69ea3 100644 --- a/apps/sequence/local_context.h +++ b/apps/sequence/local_context.h @@ -6,16 +6,17 @@ namespace Sequence { -class LocalContext : public Poincare::VariableContext { +template +class LocalContext : public Poincare::VariableContext { public: LocalContext(Poincare::Context * parentContext); - const Poincare::Evaluation * expressionForSymbol(const Poincare::Symbol * symbol) override; - void setValueForSequenceRank(float value, const char * sequenceName, int rank); + const Poincare::Expression * expressionForSymbol(const Poincare::Symbol * symbol) override; + void setValueForSequenceRank(T value, const char * sequenceName, int rank); private: constexpr static int k_depth = 2; int nameIndexForSymbol(const Poincare::Symbol * symbol); int rankIndexForSymbol(const Poincare::Symbol * symbol); - Poincare::Complex m_values[SequenceStore::k_maxNumberOfSequences][k_depth]; + Poincare::Complex m_values[SequenceStore::k_maxNumberOfSequences][k_depth]; }; } diff --git a/apps/sequence/sequence.cpp b/apps/sequence/sequence.cpp index 029e449e6..6a618ab10 100644 --- a/apps/sequence/sequence.cpp +++ b/apps/sequence/sequence.cpp @@ -2,7 +2,6 @@ #include "local_context.h" #include "../../poincare/src/layout/string_layout.h" #include "../../poincare/src/layout/baseline_relative_layout.h" -#include #include #include @@ -24,8 +23,10 @@ Sequence::Sequence(const char * text, KDColor color) : m_definitionName(nullptr), m_firstInitialConditionName(nullptr), m_secondInitialConditionName(nullptr), - m_indexBuffer{-1, -1}, - m_buffer{NAN, NAN} + m_indexBufferFloat{-1, -1}, + m_indexBufferDouble{-1, -1}, + m_bufferFloat{NAN, NAN}, + m_bufferDouble{NAN, NAN} { } @@ -71,15 +72,12 @@ Sequence& Sequence::operator=(const Sequence& other) { const char * contentText = other.text(); const char * firstInitialText = other.m_firstInitialConditionText; const char * secondInitialText = other.m_secondInitialConditionText; - int indexBuffer0 = other.m_indexBuffer[0]; - int indexBuffer1 = other.m_indexBuffer[1]; Function::operator=(other); setType(other.m_type); setContent(contentText); setFirstInitialConditionContent(firstInitialText); setSecondInitialConditionContent(secondInitialText); - m_indexBuffer[0] = indexBuffer0; - m_indexBuffer[1] = indexBuffer1; + resetBuffer(); return *this; } @@ -132,8 +130,7 @@ void Sequence::setType(Type type) { } setFirstInitialConditionContent(""); setSecondInitialConditionContent(""); - m_indexBuffer[0] = -1; - m_indexBuffer[1] = -1; + resetBuffer(); } Poincare::Expression * Sequence::firstInitialConditionExpression() const { @@ -166,8 +163,7 @@ Poincare::ExpressionLayout * Sequence::secondInitialConditionLayout() { void Sequence::setContent(const char * c) { Function::setContent(c); - m_indexBuffer[0] = -1; - m_indexBuffer[1] = -1; + resetBuffer(); } void Sequence::setFirstInitialConditionContent(const char * c) { @@ -180,8 +176,7 @@ void Sequence::setFirstInitialConditionContent(const char * c) { delete m_firstInitialConditionLayout; m_firstInitialConditionLayout = nullptr; } - m_indexBuffer[0] = -1; - m_indexBuffer[1] = -1; + resetBuffer(); } void Sequence::setSecondInitialConditionContent(const char * c) { @@ -194,8 +189,7 @@ void Sequence::setSecondInitialConditionContent(const char * c) { delete m_secondInitialConditionLayout; m_secondInitialConditionLayout = nullptr; } - m_indexBuffer[0] = -1; - m_indexBuffer[1] = -1; + resetBuffer(); } char Sequence::symbol() const { @@ -272,8 +266,9 @@ bool Sequence::isEmpty() { } } -float Sequence::evaluateAtAbscissa(float x, Poincare::Context * context) const { - float n = std::round(x); +template +T Sequence::templatedEvaluateAtAbscissa(T x, Poincare::Context * context) const { + T n = std::round(x); switch (m_type) { case Type::Explicite: if (n < 0) { @@ -286,22 +281,22 @@ float Sequence::evaluateAtAbscissa(float x, Poincare::Context * context) const { return NAN; } if (n == 0) { - m_indexBuffer[0] = 0; - m_buffer[0] = firstInitialConditionExpression()->approximate(*context); - return m_buffer[0]; + setBufferIndexValue(0,0); + setBufferValue(firstInitialConditionExpression()->approximate(*context), 0); + return bufferValue(0); } - LocalContext subContext = LocalContext(context); + LocalContext subContext = LocalContext(context); Poincare::Symbol nSymbol = Poincare::Symbol(symbol()); - int start = m_indexBuffer[0] < 0 || m_indexBuffer[0] > n ? 0 : m_indexBuffer[0]; - float un = m_indexBuffer[0] < 0 || m_indexBuffer[0] > n ? firstInitialConditionExpression()->approximate(*context) : m_buffer[0]; + int start = indexBuffer(0) < 0 || indexBuffer(0) > n ? 0 : indexBuffer(0); + T un = indexBuffer(0) < 0 || indexBuffer(0) > n ? firstInitialConditionExpression()->approximate(*context) : bufferValue(0); for (int i = start; i < n; i++) { subContext.setValueForSequenceRank(un, name(), 0); - Poincare::Complex e = Poincare::Complex::Float(i); + Poincare::Complex e = Poincare::Complex::Float(i); subContext.setExpressionForSymbolName(&e, &nSymbol); - un = expression()->approximate(subContext); + un = expression()->approximate(subContext); } - m_buffer[0] = un; - m_indexBuffer[0] = n; + setBufferValue(un, 0); + setBufferIndexValue(n, 0); return un; } default: @@ -310,46 +305,46 @@ float Sequence::evaluateAtAbscissa(float x, Poincare::Context * context) const { return NAN; } if (n == 0) { - return firstInitialConditionExpression()->approximate(*context); + return firstInitialConditionExpression()->approximate(*context); } if (n == 1) { - m_indexBuffer[0] = 0; - m_buffer[0] = firstInitialConditionExpression()->approximate(*context); - m_indexBuffer[1] = 1; - m_buffer[1] = secondInitialConditionExpression()->approximate(*context); - return m_buffer[1]; + setBufferIndexValue(0, 0); + setBufferValue(firstInitialConditionExpression()->approximate(*context), 0); + setBufferIndexValue(1, 1); + setBufferValue(secondInitialConditionExpression()->approximate(*context), 1); + return bufferValue(1); } - LocalContext subContext = LocalContext(context); + LocalContext subContext = LocalContext(context); Poincare::Symbol nSymbol = Poincare::Symbol(symbol()); - int start = m_indexBuffer[0] >= 0 && m_indexBuffer[0] < n && m_indexBuffer[1] > 0 && m_indexBuffer[1] <= n && m_indexBuffer[0] + 1 == m_indexBuffer[1] ? m_indexBuffer[0] : 0; - float un = m_indexBuffer[0] >= 0 && m_indexBuffer[0] < n && m_indexBuffer[1] > 0 && m_indexBuffer[1] <= n && m_indexBuffer[0] + 1 == m_indexBuffer[1] ? m_buffer[0] : firstInitialConditionExpression()->approximate(*context); - float un1 = m_indexBuffer[0] >= 0 && m_indexBuffer[0] < n && m_indexBuffer[1] > 0 && m_indexBuffer[1] <= n && m_indexBuffer[0] + 1 == m_indexBuffer[1] ? m_buffer[1] : secondInitialConditionExpression()->approximate(*context); + int start = indexBuffer(0) >= 0 && indexBuffer(0) < n && indexBuffer(1) > 0 && indexBuffer(1) <= n && indexBuffer(0) + 1 == indexBuffer(1) ? indexBuffer(0) : 0; + T un = indexBuffer(0) >= 0 && indexBuffer(0) < n && indexBuffer(1) > 0 && indexBuffer(1) <= n && indexBuffer(0) + 1 == indexBuffer(1) ? bufferValue(0) : firstInitialConditionExpression()->approximate(*context); + T un1 = indexBuffer(0) >= 0 && indexBuffer(0) < n && indexBuffer(1) > 0 && indexBuffer(1) <= n && indexBuffer(0) + 1 == indexBuffer(1) ? bufferValue(1) : secondInitialConditionExpression()->approximate(*context); for (int i = start; i < n-1; i++) { subContext.setValueForSequenceRank(un, name(), 0); subContext.setValueForSequenceRank(un1, name(), 1); - Poincare::Complex e = Poincare::Complex::Float(i); + Poincare::Complex e = Poincare::Complex::Float(i); subContext.setExpressionForSymbolName(&e, &nSymbol); un = un1; - un1 = expression()->approximate(subContext); + un1 = expression()->approximate(subContext); } - m_buffer[0] = un; - m_indexBuffer[0] = n-1; - m_buffer[1] = un1; - m_indexBuffer[1] = n; + setBufferValue(un, 0); + setBufferIndexValue(n-1, 0); + setBufferValue(un1, 1); + setBufferIndexValue(n, 1); return un1; } } } -float Sequence::sumOfTermsBetweenAbscissa(float start, float end, Context * context) { - float result = 0.0f; - if (end-start > k_maxNumberOfTermsInSum || start + 1.0f == start) { +double Sequence::sumOfTermsBetweenAbscissa(double start, double end, Context * context) { + double result = 0.0; + if (end-start > k_maxNumberOfTermsInSum || start + 1.0 == start) { return NAN; } - for (float i = std::round(start); i <= std::round(end); i = i + 1.0f) { - /* When |start| >> 1.0f, start + 1.0f = start. In that case, quit the + for (double i = std::round(start); i <= std::round(end); i = i + 1.0) { + /* When |start| >> 1.0, start + 1.0 = start. In that case, quit the * infinite loop. */ - if (i == i-1.0f || i == i+1.0f) { + if (i == i-1.0 || i == i+1.0) { return NAN; } result += evaluateAtAbscissa(i, context); @@ -393,4 +388,11 @@ void Sequence::tidy() { } } +void Sequence::resetBuffer() const { + m_indexBufferFloat[0] = -1; + m_indexBufferFloat[1] = -1; + m_indexBufferDouble[0] = -1; + m_indexBufferDouble[1] = -1; +} + } diff --git a/apps/sequence/sequence.h b/apps/sequence/sequence.h index 42c58661d..c14687fbf 100644 --- a/apps/sequence/sequence.h +++ b/apps/sequence/sequence.h @@ -2,6 +2,7 @@ #define SEQUENCE_SEQUENCE_H #include "../shared/function.h" +#include namespace Sequence { @@ -37,15 +38,21 @@ public: Poincare::ExpressionLayout * secondInitialConditionName(); bool isDefined() override; bool isEmpty() override; - float evaluateAtAbscissa(float x, Poincare::Context * context) const override; - float sumOfTermsBetweenAbscissa(float start, float end, Poincare::Context * context); + float evaluateAtAbscissa(float x, Poincare::Context * context) const override { + return templatedEvaluateAtAbscissa(x, context); + } + double evaluateAtAbscissa(double x, Poincare::Context * context) const override { + return templatedEvaluateAtAbscissa(x, context); + } + double sumOfTermsBetweenAbscissa(double start, double end, Poincare::Context * context); void tidy() override; private: constexpr static int k_maxRecurrentRank = 10000; - constexpr static float k_maxNumberOfTermsInSum = 100000.0f; + constexpr static double k_maxNumberOfTermsInSum = 100000.0; constexpr static size_t k_dataLengthInBytes = (3*TextField::maxBufferSize()+3)*sizeof(char)+1; static_assert((k_dataLengthInBytes & 0x3) == 0, "The sequence data size is not a multiple of 4 bytes (cannot compute crc)"); // Assert that dataLengthInBytes is a multiple of 4 char symbol() const override; + template T templatedEvaluateAtAbscissa(T x, Poincare::Context * context) const; Type m_type; char m_firstInitialConditionText[TextField::maxBufferSize()]; char m_secondInitialConditionText[TextField::maxBufferSize()]; @@ -63,8 +70,43 @@ private: * superior rank k > n+1 is called, we avoid iterating from 0 but can start * from n. */ constexpr static int k_maxRecurrenceDepth = 2; - mutable int m_indexBuffer[k_maxRecurrenceDepth]; - mutable float m_buffer[k_maxRecurrenceDepth]; + mutable int m_indexBufferFloat[k_maxRecurrenceDepth]; + mutable int m_indexBufferDouble[k_maxRecurrenceDepth]; + mutable float m_bufferFloat[k_maxRecurrenceDepth]; + mutable double m_bufferDouble[k_maxRecurrenceDepth]; + void resetBuffer() const; + template void setBufferValue(T value, int i) const { + assert(i >= 0 && i < k_maxRecurrentRank); + if (sizeof(T) == sizeof(float)) { + m_bufferFloat[i] = value; + } else { + m_bufferDouble[i] = value; + } + } + template void setBufferIndexValue(int index, int i) const { + assert(i >= 0 && i < k_maxRecurrentRank); + if (sizeof(T) == sizeof(float)) { + m_indexBufferFloat[i] = index; + } else { + m_indexBufferDouble[i] = index; + } + } + template T bufferValue(int i) const { + assert(i >= 0 && i < k_maxRecurrentRank); + if (sizeof(T) == sizeof(float)) { + return m_bufferFloat[i]; + } else { + return m_bufferDouble[i]; + } + } + template int indexBuffer(int i) const { + assert(i >= 0 && i < k_maxRecurrentRank); + if (sizeof(T) == sizeof(float)) { + return m_indexBufferFloat[i]; + } else { + return m_indexBufferDouble[i]; + } + } }; } diff --git a/apps/shared/curve_view.cpp b/apps/shared/curve_view.cpp index 1f0c0ec79..ec5585c7b 100644 --- a/apps/shared/curve_view.cpp +++ b/apps/shared/curve_view.cpp @@ -114,15 +114,15 @@ float CurveView::floatToPixel(Axis axis, float f) const { } void CurveView::computeLabels(Axis axis) { - char buffer[Complex::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)]; + char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)]; float step = gridUnit(axis); for (int index = 0; index < numberOfLabels(axis); index++) { float labelValue = 2.0f*step*(std::ceil(min(axis)/(2.0f*step)))+index*2.0f*step; if (labelValue < step && labelValue > -step) { labelValue = 0.0f; } - Complex::convertFloatToText(labelValue, buffer, - Complex::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits), + Complex::convertFloatToText(labelValue, buffer, + PrintFloat::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits), Constant::ShortNumberOfSignificantDigits, Expression::FloatDisplayMode::Decimal); //TODO: check for size of label? strlcpy(label(axis, index), buffer, strlen(buffer)+1); diff --git a/apps/shared/editable_cell_table_view_controller.cpp b/apps/shared/editable_cell_table_view_controller.cpp index 586bf2e6d..c0c31c9f5 100644 --- a/apps/shared/editable_cell_table_view_controller.cpp +++ b/apps/shared/editable_cell_table_view_controller.cpp @@ -23,7 +23,7 @@ bool EditableCellTableViewController::textFieldShouldFinishEditing(TextField * t bool EditableCellTableViewController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) { AppsContainer * appsContainer = ((TextFieldDelegateApp *)app())->container(); Context * globalContext = appsContainer->globalContext(); - float floatBody = Expression::approximate(text, *globalContext); + float floatBody = Expression::approximate(text, *globalContext); if (isnan(floatBody) || isinf(floatBody)) { app()->displayWarning(I18n::Message::UndefinedValue); return false; @@ -79,7 +79,7 @@ void EditableCellTableViewController::willDisplayCellAtLocationWithDisplayMode(H // The cell is editable if (cellAtLocationIsEditable(i, j)) { EvenOddEditableTextCell * myEditableValueCell = (EvenOddEditableTextCell *)cell; - char buffer[Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; + char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; // Special case 1: last row if (j == numberOfRows() - 1) { /* Display an empty line only if there is enough space for a new element in @@ -93,7 +93,7 @@ void EditableCellTableViewController::willDisplayCellAtLocationWithDisplayMode(H } if (!myEditableValueCell->isEditing()) { myCell->setEven(j%2 == 0); - Complex::convertFloatToText(dataAtLocation(i, j), buffer, Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, floatDisplayMode); + Complex::convertFloatToText(dataAtLocation(i, j), buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, floatDisplayMode); myEditableValueCell->setText(buffer); } return; diff --git a/apps/shared/float_parameter_controller.cpp b/apps/shared/float_parameter_controller.cpp index af2341b32..ff8f8c2d9 100644 --- a/apps/shared/float_parameter_controller.cpp +++ b/apps/shared/float_parameter_controller.cpp @@ -104,8 +104,8 @@ void FloatParameterController::willDisplayCellForIndex(HighlightCell * cell, int if (myCell->isEditing()) { return; } - char buffer[Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; - Complex::convertFloatToText(parameterAtIndex(index), buffer, Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, Expression::FloatDisplayMode::Decimal); + char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; + Complex::convertFloatToText(parameterAtIndex(index), buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, Expression::FloatDisplayMode::Decimal); myCell->setAccessoryText(buffer); } @@ -118,7 +118,7 @@ bool FloatParameterController::textFieldShouldFinishEditing(TextField * textFiel bool FloatParameterController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) { AppsContainer * appsContainer = ((TextFieldDelegateApp *)app())->container(); Context * globalContext = appsContainer->globalContext(); - float floatBody = Expression::approximate(text, *globalContext); + float floatBody = Expression::approximate(text, *globalContext); if (isnan(floatBody) || isinf(floatBody)) { app()->displayWarning(I18n::Message::UndefinedValue); return false; diff --git a/apps/shared/function.cpp b/apps/shared/function.cpp index f37e25083..9ad67890a 100644 --- a/apps/shared/function.cpp +++ b/apps/shared/function.cpp @@ -99,12 +99,13 @@ bool Function::isEmpty() { return m_text[0] == 0; } -float Function::evaluateAtAbscissa(float x, Poincare::Context * context) const { - Poincare::VariableContext variableContext = Poincare::VariableContext(symbol(), context); +template +T Function::templatedEvaluateAtAbscissa(T x, Poincare::Context * context) const { + Poincare::VariableContext variableContext = Poincare::VariableContext(symbol(), context); Poincare::Symbol xSymbol = Poincare::Symbol(symbol()); - Poincare::Complex e = Poincare::Complex::Float(x); + Poincare::Complex e = Poincare::Complex::Float(x); variableContext.setExpressionForSymbolName(&e, &xSymbol); - return expression()->approximate(variableContext); + return expression()->approximate(variableContext); } void Function::tidy() { @@ -119,3 +120,6 @@ void Function::tidy() { } } + +template float Shared::Function::templatedEvaluateAtAbscissa(float, Poincare::Context*) const; +template double Shared::Function::templatedEvaluateAtAbscissa(double, Poincare::Context*) const; diff --git a/apps/shared/function.h b/apps/shared/function.h index 8f331f344..2e6303bfe 100644 --- a/apps/shared/function.h +++ b/apps/shared/function.h @@ -27,11 +27,17 @@ public: virtual bool isEmpty(); virtual void setContent(const char * c); void setColor(KDColor m_color); - virtual float evaluateAtAbscissa(float x, Poincare::Context * context) const; + virtual float evaluateAtAbscissa(float x, Poincare::Context * context) const { + return templatedEvaluateAtAbscissa(x, context); + } + virtual double evaluateAtAbscissa(double x, Poincare::Context * context) const { + return templatedEvaluateAtAbscissa(x, context); + } virtual void tidy(); private: constexpr static size_t k_dataLengthInBytes = (TextField::maxBufferSize()+2)*sizeof(char)+2; static_assert((k_dataLengthInBytes & 0x3) == 0, "The function data size is not a multiple of 4 bytes (cannot compute crc)"); // Assert that dataLengthInBytes is a multiple of 4 + template T templatedEvaluateAtAbscissa(T x, Poincare::Context * context) const; virtual char symbol() const = 0; mutable Poincare::Expression * m_expression; char m_text[TextField::maxBufferSize()]; diff --git a/apps/shared/function_graph_controller.cpp b/apps/shared/function_graph_controller.cpp index fc010f088..6474ef65f 100644 --- a/apps/shared/function_graph_controller.cpp +++ b/apps/shared/function_graph_controller.cpp @@ -48,14 +48,14 @@ bool FunctionGraphController::handleEnter() { } void FunctionGraphController::reloadBannerView() { - char buffer[k_maxNumberOfCharacters+Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; + char buffer[k_maxNumberOfCharacters+PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; const char * legend = "0="; int legendLength = strlen(legend); int numberOfChar = 0; strlcpy(buffer, legend, legendLength+1); numberOfChar += legendLength; buffer[0] = functionStore()->symbol(); - numberOfChar += Complex::convertFloatToText(m_cursor->x(), buffer+numberOfChar, Complex::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits), Constant::MediumNumberOfSignificantDigits); + numberOfChar += Complex::convertFloatToText(m_cursor->x(), buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits), Constant::MediumNumberOfSignificantDigits); legend = " "; legendLength = strlen(legend); strlcpy(buffer+numberOfChar, legend, legendLength+1); @@ -73,7 +73,7 @@ void FunctionGraphController::reloadBannerView() { assert(m_indexFunctionSelectedByCursor < functionStore()->numberOfActiveFunctions()); Function * f = functionStore()->activeFunctionAtIndex(m_indexFunctionSelectedByCursor); buffer[0] = f->name()[0]; - numberOfChar += Complex::convertFloatToText(m_cursor->y(), buffer+legendLength, Complex::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits), Constant::MediumNumberOfSignificantDigits); + numberOfChar += Complex::convertFloatToText(m_cursor->y(), buffer+legendLength, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits), Constant::MediumNumberOfSignificantDigits); legend = " "; legendLength = strlen(legend); strlcpy(buffer+numberOfChar, legend, legendLength+1); diff --git a/apps/shared/function_graph_view.h b/apps/shared/function_graph_view.h index d0159ecd2..281db74a5 100644 --- a/apps/shared/function_graph_view.h +++ b/apps/shared/function_graph_view.h @@ -17,8 +17,8 @@ public: Poincare::Context * context() const; private: char * label(Axis axis, int index) const override; - char m_xLabels[k_maxNumberOfXLabels][Poincare::Complex::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)]; - char m_yLabels[k_maxNumberOfYLabels][Poincare::Complex::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)]; + char m_xLabels[k_maxNumberOfXLabels][Poincare::PrintFloat::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)]; + char m_yLabels[k_maxNumberOfYLabels][Poincare::PrintFloat::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)]; Poincare::Context * m_context; }; diff --git a/apps/shared/values_controller.cpp b/apps/shared/values_controller.cpp index d81618135..1958c9089 100644 --- a/apps/shared/values_controller.cpp +++ b/apps/shared/values_controller.cpp @@ -129,7 +129,7 @@ void ValuesController::willDisplayCellAtLocation(HighlightCell * cell, int i, in } // The cell is not a title cell and not editable if (j > 0 && i > 0) { - char buffer[Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; + char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; // Special case: last row if (j == numberOfRows() - 1) { int numberOfIntervalElements = m_interval->numberOfElements(); @@ -143,7 +143,7 @@ void ValuesController::willDisplayCellAtLocation(HighlightCell * cell, int i, in // The cell is a value cell EvenOddBufferTextCell * myValueCell = (EvenOddBufferTextCell *)cell; float x = m_interval->element(j-1); - Complex::convertFloatToText(evaluationOfAbscissaAtColumn(x, i), buffer, Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); + Complex::convertFloatToText(evaluationOfAbscissaAtColumn(x, i), buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); myValueCell->setText(buffer); } } diff --git a/apps/statistics/box_controller.cpp b/apps/statistics/box_controller.cpp index a686fe6a7..2b739d98a 100644 --- a/apps/statistics/box_controller.cpp +++ b/apps/statistics/box_controller.cpp @@ -67,11 +67,11 @@ Responder * BoxController::tabController() const { void BoxController::reloadBannerView() { I18n::Message calculationName[5] = {I18n::Message::Minimum, I18n::Message::FirstQuartile, I18n::Message::Median, I18n::Message::ThirdQuartile, I18n::Message::Maximum}; m_boxBannerView.setMessageAtIndex(calculationName[(int)m_view.selectedQuantile()], 0); - char buffer[Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; + char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; CalculPointer calculationMethods[5] = {&Store::minValue, &Store::firstQuartile, &Store::median, &Store::thirdQuartile, &Store::maxValue}; float calculation = (m_store->*calculationMethods[(int)m_view.selectedQuantile()])(); - Complex::convertFloatToText(calculation, buffer, Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); + Complex::convertFloatToText(calculation, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); m_boxBannerView.setLegendAtIndex(buffer, 1); } diff --git a/apps/statistics/box_view.h b/apps/statistics/box_view.h index 979c4d7f7..a156297e8 100644 --- a/apps/statistics/box_view.h +++ b/apps/statistics/box_view.h @@ -28,7 +28,7 @@ private: char * label(Axis axis, int index) const override; Store * m_store; BoxRange m_boxRange; - char m_labels[k_maxNumberOfXLabels][Poincare::Complex::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)]; + char m_labels[k_maxNumberOfXLabels][Poincare::PrintFloat::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)]; Quantile * m_selectedQuantile; }; diff --git a/apps/statistics/calculation_controller.cpp b/apps/statistics/calculation_controller.cpp index 66eaf5252..9637e4f1b 100644 --- a/apps/statistics/calculation_controller.cpp +++ b/apps/statistics/calculation_controller.cpp @@ -83,8 +83,8 @@ void CalculationController::willDisplayCellAtLocation(HighlightCell * cell, int &Store::thirdQuartile, &Store::median, &Store::quartileRange, &Store::sum, &Store::squaredValueSum}; float calculation = (m_store->*calculationMethods[j])(); EvenOddBufferTextCell * myCell = (EvenOddBufferTextCell *)cell; - char buffer[Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; - Complex::convertFloatToText(calculation, buffer, Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); + char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; + Complex::convertFloatToText(calculation, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); myCell->setText(buffer); } } diff --git a/apps/statistics/histogram_controller.cpp b/apps/statistics/histogram_controller.cpp index 164f08939..396b47e6c 100644 --- a/apps/statistics/histogram_controller.cpp +++ b/apps/statistics/histogram_controller.cpp @@ -149,17 +149,17 @@ Responder * HistogramController::tabController() const { } void HistogramController::reloadBannerView() { - char buffer[k_maxNumberOfCharacters+ Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)*2]; + char buffer[k_maxNumberOfCharacters+ PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)*2]; int numberOfChar = 0; const char * legend = " ["; int legendLength = strlen(legend); strlcpy(buffer, legend, legendLength+1); numberOfChar += legendLength; float lowerBound = m_store->startOfBarAtIndex(*m_selectedBarIndex); - numberOfChar += Complex::convertFloatToText(lowerBound, buffer+numberOfChar, Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); + numberOfChar += Complex::convertFloatToText(lowerBound, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); buffer[numberOfChar++] = ';'; float upperBound = m_store->endOfBarAtIndex(*m_selectedBarIndex); - numberOfChar += Complex::convertFloatToText(upperBound, buffer+numberOfChar, Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); + numberOfChar += Complex::convertFloatToText(upperBound, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); buffer[numberOfChar++] = '['; legend = " "; legendLength = strlen(legend); @@ -173,7 +173,7 @@ void HistogramController::reloadBannerView() { strlcpy(buffer, legend, legendLength+1); numberOfChar += legendLength; float size = m_store->heightOfBarAtIndex(*m_selectedBarIndex); - numberOfChar += Complex::convertFloatToText(size, buffer+numberOfChar, Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); + numberOfChar += Complex::convertFloatToText(size, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); legend = " "; legendLength = strlen(legend); strlcpy(buffer+numberOfChar, legend, legendLength+1); @@ -186,7 +186,7 @@ void HistogramController::reloadBannerView() { strlcpy(buffer, legend, legendLength+1); numberOfChar += legendLength; float frequency = size/m_store->sumOfColumn(1); - numberOfChar += Complex::convertFloatToText(frequency, buffer+numberOfChar, Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); + numberOfChar += Complex::convertFloatToText(frequency, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); legend = " "; legendLength = strlen(legend); strlcpy(buffer+numberOfChar, legend, legendLength+1); diff --git a/apps/statistics/histogram_view.h b/apps/statistics/histogram_view.h index 1278c1008..17437579d 100644 --- a/apps/statistics/histogram_view.h +++ b/apps/statistics/histogram_view.h @@ -18,7 +18,7 @@ private: char * label(Axis axis, int index) const override; float evaluateModelWithParameter(Model * curve, float t) const override; Store * m_store; - char m_labels[k_maxNumberOfXLabels][Poincare::Complex::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)]; + char m_labels[k_maxNumberOfXLabels][Poincare::PrintFloat::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)]; float m_highlightedBarStart; float m_highlightedBarEnd; }; diff --git a/apps/variable_box_controller.cpp b/apps/variable_box_controller.cpp index 6f51c4cc5..9a31d8304 100644 --- a/apps/variable_box_controller.cpp +++ b/apps/variable_box_controller.cpp @@ -6,7 +6,7 @@ using namespace Poincare; /* ContentViewController */ -VariableBoxController::ContentViewController::ContentViewController(Responder * parentResponder, Context * context) : +VariableBoxController::ContentViewController::ContentViewController(Responder * parentResponder, GlobalContext * context) : ViewController(parentResponder), m_context(context), m_firstSelectedRow(0), @@ -137,11 +137,11 @@ void VariableBoxController::ContentViewController::willDisplayCellForIndex(Highl char label[3]; putLabelAtIndexInBuffer(index, label); myCell->setLabel(label); - const Evaluation * evaluation = expressionForIndex(index); + const Evaluation * evaluation = expressionForIndex(index); if (m_currentPage == Page::Scalar) { myCell->displayExpression(false); - char buffer[Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; - evaluation->writeTextInBuffer(buffer, Complex::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)); + char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; + evaluation->writeTextInBuffer(buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)); myCell->setSubtitle(buffer); return; } @@ -149,10 +149,10 @@ void VariableBoxController::ContentViewController::willDisplayCellForIndex(Highl if (evaluation) { /* TODO: implement list contexts */ myCell->setExpression(evaluation); - char buffer[2*Complex::bufferSizeForFloatsWithPrecision(2)+1]; - int numberOfChars = Complex::convertFloatToText(evaluation->numberOfRows(), buffer, Complex::bufferSizeForFloatsWithPrecision(2), 2, Expression::FloatDisplayMode::Decimal); + char buffer[2*PrintFloat::bufferSizeForFloatsWithPrecision(2)+1]; + int numberOfChars = Complex::convertFloatToText(evaluation->numberOfRows(), buffer, PrintFloat::bufferSizeForFloatsWithPrecision(2), 2, Expression::FloatDisplayMode::Decimal); buffer[numberOfChars++] = 'x'; - Complex::convertFloatToText(evaluation->numberOfColumns(), buffer+numberOfChars, Complex::bufferSizeForFloatsWithPrecision(2), 2, Expression::FloatDisplayMode::Decimal); + Complex::convertFloatToText(evaluation->numberOfColumns(), buffer+numberOfChars, PrintFloat::bufferSizeForFloatsWithPrecision(2), 2, Expression::FloatDisplayMode::Decimal); myCell->setSubtitle(buffer); } else { myCell->setExpression(nullptr); @@ -167,7 +167,7 @@ KDCoordinate VariableBoxController::ContentViewController::rowHeight(int index) if (m_currentPage == Page::Scalar) { return k_leafRowHeight; } - const Expression * expression = expressionForIndex(index); + const Evaluation * expression = expressionForIndex(index); if (expression) { ExpressionLayout * layout = expression->createLayout(); KDCoordinate expressionHeight = layout->size().height(); @@ -201,14 +201,14 @@ int VariableBoxController::ContentViewController::typeAtLocation(int i, int j) { return 0; } -const Evaluation * 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); + return m_context->evaluationForSymbol(&symbol); } if (m_currentPage == Page::Matrix) { const Symbol symbol = Symbol::matrixSymbol('0'+(char)index); - return m_context->expressionForSymbol(&symbol); + return m_context->evaluationForSymbol(&symbol); } #if LIST_VARIABLES if (m_currentPage == Page::List) { @@ -277,7 +277,7 @@ void VariableBoxController::ContentViewController::viewDidDisappear() { ViewController::viewDidDisappear(); } -VariableBoxController::VariableBoxController(Context * context) : +VariableBoxController::VariableBoxController(GlobalContext * context) : StackViewController(nullptr, &m_contentViewController, true, KDColorWhite, Palette::PurpleBright, Palette::PurpleDark), m_contentViewController(this, context) { diff --git a/apps/variable_box_controller.h b/apps/variable_box_controller.h index 79036fa48..51aa009bf 100644 --- a/apps/variable_box_controller.h +++ b/apps/variable_box_controller.h @@ -10,7 +10,7 @@ class VariableBoxController : public StackViewController { public: - VariableBoxController(Poincare::Context * context); + VariableBoxController(Poincare::GlobalContext * context); void didBecomeFirstResponder() override; void setTextFieldCaller(TextField * textField); void viewWillAppear() override; @@ -18,7 +18,7 @@ public: private: class ContentViewController : public ViewController, public ListViewDataSource, public SelectableTableViewDataSource { public: - ContentViewController(Responder * parentResponder, Poincare::Context * context); + ContentViewController(Responder * parentResponder, Poincare::GlobalContext * context); View * view() override; const char * title() override; void didBecomeFirstResponder() override; @@ -56,9 +56,9 @@ private: Page pageAtIndex(int index); void putLabelAtIndexInBuffer(int index, char * buffer); I18n::Message nodeLabelAtIndex(int index); - const Poincare::Evaluation * expressionForIndex(int index); + const Poincare::Evaluation * expressionForIndex(int index); - Poincare::Context * m_context; + Poincare::GlobalContext * m_context; TextField * m_textFieldCaller; int m_firstSelectedRow; int m_previousSelectedRow; diff --git a/ion/src/device/bench/command/adc.cpp b/ion/src/device/bench/command/adc.cpp index b824405c7..9f7886358 100644 --- a/ion/src/device/bench/command/adc.cpp +++ b/ion/src/device/bench/command/adc.cpp @@ -15,9 +15,9 @@ void ADC(const char * input) { } float result = Ion::Battery::voltage(); constexpr int precision = 8; - constexpr int bufferSize = Poincare::Complex::bufferSizeForFloatsWithPrecision(precision); + constexpr int bufferSize = Poincare::PrintFloat::bufferSizeForFloatsWithPrecision(precision); char responseBuffer[bufferSize+4] = {'A', 'D', 'C', '='}; // ADC= - Poincare::Complex::convertFloatToText(result, responseBuffer+4, bufferSize, precision); + Poincare::Complex::convertFloatToText(result, responseBuffer+4, bufferSize, precision); reply(responseBuffer); } diff --git a/poincare/Makefile b/poincare/Makefile index dabfef752..cc1b3feef 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -72,7 +72,6 @@ objs += $(addprefix poincare/src/,\ sum.o\ symbol.o\ tangent.o\ - trigonometric_function.o\ variable_context.o\ ) objs += $(addprefix poincare/src/layout/,\ diff --git a/poincare/include/poincare/absolute_value.h b/poincare/include/poincare/absolute_value.h index 2902e8043..17fd3d8e0 100644 --- a/poincare/include/poincare/absolute_value.h +++ b/poincare/include/poincare/absolute_value.h @@ -12,7 +12,13 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c); + } + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c); + } + template Complex templatedComputeComplex(const Complex c) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; }; diff --git a/poincare/include/poincare/addition.h b/poincare/include/poincare/addition.h index 485850805..cd702bf9f 100644 --- a/poincare/include/poincare/addition.h +++ b/poincare/include/poincare/addition.h @@ -12,11 +12,14 @@ 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); + template static Complex compute(const Complex c, const Complex d); + template static Evaluation * computeOnMatrices(Evaluation * m, Evaluation * n); + template static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * m); private: - Complex privateCompute(const Complex c, const Complex d) const override { + Complex privateCompute(const Complex c, const Complex d) const override { + return compute(c, d); + } + 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 202e8da4b..66135bc63 100644 --- a/poincare/include/poincare/arc_cosine.h +++ b/poincare/include/poincare/arc_cosine.h @@ -12,7 +12,13 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c, angleUnit); + } + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c, angleUnit); + } + template Complex templatedComputeComplex(const Complex c, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/arc_sine.h b/poincare/include/poincare/arc_sine.h index afaccc878..5c137c325 100644 --- a/poincare/include/poincare/arc_sine.h +++ b/poincare/include/poincare/arc_sine.h @@ -12,7 +12,13 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c, angleUnit); + } + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c, angleUnit); + } + template Complex templatedComputeComplex(const Complex c, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/arc_tangent.h b/poincare/include/poincare/arc_tangent.h index b90afe480..83f58324e 100644 --- a/poincare/include/poincare/arc_tangent.h +++ b/poincare/include/poincare/arc_tangent.h @@ -12,7 +12,13 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c, angleUnit); + } + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c, angleUnit); + } + template Complex templatedComputeComplex(const Complex c, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/binary_operation.h b/poincare/include/poincare/binary_operation.h index 54d6e36a6..49eb30538 100644 --- a/poincare/include/poincare/binary_operation.h +++ b/poincare/include/poincare/binary_operation.h @@ -23,14 +23,36 @@ public: Expression * clone() const override; protected: Expression * m_operands[2]; - 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 Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + + virtual Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const { + return templatedComputeOnComplexAndComplexMatrix(c, n); } - virtual Complex privateCompute(const Complex c, const Complex d) const = 0; + virtual Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const { + return templatedComputeOnComplexAndComplexMatrix(c, n); + } + template Evaluation * templatedComputeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const; + + virtual Evaluation * computeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const { + return templatedComputeOnComplexMatrixAndComplex(m, d); + } + virtual Evaluation * computeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const { + return templatedComputeOnComplexMatrixAndComplex(m, d); + } + template Evaluation * templatedComputeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const; + + virtual Evaluation * computeOnComplexMatrices(Evaluation * m, Evaluation * n) const { + return templatedComputeOnComplexMatrices(m, n); + } + virtual Evaluation * computeOnComplexMatrices(Evaluation * m, Evaluation * n) const { + return templatedComputeOnComplexMatrices(m, n); + } + template Evaluation * templatedComputeOnComplexMatrices(Evaluation * m, Evaluation * n) const; + + virtual Complex privateCompute(const Complex c, const Complex d) const = 0; + 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 61cdb4618..e37f1aede 100644 --- a/poincare/include/poincare/binomial_coefficient.h +++ b/poincare/include/poincare/binomial_coefficient.h @@ -12,7 +12,9 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; }; diff --git a/poincare/include/poincare/ceiling.h b/poincare/include/poincare/ceiling.h index 19078612b..22e32d06a 100644 --- a/poincare/include/poincare/ceiling.h +++ b/poincare/include/poincare/ceiling.h @@ -12,7 +12,13 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c); + } + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c); + } + template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/complex.h b/poincare/include/poincare/complex.h index 61f94c7a7..5fbc957bb 100644 --- a/poincare/include/poincare/complex.h +++ b/poincare/include/poincare/complex.h @@ -6,38 +6,54 @@ namespace Poincare { -class Complex : public Evaluation { +namespace PrintFloat { + constexpr static int bufferSizeForFloatsWithPrecision(int numberOfSignificantDigits) { + // The wors case is -1.234E-38 + return numberOfSignificantDigits + 7; + } + /* This function prints the int i in the buffer with a '.' at the position + * specified by the decimalMarkerPosition. It starts printing at the end of the + * buffer and print from right to left. The integer given should be of the right + * length to be written in bufferLength chars. If the integer is to small, the + * empty chars on the left side are completed with '0'. If the integer is too + * big, the printing stops when no more empty chars are available without + * returning any warning. */ + void printBase10IntegerWithDecimalMarker(char * buffer, int bufferSize, int i, int decimalMarkerPosition); +} + +template +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() : m_a(0), m_b(0) {} + static Complex Float(T x); + static Complex Cartesian(T a, T b); + static Complex Polar(T r, T 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 { + T toScalar() const override; + const Complex * operand(int i) const override { return complexOperand(i); } int numberOfRows() const override; int numberOfColumns() const override; - Type type() const override; - Complex * clone() const override; - Evaluation * cloneWithDifferentOperands(Expression** newOperands, + Expression::Type type() const override; + 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 { + Evaluation * createDeterminant() const override { return clone(); } - Evaluation * createInverse() const override; - Evaluation * createTrace() const override { + Evaluation * createInverse() const override; + Evaluation * createTrace() const override { return clone(); } - float a() const; - float b() const; - float r() const; - float th() const; - Complex conjugate() const; + T a() const; + T b() const; + T r() const; + T th() const; + 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 @@ -49,17 +65,15 @@ public: * is truncated at the end of the buffer. * ConvertFloat to Text return the number of characters that have been written * in buffer (excluding the last \O character) */ - static int convertFloatToText(float f, char * buffer, int bufferSize, int numberOfSignificantDigits, FloatDisplayMode mode = FloatDisplayMode::Default); - constexpr static int bufferSizeForFloatsWithPrecision(int numberOfSignificantDigits) { - // The wors case is -1.234E-38 - return numberOfSignificantDigits + 7; - } + static int convertFloatToText(T d, char * buffer, int bufferSize, int numberOfSignificantDigits, Expression::FloatDisplayMode mode = Expression::FloatDisplayMode::Default); private: - Complex(float a, float b); - const Complex * complexOperand(int i) const override; + Complex(T a, T b); + const Complex * complexOperand(int i) const override; constexpr static int k_numberOfSignificantDigits = 7; - ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - Evaluation * privateEvaluate(Context& context, AngleUnit angleUnit) const override; + ExpressionLayout * privateCreateLayout(Expression::FloatDisplayMode floatDisplayMode, Expression::ComplexFormat complexFormat) const override; + Evaluation * privateEvaluate(Expression::SinglePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Evaluation * privateEvaluate(Expression::DoublePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Evaluation * templatedEvaluate(Context& context, Expression::AngleUnit angleUnit) const; /* 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 @@ -70,20 +84,12 @@ private: constexpr static int k_maxComplexBufferLength = 13+13+7+1; /* convertComplexToText and convertFloatToTextPrivate return the string length * of the buffer (does not count the 0 last char)*/ - int convertComplexToText(char * buffer, int bufferSize, FloatDisplayMode FloatDisplayMode, ComplexFormat complexFormat) const; - static int convertFloatToTextPrivate(float f, char * buffer, int numberOfSignificantDigits, FloatDisplayMode mode); - /* This function prints the int i in the buffer with a '.' at the position - * specified by the decimalMarkerPosition. It starts printing at the end of the - * buffer and print from right to left. The integer given should be of the right - * length to be written in bufferLength chars. If the integer is to small, the - * empty chars on the left side are completed with '0'. If the integer is too - * big, the printing stops when no more empty chars are available without - * returning any warning. */ - static void printBase10IntegerWithDecimalMarker(char * buffer, int bufferSize, int i, int decimalMarkerPosition); - ExpressionLayout * createPolarLayout(FloatDisplayMode floatDisplayMode) const; - ExpressionLayout * createCartesianLayout(FloatDisplayMode floatDisplayMode) const; - float m_a; - float m_b; + int convertComplexToText(char * buffer, int bufferSize, Expression::FloatDisplayMode floatDisplayMode, Expression::ComplexFormat complexFormat) const; + static int convertFloatToTextPrivate(T f, char * buffer, int numberOfSignificantDigits, Expression::FloatDisplayMode mode); + ExpressionLayout * createPolarLayout(Expression::FloatDisplayMode floatDisplayMode) const; + ExpressionLayout * createCartesianLayout(Expression::FloatDisplayMode floatDisplayMode) const; + T m_a; + T m_b; }; } diff --git a/poincare/include/poincare/complex_argument.h b/poincare/include/poincare/complex_argument.h index e45664b44..64d66366e 100644 --- a/poincare/include/poincare/complex_argument.h +++ b/poincare/include/poincare/complex_argument.h @@ -12,7 +12,13 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c); + } + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c); + } + template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/complex_matrix.h b/poincare/include/poincare/complex_matrix.h index 66cc268ce..aed8cb155 100644 --- a/poincare/include/poincare/complex_matrix.h +++ b/poincare/include/poincare/complex_matrix.h @@ -5,24 +5,28 @@ namespace Poincare { -class ComplexMatrix : public Evaluation { +template +class ComplexMatrix : public Evaluation { public: - ComplexMatrix(const Complex * complexes, int numberOfRows, int numberOfColumns); + 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; + T toScalar() 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, + ComplexMatrix * clone() const override; + ComplexMatrix * cloneWithDifferentOperands(Expression** newOperands, int numberOfOperands, bool cloneOperands = true) const override; - static Evaluation * createIdentity(int dim); + static Evaluation * createIdentity(int dim); private: - Complex * m_values; + Evaluation * privateEvaluate(Expression::SinglePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Evaluation * privateEvaluate(Expression::DoublePrecision p, Context& context, Expression::AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Evaluation * templatedEvaluate(Context& context, Expression::AngleUnit angleUnit) const; + Complex * m_values; int m_numberOfRows; int m_numberOfColumns; }; diff --git a/poincare/include/poincare/confidence_interval.h b/poincare/include/poincare/confidence_interval.h index 704f3817b..40ad792c3 100644 --- a/poincare/include/poincare/confidence_interval.h +++ b/poincare/include/poincare/confidence_interval.h @@ -12,7 +12,9 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Evaluation * privateEvaluate(Context& context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/conjugate.h b/poincare/include/poincare/conjugate.h index ed3980f7d..3e97c3eda 100644 --- a/poincare/include/poincare/conjugate.h +++ b/poincare/include/poincare/conjugate.h @@ -12,7 +12,13 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c); + } + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c); + } + template Complex templatedComputeComplex(const Complex c) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; }; diff --git a/poincare/include/poincare/context.h b/poincare/include/poincare/context.h index 8aa100043..c098d64a6 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 Evaluation * expressionForSymbol(const Symbol * symbol) = 0; - virtual void setExpressionForSymbolName(Evaluation * expression, const Symbol * symbol) = 0; + virtual const Expression * expressionForSymbol(const Symbol * symbol) = 0; + virtual void setExpressionForSymbolName(Expression * expression, const Symbol * symbol) = 0; }; } diff --git a/poincare/include/poincare/cosine.h b/poincare/include/poincare/cosine.h index 0a1c9b45c..53f1b1212 100644 --- a/poincare/include/poincare/cosine.h +++ b/poincare/include/poincare/cosine.h @@ -1,22 +1,24 @@ #ifndef POINCARE_COSINE_H #define POINCARE_COSINE_H -#include +#include namespace Poincare { -class Cosine : public TrigonometricFunction { +class Cosine : public Function { public: Cosine(); Type type() const override; Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; - static Complex compute(const Complex c); + template static Complex compute(const Complex c, AngleUnit angleUnit = AngleUnit::Radian); private: - Complex privateCompute(const Complex c, AngleUnit angleUnit) const override { - return compute(c); + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return compute(c, angleUnit); + } + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return compute(c, angleUnit); } - float computeForRadianReal(float x) const override; }; } diff --git a/poincare/include/poincare/derivative.h b/poincare/include/poincare/derivative.h index 62f03f060..95263859a 100644 --- a/poincare/include/poincare/derivative.h +++ b/poincare/include/poincare/derivative.h @@ -13,12 +13,15 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - 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; - constexpr static float k_minInitialRate = 0.01f; - constexpr static float k_rateStepSize = 1.4f; + Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; + template T growthRateAroundAbscissa(T x, T h, VariableContext variableContext, AngleUnit angleUnit) const; + template T approximateDerivate2(T x, T h, VariableContext xContext, AngleUnit angleUnit) const; + // TODO: Change coefficients? + constexpr static double k_maxErrorRateOnApproximation = 0.001; + constexpr static double k_minInitialRate = 0.01; + constexpr static double k_rateStepSize = 1.4; }; } diff --git a/poincare/include/poincare/determinant.h b/poincare/include/poincare/determinant.h index 87f35ea74..0a5a52311 100644 --- a/poincare/include/poincare/determinant.h +++ b/poincare/include/poincare/determinant.h @@ -12,7 +12,9 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/division_quotient.h b/poincare/include/poincare/division_quotient.h index d089fa2b3..0e0a779aa 100644 --- a/poincare/include/poincare/division_quotient.h +++ b/poincare/include/poincare/division_quotient.h @@ -12,7 +12,9 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/division_remainder.h b/poincare/include/poincare/division_remainder.h index dde2f675f..cee47de98 100644 --- a/poincare/include/poincare/division_remainder.h +++ b/poincare/include/poincare/division_remainder.h @@ -12,7 +12,9 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/evaluation.h b/poincare/include/poincare/evaluation.h index 9096fc8e8..eff614094 100644 --- a/poincare/include/poincare/evaluation.h +++ b/poincare/include/poincare/evaluation.h @@ -5,22 +5,22 @@ namespace Poincare { +template class Complex; +template class Evaluation : public Matrix { public: - virtual float toFloat() const = 0; + virtual T toScalar() 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; + 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; }; } diff --git a/poincare/include/poincare/expression.h b/poincare/include/poincare/expression.h index 5bf6c9a59..15abf5bc1 100644 --- a/poincare/include/poincare/expression.h +++ b/poincare/include/poincare/expression.h @@ -7,6 +7,7 @@ namespace Poincare { class Context; +template class Evaluation; class Expression { @@ -133,17 +134,21 @@ public: /* The function evaluate creates a new expression and thus mallocs memory. * Do not forget to delete the new expression to avoid leaking. */ - 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); + template Evaluation * evaluate(Context& context, AngleUnit angleUnit = AngleUnit::Default) const; + template T approximate(Context& context, AngleUnit angleUnit = AngleUnit::Default) const; + template static T approximate(const char * text, Context& context, AngleUnit angleUnit = AngleUnit::Default); virtual int writeTextInBuffer(char * buffer, int bufferSize) const; +protected: + typedef float SinglePrecision; + typedef double DoublePrecision; private: virtual ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const = 0; - virtual Evaluation * privateEvaluate(Context& context, AngleUnit angleUnit) const = 0; + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const = 0; + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const = 0; bool sequentialOperandsIdentity(const Expression * e) const; bool commutativeOperandsIdentity(const Expression * e) const; bool combinatoryCommutativeOperandsIdentity(const Expression * e, - bool * operandMatched, int leftToMatch) const; + bool * operandMatched, int leftToMatch) const; }; } diff --git a/poincare/include/poincare/expression_matrix.h b/poincare/include/poincare/expression_matrix.h index 9fded1261..0cd1ca73c 100644 --- a/poincare/include/poincare/expression_matrix.h +++ b/poincare/include/poincare/expression_matrix.h @@ -23,8 +23,9 @@ public: Expression * cloneWithDifferentOperands(Expression** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Evaluation * privateEvaluate(Context& context, AngleUnit angleUnit) const override; - static Complex * defaultExpression(); + Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; MatrixData * m_matrixData; }; diff --git a/poincare/include/poincare/factorial.h b/poincare/include/poincare/factorial.h index e5c1874ea..6cda8fc2d 100644 --- a/poincare/include/poincare/factorial.h +++ b/poincare/include/poincare/factorial.h @@ -12,7 +12,13 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c); + } + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c); + } + template Complex templatedComputeComplex(const Complex c) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; }; diff --git a/poincare/include/poincare/floor.h b/poincare/include/poincare/floor.h index 01c215ae7..dda7ebeac 100644 --- a/poincare/include/poincare/floor.h +++ b/poincare/include/poincare/floor.h @@ -12,7 +12,13 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c); + } + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c); + } + template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/frac_part.h b/poincare/include/poincare/frac_part.h index 88728da9e..d948bf88d 100644 --- a/poincare/include/poincare/frac_part.h +++ b/poincare/include/poincare/frac_part.h @@ -12,7 +12,13 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c); + } + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c); + } + template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/fraction.h b/poincare/include/poincare/fraction.h index 749b53fd6..ac5dd7018 100644 --- a/poincare/include/poincare/fraction.h +++ b/poincare/include/poincare/fraction.h @@ -11,12 +11,30 @@ 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); + template static Complex compute(const Complex c, const Complex d); private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) 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 { + + Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const override { + return templatedComputeOnComplexAndComplexMatrix(c, n); + } + Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const override { + return templatedComputeOnComplexAndComplexMatrix(c, n); + } + template Evaluation * templatedComputeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const; + + Evaluation * computeOnComplexMatrices(Evaluation * m, Evaluation * n) const override { + return templatedComputeOnComplexMatrices(m, n); + } + Evaluation * computeOnComplexMatrices(Evaluation * m, Evaluation * n) const override { + return templatedComputeOnComplexMatrices(m, n); + } + template Evaluation * templatedComputeOnComplexMatrices(Evaluation * m, Evaluation * n) const; + + Complex privateCompute(const Complex c, const Complex d) const override { + return compute(c, d); + } + 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 215927853..97d65367b 100644 --- a/poincare/include/poincare/function.h +++ b/poincare/include/poincare/function.h @@ -5,6 +5,7 @@ #include #include #include +#include namespace Poincare { @@ -26,8 +27,15 @@ 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; + virtual Complex computeComplex(const Complex c, AngleUnit angleUnit) const { + return Complex::Float(NAN); + } + virtual Complex computeComplex(const Complex c, AngleUnit angleUnit) const { + return Complex::Float(NAN); + } + virtual Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + virtual Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; void build(Expression ** args, int numberOfArguments, bool clone); void clean(); diff --git a/poincare/include/poincare/global_context.h b/poincare/include/poincare/global_context.h index b318976a1..3d8108e3f 100644 --- a/poincare/include/poincare/global_context.h +++ b/poincare/include/poincare/global_context.h @@ -19,20 +19,23 @@ public: GlobalContext(GlobalContext&& other) = delete; GlobalContext& operator=(const GlobalContext& other) = delete; GlobalContext& operator=(GlobalContext&& other) = delete; - /* The expression recorded in global context is already a final expression. + /* The expression recorded in global context is already a expression. * Otherwise, we would need the context and the angle unit to evaluate it */ - const Evaluation * expressionForSymbol(const Symbol * symbol) override; - void setExpressionForSymbolName(Evaluation * expression, const Symbol * symbol) override; + const Expression * expressionForSymbol(const Symbol * symbol) override { + return evaluationForSymbol(symbol); + } + const Evaluation * evaluationForSymbol(const Symbol * symbol); + void setExpressionForSymbolName(Expression * 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 Evaluation * defaultExpression(); + static Complex * defaultExpression(); private: int symbolIndex(const Symbol * symbol) const; - Evaluation * m_expressions[k_maxNumberOfScalarExpressions]; - Evaluation * m_matrixExpressions[k_maxNumberOfMatrixExpressions]; - Complex m_pi; - Complex m_e; + Complex * m_expressions[k_maxNumberOfScalarExpressions]; + ComplexMatrix * 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 282295c7d..959d114fc 100644 --- a/poincare/include/poincare/great_common_divisor.h +++ b/poincare/include/poincare/great_common_divisor.h @@ -12,7 +12,9 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/hyperbolic_arc_cosine.h b/poincare/include/poincare/hyperbolic_arc_cosine.h index dbbad5524..3829bfe98 100644 --- a/poincare/include/poincare/hyperbolic_arc_cosine.h +++ b/poincare/include/poincare/hyperbolic_arc_cosine.h @@ -12,8 +12,13 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; - + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c); + } + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c); + } + template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/hyperbolic_arc_sine.h b/poincare/include/poincare/hyperbolic_arc_sine.h index 8dff58ee8..2ea12039a 100644 --- a/poincare/include/poincare/hyperbolic_arc_sine.h +++ b/poincare/include/poincare/hyperbolic_arc_sine.h @@ -12,7 +12,13 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c); + } + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c); + } + template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/hyperbolic_arc_tangent.h b/poincare/include/poincare/hyperbolic_arc_tangent.h index 5358edc69..1f7e6d1cc 100644 --- a/poincare/include/poincare/hyperbolic_arc_tangent.h +++ b/poincare/include/poincare/hyperbolic_arc_tangent.h @@ -12,7 +12,13 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c); + } + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c); + } + template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/hyperbolic_cosine.h b/poincare/include/poincare/hyperbolic_cosine.h index c78d97647..ef50567af 100644 --- a/poincare/include/poincare/hyperbolic_cosine.h +++ b/poincare/include/poincare/hyperbolic_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); + template static Complex compute(const Complex c); private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return compute(c); + } + 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 e43e3ac02..873f0afd7 100644 --- a/poincare/include/poincare/hyperbolic_sine.h +++ b/poincare/include/poincare/hyperbolic_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); + template static Complex compute(const Complex c); private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return compute(c); + } + 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 c82c460be..b354d818c 100644 --- a/poincare/include/poincare/hyperbolic_tangent.h +++ b/poincare/include/poincare/hyperbolic_tangent.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); + template static Complex compute(const Complex c); private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return compute(c); + } + 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 8e8996e22..77bc3698d 100644 --- a/poincare/include/poincare/imaginary_part.h +++ b/poincare/include/poincare/imaginary_part.h @@ -12,7 +12,13 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c); + } + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c); + } + template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/integer.h b/poincare/include/poincare/integer.h index 882836550..a02423e0c 100644 --- a/poincare/include/poincare/integer.h +++ b/poincare/include/poincare/integer.h @@ -36,7 +36,8 @@ public: Expression * clone() const override; private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - Evaluation * privateEvaluate(Context& context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(DoublePrecision p, 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 80c369705..267ca0d07 100644 --- a/poincare/include/poincare/integral.h +++ b/poincare/include/poincare/integral.h @@ -13,21 +13,24 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; + template struct DetailedResult { - float integral; - float absoluteError; + T integral; + T absoluteError; }; constexpr static int k_maxNumberOfIterations = 100; #ifdef LAGRANGE_METHOD - float lagrangeGaussQuadrature(float a, float b, VariableContext xContext, AngleUnit angleUnit) const; + template T lagrangeGaussQuadrature(T a, T b, VariableContext xContext, AngleUnit angleUnit) const; #else - DetailedResult kronrodGaussQuadrature(float a, float b, VariableContext xContext, AngleUnit angleUnit) const; - float adaptiveQuadrature(float a, float b, float eps, int numberOfIterations, VariableContext xContext, AngleUnit angleUnit) const; + template DetailedResult kronrodGaussQuadrature(T a, T b, VariableContext xContext, AngleUnit angleUnit) const; + template T adaptiveQuadrature(T a, T b, T eps, int numberOfIterations, VariableContext xContext, AngleUnit angleUnit) const; #endif - float functionValueAtAbscissa(float x, VariableContext xcontext, AngleUnit angleUnit) const; + template T functionValueAtAbscissa(T x, VariableContext xcontext, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/least_common_multiple.h b/poincare/include/poincare/least_common_multiple.h index 6c30a4131..6700d5143 100644 --- a/poincare/include/poincare/least_common_multiple.h +++ b/poincare/include/poincare/least_common_multiple.h @@ -12,7 +12,9 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/logarithm.h b/poincare/include/poincare/logarithm.h index d776980c3..439bb1975 100644 --- a/poincare/include/poincare/logarithm.h +++ b/poincare/include/poincare/logarithm.h @@ -13,9 +13,17 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c); + } + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c); + } + template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/matrix_data.h b/poincare/include/poincare/matrix_data.h index 527295762..79b1344c4 100644 --- a/poincare/include/poincare/matrix_data.h +++ b/poincare/include/poincare/matrix_data.h @@ -6,6 +6,7 @@ namespace Poincare { +template class Complex; class MatrixData { @@ -25,7 +26,7 @@ private: int m_numberOfRows; int m_numberOfColumns; Expression ** m_operands; - static Complex * defaultExpression(); + static Complex * defaultExpression(); }; } diff --git a/poincare/include/poincare/matrix_dimension.h b/poincare/include/poincare/matrix_dimension.h index e399aece6..209378e43 100644 --- a/poincare/include/poincare/matrix_dimension.h +++ b/poincare/include/poincare/matrix_dimension.h @@ -12,7 +12,9 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Evaluation * privateEvaluate(Context& context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/matrix_inverse.h b/poincare/include/poincare/matrix_inverse.h index 28b2ff0db..4cd1d2510 100644 --- a/poincare/include/poincare/matrix_inverse.h +++ b/poincare/include/poincare/matrix_inverse.h @@ -12,7 +12,9 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Evaluation * privateEvaluate(Context& context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/matrix_trace.h b/poincare/include/poincare/matrix_trace.h index 799e45ec0..487690133 100644 --- a/poincare/include/poincare/matrix_trace.h +++ b/poincare/include/poincare/matrix_trace.h @@ -12,7 +12,9 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Evaluation * privateEvaluate(Context& context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/matrix_transpose.h b/poincare/include/poincare/matrix_transpose.h index 53bdec606..d1842657c 100644 --- a/poincare/include/poincare/matrix_transpose.h +++ b/poincare/include/poincare/matrix_transpose.h @@ -12,7 +12,9 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Evaluation * privateEvaluate(Context& context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/multiplication.h b/poincare/include/poincare/multiplication.h index fbbce4fe3..221e6b510 100644 --- a/poincare/include/poincare/multiplication.h +++ b/poincare/include/poincare/multiplication.h @@ -11,15 +11,23 @@ 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); + template static Evaluation * computeOnMatrices(Evaluation * m, Evaluation * n); + template static Evaluation * computeOnComplexAndMatrix(const Complex * c, Evaluation * m); + template static Complex compute(const Complex c, const Complex d); private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - Evaluation * computeOnNumericalMatrices(Evaluation * m, Evaluation * n) const override { + + Evaluation * computeOnComplexMatrices(Evaluation * m, Evaluation * n) const override { return computeOnMatrices(m, n); } - Complex privateCompute(const Complex c, const Complex d) const override { + Evaluation * computeOnComplexMatrices(Evaluation * m, Evaluation * n) const override { + return computeOnMatrices(m, n); + } + + Complex privateCompute(const Complex c, const Complex d) const override { + return compute(c, d); + } + 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 c2459e5ae..e89680345 100644 --- a/poincare/include/poincare/naperian_logarithm.h +++ b/poincare/include/poincare/naperian_logarithm.h @@ -12,7 +12,13 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c); + } + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c); + } + template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/nth_root.h b/poincare/include/poincare/nth_root.h index dc14ddb88..f494fe33f 100644 --- a/poincare/include/poincare/nth_root.h +++ b/poincare/include/poincare/nth_root.h @@ -12,9 +12,11 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - Complex compute(const Complex c, const Complex d) const; + template Complex compute(const Complex c, const Complex d) const; }; } diff --git a/poincare/include/poincare/opposite.h b/poincare/include/poincare/opposite.h index 747f89b02..e54093ad6 100644 --- a/poincare/include/poincare/opposite.h +++ b/poincare/include/poincare/opposite.h @@ -21,10 +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); + template static Complex compute(const Complex c); + template static Evaluation * computeOnMatrix(Evaluation * m); private: - Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; Expression * m_operand; }; diff --git a/poincare/include/poincare/parenthesis.h b/poincare/include/poincare/parenthesis.h index c317181c9..5b9b8178d 100644 --- a/poincare/include/poincare/parenthesis.h +++ b/poincare/include/poincare/parenthesis.h @@ -22,7 +22,9 @@ public: int numnerOfOperands, bool cloneOperands = true) const override; private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; Expression * m_operand; }; diff --git a/poincare/include/poincare/permute_coefficient.h b/poincare/include/poincare/permute_coefficient.h index 578ca4203..82e2f1140 100644 --- a/poincare/include/poincare/permute_coefficient.h +++ b/poincare/include/poincare/permute_coefficient.h @@ -12,7 +12,9 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/power.h b/poincare/include/poincare/power.h index d709c5e60..b86b7d997 100644 --- a/poincare/include/poincare/power.h +++ b/poincare/include/poincare/power.h @@ -11,16 +11,39 @@ 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); + template 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; - Complex privateCompute(const Complex c, const Complex d) 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; + Complex privateCompute(const Complex c, const Complex d) const override { + return compute(c, d); + } + Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const override { + return templatedComputeOnComplexAndComplexMatrix(c, n); + } + Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const override { + return templatedComputeOnComplexAndComplexMatrix(c, n); + } + template Evaluation * templatedComputeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const; + + Evaluation * computeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const override { + return templatedComputeOnComplexMatrixAndComplex(m, d); + } + Evaluation * computeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const override { + return templatedComputeOnComplexMatrixAndComplex(m, d); + } + template Evaluation * templatedComputeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const; + + Evaluation * computeOnComplexMatrices(Evaluation * m, Evaluation * n) const override { + return templatedComputeOnComplexMatrices(m, n); + } + Evaluation * computeOnComplexMatrices(Evaluation * m, Evaluation * n) const override { + return templatedComputeOnComplexMatrices(m, n); + } + template Evaluation * templatedComputeOnComplexMatrices(Evaluation * m, Evaluation * n) const; }; } diff --git a/poincare/include/poincare/prediction_interval.h b/poincare/include/poincare/prediction_interval.h index 476269891..9d3b4c2d7 100644 --- a/poincare/include/poincare/prediction_interval.h +++ b/poincare/include/poincare/prediction_interval.h @@ -12,7 +12,9 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/product.h b/poincare/include/poincare/product.h index 596c44a18..9940d1e3c 100644 --- a/poincare/include/poincare/product.h +++ b/poincare/include/poincare/product.h @@ -12,9 +12,15 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float emptySequenceValue() const override; + int emptySequenceValue() const override; ExpressionLayout * createSequenceLayoutWithArgumentLayouts(ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout, ExpressionLayout * argumentLayout) const override; - Evaluation * evaluateWithNextTerm(Evaluation * a, Evaluation * b) const override; + Evaluation * evaluateWithNextTerm(Evaluation * a, Evaluation * b) const override { + return templatedEvaluateWithNextTerm(a, b); + } + Evaluation * evaluateWithNextTerm(Evaluation * a, Evaluation * b) const override { + return templatedEvaluateWithNextTerm(a, b); + } + template Evaluation * templatedEvaluateWithNextTerm(Evaluation * a, Evaluation * b) const; }; } diff --git a/poincare/include/poincare/reel_part.h b/poincare/include/poincare/reel_part.h index 88164c8b4..299a1d413 100644 --- a/poincare/include/poincare/reel_part.h +++ b/poincare/include/poincare/reel_part.h @@ -12,7 +12,13 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c); + } + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c); + } + template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/round.h b/poincare/include/poincare/round.h index 6cfb83229..cddf9d34f 100644 --- a/poincare/include/poincare/round.h +++ b/poincare/include/poincare/round.h @@ -12,7 +12,9 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/sequence.h b/poincare/include/poincare/sequence.h index f0cbc01b8..2ab73080f 100644 --- a/poincare/include/poincare/sequence.h +++ b/poincare/include/poincare/sequence.h @@ -11,10 +11,13 @@ public: private: constexpr static float k_maxNumberOfSteps = 10000.0f; ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - Evaluation * privateEvaluate(Context& context, AngleUnit angleUnit) const override; - virtual float emptySequenceValue() const = 0; + Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; virtual ExpressionLayout * createSequenceLayoutWithArgumentLayouts(ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout, ExpressionLayout * argumentLayout) const = 0; - virtual Evaluation * evaluateWithNextTerm(Evaluation * a, Evaluation * b) const = 0; + virtual int emptySequenceValue() const = 0; + virtual Evaluation * evaluateWithNextTerm(Evaluation * a, Evaluation * b) 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 6e81ed30e..be5c5bde0 100644 --- a/poincare/include/poincare/sine.h +++ b/poincare/include/poincare/sine.h @@ -1,22 +1,24 @@ #ifndef POINCARE_SINE_H #define POINCARE_SINE_H -#include +#include namespace Poincare { -class Sine : public TrigonometricFunction { +class Sine : public Function { public: Sine(); Type type() const override; Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; - static Complex compute(const Complex c); + template static Complex compute(const Complex c, AngleUnit angleUnit = AngleUnit::Radian); private: - Complex privateCompute(const Complex c, AngleUnit angleUnit) const override { - return compute(c); + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return compute(c, angleUnit); + } + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return compute(c, angleUnit); } - float computeForRadianReal(float x) const override; }; } diff --git a/poincare/include/poincare/square_root.h b/poincare/include/poincare/square_root.h index b33f796b9..798507c80 100644 --- a/poincare/include/poincare/square_root.h +++ b/poincare/include/poincare/square_root.h @@ -13,7 +13,13 @@ public: int numberOfOperands, bool cloneOperands = true) const override; private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - Complex computeComplex(const Complex c, AngleUnit angleUnit) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c); + } + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c); + } + template Complex templatedComputeComplex(const Complex c) const; }; } diff --git a/poincare/include/poincare/store.h b/poincare/include/poincare/store.h index 957daa044..60d5456fe 100644 --- a/poincare/include/poincare/store.h +++ b/poincare/include/poincare/store.h @@ -23,7 +23,9 @@ public: int numberOfOperands, bool cloneOperands = true) const override; private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - Evaluation * privateEvaluate(Context & context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; Symbol * m_symbol; Expression * m_value; }; diff --git a/poincare/include/poincare/subtraction.h b/poincare/include/poincare/subtraction.h index e63c6166a..15be7a073 100644 --- a/poincare/include/poincare/subtraction.h +++ b/poincare/include/poincare/subtraction.h @@ -11,11 +11,22 @@ 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); + template static Complex compute(const Complex c, const Complex d); private: ExpressionLayout * privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const override; - Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * m) const override; - Complex privateCompute(const Complex c, const Complex d) const override { + + Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const override { + return templatedComputeOnComplexAndComplexMatrix(c, n); + } + Evaluation * computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const override { + return templatedComputeOnComplexAndComplexMatrix(c, n); + } + template Evaluation * templatedComputeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const; + + Complex privateCompute(const Complex c, const Complex d) const override { + return compute(c, d); + } + 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 9723dd7c9..94bf71c6b 100644 --- a/poincare/include/poincare/sum.h +++ b/poincare/include/poincare/sum.h @@ -12,9 +12,15 @@ public: Expression * cloneWithDifferentOperands(Expression ** newOperands, int numberOfOperands, bool cloneOperands = true) const override; private: - float emptySequenceValue() const override; + int emptySequenceValue() const override; ExpressionLayout * createSequenceLayoutWithArgumentLayouts(ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout, ExpressionLayout * argumentLayout) const override; - Evaluation * evaluateWithNextTerm(Evaluation * a, Evaluation * b) const override; + Evaluation * evaluateWithNextTerm(Evaluation * a, Evaluation * b) const override { + return templatedEvaluateWithNextTerm(a, b); + } + Evaluation * evaluateWithNextTerm(Evaluation * a, Evaluation * b) const override { + return templatedEvaluateWithNextTerm(a, b); + } + template Evaluation * templatedEvaluateWithNextTerm(Evaluation * a, Evaluation * b) const; }; } diff --git a/poincare/include/poincare/symbol.h b/poincare/include/poincare/symbol.h index 66ea3f55b..cbdddf953 100644 --- a/poincare/include/poincare/symbol.h +++ b/poincare/include/poincare/symbol.h @@ -36,7 +36,9 @@ public: bool valueEquals(const Expression * e) const override; bool isMatrixSymbol() const; private: - Evaluation * privateEvaluate(Context& context, AngleUnit angleUnit) const override; + Evaluation * privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + Evaluation * privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const override { return templatedEvaluate(context, angleUnit); } + template Evaluation * templatedEvaluate(Context& context, AngleUnit angleUnit) const; 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 d4ae7ace0..8bc5bd777 100644 --- a/poincare/include/poincare/tangent.h +++ b/poincare/include/poincare/tangent.h @@ -1,19 +1,24 @@ #ifndef POINCARE_TANGENT_H #define POINCARE_TANGENT_H -#include +#include namespace Poincare { -class Tangent : public TrigonometricFunction { +class Tangent : public Function { public: Tangent(); Type type() const override; Expression * cloneWithDifferentOperands(Expression ** newOperands, int numnerOfOperands, bool cloneOperands = true) const override; private: - Complex privateCompute(const Complex c, AngleUnit angleUnit) const override; - float computeForRadianReal(float x) const override; + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c, angleUnit); + } + Complex computeComplex(const Complex c, AngleUnit angleUnit) const override { + return templatedComputeComplex(c, angleUnit); + } + template Complex templatedComputeComplex(const Complex c, AngleUnit angleUnit) const; }; } diff --git a/poincare/include/poincare/trigonometric_function.h b/poincare/include/poincare/trigonometric_function.h deleted file mode 100644 index 9a454c887..000000000 --- a/poincare/include/poincare/trigonometric_function.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef POINCARE_TRIGONOMETRIC_FUNCTION_H -#define POINCARE_TRIGONOMETRIC_FUNCTION_H - -#include - -namespace Poincare { - -class TrigonometricFunction : public Function { -public: - TrigonometricFunction(const char * name); -private: - 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; -}; - -} - -#endif diff --git a/poincare/include/poincare/variable_context.h b/poincare/include/poincare/variable_context.h index 7dd0d9eea..8dfbfeeb9 100644 --- a/poincare/include/poincare/variable_context.h +++ b/poincare/include/poincare/variable_context.h @@ -6,14 +6,15 @@ namespace Poincare { +template class VariableContext : public Context { public: VariableContext(char name, Context * parentContext = nullptr); - void setExpressionForSymbolName(Evaluation * expression, const Symbol * symbol) override; - const Evaluation * expressionForSymbol(const Symbol * symbol) override; + void setExpressionForSymbolName(Expression * expression, const Symbol * symbol) override; + const Expression * expressionForSymbol(const Symbol * symbol) override; private: char m_name; - Complex m_value; + Complex m_value; Context * m_parentContext; }; diff --git a/poincare/src/absolute_value.cpp b/poincare/src/absolute_value.cpp index 66673600e..20fb6ac3f 100644 --- a/poincare/src/absolute_value.cpp +++ b/poincare/src/absolute_value.cpp @@ -26,8 +26,9 @@ Expression * AbsoluteValue::cloneWithDifferentOperands(Expression** newOperands, return a; } -Complex AbsoluteValue::computeComplex(const Complex c, AngleUnit angleUnit) const { - return Complex::Float(c.r()); +template +Complex AbsoluteValue::templatedComputeComplex(const Complex c) 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 a561ad3f0..8bfac4c7d 100644 --- a/poincare/src/addition.cpp +++ b/poincare/src/addition.cpp @@ -26,16 +26,19 @@ ExpressionLayout * Addition::privateCreateLayout(FloatDisplayMode floatDisplayMo return layout; } -Complex Addition::compute(const Complex c, const Complex d) { - return Complex::Cartesian(c.a()+d.a(), c.b()+d.b()); +template +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) { +template +Evaluation * Addition::computeOnMatrices(Evaluation * m, Evaluation * n) { Addition a; - return a.computeOnNumericalMatrices(m,n); + return a.computeOnComplexMatrices(m,n); } -Evaluation * Addition::computeOnComplexAndMatrix(const Complex * c, Evaluation * m) { +template +Evaluation * Addition::computeOnComplexAndMatrix(const Complex * c, Evaluation * m) { Addition a; return a.computeOnComplexAndComplexMatrix(c,m); } @@ -49,4 +52,13 @@ bool Addition::isCommutative() const { return true; } +template Poincare::Complex Poincare::Addition::compute(Poincare::Complex, Poincare::Complex); +template Poincare::Complex Poincare::Addition::compute(Poincare::Complex, Poincare::Complex); + +template Poincare::Evaluation* Poincare::Addition::computeOnMatrices(Poincare::Evaluation*, Poincare::Evaluation*); +template Poincare::Evaluation* Poincare::Addition::computeOnMatrices(Poincare::Evaluation*, Poincare::Evaluation*); + +template Poincare::Evaluation* Poincare::Addition::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); +template Poincare::Evaluation* Poincare::Addition::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); + } diff --git a/poincare/src/arc_cosine.cpp b/poincare/src/arc_cosine.cpp index b47525e43..ec22a2505 100644 --- a/poincare/src/arc_cosine.cpp +++ b/poincare/src/arc_cosine.cpp @@ -23,16 +23,17 @@ Expression * ArcCosine::cloneWithDifferentOperands(Expression** newOperands, return c; } -Complex ArcCosine::computeComplex(const Complex c, AngleUnit angleUnit) const { +template +Complex ArcCosine::templatedComputeComplex(const Complex c, AngleUnit angleUnit) const { assert(angleUnit != AngleUnit::Default); - if (c.b() != 0.0f) { - return Complex::Float(NAN); + if (c.b() != 0) { + return Complex::Float(NAN); } - float result = std::acos(c.a()); + T result = std::acos(c.a()); if (angleUnit == AngleUnit::Degree) { - return Complex::Float(result*180.0f/M_PI); + return Complex::Float(result*180/M_PI); } - return Complex::Float(result); + return Complex::Float(result); } } diff --git a/poincare/src/arc_sine.cpp b/poincare/src/arc_sine.cpp index e940bc03c..61c774ad7 100644 --- a/poincare/src/arc_sine.cpp +++ b/poincare/src/arc_sine.cpp @@ -23,16 +23,17 @@ Expression * ArcSine::cloneWithDifferentOperands(Expression** newOperands, return s; } -Complex ArcSine::computeComplex(const Complex c, AngleUnit angleUnit) const { +template +Complex ArcSine::templatedComputeComplex(const Complex c, AngleUnit angleUnit) const { assert(angleUnit != AngleUnit::Default); - if (c.b() != 0.0f) { - return Complex::Float(NAN); + if (c.b() != 0) { + return Complex::Float(NAN); } - float result = std::asin(c.a()); + T result = std::asin(c.a()); if (angleUnit == AngleUnit::Degree) { - return Complex::Float(result*180.0f/M_PI); + return Complex::Float(result*180/M_PI); } - return Complex::Float(result); + return Complex::Float(result); } } diff --git a/poincare/src/arc_tangent.cpp b/poincare/src/arc_tangent.cpp index 7ef3db844..24b90e046 100644 --- a/poincare/src/arc_tangent.cpp +++ b/poincare/src/arc_tangent.cpp @@ -23,16 +23,17 @@ Expression * ArcTangent::cloneWithDifferentOperands(Expression** newOperands, return t; } -Complex ArcTangent::computeComplex(const Complex c, AngleUnit angleUnit) const { +template +Complex ArcTangent::templatedComputeComplex(const Complex c, AngleUnit angleUnit) const { assert(angleUnit != AngleUnit::Default); - if (c.b() != 0.0f) { - return Complex::Float(NAN); + if (c.b() != 0) { + return Complex::Float(NAN); } - float result = std::atan(c.a()); + T result = std::atan(c.a()); if (angleUnit == AngleUnit::Degree) { - return Complex::Float(result*180.0f/M_PI); + return Complex::Float(result*180/M_PI); } - return Complex::Float(result); + return Complex::Float(result); } } diff --git a/poincare/src/binary_operation.cpp b/poincare/src/binary_operation.cpp index 94b39db55..4505c0635 100644 --- a/poincare/src/binary_operation.cpp +++ b/poincare/src/binary_operation.cpp @@ -54,53 +54,55 @@ Expression * BinaryOperation::clone() const { return this->cloneWithDifferentOperands((Expression**) m_operands, 2, true); } -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; +template Evaluation * BinaryOperation::templatedEvaluate(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)); + result = new Complex(privateCompute(*(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); + result = computeOnComplexMatrices(leftOperandEvalutation, rightOperandEvalutation); } delete leftOperandEvalutation; delete rightOperandEvalutation; if (result == nullptr) { - result = new Complex(Complex::Float(NAN)); + result = new Complex(Complex::Float(NAN)); } return result; } -Evaluation * BinaryOperation::computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const { +template Evaluation * BinaryOperation::templatedComputeOnComplexAndComplexMatrix(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()]; +template Evaluation * BinaryOperation::templatedComputeOnComplexMatrixAndComplex(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); } - Evaluation * result = new ComplexMatrix(operands, m->numberOfRows(), m->numberOfColumns()); + Evaluation * result = new ComplexMatrix(operands, m->numberOfRows(), m->numberOfColumns()); delete[] operands; return result; } -Evaluation * BinaryOperation::computeOnNumericalMatrices(Evaluation * m, Evaluation * n) const { +template Evaluation * BinaryOperation::templatedComputeOnComplexMatrices(Evaluation * m, Evaluation * n) const { if (m->numberOfRows() != n->numberOfRows() && m->numberOfColumns() != n->numberOfColumns()) { return nullptr; } - Complex * operands = new Complex[m->numberOfRows()*m->numberOfColumns()]; + 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))); } - Evaluation * result = new ComplexMatrix(operands, m->numberOfRows(), m->numberOfColumns()); + Evaluation * result = new ComplexMatrix(operands, m->numberOfRows(), m->numberOfColumns()); delete[] operands; return result; } } +template Poincare::Evaluation* Poincare::BinaryOperation::templatedComputeOnComplexAndComplexMatrix(Poincare::Complex const*, Poincare::Evaluation*) const; +template Poincare::Evaluation* Poincare::BinaryOperation::templatedComputeOnComplexAndComplexMatrix(Poincare::Complex const*, Poincare::Evaluation*) const; diff --git a/poincare/src/binomial_coefficient.cpp b/poincare/src/binomial_coefficient.cpp index 074d66e78..464f1fb58 100644 --- a/poincare/src/binomial_coefficient.cpp +++ b/poincare/src/binomial_coefficient.cpp @@ -29,21 +29,22 @@ Expression * BinomialCoefficient::cloneWithDifferentOperands(Expression** newOpe return bc; } -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(); +template +Evaluation * BinomialCoefficient::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Evaluation * nInput = m_args[0]->evaluate(context, angleUnit); + Evaluation * kInput = m_args[1]->evaluate(context, angleUnit); + T n = nInput->toScalar(); + T k = kInput->toScalar(); delete nInput; delete kInput; - if (isnan(n) || isnan(k) || n != (int)n || k != (int)k || k > n || k < 0.0f || n < 0.0f) { - return new Complex(Complex::Float(NAN)); + if (isnan(n) || isnan(k) || n != (int)n || k != (int)k || k > n || k < 0 || n < 0) { + return new Complex(Complex::Float(NAN)); } - float result = 1.0f; + T result = 1; for (int i = 0; i < (int)k; i++) { - result *= (n-(float)i)/(k-(float)i); + result *= (n-(T)i)/(k-(T)i); } - return new Complex(Complex::Float(std::round(result))); + return new Complex(Complex::Float(std::round(result))); } ExpressionLayout * BinomialCoefficient::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { diff --git a/poincare/src/ceiling.cpp b/poincare/src/ceiling.cpp index 31750f21d..885a61c21 100644 --- a/poincare/src/ceiling.cpp +++ b/poincare/src/ceiling.cpp @@ -24,11 +24,12 @@ Expression * Ceiling::cloneWithDifferentOperands(Expression** newOperands, return c; } -Complex Ceiling::computeComplex(const Complex c, AngleUnit angleUnit) const { - if (c.b() != 0.0f) { - return Complex::Float(NAN); +template +Complex Ceiling::templatedComputeComplex(const Complex c) const { + if (c.b() != 0) { + return Complex::Float(NAN); } - return Complex::Float(std::ceil(c.a())); + return Complex::Float(std::ceil(c.a())); } } diff --git a/poincare/src/complex.cpp b/poincare/src/complex.cpp index 47a75a9f2..6cb9dba01 100644 --- a/poincare/src/complex.cpp +++ b/poincare/src/complex.cpp @@ -13,348 +13,8 @@ extern "C" { namespace Poincare { -Complex Complex::Float(float x) { - return Complex(x,0.0f); -} -Complex Complex::Cartesian(float a, float b) { - return Complex(a,b); -} - -Complex Complex::Polar(float r, float th) { - return Complex(r*std::cos(th),r*std::sin(th)); -} - -static inline float setSign(float f, bool negative) { - if (negative) { - return -f; - } - return f; -} - -float digitsToFloat(const char * digits, int length) { - if (digits == nullptr) { - return 0.0f; - } - float result = 0.0f; - const char * digit = digits; - for (int i = 0; i < length; i++) { - result = 10.0f * result; - result += *digit-'0'; - digit++; - } - return result; -} - -Complex::Complex(const char * integralPart, int integralPartLength, bool integralNegative, - const char * fractionalPart, int fractionalPartLength, - const char * exponent, int exponentLength, bool exponentNegative) { - float i = digitsToFloat(integralPart, integralPartLength); - float j = digitsToFloat(fractionalPart, fractionalPartLength); - float l = setSign(digitsToFloat(exponent, exponentLength), exponentNegative); - - m_a = setSign((i + j*std::pow(10.0f, -std::ceil((float)fractionalPartLength)))* std::pow(10.0f, l), integralNegative); - m_b = 0.0f; -} - -float Complex::toFloat() const { - if (m_b != 0.0f) { - return NAN; - } - return m_a; -} - -int Complex::numberOfRows() const { - return 1; -} - -int Complex::numberOfColumns() const { - return 1; -} - -Expression::Type Complex::type() const { - return Type::Complex; -} - -Complex * Complex::clone() const { - return new Complex(Cartesian(m_a, m_b)); -} - -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()); -} - -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() const { - return m_b; -} - -float Complex::r() const { - if (m_b == 0) { - return std::fabs(m_a); - } - return std::sqrt(m_a*m_a + m_b*m_b); -} - -float Complex::th() const { - float result = std::atan(m_b/m_a) + M_PI; - if (m_a >= 0.0f) { - float a = m_a == 0.0f ? 0.0f : m_a; - result = std::atan(m_b/a); - } - if (result > M_PI + FLT_EPSILON) { - result = result - 2.0f*M_PI; - } - return result; -} - -Complex Complex::conjugate() const { - return Complex::Cartesian(m_a, -m_b); -} - -int Complex::convertFloatToText(float f, char * buffer, int bufferSize, - int numberOfSignificantDigits, FloatDisplayMode mode) { - assert(numberOfSignificantDigits > 0); - if (mode == FloatDisplayMode::Default) { - return convertFloatToText(f, buffer, bufferSize, numberOfSignificantDigits, Preferences::sharedPreferences()->displayMode()); - } - char tempBuffer[k_maxFloatBufferLength]; - int requiredLength = convertFloatToTextPrivate(f, tempBuffer, numberOfSignificantDigits, mode); - /* if the required buffer size overflows the buffer size, we first force the - * display mode to scientific and decrease the number of significant digits to - * fit the buffer size. If the buffer size is still to small, we only write - * the beginning of the float and truncate it (which can result in a non sense - * text) */ - if (mode == FloatDisplayMode::Decimal && requiredLength >= bufferSize) { - requiredLength = convertFloatToTextPrivate(f, tempBuffer, numberOfSignificantDigits, FloatDisplayMode::Scientific); - } - if (requiredLength >= bufferSize) { - int adjustedNumberOfSignificantDigits = numberOfSignificantDigits - requiredLength + bufferSize - 1; - adjustedNumberOfSignificantDigits = adjustedNumberOfSignificantDigits < 1 ? 1 : adjustedNumberOfSignificantDigits; - requiredLength = convertFloatToTextPrivate(f, tempBuffer, adjustedNumberOfSignificantDigits, FloatDisplayMode::Scientific); - } - requiredLength = requiredLength < bufferSize ? requiredLength : bufferSize; - strlcpy(buffer, tempBuffer, bufferSize); - return requiredLength; -} - -Complex::Complex(float a, float b) : - m_a(a), - m_b(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; - if (isnan(m_a) || isnan(m_b)) { - return convertFloatToText(NAN, buffer, bufferSize, k_numberOfSignificantDigits, displayMode); - } - if (complexFormat == ComplexFormat::Polar) { - if (r() != 1.0f || th() == 0.0f) { - numberOfChars = convertFloatToText(r(), buffer, bufferSize, k_numberOfSignificantDigits, displayMode); - if (r() != 0.0f && th() != 0.0f && bufferSize > numberOfChars+1) { - buffer[numberOfChars++] = '*'; - // Ensure that the string is null terminated even if buffer size is to small - buffer[numberOfChars] = 0; - } - } - if (r() != 0.0f && th() != 0.0f) { - if (bufferSize > numberOfChars+3) { - buffer[numberOfChars++] = Ion::Charset::Exponential; - buffer[numberOfChars++] = '^'; - buffer[numberOfChars++] = '('; - // Ensure that the string is null terminated even if buffer size is to small - buffer[numberOfChars] = 0; - } - numberOfChars += convertFloatToText(th(), buffer+numberOfChars, bufferSize-numberOfChars, k_numberOfSignificantDigits, displayMode); - if (bufferSize > numberOfChars+3) { - buffer[numberOfChars++] = '*'; - buffer[numberOfChars++] = Ion::Charset::IComplex; - buffer[numberOfChars++] = ')'; - buffer[numberOfChars] = 0; - } - } - return numberOfChars; - } - - if (m_a != 0.0f || m_b == 0.0f) { - numberOfChars = convertFloatToText(m_a, buffer, bufferSize, k_numberOfSignificantDigits, displayMode); - if (m_b > 0.0f && !isnan(m_b) && bufferSize > numberOfChars+1) { - buffer[numberOfChars++] = '+'; - // Ensure that the string is null terminated even if buffer size is to small - buffer[numberOfChars] = 0; - } - } - if (m_b != 1.0f && m_b != -1.0f && m_b != 0.0f) { - numberOfChars += convertFloatToText(m_b, buffer+numberOfChars, bufferSize-numberOfChars, k_numberOfSignificantDigits, displayMode); - buffer[numberOfChars++] = '*'; - } - if (m_b == -1.0f && bufferSize > numberOfChars+1) { - buffer[numberOfChars++] = '-'; - } - if (m_b != 0.0f && bufferSize > numberOfChars+1) { - buffer[numberOfChars++] = Ion::Charset::IComplex; - buffer[numberOfChars] = 0; - } - return numberOfChars; -} - - -int Complex::convertFloatToTextPrivate(float f, char * buffer, int numberOfSignificantDigits, FloatDisplayMode mode) { - assert(mode != FloatDisplayMode::Default); - assert(numberOfSignificantDigits > 0); - if (isinf(f)) { - int currentChar = 0; - if (f < 0) { - buffer[currentChar++] = '-'; - } - buffer[currentChar++] = 'i'; - buffer[currentChar++] = 'n'; - buffer[currentChar++] = 'f'; - buffer[currentChar] = 0; - return currentChar; - } - - if (isnan(f)) { - int currentChar = 0; - buffer[currentChar++] = 'u'; - buffer[currentChar++] = 'n'; - buffer[currentChar++] = 'd'; - buffer[currentChar++] = 'e'; - buffer[currentChar++] = 'f'; - buffer[currentChar] = 0; - return currentChar; - } - - float logBase10 = f != 0.0f ? std::log10(std::fabs(f)) : 0; - int exponentInBase10 = std::floor(logBase10); - /* Correct the exponent in base 10: sometines the exact log10 of f is 6.999999 - * but is stored as 7 in hardware. We catch these cases here. */ - if (f != 0.0f && logBase10 == (int)logBase10 && std::fabs(f) < std::pow(10.0f, logBase10)) { - exponentInBase10--; - } - - FloatDisplayMode displayMode = mode; - if ((exponentInBase10 >= numberOfSignificantDigits || exponentInBase10 <= -numberOfSignificantDigits) && mode == FloatDisplayMode::Decimal) { - displayMode = FloatDisplayMode::Scientific; - } - - // Number of char available for the mantissa - int availableCharsForMantissaWithoutSign = numberOfSignificantDigits + 1; - int availableCharsForMantissaWithSign = f >= 0 ? availableCharsForMantissaWithoutSign : availableCharsForMantissaWithoutSign + 1; - - // Compute mantissa - /* The number of digits in an integer is capped because the maximal integer is - * 2^31 - 1. As our mantissa is an integer, we assert that we stay beyond this - * threshold during computation. */ - assert(availableCharsForMantissaWithoutSign - 1 < std::log10(std::pow(2.0f, 31.0f))); - - int numberOfDigitBeforeDecimal = exponentInBase10 >= 0 || displayMode == FloatDisplayMode::Scientific ? - exponentInBase10 + 1 : 1; - float mantissa = std::round(f * std::pow(10.0f, availableCharsForMantissaWithoutSign - 1 - numberOfDigitBeforeDecimal)); - /* if availableCharsForMantissaWithoutSign - 1 - numberOfDigitBeforeDecimal - * is too big (or too small), mantissa is now inf. We handle this case by - * using logarithm function. */ - if (isnan(mantissa) || isinf(mantissa)) { - mantissa = std::round(std::pow(10.0f, std::log10(std::fabs(f))+(float)(availableCharsForMantissaWithoutSign - 1 - numberOfDigitBeforeDecimal))); - mantissa = std::copysign(mantissa, f); - } - /* We update the exponent in base 10 (if 0.99999999 was rounded to 1 for - * instance) */ - float truncatedMantissa = (int)(f * std::pow(10.0f, availableCharsForMantissaWithoutSign - 1 - numberOfDigitBeforeDecimal)); - if (isinf(truncatedMantissa) || isnan(truncatedMantissa)) { - truncatedMantissa = (int)(std::pow(10.0f, std::log10(std::fabs(f))+(float)(availableCharsForMantissaWithoutSign - 1 - numberOfDigitBeforeDecimal))); - truncatedMantissa = std::copysign(truncatedMantissa, f); - } - if (mantissa != truncatedMantissa) { - float newLogBase10 = mantissa != 0.0f ? std::log10(std::fabs(mantissa/std::pow(10.0f, availableCharsForMantissaWithoutSign - 1 - numberOfDigitBeforeDecimal))) : 0.0f; - if (isnan(newLogBase10) || isinf(newLogBase10)) { - newLogBase10 = std::log10(std::fabs(mantissa)) - (float)(availableCharsForMantissaWithoutSign - 1 - numberOfDigitBeforeDecimal); - } - exponentInBase10 = std::floor(newLogBase10); - } - int decimalMarkerPosition = exponentInBase10 < 0 || displayMode == FloatDisplayMode::Scientific ? - 1 : exponentInBase10+1; - - // Correct the number of digits in mantissa after rounding - int mantissaExponentInBase10 = exponentInBase10 > 0 || displayMode == FloatDisplayMode::Scientific ? availableCharsForMantissaWithoutSign - 1 : availableCharsForMantissaWithoutSign + exponentInBase10; - if ((int)(std::fabs(mantissa) * std::pow(10.0f, - mantissaExponentInBase10)) > 0) { - mantissa = mantissa/10; - } - - int numberOfCharExponent = exponentInBase10 != 0 ? std::log10(std::fabs((float)exponentInBase10)) + 1 : 1; - if (exponentInBase10 < 0){ - // If the exponent is < 0, we need a additional char for the sign - numberOfCharExponent++; - } - - // Supress the 0 on the right side of the mantissa - int dividend = std::fabs((float)mantissa); - int quotien = dividend/10; - int digit = dividend - quotien*10; - int minimumNumberOfCharsInMantissa = 1; - while (digit == 0 && availableCharsForMantissaWithoutSign > minimumNumberOfCharsInMantissa && - (availableCharsForMantissaWithoutSign > exponentInBase10+2 || displayMode == FloatDisplayMode::Scientific)) { - mantissa = mantissa/10; - availableCharsForMantissaWithoutSign--; - availableCharsForMantissaWithSign--; - dividend = quotien; - quotien = dividend/10; - digit = dividend - quotien*10; - } - - // Suppress the decimal marker if no fractional part - if ((displayMode == FloatDisplayMode::Decimal && availableCharsForMantissaWithoutSign == exponentInBase10+2) - || (displayMode == FloatDisplayMode::Scientific && availableCharsForMantissaWithoutSign == 2)) { - availableCharsForMantissaWithSign--; - } - - // Print mantissa - assert(availableCharsForMantissaWithSign < k_maxFloatBufferLength); - printBase10IntegerWithDecimalMarker(buffer, availableCharsForMantissaWithSign, mantissa, decimalMarkerPosition); - if (displayMode == FloatDisplayMode::Decimal || exponentInBase10 == 0.0f) { - buffer[availableCharsForMantissaWithSign] = 0; - return availableCharsForMantissaWithSign; - } - // Print exponent - assert(availableCharsForMantissaWithSign < k_maxFloatBufferLength); - buffer[availableCharsForMantissaWithSign] = Ion::Charset::Exponent; - assert(numberOfCharExponent+availableCharsForMantissaWithSign+1 < k_maxFloatBufferLength); - printBase10IntegerWithDecimalMarker(buffer+availableCharsForMantissaWithSign+1, numberOfCharExponent, exponentInBase10, -1); - buffer[availableCharsForMantissaWithSign+1+numberOfCharExponent] = 0; - return (availableCharsForMantissaWithSign+1+numberOfCharExponent); -} - -void Complex::printBase10IntegerWithDecimalMarker(char * buffer, int bufferSize, int i, int decimalMarkerPosition) { +void PrintFloat::printBase10IntegerWithDecimalMarker(char * buffer, int bufferSize, int i, int decimalMarkerPosition) { /* The decimal marker position is always preceded by a char, thus, it is never * in first position. When called by convertFloatToText, the buffer length is * always > 0 as we asserted a minimal number of available chars. */ @@ -381,24 +41,392 @@ void Complex::printBase10IntegerWithDecimalMarker(char * buffer, int bufferSize, } while (endChar >= startChar); } -ExpressionLayout * Complex::createPolarLayout(FloatDisplayMode floatDisplayMode) const { +template +Complex Complex::Float(T x) { + return Complex(x,0); +} + +template +Complex Complex::Cartesian(T a, T b) { + return Complex(a,b); +} + +template +Complex Complex::Polar(T r, T th) { + return Complex(r*std::cos(th),r*std::sin(th)); +} + +template +static inline T setSign(T f, bool negative) { + if (negative) { + return -f; + } + return f; +} + +template +T digitsToFloat(const char * digits, int length) { + if (digits == nullptr) { + return 0; + } + T result = 0; + const char * digit = digits; + for (int i = 0; i < length; i++) { + result = 10 * result; + result += *digit-'0'; + digit++; + } + return result; +} + +template +Complex::Complex(const char * integralPart, int integralPartLength, bool integralNegative, + const char * fractionalPart, int fractionalPartLength, + const char * exponent, int exponentLength, bool exponentNegative) { + T i = digitsToFloat(integralPart, integralPartLength); + T j = digitsToFloat(fractionalPart, fractionalPartLength); + T l = setSign(digitsToFloat(exponent, exponentLength), exponentNegative); + + m_a = setSign((i + j*std::pow(10, -std::ceil((T)fractionalPartLength)))* std::pow(10, l), integralNegative); + m_b = 0; +} + +template +T Complex::toScalar() const { + if (m_b != 0) { + return NAN; + } + return m_a; +} + +template +int Complex::numberOfRows() const { + return 1; +} + +template +int Complex::numberOfColumns() const { + return 1; +} + +template +Expression::Type Complex::type() const { + return Expression::Type::Complex; +} + +template +Complex * Complex::clone() const { + return new Complex(*this); +} + +template +Evaluation * Complex::cloneWithDifferentOperands(Expression** newOperands, + int numberOfOperands, bool cloneOperands) const { + return this->clone(); +} + +template +int Complex::writeTextInBuffer(char * buffer, int bufferSize) const { + return convertComplexToText(buffer, bufferSize, Preferences::sharedPreferences()->displayMode(), Preferences::sharedPreferences()->complexFormat()); +} + +template +Evaluation * Complex::createInverse() const { + return new Complex(Cartesian(1/m_a, -1/m_b)); +} + +template +T Complex::a() const { + return m_a; +} + +template +T Complex::b() const { + return m_b; +} + +template +T Complex::r() const { + if (m_b == 0) { + return std::fabs(m_a); + } + return std::sqrt(m_a*m_a + m_b*m_b); +} + +template +T Complex::th() const { + T result = std::atan(m_b/m_a) + M_PI; + if (m_a >= 0) { + T a = m_a == 0 ? 0 : m_a; + result = std::atan(m_b/a); + } + if (result > M_PI + FLT_EPSILON) { + result = result - 2*M_PI; + } + return result; +} + +template +Complex Complex::conjugate() const { + return Cartesian(m_a, -m_b); +} + +template +int Complex::convertFloatToText(T f, char * buffer, int bufferSize, + int numberOfSignificantDigits, Expression::FloatDisplayMode mode) { + assert(numberOfSignificantDigits > 0); + if (mode == Expression::FloatDisplayMode::Default) { + return convertFloatToText(f, buffer, bufferSize, numberOfSignificantDigits, Preferences::sharedPreferences()->displayMode()); + } + char tempBuffer[k_maxFloatBufferLength]; + int requiredLength = convertFloatToTextPrivate(f, tempBuffer, numberOfSignificantDigits, mode); + /* if the required buffer size overflows the buffer size, we first force the + * display mode to scientific and decrease the number of significant digits to + * fit the buffer size. If the buffer size is still to small, we only write + * the beginning of the float and truncate it (which can result in a non sense + * text) */ + if (mode == Expression::FloatDisplayMode::Decimal && requiredLength >= bufferSize) { + requiredLength = convertFloatToTextPrivate(f, tempBuffer, numberOfSignificantDigits, Expression::FloatDisplayMode::Scientific); + } + if (requiredLength >= bufferSize) { + int adjustedNumberOfSignificantDigits = numberOfSignificantDigits - requiredLength + bufferSize - 1; + adjustedNumberOfSignificantDigits = adjustedNumberOfSignificantDigits < 1 ? 1 : adjustedNumberOfSignificantDigits; + requiredLength = convertFloatToTextPrivate(f, tempBuffer, adjustedNumberOfSignificantDigits, Expression::FloatDisplayMode::Scientific); + } + requiredLength = requiredLength < bufferSize ? requiredLength : bufferSize; + strlcpy(buffer, tempBuffer, bufferSize); + return requiredLength; +} + +template +Complex::Complex(T a, T b) : + m_a(a), + m_b(b) +{ +} + +template +const Complex * Complex::complexOperand(int i) const { + return this; +} + +template +ExpressionLayout * Complex::privateCreateLayout(Expression::FloatDisplayMode floatDisplayMode, Expression::ComplexFormat complexFormat) const { + assert(floatDisplayMode != Expression::FloatDisplayMode::Default); + if (complexFormat == Expression::ComplexFormat::Polar) { + return createPolarLayout(floatDisplayMode); + } + return createCartesianLayout(floatDisplayMode); +} + +template +template +Evaluation * Complex::templatedEvaluate(Context& context, Expression::AngleUnit angleUnit) const { + return new Complex(Complex::Cartesian((U)m_a, (U)m_b)); +} + +template +int Complex::convertComplexToText(char * buffer, int bufferSize, Expression::FloatDisplayMode displayMode, Expression::ComplexFormat complexFormat) const { + assert(displayMode != Expression::FloatDisplayMode::Default); + int numberOfChars = 0; + if (isnan(m_a) || isnan(m_b)) { + return convertFloatToText(NAN, buffer, bufferSize, k_numberOfSignificantDigits, displayMode); + } + if (complexFormat == Expression::ComplexFormat::Polar) { + if (r() != 1 || th() == 0) { + numberOfChars = convertFloatToText(r(), buffer, bufferSize, k_numberOfSignificantDigits, displayMode); + if (r() != 0 && th() != 0 && bufferSize > numberOfChars+1) { + buffer[numberOfChars++] = '*'; + // Ensure that the string is null terminated even if buffer size is to small + buffer[numberOfChars] = 0; + } + } + if (r() != 0 && th() != 0) { + if (bufferSize > numberOfChars+3) { + buffer[numberOfChars++] = Ion::Charset::Exponential; + buffer[numberOfChars++] = '^'; + buffer[numberOfChars++] = '('; + // Ensure that the string is null terminated even if buffer size is to small + buffer[numberOfChars] = 0; + } + numberOfChars += convertFloatToText(th(), buffer+numberOfChars, bufferSize-numberOfChars, k_numberOfSignificantDigits, displayMode); + if (bufferSize > numberOfChars+3) { + buffer[numberOfChars++] = '*'; + buffer[numberOfChars++] = Ion::Charset::IComplex; + buffer[numberOfChars++] = ')'; + buffer[numberOfChars] = 0; + } + } + return numberOfChars; + } + + if (m_a != 0 || m_b == 0) { + numberOfChars = convertFloatToText(m_a, buffer, bufferSize, k_numberOfSignificantDigits, displayMode); + if (m_b > 0 && !isnan(m_b) && bufferSize > numberOfChars+1) { + buffer[numberOfChars++] = '+'; + // Ensure that the string is null terminated even if buffer size is to small + buffer[numberOfChars] = 0; + } + } + if (m_b != 1 && m_b != -1 && m_b != 0) { + numberOfChars += convertFloatToText(m_b, buffer+numberOfChars, bufferSize-numberOfChars, k_numberOfSignificantDigits, displayMode); + buffer[numberOfChars++] = '*'; + } + if (m_b == -1 && bufferSize > numberOfChars+1) { + buffer[numberOfChars++] = '-'; + } + if (m_b != 0 && bufferSize > numberOfChars+1) { + buffer[numberOfChars++] = Ion::Charset::IComplex; + buffer[numberOfChars] = 0; + } + return numberOfChars; +} + +template +int Complex::convertFloatToTextPrivate(T f, char * buffer, int numberOfSignificantDigits, Expression::FloatDisplayMode mode) { + assert(mode != Expression::FloatDisplayMode::Default); + assert(numberOfSignificantDigits > 0); + if (isinf(f)) { + int currentChar = 0; + if (f < 0) { + buffer[currentChar++] = '-'; + } + buffer[currentChar++] = 'i'; + buffer[currentChar++] = 'n'; + buffer[currentChar++] = 'f'; + buffer[currentChar] = 0; + return currentChar; + } + + if (isnan(f)) { + int currentChar = 0; + buffer[currentChar++] = 'u'; + buffer[currentChar++] = 'n'; + buffer[currentChar++] = 'd'; + buffer[currentChar++] = 'e'; + buffer[currentChar++] = 'f'; + buffer[currentChar] = 0; + return currentChar; + } + + T logBase10 = f != 0 ? std::log10(std::fabs(f)) : 0; + int exponentInBase10 = std::floor(logBase10); + /* Correct the exponent in base 10: sometines the exact log10 of f is 6.999999 + * but is stored as 7 in hardware. We catch these cases here. */ + if (f != 0 && logBase10 == (int)logBase10 && std::fabs(f) < std::pow(10, logBase10)) { + exponentInBase10--; + } + + Expression::FloatDisplayMode displayMode = mode; + if ((exponentInBase10 >= numberOfSignificantDigits || exponentInBase10 <= -numberOfSignificantDigits) && mode == Expression::FloatDisplayMode::Decimal) { + displayMode = Expression::FloatDisplayMode::Scientific; + } + + // Number of char available for the mantissa + int availableCharsForMantissaWithoutSign = numberOfSignificantDigits + 1; + int availableCharsForMantissaWithSign = f >= 0 ? availableCharsForMantissaWithoutSign : availableCharsForMantissaWithoutSign + 1; + + // Compute mantissa + /* The number of digits in an integer is capped because the maximal integer is + * 2^31 - 1. As our mantissa is an integer, we assert that we stay beyond this + * threshold during computation. */ + assert(availableCharsForMantissaWithoutSign - 1 < std::log10(std::pow(2.0f, 31.0f))); + + int numberOfDigitBeforeDecimal = exponentInBase10 >= 0 || displayMode == Expression::FloatDisplayMode::Scientific ? + exponentInBase10 + 1 : 1; + T mantissa = std::round(f * std::pow(10, (T)availableCharsForMantissaWithoutSign - 1 - numberOfDigitBeforeDecimal)); + /* if availableCharsForMantissaWithoutSign - 1 - numberOfDigitBeforeDecimal + * is too big (or too small), mantissa is now inf. We handle this case by + * using logarithm function. */ + if (isnan(mantissa) || isinf(mantissa)) { + mantissa = std::round(std::pow(10, std::log10(std::fabs(f))+(T)(availableCharsForMantissaWithoutSign - 1 - numberOfDigitBeforeDecimal))); + mantissa = std::copysign(mantissa, f); + } + /* We update the exponent in base 10 (if 0.99999999 was rounded to 1 for + * instance) */ + T truncatedMantissa = (int)(f * std::pow(10, (T)(availableCharsForMantissaWithoutSign - 1 - numberOfDigitBeforeDecimal))); + if (isinf(truncatedMantissa) || isnan(truncatedMantissa)) { + truncatedMantissa = (int)(std::pow(10, std::log10(std::fabs(f))+(T)(availableCharsForMantissaWithoutSign - 1 - numberOfDigitBeforeDecimal))); + truncatedMantissa = std::copysign(truncatedMantissa, f); + } + if (mantissa != truncatedMantissa) { + T newLogBase10 = mantissa != 0 ? std::log10(std::fabs(mantissa/std::pow((T)10, (T)(availableCharsForMantissaWithoutSign - 1 - numberOfDigitBeforeDecimal)))) : 0; + if (isnan(newLogBase10) || isinf(newLogBase10)) { + newLogBase10 = std::log10(std::fabs((T)mantissa)) - (T)(availableCharsForMantissaWithoutSign - 1 - numberOfDigitBeforeDecimal); + } + exponentInBase10 = std::floor(newLogBase10); + } + int decimalMarkerPosition = exponentInBase10 < 0 || displayMode == Expression::FloatDisplayMode::Scientific ? + 1 : exponentInBase10+1; + + // Correct the number of digits in mantissa after rounding + int mantissaExponentInBase10 = exponentInBase10 > 0 || displayMode == Expression::FloatDisplayMode::Scientific ? availableCharsForMantissaWithoutSign - 1 : availableCharsForMantissaWithoutSign + exponentInBase10; + if ((int)(std::fabs(mantissa) * std::pow((T)10, - mantissaExponentInBase10)) > 0) { + mantissa = mantissa/10; + } + + int numberOfCharExponent = exponentInBase10 != 0 ? std::log10(std::fabs((T)exponentInBase10)) + 1 : 1; + if (exponentInBase10 < 0){ + // If the exponent is < 0, we need a additional char for the sign + numberOfCharExponent++; + } + + // Supress the 0 on the right side of the mantissa + int dividend = std::fabs((T)mantissa); + int quotien = dividend/10; + int digit = dividend - quotien*10; + int minimumNumberOfCharsInMantissa = 1; + while (digit == 0 && availableCharsForMantissaWithoutSign > minimumNumberOfCharsInMantissa && + (availableCharsForMantissaWithoutSign > exponentInBase10+2 || displayMode == Expression::FloatDisplayMode::Scientific)) { + mantissa = mantissa/10; + availableCharsForMantissaWithoutSign--; + availableCharsForMantissaWithSign--; + dividend = quotien; + quotien = dividend/10; + digit = dividend - quotien*10; + } + + // Suppress the decimal marker if no fractional part + if ((displayMode == Expression::FloatDisplayMode::Decimal && availableCharsForMantissaWithoutSign == exponentInBase10+2) + || (displayMode == Expression::FloatDisplayMode::Scientific && availableCharsForMantissaWithoutSign == 2)) { + availableCharsForMantissaWithSign--; + } + + // Print mantissa + assert(availableCharsForMantissaWithSign < k_maxFloatBufferLength); + PrintFloat::printBase10IntegerWithDecimalMarker(buffer, availableCharsForMantissaWithSign, mantissa, decimalMarkerPosition); + if (displayMode == Expression::FloatDisplayMode::Decimal || exponentInBase10 == 0) { + buffer[availableCharsForMantissaWithSign] = 0; + return availableCharsForMantissaWithSign; + } + // Print exponent + assert(availableCharsForMantissaWithSign < k_maxFloatBufferLength); + buffer[availableCharsForMantissaWithSign] = Ion::Charset::Exponent; + assert(numberOfCharExponent+availableCharsForMantissaWithSign+1 < k_maxFloatBufferLength); + PrintFloat::printBase10IntegerWithDecimalMarker(buffer+availableCharsForMantissaWithSign+1, numberOfCharExponent, exponentInBase10, -1); + buffer[availableCharsForMantissaWithSign+1+numberOfCharExponent] = 0; + return (availableCharsForMantissaWithSign+1+numberOfCharExponent); +} + +template +ExpressionLayout * Complex::createPolarLayout(Expression::FloatDisplayMode floatDisplayMode) const { char bufferBase[k_maxFloatBufferLength+2]; int numberOfCharInBase = 0; char bufferSuperscript[k_maxFloatBufferLength+2]; int numberOfCharInSuperscript = 0; - if (r() != 1.0f || th() == 0.0f) { + if (r() != 1 || th() == 0) { numberOfCharInBase = convertFloatToText(r(), bufferBase, k_maxFloatBufferLength, k_numberOfSignificantDigits, floatDisplayMode); - if (r() != 0.0f && th() != 0.0f) { + if (r() != 0 && th() != 0) { bufferBase[numberOfCharInBase++] = '*'; } } - if (r() != 0.0f && th() != 0.0f) { + if (r() != 0 && th() != 0) { bufferBase[numberOfCharInBase++] = Ion::Charset::Exponential; bufferBase[numberOfCharInBase] = 0; } - if (r() != 0.0f && th() != 0.0f) { + if (r() != 0 && th() != 0) { numberOfCharInSuperscript = convertFloatToText(th(), bufferSuperscript, k_maxFloatBufferLength, k_numberOfSignificantDigits, floatDisplayMode); bufferSuperscript[numberOfCharInSuperscript++] = '*'; bufferSuperscript[numberOfCharInSuperscript++] = Ion::Charset::IComplex; @@ -410,11 +438,19 @@ ExpressionLayout * Complex::createPolarLayout(FloatDisplayMode floatDisplayMode) return new BaselineRelativeLayout(new StringLayout(bufferBase, numberOfCharInBase), new StringLayout(bufferSuperscript, numberOfCharInSuperscript), BaselineRelativeLayout::Type::Superscript); } -ExpressionLayout * Complex::createCartesianLayout(FloatDisplayMode floatDisplayMode) const { +template +ExpressionLayout * Complex::createCartesianLayout(Expression::FloatDisplayMode floatDisplayMode) const { char buffer[k_maxComplexBufferLength]; - int numberOfChars = convertComplexToText(buffer, k_maxComplexBufferLength, floatDisplayMode, ComplexFormat::Cartesian); + int numberOfChars = convertComplexToText(buffer, k_maxComplexBufferLength, floatDisplayMode, Expression::ComplexFormat::Cartesian); return new StringLayout(buffer, numberOfChars); } +template class Poincare::Complex; +template class Poincare::Complex; +template Poincare::Evaluation* Poincare::Complex::templatedEvaluate(Poincare::Context&, Poincare::Expression::AngleUnit) const; +template Poincare::Evaluation* Poincare::Complex::templatedEvaluate(Poincare::Context&, Poincare::Expression::AngleUnit) const; +template Poincare::Evaluation* Poincare::Complex::templatedEvaluate(Poincare::Context&, Poincare::Expression::AngleUnit) const; +template Poincare::Evaluation* Poincare::Complex::templatedEvaluate(Poincare::Context&, Poincare::Expression::AngleUnit) const; + } diff --git a/poincare/src/complex_argument.cpp b/poincare/src/complex_argument.cpp index 7ae51889c..85a4c2505 100644 --- a/poincare/src/complex_argument.cpp +++ b/poincare/src/complex_argument.cpp @@ -25,8 +25,9 @@ Expression * ComplexArgument::cloneWithDifferentOperands(Expression** newOperand return ca; } -Complex ComplexArgument::computeComplex(const Complex c, AngleUnit angleUnit) const { - return Complex::Float(c.th()); +template +Complex ComplexArgument::templatedComputeComplex(const Complex c) const { + return Complex::Float(c.th()); } } diff --git a/poincare/src/complex_matrix.cpp b/poincare/src/complex_matrix.cpp index 9590b29f5..3619a7787 100644 --- a/poincare/src/complex_matrix.cpp +++ b/poincare/src/complex_matrix.cpp @@ -12,67 +12,90 @@ extern "C" { namespace Poincare { -ComplexMatrix::ComplexMatrix(const Complex * complexes, int numberOfRows, int numberOfColumns) : +template +ComplexMatrix::ComplexMatrix(const Complex * complexes, int numberOfRows, int numberOfColumns) : m_numberOfRows(numberOfRows), m_numberOfColumns(numberOfColumns) { assert(complexes != nullptr); - m_values = new Complex[numberOfColumns*numberOfRows]; + m_values = new Complex[numberOfColumns*numberOfRows]; for (int i = 0; i < numberOfColumns*numberOfRows; i++) { m_values[i] = complexes[i]; } } -ComplexMatrix::~ComplexMatrix() { +template +ComplexMatrix::~ComplexMatrix() { delete[] m_values; } -float ComplexMatrix::toFloat() const { +template +T ComplexMatrix::toScalar() const { if (m_numberOfColumns != 1 || m_numberOfRows != 1) { return NAN; } - if (m_values[0].b() != 0.0f) { + if (m_values[0].b() != 0) { return NAN; } return m_values[0].a(); } -int ComplexMatrix::numberOfRows() const { +template +int ComplexMatrix::numberOfRows() const { return m_numberOfRows; } -int ComplexMatrix::numberOfColumns() const { +template +int ComplexMatrix::numberOfColumns() const { return m_numberOfColumns; } -const Complex * ComplexMatrix::complexOperand(int i) const { +template +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); +template +ComplexMatrix * ComplexMatrix::clone() const { + return new ComplexMatrix(m_values, m_numberOfRows, m_numberOfColumns); } -ComplexMatrix * ComplexMatrix::cloneWithDifferentOperands(Expression** newOperands, +template +ComplexMatrix * ComplexMatrix::cloneWithDifferentOperands(Expression** newOperands, int numberOfOperands, bool cloneOperands) const { assert(newOperands != nullptr); - return new ComplexMatrix((Complex *)newOperands[0], m_numberOfColumns, m_numberOfRows); + return new ComplexMatrix((Complex *)newOperands[0], m_numberOfColumns, m_numberOfRows); } -Evaluation * ComplexMatrix::createIdentity(int dim) { - Complex * operands = new Complex [dim*dim]; +template +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)); + operands[i*dim+j] = Complex::Float(1.0); } else { - operands[i*dim+j] = Complex(Complex::Float(0.0)); + operands[i*dim+j] = Complex::Float(0.0); } } } - Evaluation * matrix = new ComplexMatrix(operands, dim, dim); + Evaluation * matrix = new ComplexMatrix(operands, dim, dim); delete [] operands; return matrix; } +template +template +Evaluation * ComplexMatrix::templatedEvaluate(Context& context, Expression::AngleUnit angleUnit) const { + Complex * values = new Complex[m_numberOfColumns*m_numberOfRows]; + for (int i = 0; i < m_numberOfColumns*m_numberOfRows; i++) { + values[i] = Complex::Cartesian(m_values[i].a(), m_values[i].b()); + } + return new ComplexMatrix(values, m_numberOfRows, m_numberOfColumns); + +} + +template class Poincare::ComplexMatrix; +template class Poincare::ComplexMatrix; + } diff --git a/poincare/src/confidence_interval.cpp b/poincare/src/confidence_interval.cpp index 386ea624a..adf99e678 100644 --- a/poincare/src/confidence_interval.cpp +++ b/poincare/src/confidence_interval.cpp @@ -25,20 +25,21 @@ Expression * ConfidenceInterval::cloneWithDifferentOperands(Expression** newOper return ci; } -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(); +template +Evaluation * ConfidenceInterval::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Evaluation * fInput = m_args[0]->evaluate(context, angleUnit); + Evaluation * nInput = m_args[1]->evaluate(context, angleUnit); + T f = fInput->toScalar(); + T n = nInput->toScalar(); 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)); + if (isnan(f) || isnan(n) || n != (int)n || n < 0 || f < 0 || f > 1) { + return new Complex(Complex::Float(NAN)); } - Complex operands[2]; - operands[0] = Complex::Float(f - 1.0f/std::sqrt(n)); - operands[1] = Complex::Float(f + 1.0f/std::sqrt(n)); - return new ComplexMatrix(operands, 2, 1); + Complex operands[2]; + operands[0] = Complex::Float(f - 1/std::sqrt(n)); + operands[1] = Complex::Float(f + 1/std::sqrt(n)); + return new ComplexMatrix(operands, 2, 1); } } diff --git a/poincare/src/conjugate.cpp b/poincare/src/conjugate.cpp index 7273b16ed..33333cc7f 100644 --- a/poincare/src/conjugate.cpp +++ b/poincare/src/conjugate.cpp @@ -26,7 +26,8 @@ Expression * Conjugate::cloneWithDifferentOperands(Expression** newOperands, return c; } -Complex Conjugate::computeComplex(const Complex c, AngleUnit angleUnit) const { +template +Complex Conjugate::templatedComputeComplex(const Complex c) const { return c.conjugate(); } diff --git a/poincare/src/cosine.cpp b/poincare/src/cosine.cpp index bd88612d5..2524592dd 100644 --- a/poincare/src/cosine.cpp +++ b/poincare/src/cosine.cpp @@ -9,7 +9,7 @@ extern "C" { namespace Poincare { Cosine::Cosine() : - TrigonometricFunction("cos") + Function("cos") { } @@ -25,13 +25,23 @@ Expression * Cosine::cloneWithDifferentOperands(Expression** newOperands, return c; } -Complex Cosine::compute(const Complex c) { - Complex arg = Complex::Cartesian(-c.b(), c.a()); +template +Complex Cosine::compute(const Complex c, AngleUnit angleUnit) { + assert(angleUnit != AngleUnit::Default); + if (c.b() == 0) { + T input = c.a(); + if (angleUnit == AngleUnit::Degree) { + input *= M_PI/180.0f; + } + T result = std::cos(input); + // TODO: See if necessary with double???? + if (input != 0 && std::fabs(result/input) <= 1E-7f) { + return Complex::Float(0); + } + return Complex::Float(result); + } + Complex arg = Complex::Cartesian(-c.b(), c.a()); return HyperbolicCosine::compute(arg); } -float Cosine::computeForRadianReal(float x) const { - return std::cos(x); -} - } diff --git a/poincare/src/derivative.cpp b/poincare/src/derivative.cpp index e0cf804e5..7e87c0589 100644 --- a/poincare/src/derivative.cpp +++ b/poincare/src/derivative.cpp @@ -26,21 +26,24 @@ Expression * Derivative::cloneWithDifferentOperands(Expression** newOperands, return d; } -Evaluation * Derivative::privateEvaluate(Context& context, AngleUnit angleUnit) const { - VariableContext xContext = VariableContext('x', &context); +template +Evaluation * Derivative::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + static T min = sizeof(T) == sizeof(double) ? DBL_MIN : FLT_MIN; + static T max = sizeof(T) == sizeof(double) ? DBL_MAX : FLT_MAX; + VariableContext xContext = VariableContext('x', &context); Symbol xSymbol = Symbol('x'); - Evaluation * xInput = m_args[1]->evaluate(context, angleUnit); - float x = xInput->toFloat(); + Evaluation * xInput = m_args[1]->evaluate(context, angleUnit); + T x = xInput->toScalar(); delete xInput; - Complex e = Complex::Float(x); + Complex e = Complex::Float(x); xContext.setExpressionForSymbolName(&e, &xSymbol); - Evaluation * fInput = m_args[1]->evaluate(xContext, angleUnit); - float functionValue = fInput->toFloat(); + Evaluation * fInput = m_args[1]->evaluate(xContext, angleUnit); + T functionValue = fInput->toScalar(); delete fInput; // No complex/matrix version of Derivative if (isnan(x) || isnan(functionValue)) { - return new Complex(Complex::Float(NAN)); + return new Complex(Complex::Float(NAN)); } /* Ridders' Algorithm @@ -51,37 +54,37 @@ Evaluation * Derivative::privateEvaluate(Context& context, AngleUnit angleUnit) * pp. 75–76. */ // Initiate hh - float h = std::fabs(x) < FLT_MIN ? k_minInitialRate : x/1000.0f; - float f2 = approximateDerivate2(x, h, xContext, angleUnit); - f2 = std::fabs(f2) < FLT_MIN ? k_minInitialRate : f2; - float hh = std::sqrt(std::fabs(functionValue/(f2/(std::pow(h,2.0f)))))/10.0f; - hh = std::fabs(hh) std::fabs(a[j][i]-a[j-1][i-1]) ? std::fabs(a[j][i]-a[j-1][i]) : std::fabs(a[j][i]-a[j-1][i-1]); /* Update error and answer if error decreases */ @@ -92,54 +95,56 @@ Evaluation * Derivative::privateEvaluate(Context& context, AngleUnit angleUnit) } /* If higher extrapolation order significantly increases the error, return * early */ - if (std::fabs(a[i][i]-a[i-1][i-1]) > 2.0f*err) { + if (std::fabs(a[i][i]-a[i-1][i-1]) > 2*err) { break; } } /* if the error is too big regarding the value, do not return the answer */ if (err/ans > k_maxErrorRateOnApproximation || isnan(err)) { - return new Complex(Complex::Float(NAN)); + return new Complex(Complex::Float(NAN)); } - if (err < FLT_MIN) { - return new Complex(Complex::Float(ans)); + if (err < min) { + return new Complex(Complex::Float(ans)); } - err = std::pow(10.0f, (int)std::log10(std::fabs(err))+2.0f); - return new Complex(Complex::Float(std::round(ans/err)*err)); + err = std::pow((T)10, std::floor(std::log10(std::fabs(err)))+2); + return new Complex(Complex::Float(std::round(ans/err)*err)); } -float Derivative::growthRateAroundAbscissa(float x, float h, VariableContext xContext, AngleUnit angleUnit) const { +template +T Derivative::growthRateAroundAbscissa(T x, T h, VariableContext xContext, AngleUnit angleUnit) const { Symbol xSymbol = Symbol('x'); - Complex e = Complex::Float(x + h); + Complex e = Complex::Float(x + h); xContext.setExpressionForSymbolName(&e, &xSymbol); - Evaluation * fInput = m_args[0]->evaluate(xContext, angleUnit); - float expressionPlus = fInput->toFloat(); + Evaluation * fInput = m_args[0]->evaluate(xContext, angleUnit); + T expressionPlus = fInput->toScalar(); delete fInput; - e = Complex::Float(x-h); + e = Complex::Float(x-h); xContext.setExpressionForSymbolName(&e, &xSymbol); - fInput = m_args[0]->evaluate(xContext, angleUnit); - float expressionMinus = fInput->toFloat(); + fInput = m_args[0]->evaluate(xContext, angleUnit); + T expressionMinus = fInput->toScalar(); delete fInput; return (expressionPlus - expressionMinus)/(2*h); } -float Derivative::approximateDerivate2(float x, float h, VariableContext xContext, AngleUnit angleUnit) const { +template +T Derivative::approximateDerivate2(T x, T h, VariableContext xContext, AngleUnit angleUnit) const { Symbol xSymbol = Symbol('x'); - Complex e = Complex::Float(x + h); + Complex e = Complex::Float(x + h); xContext.setExpressionForSymbolName(&e, &xSymbol); - Evaluation * fInput = m_args[0]->evaluate(xContext, angleUnit); - float expressionPlus = fInput->toFloat(); + Evaluation * fInput = m_args[0]->evaluate(xContext, angleUnit); + T expressionPlus = fInput->toScalar(); delete fInput; - e = Complex::Float(x); + e = Complex::Float(x); xContext.setExpressionForSymbolName(&e, &xSymbol); - fInput = m_args[0]->evaluate(xContext, angleUnit); - float expression = fInput->toFloat(); + fInput = m_args[0]->evaluate(xContext, angleUnit); + T expression = fInput->toScalar(); delete fInput; - e = Complex::Float(x-h); + e = Complex::Float(x-h); xContext.setExpressionForSymbolName(&e, &xSymbol); - fInput = m_args[0]->evaluate(xContext, angleUnit); - float expressionMinus = fInput->toFloat(); + fInput = m_args[0]->evaluate(xContext, angleUnit); + T expressionMinus = fInput->toScalar(); delete fInput; - return expressionPlus - 2.0f*expression + expressionMinus; + return expressionPlus - 2.0*expression + expressionMinus; } } diff --git a/poincare/src/determinant.cpp b/poincare/src/determinant.cpp index 69fc00056..314bd4230 100644 --- a/poincare/src/determinant.cpp +++ b/poincare/src/determinant.cpp @@ -24,9 +24,11 @@ Expression * Determinant::cloneWithDifferentOperands(Expression** newOperands, return d; } -Evaluation * Determinant::privateEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * input = m_args[0]->evaluate(context, angleUnit); - Evaluation * result = input->createDeterminant(); +template +Evaluation * Determinant::templatedEvaluate(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 933dfda5f..f659377b9 100644 --- a/poincare/src/division_quotient.cpp +++ b/poincare/src/division_quotient.cpp @@ -24,17 +24,18 @@ Expression * DivisionQuotient::cloneWithDifferentOperands(Expression** newOperan return dq; } -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(); +template +Evaluation * DivisionQuotient::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Evaluation * f1Input = m_args[0]->evaluate(context, angleUnit); + Evaluation * f2Input = m_args[1]->evaluate(context, angleUnit); + T f1 = f1Input->toScalar(); + T f2 = f2Input->toScalar(); delete f1Input; delete f2Input; if (isnan(f1) || isnan(f2) || f1 != (int)f1 || f2 != (int)f2) { - return new Complex(Complex::Float(NAN)); + return new Complex(Complex::Float(NAN)); } - return new Complex(Complex::Float(std::floor(f1/f2))); + return new Complex(Complex::Float(std::floor(f1/f2))); } } diff --git a/poincare/src/division_remainder.cpp b/poincare/src/division_remainder.cpp index 52f236767..4bc9fb5aa 100644 --- a/poincare/src/division_remainder.cpp +++ b/poincare/src/division_remainder.cpp @@ -24,17 +24,18 @@ Expression * DivisionRemainder::cloneWithDifferentOperands(Expression** newOpera return dr; } -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(); +template +Evaluation * DivisionRemainder::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Evaluation * f1Input = m_args[0]->evaluate(context, angleUnit); + Evaluation * f2Input = m_args[1]->evaluate(context, angleUnit); + T f1 = f1Input->toScalar(); + T f2 = f2Input->toScalar(); delete f1Input; delete f2Input; if (isnan(f1) || isnan(f2) || f1 != (int)f1 || f2 != (int)f2) { - return new Complex(Complex::Float(NAN)); + return new Complex(Complex::Float(NAN)); } - return new Complex(Complex::Float(std::round(f1-f2*std::floor(f1/f2)))); + return new Complex(Complex::Float(std::round(f1-f2*std::floor(f1/f2)))); } } diff --git a/poincare/src/evaluation.cpp b/poincare/src/evaluation.cpp index 70e8ebe7f..ed5d0012a 100644 --- a/poincare/src/evaluation.cpp +++ b/poincare/src/evaluation.cpp @@ -14,50 +14,50 @@ extern "C" { namespace Poincare { -Expression::Type Evaluation::type() const { +template +Expression::Type Evaluation::type() const { return Type::Evaluation; } -bool Evaluation::hasValidNumberOfArguments() const { +template +bool Evaluation::hasValidNumberOfArguments() const { return true; } -const Expression * Evaluation::operand(int i) const { +template +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 { +template +Evaluation * Evaluation::createTrace() const { if (numberOfColumns() != numberOfRows()) { - return new Complex(Complex::Float(NAN)); + return new Complex(Complex::Float(NAN)); } int dim = numberOfRows(); - Complex c = Complex::Float(0.0f); + Complex c = Complex::Float(0); for (int i = 0; i < dim; i++) { c = Addition::compute(c, *complexOperand(i*dim+i)); } - return new Complex(c); + return new Complex(c); } +template // TODO: implement determinant for complex matrix? -Evaluation * Evaluation::createDeterminant() const { +Evaluation * Evaluation::createDeterminant() const { if (numberOfColumns() != numberOfRows()) { - return new Complex(Complex::Float(NAN)); + return new Complex(Complex::Float(NAN)); } int dim = numberOfRows(); - float ** tempMat = new float*[dim]; + T ** tempMat = new T*[dim]; for (int i = 0; i < dim; i++) { - tempMat[i] = new float[dim]; + tempMat[i] = new T[dim]; } - float det = 1.0f; + T det = 1; /* 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(); + tempMat[i][j] = complexOperand(i*dim+ j)->toScalar(); } } @@ -70,19 +70,19 @@ Evaluation * Evaluation::createDeterminant() const { rowWithPivot = row; } } - float valuePivot = tempMat[rowWithPivot][i]; + T valuePivot = tempMat[rowWithPivot][i]; /* if the pivot is null, det = 0. */ if (std::fabs(valuePivot) <= FLT_EPSILON) { for (int i = 0; i < dim; i++) { free(tempMat[i]); } free(tempMat); - return new Complex(Complex::Float(0.0f)); + 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]; + T temp = tempMat[i][col]; tempMat[i][col] = tempMat[rowWithPivot][col]; tempMat[rowWithPivot][col] = temp; } @@ -91,7 +91,7 @@ Evaluation * Evaluation::createDeterminant() const { 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; + T factor = tempMat[row][i]/valuePivot; for (int col = i; col < dim; col++) { tempMat[row][col] -= factor*tempMat[i][col]; } @@ -102,22 +102,23 @@ Evaluation * Evaluation::createDeterminant() const { delete[] tempMat[i]; } delete[] tempMat; - return new Complex(Complex::Float(det)); + return new Complex(Complex::Float(det)); } -Evaluation * Evaluation::createInverse() const { +template +Evaluation * Evaluation::createInverse() const { if (numberOfColumns() != numberOfRows()) { - return new Complex(Complex::Float(NAN)); + 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]; + T ** inv = new T*[dim]; for (int i = 0; i < dim; i++) { - inv[i] = new float [2*dim]; + inv[i] = new T [2*dim]; } for (int i = 0; i < dim; i++) { for (int j = 0; j < dim; j++) { - inv[i][j] = complexOperand(i*dim+j)->toFloat(); + inv[i][j] = complexOperand(i*dim+j)->toScalar(); } for (int j = dim; j < 2*dim; j++) { inv[i][j] = (i+dim == j); @@ -132,19 +133,19 @@ Evaluation * Evaluation::createInverse() const { rowWithPivot = row; } } - float valuePivot = inv[rowWithPivot][i]; + T valuePivot = inv[rowWithPivot][i]; /* if the pivot is null, the matrix in not invertible. */ if (std::fabs(valuePivot) <= FLT_EPSILON) { for (int i = 0; i < dim; i++) { free(inv[i]); } free(inv); - return new Complex(Complex::Float(NAN)); + 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]; + T temp = inv[i][col]; inv[i][col] = inv[rowWithPivot][col]; inv[rowWithPivot][col] = temp; } @@ -158,37 +159,41 @@ Evaluation * Evaluation::createInverse() const { if (row == i) { continue; } - float factor = inv[row][i]; + T factor = inv[row][i]; for (int col = 0; col < 2*dim; col++) { inv[row][col] -= factor*inv[i][col]; } } } - Complex * operands = new Complex[numberOfOperands()]; + 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])); + 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()); + Evaluation * matrix = new ComplexMatrix(operands, numberOfColumns(), numberOfRows()); delete[] operands; return matrix; } -Evaluation * Evaluation::createTranspose() const { - Complex * operands = new Complex[numberOfOperands()]; +template +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()); + Evaluation * matrix = new ComplexMatrix(operands, numberOfRows(), numberOfColumns()); delete[] operands; return matrix; } +template class Poincare::Evaluation; +template class Poincare::Evaluation; + } diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index 2eaed2f59..fe59f7c5d 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -59,30 +59,30 @@ ExpressionLayout * Expression::createLayout(FloatDisplayMode floatDisplayMode, C } } -Evaluation * Expression::evaluate(Context& context, AngleUnit angleUnit) const { +template Evaluation * Expression::evaluate(Context& context, AngleUnit angleUnit) const { switch (angleUnit) { case AngleUnit::Default: - return privateEvaluate(context, Preferences::sharedPreferences()->angleUnit()); + return privateEvaluate(T(), context, Preferences::sharedPreferences()->angleUnit()); default: - return privateEvaluate(context, angleUnit); + return privateEvaluate(T(), context, angleUnit); } } -float Expression::approximate(Context& context, AngleUnit angleUnit) const { - Evaluation * evaluation = evaluate(context, angleUnit); - float result = evaluation->toFloat(); +template T Expression::approximate(Context& context, AngleUnit angleUnit) const { + Evaluation * evaluation = evaluate(context, angleUnit); + T result = evaluation->toScalar(); delete evaluation; return result; } -float Expression::approximate(const char * text, Context& context, AngleUnit angleUnit) { +template T Expression::approximate(const char * text, Context& context, AngleUnit angleUnit) { Expression * exp = parse(text); if (exp == nullptr) { return NAN; } - Evaluation * evaluation = exp->evaluate(context, angleUnit); + Evaluation * evaluation = exp->evaluate(context, angleUnit); delete exp; - float result = evaluation->toFloat(); + T result = evaluation->toScalar(); delete evaluation; return result; } @@ -247,3 +247,10 @@ bool Expression::shouldStopProcessing() const { } } + +template Poincare::Evaluation * Poincare::Expression::evaluate(Context& context, AngleUnit angleUnit) const; +template Poincare::Evaluation * Poincare::Expression::evaluate(Context& context, AngleUnit angleUnit) const; +template double Poincare::Expression::approximate(char const*, Poincare::Context&, Poincare::Expression::AngleUnit); +template float Poincare::Expression::approximate(char const*, Poincare::Context&, Poincare::Expression::AngleUnit); +template double Poincare::Expression::approximate(Poincare::Context&, Poincare::Expression::AngleUnit) const; +template float Poincare::Expression::approximate(Poincare::Context&, Poincare::Expression::AngleUnit) const; diff --git a/poincare/src/expression_lexer.l b/poincare/src/expression_lexer.l index 88a201532..921f8a74a 100644 --- a/poincare/src/expression_lexer.l +++ b/poincare/src/expression_lexer.l @@ -135,8 +135,8 @@ tan { poincare_expression_yylval.expression = new Tangent(); return FUNCTION; } tanh { poincare_expression_yylval.expression = new HyperbolicTangent(); return FUNCTION; } trace { poincare_expression_yylval.expression = new MatrixTrace(); return FUNCTION; } transpose { poincare_expression_yylval.expression = new MatrixTranspose(); return FUNCTION; } -undef { poincare_expression_yylval.expression = new Complex(Complex::Float(NAN)); return UNDEFINED; } -inf { poincare_expression_yylval.expression = new Complex(Complex::Float(INFINITY)); return UNDEFINED; } +undef { poincare_expression_yylval.expression = new Complex(Complex::Float(NAN)); return UNDEFINED; } +inf { poincare_expression_yylval.expression = new Complex(Complex::Float(INFINITY)); return UNDEFINED; } \x89 { poincare_expression_yylval.character = yytext[0]; return SYMBOL; } \x8c { return EE; } \x90 { poincare_expression_yylval.expression = new SquareRoot(); return FUNCTION; } diff --git a/poincare/src/expression_matrix.cpp b/poincare/src/expression_matrix.cpp index 3ca13226e..95206fbf2 100644 --- a/poincare/src/expression_matrix.cpp +++ b/poincare/src/expression_matrix.cpp @@ -63,25 +63,21 @@ Expression * ExpressionMatrix::cloneWithDifferentOperands(Expression** newOperan return new ExpressionMatrix(newOperands, numberOfOperands, numberOfColumns(), numberOfRows(), cloneOperands); } -Evaluation * ExpressionMatrix::privateEvaluate(Context& context, AngleUnit angleUnit) const { - Complex * operands = new Complex[numberOfOperands()]; +template +Evaluation * ExpressionMatrix::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Complex * operands = new Complex[numberOfOperands()]; for (int i = 0; i < numberOfOperands(); i++) { - Evaluation * operandEvaluation = operand(i)->evaluate(context, angleUnit); + Evaluation * operandEvaluation = operand(i)->evaluate(context, angleUnit); if (operandEvaluation->numberOfOperands() != 1) { - operands[i] = Complex::Float(NAN); + operands[i] = Complex::Float(NAN); } else { operands[i] = *(operandEvaluation->complexOperand(0)); } delete operandEvaluation; } - Evaluation * matrix = new ComplexMatrix(operands, numberOfRows(), numberOfColumns()); + 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 b8768ab46..acfa871ba 100644 --- a/poincare/src/expression_parser.y +++ b/poincare/src/expression_parser.y @@ -148,14 +148,14 @@ lstData: number: DIGITS { $$ = new Poincare::Integer($1.address, false); } - | DOT DIGITS { $$ = new Poincare::Complex(nullptr, 0, false, $2.address, $2.length, nullptr, 0, false); } - | DIGITS DOT DIGITS { $$ = new Poincare::Complex($1.address, $1.length, false, $3.address, $3.length, nullptr, 0, false); } - | DOT DIGITS EE DIGITS { $$ = new Poincare::Complex(nullptr, 0, false, $2.address, $2.length, $4.address, $4.length, false); } - | DIGITS DOT DIGITS EE DIGITS { $$ = new Poincare::Complex($1.address, $1.length, false, $3.address, $3.length, $5.address, $5.length, false); } - | DIGITS EE DIGITS { $$ = new Poincare::Complex($1.address, $1.length, false, nullptr, 0, $3.address, $3.length, false); } - | DOT DIGITS EE MINUS DIGITS { $$ = new Poincare::Complex(nullptr, 0, false, $2.address, $2.length, $5.address, $5.length, true); } - | DIGITS DOT DIGITS EE MINUS DIGITS { $$ = new Poincare::Complex($1.address, $1.length, false, $3.address, $3.length, $6.address, $6.length, true); } - | DIGITS EE MINUS DIGITS { $$ = new Poincare::Complex($1.address, $1.length, false, nullptr, 0, $4.address, $4.length, true); } + | DOT DIGITS { $$ = new Poincare::Complex(nullptr, 0, false, $2.address, $2.length, nullptr, 0, false); } + | DIGITS DOT DIGITS { $$ = new Poincare::Complex($1.address, $1.length, false, $3.address, $3.length, nullptr, 0, false); } + | DOT DIGITS EE DIGITS { $$ = new Poincare::Complex(nullptr, 0, false, $2.address, $2.length, $4.address, $4.length, false); } + | DIGITS DOT DIGITS EE DIGITS { $$ = new Poincare::Complex($1.address, $1.length, false, $3.address, $3.length, $5.address, $5.length, false); } + | DIGITS EE DIGITS { $$ = new Poincare::Complex($1.address, $1.length, false, nullptr, 0, $3.address, $3.length, false); } + | DOT DIGITS EE MINUS DIGITS { $$ = new Poincare::Complex(nullptr, 0, false, $2.address, $2.length, $5.address, $5.length, true); } + | DIGITS DOT DIGITS EE MINUS DIGITS { $$ = new Poincare::Complex($1.address, $1.length, false, $3.address, $3.length, $6.address, $6.length, true); } + | DIGITS EE MINUS DIGITS { $$ = new Poincare::Complex($1.address, $1.length, false, nullptr, 0, $4.address, $4.length, true); } symb: SYMBOL { $$ = new Poincare::Symbol($1); } @@ -169,7 +169,7 @@ exp: UNDEFINED { $$ = $1; } | exp BANG { $$ = new Poincare::Factorial($1, false); } | number { $$ = $1; } - | ICOMPLEX { $$ = new Poincare::Complex(Poincare::Complex::Cartesian(0.0f, 1.0f)); } + | ICOMPLEX { $$ = new Poincare::Complex(Poincare::Complex::Cartesian(0.0f, 1.0f)); } | symb { $$ = $1; } | exp PLUS exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Addition(terms, false); } | exp MINUS exp { Poincare::Expression * terms[2] = {$1,$3}; $$ = new Poincare::Subtraction(terms, false); } diff --git a/poincare/src/factorial.cpp b/poincare/src/factorial.cpp index 05ee87e91..1762ea11e 100644 --- a/poincare/src/factorial.cpp +++ b/poincare/src/factorial.cpp @@ -25,20 +25,21 @@ Expression * Factorial::cloneWithDifferentOperands(Expression** newOperands, return f; } -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); +template +Complex Factorial::templatedComputeComplex(const Complex c) const { + T n = c.a(); + if (c.b() != 0 || isnan(n) || n != (int)n || n < 0) { + return Complex::Float(NAN); } - return Complex::Float(c.r()); - float result = 1.0f; + return Complex::Float(c.r()); + T result = 1; for (int i = 1; i <= (int)n; i++) { - result *= (float)i; + result *= (T)i; if (isinf(result)) { - return Complex::Float(result); + return Complex::Float(result); } } - return Complex::Float(std::round(result)); + return Complex::Float(std::round(result)); } ExpressionLayout * Factorial::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { diff --git a/poincare/src/floor.cpp b/poincare/src/floor.cpp index 2651100a2..f0378e74a 100644 --- a/poincare/src/floor.cpp +++ b/poincare/src/floor.cpp @@ -24,11 +24,12 @@ Expression * Floor::cloneWithDifferentOperands(Expression** newOperands, return f; } -Complex Floor::computeComplex(const Complex c, AngleUnit angleUnit) const { - if (c.b() != 0.0f) { - return Complex::Float(NAN); +template +Complex Floor::templatedComputeComplex(const Complex c) const { + if (c.b() != 0) { + return Complex::Float(NAN); } - return Complex::Float(std::floor(c.a())); + return Complex::Float(std::floor(c.a())); } } diff --git a/poincare/src/frac_part.cpp b/poincare/src/frac_part.cpp index da41f7cef..554151598 100644 --- a/poincare/src/frac_part.cpp +++ b/poincare/src/frac_part.cpp @@ -24,11 +24,12 @@ Expression * FracPart::cloneWithDifferentOperands(Expression** newOperands, return fp; } -Complex FracPart::computeComplex(const Complex c, AngleUnit angleUnit) const { - if (c.b() != 0.0f) { - return Complex::Float(NAN); +template +Complex FracPart::templatedComputeComplex(const Complex c) const { + if (c.b() != 0) { + return Complex::Float(NAN); } - return Complex::Float(c.a()-std::floor(c.a())); + return Complex::Float(c.a()-std::floor(c.a())); } } diff --git a/poincare/src/fraction.cpp b/poincare/src/fraction.cpp index bd499642c..e99609b0a 100644 --- a/poincare/src/fraction.cpp +++ b/poincare/src/fraction.cpp @@ -27,31 +27,32 @@ Expression::Type Fraction::type() const { return Type::Fraction; } -Complex Fraction::compute(const Complex c, const Complex d) { - float norm = d.a()*d.a() + d.b()*d.b(); +template +Complex Fraction::compute(const Complex c, const Complex d) { + T 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 Complex::Float(c.a()/d.a()); + if (d.b() == 0 && c.b() == 0) { + return Complex::Float(c.a()/d.a()); } - return 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); } -Evaluation * Fraction::computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * m) const { - Evaluation * inverse = m->createInverse(); - Evaluation * result = Multiplication::computeOnComplexAndMatrix(c, inverse); +template Evaluation * Fraction::templatedComputeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const { + Evaluation * inverse = n->createInverse(); + Evaluation * result = Multiplication::computeOnComplexAndMatrix(c, inverse); delete inverse; return result; } -Evaluation * Fraction::computeOnNumericalMatrices(Evaluation * m, Evaluation * n) const { +template Evaluation * Fraction::templatedComputeOnComplexMatrices(Evaluation * m, Evaluation * n) const { if (m->numberOfColumns() != n->numberOfColumns()) { return nullptr; } - Evaluation * inverse = n->createInverse(); - Evaluation * result = Multiplication::computeOnMatrices(m, inverse); + 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 103efe77c..b7b905686 100644 --- a/poincare/src/function.cpp +++ b/poincare/src/function.cpp @@ -56,24 +56,21 @@ 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 { +template +Evaluation * Function::templatedEvaluate(Context& context, AngleUnit angleUnit) const { if (m_numberOfArguments != 1) { - return new Complex(Complex::Float(NAN)); + return new Complex(Complex::Float(NAN)); } - Evaluation * input = m_args[0]->evaluate(context, angleUnit); - Complex * operands = new Complex[input->numberOfRows()*input->numberOfColumns()]; + 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; + Evaluation * result = nullptr; if (input->numberOfOperands() == 1) { - result = new Complex(operands[0]); + result = new Complex(operands[0]); } else { - result = new ComplexMatrix(operands, input->numberOfRows(), input->numberOfColumns()); + result = new ComplexMatrix(operands, input->numberOfRows(), input->numberOfColumns()); } delete input; delete[] operands; diff --git a/poincare/src/global_context.cpp b/poincare/src/global_context.cpp index e6f61a9d0..d7e4d5ad0 100644 --- a/poincare/src/global_context.cpp +++ b/poincare/src/global_context.cpp @@ -7,8 +7,8 @@ namespace Poincare { GlobalContext::GlobalContext() : - m_pi(Complex::Float(M_PI)), - m_e(Complex::Float(M_E)) + m_pi(Complex::Float(M_PI)), + m_e(Complex::Float(M_E)) { for (int i = 0; i < k_maxNumberOfScalarExpressions; i++) { m_expressions[i] = nullptr; @@ -33,8 +33,8 @@ GlobalContext::~GlobalContext() { } } -Evaluation * GlobalContext::defaultExpression() { - static Evaluation * defaultExpression = new Complex(Complex::Float(0.0f)); +Complex * GlobalContext::defaultExpression() { + static Complex * defaultExpression = new Complex(Complex::Float(0.0)); return defaultExpression; } @@ -43,7 +43,7 @@ int GlobalContext::symbolIndex(const Symbol * symbol) const { return index; } -const Evaluation * GlobalContext::expressionForSymbol(const Symbol * symbol) { +const Evaluation * GlobalContext::evaluationForSymbol(const Symbol * symbol) { if (symbol->name() == Ion::Charset::SmallPi) { return &m_pi; } @@ -64,7 +64,7 @@ const Evaluation * GlobalContext::expressionForSymbol(const Symbol * symbol) { return m_expressions[index]; } -void GlobalContext::setExpressionForSymbolName(Evaluation * expression, const Symbol * symbol) { +void GlobalContext::setExpressionForSymbolName(Expression * expression, const Symbol * symbol) { if (symbol->isMatrixSymbol()) { int indexMatrix = symbol->name() - (char)Symbol::SpecialSymbols::M0; assert(indexMatrix >= 0 && indexMatrix < k_maxNumberOfMatrixExpressions); @@ -73,10 +73,12 @@ void GlobalContext::setExpressionForSymbolName(Evaluation * expression, const Sy m_matrixExpressions[indexMatrix] = nullptr; } if (expression != nullptr) { - if (expression->numberOfOperands() == 1) { - m_matrixExpressions[indexMatrix] = new ComplexMatrix(expression->complexOperand(0), 1, 1); + Evaluation * evaluation = expression->evaluate(*this); + if (evaluation->numberOfOperands() == 1) { + m_matrixExpressions[indexMatrix] = new ComplexMatrix(evaluation->complexOperand(0), 1, 1); + delete evaluation; } else { - m_matrixExpressions[indexMatrix] = expression->clone(); + m_matrixExpressions[indexMatrix] = (ComplexMatrix *)evaluation; } } return; @@ -92,11 +94,13 @@ void GlobalContext::setExpressionForSymbolName(Evaluation * expression, const Sy if (expression == nullptr) { return; } - if (expression->numberOfOperands() == 1) { - m_expressions[index] = new Complex(*(expression->complexOperand(0))); + Evaluation * evaluation = expression->evaluate(*this); + if (evaluation->numberOfOperands() == 1) { + m_expressions[index] = new Complex(*(evaluation->complexOperand(0))); } else { - m_expressions[index] = new Complex(Complex::Float(NAN)); + m_expressions[index] = new Complex(Complex::Float(NAN)); } + delete evaluation; } } diff --git a/poincare/src/great_common_divisor.cpp b/poincare/src/great_common_divisor.cpp index 719b2dd2f..832f85ff8 100644 --- a/poincare/src/great_common_divisor.cpp +++ b/poincare/src/great_common_divisor.cpp @@ -25,15 +25,16 @@ Expression * GreatCommonDivisor::cloneWithDifferentOperands(Expression** newOper return gcd; } -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(); +template +Evaluation * GreatCommonDivisor::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Evaluation * f1Input = m_args[0]->evaluate(context, angleUnit); + Evaluation * f2Input = m_args[1]->evaluate(context, angleUnit); + T f1 = f1Input->toScalar(); + T f2 = f2Input->toScalar(); delete f1Input; delete f2Input; if (isnan(f1) || isnan(f2) || f1 != (int)f1 || f2 != (int)f2) { - return new Complex(Complex::Float(NAN)); + return new Complex(Complex::Float(NAN)); } int a = (int)f2; int b = (int)f1; @@ -47,8 +48,7 @@ Evaluation * GreatCommonDivisor::privateEvaluate(Context & context, AngleUnit an a = b; b = r; } - return new Complex(Complex::Float(std::round((float)a))); - + return new Complex(Complex::Float(std::round((T)a))); } } diff --git a/poincare/src/hyperbolic_arc_cosine.cpp b/poincare/src/hyperbolic_arc_cosine.cpp index 30e86f2f2..6c6698cef 100644 --- a/poincare/src/hyperbolic_arc_cosine.cpp +++ b/poincare/src/hyperbolic_arc_cosine.cpp @@ -23,11 +23,12 @@ Expression * HyperbolicArcCosine::cloneWithDifferentOperands(Expression** newOpe return c; } -Complex HyperbolicArcCosine::computeComplex(const Complex c, AngleUnit angleUnit) const { - if (c.b() != 0.0f) { - return Complex::Float(NAN); +template +Complex HyperbolicArcCosine::templatedComputeComplex(const Complex c) const { + if (c.b() != 0) { + return Complex::Float(NAN); } - return Complex::Float(std::acosh(c.a())); + return Complex::Float(std::acosh(c.a())); } } diff --git a/poincare/src/hyperbolic_arc_sine.cpp b/poincare/src/hyperbolic_arc_sine.cpp index de1d08d40..a55395231 100644 --- a/poincare/src/hyperbolic_arc_sine.cpp +++ b/poincare/src/hyperbolic_arc_sine.cpp @@ -23,11 +23,12 @@ Expression * HyperbolicArcSine::cloneWithDifferentOperands(Expression** newOpera return s; } -Complex HyperbolicArcSine::computeComplex(const Complex c, AngleUnit angleUnit) const { - if (c.b() != 0.0f) { - return Complex::Float(NAN); +template +Complex HyperbolicArcSine::templatedComputeComplex(const Complex c) const { + if (c.b() != 0) { + return Complex::Float(NAN); } - return Complex::Float(std::asinh(c.a())); + return Complex::Float(std::asinh(c.a())); } } diff --git a/poincare/src/hyperbolic_arc_tangent.cpp b/poincare/src/hyperbolic_arc_tangent.cpp index a7be7cfcd..c2d9a68d7 100644 --- a/poincare/src/hyperbolic_arc_tangent.cpp +++ b/poincare/src/hyperbolic_arc_tangent.cpp @@ -23,11 +23,12 @@ Expression * HyperbolicArcTangent::cloneWithDifferentOperands(Expression** newOp return t; } -Complex HyperbolicArcTangent::computeComplex(const Complex c, AngleUnit angleUnit) const { - if (c.b() != 0.0f) { - return Complex::Float(NAN); +template +Complex HyperbolicArcTangent::templatedComputeComplex(const Complex c) const { + if (c.b() != 0) { + return Complex::Float(NAN); } - return Complex::Float(std::atanh(c.a())); + return Complex::Float(std::atanh(c.a())); } } diff --git a/poincare/src/hyperbolic_cosine.cpp b/poincare/src/hyperbolic_cosine.cpp index 33683bcdf..283275325 100644 --- a/poincare/src/hyperbolic_cosine.cpp +++ b/poincare/src/hyperbolic_cosine.cpp @@ -28,15 +28,16 @@ Expression * HyperbolicCosine::cloneWithDifferentOperands(Expression** newOperan return hc; } -Complex HyperbolicCosine::compute(const Complex c) { - if (c.b() == 0.0f) { - return Complex::Float(std::cosh(c.a())); +template +Complex HyperbolicCosine::compute(const Complex c) { + if (c.b() == 0) { + return Complex::Float(std::cosh(c.a())); } - 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)); + 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)); } } diff --git a/poincare/src/hyperbolic_sine.cpp b/poincare/src/hyperbolic_sine.cpp index c3ad78239..91ea1efdc 100644 --- a/poincare/src/hyperbolic_sine.cpp +++ b/poincare/src/hyperbolic_sine.cpp @@ -28,15 +28,16 @@ Expression * HyperbolicSine::cloneWithDifferentOperands(Expression** newOperands return hs; } -Complex HyperbolicSine::compute(const Complex c) { - if (c.b() == 0.0f) { - return Complex::Float(std::sinh(c.a())); +template +Complex HyperbolicSine::compute(const Complex c) { + if (c.b() == 0) { + return Complex::Float(std::sinh(c.a())); } - 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)); + 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)); } } diff --git a/poincare/src/hyperbolic_tangent.cpp b/poincare/src/hyperbolic_tangent.cpp index f01515b8f..4be35f1d3 100644 --- a/poincare/src/hyperbolic_tangent.cpp +++ b/poincare/src/hyperbolic_tangent.cpp @@ -26,12 +26,13 @@ Expression * HyperbolicTangent::cloneWithDifferentOperands(Expression** newOpera return ht; } -Complex HyperbolicTangent::compute(const Complex c) { - if (c.b() == 0.0f) { - return Complex::Float(std::tanh(c.a())); +template +Complex HyperbolicTangent::compute(const Complex c) { + if (c.b() == 0) { + return Complex::Float(std::tanh(c.a())); } - Complex arg1 = HyperbolicSine::compute(c); - Complex arg2 = HyperbolicCosine::compute(c); + 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 e0b9bd126..b68f44b4b 100644 --- a/poincare/src/imaginary_part.cpp +++ b/poincare/src/imaginary_part.cpp @@ -24,8 +24,9 @@ Expression * ImaginaryPart::cloneWithDifferentOperands(Expression** newOperands, return ip; } -Complex ImaginaryPart::computeComplex(const Complex c, AngleUnit angleUnit) const { - return Complex::Float(c.b()); +template +Complex ImaginaryPart::templatedComputeComplex(const Complex c) const { + return Complex::Float(c.b()); } } diff --git a/poincare/src/integer.cpp b/poincare/src/integer.cpp index 62d3f8430..540fae400 100644 --- a/poincare/src/integer.cpp +++ b/poincare/src/integer.cpp @@ -262,7 +262,7 @@ Expression * Integer::clone() const { return clone; } -Evaluation * Integer::privateEvaluate(Context& context, AngleUnit angleUnit) const { +Evaluation * Integer::privateEvaluate(SinglePrecision p, Context& context, AngleUnit angleUnit) const { union { uint32_t uint_result; float float_result; @@ -290,7 +290,7 @@ Evaluation * Integer::privateEvaluate(Context& context, AngleUnit angleUnit) con * 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 new Complex(Complex::Float(INFINITY)); + return new Complex(Complex::Float(INFINITY)); } exponent += (m_numberOfDigits-1)*32; exponent += numberOfBitsInLastDigit; @@ -300,7 +300,7 @@ Evaluation * Integer::privateEvaluate(Context& context, AngleUnit angleUnit) con if (m_numberOfDigits >= 2) { native_uint_t beforeLastDigit = m_digits[m_numberOfDigits-2]; mantissa |= (beforeLastDigit >> numberOfBitsInLastDigit); - } +} if ((m_numberOfDigits==1) && (m_digits[0]==0)) { /* This special case for 0 is needed, because the current algorithm assumes @@ -309,7 +309,7 @@ Evaluation * Integer::privateEvaluate(Context& context, AngleUnit angleUnit) con * assumed to be there, thus 126 0x000000 is equal to 0.5 and not zero. */ float result = m_negative ? -0.0f : 0.0f; - return new Complex(Complex::Float(result)); + return new Complex(Complex::Float(result)); } uint_result = 0; @@ -320,10 +320,79 @@ Evaluation * Integer::privateEvaluate(Context& context, AngleUnit angleUnit) con /* If exponent is 255 and the float is undefined, we have exceed IEEE 754 * representable float. */ if (exponent == 255 && isnan(float_result)) { - return new Complex(Complex::Float(INFINITY)); + return new Complex(Complex::Float(INFINITY)); } - return new Complex(Complex::Float(float_result)); + return new Complex(Complex::Float(float_result)); +} + +Evaluation * Integer::privateEvaluate(DoublePrecision p, Context& context, AngleUnit angleUnit) const { + union { + uint64_t uint_result; + double double_result; + }; + assert(sizeof(double) == 8); + /* We're generating an IEEE 754 compliant double. + * Theses numbers are 64-bit values, stored as follow: + * sign (1 bit) + * exponent (11 bits) + * mantissa (52 bits) + * + * We can tell that: + * - the exponent is the length of our BigInt, in bits - 1 + 1023; + * - the mantissa is the beginning of our BigInt, discarding the first bit + */ + native_uint_t lastDigit = m_digits[m_numberOfDigits-1]; + uint8_t numberOfBitsInLastDigit = log2(lastDigit); + + bool sign = m_negative; + + uint16_t exponent = 1022; + /* if the exponent is bigger then 2047, it cannot be stored as a uint11. Also, + * the integer whose 2-exponent is bigger than 2047 cannot be stored as a + * double (IEEE 754 double point). The approximation is thus INFINITY. */ + if ((int)exponent + (m_numberOfDigits-1)*32 +numberOfBitsInLastDigit> 2047) { + return new Complex(Complex::Float(INFINITY)); + } + exponent += (m_numberOfDigits-1)*32; + exponent += numberOfBitsInLastDigit; + + uint64_t mantissa = 0; + mantissa |= ((uint64_t)lastDigit << (64-numberOfBitsInLastDigit)); + int digitIndex = 2; + int numberOfBits = log2(lastDigit); + while (m_numberOfDigits >= digitIndex) { + lastDigit = m_digits[m_numberOfDigits-digitIndex]; + numberOfBits += 32; + if (64 > numberOfBits) { + mantissa |= ((uint64_t)lastDigit << (64-numberOfBits)); + } else { + mantissa |= ((uint64_t)lastDigit >> (numberOfBits-64)); + } + digitIndex++; + } + + if ((m_numberOfDigits==1) && (m_digits[0]==0)) { + /* This special case for 0 is needed, because the current algorithm assumes + * that the big integer is non zero, thus puts the exponent to 126 (integer + * area), the issue is that when the mantissa is 0, a "shadow bit" is + * assumed to be there, thus 126 0x000000 is equal to 0.5 and not zero. + */ + float result = m_negative ? -0.0f : 0.0f; + return new Complex(Complex::Float(result)); + } + + uint_result = 0; + uint_result |= ((uint64_t)sign << 63); + uint_result |= ((uint64_t)exponent << 52); + uint_result |= ((uint64_t)mantissa >> (64-52-1) & 0xFFFFFFFFFFFFF); + + /* If exponent is 2047 and the double is undefined, we have exceed IEEE 754 + * representable double. */ + if (exponent == 2047 && isnan(double_result)) { + return new Complex(Complex::Float(INFINITY)); + } + return new Complex(Complex::Float(double_result)); } Expression::Type Integer::type() const { diff --git a/poincare/src/integral.cpp b/poincare/src/integral.cpp index 446c5fe8c..d81949521 100644 --- a/poincare/src/integral.cpp +++ b/poincare/src/integral.cpp @@ -31,23 +31,24 @@ Expression * Integral::cloneWithDifferentOperands(Expression** newOperands, return i; } -Evaluation * Integral::privateEvaluate(Context & context, AngleUnit angleUnit) const { - VariableContext xContext = VariableContext('x', &context); - Evaluation * aInput = m_args[1]->evaluate(context, angleUnit); - float a = aInput->toFloat(); +template +Evaluation * Integral::templatedEvaluate(Context & context, AngleUnit angleUnit) const { + VariableContext xContext = VariableContext('x', &context); + Evaluation * aInput = m_args[1]->evaluate(context, angleUnit); + T a = aInput->toScalar(); delete aInput; - Evaluation * bInput = m_args[2]->evaluate(context, angleUnit); - float b = bInput->toFloat(); + Evaluation * bInput = m_args[2]->evaluate(context, angleUnit); + T b = bInput->toScalar(); delete bInput; if (isnan(a) || isnan(b)) { - return new Complex(Complex::Float(NAN)); + return new Complex(Complex::Float(NAN)); } #ifdef LAGRANGE_METHOD - float result = lagrangeGaussQuadrature(a, b, xContext, angleUnit); + T result = lagrangeGaussQuadrature(a, b, xContext, angleUnit); #else - float result = adaptiveQuadrature(a, b, 0.1, k_maxNumberOfIterations, xContext, angleUnit); + T result = adaptiveQuadrature(a, b, 0.1, k_maxNumberOfIterations, xContext, angleUnit); #endif - return new Complex(Complex::Float(result)); + return new Complex(Complex::Float(result)); } ExpressionLayout * Integral::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { @@ -59,32 +60,34 @@ ExpressionLayout * Integral::privateCreateLayout(FloatDisplayMode floatDisplayMo return new IntegralLayout(m_args[1]->createLayout(floatDisplayMode, complexFormat), m_args[2]->createLayout(floatDisplayMode, complexFormat), new HorizontalLayout(childrenLayouts, 2)); } -float Integral::functionValueAtAbscissa(float x, VariableContext xContext, AngleUnit angleUnit) const { - Complex e = Complex::Float(x); +template +T Integral::functionValueAtAbscissa(T x, VariableContext xContext, AngleUnit angleUnit) const { + Complex e = Complex::Float(x); Symbol xSymbol = Symbol('x'); xContext.setExpressionForSymbolName(&e, &xSymbol); - Evaluation * f = m_args[0]->evaluate(xContext, angleUnit); - float result = f->toFloat(); + Evaluation * f = m_args[0]->evaluate(xContext, angleUnit); + T result = f->toScalar(); delete f; return result; } #ifdef LAGRANGE_METHOD -float Integral::lagrangeGaussQuadrature(float a, float b, VariableContext xContext, AngleUnit angleUnit) const { +template +T Integral::lagrangeGaussQuadrature(T a, T b, VariableContext xContext, AngleUnit angleUnit) const { /* We here use Gauss-Legendre quadrature with n = 5 * Gauss-Legendre abscissae and weights taken from * http://www.holoborodko.com/pavel/numerical-methods/numerical-integration/*/ - const static float x[10]={0.0765265211334973337546404f, 0.2277858511416450780804962f, 0.3737060887154195606725482f, 0.5108670019508270980043641f, - 0.6360536807265150254528367f, 0.7463319064601507926143051f, 0.8391169718222188233945291f, 0.9122344282513259058677524f, - 0.9639719272779137912676661f, 0.9931285991850949247861224f}; - const static float w[10]={0.1527533871307258506980843f, 0.1491729864726037467878287f, 0.1420961093183820513292983f, 0.1316886384491766268984945f, 0.1181945319615184173123774f, - 0.1019301198172404350367501f, 0.0832767415767047487247581f, 0.0626720483341090635695065f, 0.0406014298003869413310400f, 0.0176140071391521183118620f}; - float xm = 0.5f*(a+b); - float xr = 0.5f*(b-a); - float result = 0.0f; + const static T x[10]={0.0765265211334973337546404, 0.2277858511416450780804962, 0.3737060887154195606725482, 0.5108670019508270980043641, + 0.6360536807265150254528367, 0.7463319064601507926143051, 0.8391169718222188233945291, 0.9122344282513259058677524, + 0.9639719272779137912676661, 0.9931285991850949247861224}; + const static T w[10]={0.1527533871307258506980843, 0.1491729864726037467878287, 0.1420961093183820513292983, 0.1316886384491766268984945, 0.1181945319615184173123774, + 0.1019301198172404350367501, 0.0832767415767047487247581, 0.0626720483341090635695065, 0.0406014298003869413310400, 0.0176140071391521183118620}; + T xm = 0.5*(a+b); + T xr = 0.5*(b-a); + T result = 0; for (int j = 0; j < 10; j++) { - float dx = xr * x[j]; + T dx = xr * x[j]; result += w[j]*(functionValueAtAbscissa(xm+dx, xContext, angleUnit) + functionValueAtAbscissa(xm-dx, xContext, angleUnit)); } result *= xr; @@ -93,80 +96,84 @@ float Integral::lagrangeGaussQuadrature(float a, float b, VariableContext xConte #else -Integral::DetailedResult Integral::kronrodGaussQuadrature(float a, float b, VariableContext xContext, AngleUnit angleUnit) const { +template +Integral::DetailedResult Integral::kronrodGaussQuadrature(T a, T b, VariableContext xContext, AngleUnit angleUnit) const { + static T epsilon = sizeof(T) == sizeof(double) ? DBL_EPSILON : FLT_EPSILON; + static T max = sizeof(T) == sizeof(double) ? DBL_MAX : FLT_MAX; /* We here use Kronrod-Legendre quadrature with n = 21 * The abscissa and weights are taken from QUADPACK library. */ - const static float wg[5]= {0.066671344308688137593568809893332f, 0.149451349150580593145776339657697f, - 0.219086362515982043995534934228163f, 0.269266719309996355091226921569469f, 0.295524224714752870173892994651338f}; - const static float xgk[11]= {0.995657163025808080735527280689003f, 0.973906528517171720077964012084452f, - 0.930157491355708226001207180059508f, 0.865063366688984510732096688423493f, 0.780817726586416897063717578345042f, - 0.679409568299024406234327365114874f, 0.562757134668604683339000099272694f, 0.433395394129247190799265943165784f, - 0.294392862701460198131126603103866f, 0.148874338981631210884826001129720f, 0.000000000000000000000000000000000f}; - const static float wgk[11]= {0.011694638867371874278064396062192f, 0.032558162307964727478818972459390f, - 0.054755896574351996031381300244580f, 0.075039674810919952767043140916190f, 0.093125454583697605535065465083366f, - 0.109387158802297641899210590325805f, 0.123491976262065851077958109831074f, 0.134709217311473325928054001771707f, - 0.142775938577060080797094273138717f, 0.147739104901338491374841515972068f, 0.149445554002916905664936468389821f}; - float fv1[10]; - float fv2[10]; + const static T wg[5]= {0.066671344308688137593568809893332, 0.149451349150580593145776339657697, + 0.219086362515982043995534934228163, 0.269266719309996355091226921569469, 0.295524224714752870173892994651338}; + const static T xgk[11]= {0.995657163025808080735527280689003, 0.973906528517171720077964012084452, + 0.930157491355708226001207180059508, 0.865063366688984510732096688423493, 0.780817726586416897063717578345042, + 0.679409568299024406234327365114874, 0.562757134668604683339000099272694, 0.433395394129247190799265943165784, + 0.294392862701460198131126603103866, 0.148874338981631210884826001129720, 0.000000000000000000000000000000000}; + const static T wgk[11]= {0.011694638867371874278064396062192, 0.032558162307964727478818972459390, + 0.054755896574351996031381300244580, 0.075039674810919952767043140916190, 0.093125454583697605535065465083366, + 0.109387158802297641899210590325805, 0.123491976262065851077958109831074, 0.134709217311473325928054001771707, + 0.142775938577060080797094273138717, 0.147739104901338491374841515972068, 0.149445554002916905664936468389821}; + T fv1[10]; + T fv2[10]; - float centr = 0.5f*(a+b); - float hlgth = 0.5f*(b-a); - float dhlgth = std::fabs(hlgth); + T centr = 0.5*(a+b); + T hlgth = 0.5*(b-a); + T dhlgth = std::fabs(hlgth); - float resg =0.0f; - float fc = functionValueAtAbscissa(centr, xContext, angleUnit); - float resk = wgk[10]*fc; - float resabs = std::fabs(resk); + T resg = 0; + T fc = functionValueAtAbscissa(centr, xContext, angleUnit); + T resk = wgk[10]*fc; + T resabs = std::fabs(resk); for (int j = 0; j < 5; j++) { int jtw = 2*j+1; - float absc = hlgth*xgk[jtw]; - float fval1 = functionValueAtAbscissa(centr-absc, xContext, angleUnit); - float fval2 = functionValueAtAbscissa(centr+absc, xContext, angleUnit); + T absc = hlgth*xgk[jtw]; + T fval1 = functionValueAtAbscissa(centr-absc, xContext, angleUnit); + T fval2 = functionValueAtAbscissa(centr+absc, xContext, angleUnit); fv1[jtw] = fval1; fv2[jtw] = fval2; - float fsum = fval1+fval2; + T fsum = fval1+fval2; resg += wg[j]*fsum; resk += wgk[jtw]*fsum; resabs += wgk[jtw]*(std::fabs(fval1)+std::fabs(fval2)); } for (int j = 0; j < 5; j++) { int jtwm1 = 2*j; - float absc = hlgth*xgk[jtwm1]; - float fval1 = functionValueAtAbscissa(centr-absc, xContext, angleUnit); - float fval2 = functionValueAtAbscissa(centr+absc, xContext, angleUnit); + T absc = hlgth*xgk[jtwm1]; + T fval1 = functionValueAtAbscissa(centr-absc, xContext, angleUnit); + T fval2 = functionValueAtAbscissa(centr+absc, xContext, angleUnit); fv1[jtwm1] = fval1; fv2[jtwm1] = fval2; - float fsum = fval1+fval2; + T fsum = fval1+fval2; resk += wgk[jtwm1]*fsum; resabs += wgk[jtwm1]*(std::fabs(fval1)+std::fabs(fval2)); } - float reskh = resk*0.5f; - float resasc = wgk[10]*std::fabs(fc-reskh); + T reskh = resk*0.5; + T resasc = wgk[10]*std::fabs(fc-reskh); for (int j = 0; j < 10; j++) { resasc += wgk[j]*(std::fabs(fv1[j]-reskh)+std::fabs(fv2[j]-reskh)); } - float integral = resk*hlgth; + T integral = resk*hlgth; resabs = resabs*dhlgth; resasc = resasc*dhlgth; - float abserr = std::fabs((resk-resg)*hlgth); - if (resasc != 0.0f && abserr != 0.0f) { - abserr = 1.0f > std::pow(200.0f*abserr/resasc, 1.5f)? resasc*std::pow(200.0f*abserr/resasc, 1.5f) : resasc; + T abserr = std::fabs((resk-resg)*hlgth); + if (resasc != 0 && abserr != 0) { + abserr = 1 > std::pow((T)(200*abserr/resasc), (T)1.5)? resasc*std::pow((T)(200*abserr/resasc), (T)1.5) : resasc; } - if (resabs > FLT_MAX/(50.0f*FLT_EPSILON)) { - abserr = abserr > FLT_EPSILON*50.0f*resabs ? abserr : FLT_EPSILON*50.0f*resabs; + if (resabs > max/(50.0*epsilon)) { + abserr = abserr > epsilon*50*resabs ? abserr : epsilon*50*resabs; } - DetailedResult result; + DetailedResult result; result.integral = integral; result.absoluteError = abserr; return result; } -float Integral::adaptiveQuadrature(float a, float b, float eps, int numberOfIterations, VariableContext xContext, AngleUnit angleUnit) const { - DetailedResult quadKG = kronrodGaussQuadrature(a, b, xContext, angleUnit); - float result = quadKG.integral; +template +T Integral::adaptiveQuadrature(T a, T b, T eps, int numberOfIterations, VariableContext xContext, AngleUnit angleUnit) const { + DetailedResult quadKG = kronrodGaussQuadrature(a, b, xContext, angleUnit); + T result = quadKG.integral; if (numberOfIterations < k_maxNumberOfIterations && quadKG.absoluteError > eps) { - float m = (a+b)/2.0f; - result = adaptiveQuadrature(a, m, eps/2.0f, numberOfIterations+1, xContext, angleUnit) + adaptiveQuadrature(m, b, eps/2.0f, numberOfIterations+1, xContext, angleUnit); + T m = (a+b)/2; + result = adaptiveQuadrature(a, m, eps/2, numberOfIterations+1, xContext, angleUnit) + adaptiveQuadrature(m, b, eps/2, numberOfIterations+1, xContext, angleUnit); } if (quadKG.absoluteError > eps) { return NAN; diff --git a/poincare/src/least_common_multiple.cpp b/poincare/src/least_common_multiple.cpp index 68c1dbf3d..6f958abbd 100644 --- a/poincare/src/least_common_multiple.cpp +++ b/poincare/src/least_common_multiple.cpp @@ -25,15 +25,16 @@ Expression * LeastCommonMultiple::cloneWithDifferentOperands(Expression** newOpe return lcm; } -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(); +template +Evaluation * LeastCommonMultiple::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Evaluation * f1Input = m_args[0]->evaluate(context, angleUnit); + Evaluation * f2Input = m_args[1]->evaluate(context, angleUnit); + T f1 = f1Input->toScalar(); + T f2 = f2Input->toScalar(); delete f1Input; delete f2Input; if (isnan(f1) || isnan(f2) || f1 != (int)f1 || f2 != (int)f2 || f1 == 0.0f || f2 == 0.0f) { - return new Complex(Complex::Float(NAN)); + return new Complex(Complex::Float(NAN)); } int a = (int)f2; int b = (int)f1; @@ -48,7 +49,7 @@ Evaluation * LeastCommonMultiple::privateEvaluate(Context & context, AngleUnit a a = b; b = r; } - return new Complex(Complex::Float(std::round((float)(product/a)))); + return new Complex(Complex::Float(std::round((T)(product/a)))); } } diff --git a/poincare/src/logarithm.cpp b/poincare/src/logarithm.cpp index 8d69860b5..589681b91 100644 --- a/poincare/src/logarithm.cpp +++ b/poincare/src/logarithm.cpp @@ -41,26 +41,28 @@ Expression * Logarithm::cloneWithDifferentOperands(Expression** newOperands, return l; } -Complex Logarithm::computeComplex(const Complex c, AngleUnit angleUnit) const { - if (c.b() != 0.0f) { - return Complex::Float(NAN); +template +Complex Logarithm::templatedComputeComplex(const Complex c) const { + if (c.b() != 0) { + return Complex::Float(NAN); } - return Complex::Float(std::log10(c.a())); + return Complex::Float(std::log10(c.a())); } -Evaluation * Logarithm::privateEvaluate(Context & context, AngleUnit angleUnit) const { +template +Evaluation * Logarithm::templatedEvaluate(Context& context, AngleUnit angleUnit) const { if (m_numberOfArguments == 1) { - return Function::privateEvaluate(context, angleUnit); + return Function::templatedEvaluate(context, angleUnit); } - Evaluation * x = m_args[0]->evaluate(context, angleUnit); - Evaluation * n = m_args[1]->evaluate(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)); + return new Complex(Complex::Float(NAN)); } - Complex result = Fraction::compute(computeComplex(*(n->complexOperand(0)), angleUnit), computeComplex(*(x->complexOperand(0)), angleUnit)); + Complex result = Fraction::compute(templatedComputeComplex(*(n->complexOperand(0))), templatedComputeComplex(*(x->complexOperand(0)))); delete x; delete n; - return new Complex(result); + return new Complex(result); } ExpressionLayout * Logarithm::privateCreateLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { diff --git a/poincare/src/matrix_data.cpp b/poincare/src/matrix_data.cpp index a0de65b8c..2c9c2ecda 100644 --- a/poincare/src/matrix_data.cpp +++ b/poincare/src/matrix_data.cpp @@ -38,8 +38,8 @@ MatrixData::MatrixData(Expression ** newOperands, int numberOfOperands, int numb } } -Complex * MatrixData::defaultExpression() { - static Complex * defaultExpression = new Complex(Complex::Float(0.0f)); +Complex * MatrixData::defaultExpression() { + static Complex * defaultExpression = new Complex(Complex::Float(0.0)); return defaultExpression; } diff --git a/poincare/src/matrix_dimension.cpp b/poincare/src/matrix_dimension.cpp index d9d352726..6ac315e04 100644 --- a/poincare/src/matrix_dimension.cpp +++ b/poincare/src/matrix_dimension.cpp @@ -24,13 +24,14 @@ Expression * MatrixDimension::cloneWithDifferentOperands(Expression** newOperand return md; } -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()); +template +Evaluation * MatrixDimension::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Evaluation * input = m_args[0]->evaluate(context, angleUnit); + Complex operands[2]; + operands[0] = Complex::Float((T)input->numberOfRows()); + operands[1] = Complex::Float((T)input->numberOfColumns()); delete input; - return new ComplexMatrix(operands, 2, 1); + return new ComplexMatrix(operands, 2, 1); } } diff --git a/poincare/src/matrix_inverse.cpp b/poincare/src/matrix_inverse.cpp index 957d2805e..a5edefaa5 100644 --- a/poincare/src/matrix_inverse.cpp +++ b/poincare/src/matrix_inverse.cpp @@ -26,9 +26,10 @@ Expression * MatrixInverse::cloneWithDifferentOperands(Expression** newOperands, return i; } -Evaluation * MatrixInverse::privateEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * input = m_args[0]->evaluate(context, angleUnit); - Evaluation * result = input->createInverse(); +template +Evaluation * MatrixInverse::templatedEvaluate(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 7d2104667..48c6780eb 100644 --- a/poincare/src/matrix_trace.cpp +++ b/poincare/src/matrix_trace.cpp @@ -24,9 +24,10 @@ Expression * MatrixTrace::cloneWithDifferentOperands(Expression** newOperands, return t; } -Evaluation * MatrixTrace::privateEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * input = m_args[0]->evaluate(context, angleUnit); - Evaluation * result = input->createTrace(); +template +Evaluation * MatrixTrace::templatedEvaluate(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 8b8637ae3..4b02d701d 100644 --- a/poincare/src/matrix_transpose.cpp +++ b/poincare/src/matrix_transpose.cpp @@ -26,9 +26,10 @@ Expression * MatrixTranspose::cloneWithDifferentOperands(Expression** newOperand return t; } -Evaluation * MatrixTranspose::privateEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * input = m_args[0]->evaluate(context, angleUnit); - Evaluation * result = input->createTranspose(); +template +Evaluation * MatrixTranspose::templatedEvaluate(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 5364c6317..3e696525c 100644 --- a/poincare/src/multiplication.cpp +++ b/poincare/src/multiplication.cpp @@ -32,36 +32,43 @@ Expression * Multiplication::cloneWithDifferentOperands(Expression** newOperands return new Multiplication(newOperands, cloneOperands); } -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()); +template +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()); } -Evaluation * Multiplication::computeOnComplexAndMatrix(const Complex * c, Evaluation * m) { +template +Evaluation * Multiplication::computeOnComplexAndMatrix(const Complex * c, Evaluation * m) { Multiplication mul; return mul.computeOnComplexAndComplexMatrix(c, m); } -Evaluation * Multiplication::computeOnMatrices(Evaluation * m, Evaluation * n) { +template +Evaluation * Multiplication::computeOnMatrices(Evaluation * m, Evaluation * n) { if (m->numberOfColumns() != n->numberOfRows()) { - return new Complex(Complex::Float(NAN)); + return new Complex(Complex::Float(NAN)); } - Complex * operands = new Complex[m->numberOfRows()*n->numberOfColumns()]; + 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; + T a = 0.0f; + T b = 0.0f; for (int k = 0; k < m->numberOfColumns(); k++) { - Complex mEntry = *(m->complexOperand(i*m->numberOfColumns()+k)); - Complex nEntry = *(n->complexOperand(k*n->numberOfColumns()+j)); + 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] = Complex::Cartesian(a, b); + operands[i*n->numberOfColumns()+j] = Complex::Cartesian(a, b); } } - Evaluation * result = new ComplexMatrix(operands, n->numberOfColumns(), m->numberOfRows()); + Evaluation * result = new ComplexMatrix(operands, n->numberOfColumns(), m->numberOfRows()); delete[] operands; return result; } +template Poincare::Evaluation* Poincare::Multiplication::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); +template Poincare::Evaluation* Poincare::Multiplication::computeOnComplexAndMatrix(Poincare::Complex const*, Poincare::Evaluation*); } +template Poincare::Complex Poincare::Multiplication::compute(Poincare::Complex, Poincare::Complex); +template Poincare::Complex Poincare::Multiplication::compute(Poincare::Complex, Poincare::Complex); diff --git a/poincare/src/naperian_logarithm.cpp b/poincare/src/naperian_logarithm.cpp index 4e727df0f..7df7fa038 100644 --- a/poincare/src/naperian_logarithm.cpp +++ b/poincare/src/naperian_logarithm.cpp @@ -27,11 +27,12 @@ Expression * NaperianLogarithm::cloneWithDifferentOperands(Expression** newOpera return l; } -Complex NaperianLogarithm::computeComplex(const Complex c, AngleUnit angleUnit) const { - if (c.b() != 0.0f) { - return Complex::Float(NAN); +template +Complex NaperianLogarithm::templatedComputeComplex(const Complex c) const { + if (c.b() != 0) { + return Complex::Float(NAN); } - return Complex::Float(std::log(c.a())); + return Complex::Float(std::log(c.a())); } } diff --git a/poincare/src/nth_root.cpp b/poincare/src/nth_root.cpp index deb7d1e7a..7b8087f09 100644 --- a/poincare/src/nth_root.cpp +++ b/poincare/src/nth_root.cpp @@ -34,23 +34,25 @@ ExpressionLayout * NthRoot::privateCreateLayout(FloatDisplayMode floatDisplayMod return new NthRootLayout(m_args[0]->createLayout(floatDisplayMode, complexFormat), m_args[1]->createLayout(floatDisplayMode, complexFormat)); } -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); +template +Evaluation * NthRoot::templatedEvaluate(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))); } delete base; delete index; - return new Complex(result); + 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(std::pow(c.a(), 1.0f/d.a())); +template +Complex NthRoot::compute(const Complex c, const Complex d) const { + if (c.b() == 0 && d.b() == 0) { + return Complex::Float(std::pow(c.a(), 1/d.a())); } - Complex invIndex = Fraction::compute(Complex::Float(1.0f), d); + Complex invIndex = Fraction::compute(Complex::Float(1), d); return Power::compute(c, invIndex); } diff --git a/poincare/src/opposite.cpp b/poincare/src/opposite.cpp index 30a7fd4a6..031032136 100644 --- a/poincare/src/opposite.cpp +++ b/poincare/src/opposite.cpp @@ -42,25 +42,28 @@ Expression * Opposite::clone() const { return this->cloneWithDifferentOperands((Expression**)&m_operand, 1, true); } -Complex Opposite::compute(const Complex c) { - return Complex::Cartesian(-c.a(), -c.b()); +template +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()]; +template +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()); + Complex entry = *(m->complexOperand(i)); + operands[i] = Complex::Cartesian(-entry.a(), -entry.b()); } - Evaluation * matrix = new ComplexMatrix(operands, m->numberOfColumns(), m->numberOfRows()); + 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); +template +Evaluation * Opposite::templatedEvaluate(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 new Complex(compute(*(operandEvalutation->complexOperand(0)))); } return computeOnMatrix(operandEvalutation); } @@ -87,3 +90,6 @@ Expression * Opposite::cloneWithDifferentOperands(Expression** newOperands, } } + +template Poincare::Complex Poincare::Opposite::compute(Poincare::Complex); +template Poincare::Complex Poincare::Opposite::compute(Poincare::Complex); diff --git a/poincare/src/parenthesis.cpp b/poincare/src/parenthesis.cpp index 57bf157e2..eab6bcfcb 100644 --- a/poincare/src/parenthesis.cpp +++ b/poincare/src/parenthesis.cpp @@ -43,8 +43,9 @@ ExpressionLayout * Parenthesis::privateCreateLayout(FloatDisplayMode floatDispla return new ParenthesisLayout(m_operand->createLayout(floatDisplayMode, complexFormat)); } -Evaluation * Parenthesis::privateEvaluate(Context& context, AngleUnit angleUnit) const { - return m_operand->evaluate(context, angleUnit); +template +Evaluation * Parenthesis::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + return m_operand->evaluate(context, angleUnit); } Expression::Type Parenthesis::type() const { diff --git a/poincare/src/permute_coefficient.cpp b/poincare/src/permute_coefficient.cpp index afbb5362f..cfee87119 100644 --- a/poincare/src/permute_coefficient.cpp +++ b/poincare/src/permute_coefficient.cpp @@ -25,25 +25,26 @@ Expression * PermuteCoefficient::cloneWithDifferentOperands(Expression** newOper return pc; } -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(); +template +Evaluation * PermuteCoefficient::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Evaluation * nInput = m_args[0]->evaluate(context, angleUnit); + Evaluation * kInput = m_args[1]->evaluate(context, angleUnit); + T n = nInput->toScalar(); + T k = kInput->toScalar(); delete nInput; delete kInput; if (isnan(n) || isnan(k) || n != (int)n || k != (int)k || n < 0.0f || k < 0.0f) { - return new Complex(Complex::Float(NAN)); + return new Complex(Complex::Float(NAN)); } if (k > n) { - return new Complex(Complex::Float(0.0f)); + return new Complex(Complex::Float(0)); } - float result = 1.0f; + T result = 1; for (int i = (int)n-(int)k+1; i <= (int)n; i++) { result *= i; } - return new Complex(Complex::Float(std::round(result))); + return new Complex(Complex::Float(std::round(result))); } } diff --git a/poincare/src/power.cpp b/poincare/src/power.cpp index 22052941a..334c8b21c 100644 --- a/poincare/src/power.cpp +++ b/poincare/src/power.cpp @@ -31,69 +31,72 @@ ExpressionLayout * Power::privateCreateLayout(FloatDisplayMode floatDisplayMode, return new BaselineRelativeLayout(m_operands[0]->createLayout(floatDisplayMode, complexFormat),indiceOperand->createLayout(floatDisplayMode, complexFormat), BaselineRelativeLayout::Type::Superscript); } -Complex Power::compute(const Complex c, const Complex d) { - if (d.b() != 0.0f) { +template +Complex Power::compute(const Complex c, const Complex d) { + if (d.b() != 0) { /* First case c and d is complex */ - if (c.b() != 0.0f || c.a() <= 0) { - return Complex::Float(NAN); + if (c.b() != 0 || c.a() <= 0) { + return Complex::Float(NAN); } /* Second case only d is complex */ - float radius = std::pow(c.a(), d.a()); - float theta = d.b()*std::log(c.a()); - return Complex::Polar(radius, theta); + T radius = std::pow(c.a(), d.a()); + T theta = d.b()*std::log(c.a()); + return Complex::Polar(radius, theta); } /* Third case only c is complex */ - float radius = std::pow(c.r(), d.a()); + T radius = std::pow(c.r(), d.a()); + // TODO: is it still needed with double? if (c.b() == 0 && d.a() == std::round(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 Complex::Cartesian(radius, 0.0f); + return Complex::Cartesian(radius, 0); } - if (c.a() < 0 && c.b() == 0 && d.a() == 0.5f) { + if (c.a() < 0 && c.b() == 0 && d.a() == 0.5) { /* 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 Complex::Cartesian(0.0f, radius); + return Complex::Cartesian(0, radius); } /* Third case only c is complex */ - float theta = d.a()*c.th(); - return Complex::Polar(radius, theta); + T theta = d.a()*c.th(); + return Complex::Polar(radius, theta); } -Evaluation * Power::computeOnComplexMatrixAndComplex(Evaluation * m, const Complex * c) const { +template Evaluation * Power::templatedComputeOnComplexMatrixAndComplex(Evaluation * m, const Complex * d) const { if (m->numberOfColumns() != m->numberOfRows()) { - return new Complex(Complex::Float(NAN)); + return new Complex(Complex::Float(NAN)); } - float power = c->toFloat(); + T power = d->toScalar(); if (isnan(power) || isinf(power) || power != (int)power || std::fabs(power) > k_maxNumberOfSteps) { - return new Complex(Complex::Float(NAN)); + return new Complex(Complex::Float(NAN)); } - if (power < 0.0f) { - Evaluation * inverse = m->createInverse(); - Complex minusC = Opposite::compute(*c); - Evaluation * result = Power::computeOnComplexMatrixAndComplex(inverse, &minusC); + if (power < 0) { + Evaluation * inverse = m->createInverse(); + Complex minusC = Opposite::compute(*d); + Evaluation * result = Power::computeOnComplexMatrixAndComplex(inverse, &minusC); delete inverse; return result; } - Evaluation * result = ComplexMatrix::createIdentity(m->numberOfRows()); + 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)); + return new Complex(Complex::Float(NAN)); } result = Multiplication::computeOnMatrices(result, m); } return result; } -Evaluation * Power::computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * m) const { - return new Complex(Complex::Float(NAN)); +template Evaluation * Power::templatedComputeOnComplexAndComplexMatrix(const Complex * c, Evaluation * n) const { + return new Complex(Complex::Float(NAN)); } -Evaluation * Power::computeOnNumericalMatrices(Evaluation * m, Evaluation * n) const { - return new Complex(Complex::Float(NAN)); +template Evaluation * Power::templatedComputeOnComplexMatrices(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 6d6154b09..702f134f6 100644 --- a/poincare/src/prediction_interval.cpp +++ b/poincare/src/prediction_interval.cpp @@ -24,20 +24,21 @@ Expression * PredictionInterval::cloneWithDifferentOperands(Expression** newOper return pi; } -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(); +template +Evaluation * PredictionInterval::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Evaluation * pInput = m_args[0]->evaluate(context, angleUnit); + Evaluation * nInput = m_args[1]->evaluate(context, angleUnit); + T p = pInput->toScalar(); + T n = nInput->toScalar(); 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)); + if (isnan(p) || isnan(n) || n != (int)n || n < 0 || p < 0 || p > 1) { + return new Complex(Complex::Float(NAN)); } - Complex operands[2]; - operands[0] = Complex::Float(p - 1.96f*std::sqrt(p*(1.0f-p))/std::sqrt(n)); - operands[1] = Complex::Float(p + 1.96f*std::sqrt(p*(1.0f-p))/std::sqrt(n)); - return new ComplexMatrix(operands, 2, 1); + Complex operands[2]; + operands[0] = Complex::Float(p - 1.96*std::sqrt(p*(1.0-p))/std::sqrt(n)); + operands[1] = Complex::Float(p + 1.96*std::sqrt(p*(1.0-p))/std::sqrt(n)); + return new ComplexMatrix(operands, 2, 1); } } diff --git a/poincare/src/product.cpp b/poincare/src/product.cpp index 8734f51c0..bed5c923b 100644 --- a/poincare/src/product.cpp +++ b/poincare/src/product.cpp @@ -26,17 +26,18 @@ Expression * Product::cloneWithDifferentOperands(Expression** newOperands, return p; } -float Product::emptySequenceValue() const { - return 1.0f; +int Product::emptySequenceValue() const { + return 1; } ExpressionLayout * Product::createSequenceLayoutWithArgumentLayouts(ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout, ExpressionLayout * argumentLayout) const { return new ProductLayout(subscriptLayout, superscriptLayout, argumentLayout); } -Evaluation * Product::evaluateWithNextTerm(Evaluation * a, Evaluation * b) const { +template +Evaluation * Product::templatedEvaluateWithNextTerm(Evaluation * a, Evaluation * b) const { if (a->numberOfOperands() == 1 && b->numberOfOperands() == 1) { - return new Complex(Multiplication::compute(*(a->complexOperand(0)), *(b->complexOperand(0)))); + return new Complex(Multiplication::compute(*(a->complexOperand(0)), *(b->complexOperand(0)))); } if (a->numberOfOperands() == 1) { return Multiplication::computeOnComplexAndMatrix(a->complexOperand(0), b); diff --git a/poincare/src/reel_part.cpp b/poincare/src/reel_part.cpp index 0784ed134..93ff40a1f 100644 --- a/poincare/src/reel_part.cpp +++ b/poincare/src/reel_part.cpp @@ -25,8 +25,9 @@ Expression * ReelPart::cloneWithDifferentOperands(Expression** newOperands, return rp; } -Complex ReelPart::computeComplex(const Complex c, AngleUnit angleUnit) const { - return Complex::Float(c.a()); +template +Complex ReelPart::templatedComputeComplex(const Complex c) const { + return Complex::Float(c.a()); } } diff --git a/poincare/src/round.cpp b/poincare/src/round.cpp index bc4299fe6..8b7caddf9 100644 --- a/poincare/src/round.cpp +++ b/poincare/src/round.cpp @@ -24,18 +24,19 @@ Expression * Round::cloneWithDifferentOperands(Expression** newOperands, return r; } -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(); +template +Evaluation * Round::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Evaluation * f1Entry = m_args[0]->evaluate(context, angleUnit); + Evaluation * f2Entry = m_args[1]->evaluate(context, angleUnit); + T f1 = f1Entry->toScalar(); + T f2 = f2Entry->toScalar(); delete f1Entry; delete f2Entry; if (isnan(f2) || f2 != (int)f2) { - return new Complex(Complex::Float(NAN)); + return new Complex(Complex::Float(NAN)); } - float err = std::pow(10.0f, (int)f2); - return new Complex(Complex::Float(std::round(f1*err)/err)); + T err = std::pow(10, std::floor(f2)); + return new Complex(Complex::Float(std::round(f1*err)/err)); } } diff --git a/poincare/src/sequence.cpp b/poincare/src/sequence.cpp index e566c4492..d38ed26c7 100644 --- a/poincare/src/sequence.cpp +++ b/poincare/src/sequence.cpp @@ -26,28 +26,29 @@ ExpressionLayout * Sequence::privateCreateLayout(FloatDisplayMode floatDisplayMo return createSequenceLayoutWithArgumentLayouts(new HorizontalLayout(childrenLayouts, 2), m_args[2]->createLayout(floatDisplayMode, complexFormat), m_args[0]->createLayout(floatDisplayMode, complexFormat)); } -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(); +template +Evaluation * Sequence::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + Evaluation * aInput = m_args[1]->evaluate(context, angleUnit); + Evaluation * bInput = m_args[2]->evaluate(context, angleUnit); + T start = aInput->toScalar(); + T end = bInput->toScalar(); 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)); + return new Complex(Complex::Float(NAN)); } - VariableContext nContext = VariableContext('n', &context); + VariableContext nContext = VariableContext('n', &context); Symbol nSymbol = Symbol('n'); - Evaluation * 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)); + return new Complex(Complex::Float(NAN)); } - Complex iExpression = Complex::Float(i); + Complex iExpression = Complex::Float(i); nContext.setExpressionForSymbolName(&iExpression, &nSymbol); - Evaluation * expression = m_args[0]->evaluate(nContext, angleUnit); - Evaluation * newResult = evaluateWithNextTerm(result, expression); + Evaluation * expression = m_args[0]->evaluate(nContext, angleUnit); + Evaluation * newResult = evaluateWithNextTerm(result, expression); delete result; delete expression; result = newResult; diff --git a/poincare/src/sine.cpp b/poincare/src/sine.cpp index ffa2a5536..b222021e2 100644 --- a/poincare/src/sine.cpp +++ b/poincare/src/sine.cpp @@ -10,7 +10,7 @@ extern "C" { namespace Poincare { Sine::Sine() : - TrigonometricFunction("sin") + Function("sin") { } @@ -26,14 +26,23 @@ Expression * Sine::cloneWithDifferentOperands(Expression** newOperands, return s; } -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 std::sin(x); +template +Complex Sine::compute(const Complex c, AngleUnit angleUnit) { + if (c.b() == 0) { + T input = c.a(); + if (angleUnit == AngleUnit::Degree) { + input *= M_PI/180; + } + T result = std::sin(input); + // TODO: See if necessary with double???? + if (input != 0 && std::fabs(result/input) <= 1E-7f) { + return Complex::Float(0); + } + return Complex::Float(result); + } + Complex arg = Complex::Cartesian(-c.b(), c.a()); + Complex sinh = HyperbolicSine::compute(arg); + return Multiplication::compute(Complex::Cartesian(0, -1), sinh); } } diff --git a/poincare/src/square_root.cpp b/poincare/src/square_root.cpp index c1e0f63a7..5be0a7da7 100644 --- a/poincare/src/square_root.cpp +++ b/poincare/src/square_root.cpp @@ -32,11 +32,12 @@ ExpressionLayout * SquareRoot::privateCreateLayout(FloatDisplayMode floatDisplay return new NthRootLayout(m_args[0]->createLayout(floatDisplayMode, complexFormat),nullptr); } -Complex SquareRoot::computeComplex(const Complex c, AngleUnit angleUnit) const { - if (c.b() == 0.0f) { - return Complex::Float(std::sqrt(c.a())); +template +Complex SquareRoot::templatedComputeComplex(const Complex c) const { + if (c.b() == 0) { + return Complex::Float(std::sqrt(c.a())); } - return Power::compute(c, Complex::Float(0.5f)); + return Power::compute(c, Complex::Float(0.5)); } } diff --git a/poincare/src/store.cpp b/poincare/src/store.cpp index 9ce30acfe..84b7aefa8 100644 --- a/poincare/src/store.cpp +++ b/poincare/src/store.cpp @@ -73,14 +73,13 @@ ExpressionLayout * Store::privateCreateLayout(FloatDisplayMode floatDisplayMode, } -Evaluation * Store::privateEvaluate(Context& context, AngleUnit angleUnit) const { - Evaluation * valueEvaluation = m_value->evaluate(context, angleUnit); - context.setExpressionForSymbolName(valueEvaluation, m_symbol); - delete valueEvaluation; +template +Evaluation * Store::templatedEvaluate(Context& context, AngleUnit angleUnit) const { + context.setExpressionForSymbolName(m_value, m_symbol); if (context.expressionForSymbol(m_symbol) != nullptr) { - return context.expressionForSymbol(m_symbol)->clone(); + return context.expressionForSymbol(m_symbol)->evaluate(context, angleUnit); } - return new Complex(Complex::Float(NAN)); + return new Complex(Complex::Float(NAN)); } } diff --git a/poincare/src/subtraction.cpp b/poincare/src/subtraction.cpp index c54a196b1..4cbe68cd8 100644 --- a/poincare/src/subtraction.cpp +++ b/poincare/src/subtraction.cpp @@ -33,15 +33,19 @@ ExpressionLayout * Subtraction::privateCreateLayout(FloatDisplayMode floatDispla return new HorizontalLayout(children_layouts, 3); } -Complex Subtraction::compute(const Complex c, const Complex d) { - return Complex::Cartesian(c.a()-d.a(), c.b() - d.b()); +template +Complex Subtraction::compute(const Complex c, const Complex d) { + return Complex::Cartesian(c.a()-d.a(), c.b() - d.b()); } -Evaluation * Subtraction::computeOnComplexAndComplexMatrix(const Complex * c, Evaluation * m) const { - Evaluation * operand = computeOnComplexMatrixAndComplex(m, c); - Evaluation * result = Opposite::computeOnMatrix(operand); +template Evaluation * Subtraction::templatedComputeOnComplexAndComplexMatrix(const Complex * c, Evaluation * m) const { + Evaluation * operand = computeOnComplexMatrixAndComplex(m, c); + Evaluation * result = Opposite::computeOnMatrix(operand); delete operand; return result; } } + +template Poincare::Complex Poincare::Subtraction::compute(Poincare::Complex, Poincare::Complex); +template Poincare::Complex Poincare::Subtraction::compute(Poincare::Complex, Poincare::Complex); diff --git a/poincare/src/sum.cpp b/poincare/src/sum.cpp index 221bcd19c..87b432fc1 100644 --- a/poincare/src/sum.cpp +++ b/poincare/src/sum.cpp @@ -26,17 +26,18 @@ Expression * Sum::cloneWithDifferentOperands(Expression** newOperands, return s; } -float Sum::emptySequenceValue() const { - return 0.0f; +int Sum::emptySequenceValue() const { + return 0; } ExpressionLayout * Sum::createSequenceLayoutWithArgumentLayouts(ExpressionLayout * subscriptLayout, ExpressionLayout * superscriptLayout, ExpressionLayout * argumentLayout) const { return new SumLayout(subscriptLayout, superscriptLayout, argumentLayout); } -Evaluation * Sum::evaluateWithNextTerm(Evaluation * a, Evaluation * b) const { +template +Evaluation * Sum::templatedEvaluateWithNextTerm(Evaluation * a, Evaluation * b) const { if (a->numberOfOperands() == 1 && b->numberOfOperands() == 1) { - return new Complex(Addition::compute(*(a->complexOperand(0)), *(b->complexOperand(0)))); + return new Complex(Addition::compute(*(a->complexOperand(0)), *(b->complexOperand(0)))); } if (a->numberOfOperands() == 1) { return Addition::computeOnComplexAndMatrix(a->complexOperand(0), b); diff --git a/poincare/src/symbol.cpp b/poincare/src/symbol.cpp index 295325d59..f9a96d75d 100644 --- a/poincare/src/symbol.cpp +++ b/poincare/src/symbol.cpp @@ -44,11 +44,12 @@ Symbol::Symbol(char name) : { } -Evaluation * Symbol::privateEvaluate(Context& context, AngleUnit angleUnit) const { +template +Evaluation * Symbol::templatedEvaluate(Context& context, AngleUnit angleUnit) const { if (context.expressionForSymbol(this) != nullptr) { - return context.expressionForSymbol(this)->clone(); + return context.expressionForSymbol(this)->evaluate(context, angleUnit); } - return new Complex(Complex::Float(NAN)); + return new Complex(Complex::Float(NAN)); } Expression::Type Symbol::type() const { diff --git a/poincare/src/tangent.cpp b/poincare/src/tangent.cpp index 45e379203..8e2932ab7 100644 --- a/poincare/src/tangent.cpp +++ b/poincare/src/tangent.cpp @@ -13,7 +13,7 @@ extern "C" { namespace Poincare { Tangent::Tangent() : - TrigonometricFunction("tan") + Function("tan") { } @@ -29,17 +29,14 @@ Expression::Type Tangent::type() const { return Expression::Type::Tangent; } -float Tangent::computeForRadianReal(float x) const { - return std::tan(x); -} - -Complex Tangent::privateCompute(const Complex c, AngleUnit angleUnit) const { - Complex result = Fraction::compute(Sine::compute(c), Cosine::compute(c)); +template +Complex Tangent::templatedComputeComplex(const Complex c, AngleUnit angleUnit) const { + Complex result = Fraction::compute(Sine::compute(c, angleUnit), Cosine::compute(c, angleUnit)); if (!isnan(result.a()) && !isnan(result.b())) { return result; } - Complex tanh = HyperbolicTangent::compute(Multiplication::compute(Complex::Cartesian(0.0f, -1.0f), c)); - return Multiplication::compute(Complex::Cartesian(0.0f, 1.0f), tanh); + Complex tanh = HyperbolicTangent::compute(Multiplication::compute(Complex::Cartesian(0, -1), c)); + return Multiplication::compute(Complex::Cartesian(0, 1), tanh); } } diff --git a/poincare/src/trigonometric_function.cpp b/poincare/src/trigonometric_function.cpp deleted file mode 100644 index c0960639e..000000000 --- a/poincare/src/trigonometric_function.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include -extern "C" { -#include -} -#include - -namespace Poincare { - -TrigonometricFunction::TrigonometricFunction(const char * name) : - Function(name) -{ -} - -Complex TrigonometricFunction::computeComplex(const Complex c, AngleUnit angleUnit) const { - assert(angleUnit != AngleUnit::Default); - 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 && std::fabs(result/input) <= 1E-7f) { - return Complex::Float(0.0f); - } - return Complex::Float(result); - } - return privateCompute(c, angleUnit); -} - -} diff --git a/poincare/src/variable_context.cpp b/poincare/src/variable_context.cpp index ffd35b68b..7b9096054 100644 --- a/poincare/src/variable_context.cpp +++ b/poincare/src/variable_context.cpp @@ -7,24 +7,31 @@ extern "C" { namespace Poincare { -VariableContext::VariableContext(char name, Context * parentContext) : +template +VariableContext::VariableContext(char name, Context * parentContext) : m_name(name), - m_value(Complex::Float(NAN)), + m_value(Complex::Float(NAN)), m_parentContext(parentContext) { } -void VariableContext::setExpressionForSymbolName(Evaluation * expression, const Symbol * symbol) { +template +void VariableContext::setExpressionForSymbolName(Expression * expression, const Symbol * symbol) { if (symbol->name() == m_name) { - assert(expression->numberOfOperands() == 1); + if (expression == nullptr) { + return; + } + Evaluation * evaluation = expression->evaluate(*m_parentContext); /* WARNING: We assume that the evaluation of expression is a real */ - m_value = Complex::Float(expression->toFloat()); + m_value = Complex::Float(evaluation->toScalar()); + delete evaluation; } else { m_parentContext->setExpressionForSymbolName(expression, symbol); } } -const Evaluation * VariableContext::expressionForSymbol(const Symbol * symbol) { +template +const Expression * VariableContext::expressionForSymbol(const Symbol * symbol) { if (symbol->name() == m_name) { return &m_value; } else { @@ -32,4 +39,7 @@ const Evaluation * VariableContext::expressionForSymbol(const Symbol * symbol) { } } +template class Poincare::VariableContext; +template class Poincare::VariableContext; + } diff --git a/poincare/test/addition.cpp b/poincare/test/addition.cpp index 5d58dbca5..563f7da85 100644 --- a/poincare/test/addition.cpp +++ b/poincare/test/addition.cpp @@ -7,27 +7,27 @@ using namespace Poincare; QUIZ_CASE(poincare_addition_evaluate) { - Complex a[1] = {Complex::Float(3.0f)}; + Complex a[1] = {Complex::Float(3.0f)}; assert_parsed_expression_evaluate_to("1+2", a, 1); - Complex b[1] = {Complex::Cartesian(6.0f, 2.0f)}; + Complex b[1] = {Complex::Cartesian(6.0, 2.0)}; assert_parsed_expression_evaluate_to("2+I+4+I", b, 1); #if MATRICES_ARE_DEFINED - 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)}; + 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); - 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)}; + Complex d[6] = {Complex::Cartesian(4.0, 1.0), Complex::Cartesian(5.0, 2.0), Complex::Cartesian(6.0, 1.0), Complex::Cartesian(7.0, 1.0), Complex::Cartesian(8.0, 1.0), Complex::Cartesian(9.0, 1.0)}; assert_parsed_expression_evaluate_to("[[1,2+I][3,4][5,6]]+3+I", d, 6); assert_parsed_expression_evaluate_to("3+[[1,2][3,4][5,6]]", c, 6); assert_parsed_expression_evaluate_to("3+I+[[1,2+I][3,4][5,6]]", d, 6); - 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)}; + 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); - 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)}; + Complex f[6] = {Complex::Cartesian(2.0, 0.0), Complex::Cartesian(4.0, 2.0), Complex::Cartesian(6.0, 0.0), Complex::Cartesian(8.0, 0.0), Complex::Cartesian(10.0, 0.0), Complex::Cartesian(12.0, 0.0)}; 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 36c750590..c55ed67f3 100644 --- a/poincare/test/complex.cpp +++ b/poincare/test/complex.cpp @@ -12,19 +12,20 @@ constexpr Expression::FloatDisplayMode Scientific = Expression::FloatDisplayMode constexpr Expression::ComplexFormat Cartesian = Expression::ComplexFormat::Cartesian; 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) { +template +void assert_cartesian_complex_converts_to(T a, T 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 = new char[bufferSize+2*tagSize]; memset(taggedBuffer, tag, bufferSize+2*tagSize); char * buffer = taggedBuffer + tagSize; - if (b == 0.0f) { - Complex::convertFloatToText(a, buffer, bufferSize, significantDigits, mode); + if (b == 0) { + Complex::convertFloatToText(a, buffer, bufferSize, significantDigits, mode); } else { Preferences::sharedPreferences()->setComplexFormat(format); Preferences::sharedPreferences()->setDisplayMode(mode); - Complex::Cartesian(a, b).writeTextInBuffer(buffer, bufferSize); + Complex::Cartesian(a, b).writeTextInBuffer(buffer, bufferSize); } for (int i=0; ievaluate(globalContext); - assert(m->complexOperand(0)->a() == 123.456f); - assert(m->complexOperand(0)->b() == 0.0f); + Expression * a = new Complex(Complex::Float(123.456f)); + Evaluation * m = a->evaluate(globalContext); + assert(std::fabs(m->complexOperand(0)->a() - 123.456) < 0.00001); + assert(m->complexOperand(0)->b() == 0.0); assert(m->numberOfOperands() == 1); + delete m; + + Evaluation * n = a->evaluate(globalContext); + assert(n->complexOperand(0)->a() == 123.456f); + assert(n->complexOperand(0)->b() == 0.0f); + assert(n->numberOfOperands() == 1); + delete n; delete a; - delete m; } QUIZ_CASE(poincare_complex_constructor) { - Complex * a = new Complex(Complex::Cartesian(2.0f, 3.0f)); + Complex * a = new Complex(Complex::Cartesian(2.0f, 3.0f)); assert(std::fabs(a->a() - 2.0f) < 0.00001f && std::fabs(a->b()-3.0f) < 0.00001f); assert(a->r() == 3.60555124f && a->th() == 0.982793748f); delete a; - a = new Complex(Complex::Polar(3.60555124f, 0.982793748f)); + a = new Complex(Complex::Polar(3.60555124f, 0.982793748f)); assert(std::fabs(a->a() - 2.0f) < 0.00001f && std::fabs(a->b()-3.0f) < 0.00001f); delete a; + + Complex * b = new Complex(Complex::Cartesian(1.0, 12.0)); + assert(std::fabs(b->a() - 1.0) < 0.0000000001 && std::fabs(b->b()-12.0) < 0.0000000001); + delete b; + + b = new Complex(Complex::Polar(12.04159457879229548012824103, 1.4876550949)); + assert(std::fabs(b->a() - 1.0) < 0.0000000001 && std::fabs(b->b()-12.0) < 0.0000000001); + delete b; } diff --git a/poincare/test/fraction.cpp b/poincare/test/fraction.cpp index 3aac15e37..7733732a0 100644 --- a/poincare/test/fraction.cpp +++ b/poincare/test/fraction.cpp @@ -8,27 +8,27 @@ using namespace Poincare; QUIZ_CASE(poincare_fraction_evaluate) { - Complex a[1] = {Complex::Float(0.5f)}; + Complex a[1] = {Complex::Float(0.5f)}; assert_parsed_expression_evaluate_to("1/2", a, 1); - Complex b[1] = {Complex::Cartesian(13.0f/17.0f, 1.0f/17.0f)}; + Complex b[1] = {Complex::Cartesian(13.0/17.0, 1.0/17.0)}; assert_parsed_expression_evaluate_to("(3+I)/(4+I)", b, 1); #if MATRICES_ARE_DEFINED - 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)}; + 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); - 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)}; + Complex d[6] = {Complex::Cartesian(4.0/17.0, -1.0/17.0), Complex::Cartesian(9.0/17.0, 2.0/17.0), Complex::Cartesian(12.0/17.0, -3.0/17.0), Complex::Cartesian(16.0/17.0, -4.0/17.0), Complex::Cartesian(20.0/17.0, -5.0/17.0), Complex::Cartesian(24.0/17.0, -6.0/17.0)}; 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)}; + 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)}; + Complex f[4] = {Complex::Float(-9.0), Complex::Float(6.0), Complex::Float(15.0/2.0), Complex::Float(-9.0/2.0)}; 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)}; + /* Complex g[4] = {Complex::Cartesian(-9.0, -12.0), Complex::Cartesian(6.0, 8.0), Complex::Cartesian(15.0/2.0, 10.0), Complex::Cartesian(-9.0/2.0, -6.0)}; assert_parsed_expression_evaluate_to("(3+4i)/[[1,2+i][3,4][5,6]]", g, 4);*/ #endif diff --git a/poincare/test/function.cpp b/poincare/test/function.cpp index b1507a040..3846fb7a1 100644 --- a/poincare/test/function.cpp +++ b/poincare/test/function.cpp @@ -145,123 +145,123 @@ QUIZ_CASE(poincare_parse_function) { QUIZ_CASE(poincare_function_evaluate) { - Complex a0[1] = {Complex::Float(1.0f)}; + Complex a0[1] = {Complex::Float(1.0)}; assert_parsed_expression_evaluate_to("abs(-1)", a0, 1); - Complex a1[1] = {Complex::Float(std::sqrt(3.0f*3.0f+2.0f*2.0f))}; + Complex a1[1] = {Complex::Float(std::sqrt(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)}; + Complex a2[4] = {Complex::Float(1.0), Complex::Float(2.0), Complex::Float(3.0), Complex::Float(4.0)}; assert_parsed_expression_evaluate_to("abs([[1,-2][3,-4]])", a2, 4); - Complex a3[4] = {Complex::Float(std::sqrt(3.0f*3.0f+2.0f*2.0f)), Complex::Float(std::sqrt(3.0f*3.0f+4.0f*4.0f)), Complex::Float(std::sqrt(5.0f*5.0f+2.0f*2.0f)), Complex::Float(std::sqrt(3.0f*3.0f+2.0f*2.0f))}; + Complex a3[4] = {Complex::Float(std::sqrt(3.0f*3.0f+2.0f*2.0f)), Complex::Float(std::sqrt(3.0f*3.0f+4.0f*4.0f)), Complex::Float(std::sqrt(5.0f*5.0f+2.0f*2.0f)), Complex::Float(std::sqrt(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)}; + Complex b[1] = {Complex::Float(210.0)}; assert_parsed_expression_evaluate_to("binomial(10, 4)", b, 1); - Complex c[1] = {Complex::Float(1.0f)}; + Complex c[1] = {Complex::Float(1.0f)}; assert_parsed_expression_evaluate_to("ceil(0.2)", c, 1); - Complex d[1] = {Complex::Float(2.0f)}; + Complex d[1] = {Complex::Float(2.0)}; assert_parsed_expression_evaluate_to("diff(2*x, 2)", d, 1); #if MATRICES_ARE_DEFINED - Complex e[1] = {Complex::Float(126.0f)}; + 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 - Complex f[1] = {Complex::Float(2.0f)}; + Complex f[1] = {Complex::Float(2.0)}; assert_parsed_expression_evaluate_to("floor(2.3)", f, 1); - Complex g[1] = {Complex::Float(0.3f)}; + Complex g[1] = {Complex::Float(0.3f)}; assert_parsed_expression_evaluate_to("frac(2.3)", g, 1); - Complex h[1] = {Complex::Float(2.0f)}; + Complex h[1] = {Complex::Float(2.0)}; assert_parsed_expression_evaluate_to("gcd(234,394)", h, 1); - Complex i[1] = {Complex::Float(3.0f)}; + 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)}; + Complex j[1] = {Complex::Float(3.0/2.0)}; assert_parsed_expression_evaluate_to("int(x, 1, 2)", j, 1); - Complex k[1] = {Complex::Float(46098.0f)}; + Complex k[1] = {Complex::Float(46098.0f)}; assert_parsed_expression_evaluate_to("lcm(234,394)", k, 1); - Complex l[1] = {Complex::Float(std::log(2.0f))}; + Complex l[1] = {Complex::Float(std::log(2.0))}; assert_parsed_expression_evaluate_to("ln(2)", l, 1); - Complex m[1] = {Complex::Float(std::log10(2.0f))}; + Complex m[1] = {Complex::Float(std::log10(2.0f))}; assert_parsed_expression_evaluate_to("log(2)", m, 1); - Complex n[1] = {Complex::Float(5040.0f)}; + Complex n[1] = {Complex::Float(5040.0)}; assert_parsed_expression_evaluate_to("permute(10, 4)", n, 1); - Complex o[1] = {Complex::Float(604800.0f)}; + 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)}; + Complex p[1] = {Complex::Float(2.0)}; assert_parsed_expression_evaluate_to("re(2+I)", p, 1); - Complex q[1] = {Complex::Float(9.0f)}; + Complex q[1] = {Complex::Float(9.0f)}; assert_parsed_expression_evaluate_to("rem(29, 10)", q, 1); - Complex r[1] = {Complex::Float(std::pow(2.0f, 1.0f/3.0f))}; + Complex r[1] = {Complex::Float(std::pow(2.0, 1.0/3.0))}; assert_parsed_expression_evaluate_to("root(2,3)", r, 1); - Complex s[1] = {Complex::Float(std::sqrt(2.0f))}; + Complex s[1] = {Complex::Float(std::sqrt(2.0f))}; assert_parsed_expression_evaluate_to("R(2)", s, 1); - Complex t[1] = {Complex::Float(49.0f)}; + Complex t[1] = {Complex::Float(49.0)}; assert_parsed_expression_evaluate_to("sum(n, 4, 10)", t, 1); #if MATRICES_ARE_DEFINED - Complex u[1] = {Complex::Float(15.0f)}; + 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 - Complex v[2] = {Complex::Float(0.1f - std::sqrt(1.0f/100.0f)), Complex::Float(0.1f + std::sqrt(1.0f/100.0f))}; + Complex v[2] = {Complex::Float(0.1 - std::sqrt(1.0/100.0)), Complex::Float(0.1 + std::sqrt(1.0/100.0))}; assert_parsed_expression_evaluate_to("confidence(0.1, 100)", v, 2); #if MATRICES_ARE_DEFINED - Complex w[2] = {Complex::Float(2.0f), Complex::Float(3.0f)}; + 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)}; + Complex x[1] = {Complex::Cartesian(3.0, -2.0)}; 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)}; + 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-std::sqrt(1.0f/100.0f)), Complex::Float(0.1f+std::sqrt(1.0f/100.0f))}; + Complex z[2] = {Complex::Float(0.1-std::sqrt(1.0/100.0)), Complex::Float(0.1+std::sqrt(1.0/100.0))}; assert_parsed_expression_evaluate_to("prediction(0.1, 100)", z, 2); - Complex aa[2] = {Complex::Float(0.1f-1.96f*std::sqrt((0.1f*(1.0f-0.1f))/100.0f)), Complex::Float(0.1f+1.96f*std::sqrt((0.1f*(1.0f-0.1f))/100.0f))}; + Complex aa[2] = {Complex::Float(0.1f-1.96f*std::sqrt((0.1f*(1.0f-0.1f))/100.0f)), Complex::Float(0.1f+1.96f*std::sqrt((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)}; + Complex ab[1] = {Complex::Cartesian(-100.0, -540.0)}; assert_parsed_expression_evaluate_to("product(2+n*I, 1, 5)", ab, 1); - Complex ac[1] = {Complex::Cartesian(1.4593656008f, 0.1571201229f)}; + 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)}; + Complex ad[1] = {Complex::Cartesian(1.38200696233, -0.152442779)}; assert_parsed_expression_evaluate_to("root(3, 3+I)", ad, 1); - Complex ae[1] = {Complex::Cartesian(1.75532f, 0.28485f)}; + 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)}; + Complex af[1] = {Complex::Cartesian(10.0, 15.0)}; 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)}; + Complex ag[9] = {Complex::Float(1.0), Complex::Float(4.0), Complex::Float(7.0), Complex::Float(2.0), Complex::Float(5.0), Complex::Float(8.0), Complex::Float(3.0), Complex::Float(-6.0), Complex::Float(9.0)}; 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)}; + 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 index 41baa308d..1ac4a3aa6 100644 --- a/poincare/test/helper.cpp +++ b/poincare/test/helper.cpp @@ -8,7 +8,8 @@ using namespace Poincare; -void assert_parsed_expression_evaluate_to(const char * expression, Complex * results, int numberOfEntries, Expression::AngleUnit angleUnit) { +template +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); + Evaluation * m = a->evaluate(globalContext, angleUnit); for (int i = 0; i < numberOfEntries; i++) { assert(std::fabs(m->complexOperand(i)->a() - results[i].a()) < 0.0001f); assert(std::fabs(m->complexOperand(i)->b() - results[i].b()) < 0.0001f); @@ -38,3 +39,6 @@ void assert_parsed_expression_evaluate_to(const char * expression, Complex * res delete a; delete m; } + +template void assert_parsed_expression_evaluate_to(char const*, Poincare::Complex*, int, Poincare::Expression::AngleUnit); +template void assert_parsed_expression_evaluate_to(char const*, Poincare::Complex*, int, Poincare::Expression::AngleUnit); diff --git a/poincare/test/helper.h b/poincare/test/helper.h index bf15fca49..37ad36b01 100644 --- a/poincare/test/helper.h +++ b/poincare/test/helper.h @@ -3,4 +3,5 @@ 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); +template +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 7a54d409d..dbcca306e 100644 --- a/poincare/test/integer.cpp +++ b/poincare/test/integer.cpp @@ -52,9 +52,10 @@ QUIZ_CASE(poincare_integer_divide) { assert(Integer("3293920983029832").divide_by(Integer("389090928")) == Integer("8465684")); } -void assert_integer_evals_to(int i, float result) { +template +void assert_integer_evals_to(int i, T result) { GlobalContext globalContext; - Evaluation * m = Integer(i).evaluate(globalContext); + Evaluation * m = Integer(i).evaluate(globalContext); assert(m->complexOperand(0)->a() == result); assert(m->complexOperand(0)->b() == 0.0f); assert(m->numberOfOperands() == 1); @@ -63,9 +64,9 @@ void assert_integer_evals_to(int i, float result) { QUIZ_CASE(poincare_integer_evaluate) { assert_integer_evals_to(1, 1.0f); - assert_integer_evals_to(12345678, 12345678.0f); + assert_integer_evals_to(12345678, 12345678.0); assert_integer_evals_to(0, 0.0f); - assert_integer_evals_to(-0, 0.0f); + assert_integer_evals_to(-0, 0.0); assert_integer_evals_to(-1, -1.0f); - assert_integer_evals_to(12345678, 12345678.0f); + assert_integer_evals_to(12345678, 12345678.0); } diff --git a/poincare/test/matrix.cpp b/poincare/test/matrix.cpp index a099a677a..300db8c61 100644 --- a/poincare/test/matrix.cpp +++ b/poincare/test/matrix.cpp @@ -7,7 +7,10 @@ using namespace Poincare; QUIZ_CASE(poincare_matrix_evaluate) { #if MATRICES_ARE_DEFINED - 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)}; + 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); + + Complex b[6] = {Complex::Float(1.0), Complex::Float(2.0), Complex::Float(3.0), Complex::Float(4.0), Complex::Float(5.0), Complex::Float(6.0)}; + assert_parsed_expression_evaluate_to("[[1,2,3][4,5,6]]", b, 6); #endif } diff --git a/poincare/test/parser.cpp b/poincare/test/parser.cpp index 6d2b37118..860f9cb50 100644 --- a/poincare/test/parser.cpp +++ b/poincare/test/parser.cpp @@ -8,30 +8,30 @@ using namespace Poincare; QUIZ_CASE(poincare_parser) { - Complex a[1] = {Complex::Float(1.2f*M_E)}; + Complex a[1] = {Complex::Float(1.2*M_E)}; assert_parsed_expression_evaluate_to("1.2*X^(1)", a, 1); - Complex b[1] = {Complex::Float(std::pow((float)M_E, 2.0f)*M_E)}; + Complex b[1] = {Complex::Float(std::pow((float)M_E, 2.0f)*M_E)}; assert_parsed_expression_evaluate_to("X^2*X^(1)", b, 1); - Complex c[1] = {Complex::Float(2.0f*std::pow(3.0f, 4.0f)+2.0f)}; + Complex c[1] = {Complex::Float(2.0*std::pow(3.0, 4.0)+2.0)}; assert_parsed_expression_evaluate_to("2*3^4+2", c, 1); - Complex d[1] = {Complex::Float(-2.0f*std::pow(3.0f, 4.0f)+2.0f)}; + Complex d[1] = {Complex::Float(-2.0f*std::pow(3.0f, 4.0f)+2.0f)}; assert_parsed_expression_evaluate_to("-2*3^4+2", d,1); - Complex e[1] = {Complex::Float(-std::sin(3.0f)*2.0f-3.0f)}; + Complex e[1] = {Complex::Float(-std::sin(3.0)*2.0-3.0)}; assert_parsed_expression_evaluate_to("-sin(3)*2-3", e, 1, Radian); - Complex f[1] = {Complex::Float(-0.003f)}; + Complex f[1] = {Complex::Float(-0.003f)}; assert_parsed_expression_evaluate_to("-.003", f, 1); - Complex g[1] = {Complex::Float(2.0f)}; + Complex g[1] = {Complex::Float(2.0)}; assert_parsed_expression_evaluate_to(".02E2", g, 1); - Complex h[1] = {Complex::Float(5.0f-2.0f/3.0f)}; + 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)}; + Complex i[1] = {Complex::Float(2.0/3.0-5.0)}; assert_parsed_expression_evaluate_to("2/3-5", i, 1); - Complex j[1] = {Complex::Float(-2.0f/3.0f-5.0f)}; + 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(std::sin(3.0f)*2.0f*(4.0f+2.0f))}; + Complex k[1] = {Complex::Float(std::sin(3.0)*2.0*(4.0+2.0))}; 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))}; + 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))}; + Complex m[1] = {Complex::Float(4.0/2.0*(2.0+3.0))}; 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 344ef7937..ce5b75e0c 100644 --- a/poincare/test/power.cpp +++ b/poincare/test/power.cpp @@ -7,17 +7,17 @@ using namespace Poincare; QUIZ_CASE(poincare_power_evaluate) { - Complex a[1] = {Complex::Float(8.0f)}; + Complex a[1] = {Complex::Float(8.0f)}; assert_parsed_expression_evaluate_to("2^3", a, 1); - Complex b[1] = {Complex::Cartesian(28.0f, 96.0f)}; + Complex b[1] = {Complex::Cartesian(28.0, 96.0)}; assert_parsed_expression_evaluate_to("(3+I)^4", b, 1); - Complex c[1] = {Complex::Cartesian(11.7412464f, 62.9137754f)}; + Complex c[1] = {Complex::Cartesian(11.7412464f, 62.9137754f)}; assert_parsed_expression_evaluate_to("4^(3+I)", c, 1); #if MATRICES_ARE_DEFINED - Complex d[4] = {Complex::Float(37.0f), Complex::Float(54.0f), Complex::Float(81.0f), Complex::Float(118.0f)}; + Complex d[4] = {Complex::Float(37.0), Complex::Float(54.0), Complex::Float(81.0), Complex::Float(118.0)}; 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 6b3e298e9..68ee72691 100644 --- a/poincare/test/product.cpp +++ b/poincare/test/product.cpp @@ -7,27 +7,27 @@ using namespace Poincare; QUIZ_CASE(poincare_product_evaluate) { - Complex a[1] = {Complex::Float(2.0f)}; + Complex a[1] = {Complex::Float(2.0f)}; assert_parsed_expression_evaluate_to("1*2", a, 1); - Complex b[1] = {Complex::Cartesian(11.0f, 7.0f)}; + Complex b[1] = {Complex::Cartesian(11.0, 7.0)}; assert_parsed_expression_evaluate_to("(3+I)*(4+I)", b, 1); #if MATRICES_ARE_DEFINED - 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)}; + 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)}; + Complex d[6] = {Complex::Cartesian(3.0, 1.0), Complex::Cartesian(5.0, 5.0), Complex::Cartesian(9.0, 3.0), Complex::Cartesian(12.0, 4.0), Complex::Cartesian(15.0, 5.0), Complex::Cartesian(18.0, 6.0)}; assert_parsed_expression_evaluate_to("[[1,2+I][3,4][5,6]]*(3+I)", d, 6); assert_parsed_expression_evaluate_to("2*[[1,2][3,4][5,6]]", c, 6); assert_parsed_expression_evaluate_to("(3+I)*[[1,2+I][3,4][5,6]]", d, 6); - 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)}; + 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); - 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)}; + Complex f[12] = {Complex::Cartesian(11.0, 5.0), Complex::Cartesian(13.0, 9.0), Complex::Cartesian(17.0, 7.0), Complex::Cartesian(20.0, 8.0), Complex::Cartesian(23.0, 0.0), Complex::Cartesian(30.0, 7.0), Complex::Cartesian(37.0, 0.0), Complex::Cartesian(44.0, 0.0), Complex::Cartesian(35.0, 0.0), Complex::Cartesian(46.0, 11.0), Complex::Cartesian(57.0, 0.0), Complex::Cartesian(68.0, 0.0)}; 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 96899d6f5..d2a4d6f62 100644 --- a/poincare/test/subtraction.cpp +++ b/poincare/test/subtraction.cpp @@ -7,29 +7,29 @@ using namespace Poincare; QUIZ_CASE(poincare_substraction_evaluate) { - Complex a[1] = {Complex::Float(-1.0f)}; + Complex a[1] = {Complex::Float(-1.0f)}; assert_parsed_expression_evaluate_to("1-2", a, 1); - Complex b[1] = {Complex::Cartesian(-1.0f, 0.0f)}; + Complex b[1] = {Complex::Cartesian(-1.0, 0.0)}; assert_parsed_expression_evaluate_to("3+I-(4+I)", b, 1); #if MATRICES_ARE_DEFINED - 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)}; + 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); - 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)}; + Complex d[6] = {Complex::Cartesian(-3.0, -1.0), Complex::Cartesian(-2.0, 0.0), Complex::Cartesian(-1.0, -1.0), Complex::Cartesian(0.0, -1.0), Complex::Cartesian(1.0, -1.0), Complex::Cartesian(2.0, -1.0)}; assert_parsed_expression_evaluate_to("[[1,2+I][3,4][5,6]]-(4+I)", d, 6); - 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)}; + 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); - 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)}; + Complex f[6] = {Complex::Cartesian(2.0, 1.0), Complex::Cartesian(1.0, 0.0), Complex::Cartesian(0.0, 1.0), Complex::Cartesian(-1.0, 1.0), Complex::Cartesian(-2.0, 1.0), Complex::Cartesian(-3.0, 1.0)}; assert_parsed_expression_evaluate_to("3+I-[[1,2+I][3,4][5,6]]", f, 6); - 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)}; + 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); - 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)}; + Complex h[6] = {Complex::Float(0.0), Complex::Float(0.0), Complex::Float(0.0), Complex::Float(0.0), Complex::Float(0.0), Complex::Float(0.0)}; 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 929d994a4..0d34c9dbe 100644 --- a/poincare/test/symbol.cpp +++ b/poincare/test/symbol.cpp @@ -35,11 +35,11 @@ QUIZ_CASE(poincare_parse_symbol) { QUIZ_CASE(poincare_symbol_approximate) { - Complex a[1] = {Complex::Float(M_PI)}; + Complex a[1] = {Complex::Float(M_PI)}; assert_parsed_expression_evaluate_to("P", a, 1); - Complex b[1] = {Complex::Float(M_E)}; + Complex b[1] = {Complex::Float(M_E)}; assert_parsed_expression_evaluate_to("X", b, 1); - Complex c[1] = {Complex::Float(1200.0f)}; + Complex c[1] = {Complex::Float(1200.0)}; assert_parsed_expression_evaluate_to("1.2E3", c, 1); } diff --git a/poincare/test/trigo.cpp b/poincare/test/trigo.cpp index 703d0dbb6..705eb888d 100644 --- a/poincare/test/trigo.cpp +++ b/poincare/test/trigo.cpp @@ -94,28 +94,28 @@ QUIZ_CASE(poincare_parse_trigo) { } QUIZ_CASE(poincare_trigo_evaluate) { - Complex a[1] = {Complex::Float(-0.4161468365f)}; + Complex a[1] = {Complex::Float(-0.4161468365)}; assert_parsed_expression_evaluate_to("cos(2)", a, 1, Radian); - Complex a1[1] = {Complex::Cartesian(-1.0086248134f, -0.8893951958f)}; + 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)}; + Complex b[1] = {Complex::Float(0.9092974268)}; assert_parsed_expression_evaluate_to("sin(2)", b, 1, Radian); - Complex b1[1] = {Complex::Cartesian( 1.16780727488f, -0.768162763456f)}; + 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)}; + Complex c[1] = {Complex::Float(-2.18503986326151899)}; assert_parsed_expression_evaluate_to("tan(2)", c, 1, Radian); - Complex c1[1] = {Complex::Cartesian(-0.27355308280730f, 1.002810507583504f)}; + 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)}; + Complex a2[1] = {Complex::Float(3.762195691)}; assert_parsed_expression_evaluate_to("cosh(2)", a2, 1, Radian); - Complex a3[1] = {Complex::Cartesian(14.754701170483756280f,-22.96367349919304059f)}; + 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)}; + Complex b2[1] = {Complex::Float(3.62686040784701876)}; assert_parsed_expression_evaluate_to("sinh(2)", b2, 1, Radian); - Complex b3[1] = {Complex::Cartesian(-14.744805188558725031023f, 22.979085577886129555168f)}; + 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)}; + Complex c2[1] = {Complex::Float(0.9640275800758168839464)}; assert_parsed_expression_evaluate_to("tanh(2)", c2, 1, Radian); - Complex c3[1] = {Complex::Cartesian(-1.00027905623446556836909f, 0.000610240921376259f)}; + Complex c3[1] = {Complex::Cartesian(-1.00027905623446556836909f, 0.000610240921376259f)}; assert_parsed_expression_evaluate_to("tanh(I-4)", c3, 1, Radian); }