1 /* Test file for mpfr_set_z_2exp.
2 
3 Copyright 1999, 2001-2020 Free Software Foundation, Inc.
4 Contributed by the AriC and Caramba projects, INRIA.
5 
6 This file is part of the GNU MPFR Library.
7 
8 The GNU MPFR Library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12 
13 The GNU MPFR Library is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16 License for more details.
17 
18 You should have received a copy of the GNU Lesser General Public License
19 along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
20 https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
21 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
22 
23 #include "mpfr-test.h"
24 
25 /* generate a random exponent in [__gmpfr_emin, __gmpfr_emax-1] */
26 static mpfr_exp_t
randexp(void)27 randexp (void)
28 {
29   mpfr_uexp_t e;
30 
31   if (MPFR_EXP_MAX <= MPFR_LIMB_MAX >> 1)
32     {
33       /* mpfr_uexp_t fits in a limb: we can generate the whole range
34          [emin, emax] directly. */
35       e = randlimb ();
36     }
37   else
38     {
39       mpfr_uexp_t emax = (mpfr_uexp_t) -1;
40 
41       e = 0;
42       while (emax != 0)
43         {
44           /* Since mp_limb_t < mpfr_uexp_t, the shift counts are valid.
45              Use GMP_NUMB_BITS - 1 instead of GMP_NUMB_BITS to avoid a
46              bug in GCC. */
47           e = (e << (GMP_NUMB_BITS - 1)) + (randlimb () >> 1);
48           emax >>= GMP_NUMB_BITS - 1;
49         }
50     }
51   return (mpfr_exp_t) (e % (__gmpfr_emax - __gmpfr_emin)) + __gmpfr_emin;
52 }
53 
54 static void
check0(void)55 check0 (void)
56 {
57   mpz_t y;
58   mpfr_t x;
59   int inexact, r;
60   mpfr_exp_t e;
61 
62   /* Check for +0 */
63   mpfr_init (x);
64   mpz_init (y);
65   mpz_set_si (y, 0);
66   for (r = 0; r < MPFR_RND_MAX; r++)
67     {
68       e = randexp ();
69       inexact = mpfr_set_z_2exp (x, y, e, (mpfr_rnd_t) r);
70       if (!MPFR_IS_ZERO(x) || !MPFR_IS_POS(x) || inexact)
71         {
72           printf ("mpfr_set_z_2exp(x,0,e) failed for e=");
73           if (e < LONG_MIN)
74             printf ("(<LONG_MIN)");
75           else if (e > LONG_MAX)
76             printf ("(>LONG_MAX)");
77           else
78             printf ("%ld", (long) e);
79           printf (", rnd=%s\n", mpfr_print_rnd_mode ((mpfr_rnd_t) r));
80           exit (1);
81         }
82     }
83 
84   /* coverage test for huge exponent */
85   mpz_setbit (y, GMP_NUMB_BITS);
86   mpfr_clear_flags ();
87   inexact = mpfr_set_z_2exp (x, y, mpfr_get_emax_max(), MPFR_RNDN);
88   MPFR_ASSERTN(inexact > 0);
89   MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) > 0);
90   MPFR_ASSERTN(mpfr_overflow_p ());
91   mpfr_clear(x);
92   mpz_clear(y);
93 }
94 
95 /* FIXME: It'd be better to examine the actual data in an mpfr_t to see that
96    it's as expected.  Comparing mpfr_set_z with mpfr_cmp or against
97    mpfr_get_si is a rather indirect test of a low level routine.  */
98 
99 static void
check(long i,mpfr_rnd_t rnd,int reduced)100 check (long i, mpfr_rnd_t rnd, int reduced)
101 {
102   mpfr_t f1, f2, f3;
103   mpz_t z;
104   mpfr_exp_t e, old_emin, old_emax;
105   int inex;
106   mpfr_flags_t flags;
107 
108   old_emin = mpfr_get_emin ();
109   old_emax = mpfr_get_emax ();
110 
111   /* using CHAR_BIT * sizeof(long) bits of precision ensures that
112      mpfr_set_z_2exp is exact below */
113   mpfr_inits2 (CHAR_BIT * sizeof(long), f1, f2, f3, (mpfr_ptr) 0);
114   mpz_init (z);
115   mpz_set_ui (z, i);
116   /* the following loop ensures that no overflow occurs */
117   do
118     e = randexp ();
119   while (e > mpfr_get_emax () - CHAR_BIT * sizeof(long));
120 
121   mpfr_clear_flags ();
122   inex = mpfr_set_z_2exp (f1, z, e, rnd);
123   flags = __gmpfr_flags;
124 
125   if (inex != 0 || flags != 0 ||
126       (mpfr_div_2si (f2, f1, e, rnd), mpfr_get_si (f2, MPFR_RNDZ) != i))
127     {
128       printf ("Error in mpfr_set_z_2exp for i=%ld e=%" MPFR_EXP_FSPEC
129               "d rnd_mode=%d\n", i, (mpfr_eexp_t) e, rnd);
130       mpfr_set_si_2exp (f2, i, e, MPFR_RNDN);
131       printf ("expected "); mpfr_dump (f2);
132       printf ("with inex = %d and flags =", 0);
133       flags_out (0);
134       printf ("got      "); mpfr_dump (f1);
135       printf ("with inex = %d and flags =", inex);
136       flags_out (flags);
137       exit (1);
138     }
139 
140   if (reduced)
141     {
142       mpfr_exp_t ef, emin, emax;
143       int inex2, inex3;
144       mpfr_flags_t flags2, flags3;
145 
146       ef = i == 0 ? 0 : mpfr_get_exp (f1);
147       for (emin = ef - 2; emin <= ef + 2; emin++)
148         for (emax = emin; emax <= ef + 2; emax++)
149           {
150             inex3 = mpfr_set (f3, f1, rnd);
151             MPFR_ASSERTN (inex3 == 0);
152             mpfr_set_emin (emin);
153             mpfr_set_emax (emax);
154             mpfr_clear_flags ();
155             inex2 = mpfr_set_z_2exp (f2, z, e, rnd);
156             flags2 = __gmpfr_flags;
157             mpfr_clear_flags ();
158             inex3 = mpfr_check_range (f3, 0, rnd);
159             flags3 = __gmpfr_flags;
160             if (!(mpfr_equal_p (f2, f3) &&
161                   SAME_SIGN (inex2, inex3) &&
162                   flags2 == flags3))
163               {
164                 printf ("Error in mpfr_set_z_2exp for i=%ld e=%"
165                         MPFR_EXP_FSPEC "d rnd_mode=%d\nand emin=%"
166                         MPFR_EXP_FSPEC "d emax=%" MPFR_EXP_FSPEC
167                         "d\n", i, (mpfr_eexp_t) e, rnd,
168                         (mpfr_eexp_t) emin, (mpfr_eexp_t) emax);
169                 printf ("expected "); mpfr_dump (f3);
170                 printf ("with inex = %d and flags =", inex3);
171                 flags_out (flags3);
172                 printf ("got      "); mpfr_dump (f2);
173                 printf ("with inex = %d and flags =", inex2);
174                 flags_out (flags2);
175                 exit (1);
176               }
177           }
178       mpfr_set_emin (old_emin);
179       mpfr_set_emax (old_emax);
180     }
181 
182   mpfr_clears (f1, f2, f3, (mpfr_ptr) 0);
183   mpz_clear (z);
184 }
185 
186 static void
check_huge(void)187 check_huge (void)
188 {
189   if (getenv ("MPFR_CHECK_LARGEMEM") != NULL)
190     {
191       mpfr_t x;
192       mpz_t z;
193       long e;
194 
195       /* Increase tests_memory_limit to the maximum in order to avoid
196          an obvious failure due to insufficient memory. */
197       tests_memory_limit = (size_t) -1;  /* no memory limit */
198 
199       mpfr_init2 (x, 32);
200 
201       /* In r14140, with a 32-bit ABI (GCC's -m32):
202          - With UBsan (-fsanitize=undefined -fno-sanitize-recover),
203            this fails with:
204              set_z_2exp.c:71:26: runtime error: signed integer overflow:
205              67108864 * 32 cannot be represented in type 'long int'
206          - With -D_MPFR_EXP_FORMAT=4, this fails with:
207              Expected 0.10001000000000000000000000000000E5
208              Got      0
209       */
210       mpz_init_set_ui (z, 17);
211       e = 0x7ffffff0;
212       mpz_mul_2exp (z, z, e);
213       mpz_add_ui (z, z, 1);
214       mpfr_set_z_2exp (x, z, -e, MPFR_RNDN);
215       if (mpfr_cmp_ui0 (x, 17) != 0)
216         {
217           printf ("Error 1 in check_huge\n");
218           printf ("Expected 0.10001000000000000000000000000000E5\n");
219           printf ("Got      ");
220           mpfr_dump (x);
221           exit (1);
222         }
223       mpz_clear (z);
224 
225       mpz_init_set_ui (z, 17);
226       mpz_mul_2exp (z, z, 0xffffffb0);
227       mpz_add_ui (z, z, 1);
228       mpfr_set_z_2exp (x, z, -1, MPFR_RNDN);
229       if (! MPFR_IS_INF (x) || MPFR_IS_NEG (x))
230         {
231           printf ("Error 2 in check_huge\n");
232           printf ("Expected @Inf@\n");
233           printf ("Got      ");
234           mpfr_dump (x);
235           exit (1);
236         }
237       mpz_clear (z);
238 
239       mpfr_clear (x);
240     }
241 }
242 
243 int
main(int argc,char * argv[])244 main (int argc, char *argv[])
245 {
246   long j;
247 
248   tests_start_mpfr ();
249 
250   check (0, MPFR_RNDN, 0);
251   for (j = 0; j < 200000; j++)
252     check (randlimb () & LONG_MAX, RND_RAND (), j < 200);
253   check0 ();
254 
255   check_huge ();
256 
257   tests_end_mpfr ();
258 
259   return 0;
260 }
261