1 /* floating point to accurate string
3 Copyright (C) 2010 Free Software Foundation, Inc.
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 /* Written by Paul Eggert. */
28 # define FLOAT long double
29 # define FLOAT_DIG LDBL_DIG
30 # define FLOAT_MIN LDBL_MIN
31 # define FLOAT_PREC_BOUND _GL_LDBL_PREC_BOUND
32 # define FTOASTR ldtoastr
33 # define STRTOF strtold
36 # define FLOAT_DIG DBL_DIG
37 # define FLOAT_MIN DBL_MIN
38 # define FLOAT_PREC_BOUND _GL_DBL_PREC_BOUND
39 # define FTOASTR dtoastr
40 # define STRTOF strtod
44 # define FLOAT_DIG FLT_DIG
45 # define FLOAT_MIN FLT_MIN
46 # define FLOAT_PREC_BOUND _GL_FLT_PREC_BOUND
47 # define FTOASTR ftoastr
48 # define STRTOF strtof
52 FTOASTR (char *buf, size_t bufsize, int flags, int width, FLOAT x)
54 /* The following method is simple but slow.
55 For ideas about speeding things up, please see:
57 Florian Loitsch, Printing floating-point numbers quickly and accurately
58 with integers. ACM SIGPLAN notices 46, 6 (June 2010), 233-243
59 <http://dx.doi.org/10.1145/1809028.1806623>. */
61 char format[sizeof "%-+ 0*.*Lg"];
62 FLOAT abs_x = x < 0 ? -x : x;
68 /* Support flags that generate output parsable by strtof. */
69 *p = '-'; p += (flags & FTOASTR_LEFT_JUSTIFY ) != 0;
70 *p = '+'; p += (flags & FTOASTR_ALWAYS_SIGNED ) != 0;
71 *p = ' '; p += (flags & FTOASTR_SPACE_POSITIVE) != 0;
72 *p = '0'; p += (flags & FTOASTR_ZERO_PAD ) != 0;
77 *p = 'L'; p += 2 < LENGTH;
78 *p++ = flags & FTOASTR_UPPER_E ? 'G' : 'g';
81 for (prec = abs_x < FLOAT_MIN ? 1 : FLOAT_DIG; ; prec++)
83 int n = snprintf (buf, bufsize, format, width, prec, x);
85 || FLOAT_PREC_BOUND <= prec
86 || (n < bufsize && STRTOF (buf, NULL) == x))