ReactOS 0.4.15-dev-7788-g1ad9096
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)
32extern char *ecvt __PR((double, int, int *, int *));
33extern 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
189static char _js_nan[] = "(NaN)";
190static char _js_inf[] = "(Infinity)";
191
192static 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
208EXPORT int
209ftoes(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
289EXPORT int
290ftofs(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
396LOCAL 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 */
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
static char _js_inf[]
Definition: fconv.c:190
#define isnan(val)
Definition: fconv.c:124
#define isinf(val)
Definition: fconv.c:129
LOCAL int _ferr(char *s, double val)
Definition: fconv.c:397
static char _js_nan[]
Definition: fconv.c:189
EXPORT int ftoes(register char *s, MDOUBLE val, register int fieldwidth, register int ndigits)
Definition: fconv.c:209
EXPORT int ftofs(register char *s, MDOUBLE val, register int fieldwidth, register int ndigits)
Definition: fconv.c:290
#define abs(i)
Definition: fconv.c:206
#define MDOUBLE
Definition: fconv.c:200
GLdouble s
Definition: gl.h:2039
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLuint GLfloat * val
Definition: glext.h:7180
GLenum GLsizei len
Definition: glext.h:6722
_Check_return_opt_ _CRTIMP struct lconv *__cdecl localeconv(void)
Definition: locale.c:601
_Check_return_ _CRTIMP char *__cdecl fcvt(_In_ double _Val, _In_ int _NumOfDec, _Out_ int *_PtDec, _Out_ int *_PtSign)
_Check_return_ _CRTIMP char *__cdecl ecvt(_In_ double _Val, _In_ int _NumOfDigits, _Out_ int *_PtDec, _Out_ int *_PtSign)
#define LOCAL(type)
Definition: jmorecfg.h:289
#define b
Definition: ke_i.h:79
#define sign(x)
Definition: mapdesc.cc:613
static size_t double int ndigits
Definition: printf.c:72
static size_t double int int * decpt
Definition: printf.c:72
#define __PR(a)
Definition: prototyp.h:106