github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/mpn/generic/get_d.c (about) 1 /* mpn_get_d -- limbs to double conversion. 2 3 THE FUNCTIONS IN THIS FILE ARE FOR INTERNAL USE ONLY. THEY'RE ALMOST 4 CERTAIN TO BE SUBJECT TO INCOMPATIBLE CHANGES OR DISAPPEAR COMPLETELY IN 5 FUTURE GNU MP RELEASES. 6 7 Copyright 2003, 2004, 2007, 2009, 2010, 2012 Free Software Foundation, Inc. 8 9 This file is part of the GNU MP Library. 10 11 The GNU MP Library is free software; you can redistribute it and/or modify 12 it under the terms of either: 13 14 * the GNU Lesser General Public License as published by the Free 15 Software Foundation; either version 3 of the License, or (at your 16 option) any later version. 17 18 or 19 20 * the GNU General Public License as published by the Free Software 21 Foundation; either version 2 of the License, or (at your option) any 22 later version. 23 24 or both in parallel, as here. 25 26 The GNU MP Library is distributed in the hope that it will be useful, but 27 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 28 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 29 for more details. 30 31 You should have received copies of the GNU General Public License and the 32 GNU Lesser General Public License along with the GNU MP Library. If not, 33 see https://www.gnu.org/licenses/. */ 34 35 #include "gmp.h" 36 #include "gmp-impl.h" 37 #include "longlong.h" 38 39 #ifndef _GMP_IEEE_FLOATS 40 #define _GMP_IEEE_FLOATS 0 41 #endif 42 43 /* To force use of the generic C code for testing, put 44 "#define _GMP_IEEE_FLOATS 0" at this point. */ 45 46 47 /* In alpha gcc prior to 3.4, signed DI comparisons involving constants are 48 rearranged from "x < n" to "x+(-n) < 0", which is of course hopelessly 49 wrong if that addition overflows. 50 51 The workaround here avoids this bug by ensuring n is not a literal constant. 52 Note that this is alpha specific. The offending transformation is/was in 53 alpha.c alpha_emit_conditional_branch() under "We want to use cmpcc/bcc". 54 55 Bizarrely, this happens also with Cray cc on alphaev5-cray-unicosmk2.0.6.X, 56 and has the same solution. Don't know why or how. */ 57 58 #if HAVE_HOST_CPU_FAMILY_alpha \ 59 && ((defined (__GNUC__) && ! __GMP_GNUC_PREREQ(3,4)) \ 60 || defined (_CRAY)) 61 static volatile const long CONST_1024 = 1024; 62 static volatile const long CONST_NEG_1023 = -1023; 63 static volatile const long CONST_NEG_1022_SUB_53 = -1022 - 53; 64 #else 65 #define CONST_1024 (1024) 66 #define CONST_NEG_1023 (-1023) 67 #define CONST_NEG_1022_SUB_53 (-1022 - 53) 68 #endif 69 70 71 /* Return the value {ptr,size}*2^exp, and negative if sign<0. Must have 72 size>=1, and a non-zero high limb ptr[size-1]. 73 74 When we know the fp format, the result is truncated towards zero. This is 75 consistent with other gmp conversions, like mpz_set_f or mpz_set_q, and is 76 easy to implement and test. 77 78 When we do not know the format, such truncation seems much harder. One 79 would need to defeat any rounding mode, including round-up. 80 81 It's felt that GMP is not primarily concerned with hardware floats, and 82 really isn't enhanced by getting involved with hardware rounding modes 83 (which could even be some weird unknown style), so something unambiguous and 84 straightforward is best. 85 86 87 The IEEE code below is the usual case, it knows either a 32-bit or 64-bit 88 limb and is done with shifts and masks. The 64-bit case in particular 89 should come out nice and compact. 90 91 The generic code used to work one bit at a time, which was not only slow, 92 but implicitly relied upon denorms for intermediates, since the lowest bits' 93 weight of a perfectly valid fp number underflows in non-denorm. Therefore, 94 the generic code now works limb-per-limb, initially creating a number x such 95 that 1 <= x <= BASE. (BASE is reached only as result of rounding.) Then 96 x's exponent is scaled with explicit code (not ldexp to avoid libm 97 dependency). It is a tap-dance to avoid underflow or overflow, beware! 98 99 100 Traps: 101 102 Hardware traps for overflow to infinity, underflow to zero, or unsupported 103 denorms may or may not be taken. The IEEE code works bitwise and so 104 probably won't trigger them, the generic code works by float operations and 105 so probably will. This difference might be thought less than ideal, but 106 again its felt straightforward code is better than trying to get intimate 107 with hardware exceptions (of perhaps unknown nature). 108 109 110 Not done: 111 112 mpz_get_d in the past handled size==1 with a cast limb->double. This might 113 still be worthwhile there (for up to the mantissa many bits), but for 114 mpn_get_d here, the cost of applying "exp" to the resulting exponent would 115 probably use up any benefit a cast may have over bit twiddling. Also, if 116 the exponent is pushed into denorm range then bit twiddling is the only 117 option, to ensure the desired truncation is obtained. 118 119 120 Other: 121 122 For reference, note that HPPA 8000, 8200, 8500 and 8600 trap FCNV,UDW,DBL 123 to the kernel for values >= 2^63. This makes it slow, and worse the kernel 124 Linux (what versions?) apparently uses untested code in its trap handling 125 routines, and gets the sign wrong. We don't use such a limb-to-double 126 cast, neither in the IEEE or generic code. */ 127 128 129 130 #undef FORMAT_RECOGNIZED 131 132 double 133 mpn_get_d (mp_srcptr up, mp_size_t size, mp_size_t sign, long exp) 134 { 135 int lshift, nbits; 136 mp_limb_t x, mhi, mlo; 137 138 ASSERT (size >= 0); 139 ASSERT_MPN (up, size); 140 ASSERT (size == 0 || up[size-1] != 0); 141 142 if (size == 0) 143 return 0.0; 144 145 /* Adjust exp to a radix point just above {up,size}, guarding against 146 overflow. After this exp can of course be reduced to anywhere within 147 the {up,size} region without underflow. */ 148 if (UNLIKELY ((unsigned long) (GMP_NUMB_BITS * size) 149 > ((unsigned long) LONG_MAX - exp))) 150 { 151 #if _GMP_IEEE_FLOATS 152 goto ieee_infinity; 153 #endif 154 155 /* generic */ 156 exp = LONG_MAX; 157 } 158 else 159 { 160 exp += GMP_NUMB_BITS * size; 161 } 162 163 #if _GMP_IEEE_FLOATS 164 { 165 union ieee_double_extract u; 166 167 up += size; 168 169 #if GMP_LIMB_BITS == 64 170 mlo = up[-1]; 171 count_leading_zeros (lshift, mlo); 172 173 exp -= (lshift - GMP_NAIL_BITS) + 1; 174 mlo <<= lshift; 175 176 nbits = GMP_LIMB_BITS - lshift; 177 178 if (nbits < 53 && size > 1) 179 { 180 x = up[-2]; 181 x <<= GMP_NAIL_BITS; 182 x >>= nbits; 183 mlo |= x; 184 nbits += GMP_NUMB_BITS; 185 186 if (LIMBS_PER_DOUBLE >= 3 && nbits < 53 && size > 2) 187 { 188 x = up[-3]; 189 x <<= GMP_NAIL_BITS; 190 x >>= nbits; 191 mlo |= x; 192 nbits += GMP_NUMB_BITS; 193 } 194 } 195 mhi = mlo >> (32 + 11); 196 mlo = mlo >> 11; /* later implicitly truncated to 32 bits */ 197 #endif 198 #if GMP_LIMB_BITS == 32 199 x = *--up; 200 count_leading_zeros (lshift, x); 201 202 exp -= (lshift - GMP_NAIL_BITS) + 1; 203 x <<= lshift; 204 mhi = x >> 11; 205 206 if (lshift < 11) /* FIXME: never true if NUMB < 20 bits */ 207 { 208 /* All 20 bits in mhi */ 209 mlo = x << 21; 210 /* >= 1 bit in mlo */ 211 nbits = GMP_LIMB_BITS - lshift - 21; 212 } 213 else 214 { 215 if (size > 1) 216 { 217 nbits = GMP_LIMB_BITS - lshift; 218 219 x = *--up, size--; 220 x <<= GMP_NAIL_BITS; 221 mhi |= x >> nbits >> 11; 222 223 mlo = x << GMP_LIMB_BITS - nbits - 11; 224 nbits = nbits + 11 - GMP_NAIL_BITS; 225 } 226 else 227 { 228 mlo = 0; 229 goto done; 230 } 231 } 232 233 /* Now all needed bits in mhi have been accumulated. Add bits to mlo. */ 234 235 if (LIMBS_PER_DOUBLE >= 2 && nbits < 32 && size > 1) 236 { 237 x = up[-1]; 238 x <<= GMP_NAIL_BITS; 239 x >>= nbits; 240 mlo |= x; 241 nbits += GMP_NUMB_BITS; 242 243 if (LIMBS_PER_DOUBLE >= 3 && nbits < 32 && size > 2) 244 { 245 x = up[-2]; 246 x <<= GMP_NAIL_BITS; 247 x >>= nbits; 248 mlo |= x; 249 nbits += GMP_NUMB_BITS; 250 251 if (LIMBS_PER_DOUBLE >= 4 && nbits < 32 && size > 3) 252 { 253 x = up[-3]; 254 x <<= GMP_NAIL_BITS; 255 x >>= nbits; 256 mlo |= x; 257 nbits += GMP_NUMB_BITS; 258 } 259 } 260 } 261 262 done:; 263 264 #endif 265 if (UNLIKELY (exp >= CONST_1024)) 266 { 267 /* overflow, return infinity */ 268 ieee_infinity: 269 mhi = 0; 270 mlo = 0; 271 exp = 1024; 272 } 273 else if (UNLIKELY (exp <= CONST_NEG_1023)) 274 { 275 int rshift; 276 277 if (LIKELY (exp <= CONST_NEG_1022_SUB_53)) 278 return 0.0; /* denorm underflows to zero */ 279 280 rshift = -1022 - exp; 281 ASSERT (rshift > 0 && rshift < 53); 282 #if GMP_LIMB_BITS > 53 283 mlo >>= rshift; 284 mhi = mlo >> 32; 285 #else 286 if (rshift >= 32) 287 { 288 mlo = mhi; 289 mhi = 0; 290 rshift -= 32; 291 } 292 lshift = GMP_LIMB_BITS - rshift; 293 mlo = (mlo >> rshift) | (rshift == 0 ? 0 : mhi << lshift); 294 mhi >>= rshift; 295 #endif 296 exp = -1023; 297 } 298 u.s.manh = mhi; 299 u.s.manl = mlo; 300 u.s.exp = exp + 1023; 301 u.s.sig = (sign < 0); 302 return u.d; 303 } 304 #define FORMAT_RECOGNIZED 1 305 #endif 306 307 #if HAVE_DOUBLE_VAX_D 308 { 309 union double_extract u; 310 311 up += size; 312 313 mhi = up[-1]; 314 315 count_leading_zeros (lshift, mhi); 316 exp -= lshift; 317 mhi <<= lshift; 318 319 mlo = 0; 320 if (size > 1) 321 { 322 mlo = up[-2]; 323 if (lshift != 0) 324 mhi += mlo >> (GMP_LIMB_BITS - lshift); 325 mlo <<= lshift; 326 327 if (size > 2 && lshift > 8) 328 { 329 x = up[-3]; 330 mlo += x >> (GMP_LIMB_BITS - lshift); 331 } 332 } 333 334 if (UNLIKELY (exp >= 128)) 335 { 336 /* overflow, return maximum number */ 337 mhi = 0xffffffff; 338 mlo = 0xffffffff; 339 exp = 127; 340 } 341 else if (UNLIKELY (exp < -128)) 342 { 343 return 0.0; /* underflows to zero */ 344 } 345 346 u.s.man3 = mhi >> 24; /* drop msb, since implicit */ 347 u.s.man2 = mhi >> 8; 348 u.s.man1 = (mhi << 8) + (mlo >> 24); 349 u.s.man0 = mlo >> 8; 350 u.s.exp = exp + 128; 351 u.s.sig = sign < 0; 352 return u.d; 353 } 354 #define FORMAT_RECOGNIZED 1 355 #endif 356 357 #if ! FORMAT_RECOGNIZED 358 { /* Non-IEEE or strange limb size, do something generic. */ 359 mp_size_t i; 360 double d, weight; 361 unsigned long uexp; 362 363 /* First generate an fp number disregarding exp, instead keeping things 364 within the numb base factor from 1, which should prevent overflow and 365 underflow even for the most exponent limited fp formats. The 366 termination criteria should be refined, since we now include too many 367 limbs. */ 368 weight = 1/MP_BASE_AS_DOUBLE; 369 d = up[size - 1]; 370 for (i = size - 2; i >= 0; i--) 371 { 372 d += up[i] * weight; 373 weight /= MP_BASE_AS_DOUBLE; 374 if (weight == 0) 375 break; 376 } 377 378 /* Now apply exp. */ 379 exp -= GMP_NUMB_BITS; 380 if (exp > 0) 381 { 382 weight = 2.0; 383 uexp = exp; 384 } 385 else 386 { 387 weight = 0.5; 388 uexp = 1 - (unsigned long) (exp + 1); 389 } 390 #if 1 391 /* Square-and-multiply exponentiation. */ 392 if (uexp & 1) 393 d *= weight; 394 while (uexp >>= 1) 395 { 396 weight *= weight; 397 if (uexp & 1) 398 d *= weight; 399 } 400 #else 401 /* Plain exponentiation. */ 402 while (uexp > 0) 403 { 404 d *= weight; 405 uexp--; 406 } 407 #endif 408 409 return sign >= 0 ? d : -d; 410 } 411 #endif 412 }