strtod: work around IRIX 6.5 bug
[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, AIX 7.1 */
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, AIX 7.1 */
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, AIX 7.1 */
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, AIX 7.1 */
434     ASSERT (errno == 0);
435   }
436   {
437     const char input[] = "0XP";
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, AIX 7.1 */
445     ASSERT (errno == 0);
446   }
447   {
448     const char input[] = "0x.";
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, AIX 7.1 */
456     ASSERT (errno == 0);
457   }
458   {
459     const char input[] = "0xp+";
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, AIX 7.1 */
467     ASSERT (errno == 0);
468   }
469   {
470     const char input[] = "0xp+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, AIX 7.1 */
478     ASSERT (errno == 0);
479   }
480   {
481     const char input[] = "0x.p+1";
482     char *ptr;
483     double result;
484     errno = 0;
485     result = strtod (input, &ptr);
486     ASSERT (result == 0.0);
487     ASSERT (!signbit (result));
488     ASSERT (ptr == input + 1);          /* glibc-2.3.6, MacOS X 10.3, FreeBSD 6.2, AIX 7.1 */
489     ASSERT (errno == 0);
490   }
491   {
492     const char input[] = "1p+1";
493     char *ptr;
494     double result;
495     errno = 0;
496     result = strtod (input, &ptr);
497     ASSERT (result == 1.0);
498     ASSERT (ptr == input + 1);
499     ASSERT (errno == 0);
500   }
501   {
502     const char input[] = "1P+1";
503     char *ptr;
504     double result;
505     errno = 0;
506     result = strtod (input, &ptr);
507     ASSERT (result == 1.0);
508     ASSERT (ptr == input + 1);
509     ASSERT (errno == 0);
510   }
511
512   /* Overflow/underflow.  */
513   {
514     const char input[] = "1E1000000";
515     char *ptr;
516     double result;
517     errno = 0;
518     result = strtod (input, &ptr);
519     ASSERT (result == HUGE_VAL);
520     ASSERT (ptr == input + 9);          /* OSF/1 5.1 */
521     ASSERT (errno == ERANGE);
522   }
523   {
524     const char input[] = "-1E1000000";
525     char *ptr;
526     double result;
527     errno = 0;
528     result = strtod (input, &ptr);
529     ASSERT (result == -HUGE_VAL);
530     ASSERT (ptr == input + 10);
531     ASSERT (errno == ERANGE);
532   }
533   {
534     const char input[] = "1E-100000";
535     char *ptr;
536     double result;
537     errno = 0;
538     result = strtod (input, &ptr);
539     ASSERT (0.0 <= result && result <= DBL_MIN);
540     ASSERT (!signbit (result));
541     ASSERT (ptr == input + 9);
542     ASSERT (errno == ERANGE);
543   }
544   {
545     const char input[] = "-1E-100000";
546     char *ptr;
547     double result;
548     errno = 0;
549     result = strtod (input, &ptr);
550     ASSERT (-DBL_MIN <= result && result <= 0.0);
551 #if 0
552     /* FIXME - this is glibc bug 5995; POSIX allows returning positive
553        0 on negative underflow, even though quality of implementation
554        demands preserving the sign.  Disable this test until fixed
555        glibc is more prevalent.  */
556     ASSERT (!!signbit (result) == !!signbit (-zero)); /* glibc-2.3.6, mingw */
557 #endif
558     ASSERT (ptr == input + 10);
559     ASSERT (errno == ERANGE);
560   }
561   {
562     const char input[] = "1E 1000000";
563     char *ptr;
564     double result;
565     errno = 0;
566     result = strtod (input, &ptr);
567     ASSERT (result == 1.0);             /* HP-UX 11.11, IRIX 6.5, OSF/1 4.0 */
568     ASSERT (ptr == input + 1);          /* HP-UX 11.11, IRIX 6.5 */
569     ASSERT (errno == 0);
570   }
571   {
572     const char input[] = "0x1P 1000000";
573     char *ptr;
574     double result;
575     errno = 0;
576     result = strtod (input, &ptr);
577     ASSERT (result == 1.0);             /* NetBSD 3.0, OpenBSD 4.0, AIX 7.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
578     ASSERT (ptr == input + 3);          /* NetBSD 3.0, OpenBSD 4.0, AIX 7.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
579     ASSERT (errno == 0);
580   }
581
582   /* Infinity.  */
583   {
584     const char input[] = "iNf";
585     char *ptr;
586     double result;
587     errno = 0;
588     result = strtod (input, &ptr);
589     ASSERT (result == HUGE_VAL);        /* OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
590     ASSERT (ptr == input + 3);          /* OpenBSD 4.0, HP-UX 11.00, IRIX 6.5, OSF/1 5.1, Solaris 9, mingw */
591     ASSERT (errno == 0);                /* HP-UX 11.11, OSF/1 4.0 */
592   }
593   {
594     const char input[] = "-InF";
595     char *ptr;
596     double result;
597     errno = 0;
598     result = strtod (input, &ptr);
599     ASSERT (result == -HUGE_VAL);       /* OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
600     ASSERT (ptr == input + 4);          /* OpenBSD 4.0, HP-UX 11.00, IRIX 6.5, OSF/1 4.0, Solaris 9, mingw */
601     ASSERT (errno == 0);                /* HP-UX 11.11, OSF/1 4.0 */
602   }
603   {
604     const char input[] = "infinite";
605     char *ptr;
606     double result;
607     errno = 0;
608     result = strtod (input, &ptr);
609     ASSERT (result == HUGE_VAL);        /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
610     ASSERT (ptr == input + 3);          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
611     ASSERT (errno == 0);                /* OSF/1 4.0 */
612   }
613   {
614     const char input[] = "infinitY";
615     char *ptr;
616     double result;
617     errno = 0;
618     result = strtod (input, &ptr);
619     ASSERT (result == HUGE_VAL);        /* OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
620     ASSERT (ptr == input + 8);          /* OpenBSD 4.0, HP-UX 11.00, IRIX 6.5, OSF/1 5.1, Solaris 9, mingw */
621     ASSERT (errno == 0);                /* HP-UX 11.11, OSF/1 4.0 */
622   }
623   {
624     const char input[] = "infinitY.";
625     char *ptr;
626     double result;
627     errno = 0;
628     result = strtod (input, &ptr);
629     ASSERT (result == HUGE_VAL);        /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
630     ASSERT (ptr == input + 8);          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
631     ASSERT (errno == 0);                /* OSF/1 4.0 */
632   }
633
634   /* NaN.  Some processors set the sign bit of the default NaN, so all
635      we check is that using a sign changes the result.  */
636   {
637     const char input[] = "-nan";
638     char *ptr1;
639     char *ptr2;
640     double result1;
641     double result2;
642     errno = 0;
643     result1 = strtod (input, &ptr1);
644     result2 = strtod (input + 1, &ptr2);
645 #if 1 /* All known CPUs support NaNs.  */
646     ASSERT (isnand (result1));          /* OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
647     ASSERT (isnand (result2));          /* OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
648 # if 0
649     /* Sign bits of NaN is a portability sticking point, not worth
650        worrying about.  */
651     ASSERT (!!signbit (result1) != !!signbit (result2)); /* glibc-2.3.6, IRIX 6.5, OSF/1 5.1, mingw */
652 # endif
653     ASSERT (ptr1 == input + 4);         /* OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, Solaris 2.5.1, mingw */
654     ASSERT (ptr2 == input + 4);         /* OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, Solaris 2.5.1, mingw */
655     ASSERT (errno == 0);                /* HP-UX 11.11 */
656 #else
657     ASSERT (result1 == 0.0);
658     ASSERT (result2 == 0.0);
659     ASSERT (!signbit (result1));
660     ASSERT (!signbit (result2));
661     ASSERT (ptr1 == input);
662     ASSERT (ptr2 == input + 1);
663     ASSERT (errno == 0 || errno == EINVAL);
664 #endif
665   }
666   {
667     const char input[] = "+nan(";
668     char *ptr1;
669     char *ptr2;
670     double result1;
671     double result2;
672     errno = 0;
673     result1 = strtod (input, &ptr1);
674     result2 = strtod (input + 1, &ptr2);
675 #if 1 /* All known CPUs support NaNs.  */
676     ASSERT (isnand (result1));          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
677     ASSERT (isnand (result2));          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
678     ASSERT (!!signbit (result1) == !!signbit (result2));
679     ASSERT (ptr1 == input + 4);         /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 2.5.1, mingw */
680     ASSERT (ptr2 == input + 4);         /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 2.5.1, mingw */
681     ASSERT (errno == 0);
682 #else
683     ASSERT (result1 == 0.0);
684     ASSERT (result2 == 0.0);
685     ASSERT (!signbit (result1));
686     ASSERT (!signbit (result2));
687     ASSERT (ptr1 == input);
688     ASSERT (ptr2 == input + 1);
689     ASSERT (errno == 0 || errno == EINVAL);
690 #endif
691   }
692   {
693     const char input[] = "-nan()";
694     char *ptr1;
695     char *ptr2;
696     double result1;
697     double result2;
698     errno = 0;
699     result1 = strtod (input, &ptr1);
700     result2 = strtod (input + 1, &ptr2);
701 #if 1 /* All known CPUs support NaNs.  */
702     ASSERT (isnand (result1));          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
703     ASSERT (isnand (result2));          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
704 # if 0
705     /* Sign bits of NaN is a portability sticking point, not worth
706        worrying about.  */
707     ASSERT (!!signbit (result1) != !!signbit (result2)); /* glibc-2.3.6, IRIX 6.5, OSF/1 5.1, mingw */
708 # endif
709     ASSERT (ptr1 == input + 6);         /* glibc-2.3.6, MacOS X 10.3, FreeBSD 6.2, OpenBSD 4.0, AIX 7.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
710     ASSERT (ptr2 == input + 6);         /* glibc-2.3.6, MacOS X 10.3, FreeBSD 6.2, OpenBSD 4.0, AIX 7.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
711     ASSERT (errno == 0);
712 #else
713     ASSERT (result1 == 0.0);
714     ASSERT (result2 == 0.0);
715     ASSERT (!signbit (result1));
716     ASSERT (!signbit (result2));
717     ASSERT (ptr1 == input);
718     ASSERT (ptr2 == input + 1);
719     ASSERT (errno == 0 || errno == EINVAL);
720 #endif
721   }
722   {
723     const char input[] = " nan().";
724     char *ptr;
725     double result;
726     errno = 0;
727     result = strtod (input, &ptr);
728 #if 1 /* All known CPUs support NaNs.  */
729     ASSERT (isnand (result));           /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
730     ASSERT (ptr == input + 6);          /* glibc-2.3.6, MacOS X 10.3, FreeBSD 6.2, OpenBSD 4.0, AIX 7.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
731     ASSERT (errno == 0);
732 #else
733     ASSERT (result == 0.0);
734     ASSERT (!signbit (result));
735     ASSERT (ptr == input);
736     ASSERT (errno == 0 || errno == EINVAL);
737 #endif
738   }
739   {
740     /* The behavior of nan(0) is implementation-defined, but all
741        implementations we know of which handle optional
742        n-char-sequences handle nan(0) the same as nan().  */
743     const char input[] = "-nan(0).";
744     char *ptr1;
745     char *ptr2;
746     double result1;
747     double result2;
748     errno = 0;
749     result1 = strtod (input, &ptr1);
750     result2 = strtod (input + 1, &ptr2);
751 #if 1 /* All known CPUs support NaNs.  */
752     ASSERT (isnand (result1));          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
753     ASSERT (isnand (result2));          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
754 # if 0
755     /* Sign bits of NaN is a portability sticking point, not worth
756        worrying about.  */
757     ASSERT (!!signbit (result1) != !!signbit (result2)); /* glibc-2.3.6, IRIX 6.5, OSF/1 5.1, mingw */
758 # endif
759     ASSERT (ptr1 == input + 7);         /* glibc-2.3.6, OpenBSD 4.0, AIX 7.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
760     ASSERT (ptr2 == input + 7);         /* glibc-2.3.6, OpenBSD 4.0, AIX 7.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
761     ASSERT (errno == 0);
762 #else
763     ASSERT (result1 == 0.0);
764     ASSERT (result2 == 0.0);
765     ASSERT (!signbit (result1));
766     ASSERT (!signbit (result2));
767     ASSERT (ptr1 == input);
768     ASSERT (ptr2 == input + 1);
769     ASSERT (errno == 0 || errno == EINVAL);
770 #endif
771   }
772
773   /* Hex.  */
774   {
775     const char input[] = "0xa";
776     char *ptr;
777     double result;
778     errno = 0;
779     result = strtod (input, &ptr);
780     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 */
781     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 */
782     ASSERT (errno == 0);
783   }
784   {
785     const char input[] = "0XA";
786     char *ptr;
787     double result;
788     errno = 0;
789     result = strtod (input, &ptr);
790     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 */
791     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 */
792     ASSERT (errno == 0);
793   }
794   {
795     const char input[] = "0x1p";
796     char *ptr;
797     double result;
798     errno = 0;
799     result = strtod (input, &ptr);
800     ASSERT (result == 1.0);             /* NetBSD 3.0, OpenBSD 4.0, AIX 7.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
801     ASSERT (ptr == input + 3);          /* NetBSD 3.0, OpenBSD 4.0, AIX 7.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
802     ASSERT (errno == 0);
803   }
804   {
805     const char input[] = "0x1p+";
806     char *ptr;
807     double result;
808     errno = 0;
809     result = strtod (input, &ptr);
810     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 */
811     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 */
812     ASSERT (errno == 0);
813   }
814   {
815     const char input[] = "0x1P+";
816     char *ptr;
817     double result;
818     errno = 0;
819     result = strtod (input, &ptr);
820     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 */
821     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 */
822     ASSERT (errno == 0);
823   }
824   {
825     const char input[] = "0x1p+1";
826     char *ptr;
827     double result;
828     errno = 0;
829     result = strtod (input, &ptr);
830     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 */
831     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 */
832     ASSERT (errno == 0);
833   }
834   {
835     const char input[] = "0X1P+1";
836     char *ptr;
837     double result;
838     errno = 0;
839     result = strtod (input, &ptr);
840     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 */
841     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 */
842     ASSERT (errno == 0);
843   }
844   {
845     const char input[] = "0x1p+1a";
846     char *ptr;
847     double result;
848     errno = 0;
849     result = strtod (input, &ptr);
850     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 */
851     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 */
852     ASSERT (errno == 0);
853   }
854   {
855     const char input[] = "0x1p 2";
856     char *ptr;
857     double result;
858     errno = 0;
859     result = strtod (input, &ptr);
860     ASSERT (result == 1.0);             /* NetBSD 3.0, OpenBSD 4.0, AIX 7.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
861     ASSERT (ptr == input + 3);          /* NetBSD 3.0, OpenBSD 4.0, AIX 7.1, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw */
862     ASSERT (errno == 0);
863   }
864
865   /* Large buffers.  */
866   {
867     size_t m = 1000000;
868     char *input = malloc (m + 1);
869     if (input)
870       {
871         char *ptr;
872         double result;
873         memset (input, '\t', m - 1);
874         input[m - 1] = '1';
875         input[m] = '\0';
876         errno = 0;
877         result = strtod (input, &ptr);
878         ASSERT (result == 1.0);
879         ASSERT (ptr == input + m);
880         ASSERT (errno == 0);
881       }
882     free (input);
883   }
884   {
885     size_t m = 1000000;
886     char *input = malloc (m + 1);
887     if (input)
888       {
889         char *ptr;
890         double result;
891         memset (input, '0', m - 1);
892         input[m - 1] = '1';
893         input[m] = '\0';
894         errno = 0;
895         result = strtod (input, &ptr);
896         ASSERT (result == 1.0);
897         ASSERT (ptr == input + m);
898         ASSERT (errno == 0);
899       }
900     free (input);
901   }
902 #if 0
903   /* Newlib has an artificial limit of 20000 for the exponent.  TODO -
904      gnulib should fix this.  */
905   {
906     size_t m = 1000000;
907     char *input = malloc (m + 1);
908     if (input)
909       {
910         char *ptr;
911         double result;
912         input[0] = '.';
913         memset (input + 1, '0', m - 10);
914         input[m - 9] = '1';
915         input[m - 8] = 'e';
916         input[m - 7] = '+';
917         input[m - 6] = '9';
918         input[m - 5] = '9';
919         input[m - 4] = '9';
920         input[m - 3] = '9';
921         input[m - 2] = '9';
922         input[m - 1] = '1';
923         input[m] = '\0';
924         errno = 0;
925         result = strtod (input, &ptr);
926         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 */
927         ASSERT (ptr == input + m);      /* OSF/1 5.1 */
928         ASSERT (errno == 0);            /* MacOS X 10.3, FreeBSD 6.2, NetBSD 3.0, OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
929       }
930     free (input);
931   }
932   {
933     size_t m = 1000000;
934     char *input = malloc (m + 1);
935     if (input)
936       {
937         char *ptr;
938         double result;
939         input[0] = '1';
940         memset (input + 1, '0', m - 9);
941         input[m - 8] = 'e';
942         input[m - 7] = '-';
943         input[m - 6] = '9';
944         input[m - 5] = '9';
945         input[m - 4] = '9';
946         input[m - 3] = '9';
947         input[m - 2] = '9';
948         input[m - 1] = '1';
949         input[m] = '\0';
950         errno = 0;
951         result = strtod (input, &ptr);
952         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 */
953         ASSERT (ptr == input + m);
954         ASSERT (errno == 0);            /* MacOS X 10.3, FreeBSD 6.2, NetBSD 3.0, OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
955       }
956     free (input);
957   }
958 #endif
959   {
960     size_t m = 1000000;
961     char *input = malloc (m + 1);
962     if (input)
963       {
964         char *ptr;
965         double result;
966         input[0] = '-';
967         input[1] = '0';
968         input[2] = 'e';
969         input[3] = '1';
970         memset (input + 4, '0', m - 3);
971         input[m] = '\0';
972         errno = 0;
973         result = strtod (input, &ptr);
974         ASSERT (result == 0.0);
975         ASSERT (!!signbit (result) == !!signbit (-zero)); /* IRIX 6.5, OSF/1 4.0 */
976         ASSERT (ptr == input + m);
977         ASSERT (errno == 0);
978       }
979     free (input);
980   }
981
982   /* Rounding.  */
983   /* TODO - is it worth some tests of rounding for typical IEEE corner
984      cases, such as .5 ULP rounding up to the smallest denormal and
985      not causing underflow, or DBL_MIN - .5 ULP not causing an
986      infinite loop?  */
987
988   return status;
989 }