1 /* Test mpf_eq. 2 3 Copyright 2009, 2012 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 23 #include "gmp-impl.h" 24 #include "tests.h" 25 26 #define SZ (2 * sizeof(mp_limb_t)) 27 28 void insert_random_low_zero_limbs (mpf_t, gmp_randstate_ptr); 29 void dump_abort (mpf_t, mpf_t, int, int, int, int, int, long); 30 void hexdump (mpf_t); 31 32 void 33 check_data (void) 34 { 35 static const struct 36 { 37 struct { 38 int exp, size; 39 mp_limb_t d[10]; 40 } x, y; 41 mp_bitcnt_t bits; 42 int want; 43 44 } data[] = { 45 { { 0, 0, { 0 } }, { 0, 0, { 0 } }, 0, 1 }, 46 47 { { 0, 1, { 7 } }, { 0, 1, { 7 } }, 0, 1 }, 48 { { 0, 1, { 7 } }, { 0, 1, { 7 } }, 17, 1 }, 49 { { 0, 1, { 7 } }, { 0, 1, { 7 } }, 4711, 1 }, 50 51 { { 0, 1, { 7 } }, { 0, 1, { 6 } }, 0, 1 }, 52 { { 0, 1, { 7 } }, { 0, 1, { 6 } }, 2, 1 }, 53 { { 0, 1, { 7 } }, { 0, 1, { 6 } }, 3, 0 }, 54 55 { { 0, 0, { 0 } }, { 0, 1, { 1 } }, 0, 0 }, 56 { { 0, 1, { 1 } }, { 0,-1 ,{ 1 } }, 0, 0 }, 57 { { 1, 1, { 1 } }, { 0, 1, { 1 } }, 0, 0 }, 58 59 { { 0, 1, { 8 } }, { 0, 1, { 4 } }, 0, 0 }, 60 61 { { 0, 2, { 0, 3 } }, { 0, 1, { 3 } }, 1000, 1 }, 62 }; 63 64 mpf_t x, y; 65 int got, got_swapped; 66 int i; 67 mp_trace_base = 16; 68 69 for (i = 0; i < numberof (data); i++) 70 { 71 PTR(x) = (mp_ptr) data[i].x.d; 72 SIZ(x) = data[i].x.size; 73 EXP(x) = data[i].x.exp; 74 PREC(x) = numberof (data[i].x.d); 75 MPF_CHECK_FORMAT (x); 76 77 PTR(y) = (mp_ptr) data[i].y.d; 78 SIZ(y) = data[i].y.size; 79 EXP(y) = data[i].y.exp; 80 PREC(y) = numberof (data[i].y.d); 81 MPF_CHECK_FORMAT (y); 82 83 got = mpf_eq (x, y, data[i].bits); 84 got_swapped = mpf_eq (y, x, data[i].bits); 85 86 if (got != got_swapped || got != data[i].want) 87 { 88 printf ("check_data() wrong result at data[%d]\n", i); 89 mpf_trace ("x ", x); 90 mpf_trace ("y ", y); 91 printf ("got %d\n", got); 92 printf ("got_swapped %d\n", got_swapped); 93 printf ("want %d\n", data[i].want); 94 abort (); 95 } 96 } 97 } 98 99 void 100 check_random (long reps) 101 { 102 unsigned long test; 103 gmp_randstate_ptr rands = RANDS; 104 mpf_t a, b, x; 105 mpz_t ds; 106 int hibits, lshift1, lshift2; 107 int xtra; 108 109 #define HIBITS 10 110 #define LSHIFT1 10 111 #define LSHIFT2 10 112 113 mpf_set_default_prec ((1 << HIBITS) + (1 << LSHIFT1) + (1 << LSHIFT2)); 114 115 mpz_init (ds); 116 mpf_inits (a, b, x, NULL); 117 118 for (test = 0; test < reps; test++) 119 { 120 mpz_urandomb (ds, rands, HIBITS); 121 hibits = mpz_get_ui (ds) + 1; 122 mpz_urandomb (ds, rands, hibits); 123 mpz_setbit (ds, hibits - 1); /* make sure msb is set */ 124 mpf_set_z (a, ds); 125 mpf_set_z (b, ds); 126 127 mpz_urandomb (ds, rands, LSHIFT1); 128 lshift1 = mpz_get_ui (ds); 129 mpf_mul_2exp (a, a, lshift1 + 1); 130 mpf_mul_2exp (b, b, lshift1 + 1); 131 mpf_add_ui (a, a, 1); /* make a one-bit difference */ 132 133 mpz_urandomb (ds, rands, LSHIFT2); 134 lshift2 = mpz_get_ui (ds); 135 mpf_mul_2exp (a, a, lshift2); 136 mpf_mul_2exp (b, b, lshift2); 137 mpz_urandomb (ds, rands, lshift2); 138 mpf_set_z (x, ds); 139 mpf_add (a, a, x); 140 mpf_add (b, b, x); 141 142 insert_random_low_zero_limbs (a, rands); 143 insert_random_low_zero_limbs (b, rands); 144 145 if (mpf_eq (a, b, lshift1 + hibits) == 0 || 146 mpf_eq (b, a, lshift1 + hibits) == 0) 147 { 148 dump_abort (a, b, lshift1 + hibits, lshift1, lshift2, hibits, 1, test); 149 } 150 for (xtra = 1; xtra < 100; xtra++) 151 if (mpf_eq (a, b, lshift1 + hibits + xtra) != 0 || 152 mpf_eq (b, a, lshift1 + hibits + xtra) != 0) 153 { 154 dump_abort (a, b, lshift1 + hibits + xtra, lshift1, lshift2, hibits, 0, test); 155 } 156 } 157 158 mpf_clears (a, b, x, NULL); 159 mpz_clear (ds); 160 } 161 162 void 163 insert_random_low_zero_limbs (mpf_t x, gmp_randstate_ptr rands) 164 { 165 mp_size_t max = PREC(x) - SIZ(x); 166 mp_size_t s; 167 mpz_t ds; mpz_init (ds); 168 mpz_urandomb (ds, rands, 32); 169 s = mpz_get_ui (ds) % (max + 1); 170 MPN_COPY_DECR (PTR(x) + s, PTR(x), SIZ(x)); 171 MPN_ZERO (PTR(x), s); 172 SIZ(x) += s; 173 mpz_clear (ds); 174 } 175 176 void 177 dump_abort (mpf_t a, mpf_t b, int cmp_prec, int lshift1, int lshift2, int hibits, int want, long test) 178 { 179 printf ("ERROR in test %ld\n", test); 180 printf ("want %d got %d from mpf_eq\n", want, 1-want); 181 printf ("cmp_prec = %d\n", cmp_prec); 182 printf ("lshift1 = %d\n", lshift1); 183 printf ("lshift2 = %d\n", lshift2); 184 printf ("hibits = %d\n", hibits); 185 hexdump (a); puts (""); 186 hexdump (b); puts (""); 187 abort (); 188 } 189 190 void 191 hexdump (mpf_t x) 192 { 193 mp_size_t i; 194 for (i = ABSIZ(x) - 1; i >= 0; i--) 195 { 196 gmp_printf ("%0*MX", SZ, PTR(x)[i]); 197 if (i != 0) 198 printf (" "); 199 } 200 } 201 202 int 203 main (int argc, char *argv[]) 204 { 205 long reps = 10000; 206 207 if (argc == 2) 208 reps = strtol (argv[1], 0, 0); 209 210 tests_start (); 211 212 check_data (); 213 check_random (reps); 214 215 tests_end (); 216 exit (0); 217 } 218