1 /* mpfr_div_{ui,si} -- divide a floating-point number by a machine integer
3 Copyright 1999-2016 Free Software Foundation, Inc.
4 Contributed by the AriC and Caramba projects, INRIA.
6 This file is part of the GNU MPFR Library.
8 The GNU MPFR Library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
13 The GNU MPFR Library is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16 License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see
20 http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
21 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
23 #define MPFR_NEED_LONGLONG_H
24 #include "mpfr-impl.h"
26 /* returns 0 if result exact, non-zero otherwise */
28 mpfr_div_ui (mpfr_ptr y
, mpfr_srcptr x
, unsigned long int u
, mpfr_rnd_t rnd_mode
)
32 mp_size_t xn
, yn
, dif
;
33 mp_limb_t
*xp
, *yp
, *tmp
, c
, d
;
35 int inexact
, middle
= 1, nexttoinf
;
36 MPFR_TMP_DECL(marker
);
39 (("x[%Pu]=%.*Rg u=%lu rnd=%d",
40 mpfr_get_prec(x
), mpfr_log_prec
, x
, u
, rnd_mode
),
41 ("y[%Pu]=%.*Rg inexact=%d",
42 mpfr_get_prec(y
), mpfr_log_prec
, y
, inexact
));
44 if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x
)))
51 else if (MPFR_IS_INF (x
))
54 MPFR_SET_SAME_SIGN (y
, x
);
59 MPFR_ASSERTD (MPFR_IS_ZERO(x
));
60 if (u
== 0) /* 0/0 is NaN */
68 MPFR_SET_SAME_SIGN (y
, x
);
73 else if (MPFR_UNLIKELY (u
<= 1))
77 /* x/0 is Inf since x != 0*/
79 MPFR_SET_SAME_SIGN (y
, x
);
83 else /* y = x/1 = x */
84 return mpfr_set (y
, x
, rnd_mode
);
86 else if (MPFR_UNLIKELY (IS_POW2 (u
)))
87 return mpfr_div_2si (y
, x
, MPFR_INT_CEIL_LOG2 (u
), rnd_mode
);
89 MPFR_SET_SAME_SIGN (y
, x
);
91 MPFR_TMP_MARK (marker
);
92 xn
= MPFR_LIMB_SIZE (x
);
93 yn
= MPFR_LIMB_SIZE (y
);
97 exp
= MPFR_GET_EXP (x
);
101 /* we need to store yn+1 = xn + dif limbs of the quotient */
102 /* don't use tmp=yp since the mpn_lshift call below requires yp >= tmp+1 */
103 tmp
= MPFR_TMP_LIMBS_ALLOC (yn
+ 1);
106 MPFR_ASSERTN (u
== c
);
108 c
= mpn_divrem_1 (tmp
, dif
, xp
, xn
, c
); /* used all the dividend */
109 else /* dif < 0 i.e. xn > yn, don't use the (-dif) low limbs from x */
110 c
= mpn_divrem_1 (tmp
, 0, xp
- dif
, yn
+ 1, c
);
114 /* First pass in estimating next bit of the quotient, in case of RNDN *
115 * In case we just have the right number of bits (postpone this ?), *
116 * we need to check whether the remainder is more or less than half *
117 * the divisor. The test must be performed with a subtraction, so as *
118 * to prevent carries. */
120 if (MPFR_LIKELY (rnd_mode
== MPFR_RNDN
))
122 if (c
< (mp_limb_t
) u
- c
) /* We have u > c */
124 else if (c
> (mp_limb_t
) u
- c
)
127 middle
= 0; /* exactly in the middle */
130 /* If we believe that we are right in the middle or exact, we should check
131 that we did not neglect any word of x (division large / 1 -> small). */
133 for (i
=0; ((inexact
== 0) || (middle
== 0)) && (i
< -dif
); i
++)
135 inexact
= middle
= 1; /* larger than middle */
138 If the high limb of the result is 0 (xp[xn-1] < u), remove it.
139 Otherwise, compute the left shift to be performed to normalize.
140 In the latter case, we discard some low bits computed. They
141 contain information useful for the rounding, hence the updating
142 of middle and inexact.
147 MPN_COPY(yp
, tmp
, yn
);
148 exp
-= GMP_NUMB_BITS
;
154 count_leading_zeros (shlz
, tmp
[yn
]);
156 /* shift left to normalize */
157 if (MPFR_LIKELY (shlz
!= 0))
159 mp_limb_t w
= tmp
[0] << shlz
;
161 mpn_lshift (yp
, tmp
+ 1, yn
, shlz
);
162 yp
[0] += tmp
[0] >> (GMP_NUMB_BITS
- shlz
);
164 if (w
> (MPFR_LIMB_ONE
<< (GMP_NUMB_BITS
- 1)))
166 else if (w
< (MPFR_LIMB_ONE
<< (GMP_NUMB_BITS
- 1)))
169 { middle
= (c
!= 0); }
171 inexact
= inexact
|| (w
!= 0);
175 { /* this happens only if u == 1 and xp[xn-1] >=
176 1<<(GMP_NUMB_BITS-1). It might be better to handle the
177 u == 1 case separately?
180 MPN_COPY (yp
, tmp
+ 1, yn
);
184 MPFR_UNSIGNED_MINUS_MODULO (sh
, MPFR_PREC (y
));
185 /* it remains sh bits in less significant limb of y */
187 d
= *yp
& MPFR_LIMB_MASK (sh
);
188 *yp
^= d
; /* set to zero lowest sh bits */
190 MPFR_TMP_FREE (marker
);
192 if (exp
< __gmpfr_emin
- 1)
193 return mpfr_underflow (y
, rnd_mode
== MPFR_RNDN
? MPFR_RNDZ
: rnd_mode
,
196 if (MPFR_UNLIKELY (d
== 0 && inexact
== 0))
197 nexttoinf
= 0; /* result is exact */
200 MPFR_UPDATE2_RND_MODE(rnd_mode
, MPFR_SIGN (y
));
204 inexact
= - MPFR_INT_SIGN (y
); /* result is inexact */
209 inexact
= MPFR_INT_SIGN (y
);
213 default: /* should be MPFR_RNDN */
214 MPFR_ASSERTD (rnd_mode
== MPFR_RNDN
);
215 /* We have one more significant bit in yn. */
216 if (sh
&& d
< (MPFR_LIMB_ONE
<< (sh
- 1)))
218 inexact
= - MPFR_INT_SIGN (y
);
221 else if (sh
&& d
> (MPFR_LIMB_ONE
<< (sh
- 1)))
223 inexact
= MPFR_INT_SIGN (y
);
226 else /* sh = 0 or d = 1 << (sh-1) */
228 /* The first case is "false" even rounding (significant bits
229 indicate even rounding, but the result is inexact, so up) ;
230 The second case is the case where middle should be used to
231 decide the direction of rounding (no further bit computed) ;
232 The third is the true even rounding.
234 if ((sh
&& inexact
) || (!sh
&& middle
> 0) ||
235 (!inexact
&& *yp
& (MPFR_LIMB_ONE
<< sh
)))
237 inexact
= MPFR_INT_SIGN (y
);
242 inexact
= - MPFR_INT_SIGN (y
);
250 MPFR_UNLIKELY (mpn_add_1 (yp
, yp
, yn
, MPFR_LIMB_ONE
<< sh
)))
253 yp
[yn
-1] = MPFR_LIMB_HIGHBIT
;
256 /* Set the exponent. Warning! One may still have an underflow. */
259 return mpfr_check_range (y
, inexact
, rnd_mode
);
263 mpfr_div_si (mpfr_ptr y
, mpfr_srcptr x
, long int u
, mpfr_rnd_t rnd_mode
)
268 (("x[%Pu]=%.*Rg u=%ld rnd=%d",
269 mpfr_get_prec(x
), mpfr_log_prec
, x
, u
, rnd_mode
),
270 ("y[%Pu]=%.*Rg inexact=%d",
271 mpfr_get_prec(y
), mpfr_log_prec
, y
, res
));
274 res
= mpfr_div_ui (y
, x
, u
, rnd_mode
);
277 res
= - mpfr_div_ui (y
, x
, - (unsigned long) u
,
278 MPFR_INVERT_RND (rnd_mode
));
279 MPFR_CHANGE_SIGN (y
);