From a74eef903a064a16bdc2661a7156e812ce0cca16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Wed, 11 Jan 2017 16:07:58 +0100 Subject: [PATCH] [poincare] Redesign Float::convertTotext Change-Id: Id27d9472147b5e443ee296feca891392fad735c8 --- apps/constant.cpp | 6 +-- apps/constant.h | 6 +-- apps/curve_view.cpp | 7 +-- apps/editable_cell_table_view_controller.cpp | 4 +- apps/float_parameter_controller.cpp | 4 +- apps/graph/graph/graph_controller.cpp | 15 ++++-- apps/graph/graph/graph_view.h | 4 +- apps/graph/values/values_controller.cpp | 6 +-- apps/probability/calculation_controller.cpp | 4 +- apps/probability/law_curve_view.h | 2 +- apps/probability/parameters_controller.cpp | 4 +- apps/regression/calculation_controller.cpp | 10 ++-- apps/regression/graph_controller.cpp | 10 ++-- apps/regression/graph_view.h | 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 | 4 +- poincare/include/poincare/float.h | 33 +++++++++---- poincare/src/float.cpp | 50 +++++++++++--------- poincare/test/float.cpp | 36 ++++++++++---- 23 files changed, 136 insertions(+), 95 deletions(-) diff --git a/apps/constant.cpp b/apps/constant.cpp index 8f6c523d4..8b54a3aa0 100644 --- a/apps/constant.cpp +++ b/apps/constant.cpp @@ -1,6 +1,4 @@ #include "constant.h" -constexpr int Constant::FloatBufferSizeInScientificMode; -constexpr int Constant::NumberOfDigitsInMantissaInScientificMode; -constexpr int Constant::FloatBufferSizeInDecimalMode; -constexpr int Constant::NumberOfDigitsInMantissaInDecimalMode; +constexpr int Constant::LargeNumberOfSignificantDigits; +constexpr int Constant::ShortNumberOfSignificantDigits; diff --git a/apps/constant.h b/apps/constant.h index 3e2095792..8cf5ea017 100644 --- a/apps/constant.h +++ b/apps/constant.h @@ -3,10 +3,8 @@ class Constant { public: - constexpr static int FloatBufferSizeInScientificMode = 14; - constexpr static int NumberOfDigitsInMantissaInScientificMode = 7; - constexpr static int FloatBufferSizeInDecimalMode = 11; - constexpr static int NumberOfDigitsInMantissaInDecimalMode = 4; + constexpr static int LargeNumberOfSignificantDigits = 7; + constexpr static int ShortNumberOfSignificantDigits = 4; }; #endif diff --git a/apps/curve_view.cpp b/apps/curve_view.cpp index c400b4be8..904d0098c 100644 --- a/apps/curve_view.cpp +++ b/apps/curve_view.cpp @@ -97,11 +97,12 @@ float CurveView::floatToPixel(Axis axis, float f) const { } void CurveView::computeLabels(Axis axis) { - char buffer[Constant::FloatBufferSizeInDecimalMode]; + char buffer[Float::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)]; float step = gridUnit(axis); for (int index = 0; index < numberOfLabels(axis); index++) { - // TODO: change the number of digits in mantissa once the numerical mode is implemented - Float(2.0f*step*(ceilf(min(axis)/(2.0f*step)))+index*2.0f*step).convertFloatToText(buffer, Constant::FloatBufferSizeInDecimalMode, Constant::NumberOfDigitsInMantissaInDecimalMode, Float::DisplayMode::Decimal); + Float(2.0f*step*(ceilf(min(axis)/(2.0f*step)))+index*2.0f*step).convertFloatToText(buffer, + Float::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits), + Constant::ShortNumberOfSignificantDigits, Float::DisplayMode::Decimal); //TODO: check for size of label? strlcpy(label(axis, index), buffer, strlen(buffer)+1); } diff --git a/apps/editable_cell_table_view_controller.cpp b/apps/editable_cell_table_view_controller.cpp index 77b5d9b44..3ec41c738 100644 --- a/apps/editable_cell_table_view_controller.cpp +++ b/apps/editable_cell_table_view_controller.cpp @@ -69,7 +69,7 @@ void EditableCellTableViewController::willDisplayCellAtLocation(TableViewCell * // The cell is editable if (cellAtLocationIsEditable(i, j)) { EvenOddEditableTextCell * myEditableValueCell = (EvenOddEditableTextCell *)cell; - char buffer[Constant::FloatBufferSizeInScientificMode]; + char buffer[Float::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 @@ -80,7 +80,7 @@ void EditableCellTableViewController::willDisplayCellAtLocation(TableViewCell * return; } } - Float(dataAtLocation(i, j)).convertFloatToText(buffer, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + Float(dataAtLocation(i, j)).convertFloatToText(buffer, Float::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); myEditableValueCell->setText(buffer); return; } diff --git a/apps/float_parameter_controller.cpp b/apps/float_parameter_controller.cpp index d5767a902..80ea1e631 100644 --- a/apps/float_parameter_controller.cpp +++ b/apps/float_parameter_controller.cpp @@ -26,8 +26,8 @@ int FloatParameterController::activeCell() { void FloatParameterController::willDisplayCellForIndex(TableViewCell * cell, int index) { EditableTextMenuListCell * myCell = (EditableTextMenuListCell *) cell; - char buffer[Constant::FloatBufferSizeInScientificMode]; - Float(parameterAtIndex(index)).convertFloatToText(buffer, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + char buffer[Float::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; + Float(parameterAtIndex(index)).convertFloatToText(buffer, Float::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); myCell->setAccessoryText(buffer); } diff --git a/apps/graph/graph/graph_controller.cpp b/apps/graph/graph/graph_controller.cpp index b9c6dfe2f..0ac43b81d 100644 --- a/apps/graph/graph/graph_controller.cpp +++ b/apps/graph/graph/graph_controller.cpp @@ -96,14 +96,19 @@ bool GraphController::handleEnter() { } void GraphController::reloadBannerView() { - char buffer[k_maxNumberOfCharacters+Constant::FloatBufferSizeInScientificMode] = {'x', ' ', '=', ' ',0}; - Float(m_cursor.x()).convertFloatToText(buffer+4, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + char buffer[k_maxNumberOfCharacters+Float::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; + const char * legend = "x = "; + int legendLength = strlen(legend); + strlcpy(buffer, legend, legendLength+1); + Float(m_cursor.x()).convertFloatToText(buffer+ legendLength, Float::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, Float::DisplayMode::Decimal); m_bannerView.setLegendAtIndex(buffer, 0); - strlcpy(buffer, "00(x) = ", k_maxNumberOfCharacters+1); + legend = "00(x) = "; + legendLength = strlen(legend); + strlcpy(buffer, legend, legendLength+1); Function * f = m_functionStore->activeFunctionAtIndex(m_indexFunctionSelectedByCursor); buffer[1] = f->name()[0]; - Float(m_cursor.y()).convertFloatToText(buffer+8, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + Float(m_cursor.y()).convertFloatToText(buffer+legendLength, Float::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, Float::DisplayMode::Decimal); m_bannerView.setLegendAtIndex(buffer+1, 1); if (m_bannerView.displayDerivative()) { @@ -111,7 +116,7 @@ void GraphController::reloadBannerView() { buffer[1] = '\''; App * graphApp = (Graph::App *)app(); float y = f->approximateDerivative(m_cursor.x(), graphApp->localContext()); - Float(y).convertFloatToText(buffer+8, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + Float(y).convertFloatToText(buffer + legendLength, Float::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, Float::DisplayMode::Decimal); m_bannerView.setLegendAtIndex(buffer, 2); } m_bannerView.layoutSubviews(); diff --git a/apps/graph/graph/graph_view.h b/apps/graph/graph/graph_view.h index ec050b9bb..4f2469ee3 100644 --- a/apps/graph/graph/graph_view.h +++ b/apps/graph/graph/graph_view.h @@ -18,8 +18,8 @@ public: private: char * label(Axis axis, int index) const override; float evaluateModelWithParameter(Model * expression, float abscissa) const override; - char m_xLabels[k_maxNumberOfXLabels][Constant::FloatBufferSizeInScientificMode]; - char m_yLabels[k_maxNumberOfYLabels][Constant::FloatBufferSizeInScientificMode]; + char m_xLabels[k_maxNumberOfXLabels][Float::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)]; + char m_yLabels[k_maxNumberOfYLabels][Float::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)]; FunctionStore * m_functionStore; Context * m_context; }; diff --git a/apps/graph/values/values_controller.cpp b/apps/graph/values/values_controller.cpp index e4e5ab890..af1431a36 100644 --- a/apps/graph/values/values_controller.cpp +++ b/apps/graph/values/values_controller.cpp @@ -144,7 +144,7 @@ void ValuesController::willDisplayCellAtLocation(TableViewCell * cell, int i, in return; } // The cell is not a title cell - char buffer[Constant::FloatBufferSizeInScientificMode]; + char buffer[Float::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; // Special case: last row if (j == numberOfRows() - 1) { int numberOfIntervalElements = m_interval.numberOfElements(); @@ -161,9 +161,9 @@ void ValuesController::willDisplayCellAtLocation(TableViewCell * cell, int i, in float x = m_interval.element(j-1); App * graphApp = (Graph::App *)app(); if (isDerivativeColumn(i)) { - Float(function->approximateDerivative(x, graphApp->localContext())).convertFloatToText(buffer, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + Float(function->approximateDerivative(x, graphApp->localContext())).convertFloatToText(buffer, Float::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); } else { - Float(function->evaluateAtAbscissa(x, graphApp->localContext())).convertFloatToText(buffer, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + Float(function->evaluateAtAbscissa(x, graphApp->localContext())).convertFloatToText(buffer, Float::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); } myValueCell->setText(buffer); } diff --git a/apps/probability/calculation_controller.cpp b/apps/probability/calculation_controller.cpp index b0cc7c9de..25d03132e 100644 --- a/apps/probability/calculation_controller.cpp +++ b/apps/probability/calculation_controller.cpp @@ -62,8 +62,8 @@ View * CalculationController::ContentView::subviewAtIndex(int index) { } void CalculationController::ContentView::willDisplayEditableCellAtIndex(int index) { - char buffer[Constant::FloatBufferSizeInScientificMode]; - Float(m_calculation->parameterAtIndex(index)).convertFloatToText(buffer, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + char buffer[Float::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)]; + Float(m_calculation->parameterAtIndex(index)).convertFloatToText(buffer, Float::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits), Constant::ShortNumberOfSignificantDigits, Float::DisplayMode::Decimal); m_calculationCell[index].setText(buffer); } diff --git a/apps/probability/law_curve_view.h b/apps/probability/law_curve_view.h index 2bc4bddde..b95c25fdc 100644 --- a/apps/probability/law_curve_view.h +++ b/apps/probability/law_curve_view.h @@ -19,7 +19,7 @@ public: protected: char * label(Axis axis, int index) const override; private: - char m_labels[k_maxNumberOfXLabels][Constant::FloatBufferSizeInScientificMode]; + char m_labels[k_maxNumberOfXLabels][Float::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)]; float evaluateModelWithParameter(Model * law, float abscissa) const override; Law * m_law; Calculation * m_calculation; diff --git a/apps/probability/parameters_controller.cpp b/apps/probability/parameters_controller.cpp index 9c4e2c49b..9bf8476a4 100644 --- a/apps/probability/parameters_controller.cpp +++ b/apps/probability/parameters_controller.cpp @@ -101,8 +101,8 @@ void ParametersController::updateTitle() { m_titleBuffer[currentChar++] = m_law->parameterNameAtIndex(index)[0]; strlcpy(m_titleBuffer+currentChar, " = ", 4); currentChar += 3; - char buffer[Constant::FloatBufferSizeInDecimalMode]; - Float(m_law->parameterValueAtIndex(index)).convertFloatToText(buffer, Constant::FloatBufferSizeInDecimalMode, Constant::NumberOfDigitsInMantissaInDecimalMode, Float::DisplayMode::Decimal); + char buffer[Float::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)]; + Float(m_law->parameterValueAtIndex(index)).convertFloatToText(buffer, Float::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits), Constant::ShortNumberOfSignificantDigits, Float::DisplayMode::Decimal); strlcpy(m_titleBuffer+currentChar, buffer, strlen(buffer)+1); currentChar += strlen(buffer); m_titleBuffer[currentChar++] = ' '; diff --git a/apps/regression/calculation_controller.cpp b/apps/regression/calculation_controller.cpp index 66d2e0ef5..576eae009 100644 --- a/apps/regression/calculation_controller.cpp +++ b/apps/regression/calculation_controller.cpp @@ -126,10 +126,10 @@ void CalculationController::willDisplayCellAtLocation(TableViewCell * cell, int float calculation1 = (m_store->*calculationMethods[j-1])(0); float calculation2 = (m_store->*calculationMethods[j-1])(1); EvenOddDoubleBufferTextCell * myCell = (EvenOddDoubleBufferTextCell *)cell; - char buffer[Constant::FloatBufferSizeInScientificMode]; - Float(calculation1).convertFloatToText(buffer, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + char buffer[Float::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; + Float(calculation1).convertFloatToText(buffer, Float::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); myCell->setFirstText(buffer); - Float(calculation2).convertFloatToText(buffer, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + Float(calculation2).convertFloatToText(buffer, Float::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); myCell->setSecondText(buffer); return; } @@ -138,8 +138,8 @@ void CalculationController::willDisplayCellAtLocation(TableViewCell * cell, int &Store::columnProductSum, &Store::correlationCoefficient, &Store::squaredCorrelationCoefficient}; float calculation = (m_store->*calculationMethods[j-6])(); EvenOddBufferTextCell * myCell = (EvenOddBufferTextCell *)cell; - char buffer[Constant::FloatBufferSizeInScientificMode]; - Float(calculation).convertFloatToText(buffer, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + char buffer[Float::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; + Float(calculation).convertFloatToText(buffer, Float::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); myCell->setText(buffer); return; } diff --git a/apps/regression/graph_controller.cpp b/apps/regression/graph_controller.cpp index 641b39423..d18a3f4d2 100644 --- a/apps/regression/graph_controller.cpp +++ b/apps/regression/graph_controller.cpp @@ -54,19 +54,19 @@ bool GraphController::handleEnter() { void GraphController::reloadBannerView() { m_bannerView.setLegendAtIndex((char *)"y = ax+b", 0); - char buffer[k_maxNumberOfCharacters + Constant::FloatBufferSizeInScientificMode]; + char buffer[k_maxNumberOfCharacters + Float::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; const char * legend = "a = "; float slope = m_store->slope(); int legendLength = strlen(legend); strlcpy(buffer, legend, legendLength+1); - Float(slope).convertFloatToText(buffer+legendLength, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + Float(slope).convertFloatToText(buffer+legendLength, Float::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); m_bannerView.setLegendAtIndex(buffer, 1); legend = "b = "; float yIntercept = m_store->yIntercept(); legendLength = strlen(legend); strlcpy(buffer, legend, legendLength+1); - Float(yIntercept).convertFloatToText(buffer+legendLength, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + Float(yIntercept).convertFloatToText(buffer+legendLength, Float::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); m_bannerView.setLegendAtIndex(buffer, 2); legend = "x = "; @@ -78,7 +78,7 @@ void GraphController::reloadBannerView() { } legendLength = strlen(legend); strlcpy(buffer, legend, legendLength+1); - Float(x).convertFloatToText(buffer+legendLength, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + Float(x).convertFloatToText(buffer+legendLength, Float::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); m_bannerView.setLegendAtIndex(buffer, 3); legend = "y = "; @@ -89,7 +89,7 @@ void GraphController::reloadBannerView() { } legendLength = strlen(legend); strlcpy(buffer, legend, legendLength+1); - Float(y).convertFloatToText(buffer+legendLength, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + Float(y).convertFloatToText(buffer+legendLength, Float::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); m_bannerView.setLegendAtIndex(buffer, 4); m_bannerView.layoutSubviews(); diff --git a/apps/regression/graph_view.h b/apps/regression/graph_view.h index 09b8962c6..2df77cb6a 100644 --- a/apps/regression/graph_view.h +++ b/apps/regression/graph_view.h @@ -17,8 +17,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][Constant::FloatBufferSizeInScientificMode]; - char m_yLabels[k_maxNumberOfYLabels][Constant::FloatBufferSizeInScientificMode]; + char m_xLabels[k_maxNumberOfXLabels][Float::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)]; + char m_yLabels[k_maxNumberOfYLabels][Float::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)]; }; } diff --git a/apps/statistics/box_controller.cpp b/apps/statistics/box_controller.cpp index b0d1e2c54..19eabdbf2 100644 --- a/apps/statistics/box_controller.cpp +++ b/apps/statistics/box_controller.cpp @@ -63,11 +63,11 @@ Responder * BoxController::tabController() const { void BoxController::reloadBannerView() { const char * calculationName[5] = {"Minimum", "Premier quartile", "Mediane", "Troisieme quartile", "Maximum"}; m_boxBannerView.setLegendAtIndex((char *)calculationName[(int)m_view.selectedQuantile()], 0); - char buffer[Constant::FloatBufferSizeInScientificMode]; + char buffer[Float::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()])(); - Float(calculation).convertFloatToText(buffer, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + Float(calculation).convertFloatToText(buffer, Float::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); m_boxBannerView.setLegendAtIndex(buffer, 1); m_boxBannerView.layoutSubviews(); } diff --git a/apps/statistics/box_view.h b/apps/statistics/box_view.h index ede113ac7..398b66a7a 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][Constant::FloatBufferSizeInScientificMode]; + char m_labels[k_maxNumberOfXLabels][Float::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)]; Quantile m_selectedQuantile; }; diff --git a/apps/statistics/calculation_controller.cpp b/apps/statistics/calculation_controller.cpp index 72e07d902..3bfb3aa9c 100644 --- a/apps/statistics/calculation_controller.cpp +++ b/apps/statistics/calculation_controller.cpp @@ -81,8 +81,8 @@ void CalculationController::willDisplayCellAtLocation(TableViewCell * cell, int &Store::thirdQuartile, &Store::median, &Store::quartileRange, &Store::sum, &Store::squaredValueSum}; float calculation = (m_store->*calculationMethods[j])(); EvenOddBufferTextCell * myCell = (EvenOddBufferTextCell *)cell; - char buffer[Constant::FloatBufferSizeInScientificMode]; - Float(calculation).convertFloatToText(buffer, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + char buffer[Float::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; + Float(calculation).convertFloatToText(buffer, Float::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); myCell->setText(buffer); } } diff --git a/apps/statistics/histogram_controller.cpp b/apps/statistics/histogram_controller.cpp index 20a2efac1..7b5e26d30 100644 --- a/apps/statistics/histogram_controller.cpp +++ b/apps/statistics/histogram_controller.cpp @@ -120,15 +120,15 @@ Responder * HistogramController::tabController() const { } void HistogramController::reloadBannerView() { - char buffer[k_maxNumberOfCharacters+ Constant::FloatBufferSizeInScientificMode*2]; + char buffer[k_maxNumberOfCharacters+ Float::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)*2]; const char * legend = "Interval ["; int legendLength = strlen(legend); strlcpy(buffer, legend, legendLength+1); float lowerBound = m_store->startOfBarAtIndex(m_selectedBarIndex); - int lowerBoundNumberOfChar = Float(lowerBound).convertFloatToText(buffer+legendLength, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + int lowerBoundNumberOfChar = Float(lowerBound).convertFloatToText(buffer+legendLength, Float::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); buffer[legendLength+lowerBoundNumberOfChar] = ';'; float upperBound = m_store->endOfBarAtIndex(m_selectedBarIndex); - int upperBoundNumberOfChar = Float(upperBound).convertFloatToText(buffer+legendLength+lowerBoundNumberOfChar+1, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + int upperBoundNumberOfChar = Float(upperBound).convertFloatToText(buffer+legendLength+lowerBoundNumberOfChar+1, Float::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); buffer[legendLength+lowerBoundNumberOfChar+upperBoundNumberOfChar+1] = '['; buffer[legendLength+lowerBoundNumberOfChar+upperBoundNumberOfChar+2] = 0; m_bannerView.setLegendAtIndex(buffer, 0); @@ -137,14 +137,14 @@ void HistogramController::reloadBannerView() { legendLength = strlen(legend); strlcpy(buffer, legend, legendLength+1); float size = m_store->heightOfBarAtIndex(m_selectedBarIndex); - Float(size).convertFloatToText(buffer+legendLength, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + Float(size).convertFloatToText(buffer+legendLength, Float::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); m_bannerView.setLegendAtIndex(buffer, 1); legend = "Frequence: "; legendLength = strlen(legend); strlcpy(buffer, legend, legendLength+1); float frequency = size/m_store->sumOfColumn(1); - Float(frequency).convertFloatToText(buffer+legendLength, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + Float(frequency).convertFloatToText(buffer+legendLength, Float::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); m_bannerView.setLegendAtIndex(buffer, 2); m_bannerView.layoutSubviews(); } diff --git a/apps/statistics/histogram_view.h b/apps/statistics/histogram_view.h index 3ddaf828e..3c2676420 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][Constant::FloatBufferSizeInScientificMode]; + char m_labels[k_maxNumberOfXLabels][Float::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)]; float m_highlightedBarStart; float m_highlightedBarEnd; }; diff --git a/apps/variable_box_controller.cpp b/apps/variable_box_controller.cpp index 85b2e47b0..5a77a8825 100644 --- a/apps/variable_box_controller.cpp +++ b/apps/variable_box_controller.cpp @@ -112,8 +112,8 @@ void VariableBoxController::ContentViewController::willDisplayCellForIndex(Table const Expression * expression = expressionForIndex(index); if (m_currentPage == Page::Scalar) { myCell->displayExpression(false); - char buffer[Constant::FloatBufferSizeInScientificMode]; - ((Float *)expression)->convertFloatToText(buffer, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + char buffer[Float::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)]; + ((Float *)expression)->convertFloatToText(buffer, Float::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits); myCell->setSubtitle(buffer); return; } diff --git a/poincare/include/poincare/float.h b/poincare/include/poincare/float.h index e3fad64d0..6c0fbaf54 100644 --- a/poincare/include/poincare/float.h +++ b/poincare/include/poincare/float.h @@ -21,14 +21,32 @@ public: Scientific, Decimal }; - void setNumberOfDigitsInMantissa(int numberOfDigits); - /* The parameter 'DisplayMode' refers to the way to display float 'scientific' or - * 'decimal'. The code only handles 'scientific' so far. If the buffer size is - * small, the function does nothing. */ - int convertFloatToText(char * buffer, int bufferSize, int numberOfDigitsInMantissa, DisplayMode mode = DisplayMode::Scientific) const; + void setNumberOfSignificantDigits(int numberOfDigits); + /* The parameter 'DisplayMode' refers to the way to display float 'scientific' + * or 'decimal'. The scientific mode returns float with style -1.2E2 whereas + * the decimal mode tries to return 'natural' float like (0.021) and switches + * to scientific mode if the float is too small or too big regarding the + * number of significant difits. If the buffer size is too small to display + * the right number of significant digits, the function forces the scientific + * mode and cap the number of significant digits to fit the buffer. If the + * buffer is too small to display any float, the text representing the float + * 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) */ + int convertFloatToText(char * buffer, int bufferSize, int numberOfSignificantDigits, DisplayMode mode = DisplayMode::Scientific) const; int writeTextInBuffer(char * buffer, int bufferSize) override; + constexpr static int bufferSizeForFloatsWithPrecision(int numberOfSignificantDigits) { + // The wors case is -1.234E-38 + return numberOfSignificantDigits + 7; + } private: - constexpr static int k_maxBufferLength = 14; + /* 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 decimal mode is always + * shorter. */ + constexpr static int k_maxBufferLength = 7+6+1; + /* convertFloatToTextPrivate return the string length of the buffer (does not count the 0 last char)*/ + int convertFloatToTextPrivate(char * buffer, int numberOfSignificantDigits, DisplayMode mode) const; /* 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 @@ -37,9 +55,8 @@ private: * 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); - float m_float; - int m_numberOfDigitsInMantissa; + int m_numberOfSignificantDigits; }; diff --git a/poincare/src/float.cpp b/poincare/src/float.cpp index ac8a72073..3981b1007 100644 --- a/poincare/src/float.cpp +++ b/poincare/src/float.cpp @@ -7,10 +7,9 @@ extern "C" { #include "layout/string_layout.h" #include - Float::Float(float f) : m_float(f), - m_numberOfDigitsInMantissa(7) + m_numberOfSignificantDigits(7) { } @@ -45,11 +44,11 @@ Float::Float(const char * integralPart, int integralPartLength, bool integralNeg m_float = (i + j*powf(10.0f, -ceilf(fractionalPartLength))) * powf(10.0f, l); - m_numberOfDigitsInMantissa = 7; + m_numberOfSignificantDigits = 7; } -void Float::setNumberOfDigitsInMantissa(int numberOfDigits) { - m_numberOfDigitsInMantissa = numberOfDigits; +void Float::setNumberOfSignificantDigits(int numberOfDigits) { + m_numberOfSignificantDigits = numberOfDigits; } Expression * Float::clone() const { @@ -70,7 +69,7 @@ Expression::Type Float::type() const { ExpressionLayout * Float::createLayout() const { char buffer[k_maxBufferLength]; - convertFloatToText(buffer, k_maxBufferLength, m_numberOfDigitsInMantissa); + convertFloatToText(buffer, k_maxBufferLength, m_numberOfSignificantDigits); int size = 0; while (buffer[size] != 0) { size++; @@ -84,11 +83,30 @@ bool Float::valueEquals(const Expression * e) const { } int Float::writeTextInBuffer(char * buffer, int bufferSize) { - return convertFloatToText(buffer, bufferSize, m_numberOfDigitsInMantissa); + return convertFloatToText(buffer, bufferSize, m_numberOfSignificantDigits); } int Float::convertFloatToText(char * buffer, int bufferSize, - int numberOfDigitsInMantissa, DisplayMode mode) const { + int numberOfSignificantDigits, DisplayMode mode) const { + char tempBuffer[k_maxBufferLength]; + int requiredLength = convertFloatToTextPrivate(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 == DisplayMode::Decimal && requiredLength >= bufferSize) { + requiredLength = convertFloatToTextPrivate(tempBuffer, numberOfSignificantDigits, DisplayMode::Scientific); + } + if (requiredLength >= bufferSize) { + requiredLength = convertFloatToTextPrivate(tempBuffer, numberOfSignificantDigits - requiredLength + bufferSize - 1, DisplayMode::Scientific); + } + requiredLength = requiredLength < bufferSize ? requiredLength : bufferSize; + strlcpy(buffer, tempBuffer, bufferSize); + return requiredLength; +} + +int Float::convertFloatToTextPrivate(char * buffer, int numberOfSignificantDigits, DisplayMode mode) const { if (isinf(m_float)) { buffer[0] = m_float > 0 ? '+' : '-'; buffer[1] = 'I'; @@ -116,26 +134,15 @@ int Float::convertFloatToText(char * buffer, int bufferSize, } DisplayMode displayMode = mode; - if ((exponentInBase10 >= numberOfDigitsInMantissa || exponentInBase10 <= -numberOfDigitsInMantissa) && mode == DisplayMode::Decimal) { + if ((exponentInBase10 >= numberOfSignificantDigits || exponentInBase10 <= -numberOfSignificantDigits) && mode == DisplayMode::Decimal) { displayMode = DisplayMode::Scientific; - numberOfDigitsInMantissa = numberOfDigitsInMantissa-2; - } - - /* We here assert that the buffer is long enough to display with the right - * number of digits in the mantissa. If numberOfDigitsInMantissa = 7, the - * worst case has the form -1.999999e-38 (7+6+1 char) for the scientific mode - * and -1.999999 (7+2+1 char) for the decimal mode. */ - if ((bufferSize <= 6 + numberOfDigitsInMantissa && displayMode == DisplayMode::Scientific) || - (bufferSize <= 2 + numberOfDigitsInMantissa && displayMode == DisplayMode::Decimal)) { - buffer[0] = 0; - return 0; } int decimalMarkerPosition = exponentInBase10 < 0 || displayMode == DisplayMode::Scientific ? 1 : exponentInBase10+1; // Number of char available for the mantissa - int availableCharsForMantissaWithoutSign = numberOfDigitsInMantissa + 1; + int availableCharsForMantissaWithoutSign = numberOfSignificantDigits + 1; int availableCharsForMantissaWithSign = m_float >= 0 ? availableCharsForMantissaWithoutSign : availableCharsForMantissaWithoutSign + 1; // Compute mantissa @@ -216,5 +223,4 @@ void Float::printBase10IntegerWithDecimalMarker(char * buffer, int bufferSize, buffer[endChar--] = '0'+digit; dividend = quotien; } while (endChar >= startChar); - } diff --git a/poincare/test/float.cpp b/poincare/test/float.cpp index c7210581d..ecc80170c 100644 --- a/poincare/test/float.cpp +++ b/poincare/test/float.cpp @@ -6,25 +6,41 @@ QUIZ_CASE(poincare_float_to_text) { char buffer [14]; Float(123.456f).convertFloatToText(buffer, 14, 7); - assert(strcmp(buffer, "1.23456e2") == 0); + assert(strcmp(buffer, "1.23456E2") == 0); Float(1.234567891011f).convertFloatToText(buffer, 14, 7); - assert(strcmp(buffer, "1.234568e0") == 0); + assert(strcmp(buffer, "1.234568E0") == 0); Float(2.0f).convertFloatToText(buffer, 14, 7); - assert(strcmp(buffer, "2.e0") == 0); + assert(strcmp(buffer, "2.0E0") == 0); Float(123456789.0f).convertFloatToText(buffer, 14, 7); - assert(strcmp(buffer, "1.234568e8") == 0); + assert(strcmp(buffer, "1.234568E8") == 0); Float(0.00000123456789f).convertFloatToText(buffer, 14, 7); - assert(strcmp(buffer, "1.234568e-6") == 0); + assert(strcmp(buffer, "1.234568E-6") == 0); Float(0.99f).convertFloatToText(buffer, 14, 7); - assert(strcmp(buffer, "9.9e-1") == 0); + assert(strcmp(buffer, "9.9E-1") == 0); Float(-123.456789f).convertFloatToText(buffer, 14, 7); - assert(strcmp(buffer, "-1.234568e2") == 0); + assert(strcmp(buffer, "-1.234568E2") == 0); Float(-0.000123456789f).convertFloatToText(buffer, 14, 7); - assert(strcmp(buffer, "-1.234568e-4") == 0); + assert(strcmp(buffer, "-1.234568E-4") == 0); Float(0.0f).convertFloatToText(buffer, 14, 7); - assert(strcmp(buffer, "0.e0") == 0); + assert(strcmp(buffer, "0.0E0") == 0); Float(10000000000000000000000000000.0f).convertFloatToText(buffer, 14, 7); - assert(strcmp(buffer, "1.e28") == 0); + assert(strcmp(buffer, "1.0E28") == 0); + Float(10000000000000000000000000000.0f).convertFloatToText(buffer, 14, 7, Float::DisplayMode::Decimal); + assert(strcmp(buffer, "1.0E28") == 0); + Float(1000000.0f).convertFloatToText(buffer, 14, 7, Float::DisplayMode::Decimal); + assert(strcmp(buffer, "1000000") == 0); + Float(10000000.0f).convertFloatToText(buffer, 14, 7, Float::DisplayMode::Decimal); + assert(strcmp(buffer, "1.0E7") == 0); + Float(0.000001f).convertFloatToText(buffer, 14, 7, Float::DisplayMode::Decimal); + assert(strcmp(buffer, "0.000001") == 0); + Float(0.0000001f).convertFloatToText(buffer, 14, 7, Float::DisplayMode::Decimal); + assert(strcmp(buffer, "1.0E-7") == 0); + char buffer2[6]; + Float(123.421f).convertFloatToText(buffer2, 6, 4, Float::DisplayMode::Decimal); + assert(strcmp(buffer2, "123.4") == 0); + char buffer3[6]; + Float(123.421f).convertFloatToText(buffer3, 6, 5, Float::DisplayMode::Decimal); + assert(strcmp(buffer3, "1.2E2") == 0); } QUIZ_CASE(poincare_float_approximate) {