/src/gmp/mpn/dcpi1_bdiv_q.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* mpn_dcpi1_bdiv_q -- divide-and-conquer Hensel division with precomputed |
2 | | inverse, returning quotient. |
3 | | |
4 | | Contributed to the GNU project by Niels Möller and Torbjorn Granlund. |
5 | | |
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. |
9 | | |
10 | | Copyright 2006, 2007, 2009-2011, 2017 Free Software Foundation, Inc. |
11 | | |
12 | | This file is part of the GNU MP Library. |
13 | | |
14 | | The GNU MP Library is free software; you can redistribute it and/or modify |
15 | | it under the terms of either: |
16 | | |
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. |
20 | | |
21 | | or |
22 | | |
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 |
25 | | later version. |
26 | | |
27 | | or both in parallel, as here. |
28 | | |
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 |
32 | | for more details. |
33 | | |
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/. */ |
37 | | |
38 | | #include "gmp-impl.h" |
39 | | |
40 | | |
41 | | #if 0 /* unused, so leave out for now */ |
42 | | static mp_size_t |
43 | | mpn_dcpi1_bdiv_q_n_itch (mp_size_t n) |
44 | | { |
45 | | /* NOTE: Depends on mullo_n and mpn_dcpi1_bdiv_qr_n interface */ |
46 | | return n; |
47 | | } |
48 | | #endif |
49 | | |
50 | | /* Computes Q = - N / D mod B^n, destroys N. |
51 | | |
52 | | N = {np,n} |
53 | | D = {dp,n} |
54 | | */ |
55 | | |
56 | | static void |
57 | | mpn_dcpi1_bdiv_q_n (mp_ptr qp, |
58 | | mp_ptr np, mp_srcptr dp, mp_size_t n, |
59 | | mp_limb_t dinv, mp_ptr tp) |
60 | 0 | { |
61 | 0 | while (ABOVE_THRESHOLD (n, DC_BDIV_Q_THRESHOLD)) |
62 | 0 | { |
63 | 0 | mp_size_t lo, hi; |
64 | 0 | mp_limb_t cy; |
65 | |
|
66 | 0 | lo = n >> 1; /* floor(n/2) */ |
67 | 0 | hi = n - lo; /* ceil(n/2) */ |
68 | |
|
69 | 0 | cy = mpn_dcpi1_bdiv_qr_n (qp, np, dp, lo, dinv, tp); |
70 | |
|
71 | 0 | mpn_mullo_n (tp, qp, dp + hi, lo); |
72 | 0 | mpn_add_n (np + hi, np + hi, tp, lo); |
73 | |
|
74 | 0 | if (lo < hi) |
75 | 0 | { |
76 | 0 | cy += mpn_addmul_1 (np + lo, qp, lo, dp[lo]); |
77 | 0 | np[n - 1] += cy; |
78 | 0 | } |
79 | 0 | qp += lo; |
80 | 0 | np += lo; |
81 | 0 | n -= lo; |
82 | 0 | } |
83 | 0 | mpn_sbpi1_bdiv_q (qp, np, n, dp, n, dinv); |
84 | 0 | } |
85 | | |
86 | | /* Computes Q = - N / D mod B^nn, destroys N. |
87 | | |
88 | | N = {np,nn} |
89 | | D = {dp,dn} |
90 | | */ |
91 | | |
92 | | void |
93 | | mpn_dcpi1_bdiv_q (mp_ptr qp, |
94 | | mp_ptr np, mp_size_t nn, |
95 | | mp_srcptr dp, mp_size_t dn, |
96 | | mp_limb_t dinv) |
97 | 0 | { |
98 | 0 | mp_size_t qn; |
99 | 0 | mp_limb_t cy; |
100 | 0 | mp_ptr tp; |
101 | 0 | TMP_DECL; |
102 | |
|
103 | 0 | TMP_MARK; |
104 | |
|
105 | 0 | ASSERT (dn >= 2); |
106 | 0 | ASSERT (nn - dn >= 0); |
107 | 0 | ASSERT (dp[0] & 1); |
108 | |
|
109 | 0 | tp = TMP_SALLOC_LIMBS (dn); |
110 | |
|
111 | 0 | qn = nn; |
112 | |
|
113 | 0 | if (qn > dn) |
114 | 0 | { |
115 | | /* Reduce qn mod dn in a super-efficient manner. */ |
116 | 0 | do |
117 | 0 | qn -= dn; |
118 | 0 | while (qn > dn); |
119 | | |
120 | | /* Perform the typically smaller block first. */ |
121 | 0 | if (BELOW_THRESHOLD (qn, DC_BDIV_QR_THRESHOLD)) |
122 | 0 | cy = mpn_sbpi1_bdiv_qr (qp, np, 2 * qn, dp, qn, dinv); |
123 | 0 | else |
124 | 0 | cy = mpn_dcpi1_bdiv_qr_n (qp, np, dp, qn, dinv, tp); |
125 | |
|
126 | 0 | if (qn != dn) |
127 | 0 | { |
128 | 0 | if (qn > dn - qn) |
129 | 0 | mpn_mul (tp, qp, qn, dp + qn, dn - qn); |
130 | 0 | else |
131 | 0 | mpn_mul (tp, dp + qn, dn - qn, qp, qn); |
132 | 0 | mpn_incr_u (tp + qn, cy); |
133 | |
|
134 | 0 | mpn_add (np + qn, np + qn, nn - qn, tp, dn); |
135 | 0 | cy = 0; |
136 | 0 | } |
137 | |
|
138 | 0 | np += qn; |
139 | 0 | qp += qn; |
140 | |
|
141 | 0 | qn = nn - qn; |
142 | 0 | while (qn > dn) |
143 | 0 | { |
144 | 0 | mpn_add_1 (np + dn, np + dn, qn - dn, cy); |
145 | 0 | cy = mpn_dcpi1_bdiv_qr_n (qp, np, dp, dn, dinv, tp); |
146 | 0 | qp += dn; |
147 | 0 | np += dn; |
148 | 0 | qn -= dn; |
149 | 0 | } |
150 | 0 | mpn_dcpi1_bdiv_q_n (qp, np, dp, dn, dinv, tp); |
151 | 0 | } |
152 | 0 | else |
153 | 0 | { |
154 | 0 | if (BELOW_THRESHOLD (qn, DC_BDIV_Q_THRESHOLD)) |
155 | 0 | mpn_sbpi1_bdiv_q (qp, np, qn, dp, qn, dinv); |
156 | 0 | else |
157 | 0 | mpn_dcpi1_bdiv_q_n (qp, np, dp, qn, dinv, tp); |
158 | 0 | } |
159 | |
|
160 | 0 | TMP_FREE; |
161 | 0 | } |