t-hgcd_appr.c revision 1.1 1 1.1 mrg /* Test mpn_hgcd_appr.
2 1.1 mrg
3 1.1 mrg Copyright 1991, 1993, 1994, 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2011 Free
4 1.1 mrg Software 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 mrg the GNU MP Library test suite. If not, see http://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 int
161 1.1 mrg mpz_mpn_equal (const mpz_t a, mp_srcptr bp, mp_size_t bsize);
162 1.1 mrg
163 1.1 mrg static mp_size_t
164 1.1 mrg one_test (mpz_t a, mpz_t b, int i)
165 1.1 mrg {
166 1.1 mrg struct hgcd_matrix hgcd;
167 1.1 mrg struct hgcd_ref ref;
168 1.1 mrg
169 1.1 mrg mpz_t ref_r0;
170 1.1 mrg mpz_t ref_r1;
171 1.1 mrg mpz_t hgcd_r0;
172 1.1 mrg mpz_t hgcd_r1;
173 1.1 mrg
174 1.1 mrg int res[2];
175 1.1 mrg mp_size_t asize;
176 1.1 mrg mp_size_t bsize;
177 1.1 mrg
178 1.1 mrg mp_size_t hgcd_init_scratch;
179 1.1 mrg mp_size_t hgcd_scratch;
180 1.1 mrg
181 1.1 mrg mp_ptr hgcd_init_tp;
182 1.1 mrg mp_ptr hgcd_tp;
183 1.1 mrg mp_limb_t marker[4];
184 1.1 mrg
185 1.1 mrg asize = a->_mp_size;
186 1.1 mrg bsize = b->_mp_size;
187 1.1 mrg
188 1.1 mrg ASSERT (asize >= bsize);
189 1.1 mrg
190 1.1 mrg hgcd_init_scratch = MPN_HGCD_MATRIX_INIT_ITCH (asize);
191 1.1 mrg hgcd_init_tp = refmpn_malloc_limbs (hgcd_init_scratch + 2) + 1;
192 1.1 mrg mpn_hgcd_matrix_init (&hgcd, asize, hgcd_init_tp);
193 1.1 mrg
194 1.1 mrg hgcd_scratch = mpn_hgcd_appr_itch (asize);
195 1.1 mrg hgcd_tp = refmpn_malloc_limbs (hgcd_scratch + 2) + 1;
196 1.1 mrg
197 1.1 mrg mpn_random (marker, 4);
198 1.1 mrg
199 1.1 mrg hgcd_init_tp[-1] = marker[0];
200 1.1 mrg hgcd_init_tp[hgcd_init_scratch] = marker[1];
201 1.1 mrg hgcd_tp[-1] = marker[2];
202 1.1 mrg hgcd_tp[hgcd_scratch] = marker[3];
203 1.1 mrg
204 1.1 mrg #if 0
205 1.1 mrg fprintf (stderr,
206 1.1 mrg "one_test: i = %d asize = %d, bsize = %d\n",
207 1.1 mrg i, a->_mp_size, b->_mp_size);
208 1.1 mrg
209 1.1 mrg gmp_fprintf (stderr,
210 1.1 mrg "one_test: i = %d\n"
211 1.1 mrg " a = %Zx\n"
212 1.1 mrg " b = %Zx\n",
213 1.1 mrg i, a, b);
214 1.1 mrg #endif
215 1.1 mrg hgcd_ref_init (&ref);
216 1.1 mrg
217 1.1 mrg mpz_init_set (ref_r0, a);
218 1.1 mrg mpz_init_set (ref_r1, b);
219 1.1 mrg res[0] = hgcd_ref (&ref, ref_r0, ref_r1);
220 1.1 mrg
221 1.1 mrg mpz_init_set (hgcd_r0, a);
222 1.1 mrg mpz_init_set (hgcd_r1, b);
223 1.1 mrg if (bsize < asize)
224 1.1 mrg {
225 1.1 mrg _mpz_realloc (hgcd_r1, asize);
226 1.1 mrg MPN_ZERO (hgcd_r1->_mp_d + bsize, asize - bsize);
227 1.1 mrg }
228 1.1 mrg res[1] = mpn_hgcd_appr (hgcd_r0->_mp_d,
229 1.1 mrg hgcd_r1->_mp_d,
230 1.1 mrg asize,
231 1.1 mrg &hgcd, hgcd_tp);
232 1.1 mrg
233 1.1 mrg if (hgcd_init_tp[-1] != marker[0]
234 1.1 mrg || hgcd_init_tp[hgcd_init_scratch] != marker[1]
235 1.1 mrg || hgcd_tp[-1] != marker[2]
236 1.1 mrg || hgcd_tp[hgcd_scratch] != marker[3])
237 1.1 mrg {
238 1.1 mrg fprintf (stderr, "ERROR in test %d\n", i);
239 1.1 mrg fprintf (stderr, "scratch space overwritten!\n");
240 1.1 mrg
241 1.1 mrg if (hgcd_init_tp[-1] != marker[0])
242 1.1 mrg gmp_fprintf (stderr,
243 1.1 mrg "before init_tp: %Mx\n"
244 1.1 mrg "expected: %Mx\n",
245 1.1 mrg hgcd_init_tp[-1], marker[0]);
246 1.1 mrg if (hgcd_init_tp[hgcd_init_scratch] != marker[1])
247 1.1 mrg gmp_fprintf (stderr,
248 1.1 mrg "after init_tp: %Mx\n"
249 1.1 mrg "expected: %Mx\n",
250 1.1 mrg hgcd_init_tp[hgcd_init_scratch], marker[1]);
251 1.1 mrg if (hgcd_tp[-1] != marker[2])
252 1.1 mrg gmp_fprintf (stderr,
253 1.1 mrg "before tp: %Mx\n"
254 1.1 mrg "expected: %Mx\n",
255 1.1 mrg hgcd_tp[-1], marker[2]);
256 1.1 mrg if (hgcd_tp[hgcd_scratch] != marker[3])
257 1.1 mrg gmp_fprintf (stderr,
258 1.1 mrg "after tp: %Mx\n"
259 1.1 mrg "expected: %Mx\n",
260 1.1 mrg hgcd_tp[hgcd_scratch], marker[3]);
261 1.1 mrg
262 1.1 mrg abort ();
263 1.1 mrg }
264 1.1 mrg
265 1.1 mrg if (!hgcd_appr_valid_p (a, b, res[0], &ref, ref_r0, ref_r1,
266 1.1 mrg res[1], &hgcd))
267 1.1 mrg {
268 1.1 mrg fprintf (stderr, "ERROR in test %d\n", i);
269 1.1 mrg fprintf (stderr, "Invalid results for hgcd and hgcd_ref\n");
270 1.1 mrg fprintf (stderr, "op1="); debug_mp (a, -16);
271 1.1 mrg fprintf (stderr, "op2="); debug_mp (b, -16);
272 1.1 mrg fprintf (stderr, "hgcd_ref: %ld\n", (long) res[0]);
273 1.1 mrg fprintf (stderr, "mpn_hgcd_appr: %ld\n", (long) res[1]);
274 1.1 mrg abort ();
275 1.1 mrg }
276 1.1 mrg
277 1.1 mrg refmpn_free_limbs (hgcd_init_tp - 1);
278 1.1 mrg refmpn_free_limbs (hgcd_tp - 1);
279 1.1 mrg hgcd_ref_clear (&ref);
280 1.1 mrg mpz_clear (ref_r0);
281 1.1 mrg mpz_clear (ref_r1);
282 1.1 mrg mpz_clear (hgcd_r0);
283 1.1 mrg mpz_clear (hgcd_r1);
284 1.1 mrg
285 1.1 mrg return res[0];
286 1.1 mrg }
287 1.1 mrg
288 1.1 mrg static void
289 1.1 mrg hgcd_ref_init (struct hgcd_ref *hgcd)
290 1.1 mrg {
291 1.1 mrg unsigned i;
292 1.1 mrg for (i = 0; i<2; i++)
293 1.1 mrg {
294 1.1 mrg unsigned j;
295 1.1 mrg for (j = 0; j<2; j++)
296 1.1 mrg mpz_init (hgcd->m[i][j]);
297 1.1 mrg }
298 1.1 mrg }
299 1.1 mrg
300 1.1 mrg static void
301 1.1 mrg hgcd_ref_clear (struct hgcd_ref *hgcd)
302 1.1 mrg {
303 1.1 mrg unsigned i;
304 1.1 mrg for (i = 0; i<2; i++)
305 1.1 mrg {
306 1.1 mrg unsigned j;
307 1.1 mrg for (j = 0; j<2; j++)
308 1.1 mrg mpz_clear (hgcd->m[i][j]);
309 1.1 mrg }
310 1.1 mrg }
311 1.1 mrg
312 1.1 mrg static int
313 1.1 mrg sdiv_qr (mpz_t q, mpz_t r, mp_size_t s, const mpz_t a, const mpz_t b)
314 1.1 mrg {
315 1.1 mrg mpz_fdiv_qr (q, r, a, b);
316 1.1 mrg if (mpz_size (r) <= s)
317 1.1 mrg {
318 1.1 mrg mpz_add (r, r, b);
319 1.1 mrg mpz_sub_ui (q, q, 1);
320 1.1 mrg }
321 1.1 mrg
322 1.1 mrg return (mpz_sgn (q) > 0);
323 1.1 mrg }
324 1.1 mrg
325 1.1 mrg static int
326 1.1 mrg hgcd_ref (struct hgcd_ref *hgcd, mpz_t a, mpz_t b)
327 1.1 mrg {
328 1.1 mrg mp_size_t n = MAX (mpz_size (a), mpz_size (b));
329 1.1 mrg mp_size_t s = n/2 + 1;
330 1.1 mrg mpz_t q;
331 1.1 mrg int res;
332 1.1 mrg
333 1.1 mrg if (mpz_size (a) <= s || mpz_size (b) <= s)
334 1.1 mrg return 0;
335 1.1 mrg
336 1.1 mrg res = mpz_cmp (a, b);
337 1.1 mrg if (res < 0)
338 1.1 mrg {
339 1.1 mrg mpz_sub (b, b, a);
340 1.1 mrg if (mpz_size (b) <= s)
341 1.1 mrg return 0;
342 1.1 mrg
343 1.1 mrg mpz_set_ui (hgcd->m[0][0], 1); mpz_set_ui (hgcd->m[0][1], 0);
344 1.1 mrg mpz_set_ui (hgcd->m[1][0], 1); mpz_set_ui (hgcd->m[1][1], 1);
345 1.1 mrg }
346 1.1 mrg else if (res > 0)
347 1.1 mrg {
348 1.1 mrg mpz_sub (a, a, b);
349 1.1 mrg if (mpz_size (a) <= s)
350 1.1 mrg return 0;
351 1.1 mrg
352 1.1 mrg mpz_set_ui (hgcd->m[0][0], 1); mpz_set_ui (hgcd->m[0][1], 1);
353 1.1 mrg mpz_set_ui (hgcd->m[1][0], 0); mpz_set_ui (hgcd->m[1][1], 1);
354 1.1 mrg }
355 1.1 mrg else
356 1.1 mrg return 0;
357 1.1 mrg
358 1.1 mrg mpz_init (q);
359 1.1 mrg
360 1.1 mrg for (;;)
361 1.1 mrg {
362 1.1 mrg ASSERT (mpz_size (a) > s);
363 1.1 mrg ASSERT (mpz_size (b) > s);
364 1.1 mrg
365 1.1 mrg if (mpz_cmp (a, b) > 0)
366 1.1 mrg {
367 1.1 mrg if (!sdiv_qr (q, a, s, a, b))
368 1.1 mrg break;
369 1.1 mrg mpz_addmul (hgcd->m[0][1], q, hgcd->m[0][0]);
370 1.1 mrg mpz_addmul (hgcd->m[1][1], q, hgcd->m[1][0]);
371 1.1 mrg }
372 1.1 mrg else
373 1.1 mrg {
374 1.1 mrg if (!sdiv_qr (q, b, s, b, a))
375 1.1 mrg break;
376 1.1 mrg mpz_addmul (hgcd->m[0][0], q, hgcd->m[0][1]);
377 1.1 mrg mpz_addmul (hgcd->m[1][0], q, hgcd->m[1][1]);
378 1.1 mrg }
379 1.1 mrg }
380 1.1 mrg
381 1.1 mrg mpz_clear (q);
382 1.1 mrg
383 1.1 mrg return 1;
384 1.1 mrg }
385 1.1 mrg
386 1.1 mrg static int
387 1.1 mrg mpz_mpn_equal (const mpz_t a, mp_srcptr bp, mp_size_t bsize)
388 1.1 mrg {
389 1.1 mrg mp_srcptr ap = a->_mp_d;
390 1.1 mrg mp_size_t asize = a->_mp_size;
391 1.1 mrg
392 1.1 mrg MPN_NORMALIZE (bp, bsize);
393 1.1 mrg return asize == bsize && mpn_cmp (ap, bp, asize) == 0;
394 1.1 mrg }
395 1.1 mrg
396 1.1 mrg static int
397 1.1 mrg hgcd_ref_equal (const struct hgcd_ref *A, const struct hgcd_ref *B)
398 1.1 mrg {
399 1.1 mrg unsigned i;
400 1.1 mrg
401 1.1 mrg for (i = 0; i<2; i++)
402 1.1 mrg {
403 1.1 mrg unsigned j;
404 1.1 mrg
405 1.1 mrg for (j = 0; j<2; j++)
406 1.1 mrg if (mpz_cmp (A->m[i][j], B->m[i][j]) != 0)
407 1.1 mrg return 0;
408 1.1 mrg }
409 1.1 mrg
410 1.1 mrg return 1;
411 1.1 mrg }
412 1.1 mrg
413 1.1 mrg static int
414 1.1 mrg hgcd_appr_valid_p (mpz_t a, mpz_t b, mp_size_t res0,
415 1.1 mrg struct hgcd_ref *ref, mpz_t ref_r0, mpz_t ref_r1,
416 1.1 mrg mp_size_t res1, struct hgcd_matrix *hgcd)
417 1.1 mrg {
418 1.1 mrg mp_size_t n = MAX (mpz_size (a), mpz_size (b));
419 1.1 mrg mp_size_t s = n/2 + 1;
420 1.1 mrg
421 1.1 mrg mp_bitcnt_t dbits, abits, margin;
422 1.1 mrg mpz_t appr_r0, appr_r1, t, q;
423 1.1 mrg struct hgcd_ref appr;
424 1.1 mrg
425 1.1 mrg if (!res0)
426 1.1 mrg {
427 1.1 mrg if (!res1)
428 1.1 mrg return 1;
429 1.1 mrg
430 1.1 mrg fprintf (stderr, "mpn_hgcd_appr returned 1 when no reduction possible.\n");
431 1.1 mrg return 0;
432 1.1 mrg }
433 1.1 mrg
434 1.1 mrg /* NOTE: No *_clear calls on error return, since we're going to
435 1.1 mrg abort anyway. */
436 1.1 mrg mpz_init (t);
437 1.1 mrg mpz_init (q);
438 1.1 mrg hgcd_ref_init (&appr);
439 1.1 mrg mpz_init (appr_r0);
440 1.1 mrg mpz_init (appr_r1);
441 1.1 mrg
442 1.1 mrg if (mpz_size (ref_r0) <= s)
443 1.1 mrg {
444 1.1 mrg fprintf (stderr, "ref_r0 too small!!!: "); debug_mp (ref_r0, 16);
445 1.1 mrg return 0;
446 1.1 mrg }
447 1.1 mrg if (mpz_size (ref_r1) <= s)
448 1.1 mrg {
449 1.1 mrg fprintf (stderr, "ref_r1 too small!!!: "); debug_mp (ref_r1, 16);
450 1.1 mrg return 0;
451 1.1 mrg }
452 1.1 mrg
453 1.1 mrg mpz_sub (t, ref_r0, ref_r1);
454 1.1 mrg dbits = mpz_sizeinbase (t, 2);
455 1.1 mrg if (dbits > s*GMP_NUMB_BITS)
456 1.1 mrg {
457 1.1 mrg fprintf (stderr, "ref |r0 - r1| too large!!!: "); debug_mp (t, 16);
458 1.1 mrg return 0;
459 1.1 mrg }
460 1.1 mrg
461 1.1 mrg if (!res1)
462 1.1 mrg {
463 1.1 mrg mpz_set (appr_r0, a);
464 1.1 mrg mpz_set (appr_r1, b);
465 1.1 mrg }
466 1.1 mrg else
467 1.1 mrg {
468 1.1 mrg unsigned i;
469 1.1 mrg
470 1.1 mrg for (i = 0; i<2; i++)
471 1.1 mrg {
472 1.1 mrg unsigned j;
473 1.1 mrg
474 1.1 mrg for (j = 0; j<2; j++)
475 1.1 mrg {
476 1.1 mrg mp_size_t mn = hgcd->n;
477 1.1 mrg MPN_NORMALIZE (hgcd->p[i][j], mn);
478 1.1 mrg mpz_realloc (appr.m[i][j], mn);
479 1.1 mrg MPN_COPY (PTR (appr.m[i][j]), hgcd->p[i][j], mn);
480 1.1 mrg SIZ (appr.m[i][j]) = mn;
481 1.1 mrg }
482 1.1 mrg }
483 1.1 mrg mpz_mul (appr_r0, appr.m[1][1], a);
484 1.1 mrg mpz_mul (t, appr.m[0][1], b);
485 1.1 mrg mpz_sub (appr_r0, appr_r0, t);
486 1.1 mrg if (mpz_sgn (appr_r0) <= 0
487 1.1 mrg || mpz_size (appr_r0) <= s)
488 1.1 mrg {
489 1.1 mrg fprintf (stderr, "appr_r0 too small: "); debug_mp (appr_r0, 16);
490 1.1 mrg return 0;
491 1.1 mrg }
492 1.1 mrg
493 1.1 mrg mpz_mul (appr_r1, appr.m[1][0], a);
494 1.1 mrg mpz_mul (t, appr.m[0][0], b);
495 1.1 mrg mpz_sub (appr_r1, t, appr_r1);
496 1.1 mrg if (mpz_sgn (appr_r1) <= 0
497 1.1 mrg || mpz_size (appr_r1) <= s)
498 1.1 mrg {
499 1.1 mrg fprintf (stderr, "appr_r1 too small: "); debug_mp (appr_r1, 16);
500 1.1 mrg return 0;
501 1.1 mrg }
502 1.1 mrg }
503 1.1 mrg
504 1.1 mrg mpz_sub (t, appr_r0, appr_r1);
505 1.1 mrg abits = mpz_sizeinbase (t, 2);
506 1.1 mrg if (abits < dbits)
507 1.1 mrg {
508 1.1 mrg fprintf (stderr, "|r0 - r1| too small: "); debug_mp (t, 16);
509 1.1 mrg return 0;
510 1.1 mrg }
511 1.1 mrg
512 1.1 mrg /* We lose one bit each time we discard the least significant limbs.
513 1.1 mrg For the lehmer code, that can happen at most s * (GMP_NUMB_BITS)
514 1.1 mrg / (GMP_NUMB_BITS - 1) times. For the dc code, we lose an entire
515 1.1 mrg limb (or more?) for each level of recursion. */
516 1.1 mrg
517 1.1 mrg margin = (n/2+1) * GMP_NUMB_BITS / (GMP_NUMB_BITS - 1);
518 1.1 mrg {
519 1.1 mrg mp_size_t rn;
520 1.1 mrg for (rn = n; ABOVE_THRESHOLD (rn, HGCD_APPR_THRESHOLD); rn = (rn + 1)/2)
521 1.1 mrg margin += GMP_NUMB_BITS;
522 1.1 mrg }
523 1.1 mrg
524 1.1 mrg if (verbose_flag && abits > dbits)
525 1.1 mrg fprintf (stderr, "n = %u: sbits = %u: ref #(r0-r1): %u, appr #(r0-r1): %u excess: %d, margin: %u\n",
526 1.1 mrg (unsigned) n, (unsigned) s*GMP_NUMB_BITS,
527 1.1 mrg (unsigned) dbits, (unsigned) abits,
528 1.1 mrg (int) abits - s * GMP_NUMB_BITS, (unsigned) margin);
529 1.1 mrg
530 1.1 mrg if (abits > s*GMP_NUMB_BITS + margin)
531 1.1 mrg {
532 1.1 mrg fprintf (stderr, "appr |r0 - r1| much larger than minimal (by %u bits, margin = %u bits)\n",
533 1.1 mrg (unsigned) (abits - s*GMP_NUMB_BITS), (unsigned) margin);
534 1.1 mrg return 0;
535 1.1 mrg }
536 1.1 mrg
537 1.1 mrg while (mpz_cmp (appr_r0, ref_r0) > 0 || mpz_cmp (appr_r1, ref_r1) > 0)
538 1.1 mrg {
539 1.1 mrg ASSERT (mpz_size (appr_r0) > s);
540 1.1 mrg ASSERT (mpz_size (appr_r1) > s);
541 1.1 mrg
542 1.1 mrg if (mpz_cmp (appr_r0, appr_r1) > 0)
543 1.1 mrg {
544 1.1 mrg if (!sdiv_qr (q, appr_r0, s, appr_r0, appr_r1))
545 1.1 mrg break;
546 1.1 mrg mpz_addmul (appr.m[0][1], q, appr.m[0][0]);
547 1.1 mrg mpz_addmul (appr.m[1][1], q, appr.m[1][0]);
548 1.1 mrg }
549 1.1 mrg else
550 1.1 mrg {
551 1.1 mrg if (!sdiv_qr (q, appr_r1, s, appr_r1, appr_r0))
552 1.1 mrg break;
553 1.1 mrg mpz_addmul (appr.m[0][0], q, appr.m[0][1]);
554 1.1 mrg mpz_addmul (appr.m[1][0], q, appr.m[1][1]);
555 1.1 mrg }
556 1.1 mrg }
557 1.1 mrg
558 1.1 mrg if (mpz_cmp (appr_r0, ref_r0) != 0
559 1.1 mrg || mpz_cmp (appr_r1, ref_r1) != 0
560 1.1 mrg || !hgcd_ref_equal (ref, &appr))
561 1.1 mrg {
562 1.1 mrg fprintf (stderr, "appr_r0: "); debug_mp (appr_r0, 16);
563 1.1 mrg fprintf (stderr, "ref_r0: "); debug_mp (ref_r0, 16);
564 1.1 mrg
565 1.1 mrg fprintf (stderr, "appr_r1: "); debug_mp (appr_r1, 16);
566 1.1 mrg fprintf (stderr, "ref_r1: "); debug_mp (ref_r1, 16);
567 1.1 mrg
568 1.1 mrg return 0;
569 1.1 mrg }
570 1.1 mrg mpz_clear (t);
571 1.1 mrg mpz_clear (q);
572 1.1 mrg hgcd_ref_clear (&appr);
573 1.1 mrg mpz_clear (appr_r0);
574 1.1 mrg mpz_clear (appr_r1);
575 1.1 mrg
576 1.1 mrg return 1;
577 1.1 mrg }
578