summaryrefslogtreecommitdiff
path: root/mpz/fdiv_qr_ui.c
diff options
context:
space:
mode:
authortege <tege@gmplib.org>2002-04-20 16:42:23 +0200
committertege <tege@gmplib.org>2002-04-20 16:42:23 +0200
commit3c7d00eb181e32917f7e8aac2d94f0ffde56056b (patch)
tree31732a62b53c3e1dfcc3afcabbc5e26f25d646c2 /mpz/fdiv_qr_ui.c
parent145ab235c286e4cacc64909886cbec3b217ce13b (diff)
downloadgmp-3c7d00eb181e32917f7e8aac2d94f0ffde56056b.tar.gz
Nailify.
Diffstat (limited to 'mpz/fdiv_qr_ui.c')
-rw-r--r--mpz/fdiv_qr_ui.c94
1 files changed, 71 insertions, 23 deletions
diff --git a/mpz/fdiv_qr_ui.c b/mpz/fdiv_qr_ui.c
index 7d26ec6de..2ff0f27e1 100644
--- a/mpz/fdiv_qr_ui.c
+++ b/mpz/fdiv_qr_ui.c
@@ -26,36 +26,84 @@ MA 02111-1307, USA. */
unsigned long int
mpz_fdiv_qr_ui (mpz_ptr quot, mpz_ptr rem, mpz_srcptr dividend, unsigned long int divisor)
{
- mp_size_t dividend_size;
- mp_size_t size;
- mp_ptr quot_ptr;
- mp_limb_t remainder_limb;
+ mp_size_t ns, nn, qn;
+ mp_ptr np, qp;
+ mp_limb_t rl;
if (divisor == 0)
DIVIDE_BY_ZERO;
- dividend_size = dividend->_mp_size;
- size = ABS (dividend_size);
-
- if (quot->_mp_alloc < size)
- _mpz_realloc (quot, size);
-
- quot_ptr = quot->_mp_d;
-
- remainder_limb = mpn_divmod_1 (quot_ptr, dividend->_mp_d, size,
- (mp_limb_t) divisor);
-
- if (remainder_limb != 0 && dividend_size < 0)
+ ns = SIZ(dividend);
+ if (ns == 0)
{
- mpn_incr_u (quot_ptr, (mp_limb_t) 1);
- remainder_limb = divisor - remainder_limb;
+ SIZ(quot) = 0;
+ SIZ(rem) = 0;
+ return 0;
}
- size -= size != 0 && quot_ptr[size - 1] == 0;
- quot->_mp_size = dividend_size >= 0 ? size : -size;
+ nn = ABS(ns);
+ MPZ_REALLOC (quot, nn);
+ qp = PTR(quot);
+ np = PTR(dividend);
- rem->_mp_d[0] = remainder_limb;
- rem->_mp_size = remainder_limb != 0;
+#if GMP_NAIL_BITS != 0
+ if (divisor > GMP_NUMB_MAX)
+ {
+ mp_limb_t dp[2];
+ mp_ptr rp;
+ mp_size_t rn;
+
+ MPZ_REALLOC (rem, 2);
+ rp = PTR(rem);
+
+ if (nn == 1) /* tdiv_qr requirements; tested above for 0 */
+ {
+ qp[0] = 0;
+ qn = 1; /* a white lie, fixed below */
+ rl = np[0];
+ rp[0] = rl;
+ }
+ else
+ {
+ dp[0] = divisor & GMP_NUMB_MASK;
+ dp[1] = divisor >> GMP_NUMB_BITS;
+ mpn_tdiv_qr (qp, rp, (mp_size_t) 0, np, nn, dp, (mp_size_t) 2);
+ rl = rp[0] + (rp[1] << GMP_NUMB_BITS);
+ qn = nn - 2 + 1;
+ }
+
+ if (rl != 0 && ns < 0)
+ {
+ mpn_incr_u (qp, (mp_limb_t) 1);
+ rl = divisor - rl;
+ rp[0] = rl & GMP_NUMB_MASK;
+ rp[1] = rl >> GMP_NUMB_BITS;
+ }
+
+ qn -= qp[qn - 1] == 0; qn -= qn != 0 && qp[qn - 1] == 0;
+ rn = 1 + (rl > GMP_NUMB_MAX); rn -= (rp[rn - 1] == 0);
+ SIZ(rem) = rn;
+ }
+ else
+#endif
+ {
+ rl = mpn_divrem_1 (qp, (mp_size_t) 0, np, nn, (mp_limb_t) divisor);
+ if (rl == 0)
+ SIZ(rem) = 0;
+ else
+ {
+ if (ns < 0)
+ {
+ mpn_incr_u (qp, (mp_limb_t) 1);
+ rl = divisor - rl;
+ }
+
+ PTR(rem)[0] = rl;
+ SIZ(rem) = rl != 0;
+ }
+ qn = nn - (qp[nn - 1] == 0);
+ }
- return remainder_limb;
+ SIZ(quot) = ns >= 0 ? qn : -qn;
+ return rl;
}