Upload Tizen:Base source
[external/gmp.git] / mpn / generic / tdiv_qr.c
1 /* mpn_tdiv_qr -- Divide the numerator (np,nn) by the denominator (dp,dn) and
2    write the nn-dn+1 quotient limbs at qp and the dn remainder limbs at rp.  If
3    qxn is non-zero, generate that many fraction limbs and append them after the
4    other quotient limbs, and update the remainder accordingly.  The input
5    operands are unaffected.
6
7    Preconditions:
8    1. The most significant limb of of the divisor must be non-zero.
9    2. nn >= dn, even if qxn is non-zero.  (??? relax this ???)
10
11    The time complexity of this is O(qn*qn+M(dn,qn)), where M(m,n) is the time
12    complexity of multiplication.
13
14 Copyright 1997, 2000, 2001, 2002, 2005, 2009 Free Software Foundation, Inc.
15
16 This file is part of the GNU MP Library.
17
18 The GNU MP Library is free software; you can redistribute it and/or modify
19 it under the terms of the GNU Lesser General Public License as published by
20 the Free Software Foundation; either version 3 of the License, or (at your
21 option) any later version.
22
23 The GNU MP Library is distributed in the hope that it will be useful, but
24 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
25 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
26 License for more details.
27
28 You should have received a copy of the GNU Lesser General Public License
29 along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
30
31 #include "gmp.h"
32 #include "gmp-impl.h"
33 #include "longlong.h"
34
35
36 void
37 mpn_tdiv_qr (mp_ptr qp, mp_ptr rp, mp_size_t qxn,
38              mp_srcptr np, mp_size_t nn, mp_srcptr dp, mp_size_t dn)
39 {
40   ASSERT_ALWAYS (qxn == 0);
41
42   ASSERT (nn >= 0);
43   ASSERT (dn >= 0);
44   ASSERT (dn == 0 || dp[dn - 1] != 0);
45   ASSERT (! MPN_OVERLAP_P (qp, nn - dn + 1 + qxn, np, nn));
46   ASSERT (! MPN_OVERLAP_P (qp, nn - dn + 1 + qxn, dp, dn));
47
48   switch (dn)
49     {
50     case 0:
51       DIVIDE_BY_ZERO;
52
53     case 1:
54       {
55         rp[0] = mpn_divrem_1 (qp, (mp_size_t) 0, np, nn, dp[0]);
56         return;
57       }
58
59     case 2:
60       {
61         mp_ptr n2p, d2p;
62         mp_limb_t qhl, cy;
63         TMP_DECL;
64         TMP_MARK;
65         if ((dp[1] & GMP_NUMB_HIGHBIT) == 0)
66           {
67             int cnt;
68             mp_limb_t dtmp[2];
69             count_leading_zeros (cnt, dp[1]);
70             cnt -= GMP_NAIL_BITS;
71             d2p = dtmp;
72             d2p[1] = (dp[1] << cnt) | (dp[0] >> (GMP_NUMB_BITS - cnt));
73             d2p[0] = (dp[0] << cnt) & GMP_NUMB_MASK;
74             n2p = TMP_ALLOC_LIMBS (nn + 1);
75             cy = mpn_lshift (n2p, np, nn, cnt);
76             n2p[nn] = cy;
77             qhl = mpn_divrem_2 (qp, 0L, n2p, nn + (cy != 0), d2p);
78             if (cy == 0)
79               qp[nn - 2] = qhl; /* always store nn-2+1 quotient limbs */
80             rp[0] = (n2p[0] >> cnt)
81               | ((n2p[1] << (GMP_NUMB_BITS - cnt)) & GMP_NUMB_MASK);
82             rp[1] = (n2p[1] >> cnt);
83           }
84         else
85           {
86             d2p = (mp_ptr) dp;
87             n2p = TMP_ALLOC_LIMBS (nn);
88             MPN_COPY (n2p, np, nn);
89             qhl = mpn_divrem_2 (qp, 0L, n2p, nn, d2p);
90             qp[nn - 2] = qhl;   /* always store nn-2+1 quotient limbs */
91             rp[0] = n2p[0];
92             rp[1] = n2p[1];
93           }
94         TMP_FREE;
95         return;
96       }
97
98     default:
99       {
100         int adjust;
101         gmp_pi1_t dinv;
102         TMP_DECL;
103         TMP_MARK;
104         adjust = np[nn - 1] >= dp[dn - 1];      /* conservative tests for quotient size */
105         if (nn + adjust >= 2 * dn)
106           {
107             mp_ptr n2p, d2p;
108             mp_limb_t cy;
109             int cnt;
110
111             qp[nn - dn] = 0;                      /* zero high quotient limb */
112             if ((dp[dn - 1] & GMP_NUMB_HIGHBIT) == 0) /* normalize divisor */
113               {
114                 count_leading_zeros (cnt, dp[dn - 1]);
115                 cnt -= GMP_NAIL_BITS;
116                 d2p = TMP_ALLOC_LIMBS (dn);
117                 mpn_lshift (d2p, dp, dn, cnt);
118                 n2p = TMP_ALLOC_LIMBS (nn + 1);
119                 cy = mpn_lshift (n2p, np, nn, cnt);
120                 n2p[nn] = cy;
121                 nn += adjust;
122               }
123             else
124               {
125                 cnt = 0;
126                 d2p = (mp_ptr) dp;
127                 n2p = TMP_ALLOC_LIMBS (nn + 1);
128                 MPN_COPY (n2p, np, nn);
129                 n2p[nn] = 0;
130                 nn += adjust;
131               }
132
133             invert_pi1 (dinv, d2p[dn - 1], d2p[dn - 2]);
134             if (BELOW_THRESHOLD (dn, DC_DIV_QR_THRESHOLD))
135               mpn_sbpi1_div_qr (qp, n2p, nn, d2p, dn, dinv.inv32);
136             else if (BELOW_THRESHOLD (dn, MUPI_DIV_QR_THRESHOLD) ||   /* fast condition */
137                      BELOW_THRESHOLD (nn, 2 * MU_DIV_QR_THRESHOLD) || /* fast condition */
138                      (double) (2 * (MU_DIV_QR_THRESHOLD - MUPI_DIV_QR_THRESHOLD)) * dn /* slow... */
139                      + (double) MUPI_DIV_QR_THRESHOLD * nn > (double) dn * nn)    /* ...condition */
140               mpn_dcpi1_div_qr (qp, n2p, nn, d2p, dn, &dinv);
141             else
142               {
143                 mp_size_t itch = mpn_mu_div_qr_itch (nn, dn, 0);
144                 mp_ptr scratch = TMP_ALLOC_LIMBS (itch);
145                 mpn_mu_div_qr (qp, rp, n2p, nn, d2p, dn, scratch);
146                 n2p = rp;
147               }
148
149             if (cnt != 0)
150               mpn_rshift (rp, n2p, dn, cnt);
151             else
152               MPN_COPY (rp, n2p, dn);
153             TMP_FREE;
154             return;
155           }
156
157         /* When we come here, the numerator/partial remainder is less
158            than twice the size of the denominator.  */
159
160           {
161             /* Problem:
162
163                Divide a numerator N with nn limbs by a denominator D with dn
164                limbs forming a quotient of qn=nn-dn+1 limbs.  When qn is small
165                compared to dn, conventional division algorithms perform poorly.
166                We want an algorithm that has an expected running time that is
167                dependent only on qn.
168
169                Algorithm (very informally stated):
170
171                1) Divide the 2 x qn most significant limbs from the numerator
172                   by the qn most significant limbs from the denominator.  Call
173                   the result qest.  This is either the correct quotient, but
174                   might be 1 or 2 too large.  Compute the remainder from the
175                   division.  (This step is implemented by a mpn_divrem call.)
176
177                2) Is the most significant limb from the remainder < p, where p
178                   is the product of the most significant limb from the quotient
179                   and the next(d)?  (Next(d) denotes the next ignored limb from
180                   the denominator.)  If it is, decrement qest, and adjust the
181                   remainder accordingly.
182
183                3) Is the remainder >= qest?  If it is, qest is the desired
184                   quotient.  The algorithm terminates.
185
186                4) Subtract qest x next(d) from the remainder.  If there is
187                   borrow out, decrement qest, and adjust the remainder
188                   accordingly.
189
190                5) Skip one word from the denominator (i.e., let next(d) denote
191                   the next less significant limb.  */
192
193             mp_size_t qn;
194             mp_ptr n2p, d2p;
195             mp_ptr tp;
196             mp_limb_t cy;
197             mp_size_t in, rn;
198             mp_limb_t quotient_too_large;
199             unsigned int cnt;
200
201             qn = nn - dn;
202             qp[qn] = 0;                         /* zero high quotient limb */
203             qn += adjust;                       /* qn cannot become bigger */
204
205             if (qn == 0)
206               {
207                 MPN_COPY (rp, np, dn);
208                 TMP_FREE;
209                 return;
210               }
211
212             in = dn - qn;               /* (at least partially) ignored # of limbs in ops */
213             /* Normalize denominator by shifting it to the left such that its
214                most significant bit is set.  Then shift the numerator the same
215                amount, to mathematically preserve quotient.  */
216             if ((dp[dn - 1] & GMP_NUMB_HIGHBIT) == 0)
217               {
218                 count_leading_zeros (cnt, dp[dn - 1]);
219                 cnt -= GMP_NAIL_BITS;
220
221                 d2p = TMP_ALLOC_LIMBS (qn);
222                 mpn_lshift (d2p, dp + in, qn, cnt);
223                 d2p[0] |= dp[in - 1] >> (GMP_NUMB_BITS - cnt);
224
225                 n2p = TMP_ALLOC_LIMBS (2 * qn + 1);
226                 cy = mpn_lshift (n2p, np + nn - 2 * qn, 2 * qn, cnt);
227                 if (adjust)
228                   {
229                     n2p[2 * qn] = cy;
230                     n2p++;
231                   }
232                 else
233                   {
234                     n2p[0] |= np[nn - 2 * qn - 1] >> (GMP_NUMB_BITS - cnt);
235                   }
236               }
237             else
238               {
239                 cnt = 0;
240                 d2p = (mp_ptr) dp + in;
241
242                 n2p = TMP_ALLOC_LIMBS (2 * qn + 1);
243                 MPN_COPY (n2p, np + nn - 2 * qn, 2 * qn);
244                 if (adjust)
245                   {
246                     n2p[2 * qn] = 0;
247                     n2p++;
248                   }
249               }
250
251             /* Get an approximate quotient using the extracted operands.  */
252             if (qn == 1)
253               {
254                 mp_limb_t q0, r0;
255                 udiv_qrnnd (q0, r0, n2p[1], n2p[0] << GMP_NAIL_BITS, d2p[0] << GMP_NAIL_BITS);
256                 n2p[0] = r0 >> GMP_NAIL_BITS;
257                 qp[0] = q0;
258               }
259             else if (qn == 2)
260               mpn_divrem_2 (qp, 0L, n2p, 4L, d2p); /* FIXME: obsolete function */
261             else
262               {
263                 invert_pi1 (dinv, d2p[qn - 1], d2p[qn - 2]);
264                 if (BELOW_THRESHOLD (qn, DC_DIV_QR_THRESHOLD))
265                   mpn_sbpi1_div_qr (qp, n2p, 2 * qn, d2p, qn, dinv.inv32);
266                 else if (BELOW_THRESHOLD (qn, MU_DIV_QR_THRESHOLD))
267                   mpn_dcpi1_div_qr (qp, n2p, 2 * qn, d2p, qn, &dinv);
268                 else
269                   {
270                     mp_size_t itch = mpn_mu_div_qr_itch (2 * qn, qn, 0);
271                     mp_ptr scratch = TMP_ALLOC_LIMBS (itch);
272                     mp_ptr r2p = rp;
273                     if (np == r2p)      /* If N and R share space, put ... */
274                       r2p += nn - qn;   /* intermediate remainder at N's upper end. */
275                     mpn_mu_div_qr (qp, r2p, n2p, 2 * qn, d2p, qn, scratch);
276                     MPN_COPY (n2p, r2p, qn);
277                   }
278               }
279
280             rn = qn;
281             /* Multiply the first ignored divisor limb by the most significant
282                quotient limb.  If that product is > the partial remainder's
283                most significant limb, we know the quotient is too large.  This
284                test quickly catches most cases where the quotient is too large;
285                it catches all cases where the quotient is 2 too large.  */
286             {
287               mp_limb_t dl, x;
288               mp_limb_t h, dummy;
289
290               if (in - 2 < 0)
291                 dl = 0;
292               else
293                 dl = dp[in - 2];
294
295 #if GMP_NAIL_BITS == 0
296               x = (dp[in - 1] << cnt) | ((dl >> 1) >> ((~cnt) % GMP_LIMB_BITS));
297 #else
298               x = (dp[in - 1] << cnt) & GMP_NUMB_MASK;
299               if (cnt != 0)
300                 x |= dl >> (GMP_NUMB_BITS - cnt);
301 #endif
302               umul_ppmm (h, dummy, x, qp[qn - 1] << GMP_NAIL_BITS);
303
304               if (n2p[qn - 1] < h)
305                 {
306                   mp_limb_t cy;
307
308                   mpn_decr_u (qp, (mp_limb_t) 1);
309                   cy = mpn_add_n (n2p, n2p, d2p, qn);
310                   if (cy)
311                     {
312                       /* The partial remainder is safely large.  */
313                       n2p[qn] = cy;
314                       ++rn;
315                     }
316                 }
317             }
318
319             quotient_too_large = 0;
320             if (cnt != 0)
321               {
322                 mp_limb_t cy1, cy2;
323
324                 /* Append partially used numerator limb to partial remainder.  */
325                 cy1 = mpn_lshift (n2p, n2p, rn, GMP_NUMB_BITS - cnt);
326                 n2p[0] |= np[in - 1] & (GMP_NUMB_MASK >> cnt);
327
328                 /* Update partial remainder with partially used divisor limb.  */
329                 cy2 = mpn_submul_1 (n2p, qp, qn, dp[in - 1] & (GMP_NUMB_MASK >> cnt));
330                 if (qn != rn)
331                   {
332                     ASSERT_ALWAYS (n2p[qn] >= cy2);
333                     n2p[qn] -= cy2;
334                   }
335                 else
336                   {
337                     n2p[qn] = cy1 - cy2; /* & GMP_NUMB_MASK; */
338
339                     quotient_too_large = (cy1 < cy2);
340                     ++rn;
341                   }
342                 --in;
343               }
344             /* True: partial remainder now is neutral, i.e., it is not shifted up.  */
345
346             tp = TMP_ALLOC_LIMBS (dn);
347
348             if (in < qn)
349               {
350                 if (in == 0)
351                   {
352                     MPN_COPY (rp, n2p, rn);
353                     ASSERT_ALWAYS (rn == dn);
354                     goto foo;
355                   }
356                 mpn_mul (tp, qp, qn, dp, in);
357               }
358             else
359               mpn_mul (tp, dp, in, qp, qn);
360
361             cy = mpn_sub (n2p, n2p, rn, tp + in, qn);
362             MPN_COPY (rp + in, n2p, dn - in);
363             quotient_too_large |= cy;
364             cy = mpn_sub_n (rp, np, tp, in);
365             cy = mpn_sub_1 (rp + in, rp + in, rn, cy);
366             quotient_too_large |= cy;
367           foo:
368             if (quotient_too_large)
369               {
370                 mpn_decr_u (qp, (mp_limb_t) 1);
371                 mpn_add_n (rp, rp, dp, dn);
372               }
373           }
374         TMP_FREE;
375         return;
376       }
377     }
378 }