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