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