1 /* test mpz_congruent_2exp_p */ 2 3 /* 4 Copyright 2001 Free Software Foundation, Inc. 5 6 This file is part of the GNU MP Library. 7 8 The GNU MP Library is free software; you can redistribute it and/or modify 9 it under the terms of the GNU Lesser General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or (at your 11 option) any later version. 12 13 The GNU MP Library is distributed in the hope that it will be useful, but 14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 16 License for more details. 17 18 You should have received a copy of the GNU Lesser General Public License 19 along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ 20 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include "gmp.h" 24 #include "gmp-impl.h" 25 #include "tests.h" 26 27 28 void 29 check_one (mpz_srcptr a, mpz_srcptr c, unsigned long d, int want) 30 { 31 mpz_t diff, d2exp; 32 int got; 33 int swap; 34 35 for (swap = 0; swap <= 1; swap++) 36 { 37 got = (mpz_congruent_2exp_p (a, c, d) != 0); 38 if (want != got) 39 { 40 mpz_init (diff); 41 mpz_init (d2exp); 42 43 mpz_sub (diff, a, c); 44 mpz_set_ui (d2exp, 1L); 45 mpz_mul_2exp (d2exp, d2exp, d); 46 47 printf ("mpz_congruent_2exp_p wrong\n"); 48 printf (" expected %d got %d\n", want, got); 49 mpz_trace (" a", a); 50 mpz_trace (" c", c); 51 mpz_trace (" a-c", diff); 52 mpz_trace (" 2^d", d2exp); 53 printf (" d=%lu\n", d); 54 55 mp_trace_base = -16; 56 mpz_trace (" a", a); 57 mpz_trace (" c", c); 58 mpz_trace (" a-c", diff); 59 mpz_trace (" 2^d", d2exp); 60 printf (" d=0x%lX\n", d); 61 abort (); 62 } 63 64 MPZ_SRCPTR_SWAP (a, c); 65 } 66 } 67 68 69 void 70 check_data (void) 71 { 72 static const struct { 73 const char *a; 74 const char *c; 75 unsigned long d; 76 int want; 77 78 } data[] = { 79 80 /* anything is congruent mod 1 */ 81 { "0", "0", 0, 1 }, 82 { "1", "0", 0, 1 }, 83 { "0", "1", 0, 1 }, 84 { "123", "456", 0, 1 }, 85 { "0x123456789123456789", "0x987654321987654321", 0, 1 }, 86 87 }; 88 89 mpz_t a, c; 90 int i; 91 92 mpz_init (a); 93 mpz_init (c); 94 95 for (i = 0; i < numberof (data); i++) 96 { 97 mpz_set_str_or_abort (a, data[i].a, 0); 98 mpz_set_str_or_abort (c, data[i].c, 0); 99 check_one (a, c, data[i].d, data[i].want); 100 } 101 102 mpz_clear (a); 103 mpz_clear (c); 104 } 105 106 107 void 108 check_random (int argc, char *argv[]) 109 { 110 gmp_randstate_ptr rands = RANDS; 111 unsigned long d; 112 mpz_t a, c, ra, rc; 113 int i; 114 int want; 115 int reps = 5000; 116 117 if (argc >= 2) 118 reps = atoi (argv[1]); 119 120 mpz_init (a); 121 mpz_init (c); 122 mpz_init (ra); 123 mpz_init (rc); 124 125 for (i = 0; i < reps; i++) 126 { 127 mpz_errandomb (a, rands, 8*GMP_LIMB_BITS); 128 mpz_errandomb (c, rands, 8*GMP_LIMB_BITS); 129 d = urandom() % (8*GMP_LIMB_BITS); 130 131 mpz_mul_2exp (a, a, urandom() % (2*GMP_LIMB_BITS)); 132 mpz_mul_2exp (c, c, urandom() % (2*GMP_LIMB_BITS)); 133 134 mpz_negrandom (a, rands); 135 mpz_negrandom (c, rands); 136 137 mpz_fdiv_r_2exp (ra, a, d); 138 mpz_fdiv_r_2exp (rc, c, d); 139 140 want = (mpz_cmp (ra, rc) == 0); 141 check_one (a, c, d, want); 142 143 mpz_sub (ra, ra, rc); 144 mpz_sub (a, a, ra); 145 check_one (a, c, d, 1); 146 } 147 148 mpz_clear (a); 149 mpz_clear (c); 150 mpz_clear (ra); 151 mpz_clear (rc); 152 } 153 154 155 int 156 main (int argc, char *argv[]) 157 { 158 tests_start (); 159 160 check_data (); 161 check_random (argc, argv); 162 163 tests_end (); 164 exit (0); 165 } 166