xref: /netbsd-src/external/lgpl3/gmp/dist/tests/mpq/t-md_2exp.c (revision 0a3071956a3a9fdebdbf7f338cf2d439b45fc728)
1 /* Test mpq_mul_2exp and mpq_div_2exp.
2 
3 Copyright 2000, 2001 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 <stdio.h>
21 #include <stdlib.h>
22 #include "gmp-impl.h"
23 #include "tests.h"
24 
25 
26 struct pair_t {
27   const char     *num;
28   const char     *den;
29 };
30 
31 void
32 check_random ()
33 {
34   gmp_randstate_ptr rands;
35   mpz_t bs;
36   unsigned long arg_size, size_range;
37   mpq_t q, r;
38   int i;
39   mp_bitcnt_t shift;
40   int reps = 10000;
41 
42   rands = RANDS;
43 
44   mpz_init (bs);
45   mpq_init (q);
46   mpq_init (r);
47 
48   for (i = 0; i < reps; i++)
49     {
50       mpz_urandomb (bs, rands, 32);
51       size_range = mpz_get_ui (bs) % 11 + 2; /* 0..4096 bit operands */
52 
53       mpz_urandomb (bs, rands, size_range);
54       arg_size = mpz_get_ui (bs);
55       mpz_rrandomb (mpq_numref (q), rands, arg_size);
56       do
57 	{
58 	  mpz_urandomb (bs, rands, size_range);
59 	  arg_size = mpz_get_ui (bs);
60 	  mpz_rrandomb (mpq_denref (q), rands, arg_size);
61 	}
62       while (mpz_sgn (mpq_denref (q)) == 0);
63 
64       /* We now have a random rational in q, albeit an unnormalised one.  The
65 	 lack of normalisation should not matter here, so let's save the time a
66 	 gcd would require.  */
67 
68       mpz_urandomb (bs, rands, 32);
69       shift = mpz_get_ui (bs) % 4096;
70 
71       mpq_mul_2exp (r, q, shift);
72 
73       if (mpq_cmp (r, q) < 0)
74 	{
75 	  printf ("mpq_mul_2exp wrong on random\n");
76 	  abort ();
77 	}
78 
79       mpq_div_2exp (r, r, shift);
80 
81       if (mpq_cmp (r, q) != 0)
82 	{
83 	  printf ("mpq_mul_2exp or mpq_div_2exp wrong on random\n");
84 	  abort ();
85 	}
86     }
87   mpq_clear (q);
88   mpq_clear (r);
89   mpz_clear (bs);
90 }
91 
92 int
93 main (int argc, char **argv)
94 {
95   static const struct {
96     struct pair_t  left;
97     unsigned long  n;
98     struct pair_t  right;
99 
100   } data[] = {
101     { {"0","1"}, 0, {"0","1"} },
102     { {"0","1"}, 1, {"0","1"} },
103     { {"0","1"}, 2, {"0","1"} },
104 
105     { {"1","1"}, 0, {"1","1"} },
106     { {"1","1"}, 1, {"2","1"} },
107     { {"1","1"}, 2, {"4","1"} },
108     { {"1","1"}, 3, {"8","1"} },
109 
110     { {"1","1"}, 31, {"0x80000000","1"} },
111     { {"1","1"}, 32, {"0x100000000","1"} },
112     { {"1","1"}, 33, {"0x200000000","1"} },
113     { {"1","1"}, 63, {"0x8000000000000000","1"} },
114     { {"1","1"}, 64, {"0x10000000000000000","1"} },
115     { {"1","1"}, 65, {"0x20000000000000000","1"} },
116     { {"1","1"}, 95, {"0x800000000000000000000000","1"} },
117     { {"1","1"}, 96, {"0x1000000000000000000000000","1"} },
118     { {"1","1"}, 97, {"0x2000000000000000000000000","1"} },
119     { {"1","1"}, 127, {"0x80000000000000000000000000000000","1"} },
120     { {"1","1"}, 128, {"0x100000000000000000000000000000000","1"} },
121     { {"1","1"}, 129, {"0x200000000000000000000000000000000","1"} },
122 
123     { {"1","2"}, 31, {"0x40000000","1"} },
124     { {"1","2"}, 32, {"0x80000000","1"} },
125     { {"1","2"}, 33, {"0x100000000","1"} },
126     { {"1","2"}, 63, {"0x4000000000000000","1"} },
127     { {"1","2"}, 64, {"0x8000000000000000","1"} },
128     { {"1","2"}, 65, {"0x10000000000000000","1"} },
129     { {"1","2"}, 95, {"0x400000000000000000000000","1"} },
130     { {"1","2"}, 96, {"0x800000000000000000000000","1"} },
131     { {"1","2"}, 97, {"0x1000000000000000000000000","1"} },
132     { {"1","2"}, 127, {"0x40000000000000000000000000000000","1"} },
133     { {"1","2"}, 128, {"0x80000000000000000000000000000000","1"} },
134     { {"1","2"}, 129, {"0x100000000000000000000000000000000","1"} },
135 
136     { {"1","0x80000000"}, 30, {"1","2"} },
137     { {"1","0x80000000"}, 31, {"1","1"} },
138     { {"1","0x80000000"}, 32, {"2","1"} },
139     { {"1","0x80000000"}, 33, {"4","1"} },
140     { {"1","0x80000000"}, 62, {"0x80000000","1"} },
141     { {"1","0x80000000"}, 63, {"0x100000000","1"} },
142     { {"1","0x80000000"}, 64, {"0x200000000","1"} },
143     { {"1","0x80000000"}, 94, {"0x8000000000000000","1"} },
144     { {"1","0x80000000"}, 95, {"0x10000000000000000","1"} },
145     { {"1","0x80000000"}, 96, {"0x20000000000000000","1"} },
146     { {"1","0x80000000"}, 126, {"0x800000000000000000000000","1"} },
147     { {"1","0x80000000"}, 127, {"0x1000000000000000000000000","1"} },
148     { {"1","0x80000000"}, 128, {"0x2000000000000000000000000","1"} },
149 
150     { {"1","0x100000000"}, 1, {"1","0x80000000"} },
151     { {"1","0x100000000"}, 2, {"1","0x40000000"} },
152     { {"1","0x100000000"}, 3, {"1","0x20000000"} },
153 
154     { {"1","0x10000000000000000"}, 1, {"1","0x8000000000000000"} },
155     { {"1","0x10000000000000000"}, 2, {"1","0x4000000000000000"} },
156     { {"1","0x10000000000000000"}, 3, {"1","0x2000000000000000"} },
157   };
158 
159   void (*fun) (mpq_ptr, mpq_srcptr, unsigned long);
160   const struct pair_t  *p_start, *p_want;
161   const char  *name;
162   mpq_t    sep, got, want;
163   mpq_ptr  q;
164   int      i, muldiv, sign, overlap;
165 
166   tests_start ();
167 
168   mpq_init (sep);
169   mpq_init (got);
170   mpq_init (want);
171 
172   for (i = 0; i < numberof (data); i++)
173     {
174       for (muldiv = 0; muldiv < 2; muldiv++)
175         {
176           if (muldiv == 0)
177             {
178               fun = mpq_mul_2exp;
179               name = "mpq_mul_2exp";
180               p_start = &data[i].left;
181               p_want = &data[i].right;
182             }
183           else
184             {
185               fun = mpq_div_2exp;
186               name = "mpq_div_2exp";
187               p_start = &data[i].right;
188               p_want = &data[i].left;
189             }
190 
191           for (sign = 0; sign <= 1; sign++)
192             {
193               mpz_set_str_or_abort (mpq_numref(want), p_want->num, 0);
194               mpz_set_str_or_abort (mpq_denref(want), p_want->den, 0);
195               if (sign)
196                 mpq_neg (want, want);
197 
198               for (overlap = 0; overlap <= 1; overlap++)
199                 {
200                   q = overlap ? got : sep;
201 
202                   /* initial garbage in "got" */
203                   mpq_set_ui (got, 123L, 456L);
204 
205                   mpz_set_str_or_abort (mpq_numref(q), p_start->num, 0);
206                   mpz_set_str_or_abort (mpq_denref(q), p_start->den, 0);
207                   if (sign)
208                     mpq_neg (q, q);
209 
210                   (*fun) (got, q, data[i].n);
211                   MPQ_CHECK_FORMAT (got);
212 
213                   if (! mpq_equal (got, want))
214                     {
215                       printf ("%s wrong at data[%d], sign %d, overlap %d\n",
216                               name, i, sign, overlap);
217                       printf ("   num \"%s\"\n", p_start->num);
218                       printf ("   den \"%s\"\n", p_start->den);
219                       printf ("   n   %lu\n", data[i].n);
220 
221                       printf ("   got  ");
222                       mpq_out_str (stdout, 16, got);
223                       printf (" (hex)\n");
224 
225                       printf ("   want ");
226                       mpq_out_str (stdout, 16, want);
227                       printf (" (hex)\n");
228 
229                       abort ();
230                     }
231                 }
232             }
233         }
234     }
235 
236   check_random ();
237 
238   mpq_clear (sep);
239   mpq_clear (got);
240   mpq_clear (want);
241 
242   tests_end ();
243   exit (0);
244 }
245