1 /* mpfr_frexp -- convert to integral and fractional parts 2 3 Copyright 2011-2020 Free Software Foundation, Inc. 4 Contributed by the AriC and Caramba projects, INRIA. 5 6 This file is part of the GNU MPFR Library. 7 8 The GNU MPFR Library is free software; you can redistribute it and/or modify 9 it under the terms of the GNU Lesser General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or (at your 11 option) any later version. 12 13 The GNU MPFR Library is distributed in the hope that it will be useful, but 14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 16 License for more details. 17 18 You should have received a copy of the GNU Lesser General Public License 19 along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see 20 https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., 21 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ 22 23 #include "mpfr-impl.h" 24 25 int 26 mpfr_frexp (mpfr_exp_t *exp, mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd) 27 { 28 int inex; 29 mpfr_flags_t saved_flags = __gmpfr_flags; 30 MPFR_BLOCK_DECL (flags); 31 32 MPFR_LOG_FUNC 33 (("x[%Pu]=%.*Rg rnd=%d", mpfr_get_prec (x), mpfr_log_prec, x, rnd), 34 ("y[%Pu]=%.*Rg exp=%" MPFR_EXP_FSPEC "d inex=%d", mpfr_get_prec (y), 35 mpfr_log_prec, y, (mpfr_eexp_t) *exp, inex)); 36 37 if (MPFR_UNLIKELY(MPFR_IS_SINGULAR(x))) 38 { 39 if (MPFR_IS_NAN(x)) 40 { 41 MPFR_SET_NAN(y); 42 MPFR_RET_NAN; /* exp is unspecified */ 43 } 44 else if (MPFR_IS_INF(x)) 45 { 46 MPFR_SET_INF(y); 47 MPFR_SET_SAME_SIGN(y,x); 48 MPFR_RET(0); /* exp is unspecified */ 49 } 50 else 51 { 52 MPFR_SET_ZERO(y); 53 MPFR_SET_SAME_SIGN(y,x); 54 *exp = 0; 55 MPFR_RET(0); 56 } 57 } 58 59 MPFR_BLOCK (flags, inex = mpfr_set (y, x, rnd)); 60 __gmpfr_flags = saved_flags; 61 62 /* Possible overflow due to the rounding, no possible underflow. */ 63 64 if (MPFR_UNLIKELY (MPFR_OVERFLOW (flags))) 65 { 66 int inex2; 67 68 /* An overflow here means that the exponent of y would be larger than 69 the one of x, thus x would be rounded to the next power of 2, and 70 the returned y should be 1/2 in absolute value, rounded (i.e. with 71 possible underflow or overflow). This also implies that x and y are 72 different objects, so that the exponent of x has not been lost. */ 73 MPFR_LOG_MSG (("Internal overflow\n", 0)); 74 MPFR_ASSERTD (x != y); 75 *exp = MPFR_GET_EXP (x) + 1; 76 inex2 = mpfr_set_si_2exp (y, MPFR_INT_SIGN (x), -1, rnd); 77 MPFR_LOG_MSG (("inex=%d inex2=%d\n", inex, inex2)); 78 if (inex2 != 0) 79 inex = inex2; 80 MPFR_RET (inex); 81 } 82 83 *exp = MPFR_GET_EXP (y); 84 /* Do not use MPFR_SET_EXP because the range has not been checked yet. */ 85 MPFR_EXP (y) = 0; 86 return mpfr_check_range (y, inex, rnd); 87 } 88