1 /* mpn_dcpi1_div_qr_n -- recursive divide-and-conquer division for arbitrary
4 Contributed to the GNU project by Torbjorn Granlund.
6 THE FUNCTIONS IN THIS FILE ARE INTERNAL WITH MUTABLE INTERFACES. IT IS ONLY
7 SAFE TO REACH THEM THROUGH DOCUMENTED INTERFACES. IN FACT, IT IS ALMOST
8 GUARANTEED THAT THEY WILL CHANGE OR DISAPPEAR IN A FUTURE GMP RELEASE.
10 Copyright 2006, 2007, 2009 Free Software Foundation, Inc.
12 This file is part of the GNU MP Library.
14 The GNU MP Library is free software; you can redistribute it and/or modify
15 it under the terms of the GNU Lesser General Public License as published by
16 the Free Software Foundation; either version 3 of the License, or (at your
17 option) any later version.
19 The GNU MP Library is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
22 License for more details.
24 You should have received a copy of the GNU Lesser General Public License
25 along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
33 mpn_dcpi1_div_qr_n (mp_ptr qp, mp_ptr np, mp_srcptr dp, mp_size_t n,
34 gmp_pi1_t *dinv, mp_ptr tp)
39 lo = n >> 1; /* floor(n/2) */
40 hi = n - lo; /* ceil(n/2) */
42 if (BELOW_THRESHOLD (hi, DC_DIV_QR_THRESHOLD))
43 qh = mpn_sbpi1_div_qr (qp + lo, np + 2 * lo, 2 * hi, dp + lo, hi, dinv->inv32);
45 qh = mpn_dcpi1_div_qr_n (qp + lo, np + 2 * lo, dp + lo, hi, dinv, tp);
47 mpn_mul (tp, qp + lo, hi, dp, lo);
49 cy = mpn_sub_n (np + lo, np + lo, tp, n);
51 cy += mpn_sub_n (np + n, np + n, dp, lo);
55 qh -= mpn_sub_1 (qp + lo, qp + lo, hi, 1);
56 cy -= mpn_add_n (np + lo, np + lo, dp, n);
59 if (BELOW_THRESHOLD (lo, DC_DIV_QR_THRESHOLD))
60 ql = mpn_sbpi1_div_qr (qp, np + hi, 2 * lo, dp + hi, lo, dinv->inv32);
62 ql = mpn_dcpi1_div_qr_n (qp, np + hi, dp + hi, lo, dinv, tp);
64 mpn_mul (tp, dp, hi, qp, lo);
66 cy = mpn_sub_n (np, np, tp, n);
68 cy += mpn_sub_n (np + lo, np + lo, dp, hi);
72 mpn_sub_1 (qp, qp, lo, 1);
73 cy -= mpn_add_n (np, np, dp, n);
80 mpn_dcpi1_div_qr (mp_ptr qp,
81 mp_ptr np, mp_size_t nn,
82 mp_srcptr dp, mp_size_t dn,
92 ASSERT (dn >= 6); /* to adhere to mpn_sbpi1_div_qr's limits */
93 ASSERT (nn - dn >= 3); /* to adhere to mpn_sbpi1_div_qr's limits */
94 ASSERT (dp[dn-1] & GMP_NUMB_HIGHBIT);
96 tp = TMP_SALLOC_LIMBS (dn);
105 /* Reduce qn mod dn without division, optimizing small operations. */
110 qp -= qn; /* point at low limb of next quotient block */
111 np -= qn; /* point in the middle of partial remainder */
113 /* Perform the typically smaller block first. */
116 mp_limb_t q, n2, n1, n0, d1, d0;
118 /* Handle qh up front, for simplicity. */
119 qh = mpn_cmp (np - dn + 1, dp - dn, dn) >= 0;
121 ASSERT_NOCARRY (mpn_sub_n (np - dn + 1, np - dn + 1, dp - dn, dn));
123 /* A single iteration of schoolbook: One 3/2 division,
124 followed by the bignum update and adjustment. */
131 ASSERT (n2 < d1 || (n2 == d1 && n1 <= d0));
133 if (UNLIKELY (n2 == d1) && n1 == d0)
136 cy = mpn_submul_1 (np - dn, dp - dn, dn, q);
141 udiv_qr_3by2 (q, n1, n0, n2, n1, n0, d1, d0, dinv->inv32);
146 cy = mpn_submul_1 (np - dn, dp - dn, dn - 2, q);
149 n0 = (n0 - cy) & GMP_NUMB_MASK;
151 n1 = (n1 - cy1) & GMP_NUMB_MASK;
154 if (UNLIKELY (cy != 0))
156 n1 += d1 + mpn_add_n (np - dn, np - dn, dp - dn, dn - 1);
158 q = (q - 1) & GMP_NUMB_MASK;
170 /* Do a 2qn / qn division */
172 qh = mpn_divrem_2 (qp, 0L, np - 2, 4, dp - 2); /* FIXME: obsolete function. Use 5/3 division? */
173 else if (BELOW_THRESHOLD (qn, DC_DIV_QR_THRESHOLD))
174 qh = mpn_sbpi1_div_qr (qp, np - qn, 2 * qn, dp - qn, qn, dinv->inv32);
176 qh = mpn_dcpi1_div_qr_n (qp, np - qn, dp - qn, qn, dinv, tp);
181 mpn_mul (tp, qp, qn, dp - dn, dn - qn);
183 mpn_mul (tp, dp - dn, dn - qn, qp, qn);
185 cy = mpn_sub_n (np - dn, np - dn, tp, dn);
187 cy += mpn_sub_n (np - dn + qn, np - dn + qn, dp - dn, dn - qn);
191 qh -= mpn_sub_1 (qp, qp, qn, 1);
192 cy -= mpn_add_n (np - dn, np - dn, dp - dn, dn);
202 mpn_dcpi1_div_qr_n (qp, np - dn, dp - dn, dn, dinv, tp);
209 qp -= qn; /* point at low limb of next quotient block */
210 np -= qn; /* point in the middle of partial remainder */
212 if (BELOW_THRESHOLD (qn, DC_DIV_QR_THRESHOLD))
213 qh = mpn_sbpi1_div_qr (qp, np - qn, 2 * qn, dp - qn, qn, dinv->inv32);
215 qh = mpn_dcpi1_div_qr_n (qp, np - qn, dp - qn, qn, dinv, tp);
220 mpn_mul (tp, qp, qn, dp - dn, dn - qn);
222 mpn_mul (tp, dp - dn, dn - qn, qp, qn);
224 cy = mpn_sub_n (np - dn, np - dn, tp, dn);
226 cy += mpn_sub_n (np - dn + qn, np - dn + qn, dp - dn, dn - qn);
230 qh -= mpn_sub_1 (qp, qp, qn, 1);
231 cy -= mpn_add_n (np - dn, np - dn, dp - dn, dn);