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