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 }