OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [uClibc/] [libc/] [stdlib/] [strtod.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1325 phoenix
/*  Copyright (C) 2000, 2003     Manuel Novoa III
2
 *
3
 *  This library is free software; you can redistribute it and/or
4
 *  modify it under the terms of the GNU Library General Public
5
 *  License as published by the Free Software Foundation; either
6
 *  version 2 of the License, or (at your option) any later version.
7
 *
8
 *  This library is distributed in the hope that it will be useful,
9
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11
 *  Library General Public License for more details.
12
 *
13
 *  You should have received a copy of the GNU Library General Public
14
 *  License along with this library; if not, write to the Free
15
 *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16
 */
17
 
18
 
19
/* Notes:
20
 *
21
 * The primary objective of this implementation was minimal size and
22
 * portablility, while providing robustness and resonable accuracy.
23
 *
24
 * This implementation depends on IEEE floating point behavior and expects
25
 * to be able to generate +/- infinity as a result.
26
 *
27
 * There are a number of compile-time options below.
28
 */
29
 
30
/* July 27, 2003
31
 *
32
 * General cleanup and some minor size optimizations.
33
 * Change implementation to support __strtofpmax() rather than strtod().
34
 *   Now all the strto{floating pt}() funcs are implemented in terms of
35
 *   of the internal __strtofpmax() function.
36
 * Support "nan", "inf", and "infinity" strings (case-insensitive).
37
 * Support hexadecimal floating point notation.
38
 * Support wchar variants.
39
 * Support xlocale variants.
40
 *
41
 * TODO:
42
 *
43
 * Consider accumulating blocks of digits in longs to save floating pt mults.
44
 *   This would likely be much better on anything that only supported floats
45
 *   where DECIMAL_DIG == 9.  Actually, if floats have FLT_MAX_10_EXP == 38,
46
 *   we could calculate almost all the exponent multipliers (p_base) in
47
 *   long arithmetic as well.
48
 */
49
 
50
/**********************************************************************/
51
/*                                                      OPTIONS                                                                   */
52
/**********************************************************************/
53
 
54
/* Defined if we want to recognize "nan", "inf", and "infinity". (C99) */
55
#define _STRTOD_NAN_INF_STRINGS  1
56
 
57
/* Defined if we want support hexadecimal floating point notation. (C99) */
58
/* Note!  Now controlled by uClibc configuration.  See below. */
59
#define _STRTOD_HEXADECIMAL_FLOATS 1
60
 
61
/* Defined if we want to scale with a O(log2(exp)) multiplications.
62
 * This is generally a good thing to do unless you are really tight
63
 * on space and do not expect to convert values of large magnitude. */
64
 
65
#define _STRTOD_LOG_SCALING       1
66
 
67
/* WARNING!!!   WARNING!!!   WARNING!!!   WARNING!!!   WARNING!!!
68
 *
69
 * Clearing any of the options below this point is not advised (or tested).
70
 *
71
 * WARNING!!!   WARNING!!!   WARNING!!!   WARNING!!!   WARNING!!! */
72
 
73
/* Defined if we want strtod to set errno appropriately. */
74
/* NOTE: Implies all options below. */
75
#define _STRTOD_ERRNO                   1
76
 
77
/* Defined if we want support for the endptr arg. */
78
/* Implied by _STRTOD_ERRNO. */
79
#define _STRTOD_ENDPTR             1
80
 
81
/* Defined if we want to prevent overflow in accumulating the exponent. */
82
/* Implied by _STRTOD_ERRNO. */
83
#define _STRTOD_RESTRICT_EXP     1
84
 
85
/* Defined if we want to process mantissa digits more intelligently. */
86
/* Implied by _STRTOD_ERRNO. */
87
#define _STRTOD_RESTRICT_DIGITS  1
88
 
89
/* Defined if we want to skip scaling 0 for the exponent. */
90
/* Implied by _STRTOD_ERRNO. */
91
#define _STRTOD_ZERO_CHECK         1
92
 
93
/**********************************************************************/
94
/* Don't change anything that follows.                                                                     */
95
/**********************************************************************/
96
 
97
#ifdef _STRTOD_ERRNO
98
#undef _STRTOD_ENDPTR
99
#undef _STRTOD_RESTRICT_EXP
100
#undef _STRTOD_RESTRICT_DIGITS
101
#undef _STRTOD_ZERO_CHECK
102
#define _STRTOD_ENDPTR             1
103
#define _STRTOD_RESTRICT_EXP     1
104
#define _STRTOD_RESTRICT_DIGITS  1
105
#define _STRTOD_ZERO_CHECK         1
106
#endif
107
 
108
/**********************************************************************/
109
 
110
#define _ISOC99_SOURCE 1
111
#define _GNU_SOURCE
112
#include <stdlib.h>
113
#include <string.h>
114
#include <ctype.h>
115
#include <errno.h>
116
#include <limits.h>
117
#include <float.h>
118
#include <bits/uClibc_fpmax.h>
119
 
120
#include <locale.h>
121
 
122
#ifdef __UCLIBC_HAS_WCHAR__
123
 
124
#include <wchar.h>
125
#include <wctype.h>
126
#include <bits/uClibc_uwchar.h>
127
 
128
#endif
129
 
130
#ifdef __UCLIBC_HAS_XLOCALE__
131
#include <xlocale.h>
132
#endif /* __UCLIBC_HAS_XLOCALE__ */
133
 
134
 
135
 
136
/* Handle _STRTOD_HEXADECIMAL_FLOATS via uClibc config now. */
137
#undef _STRTOD_HEXADECIMAL_FLOATS
138
#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__
139
#define _STRTOD_HEXADECIMAL_FLOATS 1
140
#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */
141
 
142
/**********************************************************************/
143
 
144
#undef _STRTOD_FPMAX
145
 
146
#if FPMAX_TYPE == 3
147
 
148
#define NEED_STRTOLD_WRAPPER
149
#define NEED_STRTOD_WRAPPER
150
#define NEED_STRTOF_WRAPPER
151
 
152
#elif FPMAX_TYPE == 2
153
 
154
#define NEED_STRTOD_WRAPPER
155
#define NEED_STRTOF_WRAPPER
156
 
157
#elif FPMAX_TYPE == 1
158
 
159
#define NEED_STRTOF_WRAPPER
160
 
161
#else
162
 
163
#error unknown FPMAX_TYPE!
164
 
165
#endif
166
 
167
extern void __fp_range_check(__fpmax_t y, __fpmax_t x);
168
 
169
/**********************************************************************/
170
 
171
#ifdef _STRTOD_RESTRICT_DIGITS
172
#define EXP_DENORM_ADJUST DECIMAL_DIG
173
#define MAX_ALLOWED_EXP (DECIMAL_DIG  + EXP_DENORM_ADJUST - FPMAX_MIN_10_EXP)
174
 
175
#if MAX_ALLOWED_EXP > INT_MAX
176
#error size assumption violated for MAX_ALLOWED_EXP
177
#endif
178
#else
179
/* We want some excess if we're not restricting mantissa digits. */
180
#define MAX_ALLOWED_EXP ((20 - FPMAX_MIN_10_EXP) * 2)
181
#endif
182
 
183
 
184
#if defined(_STRTOD_RESTRICT_DIGITS) || defined(_STRTOD_ENDPTR) || defined(_STRTOD_HEXADECIMAL_FLOATS)
185
#undef _STRTOD_NEED_NUM_DIGITS
186
#define _STRTOD_NEED_NUM_DIGITS 1
187
#endif
188
 
189
/**********************************************************************/
190
#if defined(L___strtofpmax) || defined(L___strtofpmax_l) || defined(L___wcstofpmax) || defined(L___wcstofpmax_l)
191
 
192
#if defined(L___wcstofpmax) || defined(L___wcstofpmax_l)
193
 
194
#define __strtofpmax    __wcstofpmax
195
#define __strtofpmax_l  __wcstofpmax_l
196
 
197
#define Wchar wchar_t
198
#ifdef __UCLIBC_DO_XLOCALE
199
#define ISSPACE(C) iswspace_l((C), locale_arg)
200
#else
201
#define ISSPACE(C) iswspace((C))
202
#endif
203
 
204
#else  /* defined(L___wcstofpmax) || defined(L___wcstofpmax) */
205
 
206
#define Wchar char
207
#ifdef __UCLIBC_DO_XLOCALE
208
#define ISSPACE(C) isspace_l((C), locale_arg)
209
#else
210
#define ISSPACE(C) isspace((C))
211
#endif
212
 
213
#endif /* defined(L___wcstofpmax) || defined(L___wcstofpmax) */
214
 
215
 
216
#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE)
217
 
218
__fpmax_t __strtofpmax(const Wchar *str, Wchar **endptr, int exponent_power)
219
{
220
        return __strtofpmax_l(str, endptr, exponent_power, __UCLIBC_CURLOCALE);
221
}
222
 
223
#else  /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
224
 
225
__fpmax_t __XL_NPP(__strtofpmax)(const Wchar *str, Wchar **endptr, int exponent_power
226
                                                                 __LOCALE_PARAM )
227
{
228
        __fpmax_t number;
229
        __fpmax_t p_base = 10;                  /* Adjusted to 16 in the hex case. */
230
        Wchar *pos0;
231
#ifdef _STRTOD_ENDPTR
232
        Wchar *pos1;
233
#endif
234
        Wchar *pos = (Wchar *) str;
235
        int exponent_temp;
236
        int negative; /* A flag for the number, a multiplier for the exponent. */
237
#ifdef _STRTOD_NEED_NUM_DIGITS
238
        int num_digits;
239
#endif
240
#ifdef __UCLIBC_HAS_LOCALE__
241
        const char *decpt = __LOCALE_PTR->decimal_point;
242
#if defined(L___wcstofpmax) || defined(L___wcstofpmax)
243
        wchar_t decpt_wc = __LOCALE_PTR->decimal_point;
244
#else
245
        int decpt_len = __LOCALE_PTR->decimal_point_len;
246
#endif
247
#endif
248
 
249
#ifdef _STRTOD_HEXADECIMAL_FLOATS
250
        Wchar expchar = 'e';
251
        Wchar *poshex = NULL;
252
        __uint16_t is_mask = _ISdigit;
253
#define EXPCHAR         expchar
254
#define IS_X_DIGIT(C) __isctype((C), is_mask)
255
#else  /* _STRTOD_HEXADECIMAL_FLOATS */
256
#define EXPCHAR         'e'
257
#define IS_X_DIGIT(C) isdigit((C))
258
#endif /* _STRTOD_HEXADECIMAL_FLOATS */
259
 
260
        while (ISSPACE(*pos)) {         /* Skip leading whitespace. */
261
                ++pos;
262
        }
263
 
264
        negative = 0;
265
        switch(*pos) {                          /* Handle optional sign. */
266
                case '-': negative = 1; /* Fall through to increment position. */
267
                case '+': ++pos;
268
        }
269
 
270
#ifdef _STRTOD_HEXADECIMAL_FLOATS
271
        if ((*pos == '0') && (((pos[1])|0x20) == 'x')) {
272
                poshex = ++pos;                 /* Save position of 'x' in case no digits */
273
                ++pos;                                  /*   and advance past it.  */
274
                is_mask = _ISxdigit;    /* Used by IS_X_DIGIT. */
275
                expchar = 'p';                  /* Adjust exponent char. */
276
                p_base = 16;                    /* Adjust base multiplier. */
277
        }
278
#endif
279
 
280
        number = 0.;
281
#ifdef _STRTOD_NEED_NUM_DIGITS
282
        num_digits = -1;
283
#endif
284
/*      exponent_power = 0; */
285
        pos0 = NULL;
286
 
287
 LOOP:
288
        while (IS_X_DIGIT(*pos)) {      /* Process string of (hex) digits. */
289
#ifdef _STRTOD_RESTRICT_DIGITS
290
                if (num_digits < 0) {    /* First time through? */
291
                        ++num_digits;           /* We've now seen a digit. */
292
                }
293
                if (num_digits || (*pos != '0')) { /* Had/have nonzero. */
294
                        ++num_digits;
295
                        if (num_digits <= DECIMAL_DIG) { /* Is digit significant? */
296
#ifdef _STRTOD_HEXADECIMAL_FLOATS
297
                                number = number * p_base
298
                                        + (isdigit(*pos)
299
                                           ? (*pos - '0')
300
                                           : (((*pos)|0x20) - ('a' - 10)));
301
#else  /* _STRTOD_HEXADECIMAL_FLOATS */
302
                                number = number * p_base + (*pos - '0');
303
#endif /* _STRTOD_HEXADECIMAL_FLOATS */
304
                        }
305
                }
306
#else  /* _STRTOD_RESTRICT_DIGITS */
307
#ifdef _STRTOD_NEED_NUM_DIGITS
308
                ++num_digits;
309
#endif
310
#ifdef _STRTOD_HEXADECIMAL_FLOATS
311
                number = number * p_base
312
                        + (isdigit(*pos)
313
                           ? (*pos - '0')
314
                           : (((*pos)|0x20) - ('a' - 10)));
315
#else  /* _STRTOD_HEXADECIMAL_FLOATS */
316
                number = number * p_base + (*pos - '0');
317
#endif /* _STRTOD_HEXADECIMAL_FLOATS */
318
#endif /* _STRTOD_RESTRICT_DIGITS */
319
                ++pos;
320
        }
321
 
322
#ifdef __UCLIBC_HAS_LOCALE__
323
#if defined(L___wcstofpmax) || defined(L___wcstofpmax)
324
        if (!pos0 && (*pos == decpt_wc)) { /* First decimal point? */
325
                pos0 = ++pos;
326
                goto LOOP;
327
        }
328
#else
329
        if (!pos0 && !memcmp(pos, decpt, decpt_len)) { /* First decimal point? */
330
                pos0 = (pos += decpt_len);
331
                goto LOOP;
332
        }
333
#endif
334
#else  /* __UCLIBC_HAS_LOCALE__ */
335
        if ((*pos == '.') && !pos0) { /* First decimal point? */
336
                pos0 = ++pos;                   /* Save position of decimal point */
337
                goto LOOP;                              /*   and process rest of digits. */
338
        }
339
#endif /* __UCLIBC_HAS_LOCALE__ */
340
 
341
#ifdef _STRTOD_NEED_NUM_DIGITS
342
        if (num_digits<0) {                      /* Must have at least one digit. */
343
#ifdef _STRTOD_HEXADECIMAL_FLOATS
344
                if (poshex) {                   /* Back up to '0' in '0x' prefix. */
345
                        pos = poshex;
346
                        goto DONE;
347
                }
348
#endif /* _STRTOD_HEXADECIMAL_FLOATS */
349
 
350
#ifdef _STRTOD_NAN_INF_STRINGS
351
                if (!pos0) {                    /* No decimal point, so check for inf/nan. */
352
                        /* Note: nan is the first string so 'number = i/0.;' works. */
353
                        static const char nan_inf_str[] = "\05nan\0\012infinity\0\05inf\0";
354
                        int i = 0;
355
 
356
#ifdef __UCLIBC_HAS_LOCALE__
357
                        /* Avoid tolower problems for INFINITY in the tr_TR locale. (yuk)*/
358
#undef _tolower
359
#define _tolower(C)     ((C)|0x20)
360
#endif /* __UCLIBC_HAS_LOCALE__ */
361
 
362
                        do {
363
                                /* Unfortunately, we have no memcasecmp(). */
364
                                int j = 0;
365
                                while (_tolower(pos[j]) == nan_inf_str[i+1+j]) {
366
                                        ++j;
367
                                        if (!nan_inf_str[i+1+j]) {
368
                                                number = i / 0.;
369
                                                if (negative) { /* Correct for sign. */
370
                                                        number = -number;
371
                                                }
372
                                                pos += nan_inf_str[i] - 2;
373
                                                goto DONE;
374
                                        }
375
                                }
376
                                i += nan_inf_str[i];
377
                        } while (nan_inf_str[i]);
378
                }
379
 
380
#endif /* STRTOD_NAN_INF_STRINGS */
381
#ifdef _STRTOD_ENDPTR
382
                pos = (Wchar *) str;
383
#endif
384
                goto DONE;
385
        }
386
#endif /* _STRTOD_NEED_NUM_DIGITS */
387
 
388
#ifdef _STRTOD_RESTRICT_DIGITS
389
        if (num_digits > DECIMAL_DIG) { /* Adjust exponent for skipped digits. */
390
                exponent_power += num_digits - DECIMAL_DIG;
391
        }
392
#endif
393
 
394
        if (pos0) {
395
                exponent_power += pos0 - pos; /* Adjust exponent for decimal point. */
396
        }
397
 
398
#ifdef _STRTOD_HEXADECIMAL_FLOATS
399
        if (poshex) {
400
                exponent_power *= 4;    /* Above is 2**4, but below is 2. */
401
                p_base = 2;
402
        }
403
#endif /* _STRTOD_HEXADECIMAL_FLOATS */
404
 
405
        if (negative) {                         /* Correct for sign. */
406
                number = -number;
407
        }
408
 
409
        /* process an exponent string */
410
        if (((*pos)|0x20) == EXPCHAR) {
411
#ifdef _STRTOD_ENDPTR
412
                pos1 = pos;
413
#endif
414
                negative = 1;
415
                switch(*++pos) {                /* Handle optional sign. */
416
                        case '-': negative = -1; /* Fall through to increment pos. */
417
                        case '+': ++pos;
418
                }
419
 
420
                pos0 = pos;
421
                exponent_temp = 0;
422
                while (isdigit(*pos)) { /* Process string of digits. */
423
#ifdef _STRTOD_RESTRICT_EXP
424
                        if (exponent_temp < MAX_ALLOWED_EXP) { /* Avoid overflow. */
425
                                exponent_temp = exponent_temp * 10 + (*pos - '0');
426
                        }
427
#else
428
                        exponent_temp = exponent_temp * 10 + (*pos - '0');
429
#endif
430
                        ++pos;
431
                }
432
 
433
#ifdef _STRTOD_ENDPTR
434
                if (pos == pos0) {      /* No digits? */
435
                        pos = pos1;             /* Back up to {e|E}/{p|P}. */
436
                } /* else */
437
#endif
438
 
439
                exponent_power += negative * exponent_temp;
440
        }
441
 
442
#ifdef _STRTOD_ZERO_CHECK
443
        if (number == 0.) {
444
                goto DONE;
445
        }
446
#endif
447
 
448
        /* scale the result */
449
#ifdef _STRTOD_LOG_SCALING
450
        exponent_temp = exponent_power;
451
 
452
        if (exponent_temp < 0) {
453
                exponent_temp = -exponent_temp;
454
        }
455
 
456
        while (exponent_temp) {
457
                if (exponent_temp & 1) {
458
                        if (exponent_power < 0) {
459
                                /* Warning... caluclating a factor for the exponent and
460
                                 * then dividing could easily be faster.  But doing so
461
                                 * might cause problems when dealing with denormals. */
462
                                number /= p_base;
463
                        } else {
464
                                number *= p_base;
465
                        }
466
                }
467
                exponent_temp >>= 1;
468
                p_base *= p_base;
469
        }
470
 
471
#else  /* _STRTOD_LOG_SCALING */
472
        while (exponent_power) {
473
                if (exponent_power < 0) {
474
                        number /= p_base;
475
                        exponent_power++;
476
                } else {
477
                        number *= p_base;
478
                        exponent_power--;
479
                }
480
        }
481
#endif /* _STRTOD_LOG_SCALING */
482
 
483
#ifdef _STRTOD_ERRNO
484
        if (__FPMAX_ZERO_OR_INF_CHECK(number)) {
485
                __set_errno(ERANGE);
486
        }
487
#endif
488
 
489
 DONE:
490
#ifdef _STRTOD_ENDPTR
491
        if (endptr) {
492
                *endptr = pos;
493
        }
494
#endif
495
 
496
        return number;
497
}
498
 
499
#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */
500
 
501
#endif
502
/**********************************************************************/
503
#ifdef L___fp_range_check
504
#if defined(NEED_STRTOF_WRAPPER) || defined(NEED_STRTOD_WRAPPER)
505
 
506
extern void __fp_range_check(__fpmax_t y, __fpmax_t x)
507
{
508
        if (__FPMAX_ZERO_OR_INF_CHECK(y) /* y is 0 or +/- infinity */
509
                && (y != 0)      /* y is not 0 (could have x>0, y==0 if underflow) */
510
                && !__FPMAX_ZERO_OR_INF_CHECK(x) /* x is not 0 or +/- infinity */
511
                ) {
512
                __set_errno(ERANGE);    /* Then x is not in y's range. */
513
        }
514
}
515
 
516
#endif
517
#endif
518
/**********************************************************************/
519
#if defined(L_strtof) || defined(L_strtof_l) || defined(L_wcstof) || defined(L_wcstof_l)
520
#if defined(NEED_STRTOF_WRAPPER)
521
 
522
#if defined(L_wcstof) || defined(L_wcstof_l)
523
#define strtof           wcstof
524
#define strtof_l         wcstof_l
525
#define __strtof         __wcstof
526
#define __strtof_l       __wcstof_l
527
#define __strtofpmax     __wcstofpmax
528
#define __strtofpmax_l   __wcstofpmax_l
529
#define Wchar wchar_t
530
#else
531
#define Wchar char
532
#endif
533
 
534
 
535
float __XL(strtof)(const Wchar *str, Wchar **endptr   __LOCALE_PARAM )
536
{
537
#if FPMAX_TYPE == 1
538
        return __XL_NPP(__strtofpmax)(str, endptr, 0   __LOCALE_ARG );
539
#else
540
        __fpmax_t x;
541
        float y;
542
 
543
        x = __XL_NPP(__strtofpmax)(str, endptr, 0   __LOCALE_ARG );
544
        y = (float) x;
545
 
546
        __fp_range_check(y, x);
547
 
548
        return y;
549
#endif
550
}
551
 
552
__XL_ALIAS(strtof)
553
 
554
#endif
555
#endif
556
/**********************************************************************/
557
#if defined(L_strtod) || defined(L_strtod_l) || defined(L_wcstod) || defined(L_wcstod_l)
558
#if defined(NEED_STRTOD_WRAPPER)
559
 
560
#if defined(L_wcstod) || defined(L_wcstod_l)
561
#define strtod           wcstod
562
#define strtod_l         wcstod_l
563
#define __strtod         __wcstod
564
#define __strtod_l       __wcstod_l
565
#define __strtofpmax     __wcstofpmax
566
#define __strtofpmax_l   __wcstofpmax_l
567
#define Wchar wchar_t
568
#else
569
#define Wchar char
570
#endif
571
 
572
double __XL(strtod)(const Wchar *__restrict str,
573
                                        Wchar **__restrict endptr   __LOCALE_PARAM )
574
{
575
#if FPMAX_TYPE == 2
576
        return __XL_NPP(__strtofpmax)(str, endptr, 0   __LOCALE_ARG );
577
#else
578
        __fpmax_t x;
579
        double y;
580
 
581
        x = __XL_NPP(__strtofpmax)(str, endptr, 0   __LOCALE_ARG );
582
        y = (double) x;
583
 
584
        __fp_range_check(y, x);
585
 
586
        return y;
587
#endif
588
}
589
 
590
__XL_ALIAS(strtod)
591
 
592
#endif
593
#endif
594
/**********************************************************************/
595
#if defined(L_strtold) || defined(L_strtold_l) || defined(L_wcstold) || defined(L_wcstold_l)
596
#if defined(NEED_STRTOLD_WRAPPER)
597
 
598
#if defined(L_wcstold) || defined(L_wcstold_l)
599
#define strtold           wcstold
600
#define strtold_l         wcstold_l
601
#define __strtold         __wcstold
602
#define __strtold_l       __wcstold_l
603
#define __strtofpmax     __wcstofpmax
604
#define __strtofpmax_l   __wcstofpmax_l
605
#define Wchar wchar_t
606
#else
607
#define Wchar char
608
#endif
609
 
610
long double __XL(strtold)(const Wchar *str, Wchar **endptr   __LOCALE_PARAM )
611
{
612
#if FPMAX_TYPE == 3
613
        return __XL_NPP(__strtofpmax)(str, endptr, 0   __LOCALE_ARG );
614
#else
615
        __fpmax_t x;
616
        long double y;
617
 
618
        x = __XL_NPP(__strtofpmax)(str, endptr, 0   __LOCALE_ARG );
619
        y = (long double) x;
620
 
621
        __fp_range_check(y, x);
622
 
623
        return y;
624
#endif
625
}
626
 
627
__XL_ALIAS(strtold)
628
 
629
#endif
630
#endif
631
/**********************************************************************/

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.