1206917Smarius 2206917Smarius/* 3206917Smarius=============================================================================== 4206917Smarius 5206917SmariusThis C source file is part of TestFloat, Release 2a, a package of programs 6206917Smariusfor testing the correctness of floating-point arithmetic complying to the 7206917SmariusIEC/IEEE Standard for Floating-Point. 8206917Smarius 9206917SmariusWritten by John R. Hauser. More information is available through the Web 10206917Smariuspage `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. 11206917Smarius 12206917SmariusTHIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort 13206917Smariushas been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT 14206917SmariusTIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO 15206917SmariusPERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY 16206917SmariusAND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. 17206917Smarius 18206917SmariusDerivative works are acceptable, even for commercial purposes, so long as 19206917Smarius(1) they include prominent notice that the work is derivative, and (2) they 20206917Smariusinclude prominent notice akin to these four paragraphs for those parts of 21206917Smariusthis code that are retained. 22206917Smarius 23206917Smarius=============================================================================== 24206917Smarius*/ 25206917Smarius 26206917Smariusint8 slow_float_rounding_mode; 27206917Smariusint8 slow_float_exception_flags; 28206917Smariusint8 slow_float_detect_tininess; 29206917Smarius#ifdef FLOATX80 30206917Smariusint8 slow_floatx80_rounding_precision; 31206917Smarius#endif 32206917Smarius 33206917Smariustypedef struct { 34206917Smarius bits64 a0, a1; 35206917Smarius} bits128X; 36206917Smarius 37206917Smariustypedef struct { 38206917Smarius flag isNaN; 39206917Smarius flag isInf; 40206917Smarius flag isZero; 41206917Smarius flag sign; 42206917Smarius int32 exp; 43206917Smarius bits128X sig; 44206917Smarius} floatX; 45206917Smarius 46206917Smariusstatic const floatX floatXNaN = { TRUE, FALSE, FALSE, FALSE, 0, { 0, 0 } }; 47206917Smariusstatic const floatX floatXPositiveZero = 48206917Smarius { FALSE, FALSE, TRUE, FALSE, 0, { 0, 0 } }; 49206917Smariusstatic const floatX floatXNegativeZero = 50206917Smarius { FALSE, FALSE, TRUE, TRUE, 0, { 0, 0 } }; 51206917Smarius 52206917Smariusstatic bits128X shortShift128Left( bits128X a, int8 shiftCount ) 53206917Smarius{ 54206917Smarius int8 negShiftCount; 55206917Smarius 56206917Smarius negShiftCount = ( - shiftCount & 63 ); 57206917Smarius a.a0 = ( a.a0<<shiftCount ) | ( a.a1>>negShiftCount ); 58206917Smarius a.a1 <<= shiftCount; 59206917Smarius return a; 60206917Smarius 61206917Smarius} 62206917Smarius 63206917Smariusstatic bits128X shortShift128RightJamming( bits128X a, int8 shiftCount ) 64206917Smarius{ 65206917Smarius int8 negShiftCount; 66206917Smarius bits64 extra; 67206917Smarius 68206917Smarius negShiftCount = ( - shiftCount & 63 ); 69206917Smarius extra = a.a1<<negShiftCount; 70206917Smarius a.a1 = ( a.a0<<negShiftCount ) | ( a.a1>>shiftCount ) | ( extra != 0 ); 71206917Smarius a.a0 >>= shiftCount; 72206917Smarius return a; 73206917Smarius 74206917Smarius} 75206917Smarius 76206917Smariusstatic bits128X neg128( bits128X a ) 77206917Smarius{ 78206917Smarius 79206917Smarius if ( a.a1 == 0 ) { 80206917Smarius a.a0 = - a.a0; 81206917Smarius } 82206917Smarius else { 83206917Smarius a.a1 = - a.a1; 84206917Smarius a.a0 = ~ a.a0; 85206917Smarius } 86206917Smarius return a; 87206917Smarius 88206917Smarius} 89206917Smarius 90206917Smariusstatic bits128X add128( bits128X a, bits128X b ) 91206917Smarius{ 92206917Smarius 93206917Smarius a.a1 += b.a1; 94206917Smarius a.a0 += b.a0 + ( a.a1 < b.a1 ); 95206917Smarius return a; 96206917Smarius 97206917Smarius} 98206917Smarius 99206917Smariusstatic flag eq128( bits128X a, bits128X b ) 100206917Smarius{ 101206917Smarius 102206917Smarius return ( a.a0 == b.a0 ) && ( a.a1 == b.a1 ); 103206917Smarius 104206917Smarius} 105206917Smarius 106206917Smariusstatic flag le128( bits128X a, bits128X b ) 107206917Smarius{ 108206917Smarius 109206917Smarius return ( a.a0 < b.a0 ) || ( ( a.a0 == b.a0 ) && ( a.a1 <= b.a1 ) ); 110206917Smarius 111206917Smarius} 112206917Smarius 113206917Smariusstatic flag lt128( bits128X a, bits128X b ) 114206917Smarius{ 115206917Smarius 116206917Smarius return ( a.a0 < b.a0 ) || ( ( a.a0 == b.a0 ) && ( a.a1 < b.a1 ) ); 117206917Smarius 118206917Smarius} 119206917Smarius 120206917Smariusstatic floatX roundFloatXTo24( flag isTiny, floatX zx ) 121206917Smarius{ 122206917Smarius bits32 roundBits; 123206917Smarius 124206917Smarius zx.sig.a0 |= ( zx.sig.a1 != 0 ); 125206917Smarius zx.sig.a1 = 0; 126206917Smarius roundBits = zx.sig.a0 & 0xFFFFFFFF; 127206917Smarius zx.sig.a0 -= roundBits; 128206917Smarius if ( roundBits ) { 129206917Smarius slow_float_exception_flags |= float_flag_inexact; 130206917Smarius if ( isTiny ) slow_float_exception_flags |= float_flag_underflow; 131206917Smarius switch ( slow_float_rounding_mode ) { 132206917Smarius case float_round_nearest_even: 133206917Smarius if ( roundBits < 0x80000000 ) goto noIncrement; 134206917Smarius if ( ( roundBits == 0x80000000 ) 135206917Smarius && ! ( zx.sig.a0 & LIT64( 0x100000000 ) ) ) { 136206917Smarius goto noIncrement; 137206917Smarius } 138206917Smarius break; 139206917Smarius case float_round_to_zero: 140206917Smarius goto noIncrement; 141206917Smarius case float_round_down: 142206917Smarius if ( ! zx.sign ) goto noIncrement; 143206917Smarius break; 144206917Smarius case float_round_up: 145206917Smarius if ( zx.sign ) goto noIncrement; 146206917Smarius break; 147206917Smarius } 148206917Smarius zx.sig.a0 += LIT64( 0x100000000 ); 149206917Smarius if ( zx.sig.a0 == LIT64( 0x0100000000000000 ) ) { 150206917Smarius zx.sig.a0 = LIT64( 0x0080000000000000 ); 151206917Smarius ++zx.exp; 152206917Smarius } 153206917Smarius } 154206917Smarius noIncrement: 155206917Smarius return zx; 156206917Smarius 157206917Smarius} 158206917Smarius 159206917Smariusstatic floatX roundFloatXTo53( flag isTiny, floatX zx ) 160206917Smarius{ 161206917Smarius int8 roundBits; 162206917Smarius 163206917Smarius zx.sig.a0 |= ( zx.sig.a1 != 0 ); 164206917Smarius zx.sig.a1 = 0; 165206917Smarius roundBits = zx.sig.a0 & 7; 166206917Smarius zx.sig.a0 -= roundBits; 167206917Smarius if ( roundBits ) { 168206917Smarius slow_float_exception_flags |= float_flag_inexact; 169206917Smarius if ( isTiny ) slow_float_exception_flags |= float_flag_underflow; 170206917Smarius switch ( slow_float_rounding_mode ) { 171206917Smarius case float_round_nearest_even: 172206917Smarius if ( roundBits < 4 ) goto noIncrement; 173206917Smarius if ( ( roundBits == 4 ) && ! ( zx.sig.a0 & 8 ) ) goto noIncrement; 174206917Smarius break; 175206917Smarius case float_round_to_zero: 176206917Smarius goto noIncrement; 177206917Smarius case float_round_down: 178206917Smarius if ( ! zx.sign ) goto noIncrement; 179206917Smarius break; 180206917Smarius case float_round_up: 181206917Smarius if ( zx.sign ) goto noIncrement; 182206917Smarius break; 183206917Smarius } 184206917Smarius zx.sig.a0 += 8; 185206917Smarius if ( zx.sig.a0 == LIT64( 0x0100000000000000 ) ) { 186206917Smarius zx.sig.a0 = LIT64( 0x0080000000000000 ); 187206917Smarius ++zx.exp; 188206917Smarius } 189206917Smarius } 190206917Smarius noIncrement: 191206917Smarius return zx; 192206917Smarius 193206917Smarius} 194206917Smarius 195206917Smariusstatic floatX roundFloatXTo64( flag isTiny, floatX zx ) 196206917Smarius{ 197206917Smarius int64 roundBits; 198206917Smarius 199206917Smarius roundBits = zx.sig.a1 & LIT64( 0x00FFFFFFFFFFFFFF ); 200206917Smarius zx.sig.a1 -= roundBits; 201206917Smarius if ( roundBits ) { 202206917Smarius slow_float_exception_flags |= float_flag_inexact; 203206917Smarius if ( isTiny ) slow_float_exception_flags |= float_flag_underflow; 204206917Smarius switch ( slow_float_rounding_mode ) { 205206917Smarius case float_round_nearest_even: 206206917Smarius if ( roundBits < LIT64( 0x0080000000000000 ) ) goto noIncrement; 207206917Smarius if ( ( roundBits == LIT64( 0x0080000000000000 ) ) 208206917Smarius && ! ( zx.sig.a1 & LIT64( 0x0100000000000000 ) ) ) { 209206917Smarius goto noIncrement; 210206917Smarius } 211206917Smarius break; 212206917Smarius case float_round_to_zero: 213206917Smarius goto noIncrement; 214206917Smarius case float_round_down: 215206917Smarius if ( ! zx.sign ) goto noIncrement; 216206917Smarius break; 217206917Smarius case float_round_up: 218206917Smarius if ( zx.sign ) goto noIncrement; 219206917Smarius break; 220206917Smarius } 221206917Smarius zx.sig.a1 += LIT64( 0x0100000000000000 ); 222206917Smarius zx.sig.a0 += ( zx.sig.a1 == 0 ); 223206917Smarius if ( zx.sig.a0 == LIT64( 0x0100000000000000 ) ) { 224206917Smarius zx.sig.a0 = LIT64( 0x0080000000000000 ); 225206917Smarius ++zx.exp; 226206917Smarius } 227206917Smarius } 228206917Smarius noIncrement: 229206917Smarius return zx; 230206917Smarius 231206917Smarius} 232206917Smarius 233206917Smariusstatic floatX roundFloatXTo113( flag isTiny, floatX zx ) 234206917Smarius{ 235206917Smarius int8 roundBits; 236206917Smarius 237206917Smarius roundBits = zx.sig.a1 & 0x7F; 238206917Smarius zx.sig.a1 -= roundBits; 239206917Smarius if ( roundBits ) { 240206917Smarius slow_float_exception_flags |= float_flag_inexact; 241206917Smarius if ( isTiny ) slow_float_exception_flags |= float_flag_underflow; 242206917Smarius switch ( slow_float_rounding_mode ) { 243206917Smarius case float_round_nearest_even: 244206917Smarius if ( roundBits < 0x40 ) goto noIncrement; 245206917Smarius if ( ( roundBits == 0x40 ) 246206917Smarius && ! ( zx.sig.a1 & 0x80 ) ) goto noIncrement; 247206917Smarius break; 248206917Smarius case float_round_to_zero: 249206917Smarius goto noIncrement; 250206917Smarius case float_round_down: 251206917Smarius if ( ! zx.sign ) goto noIncrement; 252206917Smarius break; 253206917Smarius case float_round_up: 254206917Smarius if ( zx.sign ) goto noIncrement; 255206917Smarius break; 256206917Smarius } 257206917Smarius zx.sig.a1 += 0x80; 258206917Smarius zx.sig.a0 += ( zx.sig.a1 == 0 ); 259206917Smarius if ( zx.sig.a0 == LIT64( 0x0100000000000000 ) ) { 260206917Smarius zx.sig.a0 = LIT64( 0x0080000000000000 ); 261206917Smarius ++zx.exp; 262206917Smarius } 263206917Smarius } 264206917Smarius noIncrement: 265206917Smarius return zx; 266206917Smarius 267206917Smarius} 268206917Smarius 269206917Smariusstatic floatX int32ToFloatX( int32 a ) 270206917Smarius{ 271206917Smarius floatX ax; 272206917Smarius 273206917Smarius ax.isNaN = FALSE; 274206917Smarius ax.isInf = FALSE; 275206917Smarius ax.sign = ( a < 0 ); 276206917Smarius ax.sig.a1 = 0; 277206917Smarius ax.sig.a0 = ax.sign ? - (bits64) a : a; 278206917Smarius if ( a == 0 ) { 279206917Smarius ax.isZero = TRUE; 280206917Smarius return ax; 281206917Smarius } 282206917Smarius ax.isZero = FALSE; 283206917Smarius ax.sig.a0 <<= 24; 284206917Smarius ax.exp = 31; 285206917Smarius while ( ax.sig.a0 < LIT64( 0x0080000000000000 ) ) { 286206917Smarius ax.sig.a0 <<= 1; 287206917Smarius --ax.exp; 288206917Smarius } 289206917Smarius return ax; 290206917Smarius 291206917Smarius} 292206917Smarius 293206917Smariusstatic int32 floatXToInt32( floatX ax ) 294206917Smarius{ 295206917Smarius int8 savedExceptionFlags; 296206917Smarius int32 shiftCount; 297206917Smarius int32 z; 298206917Smarius 299206917Smarius if ( ax.isInf || ax.isNaN ) { 300206917Smarius slow_float_exception_flags |= float_flag_invalid; 301206917Smarius return ( ax.isInf & ax.sign ) ? (sbits32) 0x80000000 : 0x7FFFFFFF; 302206917Smarius } 303206917Smarius if ( ax.isZero ) return 0; 304206917Smarius savedExceptionFlags = slow_float_exception_flags; 305206917Smarius shiftCount = 52 - ax.exp; 306206917Smarius if ( 56 < shiftCount ) { 307206917Smarius ax.sig.a1 = 1; 308206917Smarius ax.sig.a0 = 0; 309206917Smarius } 310206917Smarius else { 311206917Smarius while ( 0 < shiftCount ) { 312206917Smarius ax.sig = shortShift128RightJamming( ax.sig, 1 ); 313206917Smarius --shiftCount; 314206917Smarius } 315206917Smarius } 316206917Smarius ax = roundFloatXTo53( FALSE, ax ); 317206917Smarius ax.sig = shortShift128RightJamming( ax.sig, 3 ); 318206917Smarius z = ax.sig.a0; 319206917Smarius if ( ax.sign ) z = - z; 320206917Smarius if ( ( shiftCount < 0 ) 321206917Smarius || ( ax.sig.a0>>32 ) 322206917Smarius || ( ( z != 0 ) && ( ( ax.sign ^ ( z < 0 ) ) != 0 ) ) 323206917Smarius ) { 324206917Smarius slow_float_exception_flags = savedExceptionFlags | float_flag_invalid; 325206917Smarius return ax.sign ? (sbits32) 0x80000000 : 0x7FFFFFFF; 326206917Smarius } 327206917Smarius return z; 328206917Smarius 329206917Smarius} 330206917Smarius 331206917Smariusstatic floatX int64ToFloatX( int64 a ) 332206917Smarius{ 333206917Smarius uint64 absA; 334206917Smarius floatX ax; 335206917Smarius 336206917Smarius ax.isNaN = FALSE; 337206917Smarius ax.isInf = FALSE; 338206917Smarius ax.sign = ( a < 0 ); 339206917Smarius ax.sig.a1 = ax.sign ? - a : a; 340206917Smarius ax.sig.a0 = 0; 341206917Smarius if ( a == 0 ) { 342206917Smarius ax.isZero = TRUE; 343206917Smarius return ax; 344206917Smarius } 345206917Smarius ax.isZero = FALSE; 346206917Smarius ax.sig = shortShift128Left( ax.sig, 56 ); 347206917Smarius ax.exp = 63; 348206917Smarius while ( ax.sig.a0 < LIT64( 0x0080000000000000 ) ) { 349206917Smarius ax.sig = shortShift128Left( ax.sig, 1 ); 350206917Smarius --ax.exp; 351206917Smarius } 352206917Smarius return ax; 353206917Smarius 354206917Smarius} 355206917Smarius 356206917Smariusstatic int64 floatXToInt64( floatX ax ) 357206917Smarius{ 358206917Smarius int8 savedExceptionFlags; 359206917Smarius int32 shiftCount; 360206917Smarius int64 z; 361206917Smarius 362206917Smarius if ( ax.isInf || ax.isNaN ) { 363206917Smarius slow_float_exception_flags |= float_flag_invalid; 364206917Smarius return 365206917Smarius ( ax.isInf & ax.sign ) ? (sbits64) LIT64( 0x8000000000000000 ) 366206917Smarius : LIT64( 0x7FFFFFFFFFFFFFFF ); 367206917Smarius } 368206917Smarius if ( ax.isZero ) return 0; 369206917Smarius savedExceptionFlags = slow_float_exception_flags; 370206917Smarius shiftCount = 112 - ax.exp; 371206917Smarius if ( 116 < shiftCount ) { 372206917Smarius ax.sig.a1 = 1; 373206917Smarius ax.sig.a0 = 0; 374206917Smarius } 375206917Smarius else { 376206917Smarius while ( 0 < shiftCount ) { 377206917Smarius ax.sig = shortShift128RightJamming( ax.sig, 1 ); 378206917Smarius --shiftCount; 379206917Smarius } 380206917Smarius } 381206917Smarius ax = roundFloatXTo113( FALSE, ax ); 382206917Smarius ax.sig = shortShift128RightJamming( ax.sig, 7 ); 383206917Smarius z = ax.sig.a1; 384206917Smarius if ( ax.sign ) z = - z; 385206917Smarius if ( ( shiftCount < 0 ) 386206917Smarius || ax.sig.a0 387206917Smarius || ( ( z != 0 ) && ( ( ax.sign ^ ( z < 0 ) ) != 0 ) ) 388206917Smarius ) { 389206917Smarius slow_float_exception_flags = savedExceptionFlags | float_flag_invalid; 390206917Smarius return 391206917Smarius ax.sign ? (sbits64) LIT64( 0x8000000000000000 ) 392206917Smarius : LIT64( 0x7FFFFFFFFFFFFFFF ); 393206917Smarius } 394206917Smarius return z; 395206917Smarius 396206917Smarius} 397206917Smarius 398206917Smariusstatic floatX float32ToFloatX( float32 a ) 399206917Smarius{ 400206917Smarius int16 expField; 401206917Smarius floatX ax; 402206917Smarius 403206917Smarius ax.isNaN = FALSE; 404206917Smarius ax.isInf = FALSE; 405206917Smarius ax.isZero = FALSE; 406206917Smarius ax.sign = ( ( a & 0x80000000 ) != 0 ); 407206917Smarius expField = ( a>>23 ) & 0xFF; 408206917Smarius ax.sig.a1 = 0; 409206917Smarius ax.sig.a0 = a & 0x007FFFFF; 410206917Smarius ax.sig.a0 <<= 32; 411206917Smarius if ( expField == 0 ) { 412206917Smarius if ( ax.sig.a0 == 0 ) { 413206917Smarius ax.isZero = TRUE; 414206917Smarius } 415206917Smarius else { 416206917Smarius expField = 1 - 0x7F; 417206917Smarius do { 418206917Smarius ax.sig.a0 <<= 1; 419206917Smarius --expField; 420206917Smarius } while ( ax.sig.a0 < LIT64( 0x0080000000000000 ) ); 421206917Smarius ax.exp = expField; 422206917Smarius } 423206917Smarius } 424206917Smarius else if ( expField == 0xFF ) { 425206917Smarius if ( ax.sig.a0 == 0 ) { 426206917Smarius ax.isInf = TRUE; 427206917Smarius } 428206917Smarius else { 429206917Smarius ax.isNaN = TRUE; 430206917Smarius } 431206917Smarius } 432206917Smarius else { 433206917Smarius ax.sig.a0 |= LIT64( 0x0080000000000000 ); 434206917Smarius ax.exp = expField - 0x7F; 435206917Smarius } 436206917Smarius return ax; 437206917Smarius 438206917Smarius} 439206917Smarius 440206917Smariusstatic float32 floatXToFloat32( floatX zx ) 441206917Smarius{ 442206917Smarius floatX savedZ; 443206917Smarius flag isTiny; 444206917Smarius int32 expField; 445206917Smarius float32 z; 446206917Smarius 447206917Smarius if ( zx.isZero ) return zx.sign ? 0x80000000 : 0; 448206917Smarius if ( zx.isInf ) return zx.sign ? 0xFF800000 : 0x7F800000; 449206917Smarius if ( zx.isNaN ) return 0xFFFFFFFF; 450206917Smarius while ( LIT64( 0x0100000000000000 ) <= zx.sig.a0 ) { 451206917Smarius zx.sig = shortShift128RightJamming( zx.sig, 1 ); 452206917Smarius ++zx.exp; 453206917Smarius } 454206917Smarius while ( zx.sig.a0 < LIT64( 0x0080000000000000 ) ) { 455206917Smarius zx.sig = shortShift128Left( zx.sig, 1 ); 456206917Smarius --zx.exp; 457206917Smarius } 458206917Smarius savedZ = zx; 459206917Smarius isTiny = 460206917Smarius ( slow_float_detect_tininess == float_tininess_before_rounding ) 461206917Smarius && ( zx.exp + 0x7F <= 0 ); 462206917Smarius zx = roundFloatXTo24( isTiny, zx ); 463206917Smarius expField = zx.exp + 0x7F; 464206917Smarius if ( 0xFF <= expField ) { 465206917Smarius slow_float_exception_flags |= 466206917Smarius float_flag_overflow | float_flag_inexact; 467206917Smarius if ( zx.sign ) { 468206917Smarius switch ( slow_float_rounding_mode ) { 469206917Smarius case float_round_nearest_even: 470206917Smarius case float_round_down: 471206917Smarius z = 0xFF800000; 472206917Smarius break; 473206917Smarius case float_round_to_zero: 474206917Smarius case float_round_up: 475206917Smarius z = 0xFF7FFFFF; 476206917Smarius break; 477206917Smarius } 478206917Smarius } 479206917Smarius else { 480206917Smarius switch ( slow_float_rounding_mode ) { 481206917Smarius case float_round_nearest_even: 482206917Smarius case float_round_up: 483206917Smarius z = 0x7F800000; 484206917Smarius break; 485206917Smarius case float_round_to_zero: 486206917Smarius case float_round_down: 487206917Smarius z = 0x7F7FFFFF; 488206917Smarius break; 489206917Smarius } 490206917Smarius } 491206917Smarius return z; 492206917Smarius } 493206917Smarius if ( expField <= 0 ) { 494206917Smarius isTiny = TRUE; 495206917Smarius zx = savedZ; 496206917Smarius expField = zx.exp + 0x7F; 497206917Smarius if ( expField < -27 ) { 498206917Smarius zx.sig.a1 = ( zx.sig.a0 != 0 ) || ( zx.sig.a1 != 0 ); 499206917Smarius zx.sig.a0 = 0; 500206917Smarius } 501206917Smarius else { 502206917Smarius while ( expField <= 0 ) { 503206917Smarius zx.sig = shortShift128RightJamming( zx.sig, 1 ); 504206917Smarius ++expField; 505206917Smarius } 506206917Smarius } 507206917Smarius zx = roundFloatXTo24( isTiny, zx ); 508206917Smarius expField = ( LIT64( 0x0080000000000000 ) <= zx.sig.a0 ) ? 1 : 0; 509206917Smarius } 510206917Smarius z = expField; 511206917Smarius z <<= 23; 512206917Smarius if ( zx.sign ) z |= 0x80000000; 513206917Smarius z |= ( zx.sig.a0>>32 ) & 0x007FFFFF; 514206917Smarius return z; 515206917Smarius 516206917Smarius} 517206917Smarius 518206917Smariusstatic floatX float64ToFloatX( float64 a ) 519206917Smarius{ 520206917Smarius int16 expField; 521206917Smarius floatX ax; 522206917Smarius 523206917Smarius ax.isNaN = FALSE; 524206917Smarius ax.isInf = FALSE; 525206917Smarius ax.isZero = FALSE; 526206917Smarius ax.sign = ( ( a & LIT64( 0x8000000000000000 ) ) != 0 ); 527206917Smarius expField = ( a>>52 ) & 0x7FF; 528206917Smarius ax.sig.a1 = 0; 529206917Smarius ax.sig.a0 = a & LIT64( 0x000FFFFFFFFFFFFF ); 530206917Smarius if ( expField == 0 ) { 531206917Smarius if ( ax.sig.a0 == 0 ) { 532206917Smarius ax.isZero = TRUE; 533206917Smarius } 534206917Smarius else { 535206917Smarius expField = 1 - 0x3FF; 536206917Smarius do { 537206917Smarius ax.sig.a0 <<= 1; 538206917Smarius --expField; 539206917Smarius } while ( ax.sig.a0 < LIT64( 0x0010000000000000 ) ); 540206917Smarius ax.exp = expField; 541206917Smarius } 542206917Smarius } 543206917Smarius else if ( expField == 0x7FF ) { 544206917Smarius if ( ax.sig.a0 == 0 ) { 545206917Smarius ax.isInf = TRUE; 546206917Smarius } 547206917Smarius else { 548206917Smarius ax.isNaN = TRUE; 549206917Smarius } 550206917Smarius } 551206917Smarius else { 552206917Smarius ax.exp = expField - 0x3FF; 553206917Smarius ax.sig.a0 |= LIT64( 0x0010000000000000 ); 554206917Smarius } 555206917Smarius ax.sig.a0 <<= 3; 556206917Smarius return ax; 557206917Smarius 558206917Smarius} 559206917Smarius 560206917Smariusstatic float64 floatXToFloat64( floatX zx ) 561206917Smarius{ 562206917Smarius floatX savedZ; 563206917Smarius flag isTiny; 564206917Smarius int32 expField; 565206917Smarius float64 z; 566206917Smarius 567206917Smarius if ( zx.isZero ) return zx.sign ? LIT64( 0x8000000000000000 ) : 0; 568206917Smarius if ( zx.isInf ) { 569206917Smarius return 570206917Smarius zx.sign ? LIT64( 0xFFF0000000000000 ) 571206917Smarius : LIT64( 0x7FF0000000000000 ); 572206917Smarius } 573206917Smarius if ( zx.isNaN ) return LIT64( 0xFFFFFFFFFFFFFFFF ); 574206917Smarius while ( LIT64( 0x0100000000000000 ) <= zx.sig.a0 ) { 575206917Smarius zx.sig = shortShift128RightJamming( zx.sig, 1 ); 576206917Smarius ++zx.exp; 577206917Smarius } 578206917Smarius while ( zx.sig.a0 < LIT64( 0x0080000000000000 ) ) { 579206917Smarius zx.sig = shortShift128Left( zx.sig, 1 ); 580206917Smarius --zx.exp; 581206917Smarius } 582206917Smarius savedZ = zx; 583206917Smarius isTiny = 584206917Smarius ( slow_float_detect_tininess == float_tininess_before_rounding ) 585206917Smarius && ( zx.exp + 0x3FF <= 0 ); 586206917Smarius zx = roundFloatXTo53( isTiny, zx ); 587206917Smarius expField = zx.exp + 0x3FF; 588206917Smarius if ( 0x7FF <= expField ) { 589206917Smarius slow_float_exception_flags |= 590206917Smarius float_flag_overflow | float_flag_inexact; 591206917Smarius if ( zx.sign ) { 592206917Smarius switch ( slow_float_rounding_mode ) { 593206917Smarius case float_round_nearest_even: 594206917Smarius case float_round_down: 595206917Smarius z = LIT64( 0xFFF0000000000000 ); 596206917Smarius break; 597206917Smarius case float_round_to_zero: 598206917Smarius case float_round_up: 599206917Smarius z = LIT64( 0xFFEFFFFFFFFFFFFF ); 600206917Smarius break; 601206917Smarius } 602206917Smarius } 603206917Smarius else { 604206917Smarius switch ( slow_float_rounding_mode ) { 605206917Smarius case float_round_nearest_even: 606206917Smarius case float_round_up: 607206917Smarius z = LIT64( 0x7FF0000000000000 ); 608206917Smarius break; 609206917Smarius case float_round_to_zero: 610206917Smarius case float_round_down: 611206917Smarius z = LIT64( 0x7FEFFFFFFFFFFFFF ); 612206917Smarius break; 613206917Smarius } 614206917Smarius } 615206917Smarius return z; 616206917Smarius } 617206917Smarius if ( expField <= 0 ) { 618206917Smarius isTiny = TRUE; 619206917Smarius zx = savedZ; 620206917Smarius expField = zx.exp + 0x3FF; 621206917Smarius if ( expField < -56 ) { 622206917Smarius zx.sig.a1 = ( zx.sig.a0 != 0 ) || ( zx.sig.a1 != 0 ); 623206917Smarius zx.sig.a0 = 0; 624206917Smarius } 625206917Smarius else { 626206917Smarius while ( expField <= 0 ) { 627206917Smarius zx.sig = shortShift128RightJamming( zx.sig, 1 ); 628206917Smarius ++expField; 629206917Smarius } 630206917Smarius } 631206917Smarius zx = roundFloatXTo53( isTiny, zx ); 632206917Smarius expField = ( LIT64( 0x0080000000000000 ) <= zx.sig.a0 ) ? 1 : 0; 633206917Smarius } 634206917Smarius zx.sig.a0 >>= 3; 635206917Smarius z = expField; 636206917Smarius z <<= 52; 637206917Smarius if ( zx.sign ) z |= LIT64( 0x8000000000000000 ); 638206917Smarius z |= zx.sig.a0 & LIT64( 0x000FFFFFFFFFFFFF ); 639206917Smarius return z; 640206917Smarius 641206917Smarius} 642206917Smarius 643206917Smarius#ifdef FLOATX80 644206917Smarius 645206917Smariusstatic floatX floatx80ToFloatX( floatx80 a ) 646206917Smarius{ 647206917Smarius int32 expField; 648206917Smarius floatX ax; 649206917Smarius 650206917Smarius ax.isNaN = FALSE; 651206917Smarius ax.isInf = FALSE; 652206917Smarius ax.isZero = FALSE; 653206917Smarius ax.sign = ( ( a.high & 0x8000 ) != 0 ); 654206917Smarius expField = a.high & 0x7FFF; 655206917Smarius ax.sig.a1 = a.low; 656206917Smarius ax.sig.a0 = 0; 657206917Smarius if ( expField == 0 ) { 658206917Smarius if ( ax.sig.a1 == 0 ) { 659206917Smarius ax.isZero = TRUE; 660206917Smarius } 661206917Smarius else { 662206917Smarius expField = 1 - 0x3FFF; 663206917Smarius while ( ax.sig.a1 < LIT64( 0x8000000000000000 ) ) { 664206917Smarius ax.sig.a1 <<= 1; 665206917Smarius --expField; 666206917Smarius } 667206917Smarius ax.exp = expField; 668206917Smarius } 669206917Smarius } 670206917Smarius else if ( expField == 0x7FFF ) { 671206917Smarius if ( ( ax.sig.a1 & LIT64( 0x7FFFFFFFFFFFFFFF ) ) == 0 ) { 672206917Smarius ax.isInf = TRUE; 673206917Smarius } 674206917Smarius else { 675206917Smarius ax.isNaN = TRUE; 676206917Smarius } 677206917Smarius } 678206917Smarius else { 679206917Smarius ax.exp = expField - 0x3FFF; 680206917Smarius } 681206917Smarius ax.sig = shortShift128Left( ax.sig, 56 ); 682206917Smarius return ax; 683206917Smarius 684206917Smarius} 685206917Smarius 686206917Smariusstatic floatx80 floatXToFloatx80( floatX zx ) 687206917Smarius{ 688206917Smarius floatX savedZ; 689206917Smarius flag isTiny; 690206917Smarius int32 expField; 691206917Smarius floatx80 z; 692206917Smarius 693206917Smarius if ( zx.isZero ) { 694206917Smarius z.low = 0; 695206917Smarius z.high = zx.sign ? 0x8000 : 0; 696206917Smarius return z; 697206917Smarius } 698206917Smarius if ( zx.isInf ) { 699206917Smarius z.low = LIT64( 0x8000000000000000 ); 700206917Smarius z.high = zx.sign ? 0xFFFF : 0x7FFF; 701206917Smarius return z; 702206917Smarius } 703206917Smarius if ( zx.isNaN ) { 704206917Smarius z.low = LIT64( 0xFFFFFFFFFFFFFFFF ); 705206917Smarius z.high = 0xFFFF; 706206917Smarius return z; 707206917Smarius } 708206917Smarius while ( LIT64( 0x0100000000000000 ) <= zx.sig.a0 ) { 709206917Smarius zx.sig = shortShift128RightJamming( zx.sig, 1 ); 710206917Smarius ++zx.exp; 711206917Smarius } 712206917Smarius while ( zx.sig.a0 < LIT64( 0x0080000000000000 ) ) { 713206917Smarius zx.sig = shortShift128Left( zx.sig, 1 ); 714206917Smarius --zx.exp; 715206917Smarius } 716206917Smarius savedZ = zx; 717206917Smarius isTiny = 718206917Smarius ( slow_float_detect_tininess == float_tininess_before_rounding ) 719206917Smarius && ( zx.exp + 0x3FFF <= 0 ); 720206917Smarius switch ( slow_floatx80_rounding_precision ) { 721206917Smarius case 32: 722206917Smarius zx = roundFloatXTo24( isTiny, zx ); 723206917Smarius break; 724206917Smarius case 64: 725206917Smarius zx = roundFloatXTo53( isTiny, zx ); 726206917Smarius break; 727206917Smarius default: 728206917Smarius zx = roundFloatXTo64( isTiny, zx ); 729206917Smarius break; 730206917Smarius } 731206917Smarius expField = zx.exp + 0x3FFF; 732206917Smarius if ( 0x7FFF <= expField ) { 733206917Smarius slow_float_exception_flags |= 734206917Smarius float_flag_overflow | float_flag_inexact; 735206917Smarius if ( zx.sign ) { 736206917Smarius switch ( slow_float_rounding_mode ) { 737206917Smarius case float_round_nearest_even: 738206917Smarius case float_round_down: 739206917Smarius z.low = LIT64( 0x8000000000000000 ); 740206917Smarius z.high = 0xFFFF; 741206917Smarius break; 742206917Smarius case float_round_to_zero: 743206917Smarius case float_round_up: 744206917Smarius switch ( slow_floatx80_rounding_precision ) { 745206917Smarius case 32: 746206917Smarius z.low = LIT64( 0xFFFFFF0000000000 ); 747206917Smarius break; 748206917Smarius case 64: 749206917Smarius z.low = LIT64( 0xFFFFFFFFFFFFF800 ); 750206917Smarius break; 751206917Smarius default: 752206917Smarius z.low = LIT64( 0xFFFFFFFFFFFFFFFF ); 753206917Smarius break; 754206917Smarius } 755206917Smarius z.high = 0xFFFE; 756206917Smarius break; 757206917Smarius } 758206917Smarius } 759206917Smarius else { 760206917Smarius switch ( slow_float_rounding_mode ) { 761206917Smarius case float_round_nearest_even: 762206917Smarius case float_round_up: 763206917Smarius z.low = LIT64( 0x8000000000000000 ); 764206917Smarius z.high = 0x7FFF; 765206917Smarius break; 766206917Smarius case float_round_to_zero: 767206917Smarius case float_round_down: 768206917Smarius switch ( slow_floatx80_rounding_precision ) { 769206917Smarius case 32: 770206917Smarius z.low = LIT64( 0xFFFFFF0000000000 ); 771206917Smarius break; 772206917Smarius case 64: 773206917Smarius z.low = LIT64( 0xFFFFFFFFFFFFF800 ); 774206917Smarius break; 775206917Smarius default: 776206917Smarius z.low = LIT64( 0xFFFFFFFFFFFFFFFF ); 777206917Smarius break; 778206917Smarius } 779206917Smarius z.high = 0x7FFE; 780206917Smarius break; 781206917Smarius } 782206917Smarius } 783206917Smarius return z; 784206917Smarius } 785206917Smarius if ( expField <= 0 ) { 786206917Smarius isTiny = TRUE; 787206917Smarius zx = savedZ; 788206917Smarius expField = zx.exp + 0x3FFF; 789206917Smarius if ( expField < -70 ) { 790206917Smarius zx.sig.a1 = ( zx.sig.a0 != 0 ) || ( zx.sig.a1 != 0 ); 791206917Smarius zx.sig.a0 = 0; 792206917Smarius } 793206917Smarius else { 794206917Smarius while ( expField <= 0 ) { 795206917Smarius zx.sig = shortShift128RightJamming( zx.sig, 1 ); 796206917Smarius ++expField; 797206917Smarius } 798206917Smarius } 799206917Smarius switch ( slow_floatx80_rounding_precision ) { 800206917Smarius case 32: 801206917Smarius zx = roundFloatXTo24( isTiny, zx ); 802206917Smarius break; 803206917Smarius case 64: 804206917Smarius zx = roundFloatXTo53( isTiny, zx ); 805206917Smarius break; 806206917Smarius default: 807206917Smarius zx = roundFloatXTo64( isTiny, zx ); 808206917Smarius break; 809206917Smarius } 810206917Smarius expField = ( LIT64( 0x0080000000000000 ) <= zx.sig.a0 ) ? 1 : 0; 811206917Smarius } 812206917Smarius zx.sig = shortShift128RightJamming( zx.sig, 56 ); 813206917Smarius z.low = zx.sig.a1; 814206917Smarius z.high = expField; 815206917Smarius if ( zx.sign ) z.high |= 0x8000; 816206917Smarius return z; 817206917Smarius 818206917Smarius} 819206917Smarius 820206917Smarius#endif 821206917Smarius 822206917Smarius#ifdef FLOAT128 823206917Smarius 824206917Smariusstatic floatX float128ToFloatX( float128 a ) 825206917Smarius{ 826206917Smarius int32 expField; 827206917Smarius floatX ax; 828206917Smarius 829206917Smarius ax.isNaN = FALSE; 830206917Smarius ax.isInf = FALSE; 831206917Smarius ax.isZero = FALSE; 832206917Smarius ax.sign = ( ( a.high & LIT64( 0x8000000000000000 ) ) != 0 ); 833206917Smarius expField = ( a.high>>48 ) & 0x7FFF; 834206917Smarius ax.sig.a1 = a.low; 835206917Smarius ax.sig.a0 = a.high & LIT64( 0x0000FFFFFFFFFFFF ); 836206917Smarius if ( expField == 0 ) { 837206917Smarius if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) { 838206917Smarius ax.isZero = TRUE; 839206917Smarius } 840206917Smarius else { 841206917Smarius expField = 1 - 0x3FFF; 842206917Smarius do { 843206917Smarius ax.sig = shortShift128Left( ax.sig, 1 ); 844206917Smarius --expField; 845206917Smarius } while ( ax.sig.a0 < LIT64( 0x0001000000000000 ) ); 846206917Smarius ax.exp = expField; 847206917Smarius } 848206917Smarius } 849206917Smarius else if ( expField == 0x7FFF ) { 850206917Smarius if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) { 851206917Smarius ax.isInf = TRUE; 852206917Smarius } 853206917Smarius else { 854206917Smarius ax.isNaN = TRUE; 855206917Smarius } 856206917Smarius } 857206917Smarius else { 858206917Smarius ax.exp = expField - 0x3FFF; 859206917Smarius ax.sig.a0 |= LIT64( 0x0001000000000000 ); 860206917Smarius } 861206917Smarius ax.sig = shortShift128Left( ax.sig, 7 ); 862206917Smarius return ax; 863206917Smarius 864206917Smarius} 865206917Smarius 866206917Smariusstatic float128 floatXToFloat128( floatX zx ) 867206917Smarius{ 868206917Smarius floatX savedZ; 869206917Smarius flag isTiny; 870206917Smarius int32 expField; 871206917Smarius float128 z; 872206917Smarius 873206917Smarius if ( zx.isZero ) { 874206917Smarius z.low = 0; 875206917Smarius z.high = zx.sign ? LIT64( 0x8000000000000000 ) : 0; 876206917Smarius return z; 877206917Smarius } 878206917Smarius if ( zx.isInf ) { 879206917Smarius z.low = 0; 880206917Smarius z.high = 881206917Smarius zx.sign ? LIT64( 0xFFFF000000000000 ) 882206917Smarius : LIT64( 0x7FFF000000000000 ); 883206917Smarius return z; 884206917Smarius } 885206917Smarius if ( zx.isNaN ) { 886206917Smarius z.high = z.low = LIT64( 0xFFFFFFFFFFFFFFFF ); 887206917Smarius return z; 888206917Smarius } 889206917Smarius while ( LIT64( 0x0100000000000000 ) <= zx.sig.a0 ) { 890206917Smarius zx.sig = shortShift128RightJamming( zx.sig, 1 ); 891206917Smarius ++zx.exp; 892206917Smarius } 893206917Smarius while ( zx.sig.a0 < LIT64( 0x0080000000000000 ) ) { 894206917Smarius zx.sig = shortShift128Left( zx.sig, 1 ); 895206917Smarius --zx.exp; 896206917Smarius } 897206917Smarius savedZ = zx; 898206917Smarius isTiny = 899206917Smarius ( slow_float_detect_tininess == float_tininess_before_rounding ) 900206917Smarius && ( zx.exp + 0x3FFF <= 0 ); 901206917Smarius zx = roundFloatXTo113( isTiny, zx ); 902206917Smarius expField = zx.exp + 0x3FFF; 903206917Smarius if ( 0x7FFF <= expField ) { 904206917Smarius slow_float_exception_flags |= 905206917Smarius float_flag_overflow | float_flag_inexact; 906206917Smarius if ( zx.sign ) { 907206917Smarius switch ( slow_float_rounding_mode ) { 908206917Smarius case float_round_nearest_even: 909206917Smarius case float_round_down: 910206917Smarius z.low = 0; 911206917Smarius z.high = LIT64( 0xFFFF000000000000 ); 912206917Smarius break; 913206917Smarius case float_round_to_zero: 914206917Smarius case float_round_up: 915206917Smarius z.low = LIT64( 0xFFFFFFFFFFFFFFFF ); 916206917Smarius z.high = LIT64( 0xFFFEFFFFFFFFFFFF ); 917206917Smarius break; 918206917Smarius } 919206917Smarius } 920206917Smarius else { 921206917Smarius switch ( slow_float_rounding_mode ) { 922206917Smarius case float_round_nearest_even: 923206917Smarius case float_round_up: 924206917Smarius z.low = 0; 925206917Smarius z.high = LIT64( 0x7FFF000000000000 ); 926206917Smarius break; 927206917Smarius case float_round_to_zero: 928206917Smarius case float_round_down: 929206917Smarius z.low = LIT64( 0xFFFFFFFFFFFFFFFF ); 930206917Smarius z.high = LIT64( 0x7FFEFFFFFFFFFFFF ); 931206917Smarius break; 932206917Smarius } 933206917Smarius } 934206917Smarius return z; 935206917Smarius } 936206917Smarius if ( expField <= 0 ) { 937206917Smarius isTiny = TRUE; 938206917Smarius zx = savedZ; 939206917Smarius expField = zx.exp + 0x3FFF; 940206917Smarius if ( expField < -120 ) { 941206917Smarius zx.sig.a1 = ( zx.sig.a0 != 0 ) || ( zx.sig.a1 != 0 ); 942206917Smarius zx.sig.a0 = 0; 943206917Smarius } 944206917Smarius else { 945206917Smarius while ( expField <= 0 ) { 946206917Smarius zx.sig = shortShift128RightJamming( zx.sig, 1 ); 947206917Smarius ++expField; 948206917Smarius } 949206917Smarius } 950206917Smarius zx = roundFloatXTo113( isTiny, zx ); 951206917Smarius expField = ( LIT64( 0x0080000000000000 ) <= zx.sig.a0 ) ? 1 : 0; 952206917Smarius } 953206917Smarius zx.sig = shortShift128RightJamming( zx.sig, 7 ); 954206917Smarius z.low = zx.sig.a1; 955206917Smarius z.high = expField; 956206917Smarius z.high <<= 48; 957206917Smarius if ( zx.sign ) z.high |= LIT64( 0x8000000000000000 ); 958206917Smarius z.high |= zx.sig.a0 & LIT64( 0x0000FFFFFFFFFFFF ); 959206917Smarius return z; 960206917Smarius 961206917Smarius} 962206917Smarius 963206917Smarius#endif 964206917Smarius 965206917Smariusstatic floatX floatXInvalid( void ) 966206917Smarius{ 967206917Smarius 968206917Smarius slow_float_exception_flags |= float_flag_invalid; 969206917Smarius return floatXNaN; 970206917Smarius 971206917Smarius} 972206917Smarius 973206917Smariusstatic floatX floatXRoundToInt( floatX ax ) 974206917Smarius{ 975206917Smarius int32 shiftCount, i; 976206917Smarius 977206917Smarius if ( ax.isNaN || ax.isInf ) return ax; 978206917Smarius shiftCount = 112 - ax.exp; 979206917Smarius if ( shiftCount <= 0 ) return ax; 980206917Smarius if ( 119 < shiftCount ) { 981206917Smarius ax.exp = 112; 982206917Smarius ax.sig.a1 = ! ax.isZero; 983206917Smarius ax.sig.a0 = 0; 984206917Smarius } 985206917Smarius else { 986206917Smarius while ( 0 < shiftCount ) { 987206917Smarius ax.sig = shortShift128RightJamming( ax.sig, 1 ); 988206917Smarius ++ax.exp; 989206917Smarius --shiftCount; 990206917Smarius } 991206917Smarius } 992206917Smarius ax = roundFloatXTo113( FALSE, ax ); 993206917Smarius if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) ax.isZero = TRUE; 994206917Smarius return ax; 995206917Smarius 996206917Smarius} 997206917Smarius 998206917Smariusstatic floatX floatXAdd( floatX ax, floatX bx ) 999206917Smarius{ 1000206917Smarius int32 expDiff; 1001206917Smarius floatX zx; 1002206917Smarius 1003206917Smarius if ( ax.isNaN ) return ax; 1004206917Smarius if ( bx.isNaN ) return bx; 1005206917Smarius if ( ax.isInf && bx.isInf ) { 1006206917Smarius if ( ax.sign == bx.sign ) return ax; 1007206917Smarius return floatXInvalid(); 1008206917Smarius } 1009206917Smarius if ( ax.isInf ) return ax; 1010206917Smarius if ( bx.isInf ) return bx; 1011206917Smarius if ( ax.isZero && bx.isZero ) { 1012206917Smarius if ( ax.sign == bx.sign ) return ax; 1013206917Smarius goto completeCancellation; 1014206917Smarius } 1015206917Smarius if ( ( ax.sign != bx.sign ) 1016206917Smarius && ( ax.exp == bx.exp ) 1017206917Smarius && eq128( ax.sig, bx.sig ) 1018206917Smarius ) { 1019206917Smarius completeCancellation: 1020206917Smarius return 1021206917Smarius ( slow_float_rounding_mode == float_round_down ) ? 1022206917Smarius floatXNegativeZero 1023206917Smarius : floatXPositiveZero; 1024206917Smarius } 1025206917Smarius if ( ax.isZero ) return bx; 1026206917Smarius if ( bx.isZero ) return ax; 1027206917Smarius expDiff = ax.exp - bx.exp; 1028206917Smarius if ( expDiff < 0 ) { 1029206917Smarius zx = ax; 1030206917Smarius zx.exp = bx.exp; 1031206917Smarius if ( expDiff < -120 ) { 1032206917Smarius zx.sig.a1 = 1; 1033206917Smarius zx.sig.a0 = 0; 1034206917Smarius } 1035206917Smarius else { 1036206917Smarius while ( expDiff < 0 ) { 1037206917Smarius zx.sig = shortShift128RightJamming( zx.sig, 1 ); 1038206917Smarius ++expDiff; 1039206917Smarius } 1040206917Smarius } 1041206917Smarius if ( ax.sign != bx.sign ) zx.sig = neg128( zx.sig ); 1042206917Smarius zx.sign = bx.sign; 1043206917Smarius zx.sig = add128( zx.sig, bx.sig ); 1044206917Smarius } 1045206917Smarius else { 1046206917Smarius zx = bx; 1047206917Smarius zx.exp = ax.exp; 1048206917Smarius if ( 120 < expDiff ) { 1049206917Smarius zx.sig.a1 = 1; 1050206917Smarius zx.sig.a0 = 0; 1051206917Smarius } 1052206917Smarius else { 1053206917Smarius while ( 0 < expDiff ) { 1054206917Smarius zx.sig = shortShift128RightJamming( zx.sig, 1 ); 1055206917Smarius --expDiff; 1056206917Smarius } 1057206917Smarius } 1058206917Smarius if ( ax.sign != bx.sign ) zx.sig = neg128( zx.sig ); 1059206917Smarius zx.sign = ax.sign; 1060206917Smarius zx.sig = add128( zx.sig, ax.sig ); 1061206917Smarius } 1062206917Smarius if ( zx.sig.a0 & LIT64( 0x8000000000000000 ) ) { 1063206917Smarius zx.sig = neg128( zx.sig ); 1064206917Smarius zx.sign = ! zx.sign; 1065206917Smarius } 1066206917Smarius return zx; 1067206917Smarius 1068206917Smarius} 1069206917Smarius 1070206917Smariusstatic floatX floatXMul( floatX ax, floatX bx ) 1071206917Smarius{ 1072206917Smarius int8 bitNum; 1073206917Smarius floatX zx; 1074206917Smarius 1075206917Smarius if ( ax.isNaN ) return ax; 1076206917Smarius if ( bx.isNaN ) return bx; 1077206917Smarius if ( ax.isInf ) { 1078206917Smarius if ( bx.isZero ) return floatXInvalid(); 1079206917Smarius if ( bx.sign ) ax.sign = ! ax.sign; 1080206917Smarius return ax; 1081206917Smarius } 1082206917Smarius if ( bx.isInf ) { 1083206917Smarius if ( ax.isZero ) return floatXInvalid(); 1084206917Smarius if ( ax.sign ) bx.sign = ! bx.sign; 1085206917Smarius return bx; 1086206917Smarius } 1087206917Smarius zx = ax; 1088206917Smarius zx.sign ^= bx.sign; 1089206917Smarius if ( ax.isZero || bx.isZero ) { 1090206917Smarius return zx.sign ? floatXNegativeZero : floatXPositiveZero; 1091206917Smarius } 1092206917Smarius zx.exp += bx.exp + 1; 1093206917Smarius zx.sig.a1 = 0; 1094206917Smarius zx.sig.a0 = 0; 1095206917Smarius for ( bitNum = 0; bitNum < 119; ++bitNum ) { 1096206917Smarius if ( bx.sig.a1 & 2 ) zx.sig = add128( zx.sig, ax.sig ); 1097206917Smarius bx.sig = shortShift128RightJamming( bx.sig, 1 ); 1098206917Smarius zx.sig = shortShift128RightJamming( zx.sig, 1 ); 1099206917Smarius } 1100206917Smarius return zx; 1101206917Smarius 1102206917Smarius} 1103206917Smarius 1104206917Smariusstatic floatX floatXDiv( floatX ax, floatX bx ) 1105206917Smarius{ 1106206917Smarius bits128X negBSig; 1107206917Smarius int8 bitNum; 1108206917Smarius floatX zx; 1109206917Smarius 1110206917Smarius if ( ax.isNaN ) return ax; 1111206917Smarius if ( bx.isNaN ) return bx; 1112206917Smarius if ( ax.isInf ) { 1113206917Smarius if ( bx.isInf ) return floatXInvalid(); 1114206917Smarius if ( bx.sign ) ax.sign = ! ax.sign; 1115206917Smarius return ax; 1116206917Smarius } 1117206917Smarius if ( bx.isZero ) { 1118206917Smarius if ( ax.isZero ) return floatXInvalid(); 1119206917Smarius slow_float_exception_flags |= float_flag_divbyzero; 1120206917Smarius if ( ax.sign ) bx.sign = ! bx.sign; 1121206917Smarius bx.isZero = FALSE; 1122206917Smarius bx.isInf = TRUE; 1123206917Smarius return bx; 1124206917Smarius } 1125206917Smarius zx = ax; 1126206917Smarius zx.sign ^= bx.sign; 1127206917Smarius if ( ax.isZero || bx.isInf ) { 1128206917Smarius return zx.sign ? floatXNegativeZero : floatXPositiveZero; 1129206917Smarius } 1130206917Smarius zx.exp -= bx.exp + 1; 1131206917Smarius zx.sig.a1 = 0; 1132206917Smarius zx.sig.a0 = 0; 1133206917Smarius negBSig = neg128( bx.sig ); 1134206917Smarius for ( bitNum = 0; bitNum < 120; ++bitNum ) { 1135206917Smarius if ( le128( bx.sig, ax.sig ) ) { 1136206917Smarius zx.sig.a1 |= 1; 1137206917Smarius ax.sig = add128( ax.sig, negBSig ); 1138206917Smarius } 1139206917Smarius ax.sig = shortShift128Left( ax.sig, 1 ); 1140206917Smarius zx.sig = shortShift128Left( zx.sig, 1 ); 1141206917Smarius } 1142206917Smarius if ( ax.sig.a0 || ax.sig.a1 ) zx.sig.a1 |= 1; 1143206917Smarius return zx; 1144206917Smarius 1145206917Smarius} 1146206917Smarius 1147206917Smariusstatic floatX floatXRem( floatX ax, floatX bx ) 1148206917Smarius{ 1149206917Smarius bits128X negBSig; 1150206917Smarius flag lastQuotientBit; 1151206917Smarius bits128X savedASig; 1152206917Smarius 1153206917Smarius if ( ax.isNaN ) return ax; 1154206917Smarius if ( bx.isNaN ) return bx; 1155206917Smarius if ( ax.isInf || bx.isZero ) return floatXInvalid(); 1156206917Smarius if ( ax.isZero || bx.isInf ) return ax; 1157206917Smarius --bx.exp; 1158206917Smarius if ( ax.exp < bx.exp ) return ax; 1159206917Smarius bx.sig = shortShift128Left( bx.sig, 1 ); 1160206917Smarius negBSig = neg128( bx.sig ); 1161206917Smarius while ( bx.exp < ax.exp ) { 1162206917Smarius if ( le128( bx.sig, ax.sig ) ) ax.sig = add128( ax.sig, negBSig ); 1163206917Smarius ax.sig = shortShift128Left( ax.sig, 1 ); 1164206917Smarius --ax.exp; 1165206917Smarius } 1166206917Smarius lastQuotientBit = le128( bx.sig, ax.sig ); 1167206917Smarius if ( lastQuotientBit ) ax.sig = add128( ax.sig, negBSig ); 1168206917Smarius savedASig = ax.sig; 1169206917Smarius ax.sig = neg128( add128( ax.sig, negBSig ) ); 1170206917Smarius if ( lt128( ax.sig, savedASig ) ) { 1171206917Smarius ax.sign = ! ax.sign; 1172206917Smarius } 1173206917Smarius else if ( lt128( savedASig, ax.sig ) ) { 1174206917Smarius ax.sig = savedASig; 1175206917Smarius } 1176206917Smarius else { 1177206917Smarius if ( lastQuotientBit ) { 1178206917Smarius ax.sign = ! ax.sign; 1179206917Smarius } 1180206917Smarius else { 1181206917Smarius ax.sig = savedASig; 1182206917Smarius } 1183206917Smarius } 1184206917Smarius if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) ax.isZero = TRUE; 1185206917Smarius return ax; 1186206917Smarius 1187206917Smarius} 1188206917Smarius 1189206917Smariusstatic floatX floatXSqrt( floatX ax ) 1190206917Smarius{ 1191206917Smarius int8 bitNum; 1192206917Smarius bits128X bitSig, savedASig; 1193206917Smarius floatX zx; 1194206917Smarius 1195206917Smarius if ( ax.isNaN || ax.isZero ) return ax; 1196206917Smarius if ( ax.sign ) return floatXInvalid(); 1197206917Smarius if ( ax.isInf ) return ax; 1198206917Smarius zx = ax; 1199206917Smarius zx.exp >>= 1; 1200206917Smarius if ( ( ax.exp & 1 ) == 0 ) ax.sig = shortShift128RightJamming( ax.sig, 1 ); 1201206917Smarius zx.sig.a1 = 0; 1202206917Smarius zx.sig.a0 = 0; 1203206917Smarius bitSig.a1 = 0; 1204206917Smarius bitSig.a0 = LIT64( 0x0080000000000000 ); 1205206917Smarius for ( bitNum = 0; bitNum < 120; ++bitNum ) { 1206206917Smarius savedASig = ax.sig; 1207206917Smarius ax.sig = add128( ax.sig, neg128( zx.sig ) ); 1208206917Smarius ax.sig = shortShift128Left( ax.sig, 1 ); 1209206917Smarius ax.sig = add128( ax.sig, neg128( bitSig ) ); 1210206917Smarius if ( ax.sig.a0 & LIT64( 0x8000000000000000 ) ) { 1211206917Smarius ax.sig = shortShift128Left( savedASig, 1 ); 1212206917Smarius } 1213206917Smarius else { 1214206917Smarius zx.sig.a1 |= bitSig.a1; 1215206917Smarius zx.sig.a0 |= bitSig.a0; 1216206917Smarius } 1217206917Smarius bitSig = shortShift128RightJamming( bitSig, 1 ); 1218206917Smarius } 1219206917Smarius if ( ax.sig.a0 || ax.sig.a1 ) zx.sig.a1 |= 1; 1220206917Smarius return zx; 1221206917Smarius 1222206917Smarius} 1223206917Smarius 1224206917Smariusstatic flag floatXEq( floatX ax, floatX bx ) 1225206917Smarius{ 1226206917Smarius 1227206917Smarius if ( ax.isNaN || bx.isNaN ) return FALSE; 1228206917Smarius if ( ax.isZero && bx.isZero ) return TRUE; 1229206917Smarius if ( ax.sign != bx.sign ) return FALSE; 1230206917Smarius if ( ax.isInf || bx.isInf ) return ax.isInf && bx.isInf; 1231206917Smarius return ( ax.exp == bx.exp ) && eq128( ax.sig, bx.sig ); 1232206917Smarius 1233206917Smarius} 1234206917Smarius 1235206917Smariusstatic flag floatXLe( floatX ax, floatX bx ) 1236206917Smarius{ 1237206917Smarius 1238206917Smarius if ( ax.isNaN || bx.isNaN ) return FALSE; 1239206917Smarius if ( ax.isZero && bx.isZero ) return TRUE; 1240206917Smarius if ( ax.sign != bx.sign ) return ax.sign; 1241206917Smarius if ( ax.sign ) { 1242206917Smarius if ( ax.isInf || bx.isZero ) return TRUE; 1243206917Smarius if ( bx.isInf || ax.isZero ) return FALSE; 1244206917Smarius if ( bx.exp < ax.exp ) return TRUE; 1245206917Smarius if ( ax.exp < bx.exp ) return FALSE; 1246206917Smarius return le128( bx.sig, ax.sig ); 1247206917Smarius } 1248206917Smarius else { 1249206917Smarius if ( bx.isInf || ax.isZero ) return TRUE; 1250206917Smarius if ( ax.isInf || bx.isZero ) return FALSE; 1251206917Smarius if ( ax.exp < bx.exp ) return TRUE; 1252206917Smarius if ( bx.exp < ax.exp ) return FALSE; 1253206917Smarius return le128( ax.sig, bx.sig ); 1254206917Smarius } 1255206917Smarius 1256206917Smarius} 1257206917Smarius 1258206917Smariusstatic flag floatXLt( floatX ax, floatX bx ) 1259206917Smarius{ 1260206917Smarius 1261206917Smarius if ( ax.isNaN || bx.isNaN ) return FALSE; 1262206917Smarius if ( ax.isZero && bx.isZero ) return FALSE; 1263206917Smarius if ( ax.sign != bx.sign ) return ax.sign; 1264206917Smarius if ( ax.isInf && bx.isInf ) return FALSE; 1265206917Smarius if ( ax.sign ) { 1266206917Smarius if ( ax.isInf || bx.isZero ) return TRUE; 1267206917Smarius if ( bx.isInf || ax.isZero ) return FALSE; 1268206917Smarius if ( bx.exp < ax.exp ) return TRUE; 1269206917Smarius if ( ax.exp < bx.exp ) return FALSE; 1270206917Smarius return lt128( bx.sig, ax.sig ); 1271206917Smarius } 1272206917Smarius else { 1273206917Smarius if ( bx.isInf || ax.isZero ) return TRUE; 1274206917Smarius if ( ax.isInf || bx.isZero ) return FALSE; 1275206917Smarius if ( ax.exp < bx.exp ) return TRUE; 1276206917Smarius if ( bx.exp < ax.exp ) return FALSE; 1277206917Smarius return lt128( ax.sig, bx.sig ); 1278206917Smarius } 1279206917Smarius 1280206917Smarius} 1281206917Smarius 1282206917Smariusfloat32 slow_int32_to_float32( int32 a ) 1283206917Smarius{ 1284206917Smarius 1285206917Smarius return floatXToFloat32( int32ToFloatX( a ) ); 1286206917Smarius 1287206917Smarius} 1288206917Smarius 1289206917Smariusfloat64 slow_int32_to_float64( int32 a ) 1290206917Smarius{ 1291206917Smarius 1292206917Smarius return floatXToFloat64( int32ToFloatX( a ) ); 1293206917Smarius 1294206917Smarius} 1295206917Smarius 1296206917Smarius#ifdef FLOATX80 1297206917Smarius 1298206917Smariusfloatx80 slow_int32_to_floatx80( int32 a ) 1299206917Smarius{ 1300206917Smarius 1301206917Smarius return floatXToFloatx80( int32ToFloatX( a ) ); 1302206917Smarius 1303206917Smarius} 1304206917Smarius 1305206917Smarius#endif 1306206917Smarius 1307206917Smarius#ifdef FLOAT128 1308206917Smarius 1309206917Smariusfloat128 slow_int32_to_float128( int32 a ) 1310206917Smarius{ 1311206917Smarius 1312206917Smarius return floatXToFloat128( int32ToFloatX( a ) ); 1313206917Smarius 1314206917Smarius} 1315206917Smarius 1316206917Smarius#endif 1317206917Smarius 1318206917Smariusfloat32 slow_int64_to_float32( int64 a ) 1319206917Smarius{ 1320206917Smarius 1321206917Smarius return floatXToFloat32( int64ToFloatX( a ) ); 1322206917Smarius 1323206917Smarius} 1324206917Smarius 1325206917Smariusfloat64 slow_int64_to_float64( int64 a ) 1326206917Smarius{ 1327206917Smarius 1328206917Smarius return floatXToFloat64( int64ToFloatX( a ) ); 1329206917Smarius 1330206917Smarius} 1331206917Smarius 1332206917Smarius#ifdef FLOATX80 1333206917Smarius 1334206917Smariusfloatx80 slow_int64_to_floatx80( int64 a ) 1335206917Smarius{ 1336206917Smarius 1337206917Smarius return floatXToFloatx80( int64ToFloatX( a ) ); 1338206917Smarius 1339206917Smarius} 1340206917Smarius 1341206917Smarius#endif 1342206917Smarius 1343206917Smarius#ifdef FLOAT128 1344206917Smarius 1345206917Smariusfloat128 slow_int64_to_float128( int64 a ) 1346206917Smarius{ 1347206917Smarius 1348206917Smarius return floatXToFloat128( int64ToFloatX( a ) ); 1349206917Smarius 1350206917Smarius} 1351206917Smarius 1352206917Smarius#endif 1353206917Smarius 1354206917Smariusint32 slow_float32_to_int32( float32 a ) 1355206917Smarius{ 1356206917Smarius 1357206917Smarius return floatXToInt32( float32ToFloatX( a ) ); 1358206917Smarius 1359206917Smarius} 1360206917Smarius 1361206917Smariusint32 slow_float32_to_int32_round_to_zero( float32 a ) 1362206917Smarius{ 1363206917Smarius int8 savedRoundingMode; 1364206917Smarius int32 z; 1365206917Smarius 1366206917Smarius savedRoundingMode = slow_float_rounding_mode; 1367206917Smarius slow_float_rounding_mode = float_round_to_zero; 1368206917Smarius z = floatXToInt32( float32ToFloatX( a ) ); 1369206917Smarius slow_float_rounding_mode = savedRoundingMode; 1370206917Smarius return z; 1371206917Smarius 1372206917Smarius} 1373206917Smarius 1374206917Smariusint64 slow_float32_to_int64( float32 a ) 1375206917Smarius{ 1376206917Smarius 1377206917Smarius return floatXToInt64( float32ToFloatX( a ) ); 1378206917Smarius 1379206917Smarius} 1380206917Smarius 1381206917Smariusint64 slow_float32_to_int64_round_to_zero( float32 a ) 1382206917Smarius{ 1383206917Smarius int8 savedRoundingMode; 1384206917Smarius int64 z; 1385206917Smarius 1386206917Smarius savedRoundingMode = slow_float_rounding_mode; 1387206917Smarius slow_float_rounding_mode = float_round_to_zero; 1388206917Smarius z = floatXToInt64( float32ToFloatX( a ) ); 1389206917Smarius slow_float_rounding_mode = savedRoundingMode; 1390206917Smarius return z; 1391206917Smarius 1392206917Smarius} 1393206917Smarius 1394206917Smariusfloat64 slow_float32_to_float64( float32 a ) 1395206917Smarius{ 1396206917Smarius 1397206917Smarius return floatXToFloat64( float32ToFloatX( a ) ); 1398206917Smarius 1399206917Smarius} 1400206917Smarius 1401206917Smarius#ifdef FLOATX80 1402206917Smarius 1403206917Smariusfloatx80 slow_float32_to_floatx80( float32 a ) 1404206917Smarius{ 1405206917Smarius 1406206917Smarius return floatXToFloatx80( float32ToFloatX( a ) ); 1407206917Smarius 1408206917Smarius} 1409206917Smarius 1410206917Smarius#endif 1411206917Smarius 1412206917Smarius#ifdef FLOAT128 1413206917Smarius 1414206917Smariusfloat128 slow_float32_to_float128( float32 a ) 1415206917Smarius{ 1416206917Smarius 1417206917Smarius return floatXToFloat128( float32ToFloatX( a ) ); 1418206917Smarius 1419206917Smarius} 1420206917Smarius 1421206917Smarius#endif 1422206917Smarius 1423206917Smariusfloat32 slow_float32_round_to_int( float32 a ) 1424206917Smarius{ 1425206917Smarius 1426206917Smarius return floatXToFloat32( floatXRoundToInt( float32ToFloatX( a ) ) ); 1427206917Smarius 1428206917Smarius} 1429206917Smarius 1430206917Smariusfloat32 slow_float32_add( float32 a, float32 b ) 1431206917Smarius{ 1432206917Smarius 1433206917Smarius return 1434206917Smarius floatXToFloat32( 1435206917Smarius floatXAdd( float32ToFloatX( a ), float32ToFloatX( b ) ) ); 1436206917Smarius 1437206917Smarius} 1438206917Smarius 1439206917Smariusfloat32 slow_float32_sub( float32 a, float32 b ) 1440206917Smarius{ 1441206917Smarius 1442206917Smarius b ^= 0x80000000; 1443206917Smarius return 1444206917Smarius floatXToFloat32( 1445206917Smarius floatXAdd( float32ToFloatX( a ), float32ToFloatX( b ) ) ); 1446206917Smarius 1447206917Smarius} 1448206917Smarius 1449206917Smariusfloat32 slow_float32_mul( float32 a, float32 b ) 1450206917Smarius{ 1451206917Smarius 1452206917Smarius return 1453206917Smarius floatXToFloat32( 1454206917Smarius floatXMul( float32ToFloatX( a ), float32ToFloatX( b ) ) ); 1455206917Smarius 1456206917Smarius} 1457206917Smarius 1458206917Smariusfloat32 slow_float32_div( float32 a, float32 b ) 1459206917Smarius{ 1460206917Smarius 1461206917Smarius return 1462206917Smarius floatXToFloat32( 1463206917Smarius floatXDiv( float32ToFloatX( a ), float32ToFloatX( b ) ) ); 1464206917Smarius 1465206917Smarius} 1466206917Smarius 1467206917Smariusfloat32 slow_float32_rem( float32 a, float32 b ) 1468206917Smarius{ 1469206917Smarius 1470206917Smarius return 1471206917Smarius floatXToFloat32( 1472206917Smarius floatXRem( float32ToFloatX( a ), float32ToFloatX( b ) ) ); 1473206917Smarius 1474206917Smarius} 1475206917Smarius 1476206917Smariusfloat32 slow_float32_sqrt( float32 a ) 1477206917Smarius{ 1478206917Smarius 1479206917Smarius return floatXToFloat32( floatXSqrt( float32ToFloatX( a ) ) ); 1480206917Smarius 1481206917Smarius} 1482206917Smarius 1483206917Smariusflag slow_float32_eq( float32 a, float32 b ) 1484206917Smarius{ 1485206917Smarius 1486206917Smarius return floatXEq( float32ToFloatX( a ), float32ToFloatX( b ) ); 1487206917Smarius 1488206917Smarius} 1489206917Smarius 1490206917Smariusflag slow_float32_le( float32 a, float32 b ) 1491206917Smarius{ 1492206917Smarius floatX ax, bx; 1493206917Smarius 1494206917Smarius ax = float32ToFloatX( a ); 1495206917Smarius bx = float32ToFloatX( b ); 1496206917Smarius if ( ax.isNaN || bx.isNaN ) { 1497206917Smarius slow_float_exception_flags |= float_flag_invalid; 1498206917Smarius } 1499206917Smarius return floatXLe( ax, bx ); 1500206917Smarius 1501206917Smarius} 1502206917Smarius 1503206917Smariusflag slow_float32_lt( float32 a, float32 b ) 1504206917Smarius{ 1505206917Smarius floatX ax, bx; 1506206917Smarius 1507206917Smarius ax = float32ToFloatX( a ); 1508206917Smarius bx = float32ToFloatX( b ); 1509206917Smarius if ( ax.isNaN || bx.isNaN ) { 1510206917Smarius slow_float_exception_flags |= float_flag_invalid; 1511206917Smarius } 1512206917Smarius return floatXLt( ax, bx ); 1513206917Smarius 1514206917Smarius} 1515206917Smarius 1516206917Smariusflag slow_float32_eq_signaling( float32 a, float32 b ) 1517206917Smarius{ 1518206917Smarius floatX ax, bx; 1519206917Smarius 1520206917Smarius ax = float32ToFloatX( a ); 1521206917Smarius bx = float32ToFloatX( b ); 1522206917Smarius if ( ax.isNaN || bx.isNaN ) { 1523206917Smarius slow_float_exception_flags |= float_flag_invalid; 1524206917Smarius } 1525206917Smarius return floatXEq( ax, bx ); 1526206917Smarius 1527206917Smarius} 1528206917Smarius 1529206917Smariusflag slow_float32_le_quiet( float32 a, float32 b ) 1530206917Smarius{ 1531206917Smarius 1532206917Smarius return floatXLe( float32ToFloatX( a ), float32ToFloatX( b ) ); 1533206917Smarius 1534206917Smarius} 1535206917Smarius 1536206917Smariusflag slow_float32_lt_quiet( float32 a, float32 b ) 1537206917Smarius{ 1538206917Smarius 1539206917Smarius return floatXLt( float32ToFloatX( a ), float32ToFloatX( b ) ); 1540206917Smarius 1541206917Smarius} 1542206917Smarius 1543206917Smariusint32 slow_float64_to_int32( float64 a ) 1544206917Smarius{ 1545206917Smarius 1546206917Smarius return floatXToInt32( float64ToFloatX( a ) ); 1547206917Smarius 1548206917Smarius} 1549206917Smarius 1550206917Smariusint32 slow_float64_to_int32_round_to_zero( float64 a ) 1551206917Smarius{ 1552206917Smarius int8 savedRoundingMode; 1553206917Smarius int32 z; 1554206917Smarius 1555206917Smarius savedRoundingMode = slow_float_rounding_mode; 1556206917Smarius slow_float_rounding_mode = float_round_to_zero; 1557206917Smarius z = floatXToInt32( float64ToFloatX( a ) ); 1558206917Smarius slow_float_rounding_mode = savedRoundingMode; 1559206917Smarius return z; 1560206917Smarius 1561206917Smarius} 1562206917Smarius 1563206917Smariusint64 slow_float64_to_int64( float64 a ) 1564206917Smarius{ 1565206917Smarius 1566206917Smarius return floatXToInt64( float64ToFloatX( a ) ); 1567206917Smarius 1568206917Smarius} 1569206917Smarius 1570206917Smariusint64 slow_float64_to_int64_round_to_zero( float64 a ) 1571206917Smarius{ 1572206917Smarius int8 savedRoundingMode; 1573206917Smarius int64 z; 1574206917Smarius 1575206917Smarius savedRoundingMode = slow_float_rounding_mode; 1576206917Smarius slow_float_rounding_mode = float_round_to_zero; 1577206917Smarius z = floatXToInt64( float64ToFloatX( a ) ); 1578206917Smarius slow_float_rounding_mode = savedRoundingMode; 1579206917Smarius return z; 1580206917Smarius 1581206917Smarius} 1582206917Smarius 1583206917Smariusfloat32 slow_float64_to_float32( float64 a ) 1584206917Smarius{ 1585206917Smarius 1586206917Smarius return floatXToFloat32( float64ToFloatX( a ) ); 1587206917Smarius 1588206917Smarius} 1589206917Smarius 1590206917Smarius#ifdef FLOATX80 1591206917Smarius 1592206917Smariusfloatx80 slow_float64_to_floatx80( float64 a ) 1593206917Smarius{ 1594206917Smarius 1595206917Smarius return floatXToFloatx80( float64ToFloatX( a ) ); 1596206917Smarius 1597206917Smarius} 1598206917Smarius 1599206917Smarius#endif 1600206917Smarius 1601206917Smarius#ifdef FLOAT128 1602206917Smarius 1603206917Smariusfloat128 slow_float64_to_float128( float64 a ) 1604206917Smarius{ 1605206917Smarius 1606206917Smarius return floatXToFloat128( float64ToFloatX( a ) ); 1607206917Smarius 1608206917Smarius} 1609206917Smarius 1610206917Smarius#endif 1611206917Smarius 1612206917Smariusfloat64 slow_float64_round_to_int( float64 a ) 1613206917Smarius{ 1614206917Smarius 1615206917Smarius return floatXToFloat64( floatXRoundToInt( float64ToFloatX( a ) ) ); 1616206917Smarius 1617206917Smarius} 1618206917Smarius 1619206917Smariusfloat64 slow_float64_add( float64 a, float64 b ) 1620206917Smarius{ 1621206917Smarius 1622206917Smarius return 1623206917Smarius floatXToFloat64( 1624206917Smarius floatXAdd( float64ToFloatX( a ), float64ToFloatX( b ) ) ); 1625206917Smarius 1626206917Smarius} 1627206917Smarius 1628206917Smariusfloat64 slow_float64_sub( float64 a, float64 b ) 1629206917Smarius{ 1630206917Smarius 1631206917Smarius b ^= LIT64( 0x8000000000000000 ); 1632206917Smarius return 1633206917Smarius floatXToFloat64( 1634206917Smarius floatXAdd( float64ToFloatX( a ), float64ToFloatX( b ) ) ); 1635206917Smarius 1636206917Smarius} 1637206917Smarius 1638206917Smariusfloat64 slow_float64_mul( float64 a, float64 b ) 1639206917Smarius{ 1640206917Smarius 1641206917Smarius return 1642206917Smarius floatXToFloat64( 1643206917Smarius floatXMul( float64ToFloatX( a ), float64ToFloatX( b ) ) ); 1644206917Smarius 1645206917Smarius} 1646206917Smarius 1647206917Smariusfloat64 slow_float64_div( float64 a, float64 b ) 1648206917Smarius{ 1649206917Smarius 1650206917Smarius return 1651206917Smarius floatXToFloat64( 1652206917Smarius floatXDiv( float64ToFloatX( a ), float64ToFloatX( b ) ) ); 1653206917Smarius 1654206917Smarius} 1655206917Smarius 1656206917Smariusfloat64 slow_float64_rem( float64 a, float64 b ) 1657206917Smarius{ 1658206917Smarius 1659206917Smarius return 1660206917Smarius floatXToFloat64( 1661206917Smarius floatXRem( float64ToFloatX( a ), float64ToFloatX( b ) ) ); 1662206917Smarius 1663206917Smarius} 1664206917Smarius 1665206917Smariusfloat64 slow_float64_sqrt( float64 a ) 1666206917Smarius{ 1667206917Smarius 1668206917Smarius return floatXToFloat64( floatXSqrt( float64ToFloatX( a ) ) ); 1669206917Smarius 1670206917Smarius} 1671206917Smarius 1672206917Smariusflag slow_float64_eq( float64 a, float64 b ) 1673206917Smarius{ 1674206917Smarius 1675206917Smarius return floatXEq( float64ToFloatX( a ), float64ToFloatX( b ) ); 1676206917Smarius 1677206917Smarius} 1678206917Smarius 1679206917Smariusflag slow_float64_le( float64 a, float64 b ) 1680206917Smarius{ 1681206917Smarius floatX ax, bx; 1682206917Smarius 1683206917Smarius ax = float64ToFloatX( a ); 1684206917Smarius bx = float64ToFloatX( b ); 1685206917Smarius if ( ax.isNaN || bx.isNaN ) { 1686206917Smarius slow_float_exception_flags |= float_flag_invalid; 1687206917Smarius } 1688206917Smarius return floatXLe( ax, bx ); 1689206917Smarius 1690206917Smarius} 1691206917Smarius 1692206917Smariusflag slow_float64_lt( float64 a, float64 b ) 1693206917Smarius{ 1694206917Smarius floatX ax, bx; 1695206917Smarius 1696206917Smarius ax = float64ToFloatX( a ); 1697206917Smarius bx = float64ToFloatX( b ); 1698206917Smarius if ( ax.isNaN || bx.isNaN ) { 1699206917Smarius slow_float_exception_flags |= float_flag_invalid; 1700206917Smarius } 1701206917Smarius return floatXLt( ax, bx ); 1702206917Smarius 1703206917Smarius} 1704206917Smarius 1705206917Smariusflag slow_float64_eq_signaling( float64 a, float64 b ) 1706206917Smarius{ 1707206917Smarius floatX ax, bx; 1708206917Smarius 1709206917Smarius ax = float64ToFloatX( a ); 1710206917Smarius bx = float64ToFloatX( b ); 1711206917Smarius if ( ax.isNaN || bx.isNaN ) { 1712206917Smarius slow_float_exception_flags |= float_flag_invalid; 1713206917Smarius } 1714206917Smarius return floatXEq( ax, bx ); 1715206917Smarius 1716206917Smarius} 1717206917Smarius 1718206917Smariusflag slow_float64_le_quiet( float64 a, float64 b ) 1719206917Smarius{ 1720206917Smarius 1721206917Smarius return floatXLe( float64ToFloatX( a ), float64ToFloatX( b ) ); 1722206917Smarius 1723206917Smarius} 1724206917Smarius 1725206917Smariusflag slow_float64_lt_quiet( float64 a, float64 b ) 1726206917Smarius{ 1727206917Smarius 1728206917Smarius return floatXLt( float64ToFloatX( a ), float64ToFloatX( b ) ); 1729206917Smarius 1730206917Smarius} 1731206917Smarius 1732206917Smarius#ifdef FLOATX80 1733206917Smarius 1734206917Smariusint32 slow_floatx80_to_int32( floatx80 a ) 1735206917Smarius{ 1736206917Smarius 1737206917Smarius return floatXToInt32( floatx80ToFloatX( a ) ); 1738206917Smarius 1739206917Smarius} 1740206917Smarius 1741206917Smariusint32 slow_floatx80_to_int32_round_to_zero( floatx80 a ) 1742206917Smarius{ 1743206917Smarius int8 savedRoundingMode; 1744206917Smarius int32 z; 1745206917Smarius 1746206917Smarius savedRoundingMode = slow_float_rounding_mode; 1747206917Smarius slow_float_rounding_mode = float_round_to_zero; 1748206917Smarius z = floatXToInt32( floatx80ToFloatX( a ) ); 1749206917Smarius slow_float_rounding_mode = savedRoundingMode; 1750206917Smarius return z; 1751206917Smarius 1752206917Smarius} 1753206917Smarius 1754206917Smariusint64 slow_floatx80_to_int64( floatx80 a ) 1755206917Smarius{ 1756206917Smarius 1757206917Smarius return floatXToInt64( floatx80ToFloatX( a ) ); 1758206917Smarius 1759206917Smarius} 1760206917Smarius 1761206917Smariusint64 slow_floatx80_to_int64_round_to_zero( floatx80 a ) 1762206917Smarius{ 1763206917Smarius int8 savedRoundingMode; 1764206917Smarius int64 z; 1765206917Smarius 1766206917Smarius savedRoundingMode = slow_float_rounding_mode; 1767206917Smarius slow_float_rounding_mode = float_round_to_zero; 1768206917Smarius z = floatXToInt64( floatx80ToFloatX( a ) ); 1769206917Smarius slow_float_rounding_mode = savedRoundingMode; 1770206917Smarius return z; 1771206917Smarius 1772206917Smarius} 1773206917Smarius 1774206917Smariusfloat32 slow_floatx80_to_float32( floatx80 a ) 1775206917Smarius{ 1776206917Smarius 1777206917Smarius return floatXToFloat32( floatx80ToFloatX( a ) ); 1778206917Smarius 1779206917Smarius} 1780206917Smarius 1781206917Smariusfloat64 slow_floatx80_to_float64( floatx80 a ) 1782206917Smarius{ 1783206917Smarius 1784206917Smarius return floatXToFloat64( floatx80ToFloatX( a ) ); 1785206917Smarius 1786206917Smarius} 1787206917Smarius 1788206917Smarius#ifdef FLOAT128 1789206917Smarius 1790206917Smariusfloat128 slow_floatx80_to_float128( floatx80 a ) 1791206917Smarius{ 1792206917Smarius 1793206917Smarius return floatXToFloat128( floatx80ToFloatX( a ) ); 1794206917Smarius 1795206917Smarius} 1796206917Smarius 1797206917Smarius#endif 1798206917Smarius 1799206917Smariusfloatx80 slow_floatx80_round_to_int( floatx80 a ) 1800206917Smarius{ 1801206917Smarius 1802206917Smarius return floatXToFloatx80( floatXRoundToInt( floatx80ToFloatX( a ) ) ); 1803206917Smarius 1804206917Smarius} 1805206917Smarius 1806206917Smariusfloatx80 slow_floatx80_add( floatx80 a, floatx80 b ) 1807206917Smarius{ 1808206917Smarius 1809206917Smarius return 1810206917Smarius floatXToFloatx80( 1811206917Smarius floatXAdd( floatx80ToFloatX( a ), floatx80ToFloatX( b ) ) ); 1812206917Smarius 1813206917Smarius} 1814206917Smarius 1815206917Smariusfloatx80 slow_floatx80_sub( floatx80 a, floatx80 b ) 1816206917Smarius{ 1817206917Smarius 1818206917Smarius b.high ^= 0x8000; 1819206917Smarius return 1820206917Smarius floatXToFloatx80( 1821206917Smarius floatXAdd( floatx80ToFloatX( a ), floatx80ToFloatX( b ) ) ); 1822206917Smarius 1823206917Smarius} 1824206917Smarius 1825206917Smariusfloatx80 slow_floatx80_mul( floatx80 a, floatx80 b ) 1826206917Smarius{ 1827206917Smarius 1828206917Smarius return 1829206917Smarius floatXToFloatx80( 1830206917Smarius floatXMul( floatx80ToFloatX( a ), floatx80ToFloatX( b ) ) ); 1831206917Smarius 1832206917Smarius} 1833206917Smarius 1834206917Smariusfloatx80 slow_floatx80_div( floatx80 a, floatx80 b ) 1835206917Smarius{ 1836206917Smarius 1837206917Smarius return 1838206917Smarius floatXToFloatx80( 1839206917Smarius floatXDiv( floatx80ToFloatX( a ), floatx80ToFloatX( b ) ) ); 1840206917Smarius 1841206917Smarius} 1842206917Smarius 1843206917Smariusfloatx80 slow_floatx80_rem( floatx80 a, floatx80 b ) 1844206917Smarius{ 1845206917Smarius 1846206917Smarius return 1847206917Smarius floatXToFloatx80( 1848206917Smarius floatXRem( floatx80ToFloatX( a ), floatx80ToFloatX( b ) ) ); 1849206917Smarius 1850206917Smarius} 1851206917Smarius 1852206917Smariusfloatx80 slow_floatx80_sqrt( floatx80 a ) 1853206917Smarius{ 1854206917Smarius 1855206917Smarius return floatXToFloatx80( floatXSqrt( floatx80ToFloatX( a ) ) ); 1856206917Smarius 1857206917Smarius} 1858206917Smarius 1859206917Smariusflag slow_floatx80_eq( floatx80 a, floatx80 b ) 1860206917Smarius{ 1861206917Smarius 1862206917Smarius return floatXEq( floatx80ToFloatX( a ), floatx80ToFloatX( b ) ); 1863206917Smarius 1864206917Smarius} 1865206917Smarius 1866206917Smariusflag slow_floatx80_le( floatx80 a, floatx80 b ) 1867206917Smarius{ 1868206917Smarius floatX ax, bx; 1869206917Smarius 1870206917Smarius ax = floatx80ToFloatX( a ); 1871206917Smarius bx = floatx80ToFloatX( b ); 1872206917Smarius if ( ax.isNaN || bx.isNaN ) { 1873206917Smarius slow_float_exception_flags |= float_flag_invalid; 1874206917Smarius } 1875206917Smarius return floatXLe( ax, bx ); 1876206917Smarius 1877206917Smarius} 1878206917Smarius 1879206917Smariusflag slow_floatx80_lt( floatx80 a, floatx80 b ) 1880206917Smarius{ 1881206917Smarius floatX ax, bx; 1882206917Smarius 1883206917Smarius ax = floatx80ToFloatX( a ); 1884206917Smarius bx = floatx80ToFloatX( b ); 1885206917Smarius if ( ax.isNaN || bx.isNaN ) { 1886206917Smarius slow_float_exception_flags |= float_flag_invalid; 1887206917Smarius } 1888206917Smarius return floatXLt( ax, bx ); 1889206917Smarius 1890206917Smarius} 1891206917Smarius 1892206917Smariusflag slow_floatx80_eq_signaling( floatx80 a, floatx80 b ) 1893206917Smarius{ 1894206917Smarius floatX ax, bx; 1895206917Smarius 1896206917Smarius ax = floatx80ToFloatX( a ); 1897206917Smarius bx = floatx80ToFloatX( b ); 1898206917Smarius if ( ax.isNaN || bx.isNaN ) { 1899206917Smarius slow_float_exception_flags |= float_flag_invalid; 1900206917Smarius } 1901206917Smarius return floatXEq( ax, bx ); 1902206917Smarius 1903206917Smarius} 1904206917Smarius 1905206917Smariusflag slow_floatx80_le_quiet( floatx80 a, floatx80 b ) 1906206917Smarius{ 1907206917Smarius 1908206917Smarius return floatXLe( floatx80ToFloatX( a ), floatx80ToFloatX( b ) ); 1909206917Smarius 1910206917Smarius} 1911206917Smarius 1912206917Smariusflag slow_floatx80_lt_quiet( floatx80 a, floatx80 b ) 1913206917Smarius{ 1914206917Smarius 1915206917Smarius return floatXLt( floatx80ToFloatX( a ), floatx80ToFloatX( b ) ); 1916206917Smarius 1917206917Smarius} 1918206917Smarius 1919206917Smarius#endif 1920206917Smarius 1921206917Smarius#ifdef FLOAT128 1922206917Smarius 1923206917Smariusint32 slow_float128_to_int32( float128 a ) 1924206917Smarius{ 1925206917Smarius 1926206917Smarius return floatXToInt32( float128ToFloatX( a ) ); 1927206917Smarius 1928206917Smarius} 1929206917Smarius 1930206917Smariusint32 slow_float128_to_int32_round_to_zero( float128 a ) 1931206917Smarius{ 1932206917Smarius int8 savedRoundingMode; 1933206917Smarius int32 z; 1934206917Smarius 1935206917Smarius savedRoundingMode = slow_float_rounding_mode; 1936206917Smarius slow_float_rounding_mode = float_round_to_zero; 1937206917Smarius z = floatXToInt32( float128ToFloatX( a ) ); 1938206917Smarius slow_float_rounding_mode = savedRoundingMode; 1939206917Smarius return z; 1940206917Smarius 1941206917Smarius} 1942206917Smarius 1943206917Smariusint64 slow_float128_to_int64( float128 a ) 1944206917Smarius{ 1945206917Smarius 1946206917Smarius return floatXToInt64( float128ToFloatX( a ) ); 1947206917Smarius 1948206917Smarius} 1949206917Smarius 1950206917Smariusint64 slow_float128_to_int64_round_to_zero( float128 a ) 1951206917Smarius{ 1952206917Smarius int8 savedRoundingMode; 1953206917Smarius int64 z; 1954206917Smarius 1955206917Smarius savedRoundingMode = slow_float_rounding_mode; 1956206917Smarius slow_float_rounding_mode = float_round_to_zero; 1957206917Smarius z = floatXToInt64( float128ToFloatX( a ) ); 1958206917Smarius slow_float_rounding_mode = savedRoundingMode; 1959206917Smarius return z; 1960206917Smarius 1961206917Smarius} 1962206917Smarius 1963206917Smariusfloat32 slow_float128_to_float32( float128 a ) 1964206917Smarius{ 1965206917Smarius 1966206917Smarius return floatXToFloat32( float128ToFloatX( a ) ); 1967206917Smarius 1968206917Smarius} 1969206917Smarius 1970206917Smariusfloat64 slow_float128_to_float64( float128 a ) 1971206917Smarius{ 1972206917Smarius 1973206917Smarius return floatXToFloat64( float128ToFloatX( a ) ); 1974206917Smarius 1975206917Smarius} 1976206917Smarius 1977206917Smarius#ifdef FLOATX80 1978206917Smarius 1979206917Smariusfloatx80 slow_float128_to_floatx80( float128 a ) 1980206917Smarius{ 1981206917Smarius 1982206917Smarius return floatXToFloatx80( float128ToFloatX( a ) ); 1983206917Smarius 1984206917Smarius} 1985206917Smarius 1986206917Smarius#endif 1987206917Smarius 1988206917Smariusfloat128 slow_float128_round_to_int( float128 a ) 1989206917Smarius{ 1990206917Smarius 1991206917Smarius return floatXToFloat128( floatXRoundToInt( float128ToFloatX( a ) ) ); 1992206917Smarius 1993206917Smarius} 1994206917Smarius 1995206917Smariusfloat128 slow_float128_add( float128 a, float128 b ) 1996206917Smarius{ 1997206917Smarius 1998206917Smarius return 1999206917Smarius floatXToFloat128( 2000206917Smarius floatXAdd( float128ToFloatX( a ), float128ToFloatX( b ) ) ); 2001206917Smarius 2002206917Smarius} 2003206917Smarius 2004206917Smariusfloat128 slow_float128_sub( float128 a, float128 b ) 2005206917Smarius{ 2006206917Smarius 2007206917Smarius b.high ^= LIT64( 0x8000000000000000 ); 2008206917Smarius return 2009206917Smarius floatXToFloat128( 2010206917Smarius floatXAdd( float128ToFloatX( a ), float128ToFloatX( b ) ) ); 2011206917Smarius 2012206917Smarius} 2013206917Smarius 2014206917Smariusfloat128 slow_float128_mul( float128 a, float128 b ) 2015206917Smarius{ 2016206917Smarius 2017206917Smarius return 2018206917Smarius floatXToFloat128( 2019206917Smarius floatXMul( float128ToFloatX( a ), float128ToFloatX( b ) ) ); 2020206917Smarius 2021206917Smarius} 2022206917Smarius 2023206917Smariusfloat128 slow_float128_div( float128 a, float128 b ) 2024206917Smarius{ 2025206917Smarius 2026206917Smarius return 2027206917Smarius floatXToFloat128( 2028206917Smarius floatXDiv( float128ToFloatX( a ), float128ToFloatX( b ) ) ); 2029206917Smarius 2030206917Smarius} 2031206917Smarius 2032206917Smariusfloat128 slow_float128_rem( float128 a, float128 b ) 2033206917Smarius{ 2034206917Smarius 2035206917Smarius return 2036206917Smarius floatXToFloat128( 2037206917Smarius floatXRem( float128ToFloatX( a ), float128ToFloatX( b ) ) ); 2038206917Smarius 2039206917Smarius} 2040206917Smarius 2041206917Smariusfloat128 slow_float128_sqrt( float128 a ) 2042206917Smarius{ 2043206917Smarius 2044206917Smarius return floatXToFloat128( floatXSqrt( float128ToFloatX( a ) ) ); 2045206917Smarius 2046206917Smarius} 2047206917Smarius 2048206917Smariusflag slow_float128_eq( float128 a, float128 b ) 2049206917Smarius{ 2050206917Smarius 2051206917Smarius return floatXEq( float128ToFloatX( a ), float128ToFloatX( b ) ); 2052206917Smarius 2053206917Smarius} 2054206917Smarius 2055206917Smariusflag slow_float128_le( float128 a, float128 b ) 2056206917Smarius{ 2057206917Smarius floatX ax, bx; 2058206917Smarius 2059206917Smarius ax = float128ToFloatX( a ); 2060206917Smarius bx = float128ToFloatX( b ); 2061206917Smarius if ( ax.isNaN || bx.isNaN ) { 2062206917Smarius slow_float_exception_flags |= float_flag_invalid; 2063206917Smarius } 2064206917Smarius return floatXLe( ax, bx ); 2065206917Smarius 2066206917Smarius} 2067206917Smarius 2068206917Smariusflag slow_float128_lt( float128 a, float128 b ) 2069206917Smarius{ 2070206917Smarius floatX ax, bx; 2071206917Smarius 2072206917Smarius ax = float128ToFloatX( a ); 2073206917Smarius bx = float128ToFloatX( b ); 2074206917Smarius if ( ax.isNaN || bx.isNaN ) { 2075206917Smarius slow_float_exception_flags |= float_flag_invalid; 2076206917Smarius } 2077206917Smarius return floatXLt( ax, bx ); 2078206917Smarius 2079206917Smarius} 2080206917Smarius 2081206917Smariusflag slow_float128_eq_signaling( float128 a, float128 b ) 2082206917Smarius{ 2083206917Smarius floatX ax, bx; 2084206917Smarius 2085206917Smarius ax = float128ToFloatX( a ); 2086206917Smarius bx = float128ToFloatX( b ); 2087206917Smarius if ( ax.isNaN || bx.isNaN ) { 2088206917Smarius slow_float_exception_flags |= float_flag_invalid; 2089206917Smarius } 2090206917Smarius return floatXEq( ax, bx ); 2091206917Smarius 2092206917Smarius} 2093206917Smarius 2094206917Smariusflag slow_float128_le_quiet( float128 a, float128 b ) 2095206917Smarius{ 2096206917Smarius 2097206917Smarius return floatXLe( float128ToFloatX( a ), float128ToFloatX( b ) ); 2098206917Smarius 2099206917Smarius} 2100206917Smarius 2101206917Smariusflag slow_float128_lt_quiet( float128 a, float128 b ) 2102206917Smarius{ 2103206917Smarius 2104206917Smarius return floatXLt( float128ToFloatX( a ), float128ToFloatX( b ) ); 2105206917Smarius 2106206917Smarius} 2107206917Smarius 2108206917Smarius#endif 2109206917Smarius 2110