xref: /netbsd-src/external/lgpl3/gmp/dist/mini-gmp/tests/t-mpq_muldiv_2exp.c (revision 2718af68c3efc72c9769069b5c7f9ed36f6b9def)
1 /*
2 
3 Copyright 2012, 2013, 2018 Free Software Foundation, Inc.
4 
5 This file is part of the GNU MP Library test suite.
6 
7 The GNU MP Library test suite is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 3 of the License,
10 or (at your option) any later version.
11 
12 The GNU MP Library test suite is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
15 Public License for more details.
16 
17 You should have received a copy of the GNU General Public License along with
18 the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
19 
20 #include <assert.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 
24 #include "testutils.h"
25 #include "../mini-mpq.h"
26 
27 #define MAXBITS 300
28 #define COUNT 10000
29 
30 static void
31 _mpq_set_zz (mpq_t q, mpz_t n, mpz_t d)
32 {
33   if (mpz_fits_ulong_p (d) && mpz_fits_slong_p (n))
34     {
35       mpq_set_si (q, mpz_get_si (n), mpz_get_ui (d));
36     }
37   else if (mpz_fits_ulong_p (d) && mpz_fits_ulong_p (n))
38     {
39       mpq_set_ui (q, mpz_get_ui (n), mpz_get_ui (d));
40     }
41   else
42     {
43       mpq_set_num (q, n);
44       mpq_set_den (q, d);
45     }
46   mpq_canonicalize (q);
47 }
48 
49 void
50 testmain (int argc, char **argv)
51 {
52   unsigned i;
53   mpz_t a, b, t;
54   mpq_t aq, rq, tq;
55   mp_bitcnt_t e;
56   long int e2, t1, t2;
57 
58   mpz_init (a);
59   mpz_init (b);
60   mpz_init (t);
61   mpq_init (aq);
62   mpq_init (rq);
63   mpq_init (tq);
64 
65   for (i = 0; i < COUNT; i++)
66     {
67       do {
68 	mini_random_bit_op (OP_COMBIT, MAXBITS, a, &e, b);
69       } while (mpz_sgn (a) == 0 || mpz_sgn (b) == 0);
70 
71       _mpq_set_zz (aq, a, b);
72       e2 = mpz_scan1 (a, 0);
73       e2-= mpz_scan1 (b, 0);
74 
75       mpq_mul_2exp (rq, aq, e);
76       t1 = mpz_scan1 (mpq_numref (rq), 0);
77       t2 = mpz_scan1 (mpq_denref (rq), 0);
78       mpq_neg (tq, rq);
79       mpq_div (tq, aq, tq);
80       mpq_get_den (t, tq);
81 
82       if (e2 + e != t1 - t2 || (t2 != 0 && t1 != 0) || mpz_scan1 (t, 0) != e
83 	  || mpz_sizeinbase (t, 2) - 1 != e || mpz_cmp_si (mpq_numref (tq), -1) != 0)
84 	{
85 	  fprintf (stderr, "mpq_mul_2exp failed: %lu\n", e);
86 	  dump ("na", a);
87 	  dump ("da", b);
88 	  dump ("nr", mpq_numref (rq));
89 	  dump ("dr", mpq_denref (rq));
90 	  abort ();
91 	}
92 
93       mpq_div_2exp (rq, aq, e);
94       t1 = mpz_scan1 (mpq_numref (rq), 0);
95       t2 = mpz_scan1 (mpq_denref (rq), 0);
96       mpq_div (aq, aq, rq);
97       mpq_get_num (t, aq);
98 
99       if (e2 != t1 - t2 + e || (t2 != 0 && t1 != 0) || mpz_scan1 (t, 0) != e
100 	  || mpz_sizeinbase (t, 2) - 1 != e || mpz_cmp_ui (mpq_denref (aq), 1) != 0)
101 	{
102 	  fprintf (stderr, "mpq_div_2exp failed: %lu\n", e);
103 	  fprintf (stderr, "%li %li %lu %lu\n", e2, t2, mpz_scan1 (t, 0), (unsigned long) mpz_sizeinbase (t, 2));
104 	  dump ("na", a);
105 	  dump ("da", b);
106 	  dump ("nr", mpq_numref (rq));
107 	  dump ("dr", mpq_denref (rq));
108 	  abort ();
109 	}
110 
111       mpq_set_ui (aq, 0, 1);
112       mpq_set_ui (rq, 6, 7);
113       mpq_set (tq, aq);
114       mpq_div_2exp (rq, aq, e);
115 
116       if (!mpq_equal (tq, rq))
117 	{
118 	  fprintf (stderr, "mpq_div_2exp failed on zero: %lu\n", e);
119 	  abort ();
120 	}
121 
122       mpq_set_ui (rq, 7, 6);
123       mpq_mul_2exp (rq, aq, e);
124 
125       if (!mpq_equal (rq, tq))
126 	{
127 	  fprintf (stderr, "mpq_mul_2exp failed on zero: %lu\n", e);
128 	  abort ();
129 	}
130     }
131 
132   mpz_clear (a);
133   mpz_clear (b);
134   mpz_clear (t);
135   mpq_clear (aq);
136   mpq_clear (rq);
137   mpq_clear (tq);
138 }
139