Merge branch 'vendor/GMP' into gcc441
[dragonfly.git] / contrib / gmp / mpn / generic / dc_bdiv_q.c
1 /* mpn_dc_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 Torbjörn Granlund.
5
6    THE FUNCTIONS IN THIS FILE ARE INTERNAL WITH A MUTABLE INTERFACE.  IT IS
7    ONLY SAFE TO REACH THEM THROUGH DOCUMENTED INTERFACES.  IN FACT, IT IS
8    ALMOST GUARANTEED THAT THEY WILL CHANGE OR DISAPPEAR IN A FUTURE GMP
9    RELEASE.
10
11 Copyright 2006, 2007 Free Software Foundation, Inc.
12
13 This file is part of the GNU MP Library.
14
15 The GNU MP Library is free software; you can redistribute it and/or modify
16 it under the terms of the GNU Lesser General Public License as published by
17 the Free Software Foundation; either version 3 of the License, or (at your
18 option) any later version.
19
20 The GNU MP Library is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
22 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
23 License for more details.
24
25 You should have received a copy of the GNU Lesser General Public License
26 along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
27
28 #include "gmp.h"
29 #include "gmp-impl.h"
30
31
32 /* Computes Q = N / D mod B^n, destroys N. */
33
34 mp_size_t
35 mpn_dc_bdiv_q_n_itch (mp_size_t n)
36 {
37   /* NOTE: Depends om mullow_n interface */
38   return n;
39 }
40
41 void
42 mpn_dc_bdiv_q_n (mp_ptr qp,
43                  mp_ptr np, mp_srcptr dp, mp_size_t n,
44                  mp_limb_t dinv, mp_ptr tp)
45 {
46   while (ABOVE_THRESHOLD (n, DC_BDIV_Q_THRESHOLD))
47     {
48       mp_limb_t l, h;
49       mp_limb_t cy;
50
51       l = n >> 1;
52       h = n - l;
53
54       cy = mpn_dc_bdiv_qr_n (qp, np, dp, l, dinv, tp);
55
56       mpn_mullow_n (tp, qp, dp + h, l);
57       mpn_sub_n (np + h, np + h, tp, l);
58
59       if (l < h)
60         {
61           cy += mpn_submul_1 (np + l, qp, l, dp[l]);
62           np[n - 1] -= cy;
63         }
64       qp += l;
65       np += l;
66       n -= l;
67     }
68   mpn_sb_bdiv_q (qp, np, n, dp, n, dinv);
69 }
70
71 void
72 mpn_dc_bdiv_q (mp_ptr qp,
73                mp_ptr np, mp_size_t nn,
74                mp_srcptr dp, mp_size_t dn,
75                mp_limb_t dinv)
76 {
77   mp_size_t qn;
78   mp_limb_t cy;
79   mp_ptr tp;
80   TMP_DECL;
81
82   TMP_MARK;
83
84   tp = TMP_SALLOC_LIMBS (dn);
85
86   qn = nn;
87
88   if (qn > dn)
89     {
90       /* Reduce qn mod dn in a super-efficient manner.  */
91       do
92         qn -= dn;
93       while (qn > dn);
94
95       /* Perform the typically smaller block first.  */
96       if (BELOW_THRESHOLD (qn, DC_BDIV_QR_THRESHOLD))
97         cy = mpn_sb_bdiv_qr (qp, np, 2 * qn, dp, qn, dinv);
98       else
99         cy = mpn_dc_bdiv_qr_n (qp, np, dp, qn, dinv, tp);
100
101       if (qn != dn)
102         {
103           if (qn > dn - qn)
104             mpn_mul (tp, qp, qn, dp + qn, dn - qn);
105           else
106             mpn_mul (tp, dp + qn, dn - qn, qp, qn);
107           mpn_incr_u (tp + qn, cy);
108
109           mpn_sub (np + qn, np + qn, nn - qn, tp, dn);
110           cy = 0;
111         }
112
113       np += qn;
114       qp += qn;
115
116       qn = nn - qn;
117       while (qn > dn)
118         {
119           mpn_sub_1 (np + dn, np + dn, qn, cy);
120           cy = mpn_dc_bdiv_qr_n (qp, np, dp, dn, dinv, tp);
121           qp += dn;
122           np += dn;
123           qn -= dn;
124         }
125       mpn_sub_1 (np + dn, np + dn, qn, cy);
126       mpn_dc_bdiv_q_n (qp, np, dp, dn, dinv, tp);
127       TMP_FREE;
128       return;
129     }
130
131   if (BELOW_THRESHOLD (qn, DC_BDIV_Q_THRESHOLD))
132     mpn_sb_bdiv_q (qp, np, 2 * qn, dp, qn, dinv);
133   else
134     mpn_dc_bdiv_q_n (qp, np, dp, qn, dinv, tp);
135
136   TMP_FREE;
137 }