]>
Commit | Line | Data |
---|---|---|
19361cb7 | 1 | /* Compatibility functions for floating point formatting. |
688903eb | 2 | Copyright (C) 1995-2018 Free Software Foundation, Inc. |
19361cb7 | 3 | This file is part of the GNU C Library. |
0923c7a5 | 4 | |
19361cb7 | 5 | The GNU C Library is free software; you can redistribute it and/or |
41bdb6e2 AJ |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
0923c7a5 | 9 | |
19361cb7 UD |
10 | The GNU C Library 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 GNU | |
41bdb6e2 | 13 | Lesser General Public License for more details. |
0923c7a5 | 14 | |
41bdb6e2 | 15 | You should have received a copy of the GNU Lesser General Public |
59ba27a6 PE |
16 | License along with the GNU C Library; if not, see |
17 | <http://www.gnu.org/licenses/>. */ | |
0923c7a5 | 18 | |
b113c12c | 19 | #include <math.h> |
0923c7a5 | 20 | #include <stdio.h> |
60478656 | 21 | #include <stdlib.h> |
67994d6f | 22 | #include <sys/param.h> |
52e9a9d1 | 23 | #include <float.h> |
ec999b8e | 24 | #include <libc-lock.h> |
1d446ec6 | 25 | #include <math_ldbl_opt.h> |
52e9a9d1 | 26 | |
2064087b | 27 | #ifndef FLOAT_TYPE |
1cab5444 UD |
28 | # define FLOAT_TYPE double |
29 | # define FUNC_PREFIX | |
30 | # define FLOAT_FMT_FLAG | |
31 | /* Actually we have to write (DBL_DIG + log10 (DBL_MAX_10_EXP)) but we | |
32 | don't have log10 available in the preprocessor. */ | |
b113c12c | 33 | # define MAXDIG (NDIGIT_MAX + 3) |
887e7ab6 | 34 | # define FCVT_MAXDIG (DBL_MAX_10_EXP + MAXDIG) |
b113c12c UD |
35 | # if DBL_MANT_DIG == 53 |
36 | # define NDIGIT_MAX 17 | |
f9a2a636 UD |
37 | # elif DBL_MANT_DIG == 24 |
38 | # define NDIGIT_MAX 9 | |
39 | # elif DBL_MANT_DIG == 56 | |
40 | # define NDIGIT_MAX 18 | |
b113c12c | 41 | # else |
f9a2a636 UD |
42 | /* See IEEE 854 5.6, table 2 for this formula. Unfortunately we need a |
43 | compile time constant here, so we cannot use it. */ | |
44 | # error "NDIGIT_MAX must be precomputed" | |
b113c12c UD |
45 | # define NDIGIT_MAX (lrint (ceil (M_LN2 / M_LN10 * DBL_MANT_DIG + 1.0))) |
46 | # endif | |
c6251f03 RM |
47 | #else |
48 | # define LONG_DOUBLE_CVT | |
2064087b RM |
49 | #endif |
50 | ||
51 | #define APPEND(a, b) APPEND2 (a, b) | |
52 | #define APPEND2(a, b) a##b | |
c6251f03 RM |
53 | #define __APPEND(a, b) __APPEND2 (a, b) |
54 | #define __APPEND2(a, b) __##a##b | |
2064087b | 55 | |
0923c7a5 | 56 | |
1cab5444 | 57 | #define FCVT_BUFFER APPEND (FUNC_PREFIX, fcvt_buffer) |
887e7ab6 | 58 | #define FCVT_BUFPTR APPEND (FUNC_PREFIX, fcvt_bufptr) |
1cab5444 UD |
59 | #define ECVT_BUFFER APPEND (FUNC_PREFIX, ecvt_buffer) |
60 | ||
61 | ||
67994d6f UD |
62 | static char FCVT_BUFFER[MAXDIG]; |
63 | static char ECVT_BUFFER[MAXDIG]; | |
c877418f | 64 | libc_freeres_ptr (static char *FCVT_BUFPTR); |
1cab5444 | 65 | |
0923c7a5 | 66 | char * |
80d9be81 JM |
67 | __APPEND (FUNC_PREFIX, fcvt) (FLOAT_TYPE value, int ndigit, int *decpt, |
68 | int *sign) | |
0923c7a5 | 69 | { |
887e7ab6 UD |
70 | if (FCVT_BUFPTR == NULL) |
71 | { | |
c6251f03 RM |
72 | if (__APPEND (FUNC_PREFIX, fcvt_r) (value, ndigit, decpt, sign, |
73 | FCVT_BUFFER, MAXDIG) != -1) | |
887e7ab6 UD |
74 | return FCVT_BUFFER; |
75 | ||
76 | FCVT_BUFPTR = (char *) malloc (FCVT_MAXDIG); | |
77 | if (FCVT_BUFPTR == NULL) | |
78 | return FCVT_BUFFER; | |
79 | } | |
80 | ||
c6251f03 RM |
81 | (void) __APPEND (FUNC_PREFIX, fcvt_r) (value, ndigit, decpt, sign, |
82 | FCVT_BUFPTR, FCVT_MAXDIG); | |
1cab5444 | 83 | |
887e7ab6 | 84 | return FCVT_BUFPTR; |
1cab5444 UD |
85 | } |
86 | ||
87 | ||
0923c7a5 | 88 | char * |
80d9be81 JM |
89 | __APPEND (FUNC_PREFIX, ecvt) (FLOAT_TYPE value, int ndigit, int *decpt, |
90 | int *sign) | |
0923c7a5 | 91 | { |
c6251f03 RM |
92 | (void) __APPEND (FUNC_PREFIX, ecvt_r) (value, ndigit, decpt, sign, |
93 | ECVT_BUFFER, MAXDIG); | |
1cab5444 UD |
94 | |
95 | return ECVT_BUFFER; | |
0923c7a5 RM |
96 | } |
97 | ||
98 | char * | |
80d9be81 | 99 | __APPEND (FUNC_PREFIX, gcvt) (FLOAT_TYPE value, int ndigit, char *buf) |
0923c7a5 | 100 | { |
67994d6f | 101 | sprintf (buf, "%.*" FLOAT_FMT_FLAG "g", MIN (ndigit, NDIGIT_MAX), value); |
0923c7a5 RM |
102 | return buf; |
103 | } | |
c6251f03 RM |
104 | |
105 | #if LONG_DOUBLE_COMPAT (libc, GLIBC_2_0) | |
106 | # ifdef LONG_DOUBLE_CVT | |
107 | # define cvt_symbol(symbol) \ | |
108 | cvt_symbol_1 (libc, __APPEND (FUNC_PREFIX, symbol), \ | |
109 | APPEND (FUNC_PREFIX, symbol), GLIBC_2_4) | |
110 | # define cvt_symbol_1(lib, local, symbol, version) \ | |
111 | versioned_symbol (lib, local, symbol, version) | |
112 | # else | |
113 | # define cvt_symbol(symbol) \ | |
114 | cvt_symbol_1 (libc, __APPEND (FUNC_PREFIX, symbol), \ | |
115 | APPEND (q, symbol), GLIBC_2_0); \ | |
116 | strong_alias (__APPEND (FUNC_PREFIX, symbol), APPEND (FUNC_PREFIX, symbol)) | |
117 | # define cvt_symbol_1(lib, local, symbol, version) \ | |
118 | compat_symbol (lib, local, symbol, version) | |
119 | # endif | |
120 | #else | |
121 | # define cvt_symbol(symbol) \ | |
122 | strong_alias (__APPEND (FUNC_PREFIX, symbol), APPEND (FUNC_PREFIX, symbol)) | |
123 | #endif | |
124 | cvt_symbol(fcvt); | |
125 | cvt_symbol(ecvt); | |
126 | cvt_symbol(gcvt); |