strtod: next round of AIX fixes
[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   /* Infinity.  */
563   {
564     const char input[] = "iNf";
565     char *ptr;
566     double result;
567     errno = 0;
568     result = strtod (input, &ptr);
569     ASSERT (result == HUGE_VAL);        /* OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
570     ASSERT (ptr == input + 3);          /* OpenBSD 4.0, HP-UX 11.00, IRIX 6.5, OSF/1 5.1, Solaris 9, mingw */
571     ASSERT (errno == 0);                /* HP-UX 11.11, OSF/1 4.0 */
572   }
573   {
574     const char input[] = "-InF";
575     char *ptr;
576     double result;
577     errno = 0;
578     result = strtod (input, &ptr);
579     ASSERT (result == -HUGE_VAL);       /* OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
580     ASSERT (ptr == input + 4);          /* OpenBSD 4.0, HP-UX 11.00, IRIX 6.5, OSF/1 4.0, Solaris 9, mingw */
581     ASSERT (errno == 0);                /* HP-UX 11.11, OSF/1 4.0 */
582   }
583   {
584     const char input[] = "infinite";
585     char *ptr;
586     double result;
587     errno = 0;
588     result = strtod (input, &ptr);
589     ASSERT (result == HUGE_VAL);        /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
590     ASSERT (ptr == input + 3);          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
591     ASSERT (errno == 0);                /* OSF/1 4.0 */
592   }
593   {
594     const char input[] = "infinitY";
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 + 8);          /* OpenBSD 4.0, HP-UX 11.00, IRIX 6.5, OSF/1 5.1, Solaris 9, mingw */
601     ASSERT (errno == 0);                /* HP-UX 11.11, OSF/1 4.0 */
602   }
603   {
604     const char input[] = "infinitY.";
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 + 8);          /* 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   /* NaN.  Some processors set the sign bit of the default NaN, so all
615      we check is that using a sign changes the result.  */
616   {
617     const char input[] = "-nan";
618     char *ptr1;
619     char *ptr2;
620     double result1;
621     double result2;
622     errno = 0;
623     result1 = strtod (input, &ptr1);
624     result2 = strtod (input + 1, &ptr2);
625 #if 1 /* All known CPUs support NaNs.  */
626     ASSERT (isnand (result1));          /* OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
627     ASSERT (isnand (result2));          /* OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
628 # if 0
629     /* Sign bits of NaN is a portability sticking point, not worth
630        worrying about.  */
631     ASSERT (!!signbit (result1) != !!signbit (result2)); /* glibc-2.3.6, IRIX 6.5, OSF/1 5.1, mingw */
632 # endif
633     ASSERT (ptr1 == input + 4);         /* OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, Solaris 2.5.1, mingw */
634     ASSERT (ptr2 == input + 4);         /* OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, Solaris 2.5.1, mingw */
635     ASSERT (errno == 0);                /* HP-UX 11.11 */
636 #else
637     ASSERT (result1 == 0.0);
638     ASSERT (result2 == 0.0);
639     ASSERT (!signbit (result1));
640     ASSERT (!signbit (result2));
641     ASSERT (ptr1 == input);
642     ASSERT (ptr2 == input + 1);
643     ASSERT (errno == 0 || errno == EINVAL);
644 #endif
645   }
646   {
647     const char input[] = "+nan(";
648     char *ptr1;
649     char *ptr2;
650     double result1;
651     double result2;
652     errno = 0;
653     result1 = strtod (input, &ptr1);
654     result2 = strtod (input + 1, &ptr2);
655 #if 1 /* All known CPUs support NaNs.  */
656     ASSERT (isnand (result1));          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
657     ASSERT (isnand (result2));          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
658     ASSERT (!!signbit (result1) == !!signbit (result2));
659     ASSERT (ptr1 == input + 4);         /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 2.5.1, mingw */
660     ASSERT (ptr2 == input + 4);         /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, Solaris 2.5.1, mingw */
661     ASSERT (errno == 0);
662 #else
663     ASSERT (result1 == 0.0);
664     ASSERT (result2 == 0.0);
665     ASSERT (!signbit (result1));
666     ASSERT (!signbit (result2));
667     ASSERT (ptr1 == input);
668     ASSERT (ptr2 == input + 1);
669     ASSERT (errno == 0 || errno == EINVAL);
670 #endif
671   }
672   {
673     const char input[] = "-nan()";
674     char *ptr1;
675     char *ptr2;
676     double result1;
677     double result2;
678     errno = 0;
679     result1 = strtod (input, &ptr1);
680     result2 = strtod (input + 1, &ptr2);
681 #if 1 /* All known CPUs support NaNs.  */
682     ASSERT (isnand (result1));          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
683     ASSERT (isnand (result2));          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
684 # if 0
685     /* Sign bits of NaN is a portability sticking point, not worth
686        worrying about.  */
687     ASSERT (!!signbit (result1) != !!signbit (result2)); /* glibc-2.3.6, IRIX 6.5, OSF/1 5.1, mingw */
688 # endif
689     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 */
690     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 */
691     ASSERT (errno == 0);
692 #else
693     ASSERT (result1 == 0.0);
694     ASSERT (result2 == 0.0);
695     ASSERT (!signbit (result1));
696     ASSERT (!signbit (result2));
697     ASSERT (ptr1 == input);
698     ASSERT (ptr2 == input + 1);
699     ASSERT (errno == 0 || errno == EINVAL);
700 #endif
701   }
702   {
703     const char input[] = " nan().";
704     char *ptr;
705     double result;
706     errno = 0;
707     result = strtod (input, &ptr);
708 #if 1 /* All known CPUs support NaNs.  */
709     ASSERT (isnand (result));           /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
710     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 */
711     ASSERT (errno == 0);
712 #else
713     ASSERT (result == 0.0);
714     ASSERT (!signbit (result));
715     ASSERT (ptr == input);
716     ASSERT (errno == 0 || errno == EINVAL);
717 #endif
718   }
719   {
720     /* The behavior of nan(0) is implementation-defined, but all
721        implementations we know of which handle optional
722        n-char-sequences handle nan(0) the same as nan().  */
723     const char input[] = "-nan(0).";
724     char *ptr1;
725     char *ptr2;
726     double result1;
727     double result2;
728     errno = 0;
729     result1 = strtod (input, &ptr1);
730     result2 = strtod (input + 1, &ptr2);
731 #if 1 /* All known CPUs support NaNs.  */
732     ASSERT (isnand (result1));          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
733     ASSERT (isnand (result2));          /* OpenBSD 4.0, HP-UX 11.11, IRIX 6.5, OSF/1 5.1, mingw */
734 # if 0
735     /* Sign bits of NaN is a portability sticking point, not worth
736        worrying about.  */
737     ASSERT (!!signbit (result1) != !!signbit (result2)); /* glibc-2.3.6, IRIX 6.5, OSF/1 5.1, mingw */
738 # endif
739     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 */
740     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 */
741     ASSERT (errno == 0);
742 #else
743     ASSERT (result1 == 0.0);
744     ASSERT (result2 == 0.0);
745     ASSERT (!signbit (result1));
746     ASSERT (!signbit (result2));
747     ASSERT (ptr1 == input);
748     ASSERT (ptr2 == input + 1);
749     ASSERT (errno == 0 || errno == EINVAL);
750 #endif
751   }
752
753   /* Hex.  */
754   {
755     const char input[] = "0xa";
756     char *ptr;
757     double result;
758     errno = 0;
759     result = strtod (input, &ptr);
760     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 */
761     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 */
762     ASSERT (errno == 0);
763   }
764   {
765     const char input[] = "0XA";
766     char *ptr;
767     double result;
768     errno = 0;
769     result = strtod (input, &ptr);
770     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 */
771     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 */
772     ASSERT (errno == 0);
773   }
774   {
775     const char input[] = "0x1p";
776     char *ptr;
777     double result;
778     errno = 0;
779     result = strtod (input, &ptr);
780     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 */
781     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 */
782     ASSERT (errno == 0);
783   }
784   {
785     const char input[] = "0x1p+";
786     char *ptr;
787     double result;
788     errno = 0;
789     result = strtod (input, &ptr);
790     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 */
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 5.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 5.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+1";
806     char *ptr;
807     double result;
808     errno = 0;
809     result = strtod (input, &ptr);
810     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 */
811     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 */
812     ASSERT (errno == 0);
813   }
814   {
815     const char input[] = "0X1P+1";
816     char *ptr;
817     double result;
818     errno = 0;
819     result = strtod (input, &ptr);
820     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 */
821     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 */
822     ASSERT (errno == 0);
823   }
824   {
825     const char input[] = "0x1p+1a";
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   /* Large buffers.  */
836   {
837     size_t m = 1000000;
838     char *input = malloc (m + 1);
839     if (input)
840       {
841         char *ptr;
842         double result;
843         memset (input, '\t', m - 1);
844         input[m - 1] = '1';
845         input[m] = '\0';
846         errno = 0;
847         result = strtod (input, &ptr);
848         ASSERT (result == 1.0);
849         ASSERT (ptr == input + m);
850         ASSERT (errno == 0);
851       }
852     free (input);
853   }
854   {
855     size_t m = 1000000;
856     char *input = malloc (m + 1);
857     if (input)
858       {
859         char *ptr;
860         double result;
861         memset (input, '0', m - 1);
862         input[m - 1] = '1';
863         input[m] = '\0';
864         errno = 0;
865         result = strtod (input, &ptr);
866         ASSERT (result == 1.0);
867         ASSERT (ptr == input + m);
868         ASSERT (errno == 0);
869       }
870     free (input);
871   }
872 #if 0
873   /* Newlib has an artificial limit of 20000 for the exponent.  TODO -
874      gnulib should fix this.  */
875   {
876     size_t m = 1000000;
877     char *input = malloc (m + 1);
878     if (input)
879       {
880         char *ptr;
881         double result;
882         input[0] = '.';
883         memset (input + 1, '0', m - 10);
884         input[m - 9] = '1';
885         input[m - 8] = 'e';
886         input[m - 7] = '+';
887         input[m - 6] = '9';
888         input[m - 5] = '9';
889         input[m - 4] = '9';
890         input[m - 3] = '9';
891         input[m - 2] = '9';
892         input[m - 1] = '1';
893         input[m] = '\0';
894         errno = 0;
895         result = strtod (input, &ptr);
896         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 */
897         ASSERT (ptr == input + m);      /* OSF/1 5.1 */
898         ASSERT (errno == 0);            /* MacOS X 10.3, FreeBSD 6.2, NetBSD 3.0, OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
899       }
900     free (input);
901   }
902   {
903     size_t m = 1000000;
904     char *input = malloc (m + 1);
905     if (input)
906       {
907         char *ptr;
908         double result;
909         input[0] = '1';
910         memset (input + 1, '0', m - 9);
911         input[m - 8] = 'e';
912         input[m - 7] = '-';
913         input[m - 6] = '9';
914         input[m - 5] = '9';
915         input[m - 4] = '9';
916         input[m - 3] = '9';
917         input[m - 2] = '9';
918         input[m - 1] = '1';
919         input[m] = '\0';
920         errno = 0;
921         result = strtod (input, &ptr);
922         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 */
923         ASSERT (ptr == input + m);
924         ASSERT (errno == 0);            /* MacOS X 10.3, FreeBSD 6.2, NetBSD 3.0, OpenBSD 4.0, IRIX 6.5, OSF/1 5.1, mingw */
925       }
926     free (input);
927   }
928 #endif
929   {
930     size_t m = 1000000;
931     char *input = malloc (m + 1);
932     if (input)
933       {
934         char *ptr;
935         double result;
936         input[0] = '-';
937         input[1] = '0';
938         input[2] = 'e';
939         input[3] = '1';
940         memset (input + 4, '0', m - 3);
941         input[m] = '\0';
942         errno = 0;
943         result = strtod (input, &ptr);
944         ASSERT (result == 0.0);
945         ASSERT (!!signbit (result) == !!signbit (-zero)); /* IRIX 6.5, OSF/1 4.0 */
946         ASSERT (ptr == input + m);
947         ASSERT (errno == 0);
948       }
949     free (input);
950   }
951
952   /* Rounding.  */
953   /* TODO - is it worth some tests of rounding for typical IEEE corner
954      cases, such as .5 ULP rounding up to the smallest denormal and
955      not causing underflow, or DBL_MIN - .5 ULP not causing an
956      infinite loop?  */
957
958   return status;
959 }