xref: /haiku/src/system/libroot/posix/glibc/misc/efgcvt.c (revision 1e60bdeab63fa7a57bc9a55b032052e95a18bd2c)
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