cdb57b221a8590699b5db6365b916b65147cb163
[gnulib.git] / tests / test-strtod.c
1 /*
2  * Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
3  * Written by Eric Blake
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program 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
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18 #include <config.h>
19
20 #include <stdlib.h>
21
22 #include "signature.h"
23 SIGNATURE_CHECK (strtod, double, (char const *, char **));
24
25 #include <errno.h>
26 #include <float.h>
27 #include <math.h>
28 #include <string.h>
29
30 #include "isnand-nolibm.h"
31 #include "macros.h"
32
33 /* Avoid requiring -lm just for fabs.  */
34 #define FABS(d) ((d) < 0.0 ? -(d) : (d))
35
36 /* HP cc on HP-UX 10.20 has a bug with the constant expression -0.0.
37    So we use -zero instead.  */
38 double zero = 0.0;
39
40 int
41 main (void)
42 {
43   int status = 0;
44   /* Subject sequence empty or invalid.  */
45   {
46     const char input[] = "";
47     char *ptr;
48     double result;
49     errno = 0;
50     result = strtod (input, &ptr);
51     ASSERT (result == 0.0);
52     ASSERT (!signbit (result));
53     ASSERT (ptr == input);
54     ASSERT (errno == 0 || errno == EINVAL);
55   }
56   {
57     const char input[] = " ";
58     char *ptr;
59     double result;
60     errno = 0;
61     result = strtod (input, &ptr);
62     ASSERT (result == 0.0);
63     ASSERT (!signbit (result));
64     ASSERT (ptr == input);
65     ASSERT (errno == 0 || errno == EINVAL);
66   }
67   {
68     const char input[] = " +";
69     char *ptr;
70     double result;
71     errno = 0;
72     result = strtod (input, &ptr);
73     ASSERT (result == 0.0);
74     ASSERT (!signbit (result));
75     ASSERT (ptr == input);
76     ASSERT (errno == 0 || errno == EINVAL);
77   }
78   {
79     const char input[] = " .";
80     char *ptr;
81     double result;
82     errno = 0;
83     result = strtod (input, &ptr);
84     ASSERT (result == 0.0);
85     ASSERT (!signbit (result));
86     ASSERT (ptr == input);
87     ASSERT (errno == 0 || errno == EINVAL);
88   }
89   {
90     const char input[] = " .e0";
91     char *ptr;
92     double result;
93     errno = 0;
94     result = strtod (input, &ptr);
95     ASSERT (result == 0.0);
96     ASSERT (!signbit (result));
97     ASSERT (ptr == input);              /* IRIX 6.5, OSF/1 5.1 */
98     ASSERT (errno == 0 || errno == EINVAL);
99   }
100   {
101     const char input[] = " +.e-0";
102     char *ptr;
103     double result;
104     errno = 0;
105     result = strtod (input, &ptr);
106     ASSERT (result == 0.0);
107     ASSERT (!signbit (result));
108     ASSERT (ptr == input);              /* IRIX 6.5, OSF/1 5.1 */
109     ASSERT (errno == 0 || errno == EINVAL);
110   }
111   {
112     const char input[] = " in";
113     char *ptr;
114     double result;
115     errno = 0;
116     result = strtod (input, &ptr);
117     ASSERT (result == 0.0);
118     ASSERT (!signbit (result));
119     ASSERT (ptr == input);
120     ASSERT (errno == 0 || errno == EINVAL);
121   }
122   {
123     const char input[] = " na";
124     char *ptr;
125     double result;
126     errno = 0;
127     result = strtod (input, &ptr);
128     ASSERT (result == 0.0);
129     ASSERT (!signbit (result));
130     ASSERT (ptr == input);
131     ASSERT (errno == 0 || errno == EINVAL);
132   }
133
134   /* Simple floating point values.  */
135   {
136     const char input[] = "1";
137     char *ptr;
138     double result;
139     errno = 0;
140     result = strtod (input, &ptr);
141     ASSERT (result == 1.0);
142     ASSERT (ptr == input + 1);
143     ASSERT (errno == 0);
144   }
145   {
146     const char input[] = "1.";
147     char *ptr;
148     double result;
149     errno = 0;
150     result = strtod (input, &ptr);
151     ASSERT (result == 1.0);
152     ASSERT (ptr == input + 2);
153     ASSERT (errno == 0);
154   }
155   {
156     const char input[] = ".5";
157     char *ptr;
158     double result;
159     errno = 0;
160     result = strtod (input, &ptr);
161     /* FIXME - gnulib's version is rather inaccurate.  It would be
162        nice to guarantee an exact result, but for now, we settle for a
163        1-ulp error.  */
164     ASSERT (FABS (result - 0.5) < DBL_EPSILON);
165     ASSERT (ptr == input + 2);
166     ASSERT (errno == 0);
167   }
168   {
169     const char input[] = " 1";
170     char *ptr;
171     double result;
172     errno = 0;
173     result = strtod (input, &ptr);
174     ASSERT (result == 1.0);
175     ASSERT (ptr == input + 2);
176     ASSERT (errno == 0);
177   }
178   {
179     const char input[] = "+1";
180     char *ptr;
181     double result;
182     errno = 0;
183     result = strtod (input, &ptr);
184     ASSERT (result == 1.0);
185     ASSERT (ptr == input + 2);
186     ASSERT (errno == 0);
187   }
188   {
189     const char input[] = "-1";
190     char *ptr;
191     double result;
192     errno = 0;
193     result = strtod (input, &ptr);
194     ASSERT (result == -1.0);
195     ASSERT (ptr == input + 2);
196     ASSERT (errno == 0);
197   }
198   {
199     const char input[] = "1e0";
200     char *ptr;
201     double result;
202     errno = 0;
203     result = strtod (input, &ptr);
204     ASSERT (result == 1.0);
205     ASSERT (ptr == input + 3);
206     ASSERT (errno == 0);
207   }
208   {
209     const char input[] = "1e+0";
210     char *ptr;
211     double result;
212     errno = 0;
213     result = strtod (input, &ptr);
214     ASSERT (result == 1.0);
215     ASSERT (ptr == input + 4);
216     ASSERT (errno == 0);
217   }
218   {
219     const char input[] = "1e-0";
220     char *ptr;
221     double result;
222     errno = 0;
223     result = strtod (input, &ptr);
224     ASSERT (result == 1.0);
225     ASSERT (ptr == input + 4);
226     ASSERT (errno == 0);
227   }
228   {
229     const char input[] = "1e1";
230     char *ptr;
231     double result;
232     errno = 0;
233     result = strtod (input, &ptr);
234     ASSERT (result == 10.0);
235     ASSERT (ptr == input + 3);
236     ASSERT (errno == 0);
237   }
238   {
239     const char input[] = "5e-1";
240     char *ptr;
241     double result;
242     errno = 0;
243     result = strtod (input, &ptr);
244     /* FIXME - gnulib's version is rather inaccurate.  It would be
245        nice to guarantee an exact result, but for now, we settle for a
246        1-ulp error.  */
247     ASSERT (FABS (result - 0.5) < DBL_EPSILON);
248     ASSERT (ptr == input + 4);
249     ASSERT (errno == 0);
250   }
251
252   /* Zero.  */
253   {
254     const char input[] = "0";
255     char *ptr;
256     double result;
257     errno = 0;
258     result = strtod (input, &ptr);
259     ASSERT (result == 0.0);
260     ASSERT (!signbit (result));
261     ASSERT (ptr == input + 1);
262     ASSERT (errno == 0);
263   }
264   {
265     const char input[] = ".0";
266     char *ptr;
267     double result;
268     errno = 0;
269     result = strtod (input, &ptr);
270     ASSERT (result == 0.0);
271     ASSERT (!signbit (result));
272     ASSERT (ptr == input + 2);
273     ASSERT (errno == 0);
274   }
275   {
276     const char input[] = "0e0";
277     char *ptr;
278     double result;
279     errno = 0;
280     result = strtod (input, &ptr);
281     ASSERT (result == 0.0);
282     ASSERT (!signbit (result));
283     ASSERT (ptr == input + 3);
284     ASSERT (errno == 0);
285   }
286   {
287     const char input[] = "0e+9999999";
288     char *ptr;
289     double result;
290     errno = 0;
291     result = strtod (input, &ptr);
292     ASSERT (result == 0.0);
293     ASSERT (!signbit (result));
294     ASSERT (ptr == input + 10);
295     ASSERT (errno == 0);
296   }
297   {
298     const char input[] = "0e-9999999";
299     char *ptr;
300     double result;
301     errno = 0;
302     result = strtod (input, &ptr);
303     ASSERT (result == 0.0);
304     ASSERT (!signbit (result));
305     ASSERT (ptr == input + 10);
306     ASSERT (errno == 0);
307   }
308   {
309     const char input[] = "-0";
310     char *ptr;
311     double result;
312     errno = 0;
313     result = strtod (input, &ptr);
314     ASSERT (result == 0.0);
315     ASSERT (!!signbit (result) == !!signbit (-zero)); /* IRIX 6.5, OSF/1 4.0 */
316     ASSERT (ptr == input + 2);
317     ASSERT (errno == 0);
318   }
319
320   /* Suffixes.  */
321   {
322     const char input[] = "1f";
323     char *ptr;
324     double result;
325     errno = 0;
326     result = strtod (input, &ptr);
327     ASSERT (result == 1.0);
328     ASSERT (ptr == input + 1);
329     ASSERT (errno == 0);
330   }
331   {
332     const char input[] = "1.f";
333     char *ptr;
334     double result;
335     errno = 0;
336     result = strtod (input, &ptr);
337     ASSERT (result == 1.0);
338     ASSERT (ptr == input + 2);
339     ASSERT (errno == 0);
340   }
341   {
342     const char input[] = "1e";
343     char *ptr;
344     double result;
345     errno = 0;
346     result = strtod (input, &ptr);
347     ASSERT (result == 1.0);
348     ASSERT (ptr == input + 1);
349     ASSERT (errno == 0);
350   }
351   {
352     const char input[] = "1e+";
353     char *ptr;
354     double result;
355     errno = 0;
356     result = strtod (input, &ptr);
357     ASSERT (result == 1.0);
358     ASSERT (ptr == input + 1);
359     ASSERT (errno == 0);
360   }
361   {
362     const char input[] = "1e-";
363     char *ptr;
364     double result;
365     errno = 0;
366     result = strtod (input, &ptr);
367     ASSERT (result == 1.0);
368     ASSERT (ptr == input + 1);
369     ASSERT (errno == 0);
370   }
371   {
372     const char input[] = "1E 2";
373     char *ptr;
374     double result;
375     errno = 0;
376     result = strtod (input, &ptr);
377     ASSERT (result == 1.0);             /* HP-UX 11.11, IRIX 6.5, OSF/1 4.0 */
378     ASSERT (ptr == input + 1);          /* HP-UX 11.11, IRIX 6.5 */
379     ASSERT (errno == 0);
380   }
381   {
382     const char input[] = "0x";
383     char *ptr;
384     double result;
385     errno = 0;
386     result = strtod (input, &ptr);
387     ASSERT (result == 0.0);
388     ASSERT (!signbit (result));
389     ASSERT (ptr == input + 1);          /* glibc-2.3.6, MacOS X 10.3, FreeBSD 6.2 */
390     ASSERT (errno == 0);
391   }
392   {
393     const char input[] = "00x1";
394     char *ptr;
395     double result;
396     errno = 0;
397     result = strtod (input, &ptr);
398     ASSERT (result == 0.0);
399     ASSERT (!signbit (result));
400     ASSERT (ptr == input + 2);
401     ASSERT (errno == 0);
402   }
403   {
404     const char input[] = "-0x";
405     char *ptr;
406     double result;
407     errno = 0;
408     result = strtod (input, &ptr);
409     ASSERT (result == 0.0);
410     ASSERT (!!signbit (result) == !!signbit (-zero)); /* MacOS X 10.3, FreeBSD 6.2, IRIX 6.5, OSF/1 4.0 */
411     ASSERT (ptr == input + 2);          /* glibc-2.3.6, MacOS X 10.3, FreeBSD 6.2 */
412     ASSERT (errno == 0);
413   }
414   {
415     const char input[] = "0xg";
416     char *ptr;
417     double result;
418     errno = 0;
419     result = strtod (input, &ptr);
420     ASSERT (result == 0.0);
421     ASSERT (!signbit (result));
422     ASSERT (ptr == input + 1);          /* glibc-2.3.6, MacOS X 10.3, FreeBSD 6.2 */
423     ASSERT (errno == 0);
424   }
425   {
426     const char input[] = "0xp";
427     char *ptr;
428     double result;
429     errno = 0;
430     result = strtod (input, &ptr);
431     ASSERT (result == 0.0);
432     ASSERT (!signbit (result));
433     ASSERT (ptr == input + 1);          /* glibc-2.3.6, MacOS X 10.3, FreeBSD 6.2 */
434     ASSERT (errno == 0);
435   }
436   {
437     const char input[] = "0x.";
438     char *ptr;
439     double result;
440     errno = 0;
441     result = strtod (input, &ptr);
442     ASSERT (result == 0.0);
443     ASSERT (!signbit (result));
444     ASSERT (ptr == input + 1);          /* glibc-2.3.6, MacOS X 10.3, FreeBSD 6.2 */
445     ASSERT (errno == 0);
446   }
447   {
448     const char input[] = "0xp+";
449     char *ptr;
450     double result;
451     errno = 0;
452     result = strtod (input, &ptr);
453     ASSERT (result == 0.0);
454     ASSERT (!signbit (result));
455     ASSERT (ptr == input + 1);          /* glibc-2.3.6, MacOS X 10.3, FreeBSD 6.2 */
456     ASSERT (errno == 0);
457   }
458   {
459     const char input[] = "0xp+1";
460     char *ptr;
461     double result;
462     errno = 0;
463     result = strtod (input, &ptr);
464     ASSERT (result == 0.0);
465     ASSERT (!signbit (result));
466     ASSERT (ptr == input + 1);          /* glibc-2.3.6, MacOS X 10.3, FreeBSD 6.2 */
467     ASSERT (errno == 0);
468   }
469   {
470     const char input[] = "0x.p+1";
471     char *ptr;
472     double result;
473     errno = 0;
474     result = strtod (input, &ptr);
475     ASSERT (result == 0.0);
476     ASSERT (!signbit (result));
477     ASSERT (ptr == input + 1);          /* glibc-2.3.6, MacOS X 10.3, FreeBSD 6.2 */
478     ASSERT (errno == 0);
479   }
480   {
481     const char input[] = "1p+1";
482     char *ptr;
483     double result;
484     errno = 0;
485     result = strtod (input, &ptr);
486     ASSERT (result == 1.0);
487     ASSERT (ptr == input + 1);
488     ASSERT (errno == 0);
489   }
490
491   /* Overflow/underflow.  */
492   {
493     const char input[] = "1E1000000";
494     char *ptr;
495     double result;
496     errno = 0;
497     result = strtod (input, &ptr);
498     ASSERT (result == HUGE_VAL);
499     ASSERT (ptr == input + 9);          /* OSF/1 5.1 */
500     ASSERT (errno == ERANGE);
501   }
502   {
503     const char input[] = "-1E1000000";
504     char *ptr;
505     double result;
506     errno = 0;
507     result = strtod (input, &ptr);
508     ASSERT (result == -HUGE_VAL);
509     ASSERT (ptr == input + 10);
510     ASSERT (errno == ERANGE);
511   }
512   {
513     const char input[] = "1E-100000";
514     char *ptr;
515     double result;
516     errno = 0;
517     result = strtod (input, &ptr);
518     ASSERT (0.0 <= result && result <= DBL_MIN);
519     ASSERT (!signbit (result));
520     ASSERT (ptr == input + 9);
521     ASSERT (errno == ERANGE);
522   }
523   {
524     const char input[] = "-1E-100000";
525     char *ptr;
526     double result;
527     errno = 0;
528     result = strtod (input, &ptr);
529     ASSERT (-DBL_MIN <= result && result <= 0.0);
530 #if 0
531     /* FIXME - this is glibc bug 5995; POSIX allows returning positive
532        0 on negative underflow, even though quality of implementation
533        demands preserving the sign.  Disable this test until fixed
534        glibc is more prevalent.  */
535     ASSERT (!!signbit (result) == !!signbit (-zero)); /* glibc-2.3.6, mingw */
536 #endif
537     ASSERT (ptr == input + 10);
538     ASSERT (errno == ERANGE);
539   }
540
541   /* Infinity.  */
542   {
543     const char input[] = "iNf";
544     char *ptr;
545     double result;
546     errno = 0;
547     result = strtod (input, &ptr);
548     ASSERT (result == HUGE_VAL);        /* OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
549     ASSERT (ptr == input + 3);          /* OpenBSD 4.0, HP-UX 11.00, IRIX 6.5, OSF/1 5.1, Solaris 9, mingw */
550     ASSERT (errno == 0);                /* HP-UX 11.11, OSF/1 4.0 */
551   }
552   {
553     const char input[] = "-InF";
554     char *ptr;
555     double result;
556     errno = 0;
557     result = strtod (input, &ptr);
558     ASSERT (result == -HUGE_VAL);       /* OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
559     ASSERT (ptr == input + 4);          /* OpenBSD 4.0, HP-UX 11.00, IRIX 6.5, OSF/1 4.0, Solaris 9, mingw */
560     ASSERT (errno == 0);                /* HP-UX 11.11, OSF/1 4.0 */
561   }
562   {
563     const char input[] = "infinite";
564     char *ptr;
565     double result;
566     errno = 0;
567     result = strtod (input, &ptr);
568     ASSERT (result == HUGE_VAL);        /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
569     ASSERT (ptr == input + 3);          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
570     ASSERT (errno == 0);                /* OSF/1 4.0 */
571   }
572   {
573     const char input[] = "infinitY";
574     char *ptr;
575     double result;
576     errno = 0;
577     result = strtod (input, &ptr);
578     ASSERT (result == HUGE_VAL);        /* OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
579     ASSERT (ptr == input + 8);          /* OpenBSD 4.0, HP-UX 11.00, IRIX 6.5, OSF/1 5.1, Solaris 9, mingw */
580     ASSERT (errno == 0);                /* HP-UX 11.11, OSF/1 4.0 */
581   }
582   {
583     const char input[] = "infinitY.";
584     char *ptr;
585     double result;
586     errno = 0;
587     result = strtod (input, &ptr);
588     ASSERT (result == HUGE_VAL);        /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
589     ASSERT (ptr == input + 8);          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
590     ASSERT (errno == 0);                /* OSF/1 4.0 */
591   }
592
593   /* NaN.  Some processors set the sign bit of the default NaN, so all
594      we check is that using a sign changes the result.  */
595   {
596     const char input[] = "-nan";
597     char *ptr1;
598     char *ptr2;
599     double result1;
600     double result2;
601     errno = 0;
602     result1 = strtod (input, &ptr1);
603     result2 = strtod (input + 1, &ptr2);
604 #if 1 /* All known CPUs support NaNs.  */
605     ASSERT (isnand (result1));          /* OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
606     ASSERT (isnand (result2));          /* OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
607 # if 0
608     /* Sign bits of NaN is a portability sticking point, not worth
609        worrying about.  */
610     ASSERT (!!signbit (result1) != !!signbit (result2)); /* glibc-2.3.6, IRIX 6.5, OSF/1 5.1, mingw */
611 # endif
612     ASSERT (ptr1 == input + 4);         /* OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, Solaris 2.5.1, mingw */
613     ASSERT (ptr2 == input + 4);         /* OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, Solaris 2.5.1, mingw */
614     ASSERT (errno == 0);                /* HP-UX 11.11 */
615 #else
616     ASSERT (result1 == 0.0);
617     ASSERT (result2 == 0.0);
618     ASSERT (!signbit (result1));
619     ASSERT (!signbit (result2));
620     ASSERT (ptr1 == input);
621     ASSERT (ptr2 == input + 1);
622     ASSERT (errno == 0 || errno == EINVAL);
623 #endif
624   }
625   {
626     const char input[] = "+nan(";
627     char *ptr1;
628     char *ptr2;
629     double result1;
630     double result2;
631     errno = 0;
632     result1 = strtod (input, &ptr1);
633     result2 = strtod (input + 1, &ptr2);
634 #if 1 /* All known CPUs support NaNs.  */
635     ASSERT (isnand (result1));          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
636     ASSERT (isnand (result2));          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
637     ASSERT (!!signbit (result1) == !!signbit (result2));
638     ASSERT (ptr1 == input + 4);         /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 2.5.1, mingw */
639     ASSERT (ptr2 == input + 4);         /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 2.5.1, mingw */
640     ASSERT (errno == 0);
641 #else
642     ASSERT (result1 == 0.0);
643     ASSERT (result2 == 0.0);
644     ASSERT (!signbit (result1));
645     ASSERT (!signbit (result2));
646     ASSERT (ptr1 == input);
647     ASSERT (ptr2 == input + 1);
648     ASSERT (errno == 0 || errno == EINVAL);
649 #endif
650   }
651   {
652     const char input[] = "-nan()";
653     char *ptr1;
654     char *ptr2;
655     double result1;
656     double result2;
657     errno = 0;
658     result1 = strtod (input, &ptr1);
659     result2 = strtod (input + 1, &ptr2);
660 #if 1 /* All known CPUs support NaNs.  */
661     ASSERT (isnand (result1));          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
662     ASSERT (isnand (result2));          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
663 # if 0
664     /* Sign bits of NaN is a portability sticking point, not worth
665        worrying about.  */
666     ASSERT (!!signbit (result1) != !!signbit (result2)); /* glibc-2.3.6, IRIX 6.5, OSF/1 5.1, mingw */
667 # endif
668     ASSERT (ptr1 == input + 6);         /* glibc-2.3.6, MacOS X 10.3, FreeBSD 6.2, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
669     ASSERT (ptr2 == input + 6);         /* glibc-2.3.6, MacOS X 10.3, FreeBSD 6.2, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
670     ASSERT (errno == 0);
671 #else
672     ASSERT (result1 == 0.0);
673     ASSERT (result2 == 0.0);
674     ASSERT (!signbit (result1));
675     ASSERT (!signbit (result2));
676     ASSERT (ptr1 == input);
677     ASSERT (ptr2 == input + 1);
678     ASSERT (errno == 0 || errno == EINVAL);
679 #endif
680   }
681   {
682     const char input[] = " nan().";
683     char *ptr;
684     double result;
685     errno = 0;
686     result = strtod (input, &ptr);
687 #if 1 /* All known CPUs support NaNs.  */
688     ASSERT (isnand (result));           /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
689     ASSERT (ptr == input + 6);          /* glibc-2.3.6, MacOS X 10.3, FreeBSD 6.2, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
690     ASSERT (errno == 0);
691 #else
692     ASSERT (result == 0.0);
693     ASSERT (!signbit (result));
694     ASSERT (ptr == input);
695     ASSERT (errno == 0 || errno == EINVAL);
696 #endif
697   }
698   {
699     /* The behavior of nan(0) is implementation-defined, but all
700        implementations we know of which handle optional
701        n-char-sequences handle nan(0) the same as nan().  */
702     const char input[] = "-nan(0).";
703     char *ptr1;
704     char *ptr2;
705     double result1;
706     double result2;
707     errno = 0;
708     result1 = strtod (input, &ptr1);
709     result2 = strtod (input + 1, &ptr2);
710 #if 1 /* All known CPUs support NaNs.  */
711     ASSERT (isnand (result1));          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
712     ASSERT (isnand (result2));          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
713 # if 0
714     /* Sign bits of NaN is a portability sticking point, not worth
715        worrying about.  */
716     ASSERT (!!signbit (result1) != !!signbit (result2)); /* glibc-2.3.6, IRIX 6.5, OSF/1 5.1, mingw */
717 # endif
718     ASSERT (ptr1 == input + 7);         /* glibc-2.3.6, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
719     ASSERT (ptr2 == input + 7);         /* glibc-2.3.6, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
720     ASSERT (errno == 0);
721 #else
722     ASSERT (result1 == 0.0);
723     ASSERT (result2 == 0.0);
724     ASSERT (!signbit (result1));
725     ASSERT (!signbit (result2));
726     ASSERT (ptr1 == input);
727     ASSERT (ptr2 == input + 1);
728     ASSERT (errno == 0 || errno == EINVAL);
729 #endif
730   }
731
732   /* Hex.  */
733   {
734     const char input[] = "0xa";
735     char *ptr;
736     double result;
737     errno = 0;
738     result = strtod (input, &ptr);
739     ASSERT (result == 10.0);            /* NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
740     ASSERT (ptr == input + 3);          /* NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
741     ASSERT (errno == 0);
742   }
743   {
744     const char input[] = "0XA";
745     char *ptr;
746     double result;
747     errno = 0;
748     result = strtod (input, &ptr);
749     ASSERT (result == 10.0);            /* NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
750     ASSERT (ptr == input + 3);          /* NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
751     ASSERT (errno == 0);
752   }
753   {
754     const char input[] = "0x1p";
755     char *ptr;
756     double result;
757     errno = 0;
758     result = strtod (input, &ptr);
759     ASSERT (result == 1.0);             /* NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
760     ASSERT (ptr == input + 3);          /* NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
761     ASSERT (errno == 0);
762   }
763   {
764     const char input[] = "0x1p+";
765     char *ptr;
766     double result;
767     errno = 0;
768     result = strtod (input, &ptr);
769     ASSERT (result == 1.0);             /* NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
770     ASSERT (ptr == input + 3);          /* NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
771     ASSERT (errno == 0);
772   }
773   {
774     const char input[] = "0x1p+1";
775     char *ptr;
776     double result;
777     errno = 0;
778     result = strtod (input, &ptr);
779     ASSERT (result == 2.0);             /* NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
780     ASSERT (ptr == input + 6);          /* NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
781     ASSERT (errno == 0);
782   }
783   {
784     const char input[] = "0x1p+1a";
785     char *ptr;
786     double result;
787     errno = 0;
788     result = strtod (input, &ptr);
789     ASSERT (result == 2.0);             /* NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
790     ASSERT (ptr == input + 6);          /* NetBSD 3.0, OpenBSD 4.0, AIX 5.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
791     ASSERT (errno == 0);
792   }
793
794   /* Large buffers.  */
795   {
796     size_t m = 1000000;
797     char *input = malloc (m + 1);
798     if (input)
799       {
800         char *ptr;
801         double result;
802         memset (input, '\t', m - 1);
803         input[m - 1] = '1';
804         input[m] = '\0';
805         errno = 0;
806         result = strtod (input, &ptr);
807         ASSERT (result == 1.0);
808         ASSERT (ptr == input + m);
809         ASSERT (errno == 0);
810       }
811     free (input);
812   }
813   {
814     size_t m = 1000000;
815     char *input = malloc (m + 1);
816     if (input)
817       {
818         char *ptr;
819         double result;
820         memset (input, '0', m - 1);
821         input[m - 1] = '1';
822         input[m] = '\0';
823         errno = 0;
824         result = strtod (input, &ptr);
825         ASSERT (result == 1.0);
826         ASSERT (ptr == input + m);
827         ASSERT (errno == 0);
828       }
829     free (input);
830   }
831 #if 0
832   /* Newlib has an artificial limit of 20000 for the exponent.  TODO -
833      gnulib should fix this.  */
834   {
835     size_t m = 1000000;
836     char *input = malloc (m + 1);
837     if (input)
838       {
839         char *ptr;
840         double result;
841         input[0] = '.';
842         memset (input + 1, '0', m - 10);
843         input[m - 9] = '1';
844         input[m - 8] = 'e';
845         input[m - 7] = '+';
846         input[m - 6] = '9';
847         input[m - 5] = '9';
848         input[m - 4] = '9';
849         input[m - 3] = '9';
850         input[m - 2] = '9';
851         input[m - 1] = '1';
852         input[m] = '\0';
853         errno = 0;
854         result = strtod (input, &ptr);
855         ASSERT (result == 1.0);         /* MacOS X 10.3, FreeBSD 6.2, NetBSD 3.0, OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
856         ASSERT (ptr == input + m);      /* OSF/1 5.1 */
857         ASSERT (errno == 0);            /* MacOS X 10.3, FreeBSD 6.2, NetBSD 3.0, OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
858       }
859     free (input);
860   }
861   {
862     size_t m = 1000000;
863     char *input = malloc (m + 1);
864     if (input)
865       {
866         char *ptr;
867         double result;
868         input[0] = '1';
869         memset (input + 1, '0', m - 9);
870         input[m - 8] = 'e';
871         input[m - 7] = '-';
872         input[m - 6] = '9';
873         input[m - 5] = '9';
874         input[m - 4] = '9';
875         input[m - 3] = '9';
876         input[m - 2] = '9';
877         input[m - 1] = '1';
878         input[m] = '\0';
879         errno = 0;
880         result = strtod (input, &ptr);
881         ASSERT (result == 1.0);         /* MacOS X 10.3, FreeBSD 6.2, NetBSD 3.0, OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
882         ASSERT (ptr == input + m);
883         ASSERT (errno == 0);            /* MacOS X 10.3, FreeBSD 6.2, NetBSD 3.0, OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
884       }
885     free (input);
886   }
887 #endif
888   {
889     size_t m = 1000000;
890     char *input = malloc (m + 1);
891     if (input)
892       {
893         char *ptr;
894         double result;
895         input[0] = '-';
896         input[1] = '0';
897         input[2] = 'e';
898         input[3] = '1';
899         memset (input + 4, '0', m - 3);
900         input[m] = '\0';
901         errno = 0;
902         result = strtod (input, &ptr);
903         ASSERT (result == 0.0);
904         ASSERT (!!signbit (result) == !!signbit (-zero)); /* IRIX 6.5, OSF/1 4.0 */
905         ASSERT (ptr == input + m);
906         ASSERT (errno == 0);
907       }
908     free (input);
909   }
910
911   /* Rounding.  */
912   /* TODO - is it worth some tests of rounding for typical IEEE corner
913      cases, such as .5 ULP rounding up to the smallest denormal and
914      not causing underflow, or DBL_MIN - .5 ULP not causing an
915      infinite loop?  */
916
917   return status;
918 }