1/* mpfr_fits_intmax_p -- test whether an mpfr fits an intmax_t. 2 3Copyright 2004, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. 4Contributed by the Arenaire and Cacao 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 20http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., 2151 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ 22 23#ifdef HAVE_CONFIG_H 24# include "config.h" /* for a build within gmp */ 25#endif 26 27/* The ISO C99 standard specifies that in C++ implementations the 28 INTMAX_MAX, ... macros should only be defined if explicitly requested. */ 29#if defined __cplusplus 30# define __STDC_LIMIT_MACROS 31# define __STDC_CONSTANT_MACROS 32#endif 33 34#if HAVE_INTTYPES_H 35# include <inttypes.h> /* for intmax_t */ 36#else 37# if HAVE_STDINT_H 38# include <stdint.h> 39# endif 40#endif 41 42#include "mpfr-impl.h" 43 44#ifdef _MPFR_H_HAVE_INTMAX_T 45 46/* We can't use fits_s.h <= mpfr_cmp_ui */ 47int 48mpfr_fits_intmax_p (mpfr_srcptr f, mpfr_rnd_t rnd) 49{ 50 mpfr_exp_t e; 51 int prec; 52 mpfr_t x, y; 53 int neg; 54 int res; 55 56 if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (f))) 57 /* Zero always fit */ 58 return MPFR_IS_ZERO (f) ? 1 : 0; 59 60 /* now it fits if either 61 (a) MINIMUM <= f <= MAXIMUM 62 (b) or MINIMUM <= round(f, prec(slong), rnd) <= MAXIMUM */ 63 64 e = MPFR_EXP (f); 65 if (e < 1) 66 return 1; /* |f| < 1: always fits */ 67 68 neg = MPFR_IS_NEG (f); 69 70 /* let EXTREMUM be MAXIMUM if f > 0, and MINIMUM if f < 0 */ 71 72 /* first compute prec(EXTREMUM), this could be done at configure time, 73 but the result can depend on neg (the loop is moved inside the "if" 74 to give the compiler a better chance to compute prec statically) */ 75 if (neg) 76 { 77 uintmax_t s; 78 /* In C89, the division on negative integers isn't well-defined. */ 79 s = SAFE_ABS (uintmax_t, MPFR_INTMAX_MIN); 80 for (prec = 0; s != 0; s /= 2, prec ++); 81 } 82 else 83 { 84 intmax_t s; 85 s = MPFR_INTMAX_MAX; 86 for (prec = 0; s != 0; s /= 2, prec ++); 87 } 88 89 /* EXTREMUM needs prec bits, i.e. 2^(prec-1) <= |EXTREMUM| < 2^prec */ 90 91 /* if e <= prec - 1, then f < 2^(prec-1) <= |EXTREMUM| */ 92 if (e <= prec - 1) 93 return 1; 94 95 /* if e >= prec + 1, then f >= 2^prec > |EXTREMUM| */ 96 if (e >= prec + 1) 97 return 0; 98 99 MPFR_ASSERTD (e == prec); 100 101 /* hard case: first round to prec bits, then check */ 102 mpfr_init2 (x, prec); 103 mpfr_set (x, f, rnd); 104 105 if (neg) 106 { 107 mpfr_init2 (y, prec); 108 mpfr_set_sj (y, MPFR_INTMAX_MIN, MPFR_RNDN); 109 res = mpfr_cmp (x, y) >= 0; 110 mpfr_clear (y); 111 } 112 else 113 { 114 res = MPFR_GET_EXP (x) == e; 115 } 116 117 mpfr_clear (x); 118 return res; 119} 120 121#endif 122