summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorzimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4>2014-06-25 08:05:09 +0000
committerzimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4>2014-06-25 08:05:09 +0000
commit6d9eb54d507684e38c2baa84bbd03611795ce2db (patch)
tree751ddb999f32bac0a56aba8b70f3cb4bab96407b /src
parent642b7ce46f1e5899f1b92cbee8437de4ab525872 (diff)
downloadmpfr-6d9eb54d507684e38c2baa84bbd03611795ce2db.tar.gz
speedup of mpfr_div when divisor has one limb
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@9086 280ebfd0-de03-0410-8827-d642c229c3f4
Diffstat (limited to 'src')
-rw-r--r--src/div.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/src/div.c b/src/div.c
index a5c12036b..6e30268e9 100644
--- a/src/div.c
+++ b/src/div.c
@@ -240,6 +240,28 @@ mpfr_div (mpfr_ptr q, mpfr_srcptr u, mpfr_srcptr v, mpfr_rnd_t rnd_mode)
* *
**************************************************************************/
+ /* when the divisor has one limb, we can use mpfr_div_ui, which should be
+ faster, assuming there is no intermediate overflow or underflow.
+ The divisor interpreted as an integer satisfies
+ 2^(GMP_NUMB_BITS-1) <= vm < 2^GMP_NUMB_BITS, thus the quotient
+ satisfies 2^(EXP(u)-1-GMP_NUMB_BITS) < u/vm < 2^(EXP(u)-GMP_NUMB_BITS+1)
+ and its exponent is either EXP(u)-GMP_NUMB_BITS or one more. */
+ if (vsize <= 1 && __gmpfr_emin <= MPFR_EXP(u) - GMP_NUMB_BITS
+ && MPFR_EXP(u) - GMP_NUMB_BITS + 1 <= __gmpfr_emax)
+ {
+ mpfr_exp_t exp_v = MPFR_EXP(v); /* save it in case q=v */
+ if (MPFR_SIGN(v) > 0)
+ inex = mpfr_div_ui (q, u, vp[0], rnd_mode);
+ else
+ {
+ inex = -mpfr_div_ui (q, u, vp[0], MPFR_INVERT_RND(rnd_mode));
+ MPFR_CHANGE_SIGN(q);
+ }
+ /* q did not under/overflow */
+ MPFR_EXP(q) -= exp_v - GMP_NUMB_BITS;
+ return mpfr_check_range (q, inex, rnd_mode);
+ }
+
MPFR_TMP_MARK(marker);
/* set sign */