1 1.1 mrg /* Test mpn_hgcd_appr. 2 1.1 mrg 3 1.1.1.2 mrg Copyright 1991, 1993, 1994, 1996, 1997, 2000-2004, 2011 Free Software 4 1.1.1.2 mrg Foundation, Inc. 5 1.1 mrg 6 1.1 mrg This file is part of the GNU MP Library test suite. 7 1.1 mrg 8 1.1 mrg The GNU MP Library test suite is free software; you can redistribute it 9 1.1 mrg and/or modify it under the terms of the GNU General Public License as 10 1.1 mrg published by the Free Software Foundation; either version 3 of the License, 11 1.1 mrg or (at your option) any later version. 12 1.1 mrg 13 1.1 mrg The GNU MP Library test suite is distributed in the hope that it will be 14 1.1 mrg useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 15 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 16 1.1 mrg Public License for more details. 17 1.1 mrg 18 1.1 mrg You should have received a copy of the GNU General Public License along with 19 1.1.1.2 mrg the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */ 20 1.1 mrg 21 1.1 mrg #include <stdio.h> 22 1.1 mrg #include <stdlib.h> 23 1.1 mrg #include <string.h> 24 1.1 mrg 25 1.1 mrg #include "gmp-impl.h" 26 1.1 mrg #include "tests.h" 27 1.1 mrg 28 1.1 mrg static mp_size_t one_test (mpz_t, mpz_t, int); 29 1.1 mrg static void debug_mp (mpz_t, int); 30 1.1 mrg 31 1.1 mrg #define MIN_OPERAND_SIZE 2 32 1.1 mrg 33 1.1 mrg struct hgcd_ref 34 1.1 mrg { 35 1.1 mrg mpz_t m[2][2]; 36 1.1 mrg }; 37 1.1 mrg 38 1.1 mrg static void hgcd_ref_init (struct hgcd_ref *hgcd); 39 1.1 mrg static void hgcd_ref_clear (struct hgcd_ref *hgcd); 40 1.1 mrg static int hgcd_ref (struct hgcd_ref *hgcd, mpz_t a, mpz_t b); 41 1.1 mrg static int hgcd_ref_equal (const struct hgcd_ref *, const struct hgcd_ref *); 42 1.1 mrg static int hgcd_appr_valid_p (mpz_t, mpz_t, mp_size_t, struct hgcd_ref *, 43 1.1 mrg mpz_t, mpz_t, mp_size_t, struct hgcd_matrix *); 44 1.1 mrg 45 1.1 mrg static int verbose_flag = 0; 46 1.1 mrg 47 1.1 mrg int 48 1.1 mrg main (int argc, char **argv) 49 1.1 mrg { 50 1.1 mrg mpz_t op1, op2, temp1, temp2; 51 1.1 mrg int i, j, chain_len; 52 1.1 mrg gmp_randstate_ptr rands; 53 1.1 mrg mpz_t bs; 54 1.1 mrg unsigned long size_range; 55 1.1 mrg 56 1.1 mrg if (argc > 1) 57 1.1 mrg { 58 1.1 mrg if (strcmp (argv[1], "-v") == 0) 59 1.1 mrg verbose_flag = 1; 60 1.1 mrg else 61 1.1 mrg { 62 1.1 mrg fprintf (stderr, "Invalid argument.\n"); 63 1.1 mrg return 1; 64 1.1 mrg } 65 1.1 mrg } 66 1.1 mrg 67 1.1 mrg tests_start (); 68 1.1 mrg rands = RANDS; 69 1.1 mrg 70 1.1 mrg mpz_init (bs); 71 1.1 mrg mpz_init (op1); 72 1.1 mrg mpz_init (op2); 73 1.1 mrg mpz_init (temp1); 74 1.1 mrg mpz_init (temp2); 75 1.1 mrg 76 1.1 mrg for (i = 0; i < 15; i++) 77 1.1 mrg { 78 1.1 mrg /* Generate plain operands with unknown gcd. These types of operands 79 1.1 mrg have proven to trigger certain bugs in development versions of the 80 1.1 mrg gcd code. */ 81 1.1 mrg 82 1.1 mrg mpz_urandomb (bs, rands, 32); 83 1.1 mrg size_range = mpz_get_ui (bs) % 13 + 2; 84 1.1 mrg 85 1.1 mrg mpz_urandomb (bs, rands, size_range); 86 1.1 mrg mpz_urandomb (op1, rands, mpz_get_ui (bs) + MIN_OPERAND_SIZE); 87 1.1 mrg mpz_urandomb (bs, rands, size_range); 88 1.1 mrg mpz_urandomb (op2, rands, mpz_get_ui (bs) + MIN_OPERAND_SIZE); 89 1.1 mrg 90 1.1 mrg if (mpz_cmp (op1, op2) < 0) 91 1.1 mrg mpz_swap (op1, op2); 92 1.1 mrg 93 1.1 mrg if (mpz_size (op1) > 0) 94 1.1 mrg one_test (op1, op2, i); 95 1.1 mrg 96 1.1 mrg /* Generate a division chain backwards, allowing otherwise 97 1.1 mrg unlikely huge quotients. */ 98 1.1 mrg 99 1.1 mrg mpz_set_ui (op1, 0); 100 1.1 mrg mpz_urandomb (bs, rands, 32); 101 1.1 mrg mpz_urandomb (bs, rands, mpz_get_ui (bs) % 16 + 1); 102 1.1 mrg mpz_rrandomb (op2, rands, mpz_get_ui (bs)); 103 1.1 mrg mpz_add_ui (op2, op2, 1); 104 1.1 mrg 105 1.1 mrg #if 0 106 1.1 mrg chain_len = 1000000; 107 1.1 mrg #else 108 1.1 mrg mpz_urandomb (bs, rands, 32); 109 1.1 mrg chain_len = mpz_get_ui (bs) % (GMP_NUMB_BITS * GCD_DC_THRESHOLD / 256); 110 1.1 mrg #endif 111 1.1 mrg 112 1.1 mrg for (j = 0; j < chain_len; j++) 113 1.1 mrg { 114 1.1 mrg mpz_urandomb (bs, rands, 32); 115 1.1 mrg mpz_urandomb (bs, rands, mpz_get_ui (bs) % 12 + 1); 116 1.1 mrg mpz_rrandomb (temp2, rands, mpz_get_ui (bs) + 1); 117 1.1 mrg mpz_add_ui (temp2, temp2, 1); 118 1.1 mrg mpz_mul (temp1, op2, temp2); 119 1.1 mrg mpz_add (op1, op1, temp1); 120 1.1 mrg 121 1.1 mrg /* Don't generate overly huge operands. */ 122 1.1 mrg if (SIZ (op1) > 3 * GCD_DC_THRESHOLD) 123 1.1 mrg break; 124 1.1 mrg 125 1.1 mrg mpz_urandomb (bs, rands, 32); 126 1.1 mrg mpz_urandomb (bs, rands, mpz_get_ui (bs) % 12 + 1); 127 1.1 mrg mpz_rrandomb (temp2, rands, mpz_get_ui (bs) + 1); 128 1.1 mrg mpz_add_ui (temp2, temp2, 1); 129 1.1 mrg mpz_mul (temp1, op1, temp2); 130 1.1 mrg mpz_add (op2, op2, temp1); 131 1.1 mrg 132 1.1 mrg /* Don't generate overly huge operands. */ 133 1.1 mrg if (SIZ (op2) > 3 * GCD_DC_THRESHOLD) 134 1.1 mrg break; 135 1.1 mrg } 136 1.1 mrg if (mpz_cmp (op1, op2) < 0) 137 1.1 mrg mpz_swap (op1, op2); 138 1.1 mrg 139 1.1 mrg if (mpz_size (op1) > 0) 140 1.1 mrg one_test (op1, op2, i); 141 1.1 mrg } 142 1.1 mrg 143 1.1 mrg mpz_clear (bs); 144 1.1 mrg mpz_clear (op1); 145 1.1 mrg mpz_clear (op2); 146 1.1 mrg mpz_clear (temp1); 147 1.1 mrg mpz_clear (temp2); 148 1.1 mrg 149 1.1 mrg tests_end (); 150 1.1 mrg exit (0); 151 1.1 mrg } 152 1.1 mrg 153 1.1 mrg static void 154 1.1 mrg debug_mp (mpz_t x, int base) 155 1.1 mrg { 156 1.1 mrg mpz_out_str (stderr, base, x); fputc ('\n', stderr); 157 1.1 mrg } 158 1.1 mrg 159 1.1 mrg static mp_size_t 160 1.1 mrg one_test (mpz_t a, mpz_t b, int i) 161 1.1 mrg { 162 1.1 mrg struct hgcd_matrix hgcd; 163 1.1 mrg struct hgcd_ref ref; 164 1.1 mrg 165 1.1 mrg mpz_t ref_r0; 166 1.1 mrg mpz_t ref_r1; 167 1.1 mrg mpz_t hgcd_r0; 168 1.1 mrg mpz_t hgcd_r1; 169 1.1 mrg 170 1.1 mrg int res[2]; 171 1.1 mrg mp_size_t asize; 172 1.1 mrg mp_size_t bsize; 173 1.1 mrg 174 1.1 mrg mp_size_t hgcd_init_scratch; 175 1.1 mrg mp_size_t hgcd_scratch; 176 1.1 mrg 177 1.1 mrg mp_ptr hgcd_init_tp; 178 1.1 mrg mp_ptr hgcd_tp; 179 1.1 mrg mp_limb_t marker[4]; 180 1.1 mrg 181 1.1 mrg asize = a->_mp_size; 182 1.1 mrg bsize = b->_mp_size; 183 1.1 mrg 184 1.1 mrg ASSERT (asize >= bsize); 185 1.1 mrg 186 1.1 mrg hgcd_init_scratch = MPN_HGCD_MATRIX_INIT_ITCH (asize); 187 1.1 mrg hgcd_init_tp = refmpn_malloc_limbs (hgcd_init_scratch + 2) + 1; 188 1.1 mrg mpn_hgcd_matrix_init (&hgcd, asize, hgcd_init_tp); 189 1.1 mrg 190 1.1 mrg hgcd_scratch = mpn_hgcd_appr_itch (asize); 191 1.1 mrg hgcd_tp = refmpn_malloc_limbs (hgcd_scratch + 2) + 1; 192 1.1 mrg 193 1.1 mrg mpn_random (marker, 4); 194 1.1 mrg 195 1.1 mrg hgcd_init_tp[-1] = marker[0]; 196 1.1 mrg hgcd_init_tp[hgcd_init_scratch] = marker[1]; 197 1.1 mrg hgcd_tp[-1] = marker[2]; 198 1.1 mrg hgcd_tp[hgcd_scratch] = marker[3]; 199 1.1 mrg 200 1.1 mrg #if 0 201 1.1 mrg fprintf (stderr, 202 1.1 mrg "one_test: i = %d asize = %d, bsize = %d\n", 203 1.1 mrg i, a->_mp_size, b->_mp_size); 204 1.1 mrg 205 1.1 mrg gmp_fprintf (stderr, 206 1.1 mrg "one_test: i = %d\n" 207 1.1 mrg " a = %Zx\n" 208 1.1 mrg " b = %Zx\n", 209 1.1 mrg i, a, b); 210 1.1 mrg #endif 211 1.1 mrg hgcd_ref_init (&ref); 212 1.1 mrg 213 1.1 mrg mpz_init_set (ref_r0, a); 214 1.1 mrg mpz_init_set (ref_r1, b); 215 1.1 mrg res[0] = hgcd_ref (&ref, ref_r0, ref_r1); 216 1.1 mrg 217 1.1 mrg mpz_init_set (hgcd_r0, a); 218 1.1 mrg mpz_init_set (hgcd_r1, b); 219 1.1 mrg if (bsize < asize) 220 1.1 mrg { 221 1.1 mrg _mpz_realloc (hgcd_r1, asize); 222 1.1 mrg MPN_ZERO (hgcd_r1->_mp_d + bsize, asize - bsize); 223 1.1 mrg } 224 1.1 mrg res[1] = mpn_hgcd_appr (hgcd_r0->_mp_d, 225 1.1 mrg hgcd_r1->_mp_d, 226 1.1 mrg asize, 227 1.1 mrg &hgcd, hgcd_tp); 228 1.1 mrg 229 1.1 mrg if (hgcd_init_tp[-1] != marker[0] 230 1.1 mrg || hgcd_init_tp[hgcd_init_scratch] != marker[1] 231 1.1 mrg || hgcd_tp[-1] != marker[2] 232 1.1 mrg || hgcd_tp[hgcd_scratch] != marker[3]) 233 1.1 mrg { 234 1.1 mrg fprintf (stderr, "ERROR in test %d\n", i); 235 1.1 mrg fprintf (stderr, "scratch space overwritten!\n"); 236 1.1 mrg 237 1.1 mrg if (hgcd_init_tp[-1] != marker[0]) 238 1.1 mrg gmp_fprintf (stderr, 239 1.1 mrg "before init_tp: %Mx\n" 240 1.1 mrg "expected: %Mx\n", 241 1.1 mrg hgcd_init_tp[-1], marker[0]); 242 1.1 mrg if (hgcd_init_tp[hgcd_init_scratch] != marker[1]) 243 1.1 mrg gmp_fprintf (stderr, 244 1.1 mrg "after init_tp: %Mx\n" 245 1.1 mrg "expected: %Mx\n", 246 1.1 mrg hgcd_init_tp[hgcd_init_scratch], marker[1]); 247 1.1 mrg if (hgcd_tp[-1] != marker[2]) 248 1.1 mrg gmp_fprintf (stderr, 249 1.1 mrg "before tp: %Mx\n" 250 1.1 mrg "expected: %Mx\n", 251 1.1 mrg hgcd_tp[-1], marker[2]); 252 1.1 mrg if (hgcd_tp[hgcd_scratch] != marker[3]) 253 1.1 mrg gmp_fprintf (stderr, 254 1.1 mrg "after tp: %Mx\n" 255 1.1 mrg "expected: %Mx\n", 256 1.1 mrg hgcd_tp[hgcd_scratch], marker[3]); 257 1.1 mrg 258 1.1 mrg abort (); 259 1.1 mrg } 260 1.1 mrg 261 1.1 mrg if (!hgcd_appr_valid_p (a, b, res[0], &ref, ref_r0, ref_r1, 262 1.1 mrg res[1], &hgcd)) 263 1.1 mrg { 264 1.1 mrg fprintf (stderr, "ERROR in test %d\n", i); 265 1.1 mrg fprintf (stderr, "Invalid results for hgcd and hgcd_ref\n"); 266 1.1 mrg fprintf (stderr, "op1="); debug_mp (a, -16); 267 1.1 mrg fprintf (stderr, "op2="); debug_mp (b, -16); 268 1.1 mrg fprintf (stderr, "hgcd_ref: %ld\n", (long) res[0]); 269 1.1 mrg fprintf (stderr, "mpn_hgcd_appr: %ld\n", (long) res[1]); 270 1.1 mrg abort (); 271 1.1 mrg } 272 1.1 mrg 273 1.1 mrg refmpn_free_limbs (hgcd_init_tp - 1); 274 1.1 mrg refmpn_free_limbs (hgcd_tp - 1); 275 1.1 mrg hgcd_ref_clear (&ref); 276 1.1 mrg mpz_clear (ref_r0); 277 1.1 mrg mpz_clear (ref_r1); 278 1.1 mrg mpz_clear (hgcd_r0); 279 1.1 mrg mpz_clear (hgcd_r1); 280 1.1 mrg 281 1.1 mrg return res[0]; 282 1.1 mrg } 283 1.1 mrg 284 1.1 mrg static void 285 1.1 mrg hgcd_ref_init (struct hgcd_ref *hgcd) 286 1.1 mrg { 287 1.1 mrg unsigned i; 288 1.1 mrg for (i = 0; i<2; i++) 289 1.1 mrg { 290 1.1 mrg unsigned j; 291 1.1 mrg for (j = 0; j<2; j++) 292 1.1 mrg mpz_init (hgcd->m[i][j]); 293 1.1 mrg } 294 1.1 mrg } 295 1.1 mrg 296 1.1 mrg static void 297 1.1 mrg hgcd_ref_clear (struct hgcd_ref *hgcd) 298 1.1 mrg { 299 1.1 mrg unsigned i; 300 1.1 mrg for (i = 0; i<2; i++) 301 1.1 mrg { 302 1.1 mrg unsigned j; 303 1.1 mrg for (j = 0; j<2; j++) 304 1.1 mrg mpz_clear (hgcd->m[i][j]); 305 1.1 mrg } 306 1.1 mrg } 307 1.1 mrg 308 1.1 mrg static int 309 1.1 mrg sdiv_qr (mpz_t q, mpz_t r, mp_size_t s, const mpz_t a, const mpz_t b) 310 1.1 mrg { 311 1.1 mrg mpz_fdiv_qr (q, r, a, b); 312 1.1 mrg if (mpz_size (r) <= s) 313 1.1 mrg { 314 1.1 mrg mpz_add (r, r, b); 315 1.1 mrg mpz_sub_ui (q, q, 1); 316 1.1 mrg } 317 1.1 mrg 318 1.1 mrg return (mpz_sgn (q) > 0); 319 1.1 mrg } 320 1.1 mrg 321 1.1 mrg static int 322 1.1 mrg hgcd_ref (struct hgcd_ref *hgcd, mpz_t a, mpz_t b) 323 1.1 mrg { 324 1.1 mrg mp_size_t n = MAX (mpz_size (a), mpz_size (b)); 325 1.1 mrg mp_size_t s = n/2 + 1; 326 1.1 mrg mpz_t q; 327 1.1 mrg int res; 328 1.1 mrg 329 1.1 mrg if (mpz_size (a) <= s || mpz_size (b) <= s) 330 1.1 mrg return 0; 331 1.1 mrg 332 1.1 mrg res = mpz_cmp (a, b); 333 1.1 mrg if (res < 0) 334 1.1 mrg { 335 1.1 mrg mpz_sub (b, b, a); 336 1.1 mrg if (mpz_size (b) <= s) 337 1.1 mrg return 0; 338 1.1 mrg 339 1.1 mrg mpz_set_ui (hgcd->m[0][0], 1); mpz_set_ui (hgcd->m[0][1], 0); 340 1.1 mrg mpz_set_ui (hgcd->m[1][0], 1); mpz_set_ui (hgcd->m[1][1], 1); 341 1.1 mrg } 342 1.1 mrg else if (res > 0) 343 1.1 mrg { 344 1.1 mrg mpz_sub (a, a, b); 345 1.1 mrg if (mpz_size (a) <= s) 346 1.1 mrg return 0; 347 1.1 mrg 348 1.1 mrg mpz_set_ui (hgcd->m[0][0], 1); mpz_set_ui (hgcd->m[0][1], 1); 349 1.1 mrg mpz_set_ui (hgcd->m[1][0], 0); mpz_set_ui (hgcd->m[1][1], 1); 350 1.1 mrg } 351 1.1 mrg else 352 1.1 mrg return 0; 353 1.1 mrg 354 1.1 mrg mpz_init (q); 355 1.1 mrg 356 1.1 mrg for (;;) 357 1.1 mrg { 358 1.1 mrg ASSERT (mpz_size (a) > s); 359 1.1 mrg ASSERT (mpz_size (b) > s); 360 1.1 mrg 361 1.1 mrg if (mpz_cmp (a, b) > 0) 362 1.1 mrg { 363 1.1 mrg if (!sdiv_qr (q, a, s, a, b)) 364 1.1 mrg break; 365 1.1 mrg mpz_addmul (hgcd->m[0][1], q, hgcd->m[0][0]); 366 1.1 mrg mpz_addmul (hgcd->m[1][1], q, hgcd->m[1][0]); 367 1.1 mrg } 368 1.1 mrg else 369 1.1 mrg { 370 1.1 mrg if (!sdiv_qr (q, b, s, b, a)) 371 1.1 mrg break; 372 1.1 mrg mpz_addmul (hgcd->m[0][0], q, hgcd->m[0][1]); 373 1.1 mrg mpz_addmul (hgcd->m[1][0], q, hgcd->m[1][1]); 374 1.1 mrg } 375 1.1 mrg } 376 1.1 mrg 377 1.1 mrg mpz_clear (q); 378 1.1 mrg 379 1.1 mrg return 1; 380 1.1 mrg } 381 1.1 mrg 382 1.1 mrg static int 383 1.1 mrg hgcd_ref_equal (const struct hgcd_ref *A, const struct hgcd_ref *B) 384 1.1 mrg { 385 1.1 mrg unsigned i; 386 1.1 mrg 387 1.1 mrg for (i = 0; i<2; i++) 388 1.1 mrg { 389 1.1 mrg unsigned j; 390 1.1 mrg 391 1.1 mrg for (j = 0; j<2; j++) 392 1.1 mrg if (mpz_cmp (A->m[i][j], B->m[i][j]) != 0) 393 1.1 mrg return 0; 394 1.1 mrg } 395 1.1 mrg 396 1.1 mrg return 1; 397 1.1 mrg } 398 1.1 mrg 399 1.1 mrg static int 400 1.1 mrg hgcd_appr_valid_p (mpz_t a, mpz_t b, mp_size_t res0, 401 1.1 mrg struct hgcd_ref *ref, mpz_t ref_r0, mpz_t ref_r1, 402 1.1 mrg mp_size_t res1, struct hgcd_matrix *hgcd) 403 1.1 mrg { 404 1.1 mrg mp_size_t n = MAX (mpz_size (a), mpz_size (b)); 405 1.1 mrg mp_size_t s = n/2 + 1; 406 1.1 mrg 407 1.1 mrg mp_bitcnt_t dbits, abits, margin; 408 1.1 mrg mpz_t appr_r0, appr_r1, t, q; 409 1.1 mrg struct hgcd_ref appr; 410 1.1 mrg 411 1.1 mrg if (!res0) 412 1.1 mrg { 413 1.1 mrg if (!res1) 414 1.1 mrg return 1; 415 1.1 mrg 416 1.1 mrg fprintf (stderr, "mpn_hgcd_appr returned 1 when no reduction possible.\n"); 417 1.1 mrg return 0; 418 1.1 mrg } 419 1.1 mrg 420 1.1 mrg /* NOTE: No *_clear calls on error return, since we're going to 421 1.1 mrg abort anyway. */ 422 1.1 mrg mpz_init (t); 423 1.1 mrg mpz_init (q); 424 1.1 mrg hgcd_ref_init (&appr); 425 1.1 mrg mpz_init (appr_r0); 426 1.1 mrg mpz_init (appr_r1); 427 1.1 mrg 428 1.1 mrg if (mpz_size (ref_r0) <= s) 429 1.1 mrg { 430 1.1 mrg fprintf (stderr, "ref_r0 too small!!!: "); debug_mp (ref_r0, 16); 431 1.1 mrg return 0; 432 1.1 mrg } 433 1.1 mrg if (mpz_size (ref_r1) <= s) 434 1.1 mrg { 435 1.1 mrg fprintf (stderr, "ref_r1 too small!!!: "); debug_mp (ref_r1, 16); 436 1.1 mrg return 0; 437 1.1 mrg } 438 1.1 mrg 439 1.1 mrg mpz_sub (t, ref_r0, ref_r1); 440 1.1 mrg dbits = mpz_sizeinbase (t, 2); 441 1.1 mrg if (dbits > s*GMP_NUMB_BITS) 442 1.1 mrg { 443 1.1 mrg fprintf (stderr, "ref |r0 - r1| too large!!!: "); debug_mp (t, 16); 444 1.1 mrg return 0; 445 1.1 mrg } 446 1.1 mrg 447 1.1 mrg if (!res1) 448 1.1 mrg { 449 1.1 mrg mpz_set (appr_r0, a); 450 1.1 mrg mpz_set (appr_r1, b); 451 1.1 mrg } 452 1.1 mrg else 453 1.1 mrg { 454 1.1 mrg unsigned i; 455 1.1 mrg 456 1.1 mrg for (i = 0; i<2; i++) 457 1.1 mrg { 458 1.1 mrg unsigned j; 459 1.1 mrg 460 1.1 mrg for (j = 0; j<2; j++) 461 1.1 mrg { 462 1.1 mrg mp_size_t mn = hgcd->n; 463 1.1 mrg MPN_NORMALIZE (hgcd->p[i][j], mn); 464 1.1 mrg mpz_realloc (appr.m[i][j], mn); 465 1.1 mrg MPN_COPY (PTR (appr.m[i][j]), hgcd->p[i][j], mn); 466 1.1 mrg SIZ (appr.m[i][j]) = mn; 467 1.1 mrg } 468 1.1 mrg } 469 1.1 mrg mpz_mul (appr_r0, appr.m[1][1], a); 470 1.1 mrg mpz_mul (t, appr.m[0][1], b); 471 1.1 mrg mpz_sub (appr_r0, appr_r0, t); 472 1.1 mrg if (mpz_sgn (appr_r0) <= 0 473 1.1 mrg || mpz_size (appr_r0) <= s) 474 1.1 mrg { 475 1.1 mrg fprintf (stderr, "appr_r0 too small: "); debug_mp (appr_r0, 16); 476 1.1 mrg return 0; 477 1.1 mrg } 478 1.1 mrg 479 1.1 mrg mpz_mul (appr_r1, appr.m[1][0], a); 480 1.1 mrg mpz_mul (t, appr.m[0][0], b); 481 1.1 mrg mpz_sub (appr_r1, t, appr_r1); 482 1.1 mrg if (mpz_sgn (appr_r1) <= 0 483 1.1 mrg || mpz_size (appr_r1) <= s) 484 1.1 mrg { 485 1.1 mrg fprintf (stderr, "appr_r1 too small: "); debug_mp (appr_r1, 16); 486 1.1 mrg return 0; 487 1.1 mrg } 488 1.1 mrg } 489 1.1 mrg 490 1.1 mrg mpz_sub (t, appr_r0, appr_r1); 491 1.1 mrg abits = mpz_sizeinbase (t, 2); 492 1.1 mrg if (abits < dbits) 493 1.1 mrg { 494 1.1 mrg fprintf (stderr, "|r0 - r1| too small: "); debug_mp (t, 16); 495 1.1 mrg return 0; 496 1.1 mrg } 497 1.1 mrg 498 1.1 mrg /* We lose one bit each time we discard the least significant limbs. 499 1.1 mrg For the lehmer code, that can happen at most s * (GMP_NUMB_BITS) 500 1.1 mrg / (GMP_NUMB_BITS - 1) times. For the dc code, we lose an entire 501 1.1 mrg limb (or more?) for each level of recursion. */ 502 1.1 mrg 503 1.1 mrg margin = (n/2+1) * GMP_NUMB_BITS / (GMP_NUMB_BITS - 1); 504 1.1 mrg { 505 1.1 mrg mp_size_t rn; 506 1.1 mrg for (rn = n; ABOVE_THRESHOLD (rn, HGCD_APPR_THRESHOLD); rn = (rn + 1)/2) 507 1.1 mrg margin += GMP_NUMB_BITS; 508 1.1 mrg } 509 1.1 mrg 510 1.1 mrg if (verbose_flag && abits > dbits) 511 1.1 mrg fprintf (stderr, "n = %u: sbits = %u: ref #(r0-r1): %u, appr #(r0-r1): %u excess: %d, margin: %u\n", 512 1.1 mrg (unsigned) n, (unsigned) s*GMP_NUMB_BITS, 513 1.1 mrg (unsigned) dbits, (unsigned) abits, 514 1.1.1.2 mrg (int) (abits - s * GMP_NUMB_BITS), (unsigned) margin); 515 1.1 mrg 516 1.1 mrg if (abits > s*GMP_NUMB_BITS + margin) 517 1.1 mrg { 518 1.1 mrg fprintf (stderr, "appr |r0 - r1| much larger than minimal (by %u bits, margin = %u bits)\n", 519 1.1 mrg (unsigned) (abits - s*GMP_NUMB_BITS), (unsigned) margin); 520 1.1 mrg return 0; 521 1.1 mrg } 522 1.1 mrg 523 1.1 mrg while (mpz_cmp (appr_r0, ref_r0) > 0 || mpz_cmp (appr_r1, ref_r1) > 0) 524 1.1 mrg { 525 1.1 mrg ASSERT (mpz_size (appr_r0) > s); 526 1.1 mrg ASSERT (mpz_size (appr_r1) > s); 527 1.1 mrg 528 1.1 mrg if (mpz_cmp (appr_r0, appr_r1) > 0) 529 1.1 mrg { 530 1.1 mrg if (!sdiv_qr (q, appr_r0, s, appr_r0, appr_r1)) 531 1.1 mrg break; 532 1.1 mrg mpz_addmul (appr.m[0][1], q, appr.m[0][0]); 533 1.1 mrg mpz_addmul (appr.m[1][1], q, appr.m[1][0]); 534 1.1 mrg } 535 1.1 mrg else 536 1.1 mrg { 537 1.1 mrg if (!sdiv_qr (q, appr_r1, s, appr_r1, appr_r0)) 538 1.1 mrg break; 539 1.1 mrg mpz_addmul (appr.m[0][0], q, appr.m[0][1]); 540 1.1 mrg mpz_addmul (appr.m[1][0], q, appr.m[1][1]); 541 1.1 mrg } 542 1.1 mrg } 543 1.1 mrg 544 1.1 mrg if (mpz_cmp (appr_r0, ref_r0) != 0 545 1.1 mrg || mpz_cmp (appr_r1, ref_r1) != 0 546 1.1 mrg || !hgcd_ref_equal (ref, &appr)) 547 1.1 mrg { 548 1.1 mrg fprintf (stderr, "appr_r0: "); debug_mp (appr_r0, 16); 549 1.1 mrg fprintf (stderr, "ref_r0: "); debug_mp (ref_r0, 16); 550 1.1 mrg 551 1.1 mrg fprintf (stderr, "appr_r1: "); debug_mp (appr_r1, 16); 552 1.1 mrg fprintf (stderr, "ref_r1: "); debug_mp (ref_r1, 16); 553 1.1 mrg 554 1.1 mrg return 0; 555 1.1 mrg } 556 1.1 mrg mpz_clear (t); 557 1.1 mrg mpz_clear (q); 558 1.1 mrg hgcd_ref_clear (&appr); 559 1.1 mrg mpz_clear (appr_r0); 560 1.1 mrg mpz_clear (appr_r1); 561 1.1 mrg 562 1.1 mrg return 1; 563 1.1 mrg } 564