1/* mpfr_get_flt -- convert a mpfr_t to a machine single precision float 2 3Copyright 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. 4Contributed by the AriC and Caramel 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#include <float.h> /* for FLT_MIN */ 24 25#define MPFR_NEED_LONGLONG_H 26#include "mpfr-impl.h" 27 28#include "ieee_floats.h" 29 30#define FLT_NEG_ZERO ((float) DBL_NEG_ZERO) 31#define MPFR_FLT_INFM ((float) MPFR_DBL_INFM) 32#define MPFR_FLT_INFP ((float) MPFR_DBL_INFP) 33 34float 35mpfr_get_flt (mpfr_srcptr src, mpfr_rnd_t rnd_mode) 36{ 37 int negative; 38 mpfr_exp_t e; 39 float d; 40 41 /* in case of NaN, +Inf, -Inf, +0, -0, the conversion from double to float 42 is exact */ 43 if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (src))) 44 return (float) mpfr_get_d (src, rnd_mode); 45 46 e = MPFR_GET_EXP (src); 47 negative = MPFR_IS_NEG (src); 48 49 if (MPFR_UNLIKELY(rnd_mode == MPFR_RNDA)) 50 rnd_mode = negative ? MPFR_RNDD : MPFR_RNDU; 51 52 /* the smallest positive normal float number is 2^(-126) = 0.5*2^(-125), 53 and the smallest positive subnormal number is 2^(-149) = 0.5*2^(-148) */ 54 if (MPFR_UNLIKELY (e < -148)) 55 { 56 /* |src| < 2^(-149), i.e., |src| is smaller than the smallest positive 57 subnormal number. 58 In round-to-nearest mode, 2^(-150) is rounded to zero. 59 */ 60 d = negative ? 61 (rnd_mode == MPFR_RNDD || 62 (rnd_mode == MPFR_RNDN && mpfr_cmp_si_2exp (src, -1, -150) < 0) 63 ? -FLT_MIN : FLT_NEG_ZERO) : 64 (rnd_mode == MPFR_RNDU || 65 (rnd_mode == MPFR_RNDN && mpfr_cmp_si_2exp (src, 1, -150) > 0) 66 ? FLT_MIN : 0.0); 67 if (d != 0.0) /* we multiply FLT_MIN = 2^(-126) by FLT_EPSILON = 2^(-23) 68 to get +-2^(-149) */ 69 d *= FLT_EPSILON; 70 } 71 /* the largest normal number is 2^128*(1-2^(-24)) = 0.111...111e128 */ 72 else if (MPFR_UNLIKELY (e > 128)) 73 { 74 d = negative ? 75 (rnd_mode == MPFR_RNDZ || rnd_mode == MPFR_RNDU ? 76 -FLT_MAX : MPFR_FLT_INFM) : 77 (rnd_mode == MPFR_RNDZ || rnd_mode == MPFR_RNDD ? 78 FLT_MAX : MPFR_FLT_INFP); 79 } 80 else /* -148 <= e <= 127 */ 81 { 82 int nbits; 83 mp_size_t np, i; 84 mp_limb_t tp[MPFR_LIMBS_PER_FLT]; 85 int carry; 86 double dd; 87 88 nbits = IEEE_FLT_MANT_DIG; /* 24 */ 89 if (MPFR_UNLIKELY (e < -125)) 90 /*In the subnormal case, compute the exact number of significant bits*/ 91 { 92 nbits += (125 + e); 93 MPFR_ASSERTD (nbits >= 1); 94 } 95 np = MPFR_PREC2LIMBS (nbits); 96 MPFR_ASSERTD(np <= MPFR_LIMBS_PER_FLT); 97 carry = mpfr_round_raw_4 (tp, MPFR_MANT(src), MPFR_PREC(src), negative, 98 nbits, rnd_mode); 99 /* we perform the reconstruction using the 'double' type here, 100 knowing the result is exactly representable as 'float' */ 101 if (MPFR_UNLIKELY(carry)) 102 dd = 1.0; 103 else 104 { 105 /* The following computations are exact thanks to the previous 106 mpfr_round_raw. */ 107 dd = (double) tp[0] / MP_BASE_AS_DOUBLE; 108 for (i = 1 ; i < np ; i++) 109 dd = (dd + tp[i]) / MP_BASE_AS_DOUBLE; 110 /* dd is the mantissa (between 1/2 and 1) of the argument rounded 111 to 24 bits */ 112 } 113 dd = mpfr_scale2 (dd, e); 114 if (negative) 115 dd = -dd; 116 117 /* convert (exacly) to float */ 118 d = (float) dd; 119 } 120 121 return d; 122} 123 124