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

     1  /* Test mpz_popcount.
     2  
     3  Copyright 2001, 2005 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  #include "gmp.h"
    23  #include "gmp-impl.h"
    24  #include "tests.h"
    25  
    26  
    27  
    28  void
    29  check_onebit (void)
    30  {
    31    mpz_t          n;
    32    unsigned long  i, got;
    33  
    34    mpz_init (n);
    35    for (i = 0; i < 5 * GMP_LIMB_BITS; i++)
    36      {
    37        mpz_setbit (n, i);
    38        got = mpz_popcount (n);
    39        if (got != 1)
    40  	{
    41  	  printf ("mpz_popcount wrong on single bit at %lu\n", i);
    42  	  printf ("   got %lu, want 1\n", got);
    43  	  abort();
    44  	}
    45        mpz_clrbit (n, i);
    46      }
    47    mpz_clear (n);
    48  }
    49  
    50  
    51  void
    52  check_data (void)
    53  {
    54    static const struct {
    55      const char     *n;
    56      unsigned long  want;
    57    } data[] = {
    58      { "-1", ~ (unsigned long) 0 },
    59      { "-12345678", ~ (unsigned long) 0 },
    60      { "0", 0 },
    61      { "1", 1 },
    62      { "3", 2 },
    63      { "5", 2 },
    64      { "0xFFFF", 16 },
    65      { "0xFFFFFFFF", 32 },
    66      { "0xFFFFFFFFFFFFFFFF", 64 },
    67      { "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 128 },
    68    };
    69  
    70    unsigned long   got;
    71    int    i;
    72    mpz_t  n;
    73  
    74    mpz_init (n);
    75    for (i = 0; i < numberof (data); i++)
    76      {
    77        mpz_set_str_or_abort (n, data[i].n, 0);
    78        got = mpz_popcount (n);
    79        if (got != data[i].want)
    80  	{
    81  	  printf ("mpz_popcount wrong at data[%d]\n", i);
    82  	  printf ("   n     \"%s\"\n", data[i].n);
    83  	  printf ("         ");   mpz_out_str (stdout, 10, n); printf ("\n");
    84  	  printf ("         0x"); mpz_out_str (stdout, 16, n); printf ("\n");
    85  	  printf ("   got   %lu\n", got);
    86  	  printf ("   want  %lu\n", data[i].want);
    87  	  abort ();
    88  	}
    89      }
    90    mpz_clear (n);
    91  }
    92  
    93  unsigned long
    94  refmpz_popcount (mpz_t arg)
    95  {
    96    mp_size_t n, i;
    97    unsigned long cnt;
    98    mp_limb_t x;
    99  
   100    n = SIZ(arg);
   101    if (n < 0)
   102      return ~(unsigned long) 0;
   103  
   104    cnt = 0;
   105    for (i = 0; i < n; i++)
   106      {
   107        x = PTR(arg)[i];
   108        while (x != 0)
   109  	{
   110  	  cnt += (x & 1);
   111  	  x >>= 1;
   112  	}
   113      }
   114    return cnt;
   115  }
   116  
   117  void
   118  check_random (void)
   119  {
   120    gmp_randstate_ptr rands;
   121    mpz_t bs;
   122    mpz_t arg;
   123    unsigned long arg_size, size_range;
   124    unsigned long got, ref;
   125    int i;
   126  
   127    rands = RANDS;
   128  
   129    mpz_init (bs);
   130    mpz_init (arg);
   131  
   132    for (i = 0; i < 10000; i++)
   133      {
   134        mpz_urandomb (bs, rands, 32);
   135        size_range = mpz_get_ui (bs) % 11 + 2; /* 0..4096 bit operands */
   136  
   137        mpz_urandomb (bs, rands, size_range);
   138        arg_size = mpz_get_ui (bs);
   139        mpz_rrandomb (arg, rands, arg_size);
   140  
   141        got = mpz_popcount (arg);
   142        ref = refmpz_popcount (arg);
   143        if (got != ref)
   144  	{
   145  	  printf ("mpz_popcount wrong on random\n");
   146  	  printf ("         ");   mpz_out_str (stdout, 10, arg); printf ("\n");
   147  	  printf ("         0x"); mpz_out_str (stdout, 16, arg); printf ("\n");
   148  	  printf ("   got   %lu\n", got);
   149  	  printf ("   want  %lu\n", ref);
   150  	  abort ();
   151  	}
   152      }
   153    mpz_clear (arg);
   154    mpz_clear (bs);
   155  }
   156  
   157  int
   158  main (void)
   159  {
   160    tests_start ();
   161  
   162    check_onebit ();
   163    check_data ();
   164    check_random ();
   165  
   166    tests_end ();
   167    exit (0);
   168  }