1 /* mpn_sbpi1_div_q -- Schoolbook division using the Möller-Granlund 3/2
4 Contributed to the GNU project by Torbjorn Granlund.
6 THE FUNCTION IN THIS FILE IS INTERNAL WITH A MUTABLE INTERFACE. IT IS ONLY
7 SAFE TO REACH IT THROUGH DOCUMENTED INTERFACES. IN FACT, IT IS ALMOST
8 GUARANTEED THAT IT WILL CHANGE OR DISAPPEAR IN A FUTURE GMP RELEASE.
10 Copyright 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 either:
17 * the GNU Lesser General Public License as published by the Free
18 Software Foundation; either version 3 of the License, or (at your
19 option) any later version.
23 * the GNU General Public License as published by the Free Software
24 Foundation; either version 2 of the License, or (at your option) any
27 or both in parallel, as here.
29 The GNU MP Library is distributed in the hope that it will be useful, but
30 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
31 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
34 You should have received copies of the GNU General Public License and the
35 GNU Lesser General Public License along with the GNU MP Library. If not,
36 see https://www.gnu.org/licenses/. */
44 mpn_sbpi1_div_q (mp_ptr qp
,
45 mp_ptr np
, mp_size_t nn
,
46 mp_srcptr dp
, mp_size_t dn
,
57 mp_size_t dn_orig
= dn
;
58 mp_srcptr dp_orig
= dp
;
63 ASSERT ((dp
[dn
-1] & GMP_NUMB_HIGHBIT
) != 0);
74 qh
= mpn_cmp (np
- dn
, dp
, dn
) >= 0;
76 mpn_sub_n (np
- dn
, np
- dn
, dp
, dn
);
80 dn
-= 2; /* offset dn by 2 for main division loops,
81 saving two iterations in mpn_submul_1. */
89 for (i
= qn
- (dn
+ 2); i
>= 0; i
--)
92 if (UNLIKELY (n1
== d1
) && np
[1] == d0
)
95 mpn_submul_1 (np
- dn
, dp
, dn
+ 2, q
);
96 n1
= np
[1]; /* update n1, last loop's value will now be invalid */
100 udiv_qr_3by2 (q
, n1
, n0
, n1
, np
[1], np
[0], d1
, d0
, dinv
);
102 cy
= mpn_submul_1 (np
- dn
, dp
, dn
, q
);
105 n0
= (n0
- cy
) & GMP_NUMB_MASK
;
110 if (UNLIKELY (cy
!= 0))
112 n1
+= d1
+ mpn_add_n (np
- dn
, np
- dn
, dp
, dn
+ 1);
120 flag
= ~CNST_LIMB(0);
124 for (i
= dn
; i
> 0; i
--)
127 if (UNLIKELY (n1
>= (d1
& flag
)))
130 cy
= mpn_submul_1 (np
- dn
, dp
, dn
+ 2, q
);
132 if (UNLIKELY (n1
!= cy
))
134 if (n1
< (cy
& flag
))
137 mpn_add_n (np
- dn
, np
- dn
, dp
, dn
+ 2);
146 udiv_qr_3by2 (q
, n1
, n0
, n1
, np
[1], np
[0], d1
, d0
, dinv
);
148 cy
= mpn_submul_1 (np
- dn
, dp
, dn
, q
);
151 n0
= (n0
- cy
) & GMP_NUMB_MASK
;
156 if (UNLIKELY (cy
!= 0))
158 n1
+= d1
+ mpn_add_n (np
- dn
, np
- dn
, dp
, dn
+ 1);
165 /* Truncate operands. */
171 if (UNLIKELY (n1
>= (d1
& flag
)))
174 cy
= mpn_submul_1 (np
, dp
, 2, q
);
176 if (UNLIKELY (n1
!= cy
))
178 if (n1
< (cy
& flag
))
181 add_ssaaaa (np
[1], np
[0], np
[1], np
[0], dp
[1], dp
[0]);
190 udiv_qr_3by2 (q
, n1
, n0
, n1
, np
[1], np
[0], d1
, d0
, dinv
);
198 ASSERT_ALWAYS (np
[1] == n1
);
203 if (UNLIKELY (n1
< (dn
& flag
)))
207 /* The quotient may be too large if the remainder is small. Recompute
208 for above ignored operand parts, until the remainder spills.
210 FIXME: The quality of this code isn't the same as the code above.
211 1. We don't compute things in an optimal order, high-to-low, in order
212 to terminate as quickly as possible.
213 2. We mess with pointers and sizes, adding and subtracting and
214 adjusting to get things right. It surely could be streamlined.
215 3. The only termination criteria are that we determine that the
216 quotient needs to be adjusted, or that we have recomputed
217 everything. We should stop when the remainder is so large
218 that no additional subtracting could make it spill.
219 4. If nothing else, we should not do two loops of submul_1 over the
220 data, instead handle both the triangularization and chopping at
227 /* Compensate for triangularization. */
239 for (i
= dn
- 3; i
>= 0; i
--)
242 cy
= mpn_submul_1 (np
- (dn
- i
), dp
, dn
- i
- 2, q
);
248 cy
= mpn_sub_1 (qp
, qp
, qn
, 1);
249 ASSERT_ALWAYS (cy
== 0);
262 /* Compensate for ignored dividend and divisor tails. */
269 cy
= mpn_sub_n (np
+ qn
, np
+ qn
, dp
, dn
- (qn
+ 1));
275 cy
= mpn_sub_1 (qp
, qp
, qn
, 1);
285 for (i
= dn
- qn
- 2; i
>= 0; i
--)
287 cy
= mpn_submul_1 (np
+ i
, qp
, qn
, dp
[i
]);
288 cy
= mpn_sub_1 (np
+ qn
+ i
, np
+ qn
+ i
, dn
- qn
- i
- 1, cy
);
293 cy
= mpn_sub_1 (qp
, qp
, qn
, 1);