Home | History | Annotate | Line # | Download | only in mpz
t-bit.c revision 1.1
      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
     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
     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
    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
    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
    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
    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
    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