[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) { void GraphControllerHelper::reloadDerivativeInBannerViewForCursorOnFunction(Shared::CurveViewCursor * cursor, Ion::Storage::Record record) {
ExpiringPointer<ContinuousFunction> function = App::app()->functionStore()->modelForRecord(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]; char buffer[bufferSize];
const char * space = " "; const char * space = " ";
int numberOfChar = function->derivativeNameWithArgument(buffer, bufferSize); int numberOfChar = function->derivativeNameWithArgument(buffer, bufferSize);

View File

@@ -18,7 +18,7 @@ const char * IntersectionGraphController::title() {
void IntersectionGraphController::reloadBannerView() { void IntersectionGraphController::reloadBannerView() {
CalculationGraphController::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]; char buffer[bufferSize];
const char * space = " "; const char * space = " ";
const char * legend = "="; 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()); FunctionBannerDelegate::reloadBannerViewForCursorOnFunction(m_cursor, m_record, Shared::FunctionApp::app()->functionStore(), AppsContainer::sharedAppsContainer()->globalContext());
GraphControllerHelper::reloadDerivativeInBannerViewForCursorOnFunction(m_cursor, m_record); 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]; char buffer[bufferSize];
Poincare::Context * context = textFieldDelegateApp()->localContext(); Poincare::Context * context = textFieldDelegateApp()->localContext();
@@ -76,7 +76,7 @@ void TangentGraphController::reloadBannerView() {
int legendLength = strlcpy(buffer, legend, bufferSize); int legendLength = strlcpy(buffer, legend, bufferSize);
ExpiringPointer<ContinuousFunction> function = App::app()->functionStore()->modelForRecord(m_record); ExpiringPointer<ContinuousFunction> function = App::app()->functionStore()->modelForRecord(m_record);
double y = function->approximateDerivative(m_cursor->x(), context); 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); m_bannerView->aView()->setText(buffer);
legend = "b="; legend = "b=";
@@ -84,7 +84,7 @@ void TangentGraphController::reloadBannerView() {
Shared::TextFieldDelegateApp * myApp = textFieldDelegateApp(); Shared::TextFieldDelegateApp * myApp = textFieldDelegateApp();
assert(function->plotType() == Shared::ContinuousFunction::PlotType::Cartesian); assert(function->plotType() == Shared::ContinuousFunction::PlotType::Cartesian);
y = -y*m_cursor->x()+function->evaluate2DAtParameter(m_cursor->x(), myApp->localContext()).x2(); 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->bView()->setText(buffer);
m_bannerView->reload(); m_bannerView->reload();
} }

View File

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

View File

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

View File

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

View File

@@ -180,9 +180,10 @@ void CalculationController::willDisplayCellAtLocation(HighlightCell * cell, int
return; return;
} }
constexpr int precision = Preferences::LargeNumberOfSignificantDigits; constexpr int precision = Preferences::LargeNumberOfSignificantDigits;
constexpr int bufferSize = PrintFloat::bufferSizeForFloatsWithPrecision(precision); constexpr int bufferSize = PrintFloat::charSizeForFloatsWithPrecision(precision);
char buffer[bufferSize]; 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); field->setText(buffer);
} }
} }
@@ -283,9 +284,9 @@ void CalculationController::updateTitle() {
break; break;
} }
constexpr int precision = Preferences::ShortNumberOfSignificantDigits; constexpr int precision = Preferences::ShortNumberOfSignificantDigits;
constexpr size_t bufferSize = PrintFloat::bufferSizeForFloatsWithPrecision(precision); constexpr int bufferSize = PrintFloat::charSizeForFloatsWithPrecision(precision);
char buffer[bufferSize]; 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); currentChar += strlcpy(m_titleBuffer+currentChar, buffer, k_titleBufferSize - currentChar);
if (currentChar >= k_titleBufferSize) { if (currentChar >= k_titleBufferSize) {
break; break;

View File

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

View File

@@ -63,7 +63,7 @@ private:
static constexpr KDCoordinate k_cellHeight = 25; static constexpr KDCoordinate k_cellHeight = 25;
static constexpr KDCoordinate k_titleCalculationCellWidth = Ion::Display::Width/2 - Metric::CommonRightMargin/2 - Metric::CommonLeftMargin/2; static constexpr KDCoordinate k_titleCalculationCellWidth = Ion::Display::Width/2 - Metric::CommonRightMargin/2 - Metric::CommonLeftMargin/2;
// TODO: change 7 for KDFont::SmallFont->glyphSize().width() // 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_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_quarticCalculationCellWidth = maxCoordinate(195, k_minCalculationCellWidth ); // Should hold ? aX^4+bX^3+c*X^2+dX+e
static constexpr KDCoordinate k_margin = 8; static constexpr KDCoordinate k_margin = 8;

View File

@@ -105,7 +105,7 @@ Poincare::Context * GraphController::globalContext() {
void GraphController::reloadBannerView() { void GraphController::reloadBannerView() {
// Set point equals: "P(...) =" // 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]; char buffer[bufferSize];
int numberOfChar = 0; int numberOfChar = 0;
const char * legend = " P("; const char * legend = " P(";
@@ -119,7 +119,7 @@ void GraphController::reloadBannerView() {
assert(numberOfChar <= bufferSize); assert(numberOfChar <= bufferSize);
numberOfChar += strlcpy(buffer + numberOfChar, legend, bufferSize - numberOfChar); numberOfChar += strlcpy(buffer + numberOfChar, legend, bufferSize - numberOfChar);
} else { } 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 = ") "; legend = ") ";
assert(numberOfChar <= bufferSize); 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) { void ValuesController::printEvaluationOfAbscissaAtColumn(double abscissa, int columnIndex, char * buffer, const int bufferSize) {
Shared::ExpiringPointer<Sequence> sequence = functionStore()->modelForRecord(recordAtColumn(columnIndex)); Shared::ExpiringPointer<Sequence> sequence = functionStore()->modelForRecord(recordAtColumn(columnIndex));
Coordinate2D<double> xy = sequence->evaluateXYAtParameter(abscissa, textFieldDelegateApp()->localContext()); Coordinate2D<double> xy = sequence->evaluateXYAtParameter(abscissa, textFieldDelegateApp()->localContext());
const int floatBufferSize = PrintFloat::bufferSizeForFloatsWithPrecision(Preferences::LargeNumberOfSignificantDigits); Shared::PoincareHelpers::ConvertFloatToText<double>(xy.x2(), buffer, bufferSize, Preferences::LargeNumberOfSignificantDigits);
assert(floatBufferSize <= bufferSize);
Shared::PoincareHelpers::ConvertFloatToText<double>(xy.x2(), buffer, floatBufferSize, Preferences::LargeNumberOfSignificantDigits);
} }
Shared::Interval * ValuesController::intervalAtColumn(int columnIndex) { Shared::Interval * ValuesController::intervalAtColumn(int columnIndex) {

View File

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

View File

@@ -50,7 +50,8 @@ protected:
constexpr static KDCoordinate k_labelGraduationLength = 6; constexpr static KDCoordinate k_labelGraduationLength = 6;
constexpr static int k_numberSignificantDigits = 6; constexpr static int k_numberSignificantDigits = 6;
constexpr static int k_bigNumberSignificantDigits = Poincare::Preferences::LargeNumberOfSignificantDigits; 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_maxNumberOfXLabels = CurveViewRange::k_maxNumberOfXGridUnits;
constexpr static int k_maxNumberOfYLabels = CurveViewRange::k_maxNumberOfYGridUnits; constexpr static int k_maxNumberOfYLabels = CurveViewRange::k_maxNumberOfYGridUnits;
constexpr static int k_externRectMargin = 2; constexpr static int k_externRectMargin = 2;

View File

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

View File

@@ -121,9 +121,9 @@ void FloatParameterController<T>::willDisplayCellForIndex(HighlightCell * cell,
return; return;
} }
constexpr int precision = Preferences::LargeNumberOfSignificantDigits; constexpr int precision = Preferences::LargeNumberOfSignificantDigits;
constexpr int bufferSize = PrintFloat::bufferSizeForFloatsWithPrecision(precision); constexpr int bufferSize = PrintFloat::charSizeForFloatsWithPrecision(precision);
char buffer[bufferSize]; 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); 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) { void FunctionBannerDelegate::reloadBannerViewForCursorOnFunction(CurveViewCursor * cursor, Ion::Storage::Record record, FunctionStore * functionStore, Poincare::Context * context) {
ExpiringPointer<Function> function = functionStore->modelForRecord(record); 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]; char buffer[bufferSize];
const char * space = " "; const char * space = " ";
int numberOfChar = 0; int numberOfChar = 0;
@@ -20,7 +20,7 @@ void FunctionBannerDelegate::reloadBannerViewForCursorOnFunction(CurveViewCursor
constexpr int precision = Preferences::MediumNumberOfSignificantDigits; 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); assert(numberOfChar <= bufferSize);
strlcpy(buffer+numberOfChar, space, bufferSize - numberOfChar); strlcpy(buffer+numberOfChar, space, bufferSize - numberOfChar);
bannerView()->abscissaValue()->setText(buffer); bannerView()->abscissaValue()->setText(buffer);

View File

@@ -16,7 +16,12 @@ inline Poincare::Layout CreateLayout(const Poincare::Expression e) {
template <class T> template <class T>
inline int ConvertFloatToText(T d, char * buffer, int bufferSize, int numberOfSignificantDigits) { 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) { 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) { void SumGraphController::LegendView::setEditableZone(double d) {
constexpr int precision = Preferences::MediumNumberOfSignificantDigits; constexpr int precision = Preferences::MediumNumberOfSignificantDigits;
constexpr int bufferSize = PrintFloat::bufferSizeForFloatsWithPrecision(precision); constexpr int bufferSize = PrintFloat::charSizeForFloatsWithPrecision(precision);
char buffer[bufferSize]; 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); m_editableZone.setText(buffer);
} }
@@ -193,28 +193,28 @@ void SumGraphController::LegendView::setSumSymbol(Step step, double start, doubl
m_sumLayout = LayoutHelper::CodePointString(sigma, sigmaLength); m_sumLayout = LayoutHelper::CodePointString(sigma, sigmaLength);
} else if (step == Step::SecondParameter) { } else if (step == Step::SecondParameter) {
constexpr int precision = Preferences::MediumNumberOfSignificantDigits; constexpr int precision = Preferences::MediumNumberOfSignificantDigits;
constexpr int bufferSize = PrintFloat::bufferSizeForFloatsWithPrecision(precision); constexpr int bufferSize = PrintFloat::charSizeForFloatsWithPrecision(precision);
char buffer[bufferSize]; 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( m_sumLayout = CondensedSumLayout::Builder(
LayoutHelper::CodePointString(sigma, sigmaLength), LayoutHelper::CodePointString(sigma, sigmaLength),
LayoutHelper::String(buffer, strlen(buffer), k_font), LayoutHelper::String(buffer, strlen(buffer), k_font),
EmptyLayout::Builder(EmptyLayoutNode::Color::Yellow, false, k_font, false)); EmptyLayout::Builder(EmptyLayoutNode::Color::Yellow, false, k_font, false));
} else { } else {
constexpr int precision = Preferences::LargeNumberOfSignificantDigits; constexpr int precision = Preferences::LargeNumberOfSignificantDigits;
constexpr int sizeForPrecision = PrintFloat::bufferSizeForFloatsWithPrecision(precision); constexpr int sizeForPrecision = PrintFloat::charSizeForFloatsWithPrecision(precision);
constexpr int bufferSize = 2 + sizeForPrecision; constexpr int bufferSize = 2 + sizeForPrecision;
char buffer[bufferSize]; 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); 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); Layout end = LayoutHelper::String(buffer, strlen(buffer), k_font);
m_sumLayout = CondensedSumLayout::Builder( m_sumLayout = CondensedSumLayout::Builder(
LayoutHelper::CodePointString(sigma, sigmaLength), LayoutHelper::CodePointString(sigma, sigmaLength),
start, start,
end); end);
strlcpy(buffer, "= ", 3); 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 = HorizontalLayout::Builder(
m_sumLayout, m_sumLayout,
functionLayout, functionLayout,

View File

@@ -56,7 +56,7 @@ private:
void setEditableZone(double d); void setEditableZone(double d);
void setSumSymbol(Step step, double start, double end, double result, Poincare::Layout functionLayout); void setSumSymbol(Step step, double start, double end, double result, Poincare::Layout functionLayout);
private: 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 KDCoordinate k_legendHeight = 35;
constexpr static const KDFont * k_font = KDFont::SmallFont; constexpr static const KDFont * k_font = KDFont::SmallFont;
static KDCoordinate editableZoneWidth() { return 12*k_font->glyphSize().width(); } 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()); willDisplayCellAtLocationWithDisplayMode(cell, i, j, Preferences::sharedPreferences()->displayMode());
// The cell is not a title cell and not editable // The cell is not a title cell and not editable
if (typeAtLocation(i,j) == k_notEditableValueCellType) { 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) char buffer[bufferSize]; // The largest buffer holds (-1.234567E-123;-1.234567E-123)
// Special case: last row // Special case: last row
if (j == numberOfElementsInColumn(i) + 1) { if (j == numberOfElementsInColumn(i) + 1) {

View File

@@ -20,7 +20,7 @@ public:
protected: protected:
View * subviewAtIndex(int index) override; View * subviewAtIndex(int index) override;
private: 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; } int numberOfSubviews() const override { return k_numberOfSubviews; }
BufferTextView m_abscissaSymbol; BufferTextView m_abscissaSymbol;
TextField m_abscissaValue; TextField m_abscissaValue;

View File

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

View File

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

View File

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

View File

@@ -55,7 +55,7 @@ private:
static constexpr KDCoordinate k_cellHeight = 20; static constexpr KDCoordinate k_cellHeight = 20;
static constexpr KDCoordinate k_calculationTitleCellWidth = 175; static constexpr KDCoordinate k_calculationTitleCellWidth = 175;
// TODO: change 7 for KDFont::SmallFont->glyphSize().width() // 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_margin = 8;
static constexpr KDCoordinate k_scrollBarMargin = Metric::CommonRightMargin; static constexpr KDCoordinate k_scrollBarMargin = Metric::CommonRightMargin;

View File

@@ -96,7 +96,7 @@ void HistogramController::reloadBannerView() {
return; return;
} }
constexpr int precision = Preferences::LargeNumberOfSignificantDigits; 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] = ""; char buffer[bufferSize] = "";
int numberOfChar = 0; int numberOfChar = 0;

View File

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

View File

@@ -30,7 +30,7 @@ public:
private: private:
void layoutSubviews() override; void layoutSubviews() override;
TextField m_textField; TextField m_textField;
char m_textBody[Poincare::PrintFloat::k_maxFloatBufferSize]; char m_textBody[Poincare::PrintFloat::k_maxFloatCharSize];
}; };
#endif #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) : const KDFont * font, float horizontalAlignment, float verticalAlignment, KDColor textColor, KDColor backgroundColor, KDCoordinate topMargin, KDCoordinate rightMargin, KDCoordinate bottomMargin, KDCoordinate leftMargin) :
HighlightCell(), HighlightCell(),
Responder(parentResponder), 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_topMargin(topMargin),
m_rightMargin(rightMargin), m_rightMargin(rightMargin),
m_bottomMargin(bottomMargin), m_bottomMargin(bottomMargin),

View File

@@ -5,7 +5,7 @@
MessageTableCellWithEditableText::MessageTableCellWithEditableText(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, TextFieldDelegate * textFieldDelegate, I18n::Message message) : MessageTableCellWithEditableText::MessageTableCellWithEditableText(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, TextFieldDelegate * textFieldDelegate, I18n::Message message) :
Responder(parentResponder), Responder(parentResponder),
MessageTableCell(message), 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'; m_textBody[0] = '\0';
} }

View File

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

View File

@@ -13,11 +13,22 @@ public:
constexpr static int k_numberOfStoredSignificantDigits = 14; constexpr static int k_numberOfStoredSignificantDigits = 14;
// ᴇ and are 3 bytes long // ᴇ and are 3 bytes long
constexpr static int k_specialECodePointByteLength = 3; 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 * 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. */ * 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) { constexpr static int glyphLengthForFloatWithPrecision(int numberOfSignificantDigits) {
// The worst case is -1.234ᴇ-328 // The worst case is -1.234ᴇ-328
@@ -27,23 +38,28 @@ public:
+ 1 // '-' + 1 // '-'
+ 3; // exponant + 3; // exponant
} }
constexpr static int bufferSizeForFloatsWithPrecision(int numberOfSignificantDigits) { constexpr static int charSizeForFloatsWithPrecision(int numberOfSignificantDigits) {
// The worst case is -1.234ᴇ-328 // The worst case is -1.234ᴇ-328
return 2 // '-' and '.' return 2 // '-' and '.'
+ numberOfSignificantDigits // mantissa + numberOfSignificantDigits // mantissa
+ k_specialECodePointByteLength // ᴇ + k_specialECodePointByteLength // ᴇ
+ 1 // '-' + 1 // exponant '-'
+ 3 // 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 /* 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 * digits, the function forces the scientific mode. If the buffer is still too
* small, the text representing the float is empty. * small, the text representing the float is empty.
* ConvertFloatToText returns the number of characters that have been written * ConvertFloatToText returns the number of characters that have been written
* in buffer (excluding the last \0 character). */ * in buffer (excluding the last \0 character). */
template <class T> 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 // Engineering notation
static int EngineeringExponentFromBase10Exponent(int exponent); static int EngineeringExponentFromBase10Exponent(int exponent);
@@ -59,7 +75,7 @@ public:
private: private:
template <class T> 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 { class Long final {
public: public:

View File

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

View File

@@ -24,7 +24,7 @@ int InfinityNode::serialize(char * buffer, int bufferSize, Preferences::PrintFlo
if (bufferSize == 0) { if (bufferSize == 0) {
return -1; 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 { template<typename T> Evaluation<T> InfinityNode::templatedApproximate() const {

View File

@@ -166,7 +166,7 @@ int Integer::serialize(char * buffer, int bufferSize) const {
return 0; return 0;
} }
if (isOverflow()) { 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); Integer base(10);
@@ -185,7 +185,7 @@ int Integer::serialize(char * buffer, int bufferSize) const {
d.quotient.isZero())) { d.quotient.isZero())) {
char c = char_from_digit(d.remainder.isZero() ? 0 : d.remainder.digit(0)); char c = char_from_digit(d.remainder.isZero() ? 0 : d.remainder.digit(0));
if (length >= bufferSize-1) { 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); length += SerializationHelper::CodePoint(buffer + length, bufferSize - length, c);
d = udiv(d.quotient, base); 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 * in first position. When called by ConvertFloatToText, the buffer length is
* always > 0 as we asserted a minimal number of available chars. */ * always > 0 as we asserted a minimal number of available chars. */
assert(bufferLength > 0 && decimalMarkerPosition != 0); assert(bufferLength > 0 && decimalMarkerPosition != 0);
constexpr int tempBufferSize = PrintFloat::k_maxFloatBufferSize; constexpr int tempBufferSize = PrintFloat::k_maxFloatCharSize;
char tempBuffer[tempBufferSize]; char tempBuffer[tempBufferSize];
int intLength = i.serialize(tempBuffer, tempBufferSize); int intLength = i.serialize(tempBuffer, tempBufferSize);
int firstDigitChar = UTF8Helper::CodePointIs(tempBuffer, '-') ? 1 : 0; int firstDigitChar = UTF8Helper::CodePointIs(tempBuffer, '-') ? 1 : 0;
@@ -128,30 +128,30 @@ void PrintFloat::PrintLongWithDecimalMarker(char * buffer, int bufferLength, Lon
} }
template <class T> 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) int numberOfSignificantDigits, Preferences::PrintFloatMode mode)
{ {
assert(numberOfSignificantDigits > 0); assert(numberOfSignificantDigits > 0);
assert(bufferSize > 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 * 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. */ * the buffer with the decimal version of 1.234E-30. */
int truncatedBufferSize = minInt(PrintFloat::k_maxFloatBufferSize, bufferSize); assert(glyphLength < k_maxFloatGlyphLength);
int numberOfZerosRemoved = 0; TextLengths requiredLengths = ConvertFloatToTextPrivate(f, buffer, bufferSize, glyphLength, numberOfSignificantDigits, mode);
int requiredLength = ConvertFloatToTextPrivate(f, buffer, truncatedBufferSize, numberOfSignificantDigits, mode, &numberOfZerosRemoved);
/* If the required buffer size overflows the buffer size, we force the display /* If the required buffer size overflows the buffer size, we force the display
* mode to scientific. */ * mode to scientific. */
if (mode == Preferences::PrintFloatMode::Decimal && requiredLength >= truncatedBufferSize) { if (mode == Preferences::PrintFloatMode::Decimal && (requiredLengths.CharLength > bufferSize - 1 || requiredLengths.GlyphLength > glyphLength)) {
requiredLength = ConvertFloatToTextPrivate(f, buffer, truncatedBufferSize, numberOfSignificantDigits, Preferences::PrintFloatMode::Scientific, &numberOfZerosRemoved); requiredLengths = ConvertFloatToTextPrivate(f, buffer, bufferSize, glyphLength, numberOfSignificantDigits, Preferences::PrintFloatMode::Scientific);
} }
if (requiredLength >= truncatedBufferSize) { if (requiredLengths.CharLength > bufferSize - 1 || requiredLengths.GlyphLength > glyphLength) {
buffer[0] = 0; 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) { int PrintFloat::EngineeringExponentFromBase10Exponent(int exponent) {
@@ -163,37 +163,43 @@ int PrintFloat::EngineeringExponentFromBase10Exponent(int exponent) {
} }
template <class T> 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(numberOfSignificantDigits > 0);
assert(bufferSize > 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 ? //TODO: accelerate for f between 0 and 10 ?
if (std::isinf(f)) { if (std::isinf(f)) {
// Infinity // Infinity
bool writeMinusSign = f < 0; bool writeMinusSign = f < 0;
assert(UTF8Decoder::CharSizeOfCodePoint('-') == 1); assert(UTF8Decoder::CharSizeOfCodePoint('-') == 1);
int requiredLength = (writeMinusSign ? 1 : 0) + Infinity::NameSize() - 1; int requiredCharLength = (writeMinusSign ? 1 : 0) + Infinity::NameSize() - 1;
if (requiredLength > bufferSize - 1) { TextLengths requiredTextLengths = {.CharLength = requiredCharLength, .GlyphLength = requiredCharLength};
if (requiredCharLength > availableCharLength) {
// We will not be able to print // We will not be able to print
return requiredLength; return requiredTextLengths;
} }
// Write inf or -inf // Write inf or -inf
int currentChar = 0; int currentChar = 0;
if (f < 0) { if (f < 0) {
currentChar+= SerializationHelper::CodePoint(buffer, bufferSize, '-'); currentChar += SerializationHelper::CodePoint(buffer, bufferSize, '-');
} }
assert(bufferSize - currentChar > 0); assert(bufferSize - currentChar > 0);
strlcpy(buffer+currentChar, Infinity::Name(), bufferSize-currentChar); strlcpy(buffer+currentChar, Infinity::Name(), bufferSize-currentChar);
return requiredLength; return requiredTextLengths;
} }
if (std::isnan(f)) { if (std::isnan(f)) {
// Nan // Nan
constexpr int requiredLength = Undefined::NameSize() - 1; constexpr int requiredCharLength = Undefined::NameSize() - 1;
if (requiredLength - 1 > bufferSize - 1) { constexpr TextLengths requiredTextLengths = {.CharLength = requiredCharLength, .GlyphLength = requiredCharLength};
if (requiredCharLength > availableCharLength) {
// We will not be able to print // 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); 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. * displaying 12345 with 2 significant digis in Decimal mode for instance.
* This exception is caught by ConvertFloatToText and forces the mode to * This exception is caught by ConvertFloatToText and forces the mode to
* Scientific */ * Scientific */
return bufferSize + 1; return exceptionResult;
} }
// Correct the number of digits in mantissa after rounding // 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); assert(mantissa < 1000);
Long::MultiplySmallLongByTen(dividend); Long::MultiplySmallLongByTen(dividend);
} }
if (numberOfRemovedZeros != nullptr) {
*numberOfRemovedZeros = -numberOfZeroesToAdd;
}
} }
} }
if (removeZeroes) { if (removeZeroes) {
@@ -298,12 +301,9 @@ int PrintFloat::ConvertFloatToTextPrivate(T f, char * buffer, int bufferSize, in
Long::DivisionByTen(dividend, &quotient, &digit); Long::DivisionByTen(dividend, &quotient, &digit);
numberOfZerosRemoved++; numberOfZerosRemoved++;
} }
if (numberOfCharsForMantissaWithoutSign > bufferSize - 1) { if (numberOfCharsForMantissaWithoutSign > availableCharLength) {
// Escape now if the true number of needed digits is not required // Escape now if the true number of needed digits is not required
return bufferSize + 1; return exceptionResult;
}
if (numberOfRemovedZeros != nullptr) {
*numberOfRemovedZeros = numberOfZerosRemoved;
} }
} }
@@ -317,9 +317,9 @@ int PrintFloat::ConvertFloatToTextPrivate(T f, char * buffer, int bufferSize, in
assert(UTF8Decoder::CharSizeOfCodePoint('.') == 1); assert(UTF8Decoder::CharSizeOfCodePoint('.') == 1);
numberOfCharsForMantissaWithoutSign++; numberOfCharsForMantissaWithoutSign++;
} }
if (numberOfCharsForMantissaWithoutSign > bufferSize - 1) { if (numberOfCharsForMantissaWithoutSign > availableCharLength) {
// Escape now if the true number of needed digits is not required // 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 */ /* 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 */ /* Part III: Sign */
int numberOfCharsForMantissaWithSign = numberOfCharsForMantissaWithoutSign + (f >= 0 ? 0 : 1); int numberOfCharsForMantissaWithSign = numberOfCharsForMantissaWithoutSign + (f >= 0 ? 0 : 1);
if (numberOfCharsForMantissaWithSign > bufferSize - 1) { if (numberOfCharsForMantissaWithSign > availableCharLength) {
// Exception 2: we will overflow the buffer // Exception 2: we will overflow the buffer
return bufferSize + 1; return exceptionResult;
} }
/* Part IV: Exponent */ /* Part IV: Exponent */
@@ -360,15 +360,20 @@ int PrintFloat::ConvertFloatToTextPrivate(T f, char * buffer, int bufferSize, in
assert(UTF8Decoder::CharSizeOfCodePoint('-') == 1); assert(UTF8Decoder::CharSizeOfCodePoint('-') == 1);
// Print mantissa // Print mantissa
bool doNotWriteExponent = (mode == Preferences::PrintFloatMode::Decimal) || (exponent == 0); bool doNotWriteExponent = (mode == Preferences::PrintFloatMode::Decimal) || (exponent == 0);
int neededNumberOfChars = numberOfCharsForMantissaWithSign + (doNotWriteExponent ? 0 : UTF8Decoder::CharSizeOfCodePoint(UCodePointLatinLetterSmallCapitalE) + numberOfCharExponent); int neededNumberOfChars = numberOfCharsForMantissaWithSign;
if (neededNumberOfChars > bufferSize - 1) { 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. // Exception 3: We are about to overflow the buffer.
return neededNumberOfChars; return exceptionResult;
} }
PrintLongWithDecimalMarker(buffer, numberOfCharsForMantissaWithSign, dividend, decimalMarkerPosition); PrintLongWithDecimalMarker(buffer, numberOfCharsForMantissaWithSign, dividend, decimalMarkerPosition);
if (doNotWriteExponent) { if (doNotWriteExponent) {
buffer[numberOfCharsForMantissaWithSign] = 0; buffer[numberOfCharsForMantissaWithSign] = 0;
return numberOfCharsForMantissaWithSign; return {.CharLength = numberOfCharsForMantissaWithSign, .GlyphLength = numberOfCharsForMantissaWithSign};
} }
// Print exponent // Print exponent
assert(numberOfCharsForMantissaWithSign < bufferSize); assert(numberOfCharsForMantissaWithSign < bufferSize);
@@ -378,10 +383,10 @@ int PrintFloat::ConvertFloatToTextPrivate(T f, char * buffer, int bufferSize, in
PrintLongWithDecimalMarker(buffer + currentNumberOfChar, numberOfCharExponent, dividend, -1); PrintLongWithDecimalMarker(buffer + currentNumberOfChar, numberOfCharExponent, dividend, -1);
buffer[currentNumberOfChar + numberOfCharExponent] = 0; buffer[currentNumberOfChar + numberOfCharExponent] = 0;
assert(neededNumberOfChars == currentNumberOfChar + numberOfCharExponent); 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 PrintFloat::TextLengths PrintFloat::ConvertFloatToText<float>(float, char*, int, int, int, Preferences::Preferences::PrintFloatMode);
template int PrintFloat::ConvertFloatToText<double>(double, char*, 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); memset(taggedBuffer, tag, taggedAreaSize);
char * buffer = taggedBuffer + tagSize; 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++) { for (int i = 0; i < tagSize; i++) {
quiz_assert_print_if_failure(taggedBuffer[i] == tag, result); quiz_assert_print_if_failure(taggedBuffer[i] == tag, result);