1 /* Compatibility functions for floating point formatting. 2 Copyright (C) 1995, 1996, 1997, 1999, 2002 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 <math.h> 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <sys/param.h> 24 #include <float.h> 25 #include <bits/libc-lock.h> 26 27 #ifndef FLOAT_TYPE 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. */ 33 # define MAXDIG (NDIGIT_MAX + 3) 34 # define FCVT_MAXDIG (DBL_MAX_10_EXP + MAXDIG) 35 # if DBL_MANT_DIG == 53 36 # define NDIGIT_MAX 17 37 # elif DBL_MANT_DIG == 24 38 # define NDIGIT_MAX 9 39 # elif DBL_MANT_DIG == 56 40 # define NDIGIT_MAX 18 41 # else 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" 45 # define NDIGIT_MAX (lrint (ceil (M_LN2 / M_LN10 * DBL_MANT_DIG + 1.0))) 46 # endif 47 #endif 48 49 #define APPEND(a, b) APPEND2 (a, b) 50 #define APPEND2(a, b) a##b 51 52 53 #define FCVT_BUFFER APPEND (FUNC_PREFIX, fcvt_buffer) 54 #define FCVT_BUFPTR APPEND (FUNC_PREFIX, fcvt_bufptr) 55 #define ECVT_BUFFER APPEND (FUNC_PREFIX, ecvt_buffer) 56 57 58 static char FCVT_BUFFER[MAXDIG]; 59 static char ECVT_BUFFER[MAXDIG]; 60 libc_freeres_ptr (static char *FCVT_BUFPTR); 61 62 char * 63 APPEND (FUNC_PREFIX, fcvt) (value, ndigit, decpt, sign) 64 FLOAT_TYPE value; 65 int ndigit, *decpt, *sign; 66 { 67 if (FCVT_BUFPTR == NULL) 68 { 69 if (APPEND (FUNC_PREFIX, fcvt_r) (value, ndigit, decpt, sign, 70 FCVT_BUFFER, MAXDIG) != -1) 71 return FCVT_BUFFER; 72 73 FCVT_BUFPTR = (char *) malloc (FCVT_MAXDIG); 74 if (FCVT_BUFPTR == NULL) 75 return FCVT_BUFFER; 76 } 77 78 (void) APPEND (FUNC_PREFIX, fcvt_r) (value, ndigit, decpt, sign, 79 FCVT_BUFPTR, FCVT_MAXDIG); 80 81 return FCVT_BUFPTR; 82 } 83 84 85 char * 86 APPEND (FUNC_PREFIX, ecvt) (value, ndigit, decpt, sign) 87 FLOAT_TYPE value; 88 int ndigit, *decpt, *sign; 89 { 90 (void) APPEND (FUNC_PREFIX, ecvt_r) (value, ndigit, decpt, sign, 91 ECVT_BUFFER, MAXDIG); 92 93 return ECVT_BUFFER; 94 } 95 96 char * 97 APPEND (FUNC_PREFIX, gcvt) (value, ndigit, buf) 98 FLOAT_TYPE value; 99 int ndigit; 100 char *buf; 101 { 102 sprintf (buf, "%.*" FLOAT_FMT_FLAG "g", MIN (ndigit, NDIGIT_MAX), value); 103 return buf; 104 } 105