github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/tests/mpz/bit.c (about)

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