ReactOS  r76032
fconv.c
Go to the documentation of this file.
1 /* @(#)fconv.c 1.45 10/11/06 Copyright 1985, 1995-2010 J. Schilling */
2 /*
3  * Convert floating point numbers to strings for format.c
4  * Should rather use the MT-safe routines [efg]convert()
5  *
6  * Copyright (c) 1985, 1995-2010 J. Schilling
7  */
8 /*
9  * The contents of this file are subject to the terms of the
10  * Common Development and Distribution License, Version 1.0 only
11  * (the "License"). You may not use this file except in compliance
12  * with the License.
13  *
14  * See the file CDDL.Schily.txt in this distribution for details.
15  *
16  * When distributing Covered Code, include this CDDL HEADER in each
17  * file and include the License file CDDL.Schily.txt from this distribution.
18  */
19 
20 #include <schily/mconfig.h> /* <- may define NO_FLOATINGPOINT */
21 #ifndef NO_FLOATINGPOINT
22 
23 #ifndef __DO_LONG_DOUBLE__
24 #include <schily/stdlib.h>
25 #include <schily/standard.h>
26 #include <schily/string.h>
27 #include <schily/schily.h>
28 #include <schily/math.h> /* The default place for isinf()/isnan() */
29 #include <schily/nlsdefs.h>
30 
31 #if !defined(HAVE_STDLIB_H) || defined(HAVE_DTOA)
32 extern char *ecvt __PR((double, int, int *, int *));
33 extern char *fcvt __PR((double, int, int *, int *));
34 #endif
35 
36 #if defined(HAVE_ISNAN) && defined(HAVE_ISINF)
37 /*
38  * *BSD alike libc
39  */
40 #define FOUND_ISNAN
41 #define FOUND_ISINF
42 #define FOUND_ISXX
43 #endif
44 
45 #if defined(HAVE_C99_ISNAN) && defined(HAVE_C99_ISINF)
46 #ifndef FOUND_ISXX
47 #define FOUND_ISXX
48 #endif
49 #define FOUND_C99_ISNAN
50 #define FOUND_C99_ISINF
51 #define FOUND_C99_ISXX
52 #endif
53 
54 #if defined(HAVE_FP_H) && !defined(FOUND_ISXX)
55 /*
56  * WAS:
57  * #if defined(__osf__) || defined(_IBMR2) || defined(_AIX)
58  */
59 /*
60  * Moved before HAVE_IEEEFP_H for True64 due to a hint
61  * from Bert De Knuydt <Bert.Deknuydt@esat.kuleuven.ac.be>
62  *
63  * True64 has both fp.h & ieeefp.h but the functions
64  * isnand() & finite() seem to be erreneously not implemented
65  * as a macro and the function lives in libm.
66  * Let's hope that we will not get problems with the new order.
67  */
68 #include <fp.h>
69 #if !defined(isnan) && defined(IS_NAN)
70 #define isnan IS_NAN
71 #define FOUND_ISNAN
72 #endif
73 #if !defined(isinf) && defined(FINITE)
74 #define isinf !FINITE
75 #define FOUND_ISINF
76 #endif
77 #if defined(FOUND_ISNAN) && defined(FOUND_ISINF)
78 #define FOUND_ISXX
79 #endif
80 #endif
81 
82 #if defined(HAVE_IEEEFP_H) && !defined(FOUND_ISXX) && \
83  !defined(FOUND_C99_ISXX)
84 /*
85  * SVR4
86  */
87 #include <ieeefp.h>
88 #ifdef HAVE_ISNAND
89 #ifndef isnan
90 #define isnan isnand
91 #define FOUND_ISNAN
92 #endif
93 #endif
94 #ifdef HAVE_FINITE
95 #ifndef isinf
96 #define isinf !finite
97 #define FOUND_ISINF
98 #endif
99 #endif
100 #if defined(FOUND_ISNAN) && defined(FOUND_ISINF)
101 #define FOUND_ISXX
102 #endif
103 #endif
104 
105 /*
106  * WAS:
107  * #if defined(__hpux) || defined(VMS) || defined(_SCO_DS) || defined(__QNX__)
108  */
109 #ifdef __nneded__
110 #if defined(__hpux) || defined(__QNX__) || defined(__DJGPP__)
111 #ifndef FOUND_C99_ISXX
112 #undef isnan
113 #undef isinf
114 #endif
115 #endif
116 #endif /* __needed__ */
117 
118 /*
119  * As we no longer check for defined(isnan)/defined(isinf), the next block
120  * should also handle the problems with DJGPP, HP-UX, QNX and VMS.
121  */
122 #if !defined(FOUND_ISNAN) && !defined(HAVE_C99_ISNAN)
123 #undef isnan
124 #define isnan(val) (0)
125 #define NO_ISNAN
126 #endif
127 #if !defined(FOUND_ISINF) && !defined(HAVE_C99_ISINF)
128 #undef isinf
129 #define isinf(val) (0)
130 #define NO_ISINF
131 #endif
132 
133 #if defined(NO_ISNAN) || defined(NO_ISINF)
134 #include <schily/float.h> /* For values.h */
135 #if (_IEEE - 0) > 0 /* We know that there is IEEE FP */
136 /*
137  * Note that older HP-UX versions have different #defines for MAXINT in
138  * values.h and sys/param.h
139  */
140 #include <schily/utypes.h>
141 #include <schily/btorder.h>
142 
143 #ifdef WORDS_BIGENDIAN
144 #define fpw_high(x) ((UInt32_t *)&x)[0]
145 #define fpw_low(x) ((UInt32_t *)&x)[1]
146 #else
147 #define fpw_high(x) ((UInt32_t *)&x)[1]
148 #define fpw_low(x) ((UInt32_t *)&x)[0]
149 #endif
150 #define FP_EXP 0x7FF00000
151 #define fp_exp(x) (fpw_high(x) & FP_EXP)
152 #define fp_exc(x) (fp_exp(x) == FP_EXP)
153 
154 #ifdef NO_ISNAN
155 #undef isnan
156 #define isnan(val) (fp_exc(val) && \
157  (fpw_low(val) != 0 || (fpw_high(val) & 0xFFFFF) != 0))
158 #endif
159 #ifdef NO_ISINF
160 #undef isinf
161 #define isinf(val) (fp_exc(val) && \
162  fpw_low(val) == 0 && (fpw_high(val) & 0xFFFFF) == 0)
163 #endif
164 #endif /* We know that there is IEEE FP */
165 #endif /* defined(NO_ISNAN) || defined(NO_ISINF) */
166 
167 
168 #if !defined(HAVE_ECVT) || !defined(HAVE_FCVT) || !defined(HAVE_GCVT)
169 
170 #ifdef NO_USER_XCVT
171  /*
172  * We cannot define our own ecvt()/fcvt()/gcvt() so we need to use
173  * local names instead.
174  */
175 #ifndef HAVE_ECVT
176 #define ecvt js_ecvt
177 #endif
178 #ifndef HAVE_FCVT
179 #define fcvt js_fcvt
180 #endif
181 #ifndef HAVE_GCVT
182 #define gcvt js_gcvt
183 #endif
184 #endif
185 
186 #include "cvt.c"
187 #endif
188 
189 static char _js_nan[] = "(NaN)";
190 static char _js_inf[] = "(Infinity)";
191 
192 static int _ferr __PR((char *, double));
193 #endif /* __DO_LONG_DOUBLE__ */
194 
195 #ifdef __DO_LONG_DOUBLE__
196 #undef MDOUBLE
197 #define MDOUBLE long double
198 #else
199 #undef MDOUBLE
200 #define MDOUBLE double
201 #endif
202 
203 #ifdef abs
204 #undef abs
205 #endif
206 #define abs(i) ((i) < 0 ? -(i) : (i))
207 
208 EXPORT int
209 ftoes(s, val, fieldwidth, ndigits)
210  register char *s;
211  MDOUBLE val;
212  register int fieldwidth;
213  register int ndigits;
214 {
215  register char *b;
216  register char *rs;
217  register int len;
218  register int rdecpt;
219  int decpt;
220  int sign;
221 
222 #ifndef __DO_LONG_DOUBLE__
223  if ((len = _ferr(s, val)) > 0)
224  return (len);
225 #endif
226  rs = s;
227 #ifdef V7_FLOATSTYLE
228  b = ecvt(val, ndigits, &decpt, &sign);
229  rdecpt = decpt;
230 #else
231  b = ecvt(val, ndigits+1, &decpt, &sign);
232  rdecpt = decpt-1;
233 #endif
234 #ifdef __DO_LONG_DOUBLE__
235  len = *b;
236  if (len < '0' || len > '9') { /* Inf/NaN */
237  strcpy(s, b);
238  return (strlen(b));
239  }
240 #endif
241  len = ndigits + 6; /* Punkt e +/- nnn */
242  if (sign)
243  len++;
244  if (fieldwidth > len)
245  while (fieldwidth-- > len)
246  *rs++ = ' ';
247  if (sign)
248  *rs++ = '-';
249 #ifndef V7_FLOATSTYLE
250  if (*b)
251  *rs++ = *b++;
252 #endif
253 #if defined(HAVE_LOCALECONV) && defined(USE_LOCALE)
254  *rs++ = *(localeconv()->decimal_point);
255 #else
256  *rs++ = '.';
257 #endif
258  while (*b && ndigits-- > 0)
259  *rs++ = *b++;
260  *rs++ = 'e';
261  *rs++ = rdecpt >= 0 ? '+' : '-';
262  rdecpt = abs(rdecpt);
263 #ifdef __DO_LONG_DOUBLE__
264  if (rdecpt >= 1000) { /* Max-Exp is > 4000 */
265  *rs++ = rdecpt / 1000 + '0';
266  rdecpt %= 1000;
267  }
268 #endif
269 #ifndef V7_FLOATSTYLE
270  if (rdecpt >= 100)
271 #endif
272  {
273  *rs++ = rdecpt / 100 + '0';
274  rdecpt %= 100;
275  }
276  *rs++ = rdecpt / 10 + '0';
277  *rs++ = rdecpt % 10 + '0';
278  *rs = '\0';
279  return (rs - s);
280 }
281 
282 /*
283  * fcvt() from Cygwin32 is buggy.
284  */
285 #if !defined(HAVE_FCVT) && defined(HAVE_ECVT)
286 #define USE_ECVT
287 #endif
288 
289 EXPORT int
290 ftofs(s, val, fieldwidth, ndigits)
291  register char *s;
292  MDOUBLE val;
293  register int fieldwidth;
294  register int ndigits;
295 {
296  register char *b;
297  register char *rs;
298  register int len;
299  register int rdecpt;
300  int decpt;
301  int sign;
302 
303 #ifndef __DO_LONG_DOUBLE__
304  if ((len = _ferr(s, val)) > 0)
305  return (len);
306 #endif
307  rs = s;
308 #ifdef USE_ECVT
309  /*
310  * Needed on systems with broken fcvt() implementation
311  * (e.g. Cygwin32)
312  */
313  b = ecvt(val, ndigits, &decpt, &sign);
314  /*
315  * The next call is needed to force higher precision.
316  */
317  if (decpt > 0)
318  b = ecvt(val, ndigits+decpt, &decpt, &sign);
319 #else
320  b = fcvt(val, ndigits, &decpt, &sign);
321 #endif
322 #ifdef __DO_LONG_DOUBLE__
323  len = *b;
324  if (len < '0' || len > '9') { /* Inf/NaN */
325  strcpy(s, b);
326  return (strlen(b));
327  }
328 #endif
329  rdecpt = decpt;
330  len = rdecpt + ndigits + 1;
331  if (rdecpt < 0)
332  len -= rdecpt;
333  if (sign)
334  len++;
335  if (fieldwidth > len)
336  while (fieldwidth-- > len)
337  *rs++ = ' ';
338  if (sign)
339  *rs++ = '-';
340  if (rdecpt > 0) {
341  len = rdecpt;
342  while (*b && len-- > 0)
343  *rs++ = *b++;
344 #ifdef USE_ECVT
345  while (len-- > 0)
346  *rs++ = '0';
347 #endif
348  }
349 #ifndef V7_FLOATSTYLE
350  else {
351  *rs++ = '0';
352  }
353 #endif
354 #if defined(HAVE_LOCALECONV) && defined(USE_LOCALE)
355  *rs++ = *(localeconv()->decimal_point);
356 #else
357  *rs++ = '.';
358 #endif
359  if (rdecpt < 0) {
360  len = rdecpt;
361  while (len++ < 0 && ndigits-- > 0)
362  *rs++ = '0';
363  }
364  while (*b && ndigits-- > 0)
365  *rs++ = *b++;
366 #ifdef USE_ECVT
367  while (ndigits-- > 0)
368  *rs++ = '0';
369 #endif
370  *rs = '\0';
371  return (rs - s);
372 }
373 
374 #ifndef __DO_LONG_DOUBLE__
375 
376 #ifdef HAVE_LONGDOUBLE
377 #ifdef HAVE__LDECVT
378 #define qecvt(ld, n, dp, sp) _ldecvt(*(long_double *)&ld, n, dp, sp)
379 #endif
380 #ifdef HAVE__LDFCVT
381 #define qfcvt(ld, n, dp, sp) _ldfcvt(*(long_double *)&ld, n, dp, sp)
382 #endif
383 
384 #if (defined(HAVE_QECVT) || defined(HAVE__LDECVT)) && \
385  (defined(HAVE_QFCVT) || defined(HAVE__LDFCVT))
386 #define __DO_LONG_DOUBLE__
387 #define ftoes qftoes
388 #define ftofs qftofs
389 #define ecvt qecvt
390 #define fcvt qfcvt
391 #include "fconv.c"
392 #undef __DO_LONG_DOUBLE__
393 #endif
394 #endif /* HAVE_LONGDOUBLE */
395 
396 LOCAL int
398  char *s;
399  double val;
400 {
401  if (isnan(val)) {
402  strcpy(s, _js_nan);
403  return (sizeof (_js_nan) - 1);
404  }
405 
406  /*
407  * Check first for NaN because finite() will return 1 on Nan too.
408  */
409  if (isinf(val)) {
410  strcpy(s, _js_inf);
411  return (sizeof (_js_inf) - 1);
412  }
413  return (0);
414 }
415 #endif /* __DO_LONG_DOUBLE__ */
416 #endif /* NO_FLOATINGPOINT */
static size_t double int int int * sign
Definition: printf.c:64
#define abs(i)
Definition: fconv.c:206
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define isnan(val)
Definition: fconv.c:124
EXPORT int ftoes(register char *s, MDOUBLE val, register int fieldwidth, register int ndigits)
Definition: fconv.c:209
char *ecvt __PR((double, int, int *, int *))
static size_t double int int * decpt
Definition: printf.c:64
_Check_return_ _CRTIMP char *__cdecl fcvt(_In_ double _Val, _In_ int _NumOfDec, _Out_ int *_PtDec, _Out_ int *_PtSign)
static char _js_nan[]
Definition: fconv.c:189
unsigned char
Definition: typeof.h:27
static size_t double int ndigits
Definition: printf.c:64
#define b
Definition: ke_i.h:79
#define LOCAL(type)
Definition: jmorecfg.h:289
GLuint GLfloat * val
Definition: glext.h:7180
#define MDOUBLE
Definition: fconv.c:200
_Check_return_ _CRTIMP char *__cdecl ecvt(_In_ double _Val, _In_ int _NumOfDigits, _Out_ int *_PtDec, _Out_ int *_PtSign)
static char _js_inf[]
Definition: fconv.c:190
GLdouble s
Definition: gl.h:2039
GLenum GLsizei len
Definition: glext.h:6722
_Check_return_opt_ _CRTIMP struct lconv *__cdecl localeconv(void)
Definition: locale.c:601
EXPORT int ftofs(register char *s, MDOUBLE val, register int fieldwidth, register int ndigits)
Definition: fconv.c:290
#define isinf(val)
Definition: fconv.c:129
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
LOCAL int _ferr(char *s, double val)
Definition: fconv.c:397