version 1.1.1.2, 2000/09/09 14:12:24 |
version 1.1.1.3, 2003/08/25 16:06:20 |
|
|
/* mpn/bdivmod.c: mpn_bdivmod for computing U/V mod 2^d. |
/* mpn/bdivmod.c: mpn_bdivmod for computing U/V mod 2^d. |
|
|
Copyright (C) 1991, 1993, 1994, 1995, 1996, 1999, 2000 Free Software |
Copyright 1991, 1993, 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software |
Foundation, Inc. |
Foundation, Inc. |
|
|
This file is part of the GNU MP Library. |
This file is part of the GNU MP Library. |
Line 52 MA 02111-1307, USA. */ |
|
Line 52 MA 02111-1307, USA. */ |
|
#include "gmp-impl.h" |
#include "gmp-impl.h" |
#include "longlong.h" |
#include "longlong.h" |
|
|
|
|
mp_limb_t |
mp_limb_t |
#if __STDC__ |
|
mpn_bdivmod (mp_ptr qp, mp_ptr up, mp_size_t usize, |
mpn_bdivmod (mp_ptr qp, mp_ptr up, mp_size_t usize, |
mp_srcptr vp, mp_size_t vsize, unsigned long int d) |
mp_srcptr vp, mp_size_t vsize, unsigned long int d) |
#else |
|
mpn_bdivmod (qp, up, usize, vp, vsize, d) |
|
mp_ptr qp; |
|
mp_ptr up; |
|
mp_size_t usize; |
|
mp_srcptr vp; |
|
mp_size_t vsize; |
|
unsigned long int d; |
|
#endif |
|
{ |
{ |
mp_limb_t v_inv; |
mp_limb_t v_inv; |
|
|
/* 1/V mod 2^BITS_PER_MP_LIMB. */ |
ASSERT (usize >= 1); |
|
ASSERT (vsize >= 1); |
|
ASSERT (usize * GMP_NUMB_BITS >= d); |
|
ASSERT (! MPN_OVERLAP_P (up, usize, vp, vsize)); |
|
ASSERT (! MPN_OVERLAP_P (qp, d/GMP_NUMB_BITS, vp, vsize)); |
|
ASSERT (MPN_SAME_OR_INCR2_P (qp, d/GMP_NUMB_BITS, up, usize)); |
|
ASSERT_MPN (up, usize); |
|
ASSERT_MPN (vp, vsize); |
|
|
|
/* 1/V mod 2^GMP_NUMB_BITS. */ |
modlimb_invert (v_inv, vp[0]); |
modlimb_invert (v_inv, vp[0]); |
|
|
/* Fast code for two cases previously used by the accel part of mpn_gcd. |
/* Fast code for two cases previously used by the accel part of mpn_gcd. |
(Could probably remove this now it's inlined there.) */ |
(Could probably remove this now it's inlined there.) */ |
if (usize == 2 && vsize == 2 && |
if (usize == 2 && vsize == 2 && |
(d == BITS_PER_MP_LIMB || d == 2*BITS_PER_MP_LIMB)) |
(d == GMP_NUMB_BITS || d == 2*GMP_NUMB_BITS)) |
{ |
{ |
mp_limb_t hi, lo; |
mp_limb_t hi, lo; |
mp_limb_t q = up[0] * v_inv; |
mp_limb_t q = (up[0] * v_inv) & GMP_NUMB_MASK; |
umul_ppmm (hi, lo, q, vp[0]); |
umul_ppmm (hi, lo, q, vp[0] << GMP_NAIL_BITS); |
up[0] = 0, up[1] -= hi + q*vp[1], qp[0] = q; |
up[0] = 0; |
if (d == 2*BITS_PER_MP_LIMB) |
up[1] -= hi + q*vp[1]; |
q = up[1] * v_inv, up[1] = 0, qp[1] = q; |
qp[0] = q; |
|
if (d == 2*GMP_NUMB_BITS) |
|
{ |
|
q = (up[1] * v_inv) & GMP_NUMB_MASK; |
|
up[1] = 0; |
|
qp[1] = q; |
|
} |
return 0; |
return 0; |
} |
} |
|
|
/* Main loop. */ |
/* Main loop. */ |
while (d >= BITS_PER_MP_LIMB) |
while (d >= GMP_NUMB_BITS) |
{ |
{ |
mp_limb_t q = up[0] * v_inv; |
mp_limb_t q = (up[0] * v_inv) & GMP_NUMB_MASK; |
mp_limb_t b = mpn_submul_1 (up, vp, MIN (usize, vsize), q); |
mp_limb_t b = mpn_submul_1 (up, vp, MIN (usize, vsize), q); |
if (usize > vsize) |
if (usize > vsize) |
mpn_sub_1 (up + vsize, up + vsize, usize - vsize, b); |
mpn_sub_1 (up + vsize, up + vsize, usize - vsize, b); |
d -= BITS_PER_MP_LIMB; |
d -= GMP_NUMB_BITS; |
up += 1, usize -= 1; |
up += 1, usize -= 1; |
*qp++ = q; |
*qp++ = q; |
} |
} |