Fix for double formatting with precision > 9 (#480)

* Add a test that reproduces the double formatting failure

* Fix root cause, restrict precision to 9 on 32 bit platforms, unrestricted on 64 bit
This commit is contained in:
Noah Luskey 2021-12-10 00:49:08 -08:00 committed by GitHub
parent e1e3e7a194
commit 2932af8f93
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 24 additions and 3 deletions

View File

@ -56,8 +56,10 @@ namespace etl
{
#if ETL_NOT_USING_64BIT_TYPES
typedef int32_t workspace_t;
typedef uint32_t uworkspace_t;
#else
typedef int64_t workspace_t;
typedef uint64_t uworkspace_t;
#endif
//***************************************************************************
@ -314,13 +316,20 @@ namespace etl
// Make sure we format the two halves correctly.
uint32_t max_precision = etl::numeric_limits<T>::digits10;
#if ETL_NOT_USING_64BIT_TYPES
if (max_precision > 9)
{
max_precision = 9;
}
#endif
etl::basic_format_spec<TIString> integral_format = format;
integral_format.decimal().width(0).precision(format.get_precision() > max_precision ? max_precision : format.get_precision());
etl::basic_format_spec<TIString> fractional_format = integral_format;
fractional_format.width(integral_format.get_precision()).fill(type('0')).right();
uint32_t multiplier = 1U;
uworkspace_t multiplier = 1U;
for (uint32_t i = 0U; i < fractional_format.get_precision(); ++i)
{
@ -329,10 +338,10 @@ namespace etl
// Find the integral part of the floating point
T f_integral = floor(etl::absolute(value));
uint32_t integral = static_cast<uint32_t>(f_integral);
uworkspace_t integral = static_cast<uworkspace_t>(f_integral);
// Find the fractional part of the floating point.
uint32_t fractional = static_cast<uint32_t>(round((etl::absolute(value) - f_integral) * multiplier));
uworkspace_t fractional = static_cast<uworkspace_t>(round((etl::absolute(value) - f_integral) * multiplier));
// Check for a rounding carry to the integral.
if (fractional == multiplier)

View File

@ -596,6 +596,18 @@ namespace
CHECK_EQUAL(etl::string<20>(STR("-123.4568")).c_str(), result_i.c_str());
CHECK_EQUAL(result_d.c_str(), result_i.c_str());
}
//*************************************************************************
TEST(test_double_formatting_10_decimal_point)
{
etl::string<20> result_d;
double value_d = 1.2345;
Format format = Format().precision(10);
etl::to_string(value_d, result_d, format);
CHECK_EQUAL(etl::string<20>(STR("1.2345000000")).c_str(), result_d.c_str());
}
//*************************************************************************
TEST(test_integer_denominator_larger_width)