blob: 8952cc2ba802896d4534f1a2ee94519e5d9fd560 [file] [log] [blame]
Austin Schuhdace2a62020-08-18 10:56:48 -07001/* Test mpz_popcount.
2
3Copyright 2001, 2005 Free Software Foundation, Inc.
4
5This file is part of the GNU MP Library test suite.
6
7The GNU MP Library test suite is free software; you can redistribute it
8and/or modify it under the terms of the GNU General Public License as
9published by the Free Software Foundation; either version 3 of the License,
10or (at your option) any later version.
11
12The GNU MP Library test suite is distributed in the hope that it will be
13useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15Public License for more details.
16
17You should have received a copy of the GNU General Public License along with
18the 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-impl.h"
23#include "tests.h"
24
25
26
27void
28check_onebit (void)
29{
30 mpz_t n;
31 unsigned long i, got;
32
33 mpz_init (n);
34 for (i = 0; i < 5 * GMP_LIMB_BITS; i++)
35 {
36 mpz_setbit (n, i);
37 got = mpz_popcount (n);
38 if (got != 1)
39 {
40 printf ("mpz_popcount wrong on single bit at %lu\n", i);
41 printf (" got %lu, want 1\n", got);
42 abort();
43 }
44 mpz_clrbit (n, i);
45 }
46 mpz_clear (n);
47}
48
49
50void
51check_data (void)
52{
53 static const struct {
54 const char *n;
55 unsigned long want;
56 } data[] = {
57 { "-1", ~ (unsigned long) 0 },
58 { "-12345678", ~ (unsigned long) 0 },
59 { "0", 0 },
60 { "1", 1 },
61 { "3", 2 },
62 { "5", 2 },
63 { "0xFFFF", 16 },
64 { "0xFFFFFFFF", 32 },
65 { "0xFFFFFFFFFFFFFFFF", 64 },
66 { "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 128 },
67 };
68
69 unsigned long got;
70 int i;
71 mpz_t n;
72
73 mpz_init (n);
74 for (i = 0; i < numberof (data); i++)
75 {
76 mpz_set_str_or_abort (n, data[i].n, 0);
77 got = mpz_popcount (n);
78 if (got != data[i].want)
79 {
80 printf ("mpz_popcount wrong at data[%d]\n", i);
81 printf (" n \"%s\"\n", data[i].n);
82 printf (" "); mpz_out_str (stdout, 10, n); printf ("\n");
83 printf (" 0x"); mpz_out_str (stdout, 16, n); printf ("\n");
84 printf (" got %lu\n", got);
85 printf (" want %lu\n", data[i].want);
86 abort ();
87 }
88 }
89 mpz_clear (n);
90}
91
92unsigned long
93refmpz_popcount (mpz_t arg)
94{
95 mp_size_t n, i;
96 unsigned long cnt;
97 mp_limb_t x;
98
99 n = SIZ(arg);
100 if (n < 0)
101 return ~(unsigned long) 0;
102
103 cnt = 0;
104 for (i = 0; i < n; i++)
105 {
106 x = PTR(arg)[i];
107 while (x != 0)
108 {
109 cnt += (x & 1);
110 x >>= 1;
111 }
112 }
113 return cnt;
114}
115
116void
117check_random (void)
118{
119 gmp_randstate_ptr rands;
120 mpz_t bs;
121 mpz_t arg;
122 unsigned long arg_size, size_range;
123 unsigned long got, ref;
124 int i;
125
126 rands = RANDS;
127
128 mpz_init (bs);
129 mpz_init (arg);
130
131 for (i = 0; i < 10000; i++)
132 {
133 mpz_urandomb (bs, rands, 32);
134 size_range = mpz_get_ui (bs) % 11 + 2; /* 0..4096 bit operands */
135
136 mpz_urandomb (bs, rands, size_range);
137 arg_size = mpz_get_ui (bs);
138 mpz_rrandomb (arg, rands, arg_size);
139
140 got = mpz_popcount (arg);
141 ref = refmpz_popcount (arg);
142 if (got != ref)
143 {
144 printf ("mpz_popcount wrong on random\n");
145 printf (" "); mpz_out_str (stdout, 10, arg); printf ("\n");
146 printf (" 0x"); mpz_out_str (stdout, 16, arg); printf ("\n");
147 printf (" got %lu\n", got);
148 printf (" want %lu\n", ref);
149 abort ();
150 }
151 }
152 mpz_clear (arg);
153 mpz_clear (bs);
154}
155
156int
157main (void)
158{
159 tests_start ();
160
161 check_onebit ();
162 check_data ();
163 check_random ();
164
165 tests_end ();
166 exit (0);
167}