3 THE FUNCTIONS IN THIS FILE ARE INTERNAL WITH MUTABLE INTERFACES. IT IS ONLY
4 SAFE TO REACH THEM THROUGH DOCUMENTED INTERFACES. IN FACT, IT IS ALMOST
5 GUARANTEED THAT THEY'LL CHANGE OR DISAPPEAR IN A FUTURE GNU MP RELEASE.
7 Copyright 2003-2005, 2008, 2010, 2011 Free Software Foundation, Inc.
9 This file is part of the GNU MP Library.
11 The GNU MP Library is free software; you can redistribute it and/or modify
12 it under the terms of either:
14 * the GNU Lesser General Public License as published by the Free
15 Software Foundation; either version 3 of the License, or (at your
16 option) any later version.
20 * the GNU General Public License as published by the Free Software
21 Foundation; either version 2 of the License, or (at your option) any
24 or both in parallel, as here.
26 The GNU MP Library is distributed in the hope that it will be useful, but
27 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
28 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
31 You should have received copies of the GNU General Public License and the
32 GNU Lesser General Public License along with the GNU MP Library. If not,
33 see https://www.gnu.org/licenses/. */
35 #include <stdlib.h> /* for NULL */
41 /* Used when mpn_hgcd or mpn_hgcd2 has failed. Then either one of a or
42 b is small, or the difference is small. Perform one subtraction
43 followed by one division. The normal case is to compute the reduced
44 a and b, and return the new size.
46 If s == 0 (used for gcd and gcdext), returns zero if the gcd is
49 If s > 0, don't reduce to size <= s, and return zero if no
50 reduction is possible (if either a, b or |a-b| is of size <= s). */
52 /* The hook function is called as
54 hook(ctx, gp, gn, qp, qn, d)
56 in the following cases:
58 + If A = B at the start, G is the gcd, Q is NULL, d = -1.
60 + If one input is zero at the start, G is the gcd, Q is NULL,
61 d = 0 if A = G and d = 1 if B = G.
63 Otherwise, if d = 0 we have just subtracted a multiple of A from B,
64 and if d = 1 we have subtracted a multiple of B from A.
66 + If A = B after subtraction, G is the gcd, Q is NULL.
68 + If we get a zero remainder after division, G is the gcd, Q is the
71 + Otherwise, G is NULL, Q is the quotient (often 1).
76 mpn_gcd_subdiv_step (mp_ptr ap
, mp_ptr bp
, mp_size_t n
, mp_size_t s
,
77 gcd_subdiv_step_hook
*hook
, void *ctx
,
80 static const mp_limb_t one
= CNST_LIMB(1);
86 ASSERT (ap
[n
-1] > 0 || bp
[n
-1] > 0);
89 MPN_NORMALIZE (ap
, an
);
90 MPN_NORMALIZE (bp
, bn
);
94 /* Arrange so that a < b, subtract b -= a, and maintain
99 MPN_CMP (c
, ap
, bp
, an
);
100 if (UNLIKELY (c
== 0))
102 /* For gcdext, return the smallest of the two cofactors, so
105 hook (ctx
, ap
, an
, NULL
, 0, -1);
110 MP_PTR_SWAP (ap
, bp
);
118 MPN_PTR_SWAP (ap
, an
, bp
, bn
);
125 hook (ctx
, bp
, bn
, NULL
, 0, swapped
^ 1);
129 ASSERT_NOCARRY (mpn_sub (bp
, bp
, bn
, ap
, an
));
130 MPN_NORMALIZE (bp
, bn
);
135 /* Undo subtraction. */
136 mp_limb_t cy
= mpn_add (bp
, ap
, an
, bp
, bn
);
142 /* Arrange so that a < b */
146 MPN_CMP (c
, ap
, bp
, an
);
147 if (UNLIKELY (c
== 0))
150 /* Just record subtraction and return */
151 hook (ctx
, NULL
, 0, &one
, 1, swapped
);
154 hook (ctx
, bp
, bn
, NULL
, 0, swapped
);
158 hook (ctx
, NULL
, 0, &one
, 1, swapped
);
162 MP_PTR_SWAP (ap
, bp
);
168 hook (ctx
, NULL
, 0, &one
, 1, swapped
);
172 MPN_PTR_SWAP (ap
, an
, bp
, bn
);
177 mpn_tdiv_qr (tp
, bp
, 0, bp
, bn
, ap
, an
);
180 MPN_NORMALIZE (bp
, bn
);
182 if (UNLIKELY (bn
<= s
))
186 hook (ctx
, ap
, an
, tp
, qn
, swapped
);
190 /* Quotient is one too large, so decrement it and add back A. */
193 mp_limb_t cy
= mpn_add (bp
, ap
, an
, bp
, bn
);
198 MPN_COPY (bp
, ap
, an
);
200 MPN_DECR_U (tp
, qn
, 1);
203 hook (ctx
, NULL
, 0, tp
, qn
, swapped
);