1 1.1 mrg /* mpfr_set_ui_2exp -- set a MPFR number from a machine unsigned integer with 2 1.1 mrg a shift 3 1.1 mrg 4 1.1.1.5 mrg Copyright 2004, 2006-2023 Free Software Foundation, Inc. 5 1.1.1.2 mrg Contributed by the AriC and Caramba projects, INRIA. 6 1.1 mrg 7 1.1 mrg This file is part of the GNU MPFR Library. 8 1.1 mrg 9 1.1 mrg The GNU MPFR Library is free software; you can redistribute it and/or modify 10 1.1 mrg it under the terms of the GNU Lesser General Public License as published by 11 1.1 mrg the Free Software Foundation; either version 3 of the License, or (at your 12 1.1 mrg option) any later version. 13 1.1 mrg 14 1.1 mrg The GNU MPFR Library is distributed in the hope that it will be useful, but 15 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16 1.1 mrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 17 1.1 mrg License for more details. 18 1.1 mrg 19 1.1 mrg You should have received a copy of the GNU Lesser General Public License 20 1.1 mrg along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see 21 1.1.1.4 mrg https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., 22 1.1 mrg 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ 23 1.1 mrg 24 1.1 mrg #define MPFR_NEED_LONGLONG_H 25 1.1 mrg #include "mpfr-impl.h" 26 1.1 mrg 27 1.1.1.3 mrg MPFR_HOT_FUNCTION_ATTR int 28 1.1 mrg mpfr_set_ui_2exp (mpfr_ptr x, unsigned long i, mpfr_exp_t e, mpfr_rnd_t rnd_mode) 29 1.1 mrg { 30 1.1 mrg MPFR_SET_POS (x); 31 1.1 mrg 32 1.1.1.3 mrg if (MPFR_UNLIKELY (i == 0)) 33 1.1 mrg { 34 1.1 mrg MPFR_SET_ZERO (x); 35 1.1 mrg MPFR_RET (0); 36 1.1 mrg } 37 1.1 mrg else 38 1.1 mrg { 39 1.1.1.4 mrg #ifdef MPFR_LONG_WITHIN_LIMB 40 1.1 mrg mp_size_t xn; 41 1.1.1.3 mrg int cnt, nbits; 42 1.1 mrg mp_limb_t *xp; 43 1.1 mrg int inex = 0; 44 1.1 mrg 45 1.1.1.4 mrg /* Early underflow/overflow checking is necessary to avoid 46 1.1.1.4 mrg integer overflow or errors due to special exponent values. */ 47 1.1.1.4 mrg if (MPFR_UNLIKELY (e < __gmpfr_emin - (mpfr_exp_t) 48 1.1.1.4 mrg (sizeof (unsigned long) * CHAR_BIT + 1))) 49 1.1.1.4 mrg return mpfr_underflow (x, rnd_mode == MPFR_RNDN ? 50 1.1.1.4 mrg MPFR_RNDZ : rnd_mode, i < 0 ? -1 : 1); 51 1.1.1.4 mrg if (MPFR_UNLIKELY (e >= __gmpfr_emax)) 52 1.1.1.4 mrg return mpfr_overflow (x, rnd_mode, i < 0 ? -1 : 1); 53 1.1.1.4 mrg 54 1.1 mrg MPFR_ASSERTD (i == (mp_limb_t) i); 55 1.1 mrg 56 1.1 mrg /* Position of the highest limb */ 57 1.1 mrg xn = (MPFR_PREC (x) - 1) / GMP_NUMB_BITS; 58 1.1 mrg count_leading_zeros (cnt, (mp_limb_t) i); 59 1.1 mrg MPFR_ASSERTD (cnt < GMP_NUMB_BITS); /* OK since i != 0 */ 60 1.1 mrg 61 1.1 mrg xp = MPFR_MANT(x); 62 1.1 mrg xp[xn] = ((mp_limb_t) i) << cnt; 63 1.1 mrg /* Zero the xn lower limbs. */ 64 1.1 mrg MPN_ZERO(xp, xn); 65 1.1 mrg 66 1.1 mrg nbits = GMP_NUMB_BITS - cnt; 67 1.1 mrg e += nbits; /* exponent _before_ the rounding */ 68 1.1 mrg 69 1.1 mrg /* round if MPFR_PREC(x) smaller than length of i */ 70 1.1 mrg if (MPFR_UNLIKELY (MPFR_PREC (x) < nbits) && 71 1.1 mrg MPFR_UNLIKELY (mpfr_round_raw (xp + xn, xp + xn, nbits, 0, 72 1.1 mrg MPFR_PREC (x), rnd_mode, &inex))) 73 1.1 mrg { 74 1.1 mrg e++; 75 1.1 mrg xp[xn] = MPFR_LIMB_HIGHBIT; 76 1.1 mrg } 77 1.1 mrg 78 1.1 mrg MPFR_EXP (x) = e; 79 1.1 mrg return mpfr_check_range (x, inex, rnd_mode); 80 1.1.1.4 mrg #else 81 1.1.1.4 mrg /* if a long does not fit into a limb, we use mpfr_set_z_2exp */ 82 1.1.1.4 mrg mpz_t z; 83 1.1.1.4 mrg int inex; 84 1.1.1.4 mrg 85 1.1.1.4 mrg mpz_init_set_ui (z, i); 86 1.1.1.4 mrg inex = mpfr_set_z_2exp (x, z, e, rnd_mode); 87 1.1.1.4 mrg mpz_clear (z); 88 1.1.1.4 mrg return inex; 89 1.1.1.4 mrg #endif 90 1.1 mrg } 91 1.1 mrg } 92