[poincare] Redesign Float::convertTotext

Change-Id: Id27d9472147b5e443ee296feca891392fad735c8
This commit is contained in:
Émilie Feral
2017-01-11 16:07:58 +01:00
parent 245400015f
commit a74eef903a
23 changed files with 136 additions and 95 deletions

View File

@@ -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;

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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();

View File

@@ -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;
};

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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++] = ' ';

View File

@@ -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;
}

View File

@@ -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();

View File

@@ -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)];
};
}

View File

@@ -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();
}

View File

@@ -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;
};

View File

@@ -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);
}
}

View File

@@ -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();
}

View File

@@ -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;
};

View File

@@ -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;
}

View File

@@ -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;
};

View File

@@ -7,10 +7,9 @@ extern "C" {
#include "layout/string_layout.h"
#include <poincare/float.h>
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);
}

View File

@@ -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) {