Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:19
erlang
0249-erts-Fix-float_to_list-F-decimals-D.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0249-erts-Fix-float_to_list-F-decimals-D.patch of Package erlang
From c81c01da7b4870aa56cc38d865cd081f9bb800bc Mon Sep 17 00:00:00 2001 From: Sverker Eriksson <sverker@erlang.org> Date: Mon, 15 Jan 2018 19:13:15 +0100 Subject: [PATCH 2/3] erts: Fix float_to_list(F, [{decimals,D}]). Example symptom: 1> float_to_list(0.145, [{decimals,1}]). "0.2" There were two problems in sys_double_to_chars_fast 1. Most serious was adding 0.55555555 / (10^D) instead of 0.5 / (10^D) which imposed a 5.5% risk of a faulty rounding up. 2. Using fixpoint for frac_part which lost significant bits if F < 0.5 --- erts/emulator/sys/common/erl_sys_common_misc.c | 28 +++++++--- erts/emulator/test/num_bif_SUITE.erl | 71 +++++++++++++++++++++++--- 2 files changed, 84 insertions(+), 15 deletions(-) diff --git a/erts/emulator/sys/common/erl_sys_common_misc.c b/erts/emulator/sys/common/erl_sys_common_misc.c index 79f87eb3a9..ddb414580a 100644 --- a/erts/emulator/sys/common/erl_sys_common_misc.c +++ b/erts/emulator/sys/common/erl_sys_common_misc.c @@ -160,7 +160,7 @@ sys_double_to_chars_fast(double f, char *buffer, int buffer_size, int decimals, { /* Note that some C compilers don't support "static const" propagation * so we use a defines */ - #define SYS_DOUBLE_RND_CONST 0.55555555555555555 + #define SYS_DOUBLE_RND_CONST 0.5 #define FRAC_SIZE 52 #define EXP_SIZE 11 #define EXP_MASK ((1ll << EXP_SIZE) - 1) @@ -256,11 +256,14 @@ sys_double_to_chars_fast(double f, char *buffer, int buffer_size, int decimals, return p - buffer; } else if (exp >= FRAC_SIZE) { int_part = mantissa << (exp - FRAC_SIZE); + exp = 0; } else if (exp >= 0) { int_part = mantissa >> (FRAC_SIZE - exp); frac_part = (mantissa << (exp + 1)) & FRAC_MASK2; + exp = 0; } else /* if (exp < 0) */ { - frac_part = (mantissa & FRAC_MASK2) >> -(exp + 1); + frac_part = mantissa; + exp = -(exp+1); } if (!int_part) { @@ -298,11 +301,22 @@ sys_double_to_chars_fast(double f, char *buffer, int buffer_size, int decimals, max = decimals; for (i = 0; i < max; i++) { - /* frac_part *= 10; */ - frac_part = (frac_part << 3) + (frac_part << 1); - - *p++ = (char)((frac_part >> (FRAC_SIZE + 1)) + '0'); - frac_part &= FRAC_MASK2; + if (frac_part > (ERTS_UINT64_MAX/16)) { + frac_part /= 16; + exp -= 4; + } + if (FRAC_SIZE + 1 + exp >= 64) { + *p++ = '0'; + frac_part *= 5; + exp--; + } + else + { + frac_part *= 10; + + *p++ = (char)((frac_part >> (FRAC_SIZE + 1 + exp)) + '0'); + frac_part &= (1ll << (FRAC_SIZE + 1 + exp)) - 1; + } } /* Delete trailing zeroes */ -- 2.16.0
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor