1 /* Compatibility functions for floating point formatting, reentrant versions. 2 Copyright (C) 1995,96,97,98,99,2000,01,02 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 5 The GNU C Library is free software; you can redistribute it and/or 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. 9 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 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with the GNU C Library; if not, write to the Free 17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 18 02111-1307 USA. */ 19 20 #include <errno.h> 21 #include <float.h> 22 #include <stdio.h> 23 #include <string.h> 24 #include <ctype.h> 25 #include <math.h> 26 #include <stdlib.h> 27 #include <sys/param.h> 28 29 #ifndef FLOAT_TYPE 30 # define FLOAT_TYPE double 31 # define FUNC_PREFIX 32 # define FLOAT_FMT_FLAG 33 # define FLOAT_NAME_EXT 34 # if DBL_MANT_DIG == 53 35 # define NDIGIT_MAX 17 36 # elif DBL_MANT_DIG == 24 37 # define NDIGIT_MAX 9 38 # elif DBL_MANT_DIG == 56 39 # define NDIGIT_MAX 18 40 # else 41 /* See IEEE 854 5.6, table 2 for this formula. Unfortunately we need a 42 compile time constant here, so we cannot use it. */ 43 # error "NDIGIT_MAX must be precomputed" 44 # define NDIGIT_MAX (lrint (ceil (M_LN2 / M_LN10 * DBL_MANT_DIG + 1.0))) 45 # endif 46 #endif 47 48 #define APPEND(a, b) APPEND2 (a, b) 49 #define APPEND2(a, b) a##b 50 51 #define FLOOR APPEND(floor, FLOAT_NAME_EXT) 52 #define FABS APPEND(fabs, FLOAT_NAME_EXT) 53 #define LOG10 APPEND(log10, FLOAT_NAME_EXT) 54 #define EXP APPEND(exp, FLOAT_NAME_EXT) 55 56 57 int 58 APPEND (FUNC_PREFIX, fcvt_r) (value, ndigit, decpt, sign, buf, len) 59 FLOAT_TYPE value; 60 int ndigit, *decpt, *sign; 61 char *buf; 62 size_t len; 63 { 64 ssize_t n; 65 ssize_t i; 66 int left; 67 68 if (buf == NULL) 69 { 70 __set_errno (EINVAL); 71 return -1; 72 } 73 74 left = 0; 75 if (isfinite (value)) 76 { 77 *sign = signbit (value) != 0; 78 if (*sign) 79 value = -value; 80 81 if (ndigit < 0) 82 { 83 /* Rounding to the left of the decimal point. */ 84 while (ndigit < 0) 85 { 86 FLOAT_TYPE new_value = value * 0.1; 87 88 if (new_value < 1.0) 89 { 90 ndigit = 0; 91 break; 92 } 93 94 value = new_value; 95 ++left; 96 ++ndigit; 97 } 98 } 99 } 100 else 101 /* Value is Inf or NaN. */ 102 *sign = 0; 103 104 n = __snprintf (buf, len, "%.*" FLOAT_FMT_FLAG "f", MIN (ndigit, NDIGIT_MAX), 105 value); 106 /* Check for a too small buffer. */ 107 if (n >= (ssize_t) len) 108 return -1; 109 110 i = 0; 111 while (i < n && isdigit (buf[i])) 112 ++i; 113 *decpt = i; 114 115 if (i == 0) 116 /* Value is Inf or NaN. */ 117 return 0; 118 119 if (i < n) 120 { 121 do 122 ++i; 123 while (i < n && !isdigit (buf[i])); 124 125 if (*decpt == 1 && buf[0] == '0' && value != 0.0) 126 { 127 /* We must not have leading zeroes. Strip them all out and 128 adjust *DECPT if necessary. */ 129 --*decpt; 130 while (i < n && buf[i] == '0') 131 { 132 --*decpt; 133 ++i; 134 } 135 } 136 137 memmove (&buf[MAX (*decpt, 0)], &buf[i], n - i); 138 buf[n - (i - MAX (*decpt, 0))] = '\0'; 139 } 140 141 if (left) 142 { 143 *decpt += left; 144 if ((ssize_t) --len > n) 145 { 146 while (left-- > 0 && n < (ssize_t) len) 147 buf[n++] = '0'; 148 buf[n] = '\0'; 149 } 150 } 151 152 return 0; 153 } 154 libc_hidden_def (APPEND (FUNC_PREFIX, fcvt_r)) 155 156 int 157 APPEND (FUNC_PREFIX, ecvt_r) (value, ndigit, decpt, sign, buf, len) 158 FLOAT_TYPE value; 159 int ndigit, *decpt, *sign; 160 char *buf; 161 size_t len; 162 { 163 int exponent = 0; 164 165 if (isfinite (value) && value != 0.0) 166 { 167 /* Slow code that doesn't require -lm functions. */ 168 FLOAT_TYPE d; 169 FLOAT_TYPE f = 1.0; 170 if (value < 0.0) 171 d = -value; 172 else 173 d = value; 174 if (d < 1.0) 175 { 176 do 177 { 178 f *= 10.0; 179 --exponent; 180 } 181 while (d * f < 1.0); 182 183 value *= f; 184 } 185 else if (d >= 10.0) 186 { 187 do 188 { 189 f *= 10; 190 ++exponent; 191 } 192 while (d >= f * 10.0); 193 194 value /= f; 195 } 196 } 197 else if (value == 0.0) 198 /* SUSv2 leaves it unspecified whether *DECPT is 0 or 1 for 0.0. 199 This could be changed to -1 if we want to return 0. */ 200 exponent = 0; 201 202 if (ndigit <= 0 && len > 0) 203 { 204 buf[0] = '\0'; 205 *decpt = 1; 206 *sign = isfinite (value) ? signbit (value) != 0 : 0; 207 } 208 else 209 if (APPEND (FUNC_PREFIX, fcvt_r) (value, MIN (ndigit, NDIGIT_MAX) - 1, 210 decpt, sign, buf, len)) 211 return -1; 212 213 *decpt += exponent; 214 return 0; 215 } 216 libc_hidden_def (APPEND (FUNC_PREFIX, ecvt_r)) 217