xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/tget_z.c (revision ba125506a622fe649968631a56eba5d42ff57863)
1 /* Test file for mpz_set_fr / mpfr_get_z / mpfr_get_z_2exp.
2 
3 Copyright 2004, 2006-2023 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 static void
check_diff(void)26 check_diff (void)
27 {
28   int inex;
29   mpfr_t x;
30   mpz_t  z;
31   mpfr_exp_t emin;
32 
33   mpz_init   (z);
34   mpfr_init2 (x, 2);
35 
36   mpfr_set_ui (x, 2047, MPFR_RNDU);
37   mpz_set_fr (z, x, MPFR_RNDN);
38   if (mpz_cmp_ui (z, 2048) != 0)
39     {
40       printf ("get_z RU 2048 failed\n");
41       exit (1);
42     }
43 
44   mpfr_set_prec (x, 6);
45   mpfr_set_str (x, "17.5", 10, MPFR_RNDN);
46   inex = mpfr_get_z (z, x, MPFR_RNDN);
47   if (inex <= 0 || mpz_cmp_ui (z, 18) != 0)
48     {
49       printf ("get_z RN 17.5 failed\n");
50       exit (1);
51     }
52 
53   /* save default emin */
54   emin = mpfr_get_emin ();;
55 
56   set_emin (17);
57   mpfr_set_ui (x, 0, MPFR_RNDN);
58   inex = mpfr_get_z (z, x, MPFR_RNDN);
59   if (inex != 0 || mpz_cmp_ui (z, 0) != 0)
60     {
61       printf ("get_z 0 failed\n");
62       exit (1);
63     }
64 
65   /* restore default emin */
66   set_emin (emin);
67 
68   mpfr_clear (x);
69   mpz_clear  (z);
70 }
71 
72 static void
check_one(mpz_ptr z)73 check_one (mpz_ptr z)
74 {
75   mpfr_exp_t emin, emax;
76   int    inex;
77   int    sh, neg;
78   mpfr_t f;
79   mpz_t  got, ex, t;
80 
81   emin = mpfr_get_emin ();
82   emax = mpfr_get_emax ();
83 
84   mpfr_init2 (f, MAX (mpz_sizeinbase (z, 2), MPFR_PREC_MIN));
85   mpz_init (got);
86   mpz_init (ex);
87   mpz_init (t);
88 
89   for (sh = -2*GMP_NUMB_BITS ; sh < 2*GMP_NUMB_BITS ; sh++)
90     {
91       inex = mpfr_set_z (f, z, MPFR_RNDN);  /* exact */
92       MPFR_ASSERTN (inex == 0);
93 
94       inex = sh < 0 ?
95         mpfr_div_2ui (f, f, -sh, MPFR_RNDN) :
96         mpfr_mul_2ui (f, f, sh, MPFR_RNDN);
97       MPFR_ASSERTN (inex == 0);
98 
99       for (neg = 0; neg <= 1; neg++)
100         {
101           int rnd;
102 
103           /* Test (-1)^neg * z * 2^sh */
104 
105           RND_LOOP_NO_RNDF (rnd)
106             {
107               int ex_inex, same;
108               int d, fi, e;
109               mpfr_flags_t flags[3] = { 0, MPFR_FLAGS_ALL ^ MPFR_FLAGS_ERANGE,
110                                         MPFR_FLAGS_ALL }, ex_flags, gt_flags;
111 
112               if (neg)
113                 mpz_neg (ex, z);
114               else
115                 mpz_set (ex, z);
116 
117               if (sh < 0)
118                 switch (rnd)
119                   {
120                   case MPFR_RNDN:
121                     mpz_set_si (t, neg ? -1 : 1);
122                     mpz_mul_2exp (t, t, -sh - 1);
123                     mpz_add (ex, ex, t);
124                     /* d = mpz_divisible_2exp_p (ex, -sh); */
125                     d = mpz_scan1 (ex, 0) >= -sh;
126                     mpz_tdiv_q_2exp (ex, ex, -sh);
127                     if (d && mpz_tstbit (ex, 0) != 0)  /* even rounding */
128                       {
129                         if (neg)
130                           mpz_add_ui (ex, ex, 1);
131                         else
132                           mpz_sub_ui (ex, ex, 1);
133                       }
134                     break;
135                   case MPFR_RNDZ:
136                     mpz_tdiv_q_2exp (ex, ex, -sh);
137                     break;
138                   case MPFR_RNDU:
139                     mpz_cdiv_q_2exp (ex, ex, -sh);
140                     break;
141                   case MPFR_RNDD:
142                     mpz_fdiv_q_2exp (ex, ex, -sh);
143                     break;
144                   case MPFR_RNDA:
145                     if (neg)
146                       mpz_fdiv_q_2exp (ex, ex, -sh);
147                     else
148                       mpz_cdiv_q_2exp (ex, ex, -sh);
149                     break;
150                   default:
151                     MPFR_ASSERTN (0);
152                   }
153               else
154                 mpz_mul_2exp (ex, ex, sh);
155 
156               ex_inex = - mpfr_cmp_z (f, ex);
157               ex_inex = VSIGN (ex_inex);
158 
159               for (fi = 0; fi < numberof (flags); fi++)
160                 for (e = 0; e < 2; e++)
161                   {
162                     if (e)
163                       {
164                         mpfr_exp_t ef;
165 
166                         if (MPFR_IS_ZERO (f))
167                           break;
168                         ef = MPFR_GET_EXP (f);
169                         set_emin (ef);
170                         set_emax (ef);
171                       }
172                     ex_flags = __gmpfr_flags = flags[fi];
173                     if (ex_inex != 0)
174                       ex_flags |= MPFR_FLAGS_INEXACT;
175                     inex = mpfr_get_z (got, f, (mpfr_rnd_t) rnd);
176                     inex = VSIGN (inex);
177                     gt_flags = __gmpfr_flags;
178                     set_emin (emin);
179                     set_emax (emax);
180                     same = SAME_SIGN (inex, ex_inex);
181 
182                     if (mpz_cmp (got, ex) != 0 ||
183                         !same || gt_flags != ex_flags)
184                       {
185                         printf ("Error in check_one for sh=%d, fi=%d, %s%s\n",
186                                 sh, fi,
187                                 mpfr_print_rnd_mode ((mpfr_rnd_t) rnd),
188                                 e ? ", reduced exponent range" : "");
189                         printf ("     f = "); mpfr_dump (f);
190                         printf ("expected "); mpz_out_str (stdout, 10, ex);
191                         printf ("\n     got "); mpz_out_str (stdout, 10, got);
192                         printf ("\nExpected inex ~ %d, got %d (%s)\n",
193                                 ex_inex, inex, same ? "OK" : "wrong");
194                         printf ("Flags:\n");
195                         printf ("      in"); flags_out (flags[fi]);
196                         printf ("expected"); flags_out (ex_flags);
197                         printf ("     got"); flags_out (gt_flags);
198                         exit (1);
199                       }
200                   }
201             }
202 
203           mpfr_neg (f, f, MPFR_RNDN);
204         }
205     }
206 
207   mpfr_clear (f);
208   mpz_clear (got);
209   mpz_clear (ex);
210   mpz_clear (t);
211 }
212 
213 static void
check(void)214 check (void)
215 {
216   mpz_t  z;
217 
218   mpz_init (z);
219 
220   mpz_set_ui (z, 0L);
221   check_one (z);
222 
223   mpz_set_si (z, 17L);
224   check_one (z);
225 
226   mpz_set_si (z, 123L);
227   check_one (z);
228 
229   mpz_rrandomb (z, RANDS, 2*GMP_NUMB_BITS);
230   check_one (z);
231 
232   mpz_rrandomb (z, RANDS, 5*GMP_NUMB_BITS);
233   check_one (z);
234 
235   mpz_clear (z);
236 }
237 
238 static void
special(void)239 special (void)
240 {
241   int inex;
242   mpfr_t x;
243   mpz_t z;
244   int i, fi;
245   int rnd;
246   mpfr_exp_t e;
247   mpfr_flags_t flags[3] = { 0, MPFR_FLAGS_ALL ^ MPFR_FLAGS_ERANGE,
248                             MPFR_FLAGS_ALL }, ex_flags, gt_flags;
249 
250   mpfr_init2 (x, 2);
251   mpz_init (z);
252 
253   RND_LOOP (rnd)
254     for (i = -1; i <= 1; i++)
255       for (fi = 0; fi < numberof (flags); fi++)
256         {
257           ex_flags = flags[fi] | MPFR_FLAGS_ERANGE;
258           if (i != 0)
259             mpfr_set_nan (x);
260           else
261             mpfr_set_inf (x, i);
262           __gmpfr_flags = flags[fi];
263           inex = mpfr_get_z (z, x, (mpfr_rnd_t) rnd);
264           gt_flags = __gmpfr_flags;
265           if (gt_flags != ex_flags || inex != 0 || mpz_cmp_ui (z, 0) != 0)
266             {
267               printf ("special() failed on mpfr_get_z"
268                       " for %s, i = %d, fi = %d\n",
269                       mpfr_print_rnd_mode ((mpfr_rnd_t) rnd), i, fi);
270               printf ("Expected z = 0, inex = 0,");
271               flags_out (ex_flags);
272               printf ("Got      z = ");
273               mpz_out_str (stdout, 10, z);
274               printf (", inex = %d,", inex);
275               flags_out (gt_flags);
276               exit (1);
277             }
278           __gmpfr_flags = flags[fi];
279           e = mpfr_get_z_2exp (z, x);
280           gt_flags = __gmpfr_flags;
281           if (gt_flags != ex_flags || e != __gmpfr_emin ||
282               mpz_cmp_ui (z, 0) != 0)
283             {
284               printf ("special() failed on mpfr_get_z_2exp"
285                       " for %s, i = %d, fi = %d\n",
286                       mpfr_print_rnd_mode ((mpfr_rnd_t) rnd), i, fi);
287               printf ("Expected z = 0, e = %" MPFR_EXP_FSPEC "d,",
288                       (mpfr_eexp_t) __gmpfr_emin);
289               flags_out (ex_flags);
290               printf ("Got      z = ");
291               mpz_out_str (stdout, 10, z);
292               printf (", e = %" MPFR_EXP_FSPEC "d,", (mpfr_eexp_t) e);
293               flags_out (gt_flags);
294               exit (1);
295             }
296         }
297 
298   mpfr_clear (x);
299   mpz_clear (z);
300 }
301 
302 int
main(void)303 main (void)
304 {
305   tests_start_mpfr ();
306 
307   check ();
308   check_diff ();
309   special ();
310 
311   tests_end_mpfr ();
312   return 0;
313 }
314