Home | History | Annotate | Line # | Download | only in src
      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