1 /* Test mpq_mul_2exp and mpq_div_2exp. 2 3 Copyright 2000, 2001 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 #include "gmp-impl.h" 23 #include "tests.h" 24 25 26 struct pair_t { 27 const char *num; 28 const char *den; 29 }; 30 31 void 32 check_random () 33 { 34 gmp_randstate_ptr rands; 35 mpz_t bs; 36 unsigned long arg_size, size_range; 37 mpq_t q, r; 38 int i; 39 mp_bitcnt_t shift; 40 int reps = 10000; 41 42 rands = RANDS; 43 44 mpz_init (bs); 45 mpq_init (q); 46 mpq_init (r); 47 48 for (i = 0; i < reps; i++) 49 { 50 mpz_urandomb (bs, rands, 32); 51 size_range = mpz_get_ui (bs) % 11 + 2; /* 0..4096 bit operands */ 52 53 mpz_urandomb (bs, rands, size_range); 54 arg_size = mpz_get_ui (bs); 55 mpz_rrandomb (mpq_numref (q), rands, arg_size); 56 do 57 { 58 mpz_urandomb (bs, rands, size_range); 59 arg_size = mpz_get_ui (bs); 60 mpz_rrandomb (mpq_denref (q), rands, arg_size); 61 } 62 while (mpz_sgn (mpq_denref (q)) == 0); 63 64 /* We now have a random rational in q, albeit an unnormalised one. The 65 lack of normalisation should not matter here, so let's save the time a 66 gcd would require. */ 67 68 mpz_urandomb (bs, rands, 32); 69 shift = mpz_get_ui (bs) % 4096; 70 71 mpq_mul_2exp (r, q, shift); 72 73 if (mpq_cmp (r, q) < 0) 74 { 75 printf ("mpq_mul_2exp wrong on random\n"); 76 abort (); 77 } 78 79 mpq_div_2exp (r, r, shift); 80 81 if (mpq_cmp (r, q) != 0) 82 { 83 printf ("mpq_mul_2exp or mpq_div_2exp wrong on random\n"); 84 abort (); 85 } 86 } 87 mpq_clear (q); 88 mpq_clear (r); 89 mpz_clear (bs); 90 } 91 92 int 93 main (int argc, char **argv) 94 { 95 static const struct { 96 struct pair_t left; 97 unsigned long n; 98 struct pair_t right; 99 100 } data[] = { 101 { {"0","1"}, 0, {"0","1"} }, 102 { {"0","1"}, 1, {"0","1"} }, 103 { {"0","1"}, 2, {"0","1"} }, 104 105 { {"1","1"}, 0, {"1","1"} }, 106 { {"1","1"}, 1, {"2","1"} }, 107 { {"1","1"}, 2, {"4","1"} }, 108 { {"1","1"}, 3, {"8","1"} }, 109 110 { {"1","1"}, 31, {"0x80000000","1"} }, 111 { {"1","1"}, 32, {"0x100000000","1"} }, 112 { {"1","1"}, 33, {"0x200000000","1"} }, 113 { {"1","1"}, 63, {"0x8000000000000000","1"} }, 114 { {"1","1"}, 64, {"0x10000000000000000","1"} }, 115 { {"1","1"}, 65, {"0x20000000000000000","1"} }, 116 { {"1","1"}, 95, {"0x800000000000000000000000","1"} }, 117 { {"1","1"}, 96, {"0x1000000000000000000000000","1"} }, 118 { {"1","1"}, 97, {"0x2000000000000000000000000","1"} }, 119 { {"1","1"}, 127, {"0x80000000000000000000000000000000","1"} }, 120 { {"1","1"}, 128, {"0x100000000000000000000000000000000","1"} }, 121 { {"1","1"}, 129, {"0x200000000000000000000000000000000","1"} }, 122 123 { {"1","2"}, 31, {"0x40000000","1"} }, 124 { {"1","2"}, 32, {"0x80000000","1"} }, 125 { {"1","2"}, 33, {"0x100000000","1"} }, 126 { {"1","2"}, 63, {"0x4000000000000000","1"} }, 127 { {"1","2"}, 64, {"0x8000000000000000","1"} }, 128 { {"1","2"}, 65, {"0x10000000000000000","1"} }, 129 { {"1","2"}, 95, {"0x400000000000000000000000","1"} }, 130 { {"1","2"}, 96, {"0x800000000000000000000000","1"} }, 131 { {"1","2"}, 97, {"0x1000000000000000000000000","1"} }, 132 { {"1","2"}, 127, {"0x40000000000000000000000000000000","1"} }, 133 { {"1","2"}, 128, {"0x80000000000000000000000000000000","1"} }, 134 { {"1","2"}, 129, {"0x100000000000000000000000000000000","1"} }, 135 136 { {"1","0x80000000"}, 30, {"1","2"} }, 137 { {"1","0x80000000"}, 31, {"1","1"} }, 138 { {"1","0x80000000"}, 32, {"2","1"} }, 139 { {"1","0x80000000"}, 33, {"4","1"} }, 140 { {"1","0x80000000"}, 62, {"0x80000000","1"} }, 141 { {"1","0x80000000"}, 63, {"0x100000000","1"} }, 142 { {"1","0x80000000"}, 64, {"0x200000000","1"} }, 143 { {"1","0x80000000"}, 94, {"0x8000000000000000","1"} }, 144 { {"1","0x80000000"}, 95, {"0x10000000000000000","1"} }, 145 { {"1","0x80000000"}, 96, {"0x20000000000000000","1"} }, 146 { {"1","0x80000000"}, 126, {"0x800000000000000000000000","1"} }, 147 { {"1","0x80000000"}, 127, {"0x1000000000000000000000000","1"} }, 148 { {"1","0x80000000"}, 128, {"0x2000000000000000000000000","1"} }, 149 150 { {"1","0x100000000"}, 1, {"1","0x80000000"} }, 151 { {"1","0x100000000"}, 2, {"1","0x40000000"} }, 152 { {"1","0x100000000"}, 3, {"1","0x20000000"} }, 153 154 { {"1","0x10000000000000000"}, 1, {"1","0x8000000000000000"} }, 155 { {"1","0x10000000000000000"}, 2, {"1","0x4000000000000000"} }, 156 { {"1","0x10000000000000000"}, 3, {"1","0x2000000000000000"} }, 157 }; 158 159 void (*fun) (mpq_ptr, mpq_srcptr, unsigned long); 160 const struct pair_t *p_start, *p_want; 161 const char *name; 162 mpq_t sep, got, want; 163 mpq_ptr q; 164 int i, muldiv, sign, overlap; 165 166 tests_start (); 167 168 mpq_init (sep); 169 mpq_init (got); 170 mpq_init (want); 171 172 for (i = 0; i < numberof (data); i++) 173 { 174 for (muldiv = 0; muldiv < 2; muldiv++) 175 { 176 if (muldiv == 0) 177 { 178 fun = mpq_mul_2exp; 179 name = "mpq_mul_2exp"; 180 p_start = &data[i].left; 181 p_want = &data[i].right; 182 } 183 else 184 { 185 fun = mpq_div_2exp; 186 name = "mpq_div_2exp"; 187 p_start = &data[i].right; 188 p_want = &data[i].left; 189 } 190 191 for (sign = 0; sign <= 1; sign++) 192 { 193 mpz_set_str_or_abort (mpq_numref(want), p_want->num, 0); 194 mpz_set_str_or_abort (mpq_denref(want), p_want->den, 0); 195 if (sign) 196 mpq_neg (want, want); 197 198 for (overlap = 0; overlap <= 1; overlap++) 199 { 200 q = overlap ? got : sep; 201 202 /* initial garbage in "got" */ 203 mpq_set_ui (got, 123L, 456L); 204 205 mpz_set_str_or_abort (mpq_numref(q), p_start->num, 0); 206 mpz_set_str_or_abort (mpq_denref(q), p_start->den, 0); 207 if (sign) 208 mpq_neg (q, q); 209 210 (*fun) (got, q, data[i].n); 211 MPQ_CHECK_FORMAT (got); 212 213 if (! mpq_equal (got, want)) 214 { 215 printf ("%s wrong at data[%d], sign %d, overlap %d\n", 216 name, i, sign, overlap); 217 printf (" num \"%s\"\n", p_start->num); 218 printf (" den \"%s\"\n", p_start->den); 219 printf (" n %lu\n", data[i].n); 220 221 printf (" got "); 222 mpq_out_str (stdout, 16, got); 223 printf (" (hex)\n"); 224 225 printf (" want "); 226 mpq_out_str (stdout, 16, want); 227 printf (" (hex)\n"); 228 229 abort (); 230 } 231 } 232 } 233 } 234 } 235 236 check_random (); 237 238 mpq_clear (sep); 239 mpq_clear (got); 240 mpq_clear (want); 241 242 tests_end (); 243 exit (0); 244 } 245