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