t-bit.c revision 1.1 1 1.1 mrg /* Test mpz_setbit, mpz_clrbit, mpz_tstbit.
2 1.1 mrg
3 1.1 mrg Copyright 1997, 2000-2003, 2012, 2013 Free Software Foundation, Inc.
4 1.1 mrg
5 1.1 mrg This file is part of the GNU MP Library test suite.
6 1.1 mrg
7 1.1 mrg The GNU MP Library test suite is free software; you can redistribute it
8 1.1 mrg and/or modify it under the terms of the GNU General Public License as
9 1.1 mrg published by the Free Software Foundation; either version 3 of the License,
10 1.1 mrg or (at your option) any later version.
11 1.1 mrg
12 1.1 mrg The GNU MP Library test suite is distributed in the hope that it will be
13 1.1 mrg useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15 1.1 mrg Public License for more details.
16 1.1 mrg
17 1.1 mrg You should have received a copy of the GNU General Public License along with
18 1.1 mrg the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
19 1.1 mrg
20 1.1 mrg #include <stdio.h>
21 1.1 mrg #include <stdlib.h>
22 1.1 mrg
23 1.1 mrg #include "gmp-impl.h"
24 1.1 mrg #include "tests.h"
25 1.1 mrg
26 1.1 mrg #ifndef SIZE
27 1.1 mrg #define SIZE 4
28 1.1 mrg #endif
29 1.1 mrg
30 1.1 mrg
31 1.1 mrg void
32 1.1 mrg debug_mp (mpz_srcptr x, int base)
33 1.1 mrg {
34 1.1 mrg mpz_out_str (stdout, base, x); fputc ('\n', stdout);
35 1.1 mrg }
36 1.1 mrg
37 1.1 mrg
38 1.1 mrg /* exercise the case where mpz_clrbit or mpz_combit ends up extending a
39 1.1 mrg value like -2^(k*GMP_NUMB_BITS-1) when clearing bit k*GMP_NUMB_BITS-1. */
40 1.1 mrg /* And vice-versa. */
41 1.1 mrg void
42 1.1 mrg check_clr_extend (void)
43 1.1 mrg {
44 1.1 mrg mpz_t got, want;
45 1.1 mrg unsigned long i;
46 1.1 mrg int f;
47 1.1 mrg
48 1.1 mrg mpz_init (got);
49 1.1 mrg mpz_init (want);
50 1.1 mrg
51 1.1 mrg for (i = 1; i < 5; i++)
52 1.1 mrg {
53 1.1 mrg for (f = 0; f <= 1; f++)
54 1.1 mrg {
55 1.1 mrg /* lots of 1 bits in _mp_d */
56 1.1 mrg mpz_set_si (got, 1L);
57 1.1 mrg mpz_mul_2exp (got, got, 10*GMP_NUMB_BITS);
58 1.1 mrg mpz_sub_ui (got, got, 1L);
59 1.1 mrg
60 1.1 mrg /* value -2^(n-1) representing ..11100..00 */
61 1.1 mrg mpz_set_si (got, -1L);
62 1.1 mrg mpz_mul_2exp (got, got, i*GMP_NUMB_BITS-1);
63 1.1 mrg
64 1.1 mrg /* complement bit n, giving ..11000..00 which is -2^n */
65 1.1 mrg if (f == 0)
66 1.1 mrg mpz_clrbit (got, i*GMP_NUMB_BITS-1);
67 1.1 mrg else
68 1.1 mrg mpz_combit (got, i*GMP_NUMB_BITS-1);
69 1.1 mrg MPZ_CHECK_FORMAT (got);
70 1.1 mrg
71 1.1 mrg mpz_set_si (want, -1L);
72 1.1 mrg mpz_mul_2exp (want, want, i*GMP_NUMB_BITS);
73 1.1 mrg
74 1.1 mrg if (mpz_cmp (got, want) != 0)
75 1.1 mrg {
76 1.1 mrg if (f == 0)
77 1.1 mrg printf ("mpz_clrbit: ");
78 1.1 mrg else
79 1.1 mrg printf ("mpz_combit: ");
80 1.1 mrg printf ("wrong after extension\n");
81 1.1 mrg mpz_trace ("got ", got);
82 1.1 mrg mpz_trace ("want", want);
83 1.1 mrg abort ();
84 1.1 mrg }
85 1.1 mrg
86 1.1 mrg /* complement bit n, going back to ..11100..00 which is -2^(n-1) */
87 1.1 mrg if (f == 0)
88 1.1 mrg mpz_setbit (got, i*GMP_NUMB_BITS-1);
89 1.1 mrg else
90 1.1 mrg mpz_combit (got, i*GMP_NUMB_BITS-1);
91 1.1 mrg MPZ_CHECK_FORMAT (got);
92 1.1 mrg
93 1.1 mrg mpz_set_si (want, -1L);
94 1.1 mrg mpz_mul_2exp (want, want, i*GMP_NUMB_BITS - 1);
95 1.1 mrg
96 1.1 mrg if (mpz_cmp (got, want) != 0)
97 1.1 mrg {
98 1.1 mrg if (f == 0)
99 1.1 mrg printf ("mpz_setbit: ");
100 1.1 mrg else
101 1.1 mrg printf ("mpz_combit: ");
102 1.1 mrg printf ("wrong after shrinking\n");
103 1.1 mrg mpz_trace ("got ", got);
104 1.1 mrg mpz_trace ("want", want);
105 1.1 mrg abort ();
106 1.1 mrg }
107 1.1 mrg }
108 1.1 mrg }
109 1.1 mrg
110 1.1 mrg mpz_clear (got);
111 1.1 mrg mpz_clear (want);
112 1.1 mrg }
113 1.1 mrg
114 1.1 mrg void
115 1.1 mrg check_com_negs (void)
116 1.1 mrg {
117 1.1 mrg static const struct {
118 1.1 mrg unsigned long bit;
119 1.1 mrg mp_size_t inp_size;
120 1.1 mrg mp_limb_t inp_n[5];
121 1.1 mrg mp_size_t want_size;
122 1.1 mrg mp_limb_t want_n[5];
123 1.1 mrg } data[] = {
124 1.1 mrg { GMP_NUMB_BITS, 2, { 1, 1 }, 1, { 1 } },
125 1.1 mrg { GMP_NUMB_BITS+1, 2, { 1, 1 }, 2, { 1, 3 } },
126 1.1 mrg
127 1.1 mrg { GMP_NUMB_BITS, 2, { 0, 1 }, 2, { 0, 2 } },
128 1.1 mrg { GMP_NUMB_BITS+1, 2, { 0, 1 }, 2, { 0, 3 } },
129 1.1 mrg };
130 1.1 mrg mpz_t inp, got, want;
131 1.1 mrg int i;
132 1.1 mrg
133 1.1 mrg mpz_init (got);
134 1.1 mrg mpz_init (want);
135 1.1 mrg mpz_init (inp);
136 1.1 mrg
137 1.1 mrg for (i = 0; i < numberof (data); i++)
138 1.1 mrg {
139 1.1 mrg mpz_set_n (inp, data[i].inp_n, data[i].inp_size);
140 1.1 mrg mpz_neg (inp, inp);
141 1.1 mrg
142 1.1 mrg mpz_set_n (want, data[i].want_n, data[i].want_size);
143 1.1 mrg mpz_neg (want, want);
144 1.1 mrg
145 1.1 mrg mpz_set (got, inp);
146 1.1 mrg mpz_combit (got, data[i].bit);
147 1.1 mrg
148 1.1 mrg if (mpz_cmp (got, want) != 0)
149 1.1 mrg {
150 1.1 mrg printf ("mpz_combit: wrong on neg data[%d]\n", i);
151 1.1 mrg mpz_trace ("inp ", inp);
152 1.1 mrg printf ("bit %lu\n", data[i].bit);
153 1.1 mrg mpz_trace ("got ", got);
154 1.1 mrg mpz_trace ("want", want);
155 1.1 mrg abort ();
156 1.1 mrg }
157 1.1 mrg }
158 1.1 mrg
159 1.1 mrg mpz_clear (inp);
160 1.1 mrg mpz_clear (got);
161 1.1 mrg mpz_clear (want);
162 1.1 mrg }
163 1.1 mrg
164 1.1 mrg /* See that mpz_tstbit matches a twos complement calculated explicitly, for
165 1.1 mrg various low zeros. */
166 1.1 mrg void
167 1.1 mrg check_tstbit (void)
168 1.1 mrg {
169 1.1 mrg #define MAX_ZEROS 3
170 1.1 mrg #define NUM_LIMBS 3
171 1.1 mrg
172 1.1 mrg mp_limb_t pos[1+NUM_LIMBS+MAX_ZEROS];
173 1.1 mrg mp_limb_t neg[1+NUM_LIMBS+MAX_ZEROS];
174 1.1 mrg mpz_t z;
175 1.1 mrg unsigned long i;
176 1.1 mrg int zeros, low1;
177 1.1 mrg int got, want;
178 1.1 mrg
179 1.1 mrg mpz_init (z);
180 1.1 mrg for (zeros = 0; zeros <= MAX_ZEROS; zeros++)
181 1.1 mrg {
182 1.1 mrg MPN_ZERO (pos, numberof(pos));
183 1.1 mrg mpn_random2 (pos+zeros, (mp_size_t) NUM_LIMBS);
184 1.1 mrg
185 1.1 mrg for (low1 = 0; low1 <= 1; low1++)
186 1.1 mrg {
187 1.1 mrg if (low1)
188 1.1 mrg pos[0] |= 1;
189 1.1 mrg
190 1.1 mrg refmpn_neg (neg, pos, (mp_size_t) numberof(neg));
191 1.1 mrg mpz_set_n (z, neg, (mp_size_t) numberof(neg));
192 1.1 mrg mpz_neg (z, z);
193 1.1 mrg
194 1.1 mrg for (i = 0; i < numberof(pos)*GMP_NUMB_BITS; i++)
195 1.1 mrg {
196 1.1 mrg got = mpz_tstbit (z, i);
197 1.1 mrg want = refmpn_tstbit (pos, i);
198 1.1 mrg if (got != want)
199 1.1 mrg {
200 1.1 mrg printf ("wrong at bit %lu, with %d zeros\n", i, zeros);
201 1.1 mrg printf ("z neg "); debug_mp (z, -16);
202 1.1 mrg mpz_set_n (z, pos, (mp_size_t) numberof(pos));
203 1.1 mrg printf ("pos "); debug_mp (z, -16);
204 1.1 mrg mpz_set_n (z, neg, (mp_size_t) numberof(neg));
205 1.1 mrg printf ("neg "); debug_mp (z, -16);
206 1.1 mrg exit (1);
207 1.1 mrg }
208 1.1 mrg }
209 1.1 mrg }
210 1.1 mrg }
211 1.1 mrg mpz_clear (z);
212 1.1 mrg }
213 1.1 mrg
214 1.1 mrg
215 1.1 mrg void
216 1.1 mrg check_single (void)
217 1.1 mrg {
218 1.1 mrg mpz_t x;
219 1.1 mrg int limb, offset, initial;
220 1.1 mrg unsigned long bit;
221 1.1 mrg
222 1.1 mrg mpz_init (x);
223 1.1 mrg
224 1.1 mrg for (limb = 0; limb < 4; limb++)
225 1.1 mrg {
226 1.1 mrg for (offset = (limb==0 ? 0 : -2); offset <= 2; offset++)
227 1.1 mrg {
228 1.1 mrg for (initial = 1; initial >= -1; initial--)
229 1.1 mrg {
230 1.1 mrg mpz_set_si (x, (long) initial);
231 1.1 mrg
232 1.1 mrg bit = (unsigned long) limb*GMP_LIMB_BITS + offset;
233 1.1 mrg
234 1.1 mrg mpz_clrbit (x, bit);
235 1.1 mrg MPZ_CHECK_FORMAT (x);
236 1.1 mrg if (mpz_tstbit (x, bit) != 0)
237 1.1 mrg {
238 1.1 mrg printf ("check_single(): expected 0\n");
239 1.1 mrg abort ();
240 1.1 mrg }
241 1.1 mrg
242 1.1 mrg mpz_setbit (x, bit);
243 1.1 mrg MPZ_CHECK_FORMAT (x);
244 1.1 mrg if (mpz_tstbit (x, bit) != 1)
245 1.1 mrg {
246 1.1 mrg printf ("check_single(): expected 1\n");
247 1.1 mrg abort ();
248 1.1 mrg }
249 1.1 mrg
250 1.1 mrg mpz_clrbit (x, bit);
251 1.1 mrg MPZ_CHECK_FORMAT (x);
252 1.1 mrg if (mpz_tstbit (x, bit) != 0)
253 1.1 mrg {
254 1.1 mrg printf ("check_single(): expected 0\n");
255 1.1 mrg abort ();
256 1.1 mrg }
257 1.1 mrg
258 1.1 mrg mpz_combit (x, bit);
259 1.1 mrg MPZ_CHECK_FORMAT (x);
260 1.1 mrg if (mpz_tstbit (x, bit) != 1)
261 1.1 mrg {
262 1.1 mrg printf ("check_single(): expected 1\n");
263 1.1 mrg abort ();
264 1.1 mrg }
265 1.1 mrg
266 1.1 mrg mpz_combit (x, bit);
267 1.1 mrg MPZ_CHECK_FORMAT (x);
268 1.1 mrg if (mpz_tstbit (x, bit) != 0)
269 1.1 mrg {
270 1.1 mrg printf ("check_single(): expected 0\n");
271 1.1 mrg abort ();
272 1.1 mrg }
273 1.1 mrg }
274 1.1 mrg }
275 1.1 mrg }
276 1.1 mrg
277 1.1 mrg mpz_clear (x);
278 1.1 mrg }
279 1.1 mrg
280 1.1 mrg
281 1.1 mrg void
282 1.1 mrg check_random (int argc, char *argv[])
283 1.1 mrg {
284 1.1 mrg mpz_t x, s0, s1, s2, s3, m;
285 1.1 mrg mp_size_t xsize;
286 1.1 mrg int i;
287 1.1 mrg int reps = 100000;
288 1.1 mrg int bit0, bit1, bit2, bit3;
289 1.1 mrg unsigned long int bitindex;
290 1.1 mrg const char *s = "";
291 1.1 mrg
292 1.1 mrg if (argc == 2)
293 1.1 mrg reps = atoi (argv[1]);
294 1.1 mrg
295 1.1 mrg mpz_init (x);
296 1.1 mrg mpz_init (s0);
297 1.1 mrg mpz_init (s1);
298 1.1 mrg mpz_init (s2);
299 1.1 mrg mpz_init (s3);
300 1.1 mrg mpz_init (m);
301 1.1 mrg
302 1.1 mrg for (i = 0; i < reps; i++)
303 1.1 mrg {
304 1.1 mrg xsize = urandom () % (2 * SIZE) - SIZE;
305 1.1 mrg mpz_random2 (x, xsize);
306 1.1 mrg bitindex = urandom () % SIZE;
307 1.1 mrg
308 1.1 mrg mpz_set (s0, x);
309 1.1 mrg bit0 = mpz_tstbit (x, bitindex);
310 1.1 mrg mpz_setbit (x, bitindex);
311 1.1 mrg MPZ_CHECK_FORMAT (x);
312 1.1 mrg
313 1.1 mrg mpz_set (s1, x);
314 1.1 mrg bit1 = mpz_tstbit (x, bitindex);
315 1.1 mrg mpz_clrbit (x, bitindex);
316 1.1 mrg MPZ_CHECK_FORMAT (x);
317 1.1 mrg
318 1.1 mrg mpz_set (s2, x);
319 1.1 mrg bit2 = mpz_tstbit (x, bitindex);
320 1.1 mrg mpz_combit (x, bitindex);
321 1.1 mrg MPZ_CHECK_FORMAT (x);
322 1.1 mrg
323 1.1 mrg mpz_set (s3, x);
324 1.1 mrg bit3 = mpz_tstbit (x, bitindex);
325 1.1 mrg
326 1.1 mrg #define FAIL(str) do { s = str; goto fail; } while (0)
327 1.1 mrg
328 1.1 mrg if (bit1 != 1) FAIL ("bit1 != 1");
329 1.1 mrg if (bit2 != 0) FAIL ("bit2 != 0");
330 1.1 mrg if (bit3 != 1) FAIL ("bit3 != 1");
331 1.1 mrg
332 1.1 mrg if (bit0 == 0)
333 1.1 mrg {
334 1.1 mrg if (mpz_cmp (s0, s1) == 0 || mpz_cmp (s0, s2) != 0 || mpz_cmp (s0, s3) == 0)
335 1.1 mrg abort ();
336 1.1 mrg }
337 1.1 mrg else
338 1.1 mrg {
339 1.1 mrg if (mpz_cmp (s0, s1) != 0 || mpz_cmp (s0, s2) == 0 || mpz_cmp (s0, s3) != 0)
340 1.1 mrg abort ();
341 1.1 mrg }
342 1.1 mrg
343 1.1 mrg if (mpz_cmp (s1, s2) == 0 || mpz_cmp (s1, s3) != 0)
344 1.1 mrg abort ();
345 1.1 mrg if (mpz_cmp (s2, s3) == 0)
346 1.1 mrg abort ();
347 1.1 mrg
348 1.1 mrg mpz_combit (x, bitindex);
349 1.1 mrg MPZ_CHECK_FORMAT (x);
350 1.1 mrg if (mpz_cmp (s2, x) != 0)
351 1.1 mrg abort ();
352 1.1 mrg
353 1.1 mrg mpz_clrbit (x, bitindex);
354 1.1 mrg MPZ_CHECK_FORMAT (x);
355 1.1 mrg if (mpz_cmp (s2, x) != 0)
356 1.1 mrg abort ();
357 1.1 mrg
358 1.1 mrg mpz_ui_pow_ui (m, 2L, bitindex);
359 1.1 mrg MPZ_CHECK_FORMAT (m);
360 1.1 mrg mpz_ior (x, s0, m);
361 1.1 mrg MPZ_CHECK_FORMAT (x);
362 1.1 mrg if (mpz_cmp (x, s3) != 0)
363 1.1 mrg abort ();
364 1.1 mrg
365 1.1 mrg mpz_com (m, m);
366 1.1 mrg MPZ_CHECK_FORMAT (m);
367 1.1 mrg mpz_and (x, s0, m);
368 1.1 mrg MPZ_CHECK_FORMAT (x);
369 1.1 mrg if (mpz_cmp (x, s2) != 0)
370 1.1 mrg abort ();
371 1.1 mrg }
372 1.1 mrg
373 1.1 mrg mpz_clear (x);
374 1.1 mrg mpz_clear (s0);
375 1.1 mrg mpz_clear (s1);
376 1.1 mrg mpz_clear (s2);
377 1.1 mrg mpz_clear (s3);
378 1.1 mrg mpz_clear (m);
379 1.1 mrg return;
380 1.1 mrg
381 1.1 mrg
382 1.1 mrg fail:
383 1.1 mrg printf ("%s\n", s);
384 1.1 mrg printf ("bitindex = %lu\n", bitindex);
385 1.1 mrg printf ("x = "); mpz_out_str (stdout, -16, x); printf (" hex\n");
386 1.1 mrg exit (1);
387 1.1 mrg }
388 1.1 mrg
389 1.1 mrg
390 1.1 mrg
391 1.1 mrg int
392 1.1 mrg main (int argc, char *argv[])
393 1.1 mrg {
394 1.1 mrg tests_start ();
395 1.1 mrg mp_trace_base = -16;
396 1.1 mrg
397 1.1 mrg check_clr_extend ();
398 1.1 mrg check_com_negs ();
399 1.1 mrg check_tstbit ();
400 1.1 mrg check_random (argc, argv);
401 1.1 mrg check_single ();
402 1.1 mrg
403 1.1 mrg tests_end ();
404 1.1 mrg exit (0);
405 1.1 mrg }
406