1 /* Test file for mpfr_ui_div.
2 
3 Copyright 2000-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 /* checks that y/x gives the right result with 53 bits of precision */
26 static void
check(unsigned long y,const char * xs,mpfr_rnd_t rnd_mode,const char * zs)27 check (unsigned long y, const char *xs, mpfr_rnd_t rnd_mode, const char *zs)
28 {
29   mpfr_t xx, zz;
30 
31   mpfr_inits2 (53, xx, zz, (mpfr_ptr) 0);
32   mpfr_set_str1 (xx, xs);
33   mpfr_ui_div (zz, y, xx, rnd_mode);
34   if (mpfr_cmp_str1(zz, zs))
35     {
36       printf ("expected quotient is %s, got ", zs);
37       mpfr_out_str (stdout, 10, 0, zz, MPFR_RNDN);
38       printf ("mpfr_ui_div failed for y=%lu x=%s with rnd_mode=%s\n",
39               y, xs, mpfr_print_rnd_mode (rnd_mode));
40       exit (1);
41     }
42   mpfr_clears (xx, zz, (mpfr_ptr) 0);
43 }
44 
45 static void
check_inexact(void)46 check_inexact (void)
47 {
48   mpfr_t x, y, z;
49   mpfr_prec_t px, py;
50   int inexact, cmp;
51   unsigned long int u;
52   int rnd;
53 
54   mpfr_init (x);
55   mpfr_init (y);
56   mpfr_init (z);
57 
58   for (px = MPFR_PREC_MIN; px < 300; px++)
59     {
60       mpfr_set_prec (x, px);
61       do
62         {
63           mpfr_urandomb (x, RANDS);
64         }
65       while (mpfr_cmp_ui (x, 0) == 0);
66       u = randlimb ();
67       for (py = MPFR_PREC_MIN; py < 300; py++)
68         {
69           mpfr_set_prec (y, py);
70           mpfr_set_prec (z, py + px);
71           for (rnd = 0; rnd < MPFR_RND_MAX; rnd++)
72             {
73               inexact = mpfr_ui_div (y, u, x, (mpfr_rnd_t) rnd);
74               if (mpfr_mul (z, y, x, (mpfr_rnd_t) rnd))
75                 {
76                   printf ("z <- y * x should be exact\n");
77                   exit (1);
78                 }
79               cmp = mpfr_cmp_ui (z, u);
80               if (rnd != MPFR_RNDF && ! SAME_SIGN (inexact, cmp))
81                 {
82                   printf ("Wrong inexact flag for u=%lu, rnd=%s\n",
83                           u, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
84                   printf ("expected %d, got %d\n", cmp, inexact);
85                   printf ("x = "); mpfr_dump (x);
86                   printf ("y = "); mpfr_dump (y);
87                   printf ("y*x = "); mpfr_dump (z);
88                   exit (1);
89                 }
90             }
91         }
92     }
93 
94   mpfr_clear (x);
95   mpfr_clear (y);
96   mpfr_clear (z);
97 }
98 
99 static void
check_special(void)100 check_special (void)
101 {
102   mpfr_t  d, q;
103 
104   mpfr_init2 (d, 100L);
105   mpfr_init2 (q, 100L);
106 
107   /* 1/+inf == +0 */
108   MPFR_SET_INF (d);
109   MPFR_SET_POS (d);
110   mpfr_clear_flags ();
111   MPFR_ASSERTN (mpfr_ui_div (q, 1L, d, MPFR_RNDZ) == 0); /* exact */
112   MPFR_ASSERTN (MPFR_IS_ZERO (q) && MPFR_IS_POS (q));
113   MPFR_ASSERTN (__gmpfr_flags == 0);
114 
115   /* 1/-inf == -0 */
116   MPFR_SET_INF (d);
117   MPFR_SET_NEG (d);
118   mpfr_clear_flags ();
119   MPFR_ASSERTN (mpfr_ui_div (q, 1L, d, MPFR_RNDZ) == 0); /* exact */
120   MPFR_ASSERTN (MPFR_IS_ZERO (q) && MPFR_IS_NEG (q));
121   MPFR_ASSERTN (__gmpfr_flags == 0);
122 
123   /* 1/nan == nan */
124   MPFR_SET_NAN (d);
125   mpfr_clear_flags ();
126   MPFR_ASSERTN (mpfr_ui_div (q, 1L, d, MPFR_RNDZ) == 0); /* exact */
127   MPFR_ASSERTN (mpfr_nan_p (q));
128   MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_NAN);
129 
130   /* 0/0 == nan */
131   mpfr_set_ui (d, 0L, MPFR_RNDN);
132   mpfr_clear_flags ();
133   MPFR_ASSERTN (mpfr_ui_div (q, 0L, d, MPFR_RNDZ) == 0); /* exact */
134   MPFR_ASSERTN (mpfr_nan_p (q));
135   MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_NAN);
136 
137   /* 1/+0 = +inf */
138   mpfr_set_ui (d, 0L, MPFR_RNDN);
139   mpfr_clear_flags ();
140   MPFR_ASSERTN (mpfr_ui_div (q, 1L, d, MPFR_RNDZ) == 0); /* exact */
141   MPFR_ASSERTN (mpfr_inf_p (q) && mpfr_sgn (q) > 0);
142   MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_DIVBY0);
143 
144   /* 1/-0 = -inf */
145   mpfr_set_ui (d, 0L, MPFR_RNDN);
146   mpfr_neg (d, d, MPFR_RNDN);
147   mpfr_clear_flags ();
148   MPFR_ASSERTN (mpfr_ui_div (q, 1L, d, MPFR_RNDZ) == 0); /* exact */
149   MPFR_ASSERTN (mpfr_inf_p (q) && mpfr_sgn (q) < 0);
150   MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_DIVBY0);
151 
152   /* 0/1 = +0 */
153   mpfr_set_ui (d, 1L, MPFR_RNDN);
154   mpfr_clear_flags ();
155   MPFR_ASSERTN (mpfr_ui_div (q, 0L, d, MPFR_RNDZ) == 0); /* exact */
156   MPFR_ASSERTN (MPFR_IS_ZERO (q) && MPFR_IS_POS (q));
157   MPFR_ASSERTN (__gmpfr_flags == 0);
158 
159   /* 0/-1 = -0 */
160   mpfr_set_si (d, -1, MPFR_RNDN);
161   mpfr_clear_flags ();
162   MPFR_ASSERTN (mpfr_ui_div (q, 0L, d, MPFR_RNDZ) == 0); /* exact */
163   MPFR_ASSERTN (MPFR_IS_ZERO (q) && MPFR_IS_NEG (q));
164   MPFR_ASSERTN (__gmpfr_flags == 0);
165 
166   mpfr_clear (d);
167   mpfr_clear (q);
168 }
169 
170 static int
mpfr_inv(mpfr_ptr y,mpfr_srcptr x,mpfr_rnd_t r)171 mpfr_inv (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t r)
172 {
173   return mpfr_ui_div (y, 1, x, r);
174 }
175 
176 static void
check_overflow(void)177 check_overflow (void)
178 {
179   mpfr_exp_t emin, emax;
180   mpfr_t x, y1, y2;
181   int inex1, inex2, rnd_mode;
182   mpfr_flags_t flags1, flags2;
183 
184   emin = mpfr_get_emin ();
185   emax = mpfr_get_emax ();
186   set_emin (MPFR_EMIN_MIN);
187   set_emax (MPFR_EMAX_MAX);
188 
189   mpfr_inits2 (32, x, y1, y2, (mpfr_ptr) 0);
190   mpfr_setmin (x, MPFR_EMIN_MIN);
191   RND_LOOP (rnd_mode)
192     {
193       inex1 = mpfr_overflow (y1, (mpfr_rnd_t) rnd_mode, 1);
194       flags1 = MPFR_FLAGS_OVERFLOW | MPFR_FLAGS_INEXACT;
195       mpfr_clear_flags ();
196       inex2 = mpfr_ui_div (y2, 1, x, (mpfr_rnd_t) rnd_mode);
197       flags2 = __gmpfr_flags;
198       if (!(mpfr_equal_p (y1, y2) &&
199             SAME_SIGN (inex1, inex2) &&
200             flags1 == flags2))
201         {
202           printf ("Error in check_overflow for %s\n",
203                   mpfr_print_rnd_mode ((mpfr_rnd_t) rnd_mode));
204           printf ("Expected ");
205           mpfr_dump (y1);
206           printf ("  with inex = %d, flags =", inex1);
207           flags_out (flags1);
208           printf ("Got      ");
209           mpfr_dump (y2);
210           printf ("  with inex = %d, flags =", inex2);
211           flags_out (flags2);
212           exit (1);
213         }
214     }
215   mpfr_clears (x, y1, y2, (mpfr_ptr) 0);
216 
217   set_emin (emin);
218   set_emax (emax);
219 }
220 
221 #define TEST_FUNCTION mpfr_ui_div
222 #define ULONG_ARG1
223 #define RAND_FUNCTION(x) mpfr_random2(x, MPFR_LIMB_SIZE (x), 1, RANDS)
224 #include "tgeneric.c"
225 
226 int
main(int argc,char * argv[])227 main (int argc, char *argv[])
228 {
229   tests_start_mpfr ();
230 
231   check_special ();
232   check_inexact ();
233   check(948002822, "1.22191250737771397120e+20", MPFR_RNDN,
234         "7.758352715731357946e-12");
235   check(1976245324, "1.25296395864546893357e+232", MPFR_RNDZ,
236         "1.5772563211925444801e-223");
237   check(740454110, "2.11496253355831863313e+183", MPFR_RNDZ,
238         "3.5010270784996976041e-175");
239   check(1690540942, "1.28278599852446657468e-276", MPFR_RNDU,
240         "1.3178666932321966062e285");
241   check(1476599377, "-2.14191393656148625995e+305", MPFR_RNDD,
242         "-6.8938315017943889615e-297");
243   check_overflow ();
244 
245   test_generic (MPFR_PREC_MIN, 1000, 100);
246 
247   /* inv is for 1/x */
248   data_check ("data/inv", mpfr_inv, "mpfr_ui_div(1,x)");
249 
250   tests_end_mpfr ();
251   return 0;
252 }
253