1/* mpfr_fits_intmax_p -- test whether an mpfr fits an intmax_t. 2 3Copyright 2004, 2006-2023 Free Software Foundation, Inc. 4Contributed by the AriC and Caramba projects, INRIA. 5 6This file is part of the GNU MPFR Library. 7 8The GNU MPFR Library is free software; you can redistribute it and/or modify 9it under the terms of the GNU Lesser General Public License as published by 10the Free Software Foundation; either version 3 of the License, or (at your 11option) any later version. 12 13The GNU MPFR Library is distributed in the hope that it will be useful, but 14WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 16License for more details. 17 18You should have received a copy of the GNU Lesser General Public License 19along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see 20https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., 2151 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ 22 23#define MPFR_NEED_INTMAX_H 24#include "mpfr-impl.h" 25 26#ifdef _MPFR_H_HAVE_INTMAX_T 27 28/* We can't use fits_s.h as it uses mpfr_cmp_si */ 29int 30mpfr_fits_intmax_p (mpfr_srcptr f, mpfr_rnd_t rnd) 31{ 32 mpfr_flags_t saved_flags; 33 mpfr_exp_t e; 34 int prec; 35 mpfr_t x, y; 36 int neg; 37 int res; 38 39 if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (f))) 40 /* Zero always fit */ 41 return MPFR_IS_ZERO (f) ? 1 : 0; 42 43 /* now it fits if either 44 (a) MINIMUM <= f <= MAXIMUM 45 (b) or MINIMUM <= round(f, prec(slong), rnd) <= MAXIMUM */ 46 47 e = MPFR_EXP (f); 48 if (e < 1) 49 return 1; /* |f| < 1: always fits */ 50 51 neg = MPFR_IS_NEG (f); 52 53 /* let EXTREMUM be MAXIMUM if f > 0, and MINIMUM if f < 0 */ 54 55 /* first compute prec(EXTREMUM), this could be done at configure time, 56 but the result can depend on neg (the loop is moved inside the "if" 57 to give the compiler a better chance to compute prec statically) */ 58 if (neg) 59 { 60 uintmax_t s; 61 /* In C90, the division on negative integers isn't well-defined. */ 62 s = SAFE_ABS (uintmax_t, INTMAX_MIN); 63 for (prec = 0; s != 0; s /= 2, prec ++); 64 } 65 else 66 { 67 intmax_t s; 68 s = INTMAX_MAX; 69 for (prec = 0; s != 0; s /= 2, prec ++); 70 } 71 72 /* EXTREMUM needs prec bits, i.e. 2^(prec-1) <= |EXTREMUM| < 2^prec */ 73 74 /* if e <= prec - 1, then f < 2^(prec-1) <= |EXTREMUM| */ 75 if (e <= prec - 1) 76 return 1; 77 78 /* if e >= prec + 1, then f >= 2^prec > |EXTREMUM| */ 79 if (e >= prec + 1) 80 return 0; 81 82 MPFR_ASSERTD (e == prec); 83 84 /* hard case: first round to prec bits, then check */ 85 saved_flags = __gmpfr_flags; 86 mpfr_init2 (x, prec); 87 /* for RNDF, it is necessary and sufficient to check it fits when rounding 88 away from zero */ 89 mpfr_set (x, f, (rnd == MPFR_RNDF) ? MPFR_RNDA : rnd); 90 91 if (neg) 92 { 93 mpfr_init2 (y, prec); 94 mpfr_set_sj (y, INTMAX_MIN, MPFR_RNDN); 95 res = mpfr_cmp (x, y) >= 0; 96 mpfr_clear (y); 97 } 98 else 99 { 100 /* Warning! Due to the rounding, x can be an infinity. Here we use 101 the fact that singular numbers have a special exponent field, 102 thus well-defined and different from e, in which case this means 103 that the number does not fit. That's why we use MPFR_EXP, not 104 MPFR_GET_EXP. */ 105 res = MPFR_EXP (x) == e; 106 } 107 108 mpfr_clear (x); 109 __gmpfr_flags = saved_flags; 110 return res; 111} 112 113#endif 114