Update to LGPL v2.1.
[kopensolaris-gnu/glibc.git] / misc / efgcvt.c
1 /* Compatibility functions for floating point formatting.
2    Copyright (C) 1995, 1996, 1997, 1999 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 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
106 /* Free all resources if necessary.  */
107 static void __attribute__ ((unused))
108 free_mem (void)
109 {
110   if (FCVT_BUFPTR != NULL)
111     free (FCVT_BUFPTR);
112 }                  
113
114 text_set_element (__libc_subfreeres, free_mem);