summaryrefslogtreecommitdiff
path: root/mpz/cdiv_ui.c
diff options
context:
space:
mode:
authortege <tege@gmplib.org>2002-04-22 21:02:10 +0200
committertege <tege@gmplib.org>2002-04-22 21:02:10 +0200
commit1f8abae58224d9e312a025bbb4aafedaee972c94 (patch)
tree6af71c788a00e82cb0fc55c2554836dbe78f1c10 /mpz/cdiv_ui.c
parent4faf60cbcf4c190bbbf1a4add5de19240fbaaa8f (diff)
downloadgmp-1f8abae58224d9e312a025bbb4aafedaee972c94.tar.gz
Rewrite/Nailify.
Diffstat (limited to 'mpz/cdiv_ui.c')
-rw-r--r--mpz/cdiv_ui.c67
1 files changed, 58 insertions, 9 deletions
diff --git a/mpz/cdiv_ui.c b/mpz/cdiv_ui.c
index 41b149501..f86d082eb 100644
--- a/mpz/cdiv_ui.c
+++ b/mpz/cdiv_ui.c
@@ -28,17 +28,66 @@ MA 02111-1307, USA. */
unsigned long int
mpz_cdiv_ui (mpz_srcptr dividend, unsigned long int divisor)
{
- mp_size_t dividend_size;
- mp_size_t size;
- mp_limb_t remainder_limb;
+ mp_size_t ns, nn;
+ mp_ptr np;
+ mp_limb_t rl;
- dividend_size = dividend->_mp_size;
- size = ABS (dividend_size);
+ if (divisor == 0)
+ DIVIDE_BY_ZERO;
- remainder_limb = mpn_mod_1 (dividend->_mp_d, size, (mp_limb_t) divisor);
+ ns = SIZ(dividend);
+ if (ns == 0)
+ {
+ return 0;
+ }
- if (remainder_limb != 0 && dividend_size >= 0)
- remainder_limb = divisor - remainder_limb;
+ nn = ABS(ns);
+ np = PTR(dividend);
+#if GMP_NAIL_BITS != 0
+ if (divisor > GMP_NUMB_MAX)
+ {
+ mp_limb_t dp[2], rp[2];
+ mp_ptr qp;
+ mp_size_t rn;
+ TMP_DECL (mark);
- return remainder_limb;
+ if (nn == 1) /* tdiv_qr requirements; tested above for 0 */
+ {
+ rl = np[0];
+ rp[0] = rl;
+ }
+ else
+ {
+ TMP_MARK (mark);
+ dp[0] = divisor & GMP_NUMB_MASK;
+ dp[1] = divisor >> GMP_NUMB_BITS;
+ qp = TMP_ALLOC_LIMBS (nn - 2 + 1);
+ mpn_tdiv_qr (qp, rp, (mp_size_t) 0, np, nn, dp, (mp_size_t) 2);
+ TMP_FREE (mark);
+ rl = rp[0] + (rp[1] << GMP_NUMB_BITS);
+ }
+
+ if (rl != 0 && ns >= 0)
+ {
+ rl = divisor - rl;
+ rp[0] = rl & GMP_NUMB_MASK;
+ rp[1] = rl >> GMP_NUMB_BITS;
+ }
+
+ rn = 1 + (rl > GMP_NUMB_MAX); rn -= (rp[rn - 1] == 0);
+ }
+ else
+#endif
+ {
+ rl = mpn_mod_1 (np, nn, (mp_limb_t) divisor);
+ if (rl == 0)
+ ;
+ else
+ {
+ if (ns >= 0)
+ rl = divisor - rl;
+ }
+ }
+
+ return rl;
}