1/* mpfr_frexp -- convert to integral and fractional parts 2 3Copyright 2011-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#include "mpfr-impl.h" 24 25int 26mpfr_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[%Pd]=%.*Rg rnd=%d", mpfr_get_prec (x), mpfr_log_prec, x, rnd), 34 ("y[%Pd]=%.*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