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
58static char FCVT_BUFFER[MAXDIG];
59static char ECVT_BUFFER[MAXDIG];
60libc_freeres_ptr (static char *FCVT_BUFPTR);
61
62char *
63APPEND (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
85char *
86APPEND (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
96char *
97APPEND (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