3 ===============================================================================
5 This C source file is part of TestFloat, Release 2a, a package of programs
6 for testing the correctness of floating-point arithmetic complying to the
7 IEC/IEEE Standard for Floating-Point.
9 Written by John R. Hauser. More information is available through the Web
10 page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'.
12 THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
13 has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
14 TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
15 PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
16 AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
18 Derivative works are acceptable, even for commercial purposes, so long as
19 (1) they include prominent notice that the work is derivative, and (2) they
20 include prominent notice akin to these four paragraphs for those parts of
21 this code that are retained.
23 ===============================================================================
26 int8 slow_float_rounding_mode;
27 int8 slow_float_exception_flags;
28 int8 slow_float_detect_tininess;
43 static const floatX floatXNaN = { TRUE, FALSE, FALSE, FALSE, 0, { 0, 0 } };
44 static const floatX floatXPositiveZero =
45 { FALSE, FALSE, TRUE, FALSE, 0, { 0, 0 } };
46 static const floatX floatXNegativeZero =
47 { FALSE, FALSE, TRUE, TRUE, 0, { 0, 0 } };
49 static bits64X shortShift64Left( bits64X a, int8 shiftCount )
53 negShiftCount = ( - shiftCount & 31 );
54 a.a0 = ( a.a0<<shiftCount ) | ( a.a1>>negShiftCount );
60 static bits64X shortShift64RightJamming( bits64X a, int8 shiftCount )
65 negShiftCount = ( - shiftCount & 31 );
66 extra = a.a1<<negShiftCount;
67 a.a1 = ( a.a0<<negShiftCount ) | ( a.a1>>shiftCount ) | ( extra != 0 );
73 static bits64X neg64( bits64X a )
87 static bits64X add64( bits64X a, bits64X b )
91 a.a0 += b.a0 + ( a.a1 < b.a1 );
96 static flag eq64( bits64X a, bits64X b )
99 return ( a.a0 == b.a0 ) && ( a.a1 == b.a1 );
103 static flag le64( bits64X a, bits64X b )
106 return ( a.a0 < b.a0 ) || ( ( a.a0 == b.a0 ) && ( a.a1 <= b.a1 ) );
110 static flag lt64( bits64X a, bits64X b )
113 return ( a.a0 < b.a0 ) || ( ( a.a0 == b.a0 ) && ( a.a1 < b.a1 ) );
117 static floatX roundFloatXTo24( flag isTiny, floatX zx )
121 slow_float_exception_flags |= float_flag_inexact;
122 if ( isTiny ) slow_float_exception_flags |= float_flag_underflow;
123 switch ( slow_float_rounding_mode ) {
124 case float_round_nearest_even:
125 if ( zx.sig.a1 < 0x80000000 ) goto noIncrement;
126 if ( ( zx.sig.a1 == 0x80000000 ) && ! ( zx.sig.a0 & 1 ) ) {
130 case float_round_to_zero:
132 case float_round_down:
133 if ( ! zx.sign ) goto noIncrement;
136 if ( zx.sign ) goto noIncrement;
140 if ( zx.sig.a0 == 0x01000000 ) {
141 zx.sig.a0 = 0x00800000;
151 static floatX roundFloatXTo53( flag isTiny, floatX zx )
155 roundBits = zx.sig.a1 & 7;
156 zx.sig.a1 -= roundBits;
158 slow_float_exception_flags |= float_flag_inexact;
159 if ( isTiny ) slow_float_exception_flags |= float_flag_underflow;
160 switch ( slow_float_rounding_mode ) {
161 case float_round_nearest_even:
162 if ( roundBits < 4 ) goto noIncrement;
163 if ( ( roundBits == 4 ) && ! ( zx.sig.a1 & 8 ) ) goto noIncrement;
165 case float_round_to_zero:
167 case float_round_down:
168 if ( ! zx.sign ) goto noIncrement;
171 if ( zx.sign ) goto noIncrement;
175 zx.sig.a0 += ( zx.sig.a1 == 0 );
176 if ( zx.sig.a0 == 0x01000000 ) {
177 zx.sig.a0 = 0x00800000;
186 static floatX int32ToFloatX( int32 a )
193 ax.sig.a1 = ax.sign ? - a : a;
200 ax.sig = shortShift64Left( ax.sig, 23 );
202 while ( ax.sig.a0 < 0x00800000 ) {
203 ax.sig = shortShift64Left( ax.sig, 1 );
210 static int32 floatXToInt32( floatX ax )
212 int8 savedExceptionFlags;
216 if ( ax.isInf || ax.isNaN ) {
217 slow_float_exception_flags |= float_flag_invalid;
218 return ( ax.isInf & ax.sign ) ? 0x80000000 : 0x7FFFFFFF;
220 if ( ax.isZero ) return 0;
221 savedExceptionFlags = slow_float_exception_flags;
222 shiftCount = 52 - ax.exp;
223 if ( 56 < shiftCount ) {
228 while ( 0 < shiftCount ) {
229 ax.sig = shortShift64RightJamming( ax.sig, 1 );
233 ax = roundFloatXTo53( FALSE, ax );
234 ax.sig = shortShift64RightJamming( ax.sig, 3 );
236 if ( ax.sign ) z = - z;
237 if ( ( shiftCount < 0 )
239 || ( ( z != 0 ) && ( ( ax.sign ^ ( z < 0 ) ) != 0 ) )
241 slow_float_exception_flags = savedExceptionFlags | float_flag_invalid;
242 return ax.sign ? 0x80000000 : 0x7FFFFFFF;
248 static floatX float32ToFloatX( float32 a )
256 ax.sign = ( ( a & 0x80000000 ) != 0 );
257 expField = ( a>>23 ) & 0xFF;
259 ax.sig.a0 = a & 0x007FFFFF;
260 if ( expField == 0 ) {
261 if ( ax.sig.a0 == 0 ) {
269 } while ( ax.sig.a0 < 0x00800000 );
273 else if ( expField == 0xFF ) {
274 if ( ax.sig.a0 == 0 ) {
282 ax.sig.a0 |= 0x00800000;
283 ax.exp = expField - 0x7F;
289 static float32 floatXToFloat32( floatX zx )
296 if ( zx.isZero ) return zx.sign ? 0x80000000 : 0;
297 if ( zx.isInf ) return zx.sign ? 0xFF800000 : 0x7F800000;
298 if ( zx.isNaN ) return 0xFFFFFFFF;
299 while ( 0x01000000 <= zx.sig.a0 ) {
300 zx.sig = shortShift64RightJamming( zx.sig, 1 );
303 while ( zx.sig.a0 < 0x00800000 ) {
304 zx.sig = shortShift64Left( zx.sig, 1 );
309 ( slow_float_detect_tininess == float_tininess_before_rounding )
310 && ( zx.exp + 0x7F <= 0 );
311 zx = roundFloatXTo24( isTiny, zx );
312 expField = zx.exp + 0x7F;
313 if ( 0xFF <= expField ) {
314 slow_float_exception_flags |=
315 float_flag_overflow | float_flag_inexact;
317 switch ( slow_float_rounding_mode ) {
318 case float_round_nearest_even:
319 case float_round_down:
322 case float_round_to_zero:
329 switch ( slow_float_rounding_mode ) {
330 case float_round_nearest_even:
334 case float_round_to_zero:
335 case float_round_down:
342 if ( expField <= 0 ) {
345 expField = zx.exp + 0x7F;
346 if ( expField < -27 ) {
347 zx.sig.a1 = ( zx.sig.a0 != 0 ) || ( zx.sig.a1 != 0 );
351 while ( expField <= 0 ) {
352 zx.sig = shortShift64RightJamming( zx.sig, 1 );
356 zx = roundFloatXTo24( isTiny, zx );
357 expField = ( 0x00800000 <= zx.sig.a0 ) ? 1 : 0;
361 if ( zx.sign ) z |= 0x80000000;
362 z |= zx.sig.a0 & 0x007FFFFF;
367 static floatX float64ToFloatX( float64 a )
376 ax.sign = ( ( a & LIT64( 0x8000000000000000 ) ) != 0 );
377 expField = ( a>>52 ) & 0x7FF;
379 ax.sig.a0 = ( a>>32 ) & 0x000FFFFF;
381 ax.sign = ( ( a.high & 0x80000000 ) != 0 );
382 expField = ( a.high>>( 52 - 32 ) ) & 0x7FF;
384 ax.sig.a0 = a.high & 0x000FFFFF;
386 if ( expField == 0 ) {
387 if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) {
391 expField = 1 - 0x3FF;
393 ax.sig = shortShift64Left( ax.sig, 1 );
395 } while ( ax.sig.a0 < 0x00100000 );
399 else if ( expField == 0x7FF ) {
400 if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) {
408 ax.exp = expField - 0x3FF;
409 ax.sig.a0 |= 0x00100000;
411 ax.sig = shortShift64Left( ax.sig, 3 );
416 static float64 floatXToFloat64( floatX zx )
424 if ( zx.isZero ) return zx.sign ? LIT64( 0x8000000000000000 ) : 0;
427 zx.sign ? LIT64( 0xFFF0000000000000 )
428 : LIT64( 0x7FF0000000000000 );
430 if ( zx.isNaN ) return LIT64( 0xFFFFFFFFFFFFFFFF );
434 z.high = zx.sign ? 0x80000000 : 0;
439 z.high = zx.sign ? 0xFFF00000 : 0x7FF00000;
443 z.high = z.low = 0xFFFFFFFF;
447 while ( 0x01000000 <= zx.sig.a0 ) {
448 zx.sig = shortShift64RightJamming( zx.sig, 1 );
451 while ( zx.sig.a0 < 0x00800000 ) {
452 zx.sig = shortShift64Left( zx.sig, 1 );
457 ( slow_float_detect_tininess == float_tininess_before_rounding )
458 && ( zx.exp + 0x3FF <= 0 );
459 zx = roundFloatXTo53( isTiny, zx );
460 expField = zx.exp + 0x3FF;
461 if ( 0x7FF <= expField ) {
462 slow_float_exception_flags |=
463 float_flag_overflow | float_flag_inexact;
466 switch ( slow_float_rounding_mode ) {
467 case float_round_nearest_even:
468 case float_round_down:
469 z = LIT64( 0xFFF0000000000000 );
471 case float_round_to_zero:
473 z = LIT64( 0xFFEFFFFFFFFFFFFF );
478 switch ( slow_float_rounding_mode ) {
479 case float_round_nearest_even:
481 z = LIT64( 0x7FF0000000000000 );
483 case float_round_to_zero:
484 case float_round_down:
485 z = LIT64( 0x7FEFFFFFFFFFFFFF );
491 switch ( slow_float_rounding_mode ) {
492 case float_round_nearest_even:
493 case float_round_down:
497 case float_round_to_zero:
505 switch ( slow_float_rounding_mode ) {
506 case float_round_nearest_even:
511 case float_round_to_zero:
512 case float_round_down:
521 if ( expField <= 0 ) {
524 expField = zx.exp + 0x3FF;
525 if ( expField < -56 ) {
526 zx.sig.a1 = ( zx.sig.a0 != 0 ) || ( zx.sig.a1 != 0 );
530 while ( expField <= 0 ) {
531 zx.sig = shortShift64RightJamming( zx.sig, 1 );
535 zx = roundFloatXTo53( isTiny, zx );
536 expField = ( 0x00800000 <= zx.sig.a0 ) ? 1 : 0;
538 zx.sig = shortShift64RightJamming( zx.sig, 3 );
542 if ( zx.sign ) z |= LIT64( 0x8000000000000000 );
543 z |= ( ( (bits64) ( zx.sig.a0 & 0x000FFFFF ) )<<32 ) | zx.sig.a1;
548 if ( zx.sign ) z.high |= 0x80000000;
549 z.high |= zx.sig.a0 & 0x000FFFFF;
555 static floatX floatXInvalid( void )
558 slow_float_exception_flags |= float_flag_invalid;
563 static floatX floatXRoundToInt( floatX ax )
567 if ( ax.isNaN || ax.isInf ) return ax;
568 shiftCount = 52 - ax.exp;
569 if ( shiftCount <= 0 ) return ax;
570 if ( 55 < shiftCount ) {
572 ax.sig.a1 = ! ax.isZero;
576 while ( 0 < shiftCount ) {
577 ax.sig = shortShift64RightJamming( ax.sig, 1 );
582 ax = roundFloatXTo53( FALSE, ax );
583 if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) ax.isZero = TRUE;
588 static floatX floatXAdd( floatX ax, floatX bx )
593 if ( ax.isNaN ) return ax;
594 if ( bx.isNaN ) return bx;
595 if ( ax.isInf && bx.isInf ) {
596 if ( ax.sign == bx.sign ) return ax;
597 return floatXInvalid();
599 if ( ax.isInf ) return ax;
600 if ( bx.isInf ) return bx;
601 if ( ax.isZero && bx.isZero ) {
602 if ( ax.sign == bx.sign ) return ax;
603 goto completeCancellation;
605 if ( ( ax.sign != bx.sign )
606 && ( ax.exp == bx.exp )
607 && eq64( ax.sig, bx.sig )
609 completeCancellation:
611 ( slow_float_rounding_mode == float_round_down ) ?
613 : floatXPositiveZero;
615 if ( ax.isZero ) return bx;
616 if ( bx.isZero ) return ax;
617 expDiff = ax.exp - bx.exp;
621 if ( expDiff < -56 ) {
626 while ( expDiff < 0 ) {
627 zx.sig = shortShift64RightJamming( zx.sig, 1 );
631 if ( ax.sign != bx.sign ) zx.sig = neg64( zx.sig );
633 zx.sig = add64( zx.sig, bx.sig );
638 if ( 56 < expDiff ) {
643 while ( 0 < expDiff ) {
644 zx.sig = shortShift64RightJamming( zx.sig, 1 );
648 if ( ax.sign != bx.sign ) zx.sig = neg64( zx.sig );
650 zx.sig = add64( zx.sig, ax.sig );
652 if ( zx.sig.a0 & 0x80000000 ) {
653 zx.sig = neg64( zx.sig );
660 static floatX floatXMul( floatX ax, floatX bx )
665 if ( ax.isNaN ) return ax;
666 if ( bx.isNaN ) return bx;
668 if ( bx.isZero ) return floatXInvalid();
669 if ( bx.sign ) ax.sign = ! ax.sign;
673 if ( ax.isZero ) return floatXInvalid();
674 if ( ax.sign ) bx.sign = ! bx.sign;
679 if ( ax.isZero || bx.isZero ) {
680 return zx.sign ? floatXNegativeZero : floatXPositiveZero;
682 zx.exp += bx.exp + 1;
685 for ( bitNum = 0; bitNum < 55; ++bitNum ) {
686 if ( bx.sig.a1 & 2 ) zx.sig = add64( zx.sig, ax.sig );
687 bx.sig = shortShift64RightJamming( bx.sig, 1 );
688 zx.sig = shortShift64RightJamming( zx.sig, 1 );
694 static floatX floatXDiv( floatX ax, floatX bx )
700 if ( ax.isNaN ) return ax;
701 if ( bx.isNaN ) return bx;
703 if ( bx.isInf ) return floatXInvalid();
704 if ( bx.sign ) ax.sign = ! ax.sign;
708 if ( ax.isZero ) return floatXInvalid();
709 slow_float_exception_flags |= float_flag_divbyzero;
710 if ( ax.sign ) bx.sign = ! bx.sign;
717 if ( ax.isZero || bx.isInf ) {
718 return zx.sign ? floatXNegativeZero : floatXPositiveZero;
720 zx.exp -= bx.exp + 1;
723 negBSig = neg64( bx.sig );
724 for ( bitNum = 0; bitNum < 56; ++bitNum ) {
725 if ( le64( bx.sig, ax.sig ) ) {
727 ax.sig = add64( ax.sig, negBSig );
729 ax.sig = shortShift64Left( ax.sig, 1 );
730 zx.sig = shortShift64Left( zx.sig, 1 );
732 if ( ax.sig.a0 || ax.sig.a1 ) zx.sig.a1 |= 1;
737 static floatX floatXRem( floatX ax, floatX bx )
740 flag lastQuotientBit;
743 if ( ax.isNaN ) return ax;
744 if ( bx.isNaN ) return bx;
745 if ( ax.isInf || bx.isZero ) return floatXInvalid();
746 if ( ax.isZero || bx.isInf ) return ax;
748 if ( ax.exp < bx.exp ) return ax;
749 bx.sig = shortShift64Left( bx.sig, 1 );
750 negBSig = neg64( bx.sig );
751 while ( bx.exp < ax.exp ) {
752 if ( le64( bx.sig, ax.sig ) ) ax.sig = add64( ax.sig, negBSig );
753 ax.sig = shortShift64Left( ax.sig, 1 );
756 lastQuotientBit = le64( bx.sig, ax.sig );
757 if ( lastQuotientBit ) ax.sig = add64( ax.sig, negBSig );
759 ax.sig = neg64( add64( ax.sig, negBSig ) );
760 if ( lt64( ax.sig, savedASig ) ) {
763 else if ( lt64( savedASig, ax.sig ) ) {
767 if ( lastQuotientBit ) {
774 if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) ax.isZero = TRUE;
779 static floatX floatXSqrt( floatX ax )
782 bits64X bitSig, savedASig;
785 if ( ax.isNaN || ax.isZero ) return ax;
786 if ( ax.sign ) return floatXInvalid();
787 if ( ax.isInf ) return ax;
790 if ( ( ax.exp & 1 ) == 0 ) ax.sig = shortShift64RightJamming( ax.sig, 1 );
794 bitSig.a0 = 0x00800000;
795 for ( bitNum = 0; bitNum < 56; ++bitNum ) {
797 ax.sig = add64( ax.sig, neg64( zx.sig ) );
798 ax.sig = shortShift64Left( ax.sig, 1 );
799 ax.sig = add64( ax.sig, neg64( bitSig ) );
800 if ( ax.sig.a0 & 0x80000000 ) {
801 ax.sig = shortShift64Left( savedASig, 1 );
804 zx.sig.a1 |= bitSig.a1;
805 zx.sig.a0 |= bitSig.a0;
807 bitSig = shortShift64RightJamming( bitSig, 1 );
809 if ( ax.sig.a0 || ax.sig.a1 ) zx.sig.a1 |= 1;
814 static flag floatXEq( floatX ax, floatX bx )
817 if ( ax.isNaN || bx.isNaN ) return FALSE;
818 if ( ax.isZero && bx.isZero ) return TRUE;
819 if ( ax.sign != bx.sign ) return FALSE;
820 if ( ax.isInf || bx.isInf ) return ax.isInf && bx.isInf;
821 return ( ax.exp == bx.exp ) && eq64( ax.sig, bx.sig );
825 static flag floatXLe( floatX ax, floatX bx )
828 if ( ax.isNaN || bx.isNaN ) return FALSE;
829 if ( ax.isZero && bx.isZero ) return TRUE;
830 if ( ax.sign != bx.sign ) return ax.sign;
832 if ( ax.isInf || bx.isZero ) return TRUE;
833 if ( bx.isInf || ax.isZero ) return FALSE;
834 if ( bx.exp < ax.exp ) return TRUE;
835 if ( ax.exp < bx.exp ) return FALSE;
836 return le64( bx.sig, ax.sig );
839 if ( bx.isInf || ax.isZero ) return TRUE;
840 if ( ax.isInf || bx.isZero ) return FALSE;
841 if ( ax.exp < bx.exp ) return TRUE;
842 if ( bx.exp < ax.exp ) return FALSE;
843 return le64( ax.sig, bx.sig );
848 static flag floatXLt( floatX ax, floatX bx )
851 if ( ax.isNaN || bx.isNaN ) return FALSE;
852 if ( ax.isZero && bx.isZero ) return FALSE;
853 if ( ax.sign != bx.sign ) return ax.sign;
854 if ( ax.isInf && bx.isInf ) return FALSE;
856 if ( ax.isInf || bx.isZero ) return TRUE;
857 if ( bx.isInf || ax.isZero ) return FALSE;
858 if ( bx.exp < ax.exp ) return TRUE;
859 if ( ax.exp < bx.exp ) return FALSE;
860 return lt64( bx.sig, ax.sig );
863 if ( bx.isInf || ax.isZero ) return TRUE;
864 if ( ax.isInf || bx.isZero ) return FALSE;
865 if ( ax.exp < bx.exp ) return TRUE;
866 if ( bx.exp < ax.exp ) return FALSE;
867 return lt64( ax.sig, bx.sig );
872 float32 slow_int32_to_float32( int32 a )
875 return floatXToFloat32( int32ToFloatX( a ) );
879 float64 slow_int32_to_float64( int32 a )
882 return floatXToFloat64( int32ToFloatX( a ) );
886 int32 slow_float32_to_int32( float32 a )
889 return floatXToInt32( float32ToFloatX( a ) );
893 int32 slow_float32_to_int32_round_to_zero( float32 a )
895 int8 savedRoundingMode;
898 savedRoundingMode = slow_float_rounding_mode;
899 slow_float_rounding_mode = float_round_to_zero;
900 z = floatXToInt32( float32ToFloatX( a ) );
901 slow_float_rounding_mode = savedRoundingMode;
906 float64 slow_float32_to_float64( float32 a )
909 return floatXToFloat64( float32ToFloatX( a ) );
913 float32 slow_float32_round_to_int( float32 a )
916 return floatXToFloat32( floatXRoundToInt( float32ToFloatX( a ) ) );
920 float32 slow_float32_add( float32 a, float32 b )
925 floatXAdd( float32ToFloatX( a ), float32ToFloatX( b ) ) );
929 float32 slow_float32_sub( float32 a, float32 b )
935 floatXAdd( float32ToFloatX( a ), float32ToFloatX( b ) ) );
939 float32 slow_float32_mul( float32 a, float32 b )
944 floatXMul( float32ToFloatX( a ), float32ToFloatX( b ) ) );
948 float32 slow_float32_div( float32 a, float32 b )
953 floatXDiv( float32ToFloatX( a ), float32ToFloatX( b ) ) );
957 float32 slow_float32_rem( float32 a, float32 b )
962 floatXRem( float32ToFloatX( a ), float32ToFloatX( b ) ) );
966 float32 slow_float32_sqrt( float32 a )
969 return floatXToFloat32( floatXSqrt( float32ToFloatX( a ) ) );
973 flag slow_float32_eq( float32 a, float32 b )
976 return floatXEq( float32ToFloatX( a ), float32ToFloatX( b ) );
980 flag slow_float32_le( float32 a, float32 b )
984 ax = float32ToFloatX( a );
985 bx = float32ToFloatX( b );
986 if ( ax.isNaN || bx.isNaN ) {
987 slow_float_exception_flags |= float_flag_invalid;
989 return floatXLe( ax, bx );
993 flag slow_float32_lt( float32 a, float32 b )
997 ax = float32ToFloatX( a );
998 bx = float32ToFloatX( b );
999 if ( ax.isNaN || bx.isNaN ) {
1000 slow_float_exception_flags |= float_flag_invalid;
1002 return floatXLt( ax, bx );
1006 flag slow_float32_eq_signaling( float32 a, float32 b )
1010 ax = float32ToFloatX( a );
1011 bx = float32ToFloatX( b );
1012 if ( ax.isNaN || bx.isNaN ) {
1013 slow_float_exception_flags |= float_flag_invalid;
1015 return floatXEq( ax, bx );
1019 flag slow_float32_le_quiet( float32 a, float32 b )
1022 return floatXLe( float32ToFloatX( a ), float32ToFloatX( b ) );
1026 flag slow_float32_lt_quiet( float32 a, float32 b )
1029 return floatXLt( float32ToFloatX( a ), float32ToFloatX( b ) );
1033 int32 slow_float64_to_int32( float64 a )
1036 return floatXToInt32( float64ToFloatX( a ) );
1040 int32 slow_float64_to_int32_round_to_zero( float64 a )
1042 int8 savedRoundingMode;
1045 savedRoundingMode = slow_float_rounding_mode;
1046 slow_float_rounding_mode = float_round_to_zero;
1047 z = floatXToInt32( float64ToFloatX( a ) );
1048 slow_float_rounding_mode = savedRoundingMode;
1053 float32 slow_float64_to_float32( float64 a )
1056 return floatXToFloat32( float64ToFloatX( a ) );
1060 float64 slow_float64_round_to_int( float64 a )
1063 return floatXToFloat64( floatXRoundToInt( float64ToFloatX( a ) ) );
1067 float64 slow_float64_add( float64 a, float64 b )
1072 floatXAdd( float64ToFloatX( a ), float64ToFloatX( b ) ) );
1076 float64 slow_float64_sub( float64 a, float64 b )
1080 b ^= LIT64( 0x8000000000000000 );
1082 b.high ^= 0x80000000;
1086 floatXAdd( float64ToFloatX( a ), float64ToFloatX( b ) ) );
1090 float64 slow_float64_mul( float64 a, float64 b )
1095 floatXMul( float64ToFloatX( a ), float64ToFloatX( b ) ) );
1099 float64 slow_float64_div( float64 a, float64 b )
1104 floatXDiv( float64ToFloatX( a ), float64ToFloatX( b ) ) );
1108 float64 slow_float64_rem( float64 a, float64 b )
1113 floatXRem( float64ToFloatX( a ), float64ToFloatX( b ) ) );
1117 float64 slow_float64_sqrt( float64 a )
1120 return floatXToFloat64( floatXSqrt( float64ToFloatX( a ) ) );
1124 flag slow_float64_eq( float64 a, float64 b )
1127 return floatXEq( float64ToFloatX( a ), float64ToFloatX( b ) );
1131 flag slow_float64_le( float64 a, float64 b )
1135 ax = float64ToFloatX( a );
1136 bx = float64ToFloatX( b );
1137 if ( ax.isNaN || bx.isNaN ) {
1138 slow_float_exception_flags |= float_flag_invalid;
1140 return floatXLe( ax, bx );
1144 flag slow_float64_lt( float64 a, float64 b )
1148 ax = float64ToFloatX( a );
1149 bx = float64ToFloatX( b );
1150 if ( ax.isNaN || bx.isNaN ) {
1151 slow_float_exception_flags |= float_flag_invalid;
1153 return floatXLt( ax, bx );
1157 flag slow_float64_eq_signaling( float64 a, float64 b )
1161 ax = float64ToFloatX( a );
1162 bx = float64ToFloatX( b );
1163 if ( ax.isNaN || bx.isNaN ) {
1164 slow_float_exception_flags |= float_flag_invalid;
1166 return floatXEq( ax, bx );
1170 flag slow_float64_le_quiet( float64 a, float64 b )
1173 return floatXLe( float64ToFloatX( a ), float64ToFloatX( b ) );
1177 flag slow_float64_lt_quiet( float64 a, float64 b )
1180 return floatXLt( float64ToFloatX( a ), float64ToFloatX( b ) );