Home | History | Annotate | Line # | Download | only in mpn
      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