mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
[poincare] PrintFloat: take into account the distinction between char
and glyph length in ConvertFloatToText
This commit is contained in:
committed by
LeaNumworks
parent
d6ad694b76
commit
4d593a6149
@@ -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);
|
||||
|
||||
@@ -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 = "=";
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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++] = ')';
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(); }
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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';
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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, "ient, &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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user