Fix strtod test for values above maximum for IBM long double.
[platform/upstream/glibc.git] / stdlib / gen-tst-strtod-round.c
1 /* Generate table of tests in tst-strtod-round.c from
2    tst-strtod-round-data.
3    Copyright (C) 2012 Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, see
18    <http://www.gnu.org/licenses/>.  */
19
20 #define _GNU_SOURCE
21 #include <assert.h>
22 #include <stdbool.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <mpfr.h>
26
27 /* Work around incorrect ternary value from mpfr_strtofr
28    <https://sympa.inria.fr/sympa/arc/mpfr/2012-08/msg00005.html>.  */
29 #define WORKAROUND
30
31 static int
32 string_to_fp (mpfr_t f, const char *s, mpfr_rnd_t rnd)
33 {
34 #ifdef WORKAROUND
35   mpfr_t f2;
36   mpfr_init2 (f2, 100000);
37   int r0 = mpfr_strtofr (f2, s, NULL, 0, rnd);
38   int r = mpfr_set (f, f2, rnd);
39   mpfr_subnormalize (f, r, rnd);
40   mpfr_clear (f2);
41   return r0 | r;
42 #else
43   int r = mpfr_strtofr (f, s, NULL, 0, rnd);
44   mpfr_subnormalize (f, r, rnd);
45   return r;
46 #endif
47 }
48
49 static void
50 print_fp (mpfr_t f, const char *suffix, const char *suffix2)
51 {
52   if (mpfr_inf_p (f))
53     mpfr_printf ("\t%sINFINITY%s", mpfr_signbit (f) ? "-" : "", suffix2);
54   else
55     mpfr_printf ("\t%Ra%s%s", f, suffix, suffix2);
56 }
57
58 static void
59 round_str (const char *s, const char *suffix,
60            int prec, int emin, int emax, bool need_exact)
61 {
62   mpfr_t f;
63   mpfr_set_default_prec (prec);
64   mpfr_set_emin (emin);
65   mpfr_set_emax (emax);
66   mpfr_init (f);
67   int r = string_to_fp (f, s, MPFR_RNDD);
68   if (need_exact)
69     {
70       assert (prec == 106 && emin == -1073 && emax == 1024);
71       /* The maximum value in IBM long double has discontiguous
72          mantissa bits.  */
73       mpfr_t max_value;
74       mpfr_init2 (max_value, 107);
75       mpfr_set_str (max_value, "0x1.fffffffffffff7ffffffffffffcp+1023", 0,
76                     MPFR_RNDN);
77       if (mpfr_cmpabs (f, max_value) > 0)
78         r = 1;
79       mpfr_printf ("\t%s,\n", r ? "false" : "true");
80       mpfr_clear (max_value);
81     }
82   print_fp (f, suffix, ",\n");
83   string_to_fp (f, s, MPFR_RNDN);
84   print_fp (f, suffix, ",\n");
85   string_to_fp (f, s, MPFR_RNDZ);
86   print_fp (f, suffix, ",\n");
87   string_to_fp (f, s, MPFR_RNDU);
88   print_fp (f, suffix, "");
89   mpfr_clear (f);
90 }
91
92 static void
93 round_for_all (const char *s)
94 {
95   static const struct fmt {
96     const char *suffix;
97     int prec;
98     int emin;
99     int emax;
100     bool need_exact;
101   } formats[7] = {
102     { "f", 24, -148, 128, false },
103     { "", 53, -1073, 1024, false },
104     { "L", 53, -1073, 1024, false },
105     /* This is the Intel extended float format.  */
106     { "L", 64, -16444, 16384, false },
107     /* This is the Motorola extended float format.  */
108     { "L", 64, -16445, 16384, false },
109     { "L", 106, -1073, 1024, true },
110     { "L", 113, -16493, 16384, false },
111   };
112   mpfr_printf ("  TEST (\"");
113   const char *p;
114   for (p = s; *p; p++)
115     {
116       putchar (*p);
117       if ((p - s) % 60 == 59 && p[1])
118         mpfr_printf ("\"\n\t\"");
119     }
120   mpfr_printf ("\",\n");
121   int i;
122   for (i = 0; i < 7; i++)
123     {
124       round_str (s, formats[i].suffix, formats[i].prec,
125                  formats[i].emin, formats[i].emax, formats[i].need_exact);
126       if (i < 6)
127         mpfr_printf (",\n");
128     }
129   mpfr_printf ("),\n");
130 }
131
132 int
133 main (void)
134 {
135   char *p = NULL;
136   size_t len;
137   ssize_t nbytes;
138   while ((nbytes = getline (&p, &len, stdin)) != -1)
139     {
140       if (p[nbytes - 1] == '\n')
141         p[nbytes - 1] = 0;
142       round_for_all (p);
143       free (p);
144       p = NULL;
145     }
146   return 0;
147 }