xref: /netbsd-src/external/lgpl3/gmp/dist/tests/mpz/t-cong_2exp.c (revision 782713e6c126f1866c6d9cfdee4ceb49483b5828)
1 /* test mpz_congruent_2exp_p */
2 
3 /*
4 Copyright 2001, 2013 Free Software Foundation, Inc.
5 
6 This file is part of the GNU MP Library test suite.
7 
8 The GNU MP Library test suite is free software; you can redistribute it
9 and/or modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 3 of the License,
11 or (at your option) any later version.
12 
13 The GNU MP Library test suite is distributed in the hope that it will be
14 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
16 Public License for more details.
17 
18 You should have received a copy of the GNU General Public License along with
19 the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
20 
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include "gmp-impl.h"
24 #include "tests.h"
25 
26 
27 void
28 check_one (mpz_srcptr a, mpz_srcptr c, unsigned long d, int want)
29 {
30   mpz_t  diff, d2exp;
31   int    got;
32   int    swap;
33 
34   for (swap = 0; swap <= 1; swap++)
35     {
36       got = (mpz_congruent_2exp_p (a, c, d) != 0);
37       if (want != got)
38         {
39           mpz_init (diff);
40           mpz_init (d2exp);
41 
42           mpz_sub (diff, a, c);
43           mpz_set_ui (d2exp, 1L);
44           mpz_mul_2exp (d2exp, d2exp, d);
45 
46           printf ("mpz_congruent_2exp_p wrong\n");
47           printf ("   expected %d got %d\n", want, got);
48           mpz_trace ("   a", a);
49           mpz_trace ("   c", c);
50           mpz_trace (" a-c", diff);
51           mpz_trace (" 2^d", d2exp);
52           printf    ("   d=%lu\n", d);
53 
54           mp_trace_base = -16;
55           mpz_trace ("   a", a);
56           mpz_trace ("   c", c);
57           mpz_trace (" a-c", diff);
58           mpz_trace (" 2^d", d2exp);
59           printf    ("   d=0x%lX\n", d);
60           abort ();
61         }
62 
63       MPZ_SRCPTR_SWAP (a, c);
64     }
65 }
66 
67 
68 void
69 check_data (void)
70 {
71   static const struct {
72     const char     *a;
73     const char     *c;
74     unsigned long  d;
75     int            want;
76 
77   } data[] = {
78 
79     /* anything is congruent mod 1 */
80     { "0", "0", 0, 1 },
81     { "1", "0", 0, 1 },
82     { "0", "1", 0, 1 },
83     { "123", "-456", 0, 1 },
84     { "0x123456789123456789", "0x987654321987654321", 0, 1 },
85     { "0xfffffffffffffffffffffffffffffff7", "-0x9", 129, 0 },
86     { "0xfffffffffffffffffffffffffffffff6", "-0xa", 128, 1 },
87 
88   };
89 
90   mpz_t   a, c;
91   int     i;
92 
93   mpz_init (a);
94   mpz_init (c);
95 
96   for (i = 0; i < numberof (data); i++)
97     {
98       mpz_set_str_or_abort (a, data[i].a, 0);
99       mpz_set_str_or_abort (c, data[i].c, 0);
100       check_one (a, c, data[i].d, data[i].want);
101     }
102 
103   mpz_clear (a);
104   mpz_clear (c);
105 }
106 
107 
108 void
109 check_random (int reps)
110 {
111   gmp_randstate_ptr rands = RANDS;
112   unsigned long  d;
113   mpz_t  a, c, ra, rc;
114   int    i;
115 
116   mpz_init (a);
117   mpz_init (c);
118   mpz_init (ra);
119   mpz_init (rc);
120 
121   for (i = 0; i < reps; i++)
122     {
123       mpz_errandomb (a, rands, 8*GMP_LIMB_BITS);
124       mpz_errandomb (c, rands, 8*GMP_LIMB_BITS);
125       d = urandom() % (8*GMP_LIMB_BITS);
126 
127       mpz_mul_2exp (a, a, urandom() % (2*GMP_LIMB_BITS));
128       mpz_mul_2exp (c, c, urandom() % (2*GMP_LIMB_BITS));
129 
130       mpz_negrandom (a, rands);
131       mpz_negrandom (c, rands);
132 
133       mpz_fdiv_r_2exp (ra, a, d);
134       mpz_fdiv_r_2exp (rc, c, d);
135 
136       mpz_sub (ra, ra, rc);
137       if (mpz_cmp_ui (ra, 0) != 0)
138 	{
139 	  check_one (a, c, d, 0);
140 	  mpz_sub (a, a, ra);
141 	}
142       check_one (a, c, d, 1);
143       if (d != 0)
144 	{
145 	  mpz_combit (a, urandom() % d);
146 	  check_one (a, c, d, 0);
147 	}
148     }
149 
150   mpz_clear (a);
151   mpz_clear (c);
152   mpz_clear (ra);
153   mpz_clear (rc);
154 }
155 
156 void
157 check_random_bits (int reps)
158 {
159   mp_bitcnt_t ea, ec, en, d;
160   mp_bitcnt_t m = 10 * GMP_LIMB_BITS;
161   mpz_t  a, c;
162   int    i;
163 
164   mpz_init2 (a, m + 1);
165   mpz_init2 (c, m);
166 
167   for (i = 0; i < reps; i++)
168     {
169       d  = urandom() % m;
170       ea = urandom() % m;
171       ec = urandom() % m;
172       en = urandom() % m;
173 
174       mpz_set_ui (c, 0);
175       mpz_setbit (c, en);
176 
177       mpz_set_ui (a, 0);
178       mpz_setbit (a, ec);
179       mpz_sub (c , a, c);
180 
181       mpz_set_ui (a, 0);
182       mpz_setbit (a, ea);
183       mpz_add (a , a, c);
184 
185       check_one (a, c, d, ea >= d);
186     }
187 
188   mpz_clear (a);
189   mpz_clear (c);
190 }
191 
192 
193 int
194 main (int argc, char *argv[])
195 {
196   int    reps = 5000;
197 
198   tests_start ();
199   TESTS_REPS (reps, argv, argc);
200 
201   check_data ();
202   check_random (reps);
203   check_random_bits (reps);
204 
205   tests_end ();
206   exit (0);
207 }
208