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