this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 654 lines 25 kB view raw
1/* 2 * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * The contents of this file constitute Original Code as defined in and 7 * are subject to the Apple Public Source License Version 1.1 (the 8 * "License"). You may not use this file except in compliance with the 9 * License. Please obtain a copy of the License at 10 * http://www.apple.com/publicsource and read it before using this file. 11 * 12 * This Original Code and all software distributed under the License are 13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 * License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22/******************************************************************************* 23* * 24* File tableExpD.c, * 25* Functions exp, exp2 and expm1. * 26* Implementation of exp(x) based on IBM/Taligent table method. * 27* * 28* Copyright � 1997-2001 Apple Computer, Inc. All rights reserved. * 29* * 30* Written by Ali Sazegari, started on April 1997. * 31* Modified and ported by Robert A. Murley (ram) for Mac OS X. * 32* * 33* A MathLib v4 file. * 34* * 35* November 07 2001: removed exp2 to prevent conflict with CarbonCore. * 36* November 06 2001: commented out warning about Intel architectures. * 37* changed i386 stub to call abort(). * 38* November 02 2001: added stub for i386 version of exp2. * 39* April 28 1997: port of the ibm/taligent exp routines. * 40* July 16 1997: changed the rounding direction sensitivity of * 41* delivered results to default rounding at all times. * 42* August 28 2001: replaced __setflm with FEGETENVD/FESETENVD. * 43* replaced DblInHex typedef with hexdouble. * 44* used standard exception symbols from fenv.h. * 45* added #ifdef __ppc__. * 46* September 09 2001: added more comments. * 47* September 10 2001: added macros to detect PowerPC and correct compiler. * 48* September 18 2001: added <CoreServices/CoreServices.h> to get <fenv.h>. * 49* October 08 2001: removed <CoreServices/CoreServices.h>. * 50* changed compiler errors to warnings. * 51* * 52* W A R N I N G: * 53* These routines require a 64-bit double precision IEEE-754 model. * 54* They are written for PowerPC only and are expecting the compiler * 55* to generate the correct sequence of multiply-add fused instructions. * 56* * 57* These routines are not intended for 32-bit Intel architectures. * 58* * 59* A version of gcc higher than 932 is required. * 60* * 61* GCC compiler options: * 62* optimization level 3 (-O3) * 63* -fschedule-insns -finline-functions -funroll-all-loops * 64* * 65*******************************************************************************/ 66 67#include "math.h" 68#include "fenv_private.h" 69#include "fp_private.h" 70 71/******************************************************************************* 72* Floating-point constants. * 73*******************************************************************************/ 74 75static const double rintFactor = 6.7553994410557440000e+15; /* 0x43380000, 0x00000000 */ 76static const double oneOverLn2 = 1.4426950408889633000e+00; /* 0x3ff71547, 0x652b82fe */ 77static const double ln2Head = 6.9314718055994530000e-01; /* 0x3fe62e42, 0xfefa39ef */ 78static const double ln2Tail = 2.3190468138462996000e-17; /* 0x3c7abc9e, 0x3b39803f */ 79static const double maxExp = 7.0978271289338397000e+02; /* 0x40862e42, 0xfefa39ef */ 80static const double denormal = 2.9387358770557188000e-39; /* 0x37f00000, 0x00000000 */ 81static const hexdouble infinity = HEXDOUBLE(0x7ff00000, 0x00000000); 82 83/******************************************************************************* 84* Approximation coefficients. * 85*******************************************************************************/ 86 87static const double cm1 = 8.3333336309523691e-03; /* 0x3f811111,0x1b4af38e */ 88static const double c0 = 4.1666668402777808000e-02; /* 0x3fa55555,0x643f1505 */ 89static const double c1 = 1.6666666666666655000e-01; /* 0x3fc55555,0x55555551 */ 90static const double c2 = 4.9999999999999955000e-01; /* 0x3fdfffff,0xfffffff8 */ 91 92extern const uint32_t expTable[]; 93 94struct expTableEntry 95 { 96 double x; 97 double f; 98 }; 99 100static const double kMinNormal = 0x1.0p-1022; // 2.2250738585072014e-308; 101static const double kMaxNormal = 1.7976931348623157e308; 102 103#if !defined(BUILDING_FOR_CARBONCORE_LEGACY) 104/******************************************************************************* 105* Floating-point constants. * 106*******************************************************************************/ 107static const double minExp = -7.4513321910194122000e+02; /* 0xc0874910, 0xd52d3052 */ 108static const double oneOverDenorm = 3.402823669209384635e+38; /* 0x47f00000, 0x00000000 */ 109 110/******************************************************************************* 111* Approximation coefficients. * 112*******************************************************************************/ 113 114static const double cc4 = 0.5000000000000000000; 115static const double cc3 = 0.16666666666663809522820; 116static const double cc2 = 0.04166666666666111110939; 117static const double cc1 = 0.008333338095239329810170; 118static const double cc0 = 0.001388889583333492938381; 119 120/******************************************************************************* 121* * 122* The base e exponential function. * 123* * 124******************************************************************************** 125* * 126* Raised exceptions are inexact, overflow & inexact and underflow & inexact.* 127* * 128*******************************************************************************/ 129 130double exp ( double x ) 131{ 132 hexdouble scale, xInHex, yInHex; 133 register double d, y, yTail, z, zTail, z2, temp1, temp2, power, result; 134 register int32_t i; 135 register struct expTableEntry *tablePointer, *pT; 136 137 register double FPR_oneOverLn2, FPR_rintFactor, FPR_ln2Head, FPR_ln2Tail, FPR_h, FPR_z, FPR_512, FPR_scale; 138 register double FPR_env, FPR_x, FPR_f, FPR_cm1, FPR_c0, FPR_c1, FPR_c2; 139 140 FPR_x = __FABS( x ); 141 142 FPR_z = 0.0; FPR_512 = 512.0; 143 FPR_oneOverLn2 = oneOverLn2; FPR_rintFactor = rintFactor; 144 FPR_ln2Head = ln2Head; FPR_ln2Tail = ln2Tail; 145 tablePointer = ( struct expTableEntry * ) expTable + 177; 146 147 FEGETENVD ( FPR_env ); // save old environment, set default 148 __ENSURE( FPR_z, FPR_512, FPR_oneOverLn2 ); __ENSURE( FPR_ln2Head, FPR_ln2Tail, FPR_rintFactor ); 149 FESETENVD ( FPR_z ); 150 151 // Compute FPR_h and store it to yInHex as early as possible, even for cases that don't need it 152 FPR_h = __FMADD( x, FPR_oneOverLn2, FPR_rintFactor ); 153 yInHex.d = FPR_h; 154 FPR_h -= FPR_rintFactor; 155 156 if (likely( FPR_x < FPR_512 )) 157 { 158 if (likely( x != FPR_z )) 159 { 160 161 scale.i.hi = ( yInHex.i.lo + 1023 ) << 20; scale.i.lo = 0; 162 163 y = __FNMSUB( FPR_ln2Head, FPR_h, x ); yTail = __FMUL( FPR_ln2Tail, FPR_h ); 164 165 xInHex.d = __FMADD( FPR_512, y, FPR_rintFactor ); 166 167 __NOOP; 168 __NOOP; 169 __NOOP; 170 i = xInHex.i.lo; 171 172 pT = &(tablePointer[i]); 173 174 FPR_x = pT->x; FPR_f = pT->f; 175 176 d = y - FPR_x; 177 178 z = d - yTail; 179 FPR_cm1 = cm1; FPR_c1 = c1; 180 FPR_c0 = c0; FPR_c2 = c2; 181 182 z2 = __FMUL( z, z ); zTail = d - z - yTail; 183 184 temp1 = __FMADD( FPR_cm1, z2, FPR_c1 ); temp2 = __FMADD( FPR_c0, z2, FPR_c2 ); 185 186 temp1 = __FMADD( temp1, z, temp2 ); 187 FPR_scale = scale.d; 188 189 temp2 = __FMADD( temp1, z2, z ); 190 191 temp1 = __FMADD( zTail, temp2, zTail ); result = __FMUL( FPR_scale, FPR_f ); 192 193 temp1 = temp1 + temp2; 194 195 result = __FMADD( result, temp1, result ); 196 197 FESETENVD ( FPR_env ); 198 __PROG_INEXACT( FPR_cm1 ); 199 return result; 200 } 201 else 202 { 203 FESETENVD ( FPR_env ); 204 return 1.0; 205 } 206 } 207 208 if (likely( ( x <= maxExp ) && ( x > minExp ) )) 209 { 210 if ( x >= FPR_512 ) 211 { 212 power = 2.0; 213 scale.i.hi = ( yInHex.i.lo + 1022 ) << 20; scale.i.lo = 0; 214 } 215 else 216 { 217 power = denormal; 218 scale.i.hi = ( yInHex.i.lo + 1023+128 ) << 20; scale.i.lo = 0; 219 } 220 221 y = __FNMSUB( FPR_ln2Head, FPR_h, x ); yTail = __FMUL( FPR_ln2Tail, FPR_h ); 222 FPR_scale = scale.d; 223 224 xInHex.d = __FMADD( FPR_512, y, FPR_rintFactor ); 225 226 __NOOP; 227 __NOOP; 228 __NOOP; 229 i = xInHex.i.lo; 230 231 pT = &(tablePointer[i]); 232 233 FPR_x = pT->x; FPR_f = pT->f; 234 235 d = y - FPR_x; result = __FMUL( FPR_scale, FPR_f ); 236 237 z = d - yTail; 238 FPR_cm1 = cm1; FPR_c1 = c1; 239 FPR_c0 = c0; FPR_c2 = c2; 240 241 z2 = __FMUL( z, z ); zTail = d - z - yTail; 242 243 temp1 = __FMADD( FPR_cm1, z2, FPR_c1 ); temp2 = __FMADD( FPR_c0, z2, FPR_c2 ); 244 245 temp1 = __FMADD( temp1, z, temp2 ); 246 247 temp2 = __FMADD( temp1, z2, z ); 248 249 temp1 = __FMADD( zTail, temp2, zTail ); 250 251 temp1 = temp1 + temp2; 252 253 result = __FMADD( result, temp1, result ); 254 255 result = __FMUL( result, power ); 256 257 FESETENVD ( FPR_env ); 258 __PROG_INEXACT( FPR_oneOverLn2 ); 259 return result; 260 } 261 262 FESETENVD ( FPR_env ); 263 if ( x != x ) 264 return x; 265 else if ( x == infinity.d ) 266 return infinity.d; 267 else if ( x == -infinity.d ) 268 return FPR_z; 269 else if ( x > maxExp ) 270 { 271 __PROG_OF_INEXACT( kMaxNormal ); 272 return infinity.d; 273 } 274 else 275 { 276 __PROG_UF_INEXACT( kMinNormal ); 277 return FPR_z; 278 } 279} 280 281/******************************************************************************* 282* * 283* The expm1 function. * 284* * 285*******************************************************************************/ 286 287static const hexdouble k2M55 = HEXDOUBLE(0x3c800000, 0x00000000); 288 289double expm1 ( double x ) 290{ 291 hexdouble scale, invScale, xInHex, yInHex; 292 register double d, y, yTail, z, zTail, z2, temp1, temp2, power, result, f; 293 register int32_t i; 294 register struct expTableEntry *tablePointer, *pT; 295 296 register double FPR_oneOverLn2, FPR_rintFactor, FPR_ln2Head, FPR_ln2Tail, FPR_h, FPR_z, FPR_512, FPR_scale; 297 register double FPR_env, FPR_x, FPR_f, FPR_cc0, FPR_cc1, FPR_cc2, FPR_cc3, FPR_cc4, FPR_iscale; 298 299 FPR_x = __FABS( x ); 300 301 FPR_z = 0.0; FPR_512 = 512.0; 302 FPR_oneOverLn2 = oneOverLn2; FPR_rintFactor = rintFactor; 303 FPR_ln2Head = ln2Head; FPR_ln2Tail = ln2Tail; 304 tablePointer = ( struct expTableEntry * ) expTable + 177; 305 306 FEGETENVD ( FPR_env ); // save old environment, set default 307 __ENSURE( FPR_z, FPR_512, FPR_oneOverLn2 ); __ENSURE( FPR_ln2Head, FPR_ln2Tail, FPR_rintFactor ); 308 FESETENVD ( FPR_z ); 309 310 // Compute FPR_h and store it to yInHex as early as possible, even for cases that don't need it 311 FPR_h = __FMADD( x, FPR_oneOverLn2, FPR_rintFactor ); 312 yInHex.d = FPR_h; 313 FPR_h -= FPR_rintFactor; 314 315 if (likely( FPR_x < FPR_512 )) 316 { 317 if (unlikely( FPR_x < k2M55.d )) 318 { 319 FESETENVD ( FPR_env ); 320 if ( x == FPR_z ) 321 { 322 /* NOTHING */ 323 } 324 else 325 { 326 if ( FPR_x < kMinNormal ) 327 __PROG_UF_INEXACT( kMinNormal ); 328 else 329 __PROG_INEXACT( FPR_oneOverLn2 ); 330 } 331 return x; 332 } 333 334 scale.i.hi = ( yInHex.i.lo + 1023 ) << 20; scale.i.lo = 0; 335 336 y = __FNMSUB( FPR_ln2Head, FPR_h, x ); yTail = __FMUL( FPR_ln2Tail, FPR_h ); 337 338 xInHex.d = __FMADD( FPR_512, y, FPR_rintFactor ); 339 invScale.i.hi = 0x7fe00000 - scale.i.hi; invScale.i.lo = 0; 340 341 i = xInHex.i.lo; 342 343 pT = &(tablePointer[i]); 344 345 FPR_x = pT->x; FPR_f = pT->f; 346 347 d = y - FPR_x; 348 FPR_cc4 = cc4; 349 350 z = d - yTail; 351 FPR_cc0 = cc0; FPR_cc2 = cc2; 352 FPR_cc1 = cc1; FPR_cc3 = cc3; 353 354 z2 = __FMUL( z, z ); zTail = d - z - yTail; 355 356 temp1 = __FMADD( FPR_cc0, z2, FPR_cc2 ); temp2 = __FMADD( FPR_cc1, z2, FPR_cc3 ); 357 358 temp1 = __FMADD( temp1, z2, FPR_cc4 ); 359 360 temp2 = __FMADD( temp2, z, temp1 ); 361 FPR_iscale = invScale.d; 362 363 temp1 = __FMADD( temp2, z2, z ); 364 365 temp2 = __FMADD( zTail, temp1, zTail ); 366 367 temp2 = temp1 + temp2; d = FPR_f - FPR_iscale; 368 FPR_scale = scale.d; 369 370 temp1 = __FMADD( FPR_f, temp2, d ); 371 372 result = __FMUL( temp1, FPR_scale ); 373 374 FESETENVD ( FPR_env ); 375 __PROG_INEXACT( FPR_oneOverLn2 ); 376 return result; 377 } 378 379 if (likely( ( x <= maxExp ) && ( x > minExp ) )) 380 { 381 if ( x >= FPR_512 ) 382 { 383 power = 2.0; 384 f = 0.5; 385 scale.i.hi = ( yInHex.i.lo + 1022 ) << 20; scale.i.lo = 0; 386 } 387 else 388 { 389 power = denormal; 390 f = oneOverDenorm; 391 scale.i.hi = ( yInHex.i.lo + 1023+128 ) << 20; scale.i.lo = 0; 392 if ( scale.i.hi < ( 168<<20 ) ) 393 { 394 FESETENVD ( FPR_env ); 395 __PROG_INEXACT( FPR_oneOverLn2 ); 396 return -1.0; 397 } 398 } 399 400 y = __FNMSUB( FPR_ln2Head, FPR_h, x ); yTail = __FMUL( FPR_ln2Tail, FPR_h ); 401 FPR_scale = scale.d; 402 403 xInHex.d = __FMADD( FPR_512, y, FPR_rintFactor ); 404 invScale.i.hi = 0x7fe00000 - scale.i.hi; invScale.i.lo = 0; 405 406 i = xInHex.i.lo; 407 408 pT = &(tablePointer[i]); 409 410 FPR_x = pT->x; FPR_f = pT->f; 411 412 d = y - FPR_x; 413 FPR_iscale = invScale.d; FPR_cc4 = cc4; 414 415 z = d - yTail; 416 FPR_cc0 = cc0; FPR_cc2 = cc2; 417 FPR_cc1 = cc1; FPR_cc3 = cc3; 418 419 z2 = __FMUL( z, z ); zTail = d - z - yTail; 420 421 temp1 = __FMADD( FPR_cc0, z2, FPR_cc2 ); temp2 = __FMADD( FPR_cc1, z2, FPR_cc3 ); 422 423 temp1 = __FMADD( temp1, z2, FPR_cc4 ); d = __FNMSUB( f, FPR_iscale, FPR_f ); 424 425 temp2 = __FMADD( temp2, z, temp1 ); 426 427 temp1 = __FMADD( temp2, z2, z ); 428 429 temp2 = __FMADD( zTail, temp1, zTail ); 430 431 temp2 = temp1 + temp2; 432 433 temp1 = __FMADD( FPR_f, temp2, d ); 434 435 result = __FMUL( temp1, FPR_scale ); 436 437 result = __FMUL( result, power ); 438 439 FESETENVD ( FPR_env ); 440 __PROG_INEXACT( FPR_oneOverLn2 ); 441 return result; 442 } 443 444 FESETENVD ( FPR_env ); 445 if ( x != x ) 446 return x; 447 else if ( x == infinity.d ) 448 return infinity.d; 449 else if ( x == -infinity.d ) 450 return -1.0; 451 else if ( x > maxExp ) 452 { 453 __PROG_OF_INEXACT( kMaxNormal ); 454 return infinity.d; 455 } 456 else 457 { 458#if 0 /* XXX scp: test vectors don't want this to underflow */ 459 __PROG_UF_INEXACT( kMinNormal ); 460#else 461 __PROG_INEXACT( FPR_oneOverLn2 ); 462#endif 463 return -1.0; 464 } 465} 466 467#else /* BUILDING_FOR_CARBONCORE_LEGACY */ 468/******************************************************************************* 469* Floating-point constants. * 470*******************************************************************************/ 471 472static const double maxExp2 = 1024.0; 473static const double minNormExp2 = -1022.0; 474static const double minExp2 = -1075.0; 475 476/******************************************************************************* 477* * 478* The base 2 exponential function. * 479* * 480*******************************************************************************/ 481 482double exp2 ( double x ) 483{ 484 hexdouble OldEnvironment, scale, xInHex, yInHex; 485 register double d, y, yTail, z, zTail, z2, temp1, temp2, power, result; 486 register int32_t i; 487 register struct expTableEntry *tablePointer, *pT; 488 489 register double FPR_oneOverLn2, FPR_rintFactor, FPR_ln2Head, FPR_ln2Tail, FPR_h, FPR_z, FPR_512, FPR_scale; 490 register double FPR_env, FPR_diff, FPR_x, FPR_f, FPR_cm1, FPR_c0, FPR_c1, FPR_c2; 491 492 FPR_x = __FABS( x ); 493 494 FPR_z = 0.0; FPR_512 = 512.0; 495 FPR_oneOverLn2 = oneOverLn2; FPR_rintFactor = rintFactor; 496 FPR_ln2Head = ln2Head; FPR_ln2Tail = ln2Tail; 497 tablePointer = ( struct expTableEntry * ) expTable + 177; 498 499 FEGETENVD ( FPR_env ); // save old environment, set default 500 __ENSURE( FPR_z, FPR_512, FPR_oneOverLn2 ); __ENSURE( FPR_ln2Head, FPR_ln2Tail, FPR_rintFactor ); 501 FESETENVD ( FPR_z ); 502 503 // Compute FPR_h and store it to yInHex as early as possible, even for cases that don't need it 504 FPR_h = x + FPR_rintFactor; 505 yInHex.d = FPR_h; 506 FPR_h -= FPR_rintFactor; 507 508 FPR_diff = x - FPR_h; 509 510 if (likely( FPR_x < FPR_512 )) 511 { 512 if (likely( FPR_x != FPR_z )) 513 { 514 scale.i.hi = ( yInHex.i.lo + 1023 ) << 20; scale.i.lo = 0; 515 516 y = __FMUL( FPR_ln2Head, FPR_diff ); yTail = __FMUL( FPR_ln2Tail, FPR_diff ); 517 518 xInHex.d = __FMADD( FPR_512, y, FPR_rintFactor ); 519 520 __NOOP; 521 __NOOP; 522 __NOOP; 523 i = xInHex.i.lo; 524 525 pT = &(tablePointer[i]); 526 527 FPR_x = pT->x; FPR_f = pT->f; 528 529 d = y - FPR_x; 530 531 z = d - yTail; 532 FPR_cm1 = cm1; FPR_c1 = c1; 533 FPR_c0 = c0; FPR_c2 = c2; 534 535 z2 = __FMUL( z, z ); zTail = d - z - yTail; 536 537 temp1 = __FMADD( FPR_cm1, z2, FPR_c1 ); temp2 = __FMADD( FPR_c0, z2, FPR_c2 ); 538 539 temp1 = __FMADD( temp1, z, temp2 ); 540 541 temp2 = __FMADD( temp1, z2, z ); 542 FPR_scale = scale.d; 543 544 temp1 = __FMADD( zTail, temp2, zTail ); 545 546 temp1 = temp1 + temp2; result = __FMUL( FPR_scale, FPR_f ); 547 548 result = __FMADD( result, temp1, result ); 549 550 FESETENVD ( FPR_env ); 551 if ( FPR_diff != FPR_z) 552 __PROG_INEXACT( FPR_oneOverLn2 ); 553 554 return result; 555 } 556 else 557 { 558 FESETENVD ( FPR_env ); 559 return 1.0; 560 } 561 } 562 563 if (likely( ( x < maxExp2 ) && ( x > minExp2 ) )) 564 { 565 if ( x >= FPR_512 ) 566 { 567 power = 2.0; 568 scale.i.hi = ( yInHex.i.lo + 1022 ) << 20; scale.i.lo = 0; 569 } 570 else 571 { 572 power = denormal; 573 scale.i.hi = ( yInHex.i.lo + 1023+128 ) << 20; scale.i.lo = 0; 574 } 575 576 FPR_diff = x - FPR_h; 577 FPR_scale = scale.d; 578 579 y = __FMUL( FPR_ln2Head, FPR_diff ); yTail = __FMUL( FPR_ln2Tail, FPR_diff ); 580 581 xInHex.d = __FMADD( FPR_512, y, FPR_rintFactor ); 582 583 __NOOP; 584 __NOOP; 585 __NOOP; 586 i = xInHex.i.lo; 587 588 pT = &(tablePointer[i]); 589 590 FPR_x = pT->x; FPR_f = pT->f; 591 592 d = y - FPR_x; result = __FMUL( FPR_scale, FPR_f ); 593 594 z = d - yTail; 595 FPR_cm1 = cm1; FPR_c1 = c1; 596 FPR_c0 = c0; FPR_c2 = c2; 597 598 z2 = __FMUL( z, z ); zTail = d - z - yTail; 599 600 temp1 = __FMADD( FPR_cm1, z2, FPR_c1 ); temp2 = __FMADD( FPR_c0, z2, FPR_c2 ); 601 602 temp1 = __FMADD( temp1, z, temp2 ); 603 604 temp2 = __FMADD( temp1, z2, z ); 605 606 temp1 = __FMADD( zTail, temp2, zTail ); 607 608 temp1 = temp1 + temp2; 609 610 result = __FMADD( result, temp1, result ); 611 612 result = __FMUL( result, power ); 613 614 FESETENVD ( FPR_env ); 615 if ( x < minNormExp2 ) 616 { 617 OldEnvironment.d = FPR_env; 618 __NOOP; 619 __NOOP; 620 __NOOP; 621 622 OldEnvironment.i.lo |= FE_UNDERFLOW; // set underflow flag 623 624 if ( FPR_h != x ) 625 OldEnvironment.i.lo |= FE_INEXACT; // set inexact flag 626 627 FESETENVD_GRP ( OldEnvironment.d ); 628 } 629 else if ( FPR_h != x ) 630 __PROG_INEXACT( FPR_oneOverLn2 ); 631 632 return result; 633 } 634 635 FESETENVD ( FPR_env ); 636 if ( x != x ) 637 return x; 638 else if ( x == infinity.d ) 639 return infinity.d; 640 else if ( x == -infinity.d ) 641 return FPR_z; 642 else if ( x > maxExp ) 643 { 644 __PROG_OF_INEXACT( kMaxNormal ); 645 return infinity.d; 646 } 647 else 648 { 649 __PROG_UF_INEXACT( kMinNormal ); 650 return FPR_z; 651 } 652} 653 654#endif /* BUILDING_FOR_CARBONCORE_LEGACY */