| OLD | NEW |
| (Empty) |
| 1 /* Test mpz_setbit, mpz_clrbit, mpz_tstbit. | |
| 2 | |
| 3 Copyright 1997, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. | |
| 4 | |
| 5 This file is part of the GNU MP Library. | |
| 6 | |
| 7 The GNU MP Library is free software; you can redistribute it and/or modify | |
| 8 it under the terms of the GNU Lesser General Public License as published by | |
| 9 the Free Software Foundation; either version 3 of the License, or (at your | |
| 10 option) any later version. | |
| 11 | |
| 12 The GNU MP Library is distributed in the hope that it will be useful, but | |
| 13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
| 14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public | |
| 15 License for more details. | |
| 16 | |
| 17 You should have received a copy of the GNU Lesser General Public License | |
| 18 along with the GNU MP Library. If not, see http://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 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_ui (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 } | |
| 87 | |
| 88 mpz_clear (got); | |
| 89 mpz_clear (want); | |
| 90 } | |
| 91 | |
| 92 void | |
| 93 check_com_negs (void) | |
| 94 { | |
| 95 static const struct { | |
| 96 unsigned long bit; | |
| 97 mp_size_t inp_size; | |
| 98 mp_limb_t inp_n[5]; | |
| 99 mp_size_t want_size; | |
| 100 mp_limb_t want_n[5]; | |
| 101 } data[] = { | |
| 102 { GMP_NUMB_BITS, 2, { 1, 1 }, 1, { 1 } }, | |
| 103 { GMP_NUMB_BITS+1, 2, { 1, 1 }, 2, { 1, 3 } }, | |
| 104 | |
| 105 { GMP_NUMB_BITS, 2, { 0, 1 }, 2, { 0, 2 } }, | |
| 106 { GMP_NUMB_BITS+1, 2, { 0, 1 }, 2, { 0, 3 } }, | |
| 107 }; | |
| 108 mpz_t inp, got, want; | |
| 109 int i; | |
| 110 | |
| 111 mpz_init (got); | |
| 112 mpz_init (want); | |
| 113 mpz_init (inp); | |
| 114 | |
| 115 for (i = 0; i < numberof (data); i++) | |
| 116 { | |
| 117 mpz_set_n (inp, data[i].inp_n, data[i].inp_size); | |
| 118 mpz_neg (inp, inp); | |
| 119 | |
| 120 mpz_set_n (want, data[i].want_n, data[i].want_size); | |
| 121 mpz_neg (want, want); | |
| 122 | |
| 123 mpz_set (got, inp); | |
| 124 mpz_combit (got, data[i].bit); | |
| 125 | |
| 126 if (mpz_cmp (got, want) != 0) | |
| 127 { | |
| 128 printf ("mpz_combit: wrong on neg data[%d]\n", i); | |
| 129 mpz_trace ("inp ", inp); | |
| 130 printf ("bit %lu\n", data[i].bit); | |
| 131 mpz_trace ("got ", got); | |
| 132 mpz_trace ("want", want); | |
| 133 abort (); | |
| 134 } | |
| 135 } | |
| 136 | |
| 137 mpz_clear (inp); | |
| 138 mpz_clear (got); | |
| 139 mpz_clear (want); | |
| 140 } | |
| 141 | |
| 142 /* See that mpz_tstbit matches a twos complement calculated explicitly, for | |
| 143 various low zeros. */ | |
| 144 void | |
| 145 check_tstbit (void) | |
| 146 { | |
| 147 #define MAX_ZEROS 3 | |
| 148 #define NUM_LIMBS 3 | |
| 149 | |
| 150 mp_limb_t pos[1+NUM_LIMBS+MAX_ZEROS]; | |
| 151 mp_limb_t neg[1+NUM_LIMBS+MAX_ZEROS]; | |
| 152 mpz_t z; | |
| 153 unsigned long i; | |
| 154 int zeros, low1; | |
| 155 int got, want; | |
| 156 | |
| 157 mpz_init (z); | |
| 158 for (zeros = 0; zeros <= MAX_ZEROS; zeros++) | |
| 159 { | |
| 160 MPN_ZERO (pos, numberof(pos)); | |
| 161 mpn_random2 (pos+zeros, (mp_size_t) NUM_LIMBS); | |
| 162 | |
| 163 for (low1 = 0; low1 <= 1; low1++) | |
| 164 { | |
| 165 if (low1) | |
| 166 pos[0] |= 1; | |
| 167 | |
| 168 refmpn_neg_n (neg, pos, (mp_size_t) numberof(neg)); | |
| 169 mpz_set_n (z, neg, (mp_size_t) numberof(neg)); | |
| 170 mpz_neg (z, z); | |
| 171 | |
| 172 for (i = 0; i < numberof(pos)*GMP_NUMB_BITS; i++) | |
| 173 { | |
| 174 got = mpz_tstbit (z, i); | |
| 175 want = refmpn_tstbit (pos, i); | |
| 176 if (got != want) | |
| 177 { | |
| 178 printf ("wrong at bit %lu, with %d zeros\n", i, zeros); | |
| 179 printf ("z neg "); debug_mp (z, -16); | |
| 180 mpz_set_n (z, pos, (mp_size_t) numberof(pos)); | |
| 181 printf ("pos "); debug_mp (z, -16); | |
| 182 mpz_set_n (z, neg, (mp_size_t) numberof(neg)); | |
| 183 printf ("neg "); debug_mp (z, -16); | |
| 184 exit (1); | |
| 185 } | |
| 186 } | |
| 187 } | |
| 188 } | |
| 189 mpz_clear (z); | |
| 190 } | |
| 191 | |
| 192 | |
| 193 void | |
| 194 check_single (void) | |
| 195 { | |
| 196 mpz_t x; | |
| 197 int limb, offset, initial; | |
| 198 unsigned long bit; | |
| 199 | |
| 200 mpz_init (x); | |
| 201 | |
| 202 for (limb = 0; limb < 4; limb++) | |
| 203 { | |
| 204 for (offset = (limb==0 ? 0 : -2); offset <= 2; offset++) | |
| 205 { | |
| 206 for (initial = 0; initial >= -1; initial--) | |
| 207 { | |
| 208 mpz_set_si (x, (long) initial); | |
| 209 | |
| 210 bit = (unsigned long) limb*BITS_PER_MP_LIMB + offset; | |
| 211 | |
| 212 mpz_clrbit (x, bit); | |
| 213 MPZ_CHECK_FORMAT (x); | |
| 214 if (mpz_tstbit (x, bit) != 0) | |
| 215 { | |
| 216 printf ("check_single(): expected 0\n"); | |
| 217 abort (); | |
| 218 } | |
| 219 | |
| 220 mpz_setbit (x, bit); | |
| 221 MPZ_CHECK_FORMAT (x); | |
| 222 if (mpz_tstbit (x, bit) != 1) | |
| 223 { | |
| 224 printf ("check_single(): expected 1\n"); | |
| 225 abort (); | |
| 226 } | |
| 227 | |
| 228 mpz_clrbit (x, bit); | |
| 229 MPZ_CHECK_FORMAT (x); | |
| 230 if (mpz_tstbit (x, bit) != 0) | |
| 231 { | |
| 232 printf ("check_single(): expected 0\n"); | |
| 233 abort (); | |
| 234 } | |
| 235 | |
| 236 mpz_combit (x, bit); | |
| 237 MPZ_CHECK_FORMAT (x); | |
| 238 if (mpz_tstbit (x, bit) != 1) | |
| 239 { | |
| 240 printf ("check_single(): expected 1\n"); | |
| 241 abort (); | |
| 242 } | |
| 243 | |
| 244 mpz_combit (x, bit); | |
| 245 MPZ_CHECK_FORMAT (x); | |
| 246 if (mpz_tstbit (x, bit) != 0) | |
| 247 { | |
| 248 printf ("check_single(): expected 0\n"); | |
| 249 abort (); | |
| 250 } | |
| 251 } | |
| 252 } | |
| 253 } | |
| 254 | |
| 255 mpz_clear (x); | |
| 256 } | |
| 257 | |
| 258 | |
| 259 void | |
| 260 check_random (int argc, char *argv[]) | |
| 261 { | |
| 262 mpz_t x, s0, s1, s2, s3, m; | |
| 263 mp_size_t xsize; | |
| 264 int i; | |
| 265 int reps = 100000; | |
| 266 int bit0, bit1, bit2, bit3; | |
| 267 unsigned long int bitindex; | |
| 268 const char *s = ""; | |
| 269 | |
| 270 if (argc == 2) | |
| 271 reps = atoi (argv[1]); | |
| 272 | |
| 273 mpz_init (x); | |
| 274 mpz_init (s0); | |
| 275 mpz_init (s1); | |
| 276 mpz_init (s2); | |
| 277 mpz_init (s3); | |
| 278 mpz_init (m); | |
| 279 | |
| 280 for (i = 0; i < reps; i++) | |
| 281 { | |
| 282 xsize = urandom () % (2 * SIZE) - SIZE; | |
| 283 mpz_random2 (x, xsize); | |
| 284 bitindex = urandom () % SIZE; | |
| 285 | |
| 286 mpz_set (s0, x); | |
| 287 bit0 = mpz_tstbit (x, bitindex); | |
| 288 mpz_setbit (x, bitindex); | |
| 289 MPZ_CHECK_FORMAT (x); | |
| 290 | |
| 291 mpz_set (s1, x); | |
| 292 bit1 = mpz_tstbit (x, bitindex); | |
| 293 mpz_clrbit (x, bitindex); | |
| 294 MPZ_CHECK_FORMAT (x); | |
| 295 | |
| 296 mpz_set (s2, x); | |
| 297 bit2 = mpz_tstbit (x, bitindex); | |
| 298 mpz_setbit (x, bitindex); | |
| 299 MPZ_CHECK_FORMAT (x); | |
| 300 | |
| 301 mpz_set (s3, x); | |
| 302 bit3 = mpz_tstbit (x, bitindex); | |
| 303 | |
| 304 #define FAIL(str) do { s = str; goto fail; } while (0) | |
| 305 | |
| 306 if (bit1 != 1) FAIL ("bit1 != 1"); | |
| 307 if (bit2 != 0) FAIL ("bit2 != 0"); | |
| 308 if (bit3 != 1) FAIL ("bit3 != 1"); | |
| 309 | |
| 310 if (bit0 == 0) | |
| 311 { | |
| 312 if (mpz_cmp (s0, s1) == 0 || mpz_cmp (s0, s2) != 0 || mpz_cmp (s0, s3)
== 0) | |
| 313 abort (); | |
| 314 } | |
| 315 else | |
| 316 { | |
| 317 if (mpz_cmp (s0, s1) != 0 || mpz_cmp (s0, s2) == 0 || mpz_cmp (s0, s3)
!= 0) | |
| 318 abort (); | |
| 319 } | |
| 320 | |
| 321 if (mpz_cmp (s1, s2) == 0 || mpz_cmp (s1, s3) != 0) | |
| 322 abort (); | |
| 323 if (mpz_cmp (s2, s3) == 0) | |
| 324 abort (); | |
| 325 | |
| 326 mpz_ui_pow_ui (m, 2L, bitindex); | |
| 327 MPZ_CHECK_FORMAT (m); | |
| 328 mpz_ior (x, s2, m); | |
| 329 MPZ_CHECK_FORMAT (x); | |
| 330 if (mpz_cmp (x, s3) != 0) | |
| 331 abort (); | |
| 332 | |
| 333 mpz_com (m, m); | |
| 334 MPZ_CHECK_FORMAT (m); | |
| 335 mpz_and (x, s1, m); | |
| 336 MPZ_CHECK_FORMAT (x); | |
| 337 if (mpz_cmp (x, s2) != 0) | |
| 338 abort (); | |
| 339 } | |
| 340 | |
| 341 mpz_clear (x); | |
| 342 mpz_clear (s0); | |
| 343 mpz_clear (s1); | |
| 344 mpz_clear (s2); | |
| 345 mpz_clear (s3); | |
| 346 mpz_clear (m); | |
| 347 return; | |
| 348 | |
| 349 | |
| 350 fail: | |
| 351 printf ("%s\n", s); | |
| 352 printf ("bitindex = %lu\n", bitindex); | |
| 353 printf ("x = "); mpz_out_str (stdout, -16, x); printf (" hex\n"); | |
| 354 exit (1); | |
| 355 } | |
| 356 | |
| 357 | |
| 358 | |
| 359 int | |
| 360 main (int argc, char *argv[]) | |
| 361 { | |
| 362 tests_start (); | |
| 363 mp_trace_base = -16; | |
| 364 | |
| 365 check_clr_extend (); | |
| 366 check_com_negs (); | |
| 367 check_tstbit (); | |
| 368 check_random (argc, argv); | |
| 369 check_single (); | |
| 370 | |
| 371 tests_end (); | |
| 372 exit (0); | |
| 373 } | |
| OLD | NEW |