1/* mpfr_mul_ui -- multiply a floating-point number by a machine integer 2 mpfr_mul_si -- multiply a floating-point number by a machine integer 3 4Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. 5Contributed by the AriC and Caramel projects, INRIA. 6 7This file is part of the GNU MPFR Library. 8 9The GNU MPFR Library is free software; you can redistribute it and/or modify 10it under the terms of the GNU Lesser General Public License as published by 11the Free Software Foundation; either version 3 of the License, or (at your 12option) any later version. 13 14The GNU MPFR Library is distributed in the hope that it will be useful, but 15WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 17License for more details. 18 19You should have received a copy of the GNU Lesser General Public License 20along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see 21http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., 2251 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ 23 24#define MPFR_NEED_LONGLONG_H 25#include "mpfr-impl.h" 26 27int 28mpfr_mul_ui (mpfr_ptr y, mpfr_srcptr x, unsigned long int u, mpfr_rnd_t rnd_mode) 29{ 30 mp_limb_t *yp; 31 mp_size_t xn; 32 int cnt, inexact; 33 MPFR_TMP_DECL (marker); 34 35 if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x))) 36 { 37 if (MPFR_IS_NAN (x)) 38 { 39 MPFR_SET_NAN (y); 40 MPFR_RET_NAN; 41 } 42 else if (MPFR_IS_INF (x)) 43 { 44 if (u != 0) 45 { 46 MPFR_SET_INF (y); 47 MPFR_SET_SAME_SIGN (y, x); 48 MPFR_RET (0); /* infinity is exact */ 49 } 50 else /* 0 * infinity */ 51 { 52 MPFR_SET_NAN (y); 53 MPFR_RET_NAN; 54 } 55 } 56 else /* x is zero */ 57 { 58 MPFR_ASSERTD (MPFR_IS_ZERO (x)); 59 MPFR_SET_ZERO (y); 60 MPFR_SET_SAME_SIGN (y, x); 61 MPFR_RET (0); /* zero is exact */ 62 } 63 } 64 else if (MPFR_UNLIKELY (u <= 1)) 65 { 66 if (u < 1) 67 { 68 MPFR_SET_ZERO (y); 69 MPFR_SET_SAME_SIGN (y, x); 70 MPFR_RET (0); /* zero is exact */ 71 } 72 else 73 return mpfr_set (y, x, rnd_mode); 74 } 75 else if (MPFR_UNLIKELY (IS_POW2 (u))) 76 return mpfr_mul_2si (y, x, MPFR_INT_CEIL_LOG2 (u), rnd_mode); 77 78 yp = MPFR_MANT (y); 79 xn = MPFR_LIMB_SIZE (x); 80 81 MPFR_ASSERTD (xn < MP_SIZE_T_MAX); 82 MPFR_TMP_MARK(marker); 83 yp = MPFR_TMP_LIMBS_ALLOC (xn + 1); 84 85 MPFR_ASSERTN (u == (mp_limb_t) u); 86 yp[xn] = mpn_mul_1 (yp, MPFR_MANT (x), xn, u); 87 88 /* x * u is stored in yp[xn], ..., yp[0] */ 89 90 /* since the case u=1 was treated above, we have u >= 2, thus 91 yp[xn] >= 1 since x was msb-normalized */ 92 MPFR_ASSERTD (yp[xn] != 0); 93 if (MPFR_LIKELY (MPFR_LIMB_MSB (yp[xn]) == 0)) 94 { 95 count_leading_zeros (cnt, yp[xn]); 96 mpn_lshift (yp, yp, xn + 1, cnt); 97 } 98 else 99 { 100 cnt = 0; 101 } 102 103 /* now yp[xn], ..., yp[0] is msb-normalized too, and has at most 104 PREC(x) + (GMP_NUMB_BITS - cnt) non-zero bits */ 105 MPFR_RNDRAW (inexact, y, yp, (mpfr_prec_t) (xn + 1) * GMP_NUMB_BITS, 106 rnd_mode, MPFR_SIGN (x), cnt -- ); 107 108 MPFR_TMP_FREE (marker); 109 110 cnt = GMP_NUMB_BITS - cnt; 111 if (MPFR_UNLIKELY (__gmpfr_emax < MPFR_EMAX_MIN + cnt 112 || MPFR_GET_EXP (x) > __gmpfr_emax - cnt)) 113 return mpfr_overflow (y, rnd_mode, MPFR_SIGN(x)); 114 115 MPFR_SET_EXP (y, MPFR_GET_EXP (x) + cnt); 116 MPFR_SET_SAME_SIGN (y, x); 117 118 return inexact; 119} 120 121int mpfr_mul_si (mpfr_ptr y, mpfr_srcptr x, long int u, mpfr_rnd_t rnd_mode) 122{ 123 int res; 124 125 if (u >= 0) 126 res = mpfr_mul_ui (y, x, u, rnd_mode); 127 else 128 { 129 res = -mpfr_mul_ui (y, x, -u, MPFR_INVERT_RND (rnd_mode)); 130 MPFR_CHANGE_SIGN (y); 131 } 132 return res; 133} 134