1/* Test mpf_eq. 2 3Copyright 2009, 2012 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 23#include "gmp-impl.h" 24#include "tests.h" 25 26#define SZ (2 * sizeof(mp_limb_t)) 27 28void insert_random_low_zero_limbs (mpf_t, gmp_randstate_ptr); 29void dump_abort (mpf_t, mpf_t, int, int, int, int, int, long); 30void hexdump (mpf_t); 31 32void 33check_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 99void 100check_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 162void 163insert_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 176void 177dump_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 190void 191hexdump (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 202int 203main (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