ReactOS 0.4.15-dev-7788-g1ad9096
num_put_float.cpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 1999
3 * Silicon Graphics Computer Systems, Inc.
4 *
5 * Copyright (c) 1999
6 * Boris Fomitchev
7 *
8 * This material is provided "as is", with absolutely no warranty expressed
9 * or implied. Any use is at your own risk.
10 *
11 * Permission to use or copy this software for any purpose is hereby granted
12 * without fee, provided the above notices are retained on all copies.
13 * Permission to modify the code and to distribute modified code is granted,
14 * provided the above notices are retained, and a notice that the code was
15 * modified is included with the above copyright notice.
16 *
17 */
18
19#include "stlport_prefix.h"
20
21#include <cmath>
22#include <ios>
23#include <locale>
24
25#if defined (__DECCXX)
26# define NDIG 400
27#else
28# define NDIG 82
29#endif
30
31#define todigit(x) ((x)+'0')
32
33#if defined (_STLP_UNIX)
34
35# if defined (__sun)
36# include <floatingpoint.h>
37# endif
38
39# if defined (__sun) || defined (__digital__) || defined (__sgi) || defined (_STLP_SCO_OPENSERVER) || defined (__NCR_SVR)
40// DEC, SGI & Solaris need this
41# include <values.h>
42# include <nan.h>
43# endif
44
45# if defined (__QNXNTO__) || ( defined(__GNUC__) && defined(__APPLE__) ) || defined(_STLP_USE_UCLIBC) /* 0.9.26 */ || \
46 defined(__FreeBSD__)
47# define USE_SPRINTF_INSTEAD
48# endif
49
50# if defined (_AIX) // JFA 3-Aug-2000
51# include <math.h>
52# include <float.h>
53# endif
54
55# include <math.h>
56#endif
57
58#include <cstdio>
59#include <cstdlib>
60
61#if defined (_STLP_MSVC_LIB) || defined (__MINGW32__) || defined (__BORLANDC__) || defined (__DJGPP) || \
62 defined (_STLP_SCO_OPENSERVER) || defined (__NCR_SVR)
63# include <float.h>
64#endif
65
66#if defined (__MRC__) || defined (__SC__) || defined (_CRAY) //*TY 02/24/2000 - added support for MPW
67# include <fp.h>
68#endif
69
70#if defined (__CYGWIN__)
71# include <ieeefp.h>
72#endif
73
74#if defined (__MSL__)
75# include <cstdlib> // for atoi
76# include <cstdio> // for snprintf
77# include <algorithm>
78# include <cassert>
79#endif
80
81#if defined (__ISCPP__)
82# include <cfloat>
83#endif
84
85#include <algorithm>
86
87#if defined (__DMC__)
88# define snprintf _snprintf
89#endif
90
92
94
95#if defined (__MWERKS__) || defined(__BEOS__)
96# define USE_SPRINTF_INSTEAD
97#endif
98
99template <int N>
100struct _Dig
101{
102 enum { dig = _Dig<N/10>::dig + 1 };
103};
104
106struct _Dig<0>
107{
108 enum { dig = 0 };
109};
110
111#ifdef _STLP_NO_LONG_DOUBLE
112# define MAXEDIGITS int(_Dig<DBL_MAX_10_EXP>::dig)
113# define MAXFSIG DBL_DIG
114# define MAXFCVT (DBL_DIG + 1)
115#else
116# define MAXEDIGITS int(_Dig<LDBL_MAX_10_EXP>::dig)
117# define MAXFSIG LDBL_DIG
118# define MAXFCVT (LDBL_DIG + 1)
119#endif
120
121// Tests for infinity and NaN differ on different OSs. We encapsulate
122// these differences here.
123#if !defined (USE_SPRINTF_INSTEAD)
124# if defined (__hpux) && defined (__GNUC__)
125# define _STLP_USE_SIGN_HELPER
126# elif defined (__DJGPP) || (defined (_STLP_USE_GLIBC) && ! defined (__MSL__)) || \
127 defined (__CYGWIN__) || \
128 defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || \
129 defined (__HP_aCC)
130static inline bool _Stl_is_nan_or_inf(double x)
131# if defined (isfinite)
132{ return !isfinite(x); }
133# else
134{ return !finite(x); }
135# endif
136static inline bool _Stl_is_neg_nan(double x) { return isnan(x) && ( copysign(1., x) < 0 ); }
137static inline bool _Stl_is_inf(double x) { return isinf(x); }
138// inline bool _Stl_is_neg_inf(double x) { return isinf(x) < 0; }
139static inline bool _Stl_is_neg_inf(double x) { return isinf(x) && x < 0; }
140# elif (defined (__unix) || defined (__unix__)) && \
141 !defined (__APPLE__) && !defined (__DJGPP) && !defined(__osf__) && \
142 !defined (_CRAY)
143static inline bool _Stl_is_nan_or_inf(double x) { return IsNANorINF(x); }
144static inline bool _Stl_is_inf(double x) { return IsNANorINF(x) && IsINF(x); }
145static inline bool _Stl_is_neg_inf(double x) { return (IsINF(x)) && (x < 0.0); }
146static inline bool _Stl_is_neg_nan(double x) { return IsNegNAN(x); }
147# elif defined (_STLP_MSVC_LIB) || defined (__MINGW32__) || defined (__BORLANDC__)
148static inline bool _Stl_is_nan_or_inf(double x) { return !_finite(x); }
149# if !defined (__BORLANDC__)
150static inline bool _Stl_is_inf(double x) {
151 int fclass = _fpclass(x);
152 return fclass == _FPCLASS_NINF || fclass == _FPCLASS_PINF;
153}
154static inline bool _Stl_is_neg_inf(double x) { return _fpclass(x) == _FPCLASS_NINF; }
155# else
156static inline bool _Stl_is_inf(double x) { return _Stl_is_nan_or_inf(x) && !_isnan(x);}
157static inline bool _Stl_is_neg_inf(double x) { return _Stl_is_inf(x) && x < 0 ; }
158# endif
159static inline bool _Stl_is_neg_nan(double x) { return _isnan(x) && _copysign(1., x) < 0 ; }
160# if defined (__BORLANDC__)
161static inline bool _Stl_is_nan_or_inf(long double x) { return !_finitel(x); }
162static inline bool _Stl_is_inf(long double x) { return _Stl_is_nan_or_inf(x) && !_isnanl(x);}
163static inline bool _Stl_is_neg_inf(long double x) { return _Stl_is_inf(x) && x < 0 ; }
164static inline bool _Stl_is_neg_nan(long double x) { return _isnanl(x) && _copysignl(1.l, x) < 0 ; }
165# elif !defined (_STLP_NO_LONG_DOUBLE)
166// Simply there to avoid warning long double -> double implicit conversion:
167static inline bool _Stl_is_nan_or_inf(long double x) { return _Stl_is_nan_or_inf(__STATIC_CAST(double, x)); }
168static inline bool _Stl_is_inf(long double x) { return _Stl_is_inf(__STATIC_CAST(double, x));}
169static inline bool _Stl_is_neg_inf(long double x) { return _Stl_is_neg_inf(__STATIC_CAST(double, x)); }
170static inline bool _Stl_is_neg_nan(long double x) { return _Stl_is_neg_nan(__STATIC_CAST(double, x)); }
171# endif
172# elif defined (__MRC__) || defined (__SC__) || defined (__DMC__)
173static bool _Stl_is_nan_or_inf(double x) { return isnan(x) || !isfinite(x); }
174static bool _Stl_is_inf(double x) { return !isfinite(x); }
175static bool _Stl_is_neg_inf(double x) { return !isfinite(x) && signbit(x); }
176static bool _Stl_is_neg_nan(double x) { return isnan(x) && signbit(x); }
177# elif /* defined(__FreeBSD__) || defined(__OpenBSD__) || */ (defined(__GNUC__) && defined(__APPLE__))
178static inline bool _Stl_is_nan_or_inf(double x) { return !finite(x); }
179static inline bool _Stl_is_inf(double x) { return _Stl_is_nan_or_inf(x) && ! isnan(x); }
180static inline bool _Stl_is_neg_inf(double x) { return _Stl_is_inf(x) && x < 0 ; }
181static inline bool _Stl_is_neg_nan(double x) { return isnan(x) && copysign(1., x) < 0 ; }
182# elif defined( _AIX ) // JFA 11-Aug-2000
183static bool _Stl_is_nan_or_inf(double x) { return isnan(x) || !finite(x); }
184static bool _Stl_is_inf(double x) { return !finite(x); }
185// bool _Stl_is_neg_inf(double x) { return _class(x) == FP_MINUS_INF; }
186static bool _Stl_is_neg_inf(double x) { return _Stl_is_inf(x) && ( copysign(1., x) < 0 ); }
187static bool _Stl_is_neg_nan(double x) { return isnan(x) && ( copysign(1., x) < 0 ); }
188# elif defined (__ISCPP__)
189static inline bool _Stl_is_nan_or_inf (double x) { return _fp_isINF(x) || _fp_isNAN(x); }
190static inline bool _Stl_is_inf (double x) { return _fp_isINF(x); }
191static inline bool _Stl_is_neg_inf (double x) { return _fp_isINF(x) && x < 0; }
192static inline bool _Stl_is_neg_nan (double x) { return _fp_isNAN(x) && x < 0; }
193# elif defined (_CRAY)
194# if defined (_CRAYIEEE)
195static inline bool _Stl_is_nan_or_inf(double x) { return isnan(x) || isinf(x); }
196static inline bool _Stl_is_inf(double x) { return isinf(x); }
197static inline bool _Stl_is_neg_inf(double x) { return isinf(x) && signbit(x); }
198static inline bool _Stl_is_neg_nan(double x) { return isnan(x) && signbit(x); }
199# else
200static inline bool _Stl_is_nan_or_inf(double x) { return false; }
201static inline bool _Stl_is_inf(double x) { return false; }
202static inline bool _Stl_is_neg_inf(double x) { return false; }
203static inline bool _Stl_is_neg_nan(double x) { return false; }
204# endif
205# else // nothing from above
206# define USE_SPRINTF_INSTEAD
207# endif
208#endif // !USE_SPRINTF_INSTEAD
209
210#if !defined (USE_SPRINTF_INSTEAD)
211// Reentrant versions of floating-point conversion functions. The argument
212// lists look slightly different on different operating systems, so we're
213// encapsulating the differences here.
214
215# if defined (__CYGWIN__) || defined(__DJGPP)
216static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf)
217{ return ecvtbuf(x, n, pt, sign, buf); }
218static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf)
219{ return fcvtbuf(x, n, pt, sign, buf); }
220# if !defined (_STLP_NO_LONG_DOUBLE)
221# if defined (__CYGWIN__)
222# define _STLP_EMULATE_LONG_DOUBLE_CVT
223# else
224static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf)
225{ return ecvtbuf(x, n, pt, sign, buf); }
226static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf)
227{ return fcvtbuf(x, n, pt, sign, buf); }
228# endif
229# endif
230# elif defined (_STLP_USE_GLIBC)
231static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf, size_t bsize)
232{ return ecvt_r(x, n, pt, sign, buf, bsize) == 0 ? buf : 0; }
233static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf, size_t bsize)
234{ return fcvt_r(x, n, pt, sign, buf, bsize) == 0 ? buf : 0; }
235# ifndef _STLP_NO_LONG_DOUBLE
236static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf, size_t bsize)
237{ return qecvt_r(x, n, pt, sign, buf, bsize) == 0 ? buf : 0; }
238static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf, size_t bsize)
239{ return qfcvt_r(x, n, pt, sign, buf, bsize) == 0 ? buf : 0; }
240# endif
241# define _STLP_NEED_CVT_BUFFER_SIZE
242# elif defined (__sun)
243static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf)
244{ return econvert(x, n, pt, sign, buf); }
245static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf)
246{ return fconvert(x, n, pt, sign, buf); }
247# ifndef _STLP_NO_LONG_DOUBLE
248static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf)
249{ return qeconvert(&x, n, pt, sign, buf); }
250static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf)
251{ return qfconvert(&x, n, pt, sign, buf); }
252# endif
253# elif defined (__DECCXX)
254static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf, size_t bsize)
255{ return (ecvt_r(x, n, pt, sign, buf, bsize) == 0 ? buf : 0); }
256static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf, size_t bsize)
257{ return (fcvt_r(x, n, pt, sign, buf, bsize) == 0 ? buf : 0); }
258# ifndef _STLP_NO_LONG_DOUBLE
259// fbp : no "long double" conversions !
260static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf, size_t bsize)
261{ return (ecvt_r((double)x, n, pt, sign, buf, bsize) == 0 ? buf : 0) ; }
262static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf, size_t bsize)
263{ return (fcvt_r((double)x, n, pt, sign, buf, bsize) == 0 ? buf : 0); }
264# endif
265# define _STLP_NEED_CVT_BUFFER_SIZE
266# elif defined (__hpux)
267static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign)
268{ return ecvt(x, n, pt, sign); }
269static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign)
270{ return fcvt(x, n, pt, sign); }
271# if !defined (_STLP_NO_LONG_DOUBLE)
272static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign)
273{ return _ldecvt(*(long_double*)&x, n, pt, sign); }
274static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign)
275{ return _ldfcvt(*(long_double*)&x, n, pt, sign); }
276# endif
277# define _STLP_CVT_NEED_SYNCHRONIZATION
278# elif defined (__unix) && !defined (__APPLE__) && !defined (_CRAY)
279static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf)
280{ return ecvt_r(x, n, pt, sign, buf); }
281static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf)
282{ return fcvt_r(x, n, pt, sign, buf); }
283# if !defined (_STLP_NO_LONG_DOUBLE)
284static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf)
285{ return qecvt_r(x, n, pt, sign, buf); }
286static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf)
287{ return qfcvt_r(x, n, pt, sign, buf); }
288# endif
289# elif defined (_STLP_MSVC_LIB) || defined (__MINGW32__) || defined (__BORLANDC__)
290# if defined (_STLP_USE_SAFE_STRING_FUNCTIONS)
291# define _STLP_APPEND(a, b) a##b
292# define _STLP_BUF_PARAMS , char* buf, size_t bsize
293# define _STLP_SECURE_FUN(F, X, N, PT, SIGN) _STLP_APPEND(F, _s)(buf, bsize, X, N, PT, SIGN); return buf
294# else
295# define _STLP_BUF_PARAMS
296# define _STLP_SECURE_FUN(F, X, N, PT, SIGN) return F(X, N, PT, SIGN)
297# define _STLP_CVT_NEED_SYNCHRONIZATION
298# endif
299static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign _STLP_BUF_PARAMS)
300{ _STLP_SECURE_FUN(_ecvt, x, n, pt, sign); }
301static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign _STLP_BUF_PARAMS)
302{ _STLP_SECURE_FUN(_fcvt, x, n, pt, sign); }
303# if !defined (_STLP_NO_LONG_DOUBLE)
304# if defined (_STLP_USE_SAFE_STRING_FUNCTIONS)
305# define _STLP_PARAMS , buf, bsize
306# else
307# define _STLP_PARAMS
308# endif
309static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign _STLP_BUF_PARAMS)
310{ return _Stl_ecvtR(__STATIC_CAST(double, x), n, pt, sign _STLP_PARAMS); }
311static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign _STLP_BUF_PARAMS)
312{ return _Stl_fcvtR(__STATIC_CAST(double, x), n, pt, sign _STLP_PARAMS); }
313# undef _STLP_PARAMS
314# endif
315# undef _STLP_SECURE_FUN
316# undef _STLP_BUF_PARAMS
317# undef _STLP_APPEND
318# if defined (__BORLANDC__) /* || defined (__GNUC__) MinGW do not support 'L' modifier so emulation do not work */
319# define _STLP_EMULATE_LONG_DOUBLE_CVT
320# endif
321# elif defined (__ISCPP__)
322static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf)
323{ return _fp_ecvt( x, n, pt, sign, buf); }
324static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf)
325{ return _fp_fcvt(x, n, pt, sign, buf); }
326# if !defined (_STLP_NO_LONG_DOUBLE)
327static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf)
328{ return _fp_ecvt( x, n, pt, sign, buf); }
329static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf)
330{ return _fp_fcvt(x, n, pt, sign, buf); }
331# endif
332# elif defined (_AIX) || defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || \
333 defined (__MRC__) || defined (__SC__) || defined (_CRAY) || \
334 defined (_STLP_SCO_OPENSERVER) || defined (__NCR_SVR) || \
335 defined (__DMC__)
336static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign)
337{ return ecvt(x, n, pt, sign ); }
338static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign)
339{ return fcvt(x, n, pt, sign); }
340# if !defined (_STLP_NO_LONG_DOUBLE)
341static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign)
342{ return ecvt(x, n, pt, sign ); }
343static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign)
344{ return fcvt(x, n, pt, sign); }
345# endif
346# define _STLP_CVT_NEED_SYNCHRONIZATION
347# else
348# error Missing _Stl_ecvtR and _Stl_fcvtR implementations.
349# endif
350
351#if defined (_STLP_CVT_NEED_SYNCHRONIZATION)
352/* STLport synchronize access to *cvt functions but those methods might
353 * be called from outside, in this case we will still have a race condition. */
354# if defined (_STLP_THREADS)
355static _STLP_STATIC_MUTEX& put_float_mutex() {
356 static _STLP_STATIC_MUTEX __put_float_mutex _STLP_MUTEX_INITIALIZER;
357 return __put_float_mutex;
358}
359static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char* buf) {
360 _STLP_auto_lock lock(put_float_mutex());
361 strcpy(buf, _Stl_ecvtR(x, n, pt, sign)); return buf;
362}
363static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char* buf) {
364 _STLP_auto_lock lock(put_float_mutex());
365 strcpy(buf, _Stl_fcvtR(x, n, pt, sign)); return buf;
366}
367# if !defined (_STLP_NO_LONG_DOUBLE) && !defined (_STLP_EMULATE_LONG_DOUBLE_CVT)
368static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf) {
369 _STLP_auto_lock lock(put_float_mutex());
370 strcpy(buf, _Stl_ecvtR(x, n, pt, sign)); return buf;
371}
372static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf) {
373 _STLP_auto_lock lock(put_float_mutex());
374 strcpy(buf, _Stl_fcvtR(x, n, pt, sign)); return buf;
375}
376# endif
377# else
378static inline char* _Stl_ecvtR(double x, int n, int* pt, int* sign, char*)
379{ return _Stl_ecvtR(x, n, pt, sign); }
380static inline char* _Stl_fcvtR(double x, int n, int* pt, int* sign, char*)
381{ return _Stl_fcvtR(x, n, pt, sign); }
382# if !defined (_STLP_NO_LONG_DOUBLE) && !defined (_STLP_EMULATE_LONG_DOUBLE_CVT)
383static inline char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char*)
384{ return _Stl_ecvtR(x, n, pt, sign); }
385static inline char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char*)
386{ return _Stl_fcvtR(x, n, pt, sign); }
387# endif
388# endif
389#endif
390
391# if !defined (_STLP_USE_SAFE_STRING_FUNCTIONS) && !defined (_STLP_NEED_CVT_BUFFER_SIZE)
392# define _STLP_CVT_BUFFER(B) B
393# else
394# define _STLP_CVT_BUFFER(B) _STLP_ARRAY_AND_SIZE(B)
395# endif
396
397# if defined (_STLP_EMULATE_LONG_DOUBLE_CVT)
398static void __fill_fmtbuf(char* fmtbuf, ios_base::fmtflags flags, char long_modifier);
399
400// Emulation of ecvt/fcvt functions using sprintf:
401static char* _Stl_ecvtR(long double x, int n, int* pt, int* sign, char* buf) {
402 // If long double value can be safely converted to double without losing precision
403 // we use the ecvt function for double:
404 double y = __STATIC_CAST(double, x);
405 if (x == y)
406 return _Stl_ecvtR(y, n, pt, sign, buf);
407
408 char fmtbuf[32];
409 __fill_fmtbuf(fmtbuf, 0, 'L');
410 sprintf(buf, fmtbuf, n, x < 0.0l ? -x : x);
411 /* We are waiting for something having the form x.xxxe+yyyy */
412 *pt = 0;
413 *sign = 0;
414 int i = -1;
415 int offset = 0;
416 while (buf[++i] != 0 && n != 0) {
417 if (buf[i] >= '0' && buf[i] <= '9') {
418 --n;
419 if (offset != 0)
420 buf[i - offset] = buf[i];
421 }
422 else {
423 if (offset != 0) break;
424 ++offset;
425 *pt = i;
426 }
427 }
428 if (offset != 0)
429 buf[i - offset] = 0;
430 // Extract exponent part in point position:
431 int e = 0;
432 while (buf[++i] != 0) {
433 if (buf[i] >= '0' && buf[i] <= '9') {
434 e = e * 10 + (buf[i] - '0');
435 }
436 }
437 *pt += e;
438 return buf;
439}
440
441static char* _Stl_fcvtR(long double x, int n, int* pt, int* sign, char* buf) {
442 // If long double value can be safely converted to double without losing precision
443 // we use the fcvt function for double:
444 double y = __STATIC_CAST(double, x);
445 if (x == y)
446 return _Stl_fcvtR(y, n, pt, sign, buf);
447
448 char fmtbuf[32];
449 __fill_fmtbuf(fmtbuf, ios_base::fixed, 'L');
450 sprintf(buf, fmtbuf, n, x < 0.0l ? -x : x);
451 *pt = 0;
452 *sign = 0;
453 int i = -1;
454 int offset = 0;
455 while (buf[++i] != 0 && (offset == 0 || n != 0)) {
456 if (buf[i] >= '0' && buf[i] <= '9') {
457 if (offset != 0) {
458 --n;
459 buf[i - offset] = buf[i];
460 }
461 }
462 else {
463 ++offset;
464 *pt = i;
465 }
466 }
467 if (offset != 0)
468 buf[i - offset] = 0;
469 else
470 *pt = i;
471 return buf;
472}
473#endif
474
475//----------------------------------------------------------------------
476// num_put
477
478// __format_float formats a mantissa and exponent as returned by
479// one of the conversion functions (ecvt_r, fcvt_r, qecvt_r, qfcvt_r)
480// according to the specified precision and format flags. This is
481// based on doprnt but is much simpler since it is concerned only
482// with floating point input and does not consider all formats. It
483// also does not deal with blank padding, which is handled by
484// __copy_float_and_fill.
485
486static size_t __format_float_scientific( __iostring& buf, const char *bp,
487 int decpt, int sign, bool is_zero,
489 int precision) {
490 // sign if required
491 if (sign)
492 buf += '-';
493 else if (flags & ios_base::showpos)
494 buf += '+';
495
496 // first digit of mantissa
497 buf += *bp++;
498
499 // start of grouping position, grouping won't occur in scientific notation
500 // as it is impossible to have something like 1234.0e04 but we return a correct
501 // group position for coherency with __format_float_fixed.
502 size_t __group_pos = buf.size();
503
504 // decimal point if required
505 if (precision != 0 || flags & ios_base::showpoint) {
506 buf += '.';
507 }
508
509 // rest of mantissa
510 while (*bp != 0 && precision--)
511 buf += *bp++;
512
513 // trailing 0 if needed
514 if (precision > 0)
515 buf.append(precision, '0');
516
517 // exponent size = number of digits + exponent sign + exponent symbol + trailing zero
518 char expbuf[MAXEDIGITS + 3];
519 //We start filling at the buffer end
520 char *suffix = expbuf + MAXEDIGITS + 2;
521 *suffix = 0;
522 if (!is_zero) {
523 int nn = decpt - 1;
524 if (nn < 0)
525 nn = -nn;
526 for (; nn > 9; nn /= 10)
527 *--suffix = (char) todigit(nn % 10);
528 *--suffix = (char) todigit(nn);
529 }
530
531 // prepend leading zeros to exponent
532 // C89 Standard says that it should be at least 2 digits, C99 Standard says that
533 // we stop prepend zeros if more than 3 digits. To repect both STLport prepend zeros
534 // until it is 2 digits.
535 while (suffix > &expbuf[MAXEDIGITS])
536 *--suffix = '0';
537
538 // put in the exponent sign
539 *--suffix = (char) ((decpt > 0 || is_zero ) ? '+' : '-');
540
541 // put in the e
542 *--suffix = flags & ios_base::uppercase ? 'E' : 'e';
543
544 // copy the suffix
545 buf += suffix;
546 return __group_pos;
547}
548
549static size_t __format_float_fixed( __iostring &buf, const char *bp,
550 int decpt, int sign,
552 int precision) {
553 if ( sign && (decpt > -precision) && (*bp != 0) )
554 buf += '-';
555 else if ( flags & ios_base::showpos )
556 buf += '+';
557
558 // digits before decimal point
559 int nnn = decpt;
560 do {
561 buf += (nnn <= 0 || *bp == 0) ? '0' : *bp++;
562 } while ( --nnn > 0 );
563
564 // start of grouping position
565 size_t __group_pos = buf.size();
566
567 // decimal point if needed
568 if ( flags & ios_base::showpoint || precision > 0 ) {
569 buf += '.';
570 }
571
572 // digits after decimal point if any
573 while ( *bp != 0 && --precision >= 0 ) {
574 buf += (++decpt <= 0) ? '0' : *bp++;
575 }
576
577 // trailing zeros if needed
578 if (precision > 0)
579 buf.append(precision, '0');
580
581 return __group_pos;
582}
583
584#if defined (_STLP_USE_SIGN_HELPER)
585template<class _FloatT>
586struct float_sign_helper {
587 float_sign_helper(_FloatT __x)
588 { _M_number._num = __x; }
589
590 bool is_negative() const {
591 const unsigned short sign_mask(1 << (sizeof(unsigned short) * CHAR_BIT - 1));
592 return (get_sign_word() & sign_mask) != 0;
593 }
594private:
595 union {
596 unsigned short _Words[8];
597 _FloatT _num;
598 } _M_number;
599
600 unsigned short get_word_higher() const _STLP_NOTHROW
601 { return _M_number._Words[0]; }
602 unsigned short get_word_lower() const _STLP_NOTHROW
603 { return _M_number._Words[(sizeof(_FloatT) >= 12 ? 10 : sizeof(_FloatT)) / sizeof(unsigned short) - 1]; }
604 unsigned short get_sign_word() const _STLP_NOTHROW
605# if defined (_STLP_BIG_ENDIAN)
606 { return get_word_higher(); }
607# else /* _STLP_LITTLE_ENDIAN */
608 { return get_word_lower(); }
609# endif
610};
611#endif
612
613template <class _FloatT>
614static size_t __format_nan_or_inf(__iostring& buf, _FloatT x, ios_base::fmtflags flags) {
615 static const char* inf[2] = { "inf", "Inf" };
616 static const char* nan[2] = { "nan", "NaN" };
617 const char** inf_or_nan;
618#if !defined (_STLP_USE_SIGN_HELPER)
619 if (_Stl_is_inf(x)) { // Infinity
620 inf_or_nan = inf;
621 if (_Stl_is_neg_inf(x))
622 buf += '-';
623 else if (flags & ios_base::showpos)
624 buf += '+';
625 } else { // NaN
626 inf_or_nan = nan;
627 if (_Stl_is_neg_nan(x))
628 buf += '-';
629 else if (flags & ios_base::showpos)
630 buf += '+';
631 }
632#else
633 typedef numeric_limits<_FloatT> limits;
634 if (x == limits::infinity() || x == -limits::infinity()) {
635 inf_or_nan = inf;
636 } else { // NaN
637 inf_or_nan = nan;
638 }
639 float_sign_helper<_FloatT> helper(x);
640 if (helper.is_negative())
641 buf += '-';
642 else if (flags & ios_base::showpos)
643 buf += '+';
644#endif
645 size_t ret = buf.size();
646 buf += inf_or_nan[flags & ios_base::uppercase ? 1 : 0];
647 return ret;
648}
649
650static inline size_t __format_float(__iostring &buf, const char * bp,
651 int decpt, int sign, bool is_zero,
653 int precision) {
654 size_t __group_pos = 0;
655 switch (flags & ios_base::floatfield) {
656 case ios_base::scientific:
657 __group_pos = __format_float_scientific( buf, bp, decpt, sign, is_zero,
659 break;
660 case ios_base::fixed:
661 __group_pos = __format_float_fixed( buf, bp, decpt, sign,
663 break;
664 default: // g format
665 // establish default precision
666 if (flags & ios_base::showpoint || precision > 0) {
667 if (precision == 0) precision = 1;
668 } else
669 precision = 6;
670
671 // reset exponent if value is zero
672 if (is_zero)
673 decpt = 1;
674
675 int kk = precision;
676 if (!(flags & ios_base::showpoint)) {
677 size_t n = strlen(bp);
678 if (n < (size_t)kk)
679 kk = (int)n;
680 while (kk >= 1 && bp[kk-1] == '0')
681 --kk;
682 }
683
684 if (decpt < -3 || decpt > precision) {
685 precision = kk - 1;
686 __group_pos = __format_float_scientific( buf, bp, decpt, sign, is_zero,
688 } else {
689 precision = kk - decpt;
690 __group_pos = __format_float_fixed( buf, bp, decpt, sign,
692 }
693 break;
694 } /* switch */
695 return __group_pos;
696}
697
698#endif
699
700#if defined (USE_SPRINTF_INSTEAD) || defined (_STLP_EMULATE_LONG_DOUBLE_CVT)
701struct GroupPos {
702 bool operator () (char __c) const {
703 return __c == '.' ||
704 __c == 'e' || __c == 'E';
705 }
706};
707
708// Creates a format string for sprintf()
709static void __fill_fmtbuf(char* fmtbuf, ios_base::fmtflags flags, char long_modifier) {
710 fmtbuf[0] = '%';
711 int i = 1;
712
713 if (flags & ios_base::showpos)
714 fmtbuf[i++] = '+';
715
716 if (flags & ios_base::showpoint)
717 fmtbuf[i++] = '#';
718
719 fmtbuf[i++] = '.';
720 fmtbuf[i++] = '*';
721
722 if (long_modifier)
723 fmtbuf[i++] = long_modifier;
724
725 switch (flags & ios_base::floatfield)
726 {
727 case ios_base::scientific:
728 fmtbuf[i++] = (flags & ios_base::uppercase) ? 'E' : 'e';
729 break;
730 case ios_base::fixed:
731# if defined (__FreeBSD__)
732 fmtbuf[i++] = 'f';
733# else
734 fmtbuf[i++] = (flags & ios_base::uppercase) ? 'F' : 'f';
735# endif
736 break;
737 default:
738 fmtbuf[i++] = (flags & ios_base::uppercase) ? 'G' : 'g';
739 break;
740 }
741
742 fmtbuf[i] = 0;
743}
744
745#endif /* USE_SPRINTF_INSTEAD */
746
747template <class _FloatT>
749 _FloatT x
750#if defined (USE_SPRINTF_INSTEAD)
751 , char modifier) {
752 /* In theory, if we want 'arbitrary' precision, we should use 'arbitrary'
753 * buffer size below, but really we limited by exponent part in double.
754 * - ptr
755 */
756 typedef numeric_limits<_FloatT> limits;
757 char static_buf[limits::max_exponent10 + 6]; // 6: -xxx.yyyE-zzz (sign, dot, E, exp sign, \0)
758 char fmtbuf[32];
759 __fill_fmtbuf(fmtbuf, flags, modifier);
760 snprintf(_STLP_ARRAY_AND_SIZE(static_buf), fmtbuf, precision, x);
761 buf = static_buf;
762 return find_if(buf.begin(), buf.end(), GroupPos()) - buf.begin();
763#else
764 ) {
765 typedef numeric_limits<_FloatT> limits;
766 //If numeric_limits support is correct we use the exposed values to detect NaN and infinity:
767 if (limits::has_infinity && limits::has_quiet_NaN) {
768 if (!(x == x) || // NaN check
769 (x == limits::infinity() || x == -limits::infinity())) {
770 return __format_nan_or_inf(buf, x, flags);
771 }
772 }
773 // numeric_limits support is not good enough, we rely on platform dependent function
774 // _Stl_is_nan_or_inf that do not support long double.
775 else if (_Stl_is_nan_or_inf(x)) {
776 return __format_nan_or_inf(buf, x, flags);
777 }
778# if defined (__MINGW32__)
779 //For the moment MinGW is limited to display at most numeric_limits<double>::max()
782 return __format_nan_or_inf(buf, x, flags);
783 }
784# endif
785
786 /* Buffer size is max number of digits which is the addition of:
787 * - max_exponent10: max number of digits in fixed mode
788 * - digits10 + 2: max number of significant digits
789 * - trailing '\0'
790 */
791 char cvtbuf[limits::max_exponent10 + limits::digits10 + 2 + 1];
792 char *bp;
793 int decpt, sign;
794
795 switch (flags & ios_base::floatfield) {
796 case ios_base::fixed:
797 {
798 /* Here, number of digits represents digits _after_ decimal point.
799 * In order to limit static buffer size we have to give 2 different values depending on x value.
800 * For small values (abs(x) < 1) we need as many digits as requested by precision limited by the maximum number of digits
801 * which is min_exponent10 + digits10 + 2
802 * For bigger values we won't have more than limits::digits10 + 2 digits after decimal point. */
803 int digits10 = (x > -1.0 && x < 1.0 ? -limits::min_exponent10 + limits::digits10 + 2
804 : limits::digits10 + 2);
805 bp = _Stl_fcvtR(x, (min) (precision, digits10), &decpt, &sign, _STLP_CVT_BUFFER(cvtbuf) );
806 }
807 break;
808 case ios_base::scientific:
809 default:
810 /* Here, number of digits is total number of digits which is limited to digits10 + 2. */
811 {
812 int digits10 = limits::digits10 + 2;
813 bp = _Stl_ecvtR(x, (min) (precision, digits10), &decpt, &sign, _STLP_CVT_BUFFER(cvtbuf) );
814 }
815 break;
816 }
817 return __format_float(buf, bp, decpt, sign, x == 0.0, flags, precision);
818#endif
819}
820
821size_t _STLP_CALL
823 double x) {
825#if defined (USE_SPRINTF_INSTEAD)
826 , 0
827#endif
828 );
829}
830
831#if !defined (_STLP_NO_LONG_DOUBLE)
832size_t _STLP_CALL
834 long double x) {
836#if defined (USE_SPRINTF_INSTEAD)
837 , 'L'
838#endif
839 );
840}
841#endif
842
845#if defined (USE_SPRINTF_INSTEAD)
846 char cvtbuf[limits::max_exponent10 + 6];
847# if !defined (_STLP_NO_LONG_DOUBLE)
848 snprintf(_STLP_ARRAY_AND_SIZE(cvtbuf), "%Lf", __x); // check for 1234.56!
849# else
850 snprintf(_STLP_ARRAY_AND_SIZE(cvtbuf), "%f", __x); // check for 1234.56!
851# endif
852 char *p = strchr( cvtbuf, '.' );
853 if ( p == 0 ) {
854 out.append( cvtbuf );
855 } else {
856 out.append( cvtbuf, p );
857 }
858#else
859 char cvtbuf[limits::max_exponent10 + 1];
860 char * bp;
861 int decpt, sign;
862 bp = _Stl_fcvtR(__x, 0, &decpt, &sign, _STLP_CVT_BUFFER(cvtbuf));
863
864 if (sign) {
865 out += '-';
866 }
867 out.append(bp, bp + decpt);
868#endif
869}
870
871
872#if !defined (_STLP_NO_WCHAR_T)
874 const ctype<wchar_t>& ct, wchar_t dot, bool __check_dot) {
875 string::const_iterator str_ite(str.begin()), str_end(str.end());
876
877 //First loop, check the dot char
878 if (__check_dot) {
879 while (str_ite != str_end) {
880 if (*str_ite != '.') {
881 out += ct.widen(*str_ite++);
882 } else {
883 out += dot;
884 break;
885 }
886 }
887 } else {
888 if (str_ite != str_end) {
889 out += ct.widen(*str_ite);
890 }
891 }
892
893 if (str_ite != str_end) {
894 //Second loop, dot has been found, no check anymore
895 while (++str_ite != str_end) {
896 out += ct.widen(*str_ite);
897 }
898 }
899}
900
901#endif
902
903void _STLP_CALL
905 if ('.' != dot) {
906 size_t __dot_pos = str.find('.');
907 if (__dot_pos != string::npos) {
908 str[__dot_pos] = dot;
909 }
910 }
911}
912
915
916// Local Variables:
917// mode:C++
918// End:
#define N
Definition: crc32.c:57
_STLP_MOVE_TO_STD_NAMESPACE _InputIter find_if(_InputIter __first, _InputIter __last, _Predicate __pred)
Definition: _algobase.c:214
#define _STLP_CALL
Definition: _bc.h:131
#define _STLP_NOTHROW
Definition: _intel.h:35
#define _STLP_MUTEX_INITIALIZER
Definition: _threads.h:241
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
char * strchr(const char *String, int ch)
Definition: utclib.c:501
Definition: _ctype.h:58
int fmtflags
Definition: _ios_base.h:57
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
unsigned char
Definition: typeof.h:29
#define CHAR_BIT
Definition: urlcache.c:62
#define pt(x, y)
Definition: drawing.c:79
char * fcvtbuf(double, int, int *, int *, char *)
Definition: fcvtbuf.c:123
#define _STLP_TEMPLATE_NULL
Definition: features.h:652
#define _STLP_ARRAY_AND_SIZE(A)
Definition: features.h:1054
#define _STLP_MOVE_TO_STD_NAMESPACE
Definition: features.h:525
#define _STLP_STATIC_MUTEX
Definition: features.h:267
#define __STATIC_CAST(__x, __y)
Definition: features.h:585
#define _STLP_LONGEST_FLOAT_TYPE
Definition: features.h:213
#define _STLP_BEGIN_NAMESPACE
Definition: features.h:501
#define _STLP_END_NAMESPACE
Definition: features.h:503
#define _STLP_MOVE_TO_PRIV_NAMESPACE
Definition: features.h:524
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLdouble n
Definition: glext.h:7729
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLbitfield flags
Definition: glext.h:7161
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLint GLint * precision
Definition: glext.h:7539
GLintptr offset
Definition: glext.h:5920
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
_Check_return_ __MINGW_NOTHROW _CRTIMP int __cdecl _fpclass(_In_ double)
#define _FPCLASS_NINF
Definition: float.h:74
_Check_return_ __MINGW_NOTHROW _CRTIMP int __cdecl _isnan(_In_ double)
_Check_return_ __MINGW_NOTHROW _CRTIMP int __cdecl _finite(_In_ double)
_Check_return_ __MINGW_NOTHROW _CRTIMP double __cdecl _copysign(_In_ double, _In_ double)
#define _FPCLASS_PINF
Definition: float.h:81
_Check_return_ __CRT_INLINE long double _copysignl(_In_ long double number, _In_ long double sign)
Definition: math.h:266
_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)
_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 e
Definition: ke_i.h:82
int _isnanl(long double)
#define sign(x)
Definition: mapdesc.cc:613
#define isfinite(x)
Definition: mingw_math.h:91
#define isinf(x)
Definition: mingw_math.h:94
#define isnan(x)
Definition: mingw_math.h:133
double __cdecl nan(const char *tagp)
#define signbit(x)
Definition: mingw_math.h:164
double __cdecl copysign(double, double)
#define sprintf(buf, format,...)
Definition: sprintf.c:55
static size_t double int int * decpt
Definition: printf.c:72
#define min(a, b)
Definition: monoChain.cc:55
#define todigit(x)
#define MAXEDIGITS
size_t _STLP_CALL __write_float(__iostring &buf, ios_base::fmtflags flags, int precision, double x)
#define USE_SPRINTF_INSTEAD
static void __fill_fmtbuf(char *fmtbuf, ios_base::fmtflags flags, char long_modifier)
void _STLP_CALL __adjust_float_buffer(__iostring &str, char dot)
static size_t __write_floatT(__iostring &buf, ios_base::fmtflags flags, int precision, _FloatT x, char modifier)
void _STLP_CALL __get_floor_digits(__iostring &out, _STLP_LONGEST_FLOAT_TYPE __x)
void _STLP_CALL __convert_float_buffer(__iostring const &str, __iowstring &out, const ctype< wchar_t > &ct, wchar_t dot, bool __check_dot)
static FILE * out
Definition: regtests2xml.c:44
const WCHAR * str
#define __c
Definition: schilyio.h:209
bool operator()(char __c) const
rwlock_t lock
Definition: tcpcore.h:0
int ret
#define snprintf
Definition: wintirpc.h:48
#define const
Definition: zconf.h:233