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