[poincare] PrintFloat: take into account the distinction between char

and glyph length in ConvertFloatToText
This commit is contained in:
Émilie Feral
2019-09-25 17:31:30 +02:00
committed by LeaNumworks
parent d6ad694b76
commit 4d593a6149
37 changed files with 153 additions and 124 deletions

View File

@@ -43,7 +43,7 @@ bool GraphControllerHelper::privateMoveCursorHorizontally(Shared::CurveViewCurso
void GraphControllerHelper::reloadDerivativeInBannerViewForCursorOnFunction(Shared::CurveViewCursor * cursor, Ion::Storage::Record record) {
ExpiringPointer<ContinuousFunction> function = App::app()->functionStore()->modelForRecord(record);
constexpr size_t bufferSize = FunctionBannerDelegate::k_maxNumberOfCharacters+PrintFloat::bufferSizeForFloatsWithPrecision(Preferences::LargeNumberOfSignificantDigits);
constexpr size_t bufferSize = FunctionBannerDelegate::k_maxNumberOfCharacters+PrintFloat::charSizeForFloatsWithPrecision(Preferences::LargeNumberOfSignificantDigits);
char buffer[bufferSize];
const char * space = " ";
int numberOfChar = function->derivativeNameWithArgument(buffer, bufferSize);

View File

@@ -18,7 +18,7 @@ const char * IntersectionGraphController::title() {
void IntersectionGraphController::reloadBannerView() {
CalculationGraphController::reloadBannerView();
constexpr size_t bufferSize = FunctionBannerDelegate::k_maxNumberOfCharacters+Poincare::PrintFloat::bufferSizeForFloatsWithPrecision(Poincare::Preferences::LargeNumberOfSignificantDigits);
constexpr size_t bufferSize = FunctionBannerDelegate::k_maxNumberOfCharacters+Poincare::PrintFloat::charSizeForFloatsWithPrecision(Poincare::Preferences::LargeNumberOfSignificantDigits);
char buffer[bufferSize];
const char * space = " ";
const char * legend = "=";

View File

@@ -67,7 +67,7 @@ void TangentGraphController::reloadBannerView() {
}
FunctionBannerDelegate::reloadBannerViewForCursorOnFunction(m_cursor, m_record, Shared::FunctionApp::app()->functionStore(), AppsContainer::sharedAppsContainer()->globalContext());
GraphControllerHelper::reloadDerivativeInBannerViewForCursorOnFunction(m_cursor, m_record);
constexpr size_t bufferSize = FunctionBannerDelegate::k_maxNumberOfCharacters + PrintFloat::bufferSizeForFloatsWithPrecision(Preferences::LargeNumberOfSignificantDigits);
constexpr size_t bufferSize = FunctionBannerDelegate::k_maxNumberOfCharacters + PrintFloat::charSizeForFloatsWithPrecision(Preferences::LargeNumberOfSignificantDigits);
char buffer[bufferSize];
Poincare::Context * context = textFieldDelegateApp()->localContext();
@@ -76,7 +76,7 @@ void TangentGraphController::reloadBannerView() {
int legendLength = strlcpy(buffer, legend, bufferSize);
ExpiringPointer<ContinuousFunction> function = App::app()->functionStore()->modelForRecord(m_record);
double y = function->approximateDerivative(m_cursor->x(), context);
PoincareHelpers::ConvertFloatToText<double>(y, buffer + legendLength, PrintFloat::bufferSizeForFloatsWithPrecision(precision), precision);
PoincareHelpers::ConvertFloatToText<double>(y, buffer + legendLength, bufferSize - legendLength, precision);
m_bannerView->aView()->setText(buffer);
legend = "b=";
@@ -84,7 +84,7 @@ void TangentGraphController::reloadBannerView() {
Shared::TextFieldDelegateApp * myApp = textFieldDelegateApp();
assert(function->plotType() == Shared::ContinuousFunction::PlotType::Cartesian);
y = -y*m_cursor->x()+function->evaluate2DAtParameter(m_cursor->x(), myApp->localContext()).x2();
PoincareHelpers::ConvertFloatToText<double>(y, buffer + legendLength, PrintFloat::bufferSizeForFloatsWithPrecision(precision), precision);
PoincareHelpers::ConvertFloatToText<double>(y, buffer + legendLength, bufferSize - legendLength, precision);
m_bannerView->bView()->setText(buffer);
m_bannerView->reload();
}

View File

@@ -53,21 +53,22 @@ char intervalBracket(double value, bool opening) {
return std::isinf(value) == opening ? ']' : '[';
}
void writeInterval(char * buffer, int bufferSize, double min, double max, int numberOfSignificantDigits, Preferences::PrintFloatMode mode) {
int writeInterval(char * buffer, int bufferSize, double min, double max, int numberOfSignificantDigits, Preferences::PrintFloatMode mode) {
int numberOfChar = 0;
assert(bufferSize-1 > numberOfChar);
buffer[numberOfChar++] = intervalBracket(min, true);
int sizeRequiredForFloat = PrintFloat::bufferSizeForFloatsWithPrecision(numberOfSignificantDigits);
assert(sizeRequiredForFloat < bufferSize - numberOfChar);
numberOfChar += PrintFloat::ConvertFloatToText<double>(min, buffer+numberOfChar, sizeRequiredForFloat, numberOfSignificantDigits, mode);
int glyphLengthRequiredForFloat = PrintFloat::glyphLengthForFloatWithPrecision(numberOfSignificantDigits);
PrintFloat::TextLengths minLengths = PrintFloat::ConvertFloatToText<double>(min, buffer+numberOfChar, bufferSize - numberOfChar, glyphLengthRequiredForFloat, numberOfSignificantDigits, mode);
numberOfChar += minLengths.CharLength;
assert(bufferSize > numberOfChar);
numberOfChar += strlcpy(buffer+numberOfChar, ",", bufferSize-numberOfChar);
assert(sizeRequiredForFloat < bufferSize - numberOfChar);
numberOfChar += PrintFloat::ConvertFloatToText<double>(max, buffer+numberOfChar, sizeRequiredForFloat, numberOfSignificantDigits, mode);
PrintFloat::TextLengths maxLengths = PrintFloat::ConvertFloatToText<double>(max, buffer+numberOfChar, bufferSize - numberOfChar, glyphLengthRequiredForFloat, numberOfSignificantDigits, mode);
numberOfChar += maxLengths.CharLength;
assert(bufferSize-1 > numberOfChar);
buffer[numberOfChar++] = intervalBracket(max, false);
assert(bufferSize > numberOfChar);
strlcpy(buffer+numberOfChar, " ", bufferSize-numberOfChar);
return minLengths.GlyphLength + maxLengths. GlyphLength + 3 + 1; // Count "[,] " glyphs
}
void ListParameterController::willDisplayCellForIndex(HighlightCell * cell, int index) {
@@ -87,9 +88,9 @@ void ListParameterController::willDisplayCellForIndex(HighlightCell * cell, int
double max = function->tMax();
constexpr int bufferSize = BufferTextView::k_maxNumberOfChar;
char buffer[bufferSize];
writeInterval(buffer, bufferSize, min, max, Preferences::VeryShortNumberOfSignificantDigits, Preferences::sharedPreferences()->displayMode());
int numberOfAvailableChar = (m_functionDomain.bounds().width() - m_functionDomain.labelView()->bounds().width() - m_functionDomain.accessoryView()->bounds().width() - TableCell::k_labelMargin - TableCell::k_accessoryMargin)/KDFont::SmallFont->glyphSize().width();
if (UTF8Helper::StringGlyphLength(buffer) > numberOfAvailableChar) {
int glyphLength = writeInterval(buffer, bufferSize, min, max, Preferences::VeryShortNumberOfSignificantDigits, Preferences::sharedPreferences()->displayMode());
int numberOfAvailableGlyphs = (m_functionDomain.bounds().width() - m_functionDomain.labelView()->bounds().width() - m_functionDomain.accessoryView()->bounds().width() - TableCell::k_labelMargin - TableCell::k_accessoryMargin)/KDFont::SmallFont->glyphSize().width();
if (glyphLength > numberOfAvailableGlyphs) {
writeInterval(buffer, bufferSize, min, max, Preferences::VeryShortNumberOfSignificantDigits-1, Preferences::PrintFloatMode::Scientific);
}
m_functionDomain.setAccessoryText(buffer);

View File

@@ -248,17 +248,14 @@ void ValuesController::printEvaluationOfAbscissaAtColumn(double abscissa, int co
}
}
int numberOfChar = 0;
const int floatBufferSize = PrintFloat::bufferSizeForFloatsWithPrecision(Preferences::LargeNumberOfSignificantDigits);
if (isParametric) {
assert(numberOfChar < bufferSize-1);
buffer[numberOfChar++] = '(';
assert(floatBufferSize <= bufferSize-numberOfChar);
numberOfChar += PoincareHelpers::ConvertFloatToText<double>(evaluationX, buffer+numberOfChar, floatBufferSize, Preferences::LargeNumberOfSignificantDigits);
numberOfChar += PoincareHelpers::ConvertFloatToText<double>(evaluationX, buffer+numberOfChar, bufferSize - numberOfChar, Preferences::LargeNumberOfSignificantDigits);
assert(numberOfChar < bufferSize-1);
buffer[numberOfChar++] = ';';
}
assert(floatBufferSize <= bufferSize-numberOfChar);
numberOfChar += PoincareHelpers::ConvertFloatToText<double>(evaluationY, buffer+numberOfChar, floatBufferSize, Preferences::LargeNumberOfSignificantDigits);
numberOfChar += PoincareHelpers::ConvertFloatToText<double>(evaluationY, buffer+numberOfChar, bufferSize - numberOfChar, Preferences::LargeNumberOfSignificantDigits);
if (isParametric) {
assert(numberOfChar+1 < bufferSize-1);
buffer[numberOfChar++] = ')';

View File

@@ -1,6 +1,7 @@
#include "battery_test_controller.h"
#include <apps/shared/post_and_hardware_tests.h>
#include "app.h"
#include <apps/shared/poincare_helpers.h>
extern "C" {
#include <assert.h>
}
@@ -8,6 +9,7 @@ extern "C" {
#include <poincare/preferences.h>
using namespace Poincare;
using namespace Shared;
namespace HardwareTest {
@@ -43,12 +45,12 @@ void BatteryTestController::viewWillAppear() {
void BatteryTestController::updateBatteryState(float batteryLevel, bool batteryCharging) {
constexpr int precision = Preferences::LargeNumberOfSignificantDigits;
constexpr int sizeForPrecision = PrintFloat::bufferSizeForFloatsWithPrecision(precision);
constexpr int sizeForPrecision = PrintFloat::charSizeForFloatsWithPrecision(precision);
constexpr size_t bufferLevelSize = ContentView::k_maxNumberOfCharacters + sizeForPrecision;
char bufferLevel[bufferLevelSize];
const char * legend = "Battery level: ";
int legendLength = strlcpy(bufferLevel, legend, bufferLevelSize);
PrintFloat::ConvertFloatToText<float>(batteryLevel, bufferLevel+legendLength, sizeForPrecision, precision, Preferences::PrintFloatMode::Decimal);
PoincareHelpers::ConvertFloatToTextWithDisplayMode<float>(batteryLevel, bufferLevel+legendLength, sizeForPrecision, precision, Preferences::PrintFloatMode::Decimal);
m_view.batteryLevelTextView()->setText(bufferLevel);
constexpr size_t bufferChargingSize = ContentView::k_maxNumberOfCharacters + sizeForPrecision;

View File

@@ -180,9 +180,10 @@ void CalculationController::willDisplayCellAtLocation(HighlightCell * cell, int
return;
}
constexpr int precision = Preferences::LargeNumberOfSignificantDigits;
constexpr int bufferSize = PrintFloat::bufferSizeForFloatsWithPrecision(precision);
constexpr int bufferSize = PrintFloat::charSizeForFloatsWithPrecision(precision);
char buffer[bufferSize];
PrintFloat::ConvertFloatToText<double>(m_calculation->parameterAtIndex(i-1), buffer, bufferSize, precision, Preferences::PrintFloatMode::Decimal);
// FIXME: Leo has not decided yet if we should use the prefered mode instead of always using scientific mode
PoincareHelpers::ConvertFloatToTextWithDisplayMode<double>(m_calculation->parameterAtIndex(i-1), buffer, bufferSize, precision, Preferences::PrintFloatMode::Decimal);
field->setText(buffer);
}
}
@@ -283,9 +284,9 @@ void CalculationController::updateTitle() {
break;
}
constexpr int precision = Preferences::ShortNumberOfSignificantDigits;
constexpr size_t bufferSize = PrintFloat::bufferSizeForFloatsWithPrecision(precision);
constexpr int bufferSize = PrintFloat::charSizeForFloatsWithPrecision(precision);
char buffer[bufferSize];
PrintFloat::ConvertFloatToText<double>(m_distribution->parameterValueAtIndex(index), buffer, bufferSize, precision, Preferences::PrintFloatMode::Decimal);
PoincareHelpers::ConvertFloatToTextWithDisplayMode<double>(m_distribution->parameterValueAtIndex(index), buffer, bufferSize, precision, Preferences::PrintFloatMode::Decimal);
currentChar += strlcpy(m_titleBuffer+currentChar, buffer, k_titleBufferSize - currentChar);
if (currentChar >= k_titleBufferSize) {
break;

View File

@@ -179,7 +179,7 @@ void CalculationController::willDisplayCellAtLocation(HighlightCell * cell, int
double calculation1 = (m_store->*calculationMethods[j-1])(seriesNumber, 0);
double calculation2 = (m_store->*calculationMethods[j-1])(seriesNumber, 1);
EvenOddDoubleBufferTextCellWithSeparator * myCell = (EvenOddDoubleBufferTextCellWithSeparator *)cell;
constexpr int bufferSize = PrintFloat::bufferSizeForFloatsWithPrecision(numberSignificantDigits);
constexpr int bufferSize = PrintFloat::charSizeForFloatsWithPrecision(numberSignificantDigits);
char buffer[bufferSize];
PoincareHelpers::ConvertFloatToText<double>(calculation1, buffer, bufferSize, numberSignificantDigits);
myCell->setFirstText(buffer);
@@ -198,7 +198,7 @@ void CalculationController::willDisplayCellAtLocation(HighlightCell * cell, int
assert(j != k_regressionCellIndex);
CalculPointer calculationMethods[] = {&Store::doubleCastedNumberOfPairsOfSeries, &Store::covariance, &Store::columnProductSum};
double calculation = (m_store->*calculationMethods[j-k_totalNumberOfDoubleBufferRows-1])(seriesNumber);
constexpr int bufferSize = PrintFloat::bufferSizeForFloatsWithPrecision(numberSignificantDigits);
constexpr int bufferSize = PrintFloat::charSizeForFloatsWithPrecision(numberSignificantDigits);
char buffer[bufferSize];
PoincareHelpers::ConvertFloatToText<double>(calculation, buffer, bufferSize, numberSignificantDigits);
bufferCell->setText(buffer);
@@ -230,7 +230,7 @@ void CalculationController::willDisplayCellAtLocation(HighlightCell * cell, int
if (modelType == Model::Type::Linear) {
CalculPointer calculationMethods[2] = {&Store::correlationCoefficient, &Store::squaredCorrelationCoefficient};
double calculation = (m_store->*calculationMethods[j - k_regressionCellIndex - maxNumberCoefficients - 1])(seriesNumber);
constexpr int bufferSize = PrintFloat::bufferSizeForFloatsWithPrecision(numberSignificantDigits);
constexpr int bufferSize = PrintFloat::charSizeForFloatsWithPrecision(numberSignificantDigits);
char buffer[bufferSize];
PoincareHelpers::ConvertFloatToText<double>(calculation, buffer, bufferSize, numberSignificantDigits);
bufferCell->setText(buffer);
@@ -246,7 +246,7 @@ void CalculationController::willDisplayCellAtLocation(HighlightCell * cell, int
bufferCell->setText(I18n::translate(I18n::Message::Dash));
return;
} else {
constexpr int bufferSize = PrintFloat::bufferSizeForFloatsWithPrecision(numberSignificantDigits);
constexpr int bufferSize = PrintFloat::charSizeForFloatsWithPrecision(numberSignificantDigits);
char buffer[bufferSize];
PoincareHelpers::ConvertFloatToText<double>(coefficients[j - k_regressionCellIndex - 1], buffer, bufferSize, numberSignificantDigits);
bufferCell->setText(buffer);

View File

@@ -63,7 +63,7 @@ private:
static constexpr KDCoordinate k_cellHeight = 25;
static constexpr KDCoordinate k_titleCalculationCellWidth = Ion::Display::Width/2 - Metric::CommonRightMargin/2 - Metric::CommonLeftMargin/2;
// TODO: change 7 for KDFont::SmallFont->glyphSize().width()
static constexpr KDCoordinate k_minCalculationCellWidth = 7*2*(Poincare::PrintFloat::bufferSizeForFloatsWithPrecision(Poincare::Preferences::LargeNumberOfSignificantDigits)); //Calculation width should at least be able to hold to numbers with LargeNumberOfSignificantDigits.
static constexpr KDCoordinate k_minCalculationCellWidth = 7*2*(Poincare::PrintFloat::glyphLengthForFloatWithPrecision(Poincare::Preferences::LargeNumberOfSignificantDigits)); //Calculation width should at least be able to hold to numbers with LargeNumberOfSignificantDigits.
static constexpr KDCoordinate k_cubicCalculationCellWidth = maxCoordinate(150, k_minCalculationCellWidth); // Should hold aX^3+bX^2+cX+d
static constexpr KDCoordinate k_quarticCalculationCellWidth = maxCoordinate(195, k_minCalculationCellWidth ); // Should hold ? aX^4+bX^3+c*X^2+dX+e
static constexpr KDCoordinate k_margin = 8;

View File

@@ -105,7 +105,7 @@ Poincare::Context * GraphController::globalContext() {
void GraphController::reloadBannerView() {
// Set point equals: "P(...) ="
constexpr size_t bufferSize = k_maxNumberOfCharacters + PrintFloat::bufferSizeForFloatsWithPrecision(Preferences::LargeNumberOfSignificantDigits);
constexpr size_t bufferSize = k_maxNumberOfCharacters + PrintFloat::charSizeForFloatsWithPrecision(Preferences::LargeNumberOfSignificantDigits);
char buffer[bufferSize];
int numberOfChar = 0;
const char * legend = " P(";
@@ -119,7 +119,7 @@ void GraphController::reloadBannerView() {
assert(numberOfChar <= bufferSize);
numberOfChar += strlcpy(buffer + numberOfChar, legend, bufferSize - numberOfChar);
} else {
numberOfChar += PrintFloat::ConvertFloatToText<float>(std::round((float)*m_selectedDotIndex+1.0f), buffer + numberOfChar, bufferSize - numberOfChar, Preferences::ShortNumberOfSignificantDigits, Preferences::PrintFloatMode::Decimal);
numberOfChar += PoincareHelpers::ConvertFloatToTextWithDisplayMode<float>(std::round((float)*m_selectedDotIndex+1.0f), buffer + numberOfChar, bufferSize - numberOfChar, Preferences::ShortNumberOfSignificantDigits, Preferences::PrintFloatMode::Decimal);
}
legend = ") ";
assert(numberOfChar <= bufferSize);

View File

@@ -73,9 +73,7 @@ bool ValuesController::setDataAtLocation(double floatBody, int columnIndex, int
void ValuesController::printEvaluationOfAbscissaAtColumn(double abscissa, int columnIndex, char * buffer, const int bufferSize) {
Shared::ExpiringPointer<Sequence> sequence = functionStore()->modelForRecord(recordAtColumn(columnIndex));
Coordinate2D<double> xy = sequence->evaluateXYAtParameter(abscissa, textFieldDelegateApp()->localContext());
const int floatBufferSize = PrintFloat::bufferSizeForFloatsWithPrecision(Preferences::LargeNumberOfSignificantDigits);
assert(floatBufferSize <= bufferSize);
Shared::PoincareHelpers::ConvertFloatToText<double>(xy.x2(), buffer, floatBufferSize, Preferences::LargeNumberOfSignificantDigits);
Shared::PoincareHelpers::ConvertFloatToText<double>(xy.x2(), buffer, bufferSize, Preferences::LargeNumberOfSignificantDigits);
}
Shared::Interval * ValuesController::intervalAtColumn(int columnIndex) {

View File

@@ -177,10 +177,10 @@ void CurveView::computeLabels(Axis axis) {
float labelValue = labelValueAtIndex(axis, i);
/* Label cannot hold more than k_labelBufferMaxSize characters to prevent
* them from overprinting one another.*/
int labelMaxSize = k_labelBufferMaxSize;
int labelMaxGlyphLength = k_labelBufferMaxGlyphLength;
if (axis == Axis::Horizontal) {
float pixelsPerLabel = maxFloat(0.0f, ((float)Ion::Display::Width)/((float)axisLabelsCount) - k_labelMargin);
labelMaxSize = minInt(k_labelBufferMaxSize, pixelsPerLabel/k_font->glyphSize().width()+1);
labelMaxGlyphLength = minInt(k_labelBufferMaxGlyphLength, pixelsPerLabel/k_font->glyphSize().width());
}
if (labelValue < step && labelValue > -step) {
@@ -195,7 +195,8 @@ void CurveView::computeLabels(Axis axis) {
PrintFloat::ConvertFloatToText<float>(
labelValue,
labelBuffer,
labelMaxSize,
k_labelBufferMaxSize,
labelMaxGlyphLength,
k_numberSignificantDigits,
Preferences::PrintFloatMode::Decimal);
@@ -825,6 +826,7 @@ void CurveView::computeHorizontalExtremaLabels(bool increaseNumberOfSignificantD
labelValueAtIndex(axis, i),
label(axis, i),
k_labelBufferMaxSize,
k_labelBufferMaxGlyphLength,
increaseNumberOfSignificantDigits ? k_bigNumberSignificantDigits : k_numberSignificantDigits,
Preferences::PrintFloatMode::Decimal);
}

View File

@@ -50,7 +50,8 @@ protected:
constexpr static KDCoordinate k_labelGraduationLength = 6;
constexpr static int k_numberSignificantDigits = 6;
constexpr static int k_bigNumberSignificantDigits = Poincare::Preferences::LargeNumberOfSignificantDigits;
constexpr static int k_labelBufferMaxSize = 1 + k_bigNumberSignificantDigits + 3 + 3 + 1; // '-' + significant digits + '.' + "E-" + 3 digits + null-terminating char
constexpr static int k_labelBufferMaxSize = 1 + k_bigNumberSignificantDigits + 1 + Poincare::PrintFloat::k_specialECodePointByteLength + 1 + 3 + 1; // '-' + significant digits + '.' + "E" + '-' + 3 digits + null-terminating char
constexpr static int k_labelBufferMaxGlyphLength = 1 + k_bigNumberSignificantDigits + 3 + 3; // '-' + significant digits + ".E-" + 3 digits
constexpr static int k_maxNumberOfXLabels = CurveViewRange::k_maxNumberOfXGridUnits;
constexpr static int k_maxNumberOfYLabels = CurveViewRange::k_maxNumberOfYGridUnits;
constexpr static int k_externRectMargin = 2;

View File

@@ -78,7 +78,7 @@ void EditableCellTableViewController::willDisplayCellAtLocationWithDisplayMode(H
if (cellAtLocationIsEditable(i, j)) {
EvenOddEditableTextCell * myEditableValueCell = (EvenOddEditableTextCell *)cell;
assert(!myEditableValueCell->editableTextCell()->textField()->isEditing());
const int bufferSize = PrintFloat::bufferSizeForFloatsWithPrecision(Preferences::LargeNumberOfSignificantDigits);
const int bufferSize = PrintFloat::charSizeForFloatsWithPrecision(Preferences::LargeNumberOfSignificantDigits);
char buffer[bufferSize];
// Special case 1: last row
if (j == numberOfElementsInColumn(i) + 1) {
@@ -86,7 +86,7 @@ void EditableCellTableViewController::willDisplayCellAtLocationWithDisplayMode(H
* data */
buffer[0] = 0;
} else {
PrintFloat::ConvertFloatToText<double>(dataAtLocation(i, j), buffer, bufferSize, Preferences::LargeNumberOfSignificantDigits, floatDisplayMode);
PoincareHelpers::ConvertFloatToTextWithDisplayMode<double>(dataAtLocation(i, j), buffer, bufferSize, Preferences::LargeNumberOfSignificantDigits, floatDisplayMode);
}
myEditableValueCell->editableTextCell()->textField()->setText(buffer);
}

View File

@@ -121,9 +121,9 @@ void FloatParameterController<T>::willDisplayCellForIndex(HighlightCell * cell,
return;
}
constexpr int precision = Preferences::LargeNumberOfSignificantDigits;
constexpr int bufferSize = PrintFloat::bufferSizeForFloatsWithPrecision(precision);
constexpr int bufferSize = PrintFloat::charSizeForFloatsWithPrecision(precision);
char buffer[bufferSize];
PrintFloat::ConvertFloatToText<T>(parameterAtIndex(index), buffer, bufferSize, precision, Preferences::PrintFloatMode::Decimal);
PoincareHelpers::ConvertFloatToTextWithDisplayMode<T>(parameterAtIndex(index), buffer, bufferSize, precision, Preferences::PrintFloatMode::Decimal);
myCell->setAccessoryText(buffer);
}

View File

@@ -9,7 +9,7 @@ namespace Shared {
void FunctionBannerDelegate::reloadBannerViewForCursorOnFunction(CurveViewCursor * cursor, Ion::Storage::Record record, FunctionStore * functionStore, Poincare::Context * context) {
ExpiringPointer<Function> function = functionStore->modelForRecord(record);
constexpr int bufferSize = k_maxNumberOfCharacters+PrintFloat::bufferSizeForFloatsWithPrecision(Preferences::LargeNumberOfSignificantDigits);
constexpr int bufferSize = k_maxNumberOfCharacters+PrintFloat::charSizeForFloatsWithPrecision(Preferences::LargeNumberOfSignificantDigits);
char buffer[bufferSize];
const char * space = " ";
int numberOfChar = 0;
@@ -20,7 +20,7 @@ void FunctionBannerDelegate::reloadBannerViewForCursorOnFunction(CurveViewCursor
constexpr int precision = Preferences::MediumNumberOfSignificantDigits;
numberOfChar = PoincareHelpers::ConvertFloatToText<double>(cursor->t(), buffer, PrintFloat::bufferSizeForFloatsWithPrecision(precision), precision);
numberOfChar = PoincareHelpers::ConvertFloatToText<double>(cursor->t(), buffer, bufferSize, precision);
assert(numberOfChar <= bufferSize);
strlcpy(buffer+numberOfChar, space, bufferSize - numberOfChar);
bannerView()->abscissaValue()->setText(buffer);

View File

@@ -16,7 +16,12 @@ inline Poincare::Layout CreateLayout(const Poincare::Expression e) {
template <class T>
inline int ConvertFloatToText(T d, char * buffer, int bufferSize, int numberOfSignificantDigits) {
return Poincare::PrintFloat::ConvertFloatToText(d, buffer, bufferSize, numberOfSignificantDigits, Poincare::Preferences::sharedPreferences()->displayMode());
return Poincare::PrintFloat::ConvertFloatToText(d, buffer, bufferSize, Poincare::PrintFloat::glyphLengthForFloatWithPrecision(numberOfSignificantDigits), numberOfSignificantDigits, Poincare::Preferences::sharedPreferences()->displayMode()).CharLength;
}
template <class T>
inline int ConvertFloatToTextWithDisplayMode(T d, char * buffer, int bufferSize, int numberOfSignificantDigits, Poincare::Preferences::PrintFloatMode displayMode) {
return Poincare::PrintFloat::ConvertFloatToText(d, buffer, bufferSize, Poincare::PrintFloat::glyphLengthForFloatWithPrecision(numberOfSignificantDigits), numberOfSignificantDigits, displayMode).CharLength;
}
inline int Serialize(const Poincare::Expression e, char * buffer, int bufferSize, int numberOfSignificantDigits = Poincare::PrintFloat::k_numberOfStoredSignificantDigits) {

View File

@@ -179,9 +179,9 @@ void SumGraphController::LegendView::setLegendMessage(I18n::Message message, Ste
void SumGraphController::LegendView::setEditableZone(double d) {
constexpr int precision = Preferences::MediumNumberOfSignificantDigits;
constexpr int bufferSize = PrintFloat::bufferSizeForFloatsWithPrecision(precision);
constexpr int bufferSize = PrintFloat::charSizeForFloatsWithPrecision(precision);
char buffer[bufferSize];
PrintFloat::ConvertFloatToText<double>(d, buffer, bufferSize, precision, Preferences::PrintFloatMode::Decimal);
PoincareHelpers::ConvertFloatToTextWithDisplayMode<double>(d, buffer, bufferSize, precision, Preferences::PrintFloatMode::Decimal);
m_editableZone.setText(buffer);
}
@@ -193,28 +193,28 @@ void SumGraphController::LegendView::setSumSymbol(Step step, double start, doubl
m_sumLayout = LayoutHelper::CodePointString(sigma, sigmaLength);
} else if (step == Step::SecondParameter) {
constexpr int precision = Preferences::MediumNumberOfSignificantDigits;
constexpr int bufferSize = PrintFloat::bufferSizeForFloatsWithPrecision(precision);
constexpr int bufferSize = PrintFloat::charSizeForFloatsWithPrecision(precision);
char buffer[bufferSize];
PrintFloat::ConvertFloatToText<double>(start, buffer, bufferSize, precision, Preferences::PrintFloatMode::Decimal);
PoincareHelpers::ConvertFloatToTextWithDisplayMode<double>(start, buffer, bufferSize, precision, Preferences::PrintFloatMode::Decimal);
m_sumLayout = CondensedSumLayout::Builder(
LayoutHelper::CodePointString(sigma, sigmaLength),
LayoutHelper::String(buffer, strlen(buffer), k_font),
EmptyLayout::Builder(EmptyLayoutNode::Color::Yellow, false, k_font, false));
} else {
constexpr int precision = Preferences::LargeNumberOfSignificantDigits;
constexpr int sizeForPrecision = PrintFloat::bufferSizeForFloatsWithPrecision(precision);
constexpr int sizeForPrecision = PrintFloat::charSizeForFloatsWithPrecision(precision);
constexpr int bufferSize = 2 + sizeForPrecision;
char buffer[bufferSize];
PrintFloat::ConvertFloatToText<double>(start, buffer, sizeForPrecision, precision, Preferences::PrintFloatMode::Decimal);
PoincareHelpers::ConvertFloatToTextWithDisplayMode<double>(start, buffer, bufferSize, precision, Preferences::PrintFloatMode::Decimal);
Layout start = LayoutHelper::String(buffer, strlen(buffer), k_font);
PrintFloat::ConvertFloatToText<double>(end, buffer, sizeForPrecision, precision, Preferences::PrintFloatMode::Decimal);
PoincareHelpers::ConvertFloatToTextWithDisplayMode<double>(end, buffer, bufferSize, precision, Preferences::PrintFloatMode::Decimal);
Layout end = LayoutHelper::String(buffer, strlen(buffer), k_font);
m_sumLayout = CondensedSumLayout::Builder(
LayoutHelper::CodePointString(sigma, sigmaLength),
start,
end);
strlcpy(buffer, "= ", 3);
PoincareHelpers::ConvertFloatToText<double>(result, buffer+2, sizeForPrecision, precision);
PoincareHelpers::ConvertFloatToText<double>(result, buffer+2, bufferSize-2, precision);
m_sumLayout = HorizontalLayout::Builder(
m_sumLayout,
functionLayout,

View File

@@ -56,7 +56,7 @@ private:
void setEditableZone(double d);
void setSumSymbol(Step step, double start, double end, double result, Poincare::Layout functionLayout);
private:
constexpr static KDCoordinate k_editableZoneBufferSize = Poincare::PrintFloat::k_maxFloatBufferSize;
constexpr static KDCoordinate k_editableZoneBufferSize = Poincare::PrintFloat::k_maxFloatCharSize;
constexpr static KDCoordinate k_legendHeight = 35;
constexpr static const KDFont * k_font = KDFont::SmallFont;
static KDCoordinate editableZoneWidth() { return 12*k_font->glyphSize().width(); }

View File

@@ -124,7 +124,7 @@ void ValuesController::willDisplayCellAtLocation(HighlightCell * cell, int i, in
willDisplayCellAtLocationWithDisplayMode(cell, i, j, Preferences::sharedPreferences()->displayMode());
// The cell is not a title cell and not editable
if (typeAtLocation(i,j) == k_notEditableValueCellType) {
constexpr int bufferSize = 2*PrintFloat::bufferSizeForFloatsWithPrecision(Preferences::LargeNumberOfSignificantDigits)+3;
constexpr int bufferSize = 2*PrintFloat::charSizeForFloatsWithPrecision(Preferences::LargeNumberOfSignificantDigits)+3;
char buffer[bufferSize]; // The largest buffer holds (-1.234567E-123;-1.234567E-123)
// Special case: last row
if (j == numberOfElementsInColumn(i) + 1) {

View File

@@ -20,7 +20,7 @@ public:
protected:
View * subviewAtIndex(int index) override;
private:
constexpr static KDCoordinate k_abscissaBufferSize = Poincare::PrintFloat::k_maxFloatBufferSize;
constexpr static KDCoordinate k_abscissaBufferSize = Poincare::PrintFloat::k_maxFloatCharSize;
int numberOfSubviews() const override { return k_numberOfSubviews; }
BufferTextView m_abscissaSymbol;
TextField m_abscissaValue;

View File

@@ -189,7 +189,7 @@ void SolutionsController::willDisplayCellAtLocation(HighlightCell * cell, int i,
if (m_equationStore->type() == EquationStore::Type::Monovariable) {
EvenOddBufferTextCell * valueCell = static_cast<EvenOddBufferTextCell *>(cell);
constexpr int precision = Preferences::LargeNumberOfSignificantDigits;
constexpr int bufferSize = PrintFloat::bufferSizeForFloatsWithPrecision(precision);
constexpr int bufferSize = PrintFloat::charSizeForFloatsWithPrecision(precision);
char bufferValue[bufferSize];
PoincareHelpers::ConvertFloatToText<double>(m_equationStore->approximateSolutionAtIndex(j), bufferValue, bufferSize, precision);
valueCell->setText(bufferValue);

View File

@@ -51,12 +51,12 @@ void BoxController::reloadBannerView() {
// Set calculation result
assert(UTF8Decoder::CharSizeOfCodePoint(' ') == 1);
constexpr int precision = Preferences::LargeNumberOfSignificantDigits;
constexpr int bufferSize = PrintFloat::bufferSizeForFloatsWithPrecision(precision) + 1;
constexpr int bufferSize = PrintFloat::charSizeForFloatsWithPrecision(precision) + 1;
char buffer[bufferSize];
CalculPointer calculationMethods[5] = {&Store::minValue, &Store::firstQuartile, &Store::median, &Store::thirdQuartile,
&Store::maxValue};
double calculation = (m_store->*calculationMethods[selectedQuantile])(selectedSeriesIndex());
int numberOfChar = PoincareHelpers::ConvertFloatToText<double>(calculation, buffer, bufferSize - 1, precision);
int numberOfChar = PoincareHelpers::ConvertFloatToText<double>(calculation, buffer, bufferSize, precision);
buffer[numberOfChar++] = ' ';
assert(numberOfChar <= bufferSize - 1);
buffer[numberOfChar] = 0;

View File

@@ -100,7 +100,7 @@ void CalculationController::willDisplayCellAtLocation(HighlightCell * cell, int
double calculation = (m_store->*calculationMethods[j-1])(seriesIndex);
EvenOddBufferTextCell * calculationCell = static_cast<EvenOddBufferTextCell *>(cell);
constexpr int precision = Preferences::LargeNumberOfSignificantDigits;
constexpr int bufferSize = PrintFloat::bufferSizeForFloatsWithPrecision(precision);
constexpr int bufferSize = PrintFloat::charSizeForFloatsWithPrecision(precision);
char buffer[bufferSize];
PoincareHelpers::ConvertFloatToText<double>(calculation, buffer, bufferSize, precision);
calculationCell->setText(buffer);

View File

@@ -55,7 +55,7 @@ private:
static constexpr KDCoordinate k_cellHeight = 20;
static constexpr KDCoordinate k_calculationTitleCellWidth = 175;
// TODO: change 7 for KDFont::SmallFont->glyphSize().width()
static constexpr KDCoordinate k_calculationCellWidth = 7*(Poincare::PrintFloat::bufferSizeForFloatsWithPrecision(Poincare::Preferences::LargeNumberOfSignificantDigits));
static constexpr KDCoordinate k_calculationCellWidth = 7*(Poincare::PrintFloat::glyphLengthForFloatWithPrecision(Poincare::Preferences::LargeNumberOfSignificantDigits));
static constexpr KDCoordinate k_margin = 8;
static constexpr KDCoordinate k_scrollBarMargin = Metric::CommonRightMargin;

View File

@@ -96,7 +96,7 @@ void HistogramController::reloadBannerView() {
return;
}
constexpr int precision = Preferences::LargeNumberOfSignificantDigits;
constexpr size_t bufferSize = k_maxNumberOfCharacters + 2 * PrintFloat::bufferSizeForFloatsWithPrecision(precision);
constexpr size_t bufferSize = k_maxNumberOfCharacters + 2 * PrintFloat::charSizeForFloatsWithPrecision(precision);
char buffer[bufferSize] = "";
int numberOfChar = 0;

View File

@@ -32,7 +32,7 @@ public:
private:
constexpr static KDCoordinate k_separatorThickness = Metric::CellSeparatorThickness;
TextField m_textField;
char m_textBody[Poincare::PrintFloat::k_maxFloatBufferSize];
char m_textBody[Poincare::PrintFloat::k_maxFloatCharSize];
KDCoordinate m_topMargin;
KDCoordinate m_rightMargin;
KDCoordinate m_bottomMargin;

View File

@@ -30,7 +30,7 @@ public:
private:
void layoutSubviews() override;
TextField m_textField;
char m_textBody[Poincare::PrintFloat::k_maxFloatBufferSize];
char m_textBody[Poincare::PrintFloat::k_maxFloatCharSize];
};
#endif

View File

@@ -8,7 +8,7 @@ EditableTextCell::EditableTextCell(Responder * parentResponder, InputEventHandle
const KDFont * font, float horizontalAlignment, float verticalAlignment, KDColor textColor, KDColor backgroundColor, KDCoordinate topMargin, KDCoordinate rightMargin, KDCoordinate bottomMargin, KDCoordinate leftMargin) :
HighlightCell(),
Responder(parentResponder),
m_textField(this, m_textBody, Poincare::PrintFloat::k_maxFloatBufferSize, TextField::maxBufferSize(), inputEventHandlerDelegate, delegate, font, horizontalAlignment, verticalAlignment, textColor, backgroundColor),
m_textField(this, m_textBody, Poincare::PrintFloat::k_maxFloatCharSize, TextField::maxBufferSize(), inputEventHandlerDelegate, delegate, font, horizontalAlignment, verticalAlignment, textColor, backgroundColor),
m_topMargin(topMargin),
m_rightMargin(rightMargin),
m_bottomMargin(bottomMargin),

View File

@@ -5,7 +5,7 @@
MessageTableCellWithEditableText::MessageTableCellWithEditableText(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, TextFieldDelegate * textFieldDelegate, I18n::Message message) :
Responder(parentResponder),
MessageTableCell(message),
m_textField(this, m_textBody, Poincare::PrintFloat::k_maxFloatBufferSize, TextField::maxBufferSize(), inputEventHandlerDelegate, textFieldDelegate, KDFont::LargeFont, 1.0f, 0.5f)
m_textField(this, m_textBody, Poincare::PrintFloat::k_maxFloatCharSize, TextField::maxBufferSize(), inputEventHandlerDelegate, textFieldDelegate, KDFont::LargeFont, 1.0f, 0.5f)
{
m_textBody[0] = '\0';
}

View File

@@ -16,8 +16,9 @@ void ADC(const char * input) {
float result = Ion::Battery::voltage();
constexpr int precision = 8;
constexpr int bufferSize = Poincare::PrintFloat::bufferSizeForFloatsWithPrecision(precision);
constexpr int glyphLength = Poincare::PrintFloat::glyphLengthForFloatWithPrecision(precision);
char responseBuffer[bufferSize+4] = {'A', 'D', 'C', '='}; // ADC=
Poincare::PrintFloat::ConvertFloatToText<float>(result, responseBuffer+4, bufferSize, precision, Poincare::Preferences::PrintFloatMode::Decimal);
Poincare::PrintFloat::ConvertFloatToText<float>(result, responseBuffer+4, bufferSize, glyphLength, precision, Poincare::Preferences::PrintFloatMode::Decimal);
reply(responseBuffer);
}

View File

@@ -13,11 +13,22 @@ public:
constexpr static int k_numberOfStoredSignificantDigits = 14;
// ᴇ and are 3 bytes long
constexpr static int k_specialECodePointByteLength = 3;
/* We here define the buffer size to write the longest float possible.
/* We here define the glyph length and the buffer size to write the longest
* float possible.
* At maximum, the number has 15 significant digits so, in the worst case it
* has the form -1.99999999999999ᴇ-308 (2+15+3+1+3 char) (the auto mode is
* has the form -1.99999999999999ᴇ-308 (2+15+3+1+3 char) (the decimal mode is
* always shorter. */
constexpr static int k_maxFloatBufferSize = 2+k_numberOfStoredSignificantDigits+k_specialECodePointByteLength+1+3+1;
constexpr static int k_maxFloatGlyphLength = 2 // '-' and '.'
+ k_numberOfStoredSignificantDigits // mantissa
+ 1 // ᴇ
+ 1 // exponant '-'
+ 3; // exponant
constexpr static int k_maxFloatCharSize = 2 // '-' and '.'
+ k_numberOfStoredSignificantDigits // mantissa
+ k_specialECodePointByteLength // ᴇ
+ 1 // exponant '-'
+ 3 // exponant
+ 1; // null-terminated
constexpr static int glyphLengthForFloatWithPrecision(int numberOfSignificantDigits) {
// The worst case is -1.234ᴇ-328
@@ -27,23 +38,28 @@ public:
+ 1 // '-'
+ 3; // exponant
}
constexpr static int bufferSizeForFloatsWithPrecision(int numberOfSignificantDigits) {
constexpr static int charSizeForFloatsWithPrecision(int numberOfSignificantDigits) {
// The worst case is -1.234ᴇ-328
return 2 // '-' and '.'
+ numberOfSignificantDigits // mantissa
+ k_specialECodePointByteLength // ᴇ
+ 1 // '-'
+ 1 // exponant '-'
+ 3 // exponant
+ 1; // null-terminated buffer
+ 1; // null-terminated
}
struct TextLengths
{
int CharLength;
int GlyphLength;
};
/* If the buffer size is too small to display the right number of significant
* digits, the function forces the scientific mode. If the buffer is still too
* small, the text representing the float is empty.
* ConvertFloatToText returns the number of characters that have been written
* in buffer (excluding the last \0 character). */
template <class T>
static int ConvertFloatToText(T d, char * buffer, int bufferSize, int numberOfSignificantDigits, Preferences::PrintFloatMode mode);
static TextLengths ConvertFloatToText(T d, char * buffer, int bufferSize, int availableGlyphLength, int numberOfSignificantDigits, Preferences::PrintFloatMode mode);
// Engineering notation
static int EngineeringExponentFromBase10Exponent(int exponent);
@@ -59,7 +75,7 @@ public:
private:
template <class T>
static int ConvertFloatToTextPrivate(T f, char * buffer, int bufferSize, int numberOfSignificantDigits, Preferences::PrintFloatMode mode, int * numberOfRemovedZeros);
static TextLengths ConvertFloatToTextPrivate(T f, char * buffer, int bufferSize, int availableGlyphLength, int numberOfSignificantDigits, Preferences::PrintFloatMode mode);
class Long final {
public:

View File

@@ -31,13 +31,13 @@ int FloatNode<T>::simplificationOrderSameType(const ExpressionNode * e, bool asc
template<typename T>
int FloatNode<T>::serialize(char * buffer, int bufferSize, Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const {
return PrintFloat::ConvertFloatToText(m_value, buffer, bufferSize, numberOfSignificantDigits, floatDisplayMode);
return PrintFloat::ConvertFloatToText(m_value, buffer, bufferSize, PrintFloat::k_maxFloatGlyphLength, numberOfSignificantDigits, floatDisplayMode).CharLength;
}
template<typename T>
Layout FloatNode<T>::createLayout(Preferences::PrintFloatMode floatDisplayMode, int numberOfSignificantDigits) const {
char buffer[PrintFloat::k_maxFloatBufferSize];
int numberOfChars = serialize(buffer, PrintFloat::k_maxFloatBufferSize, floatDisplayMode, numberOfSignificantDigits);
char buffer[PrintFloat::k_maxFloatCharSize];
int numberOfChars = serialize(buffer, PrintFloat::k_maxFloatCharSize, floatDisplayMode, numberOfSignificantDigits);
return LayoutHelper::String(buffer, numberOfChars);
}

View File

@@ -24,7 +24,7 @@ int InfinityNode::serialize(char * buffer, int bufferSize, Preferences::PrintFlo
if (bufferSize == 0) {
return -1;
}
return PrintFloat::ConvertFloatToText<float>(m_negative ? -INFINITY : INFINITY, buffer, bufferSize, numberOfSignificantDigits, floatDisplayMode);
return PrintFloat::ConvertFloatToText<float>(m_negative ? -INFINITY : INFINITY, buffer, bufferSize, PrintFloat::k_maxFloatGlyphLength, numberOfSignificantDigits, floatDisplayMode).CharLength;
}
template<typename T> Evaluation<T> InfinityNode::templatedApproximate() const {

View File

@@ -166,7 +166,7 @@ int Integer::serialize(char * buffer, int bufferSize) const {
return 0;
}
if (isOverflow()) {
return PrintFloat::ConvertFloatToText<float>(m_negative ? -INFINITY : INFINITY, buffer, bufferSize, PrintFloat::k_numberOfStoredSignificantDigits, Preferences::PrintFloatMode::Decimal);
return PrintFloat::ConvertFloatToText<float>(m_negative ? -INFINITY : INFINITY, buffer, bufferSize, PrintFloat::k_maxFloatGlyphLength, PrintFloat::k_numberOfStoredSignificantDigits, Preferences::PrintFloatMode::Decimal).CharLength;
}
Integer base(10);
@@ -185,7 +185,7 @@ int Integer::serialize(char * buffer, int bufferSize) const {
d.quotient.isZero())) {
char c = char_from_digit(d.remainder.isZero() ? 0 : d.remainder.digit(0));
if (length >= bufferSize-1) {
return PrintFloat::ConvertFloatToText<float>(NAN, buffer, bufferSize, PrintFloat::k_numberOfStoredSignificantDigits, Preferences::PrintFloatMode::Decimal);
return PrintFloat::ConvertFloatToText<float>(NAN, buffer, bufferSize, PrintFloat::k_maxFloatGlyphLength, PrintFloat::k_numberOfStoredSignificantDigits, Preferences::PrintFloatMode::Decimal).CharLength;
}
length += SerializationHelper::CodePoint(buffer + length, bufferSize - length, c);
d = udiv(d.quotient, base);

View File

@@ -100,7 +100,7 @@ void PrintFloat::PrintLongWithDecimalMarker(char * buffer, int bufferLength, Lon
* in first position. When called by ConvertFloatToText, the buffer length is
* always > 0 as we asserted a minimal number of available chars. */
assert(bufferLength > 0 && decimalMarkerPosition != 0);
constexpr int tempBufferSize = PrintFloat::k_maxFloatBufferSize;
constexpr int tempBufferSize = PrintFloat::k_maxFloatCharSize;
char tempBuffer[tempBufferSize];
int intLength = i.serialize(tempBuffer, tempBufferSize);
int firstDigitChar = UTF8Helper::CodePointIs(tempBuffer, '-') ? 1 : 0;
@@ -128,30 +128,30 @@ void PrintFloat::PrintLongWithDecimalMarker(char * buffer, int bufferLength, Lon
}
template <class T>
int PrintFloat::ConvertFloatToText(T f, char * buffer, int bufferSize,
PrintFloat::TextLengths PrintFloat::ConvertFloatToText(T f, char * buffer, int bufferSize, int glyphLength,
int numberOfSignificantDigits, Preferences::PrintFloatMode mode)
{
assert(numberOfSignificantDigits > 0);
assert(bufferSize > 0);
/* Truncate the buffer if needed.
/* Assert that the glyphLength is capped.
* Example: 1+1.234E-30+... in decimal mode, because we do not want the fill
* the buffer with the decimal version of 1.234E-30. */
int truncatedBufferSize = minInt(PrintFloat::k_maxFloatBufferSize, bufferSize);
assert(glyphLength < k_maxFloatGlyphLength);
int numberOfZerosRemoved = 0;
int requiredLength = ConvertFloatToTextPrivate(f, buffer, truncatedBufferSize, numberOfSignificantDigits, mode, &numberOfZerosRemoved);
TextLengths requiredLengths = ConvertFloatToTextPrivate(f, buffer, bufferSize, glyphLength, numberOfSignificantDigits, mode);
/* If the required buffer size overflows the buffer size, we force the display
* mode to scientific. */
if (mode == Preferences::PrintFloatMode::Decimal && requiredLength >= truncatedBufferSize) {
requiredLength = ConvertFloatToTextPrivate(f, buffer, truncatedBufferSize, numberOfSignificantDigits, Preferences::PrintFloatMode::Scientific, &numberOfZerosRemoved);
if (mode == Preferences::PrintFloatMode::Decimal && (requiredLengths.CharLength > bufferSize - 1 || requiredLengths.GlyphLength > glyphLength)) {
requiredLengths = ConvertFloatToTextPrivate(f, buffer, bufferSize, glyphLength, numberOfSignificantDigits, Preferences::PrintFloatMode::Scientific);
}
if (requiredLength >= truncatedBufferSize) {
if (requiredLengths.CharLength > bufferSize - 1 || requiredLengths.GlyphLength > glyphLength) {
buffer[0] = 0;
return 0;
/* We still return the required sizes even if we could not write the float
* in the buffer in order to indicate that we overflew the buffer. */
}
return requiredLength;
return requiredLengths;
}
int PrintFloat::EngineeringExponentFromBase10Exponent(int exponent) {
@@ -163,37 +163,43 @@ int PrintFloat::EngineeringExponentFromBase10Exponent(int exponent) {
}
template <class T>
int PrintFloat::ConvertFloatToTextPrivate(T f, char * buffer, int bufferSize, int numberOfSignificantDigits, Preferences::PrintFloatMode mode, int * numberOfRemovedZeros) {
PrintFloat::TextLengths PrintFloat::ConvertFloatToTextPrivate(T f, char * buffer, int bufferSize, int glyphLength, int numberOfSignificantDigits, Preferences::PrintFloatMode mode) {
assert(numberOfSignificantDigits > 0);
assert(bufferSize > 0);
assert(glyphLength > 0 && glyphLength < k_maxFloatGlyphLength);
int availableCharLength = minInt(bufferSize-1, glyphLength);
TextLengths exceptionResult = {.CharLength = bufferSize, .GlyphLength = glyphLength+1};
//TODO: accelerate for f between 0 and 10 ?
if (std::isinf(f)) {
// Infinity
bool writeMinusSign = f < 0;
assert(UTF8Decoder::CharSizeOfCodePoint('-') == 1);
int requiredLength = (writeMinusSign ? 1 : 0) + Infinity::NameSize() - 1;
if (requiredLength > bufferSize - 1) {
int requiredCharLength = (writeMinusSign ? 1 : 0) + Infinity::NameSize() - 1;
TextLengths requiredTextLengths = {.CharLength = requiredCharLength, .GlyphLength = requiredCharLength};
if (requiredCharLength > availableCharLength) {
// We will not be able to print
return requiredLength;
return requiredTextLengths;
}
// Write inf or -inf
int currentChar = 0;
if (f < 0) {
currentChar+= SerializationHelper::CodePoint(buffer, bufferSize, '-');
currentChar += SerializationHelper::CodePoint(buffer, bufferSize, '-');
}
assert(bufferSize - currentChar > 0);
strlcpy(buffer+currentChar, Infinity::Name(), bufferSize-currentChar);
return requiredLength;
return requiredTextLengths;
}
if (std::isnan(f)) {
// Nan
constexpr int requiredLength = Undefined::NameSize() - 1;
if (requiredLength - 1 > bufferSize - 1) {
constexpr int requiredCharLength = Undefined::NameSize() - 1;
constexpr TextLengths requiredTextLengths = {.CharLength = requiredCharLength, .GlyphLength = requiredCharLength};
if (requiredCharLength > availableCharLength) {
// We will not be able to print
return requiredLength;
return requiredTextLengths;
}
return strlcpy(buffer, Undefined::Name(), bufferSize);
strlcpy(buffer, Undefined::Name(), bufferSize);
return requiredTextLengths;
}
int exponentInBase10 = IEEE754<T>::exponentBase10(f);
@@ -227,7 +233,7 @@ int PrintFloat::ConvertFloatToTextPrivate(T f, char * buffer, int bufferSize, in
* displaying 12345 with 2 significant digis in Decimal mode for instance.
* This exception is caught by ConvertFloatToText and forces the mode to
* Scientific */
return bufferSize + 1;
return exceptionResult;
}
// Correct the number of digits in mantissa after rounding
@@ -275,9 +281,6 @@ int PrintFloat::ConvertFloatToTextPrivate(T f, char * buffer, int bufferSize, in
assert(mantissa < 1000);
Long::MultiplySmallLongByTen(dividend);
}
if (numberOfRemovedZeros != nullptr) {
*numberOfRemovedZeros = -numberOfZeroesToAdd;
}
}
}
if (removeZeroes) {
@@ -298,12 +301,9 @@ int PrintFloat::ConvertFloatToTextPrivate(T f, char * buffer, int bufferSize, in
Long::DivisionByTen(dividend, &quotient, &digit);
numberOfZerosRemoved++;
}
if (numberOfCharsForMantissaWithoutSign > bufferSize - 1) {
if (numberOfCharsForMantissaWithoutSign > availableCharLength) {
// Escape now if the true number of needed digits is not required
return bufferSize + 1;
}
if (numberOfRemovedZeros != nullptr) {
*numberOfRemovedZeros = numberOfZerosRemoved;
return exceptionResult;
}
}
@@ -317,9 +317,9 @@ int PrintFloat::ConvertFloatToTextPrivate(T f, char * buffer, int bufferSize, in
assert(UTF8Decoder::CharSizeOfCodePoint('.') == 1);
numberOfCharsForMantissaWithoutSign++;
}
if (numberOfCharsForMantissaWithoutSign > bufferSize - 1) {
if (numberOfCharsForMantissaWithoutSign > availableCharLength) {
// Escape now if the true number of needed digits is not required
return bufferSize + 1;
return exceptionResult;
}
/* Find the position of the decimal marker position */
@@ -340,9 +340,9 @@ int PrintFloat::ConvertFloatToTextPrivate(T f, char * buffer, int bufferSize, in
/* Part III: Sign */
int numberOfCharsForMantissaWithSign = numberOfCharsForMantissaWithoutSign + (f >= 0 ? 0 : 1);
if (numberOfCharsForMantissaWithSign > bufferSize - 1) {
if (numberOfCharsForMantissaWithSign > availableCharLength) {
// Exception 2: we will overflow the buffer
return bufferSize + 1;
return exceptionResult;
}
/* Part IV: Exponent */
@@ -360,15 +360,20 @@ int PrintFloat::ConvertFloatToTextPrivate(T f, char * buffer, int bufferSize, in
assert(UTF8Decoder::CharSizeOfCodePoint('-') == 1);
// Print mantissa
bool doNotWriteExponent = (mode == Preferences::PrintFloatMode::Decimal) || (exponent == 0);
int neededNumberOfChars = numberOfCharsForMantissaWithSign + (doNotWriteExponent ? 0 : UTF8Decoder::CharSizeOfCodePoint(UCodePointLatinLetterSmallCapitalE) + numberOfCharExponent);
if (neededNumberOfChars > bufferSize - 1) {
int neededNumberOfChars = numberOfCharsForMantissaWithSign;
int neededNumberOfGlyphs = numberOfCharsForMantissaWithSign;
if (!doNotWriteExponent) {
neededNumberOfChars += UTF8Decoder::CharSizeOfCodePoint(UCodePointLatinLetterSmallCapitalE) + numberOfCharExponent;
neededNumberOfGlyphs += 1 + numberOfCharExponent;
}
if (neededNumberOfChars > bufferSize - 1 || neededNumberOfGlyphs > glyphLength) {
// Exception 3: We are about to overflow the buffer.
return neededNumberOfChars;
return exceptionResult;
}
PrintLongWithDecimalMarker(buffer, numberOfCharsForMantissaWithSign, dividend, decimalMarkerPosition);
if (doNotWriteExponent) {
buffer[numberOfCharsForMantissaWithSign] = 0;
return numberOfCharsForMantissaWithSign;
return {.CharLength = numberOfCharsForMantissaWithSign, .GlyphLength = numberOfCharsForMantissaWithSign};
}
// Print exponent
assert(numberOfCharsForMantissaWithSign < bufferSize);
@@ -378,10 +383,10 @@ int PrintFloat::ConvertFloatToTextPrivate(T f, char * buffer, int bufferSize, in
PrintLongWithDecimalMarker(buffer + currentNumberOfChar, numberOfCharExponent, dividend, -1);
buffer[currentNumberOfChar + numberOfCharExponent] = 0;
assert(neededNumberOfChars == currentNumberOfChar + numberOfCharExponent);
return currentNumberOfChar + numberOfCharExponent;
return {.CharLength = currentNumberOfChar + numberOfCharExponent, .GlyphLength = numberOfCharsForMantissaWithSign + 1 + numberOfCharExponent};
}
template int PrintFloat::ConvertFloatToText<float>(float, char*, int, int, Preferences::Preferences::PrintFloatMode);
template int PrintFloat::ConvertFloatToText<double>(double, char*, int, int, Preferences::Preferences::PrintFloatMode);
template PrintFloat::TextLengths PrintFloat::ConvertFloatToText<float>(float, char*, int, int, int, Preferences::Preferences::PrintFloatMode);
template PrintFloat::TextLengths PrintFloat::ConvertFloatToText<double>(double, char*, int, int, int, Preferences::Preferences::PrintFloatMode);
}

View File

@@ -21,7 +21,7 @@ void assert_float_prints_to(T a, const char * result, Preferences::PrintFloatMod
memset(taggedBuffer, tag, taggedAreaSize);
char * buffer = taggedBuffer + tagSize;
PrintFloat::ConvertFloatToText<T>(a, buffer, bufferSize, significantDigits, mode);
PrintFloat::ConvertFloatToText<T>(a, buffer, bufferSize, glyphLengthForFloatWithPrecision(significantDigits), significantDigits, mode);
for (int i = 0; i < tagSize; i++) {
quiz_assert_print_if_failure(taggedBuffer[i] == tag, result);