diff options
41 files changed, 18426 insertions, 0 deletions
diff --git a/tools/test/README b/tools/test/README index f16e215..438c1f5 100644 --- a/tools/test/README +++ b/tools/test/README @@ -11,3 +11,4 @@ devrandom Programs to test /dev/*random. dtrace DTrace test suite malloc A program to test and benchmark malloc(). posixshm A program to test POSIX shared memory. +testfloat Programs to test floating-point implementations diff --git a/tools/test/testfloat/README.txt b/tools/test/testfloat/README.txt new file mode 100644 index 0000000..fe99fd9 --- /dev/null +++ b/tools/test/testfloat/README.txt @@ -0,0 +1,50 @@ + +Package Overview for TestFloat Release 2a + +John R. Hauser +1998 December 16 + + +TestFloat is a program for testing that a floating-point implementation +conforms to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +TestFloat is distributed in the form of C source code. The TestFloat +package actually provides two related programs: + +-- The `testfloat' program tests a system's floating-point for conformance + to the IEC/IEEE Standard. This program uses the SoftFloat software + floating-point implementation as a basis for comparison. + +-- The `testsoftfloat' program tests SoftFloat itself for conformance to + the IEC/IEEE Standard. These tests are performed by comparing against a + separate, slower software floating-point that is included in the TestFloat + package. + +TestFloat depends on SoftFloat, but SoftFloat is not included in the +TestFloat package. SoftFloat can be obtained through the Web page `http:// +HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/SoftFloat.html'. + +TestFloat is documented in three text files: + + testfloat.txt Documentation for using the TestFloat programs + (both `testfloat' and `testsoftfloat'). + testfloat-source.txt Documentation for porting and compiling TestFloat. + testfloat-history.txt History of major changes to TestFloat. + +The following file is also provided: + + systemBugs.txt Information about processor bugs found using + TestFloat. + +Other files in the package comprise the source code for TestFloat. + +Please be aware that some work is involved in porting this software to other +targets. It is not just a matter of getting `make' to complete without +error messages. I would have written the code that way if I could, but +there are fundamental differences between systems that I can't make go away. +You should not attempt to compile the TestFloat sources without first +reading `testfloat-source.txt'. + +At the time of this writing, the most up-to-date information about +TestFloat and the latest release can be found at the Web page `http:// +HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + diff --git a/tools/test/testfloat/fail.c b/tools/test/testfloat/fail.c new file mode 100644 index 0000000..30bbea6 --- /dev/null +++ b/tools/test/testfloat/fail.c @@ -0,0 +1,46 @@ + +/* +=============================================================================== + +This C source file is part of TestFloat, Release 2a, a package of programs +for testing the correctness of floating-point arithmetic complying to the +IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +#include <stdlib.h> +#include <stdarg.h> +#include <stdio.h> +#include "milieu.h" +#include "fail.h" + +char *fail_programName = ""; + +void fail( const char *message, ... ) +{ + va_list varArgs; + + fprintf( stderr, "%s: ", fail_programName ); + va_start( varArgs, message ); + vfprintf( stderr, message, varArgs ); + va_end( varArgs ); + fputs( ".\n", stderr ); + exit( EXIT_FAILURE ); + +} + diff --git a/tools/test/testfloat/fail.h b/tools/test/testfloat/fail.h new file mode 100644 index 0000000..9c338da --- /dev/null +++ b/tools/test/testfloat/fail.h @@ -0,0 +1,29 @@ + +/* +=============================================================================== + +This C header file is part of TestFloat, Release 2a, a package of programs +for testing the correctness of floating-point arithmetic complying to the +IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +extern char *fail_programName; + +void fail( const char *, ... ); + diff --git a/tools/test/testfloat/random.c b/tools/test/testfloat/random.c new file mode 100644 index 0000000..21326c1 --- /dev/null +++ b/tools/test/testfloat/random.c @@ -0,0 +1,63 @@ + +/* +=============================================================================== + +This C source file is part of TestFloat, Release 2a, a package of programs +for testing the correctness of floating-point arithmetic complying to the +IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stdlib.h> +#include "milieu.h" +#include "random.h" + +uint8 randomUint8( void ) +{ + + return (bits8) ( random()>>4 ); + +} + +uint16 randomUint16( void ) +{ + + return ( random() & 0x0000ffff ); + +} + +uint32 randomUint32( void ) +{ + + return ( ( (uint32) random()<<16) | ( (uint32) random() & 0x0000ffff) ); +} + +#ifdef BITS64 + +uint64 randomUint64( void ) +{ + + return ( ( (uint64) randomUint32() )<<32 ) | randomUint32(); + +} + +#endif + diff --git a/tools/test/testfloat/random.h b/tools/test/testfloat/random.h new file mode 100644 index 0000000..7375499 --- /dev/null +++ b/tools/test/testfloat/random.h @@ -0,0 +1,32 @@ + +/* +=============================================================================== + +This C header file is part of TestFloat, Release 2a, a package of programs +for testing the correctness of floating-point arithmetic complying to the +IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +uint8 randomUint8( void ); +uint16 randomUint16( void ); +uint32 randomUint32( void ); +#ifdef BITS64 +uint64 randomUint64( void ); +#endif + diff --git a/tools/test/testfloat/slowfloat-32.c b/tools/test/testfloat/slowfloat-32.c new file mode 100644 index 0000000..549654b --- /dev/null +++ b/tools/test/testfloat/slowfloat-32.c @@ -0,0 +1,1183 @@ + +/* +=============================================================================== + +This C source file is part of TestFloat, Release 2a, a package of programs +for testing the correctness of floating-point arithmetic complying to the +IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +int8 slow_float_rounding_mode; +int8 slow_float_exception_flags; +int8 slow_float_detect_tininess; + +typedef struct { + bits32 a0, a1; +} bits64X; + +typedef struct { + flag isNaN; + flag isInf; + flag isZero; + flag sign; + int16 exp; + bits64X sig; +} floatX; + +static const floatX floatXNaN = { TRUE, FALSE, FALSE, FALSE, 0, { 0, 0 } }; +static const floatX floatXPositiveZero = + { FALSE, FALSE, TRUE, FALSE, 0, { 0, 0 } }; +static const floatX floatXNegativeZero = + { FALSE, FALSE, TRUE, TRUE, 0, { 0, 0 } }; + +static bits64X shortShift64Left( bits64X a, int8 shiftCount ) +{ + int8 negShiftCount; + + negShiftCount = ( - shiftCount & 31 ); + a.a0 = ( a.a0<<shiftCount ) | ( a.a1>>negShiftCount ); + a.a1 <<= shiftCount; + return a; + +} + +static bits64X shortShift64RightJamming( bits64X a, int8 shiftCount ) +{ + int8 negShiftCount; + bits32 extra; + + negShiftCount = ( - shiftCount & 31 ); + extra = a.a1<<negShiftCount; + a.a1 = ( a.a0<<negShiftCount ) | ( a.a1>>shiftCount ) | ( extra != 0 ); + a.a0 >>= shiftCount; + return a; + +} + +static bits64X neg64( bits64X a ) +{ + + if ( a.a1 == 0 ) { + a.a0 = - a.a0; + } + else { + a.a1 = - a.a1; + a.a0 = ~ a.a0; + } + return a; + +} + +static bits64X add64( bits64X a, bits64X b ) +{ + + a.a1 += b.a1; + a.a0 += b.a0 + ( a.a1 < b.a1 ); + return a; + +} + +static flag eq64( bits64X a, bits64X b ) +{ + + return ( a.a0 == b.a0 ) && ( a.a1 == b.a1 ); + +} + +static flag le64( bits64X a, bits64X b ) +{ + + return ( a.a0 < b.a0 ) || ( ( a.a0 == b.a0 ) && ( a.a1 <= b.a1 ) ); + +} + +static flag lt64( bits64X a, bits64X b ) +{ + + return ( a.a0 < b.a0 ) || ( ( a.a0 == b.a0 ) && ( a.a1 < b.a1 ) ); + +} + +static floatX roundFloatXTo24( flag isTiny, floatX zx ) +{ + + if ( zx.sig.a1 ) { + slow_float_exception_flags |= float_flag_inexact; + if ( isTiny ) slow_float_exception_flags |= float_flag_underflow; + switch ( slow_float_rounding_mode ) { + case float_round_nearest_even: + if ( zx.sig.a1 < 0x80000000 ) goto noIncrement; + if ( ( zx.sig.a1 == 0x80000000 ) && ! ( zx.sig.a0 & 1 ) ) { + goto noIncrement; + } + break; + case float_round_to_zero: + goto noIncrement; + case float_round_down: + if ( ! zx.sign ) goto noIncrement; + break; + case float_round_up: + if ( zx.sign ) goto noIncrement; + break; + } + ++zx.sig.a0; + if ( zx.sig.a0 == 0x01000000 ) { + zx.sig.a0 = 0x00800000; + ++zx.exp; + } + } + noIncrement: + zx.sig.a1 = 0; + return zx; + +} + +static floatX roundFloatXTo53( flag isTiny, floatX zx ) +{ + int8 roundBits; + + roundBits = zx.sig.a1 & 7; + zx.sig.a1 -= roundBits; + if ( roundBits ) { + slow_float_exception_flags |= float_flag_inexact; + if ( isTiny ) slow_float_exception_flags |= float_flag_underflow; + switch ( slow_float_rounding_mode ) { + case float_round_nearest_even: + if ( roundBits < 4 ) goto noIncrement; + if ( ( roundBits == 4 ) && ! ( zx.sig.a1 & 8 ) ) goto noIncrement; + break; + case float_round_to_zero: + goto noIncrement; + case float_round_down: + if ( ! zx.sign ) goto noIncrement; + break; + case float_round_up: + if ( zx.sign ) goto noIncrement; + break; + } + zx.sig.a1 += 8; + zx.sig.a0 += ( zx.sig.a1 == 0 ); + if ( zx.sig.a0 == 0x01000000 ) { + zx.sig.a0 = 0x00800000; + ++zx.exp; + } + } + noIncrement: + return zx; + +} + +static floatX int32ToFloatX( int32 a ) +{ + floatX ax; + + ax.isNaN = FALSE; + ax.isInf = FALSE; + ax.sign = ( a < 0 ); + ax.sig.a1 = ax.sign ? - a : a; + ax.sig.a0 = 0; + if ( a == 0 ) { + ax.isZero = TRUE; + return ax; + } + ax.isZero = FALSE; + ax.sig = shortShift64Left( ax.sig, 23 ); + ax.exp = 32; + while ( ax.sig.a0 < 0x00800000 ) { + ax.sig = shortShift64Left( ax.sig, 1 ); + --ax.exp; + } + return ax; + +} + +static int32 floatXToInt32( floatX ax ) +{ + int8 savedExceptionFlags; + int16 shiftCount; + int32 z; + + if ( ax.isInf || ax.isNaN ) { + slow_float_exception_flags |= float_flag_invalid; + return ( ax.isInf & ax.sign ) ? 0x80000000 : 0x7FFFFFFF; + } + if ( ax.isZero ) return 0; + savedExceptionFlags = slow_float_exception_flags; + shiftCount = 52 - ax.exp; + if ( 56 < shiftCount ) { + ax.sig.a1 = 1; + ax.sig.a0 = 0; + } + else { + while ( 0 < shiftCount ) { + ax.sig = shortShift64RightJamming( ax.sig, 1 ); + --shiftCount; + } + } + ax = roundFloatXTo53( FALSE, ax ); + ax.sig = shortShift64RightJamming( ax.sig, 3 ); + z = ax.sig.a1; + if ( ax.sign ) z = - z; + if ( ( shiftCount < 0 ) + || ax.sig.a0 + || ( ( z != 0 ) && ( ( ax.sign ^ ( z < 0 ) ) != 0 ) ) + ) { + slow_float_exception_flags = savedExceptionFlags | float_flag_invalid; + return ax.sign ? 0x80000000 : 0x7FFFFFFF; + } + return z; + +} + +static floatX float32ToFloatX( float32 a ) +{ + int16 expField; + floatX ax; + + ax.isNaN = FALSE; + ax.isInf = FALSE; + ax.isZero = FALSE; + ax.sign = ( ( a & 0x80000000 ) != 0 ); + expField = ( a>>23 ) & 0xFF; + ax.sig.a1 = 0; + ax.sig.a0 = a & 0x007FFFFF; + if ( expField == 0 ) { + if ( ax.sig.a0 == 0 ) { + ax.isZero = TRUE; + } + else { + expField = 1 - 0x7F; + do { + ax.sig.a0 <<= 1; + --expField; + } while ( ax.sig.a0 < 0x00800000 ); + ax.exp = expField; + } + } + else if ( expField == 0xFF ) { + if ( ax.sig.a0 == 0 ) { + ax.isInf = TRUE; + } + else { + ax.isNaN = TRUE; + } + } + else { + ax.sig.a0 |= 0x00800000; + ax.exp = expField - 0x7F; + } + return ax; + +} + +static float32 floatXToFloat32( floatX zx ) +{ + floatX savedZ; + flag isTiny; + int16 expField; + float32 z; + + if ( zx.isZero ) return zx.sign ? 0x80000000 : 0; + if ( zx.isInf ) return zx.sign ? 0xFF800000 : 0x7F800000; + if ( zx.isNaN ) return 0xFFFFFFFF; + while ( 0x01000000 <= zx.sig.a0 ) { + zx.sig = shortShift64RightJamming( zx.sig, 1 ); + ++zx.exp; + } + while ( zx.sig.a0 < 0x00800000 ) { + zx.sig = shortShift64Left( zx.sig, 1 ); + --zx.exp; + } + savedZ = zx; + isTiny = + ( slow_float_detect_tininess == float_tininess_before_rounding ) + && ( zx.exp + 0x7F <= 0 ); + zx = roundFloatXTo24( isTiny, zx ); + expField = zx.exp + 0x7F; + if ( 0xFF <= expField ) { + slow_float_exception_flags |= + float_flag_overflow | float_flag_inexact; + if ( zx.sign ) { + switch ( slow_float_rounding_mode ) { + case float_round_nearest_even: + case float_round_down: + z = 0xFF800000; + break; + case float_round_to_zero: + case float_round_up: + z = 0xFF7FFFFF; + break; + } + } + else { + switch ( slow_float_rounding_mode ) { + case float_round_nearest_even: + case float_round_up: + z = 0x7F800000; + break; + case float_round_to_zero: + case float_round_down: + z = 0x7F7FFFFF; + break; + } + } + return z; + } + if ( expField <= 0 ) { + isTiny = TRUE; + zx = savedZ; + expField = zx.exp + 0x7F; + if ( expField < -27 ) { + zx.sig.a1 = ( zx.sig.a0 != 0 ) || ( zx.sig.a1 != 0 ); + zx.sig.a0 = 0; + } + else { + while ( expField <= 0 ) { + zx.sig = shortShift64RightJamming( zx.sig, 1 ); + ++expField; + } + } + zx = roundFloatXTo24( isTiny, zx ); + expField = ( 0x00800000 <= zx.sig.a0 ) ? 1 : 0; + } + z = expField; + z <<= 23; + if ( zx.sign ) z |= 0x80000000; + z |= zx.sig.a0 & 0x007FFFFF; + return z; + +} + +static floatX float64ToFloatX( float64 a ) +{ + int16 expField; + floatX ax; + + ax.isNaN = FALSE; + ax.isInf = FALSE; + ax.isZero = FALSE; +#ifdef BITS64 + ax.sign = ( ( a & LIT64( 0x8000000000000000 ) ) != 0 ); + expField = ( a>>52 ) & 0x7FF; + ax.sig.a1 = a; + ax.sig.a0 = ( a>>32 ) & 0x000FFFFF; +#else + ax.sign = ( ( a.high & 0x80000000 ) != 0 ); + expField = ( a.high>>( 52 - 32 ) ) & 0x7FF; + ax.sig.a1 = a.low; + ax.sig.a0 = a.high & 0x000FFFFF; +#endif + if ( expField == 0 ) { + if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) { + ax.isZero = TRUE; + } + else { + expField = 1 - 0x3FF; + do { + ax.sig = shortShift64Left( ax.sig, 1 ); + --expField; + } while ( ax.sig.a0 < 0x00100000 ); + ax.exp = expField; + } + } + else if ( expField == 0x7FF ) { + if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) { + ax.isInf = TRUE; + } + else { + ax.isNaN = TRUE; + } + } + else { + ax.exp = expField - 0x3FF; + ax.sig.a0 |= 0x00100000; + } + ax.sig = shortShift64Left( ax.sig, 3 ); + return ax; + +} + +static float64 floatXToFloat64( floatX zx ) +{ + floatX savedZ; + flag isTiny; + int16 expField; + float64 z; + +#ifdef BITS64 + if ( zx.isZero ) return zx.sign ? LIT64( 0x8000000000000000 ) : 0; + if ( zx.isInf ) { + return + zx.sign ? LIT64( 0xFFF0000000000000 ) + : LIT64( 0x7FF0000000000000 ); + } + if ( zx.isNaN ) return LIT64( 0xFFFFFFFFFFFFFFFF ); +#else + if ( zx.isZero ) { + z.low = 0; + z.high = zx.sign ? 0x80000000 : 0; + return z; + } + if ( zx.isInf ) { + z.low = 0; + z.high = zx.sign ? 0xFFF00000 : 0x7FF00000; + return z; + } + if ( zx.isNaN ) { + z.high = z.low = 0xFFFFFFFF; + return z; + } +#endif + while ( 0x01000000 <= zx.sig.a0 ) { + zx.sig = shortShift64RightJamming( zx.sig, 1 ); + ++zx.exp; + } + while ( zx.sig.a0 < 0x00800000 ) { + zx.sig = shortShift64Left( zx.sig, 1 ); + --zx.exp; + } + savedZ = zx; + isTiny = + ( slow_float_detect_tininess == float_tininess_before_rounding ) + && ( zx.exp + 0x3FF <= 0 ); + zx = roundFloatXTo53( isTiny, zx ); + expField = zx.exp + 0x3FF; + if ( 0x7FF <= expField ) { + slow_float_exception_flags |= + float_flag_overflow | float_flag_inexact; +#ifdef BITS64 + if ( zx.sign ) { + switch ( slow_float_rounding_mode ) { + case float_round_nearest_even: + case float_round_down: + z = LIT64( 0xFFF0000000000000 ); + break; + case float_round_to_zero: + case float_round_up: + z = LIT64( 0xFFEFFFFFFFFFFFFF ); + break; + } + } + else { + switch ( slow_float_rounding_mode ) { + case float_round_nearest_even: + case float_round_up: + z = LIT64( 0x7FF0000000000000 ); + break; + case float_round_to_zero: + case float_round_down: + z = LIT64( 0x7FEFFFFFFFFFFFFF ); + break; + } + } +#else + if ( zx.sign ) { + switch ( slow_float_rounding_mode ) { + case float_round_nearest_even: + case float_round_down: + z.low = 0; + z.high = 0xFFF00000; + break; + case float_round_to_zero: + case float_round_up: + z.low = 0xFFFFFFFF; + z.high = 0xFFEFFFFF; + break; + } + } + else { + switch ( slow_float_rounding_mode ) { + case float_round_nearest_even: + case float_round_up: + z.low = 0; + z.high = 0x7FF00000; + break; + case float_round_to_zero: + case float_round_down: + z.low = 0xFFFFFFFF; + z.high = 0x7FEFFFFF; + break; + } + } +#endif + return z; + } + if ( expField <= 0 ) { + isTiny = TRUE; + zx = savedZ; + expField = zx.exp + 0x3FF; + if ( expField < -56 ) { + zx.sig.a1 = ( zx.sig.a0 != 0 ) || ( zx.sig.a1 != 0 ); + zx.sig.a0 = 0; + } + else { + while ( expField <= 0 ) { + zx.sig = shortShift64RightJamming( zx.sig, 1 ); + ++expField; + } + } + zx = roundFloatXTo53( isTiny, zx ); + expField = ( 0x00800000 <= zx.sig.a0 ) ? 1 : 0; + } + zx.sig = shortShift64RightJamming( zx.sig, 3 ); +#ifdef BITS64 + z = expField; + z <<= 52; + if ( zx.sign ) z |= LIT64( 0x8000000000000000 ); + z |= ( ( (bits64) ( zx.sig.a0 & 0x000FFFFF ) )<<32 ) | zx.sig.a1; +#else + z.low = zx.sig.a1; + z.high = expField; + z.high <<= 52 - 32; + if ( zx.sign ) z.high |= 0x80000000; + z.high |= zx.sig.a0 & 0x000FFFFF; +#endif + return z; + +} + +static floatX floatXInvalid( void ) +{ + + slow_float_exception_flags |= float_flag_invalid; + return floatXNaN; + +} + +static floatX floatXRoundToInt( floatX ax ) +{ + int16 shiftCount, i; + + if ( ax.isNaN || ax.isInf ) return ax; + shiftCount = 52 - ax.exp; + if ( shiftCount <= 0 ) return ax; + if ( 55 < shiftCount ) { + ax.exp = 52; + ax.sig.a1 = ! ax.isZero; + ax.sig.a0 = 0; + } + else { + while ( 0 < shiftCount ) { + ax.sig = shortShift64RightJamming( ax.sig, 1 ); + ++ax.exp; + --shiftCount; + } + } + ax = roundFloatXTo53( FALSE, ax ); + if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) ax.isZero = TRUE; + return ax; + +} + +static floatX floatXAdd( floatX ax, floatX bx ) +{ + int16 expDiff; + floatX zx; + + if ( ax.isNaN ) return ax; + if ( bx.isNaN ) return bx; + if ( ax.isInf && bx.isInf ) { + if ( ax.sign == bx.sign ) return ax; + return floatXInvalid(); + } + if ( ax.isInf ) return ax; + if ( bx.isInf ) return bx; + if ( ax.isZero && bx.isZero ) { + if ( ax.sign == bx.sign ) return ax; + goto completeCancellation; + } + if ( ( ax.sign != bx.sign ) + && ( ax.exp == bx.exp ) + && eq64( ax.sig, bx.sig ) + ) { + completeCancellation: + return + ( slow_float_rounding_mode == float_round_down ) ? + floatXNegativeZero + : floatXPositiveZero; + } + if ( ax.isZero ) return bx; + if ( bx.isZero ) return ax; + expDiff = ax.exp - bx.exp; + if ( expDiff < 0 ) { + zx = ax; + zx.exp = bx.exp; + if ( expDiff < -56 ) { + zx.sig.a1 = 1; + zx.sig.a0 = 0; + } + else { + while ( expDiff < 0 ) { + zx.sig = shortShift64RightJamming( zx.sig, 1 ); + ++expDiff; + } + } + if ( ax.sign != bx.sign ) zx.sig = neg64( zx.sig ); + zx.sign = bx.sign; + zx.sig = add64( zx.sig, bx.sig ); + } + else { + zx = bx; + zx.exp = ax.exp; + if ( 56 < expDiff ) { + zx.sig.a1 = 1; + zx.sig.a0 = 0; + } + else { + while ( 0 < expDiff ) { + zx.sig = shortShift64RightJamming( zx.sig, 1 ); + --expDiff; + } + } + if ( ax.sign != bx.sign ) zx.sig = neg64( zx.sig ); + zx.sign = ax.sign; + zx.sig = add64( zx.sig, ax.sig ); + } + if ( zx.sig.a0 & 0x80000000 ) { + zx.sig = neg64( zx.sig ); + zx.sign = ! zx.sign; + } + return zx; + +} + +static floatX floatXMul( floatX ax, floatX bx ) +{ + int8 bitNum; + floatX zx; + + if ( ax.isNaN ) return ax; + if ( bx.isNaN ) return bx; + if ( ax.isInf ) { + if ( bx.isZero ) return floatXInvalid(); + if ( bx.sign ) ax.sign = ! ax.sign; + return ax; + } + if ( bx.isInf ) { + if ( ax.isZero ) return floatXInvalid(); + if ( ax.sign ) bx.sign = ! bx.sign; + return bx; + } + zx = ax; + zx.sign ^= bx.sign; + if ( ax.isZero || bx.isZero ) { + return zx.sign ? floatXNegativeZero : floatXPositiveZero; + } + zx.exp += bx.exp + 1; + zx.sig.a1 = 0; + zx.sig.a0 = 0; + for ( bitNum = 0; bitNum < 55; ++bitNum ) { + if ( bx.sig.a1 & 2 ) zx.sig = add64( zx.sig, ax.sig ); + bx.sig = shortShift64RightJamming( bx.sig, 1 ); + zx.sig = shortShift64RightJamming( zx.sig, 1 ); + } + return zx; + +} + +static floatX floatXDiv( floatX ax, floatX bx ) +{ + bits64X negBSig; + int8 bitNum; + floatX zx; + + if ( ax.isNaN ) return ax; + if ( bx.isNaN ) return bx; + if ( ax.isInf ) { + if ( bx.isInf ) return floatXInvalid(); + if ( bx.sign ) ax.sign = ! ax.sign; + return ax; + } + if ( bx.isZero ) { + if ( ax.isZero ) return floatXInvalid(); + slow_float_exception_flags |= float_flag_divbyzero; + if ( ax.sign ) bx.sign = ! bx.sign; + bx.isZero = FALSE; + bx.isInf = TRUE; + return bx; + } + zx = ax; + zx.sign ^= bx.sign; + if ( ax.isZero || bx.isInf ) { + return zx.sign ? floatXNegativeZero : floatXPositiveZero; + } + zx.exp -= bx.exp + 1; + zx.sig.a1 = 0; + zx.sig.a0 = 0; + negBSig = neg64( bx.sig ); + for ( bitNum = 0; bitNum < 56; ++bitNum ) { + if ( le64( bx.sig, ax.sig ) ) { + zx.sig.a1 |= 1; + ax.sig = add64( ax.sig, negBSig ); + } + ax.sig = shortShift64Left( ax.sig, 1 ); + zx.sig = shortShift64Left( zx.sig, 1 ); + } + if ( ax.sig.a0 || ax.sig.a1 ) zx.sig.a1 |= 1; + return zx; + +} + +static floatX floatXRem( floatX ax, floatX bx ) +{ + bits64X negBSig; + flag lastQuotientBit; + bits64X savedASig; + + if ( ax.isNaN ) return ax; + if ( bx.isNaN ) return bx; + if ( ax.isInf || bx.isZero ) return floatXInvalid(); + if ( ax.isZero || bx.isInf ) return ax; + --bx.exp; + if ( ax.exp < bx.exp ) return ax; + bx.sig = shortShift64Left( bx.sig, 1 ); + negBSig = neg64( bx.sig ); + while ( bx.exp < ax.exp ) { + if ( le64( bx.sig, ax.sig ) ) ax.sig = add64( ax.sig, negBSig ); + ax.sig = shortShift64Left( ax.sig, 1 ); + --ax.exp; + } + lastQuotientBit = le64( bx.sig, ax.sig ); + if ( lastQuotientBit ) ax.sig = add64( ax.sig, negBSig ); + savedASig = ax.sig; + ax.sig = neg64( add64( ax.sig, negBSig ) ); + if ( lt64( ax.sig, savedASig ) ) { + ax.sign = ! ax.sign; + } + else if ( lt64( savedASig, ax.sig ) ) { + ax.sig = savedASig; + } + else { + if ( lastQuotientBit ) { + ax.sign = ! ax.sign; + } + else { + ax.sig = savedASig; + } + } + if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) ax.isZero = TRUE; + return ax; + +} + +static floatX floatXSqrt( floatX ax ) +{ + int8 bitNum; + bits64X bitSig, savedASig; + floatX zx; + + if ( ax.isNaN || ax.isZero ) return ax; + if ( ax.sign ) return floatXInvalid(); + if ( ax.isInf ) return ax; + zx = ax; + zx.exp >>= 1; + if ( ( ax.exp & 1 ) == 0 ) ax.sig = shortShift64RightJamming( ax.sig, 1 ); + zx.sig.a1 = 0; + zx.sig.a0 = 0; + bitSig.a1 = 0; + bitSig.a0 = 0x00800000; + for ( bitNum = 0; bitNum < 56; ++bitNum ) { + savedASig = ax.sig; + ax.sig = add64( ax.sig, neg64( zx.sig ) ); + ax.sig = shortShift64Left( ax.sig, 1 ); + ax.sig = add64( ax.sig, neg64( bitSig ) ); + if ( ax.sig.a0 & 0x80000000 ) { + ax.sig = shortShift64Left( savedASig, 1 ); + } + else { + zx.sig.a1 |= bitSig.a1; + zx.sig.a0 |= bitSig.a0; + } + bitSig = shortShift64RightJamming( bitSig, 1 ); + } + if ( ax.sig.a0 || ax.sig.a1 ) zx.sig.a1 |= 1; + return zx; + +} + +static flag floatXEq( floatX ax, floatX bx ) +{ + + if ( ax.isNaN || bx.isNaN ) return FALSE; + if ( ax.isZero && bx.isZero ) return TRUE; + if ( ax.sign != bx.sign ) return FALSE; + if ( ax.isInf || bx.isInf ) return ax.isInf && bx.isInf; + return ( ax.exp == bx.exp ) && eq64( ax.sig, bx.sig ); + +} + +static flag floatXLe( floatX ax, floatX bx ) +{ + + if ( ax.isNaN || bx.isNaN ) return FALSE; + if ( ax.isZero && bx.isZero ) return TRUE; + if ( ax.sign != bx.sign ) return ax.sign; + if ( ax.sign ) { + if ( ax.isInf || bx.isZero ) return TRUE; + if ( bx.isInf || ax.isZero ) return FALSE; + if ( bx.exp < ax.exp ) return TRUE; + if ( ax.exp < bx.exp ) return FALSE; + return le64( bx.sig, ax.sig ); + } + else { + if ( bx.isInf || ax.isZero ) return TRUE; + if ( ax.isInf || bx.isZero ) return FALSE; + if ( ax.exp < bx.exp ) return TRUE; + if ( bx.exp < ax.exp ) return FALSE; + return le64( ax.sig, bx.sig ); + } + +} + +static flag floatXLt( floatX ax, floatX bx ) +{ + + if ( ax.isNaN || bx.isNaN ) return FALSE; + if ( ax.isZero && bx.isZero ) return FALSE; + if ( ax.sign != bx.sign ) return ax.sign; + if ( ax.isInf && bx.isInf ) return FALSE; + if ( ax.sign ) { + if ( ax.isInf || bx.isZero ) return TRUE; + if ( bx.isInf || ax.isZero ) return FALSE; + if ( bx.exp < ax.exp ) return TRUE; + if ( ax.exp < bx.exp ) return FALSE; + return lt64( bx.sig, ax.sig ); + } + else { + if ( bx.isInf || ax.isZero ) return TRUE; + if ( ax.isInf || bx.isZero ) return FALSE; + if ( ax.exp < bx.exp ) return TRUE; + if ( bx.exp < ax.exp ) return FALSE; + return lt64( ax.sig, bx.sig ); + } + +} + +float32 slow_int32_to_float32( int32 a ) +{ + + return floatXToFloat32( int32ToFloatX( a ) ); + +} + +float64 slow_int32_to_float64( int32 a ) +{ + + return floatXToFloat64( int32ToFloatX( a ) ); + +} + +int32 slow_float32_to_int32( float32 a ) +{ + + return floatXToInt32( float32ToFloatX( a ) ); + +} + +int32 slow_float32_to_int32_round_to_zero( float32 a ) +{ + int8 savedRoundingMode; + int32 z; + + savedRoundingMode = slow_float_rounding_mode; + slow_float_rounding_mode = float_round_to_zero; + z = floatXToInt32( float32ToFloatX( a ) ); + slow_float_rounding_mode = savedRoundingMode; + return z; + +} + +float64 slow_float32_to_float64( float32 a ) +{ + + return floatXToFloat64( float32ToFloatX( a ) ); + +} + +float32 slow_float32_round_to_int( float32 a ) +{ + + return floatXToFloat32( floatXRoundToInt( float32ToFloatX( a ) ) ); + +} + +float32 slow_float32_add( float32 a, float32 b ) +{ + + return + floatXToFloat32( + floatXAdd( float32ToFloatX( a ), float32ToFloatX( b ) ) ); + +} + +float32 slow_float32_sub( float32 a, float32 b ) +{ + + b ^= 0x80000000; + return + floatXToFloat32( + floatXAdd( float32ToFloatX( a ), float32ToFloatX( b ) ) ); + +} + +float32 slow_float32_mul( float32 a, float32 b ) +{ + + return + floatXToFloat32( + floatXMul( float32ToFloatX( a ), float32ToFloatX( b ) ) ); + +} + +float32 slow_float32_div( float32 a, float32 b ) +{ + + return + floatXToFloat32( + floatXDiv( float32ToFloatX( a ), float32ToFloatX( b ) ) ); + +} + +float32 slow_float32_rem( float32 a, float32 b ) +{ + + return + floatXToFloat32( + floatXRem( float32ToFloatX( a ), float32ToFloatX( b ) ) ); + +} + +float32 slow_float32_sqrt( float32 a ) +{ + + return floatXToFloat32( floatXSqrt( float32ToFloatX( a ) ) ); + +} + +flag slow_float32_eq( float32 a, float32 b ) +{ + + return floatXEq( float32ToFloatX( a ), float32ToFloatX( b ) ); + +} + +flag slow_float32_le( float32 a, float32 b ) +{ + floatX ax, bx; + + ax = float32ToFloatX( a ); + bx = float32ToFloatX( b ); + if ( ax.isNaN || bx.isNaN ) { + slow_float_exception_flags |= float_flag_invalid; + } + return floatXLe( ax, bx ); + +} + +flag slow_float32_lt( float32 a, float32 b ) +{ + floatX ax, bx; + + ax = float32ToFloatX( a ); + bx = float32ToFloatX( b ); + if ( ax.isNaN || bx.isNaN ) { + slow_float_exception_flags |= float_flag_invalid; + } + return floatXLt( ax, bx ); + +} + +flag slow_float32_eq_signaling( float32 a, float32 b ) +{ + floatX ax, bx; + + ax = float32ToFloatX( a ); + bx = float32ToFloatX( b ); + if ( ax.isNaN || bx.isNaN ) { + slow_float_exception_flags |= float_flag_invalid; + } + return floatXEq( ax, bx ); + +} + +flag slow_float32_le_quiet( float32 a, float32 b ) +{ + + return floatXLe( float32ToFloatX( a ), float32ToFloatX( b ) ); + +} + +flag slow_float32_lt_quiet( float32 a, float32 b ) +{ + + return floatXLt( float32ToFloatX( a ), float32ToFloatX( b ) ); + +} + +int32 slow_float64_to_int32( float64 a ) +{ + + return floatXToInt32( float64ToFloatX( a ) ); + +} + +int32 slow_float64_to_int32_round_to_zero( float64 a ) +{ + int8 savedRoundingMode; + int32 z; + + savedRoundingMode = slow_float_rounding_mode; + slow_float_rounding_mode = float_round_to_zero; + z = floatXToInt32( float64ToFloatX( a ) ); + slow_float_rounding_mode = savedRoundingMode; + return z; + +} + +float32 slow_float64_to_float32( float64 a ) +{ + + return floatXToFloat32( float64ToFloatX( a ) ); + +} + +float64 slow_float64_round_to_int( float64 a ) +{ + + return floatXToFloat64( floatXRoundToInt( float64ToFloatX( a ) ) ); + +} + +float64 slow_float64_add( float64 a, float64 b ) +{ + + return + floatXToFloat64( + floatXAdd( float64ToFloatX( a ), float64ToFloatX( b ) ) ); + +} + +float64 slow_float64_sub( float64 a, float64 b ) +{ + +#ifdef BITS64 + b ^= LIT64( 0x8000000000000000 ); +#else + b.high ^= 0x80000000; +#endif + return + floatXToFloat64( + floatXAdd( float64ToFloatX( a ), float64ToFloatX( b ) ) ); + +} + +float64 slow_float64_mul( float64 a, float64 b ) +{ + + return + floatXToFloat64( + floatXMul( float64ToFloatX( a ), float64ToFloatX( b ) ) ); + +} + +float64 slow_float64_div( float64 a, float64 b ) +{ + + return + floatXToFloat64( + floatXDiv( float64ToFloatX( a ), float64ToFloatX( b ) ) ); + +} + +float64 slow_float64_rem( float64 a, float64 b ) +{ + + return + floatXToFloat64( + floatXRem( float64ToFloatX( a ), float64ToFloatX( b ) ) ); + +} + +float64 slow_float64_sqrt( float64 a ) +{ + + return floatXToFloat64( floatXSqrt( float64ToFloatX( a ) ) ); + +} + +flag slow_float64_eq( float64 a, float64 b ) +{ + + return floatXEq( float64ToFloatX( a ), float64ToFloatX( b ) ); + +} + +flag slow_float64_le( float64 a, float64 b ) +{ + floatX ax, bx; + + ax = float64ToFloatX( a ); + bx = float64ToFloatX( b ); + if ( ax.isNaN || bx.isNaN ) { + slow_float_exception_flags |= float_flag_invalid; + } + return floatXLe( ax, bx ); + +} + +flag slow_float64_lt( float64 a, float64 b ) +{ + floatX ax, bx; + + ax = float64ToFloatX( a ); + bx = float64ToFloatX( b ); + if ( ax.isNaN || bx.isNaN ) { + slow_float_exception_flags |= float_flag_invalid; + } + return floatXLt( ax, bx ); + +} + +flag slow_float64_eq_signaling( float64 a, float64 b ) +{ + floatX ax, bx; + + ax = float64ToFloatX( a ); + bx = float64ToFloatX( b ); + if ( ax.isNaN || bx.isNaN ) { + slow_float_exception_flags |= float_flag_invalid; + } + return floatXEq( ax, bx ); + +} + +flag slow_float64_le_quiet( float64 a, float64 b ) +{ + + return floatXLe( float64ToFloatX( a ), float64ToFloatX( b ) ); + +} + +flag slow_float64_lt_quiet( float64 a, float64 b ) +{ + + return floatXLt( float64ToFloatX( a ), float64ToFloatX( b ) ); + +} + diff --git a/tools/test/testfloat/slowfloat-64.c b/tools/test/testfloat/slowfloat-64.c new file mode 100644 index 0000000..27e56e1 --- /dev/null +++ b/tools/test/testfloat/slowfloat-64.c @@ -0,0 +1,2109 @@ + +/* +=============================================================================== + +This C source file is part of TestFloat, Release 2a, a package of programs +for testing the correctness of floating-point arithmetic complying to the +IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +int8 slow_float_rounding_mode; +int8 slow_float_exception_flags; +int8 slow_float_detect_tininess; +#ifdef FLOATX80 +int8 slow_floatx80_rounding_precision; +#endif + +typedef struct { + bits64 a0, a1; +} bits128X; + +typedef struct { + flag isNaN; + flag isInf; + flag isZero; + flag sign; + int32 exp; + bits128X sig; +} floatX; + +static const floatX floatXNaN = { TRUE, FALSE, FALSE, FALSE, 0, { 0, 0 } }; +static const floatX floatXPositiveZero = + { FALSE, FALSE, TRUE, FALSE, 0, { 0, 0 } }; +static const floatX floatXNegativeZero = + { FALSE, FALSE, TRUE, TRUE, 0, { 0, 0 } }; + +static bits128X shortShift128Left( bits128X a, int8 shiftCount ) +{ + int8 negShiftCount; + + negShiftCount = ( - shiftCount & 63 ); + a.a0 = ( a.a0<<shiftCount ) | ( a.a1>>negShiftCount ); + a.a1 <<= shiftCount; + return a; + +} + +static bits128X shortShift128RightJamming( bits128X a, int8 shiftCount ) +{ + int8 negShiftCount; + bits64 extra; + + negShiftCount = ( - shiftCount & 63 ); + extra = a.a1<<negShiftCount; + a.a1 = ( a.a0<<negShiftCount ) | ( a.a1>>shiftCount ) | ( extra != 0 ); + a.a0 >>= shiftCount; + return a; + +} + +static bits128X neg128( bits128X a ) +{ + + if ( a.a1 == 0 ) { + a.a0 = - a.a0; + } + else { + a.a1 = - a.a1; + a.a0 = ~ a.a0; + } + return a; + +} + +static bits128X add128( bits128X a, bits128X b ) +{ + + a.a1 += b.a1; + a.a0 += b.a0 + ( a.a1 < b.a1 ); + return a; + +} + +static flag eq128( bits128X a, bits128X b ) +{ + + return ( a.a0 == b.a0 ) && ( a.a1 == b.a1 ); + +} + +static flag le128( bits128X a, bits128X b ) +{ + + return ( a.a0 < b.a0 ) || ( ( a.a0 == b.a0 ) && ( a.a1 <= b.a1 ) ); + +} + +static flag lt128( bits128X a, bits128X b ) +{ + + return ( a.a0 < b.a0 ) || ( ( a.a0 == b.a0 ) && ( a.a1 < b.a1 ) ); + +} + +static floatX roundFloatXTo24( flag isTiny, floatX zx ) +{ + bits32 roundBits; + + zx.sig.a0 |= ( zx.sig.a1 != 0 ); + zx.sig.a1 = 0; + roundBits = zx.sig.a0 & 0xFFFFFFFF; + zx.sig.a0 -= roundBits; + if ( roundBits ) { + slow_float_exception_flags |= float_flag_inexact; + if ( isTiny ) slow_float_exception_flags |= float_flag_underflow; + switch ( slow_float_rounding_mode ) { + case float_round_nearest_even: + if ( roundBits < 0x80000000 ) goto noIncrement; + if ( ( roundBits == 0x80000000 ) + && ! ( zx.sig.a0 & LIT64( 0x100000000 ) ) ) { + goto noIncrement; + } + break; + case float_round_to_zero: + goto noIncrement; + case float_round_down: + if ( ! zx.sign ) goto noIncrement; + break; + case float_round_up: + if ( zx.sign ) goto noIncrement; + break; + } + zx.sig.a0 += LIT64( 0x100000000 ); + if ( zx.sig.a0 == LIT64( 0x0100000000000000 ) ) { + zx.sig.a0 = LIT64( 0x0080000000000000 ); + ++zx.exp; + } + } + noIncrement: + return zx; + +} + +static floatX roundFloatXTo53( flag isTiny, floatX zx ) +{ + int8 roundBits; + + zx.sig.a0 |= ( zx.sig.a1 != 0 ); + zx.sig.a1 = 0; + roundBits = zx.sig.a0 & 7; + zx.sig.a0 -= roundBits; + if ( roundBits ) { + slow_float_exception_flags |= float_flag_inexact; + if ( isTiny ) slow_float_exception_flags |= float_flag_underflow; + switch ( slow_float_rounding_mode ) { + case float_round_nearest_even: + if ( roundBits < 4 ) goto noIncrement; + if ( ( roundBits == 4 ) && ! ( zx.sig.a0 & 8 ) ) goto noIncrement; + break; + case float_round_to_zero: + goto noIncrement; + case float_round_down: + if ( ! zx.sign ) goto noIncrement; + break; + case float_round_up: + if ( zx.sign ) goto noIncrement; + break; + } + zx.sig.a0 += 8; + if ( zx.sig.a0 == LIT64( 0x0100000000000000 ) ) { + zx.sig.a0 = LIT64( 0x0080000000000000 ); + ++zx.exp; + } + } + noIncrement: + return zx; + +} + +static floatX roundFloatXTo64( flag isTiny, floatX zx ) +{ + int64 roundBits; + + roundBits = zx.sig.a1 & LIT64( 0x00FFFFFFFFFFFFFF ); + zx.sig.a1 -= roundBits; + if ( roundBits ) { + slow_float_exception_flags |= float_flag_inexact; + if ( isTiny ) slow_float_exception_flags |= float_flag_underflow; + switch ( slow_float_rounding_mode ) { + case float_round_nearest_even: + if ( roundBits < LIT64( 0x0080000000000000 ) ) goto noIncrement; + if ( ( roundBits == LIT64( 0x0080000000000000 ) ) + && ! ( zx.sig.a1 & LIT64( 0x0100000000000000 ) ) ) { + goto noIncrement; + } + break; + case float_round_to_zero: + goto noIncrement; + case float_round_down: + if ( ! zx.sign ) goto noIncrement; + break; + case float_round_up: + if ( zx.sign ) goto noIncrement; + break; + } + zx.sig.a1 += LIT64( 0x0100000000000000 ); + zx.sig.a0 += ( zx.sig.a1 == 0 ); + if ( zx.sig.a0 == LIT64( 0x0100000000000000 ) ) { + zx.sig.a0 = LIT64( 0x0080000000000000 ); + ++zx.exp; + } + } + noIncrement: + return zx; + +} + +static floatX roundFloatXTo113( flag isTiny, floatX zx ) +{ + int8 roundBits; + + roundBits = zx.sig.a1 & 0x7F; + zx.sig.a1 -= roundBits; + if ( roundBits ) { + slow_float_exception_flags |= float_flag_inexact; + if ( isTiny ) slow_float_exception_flags |= float_flag_underflow; + switch ( slow_float_rounding_mode ) { + case float_round_nearest_even: + if ( roundBits < 0x40 ) goto noIncrement; + if ( ( roundBits == 0x40 ) + && ! ( zx.sig.a1 & 0x80 ) ) goto noIncrement; + break; + case float_round_to_zero: + goto noIncrement; + case float_round_down: + if ( ! zx.sign ) goto noIncrement; + break; + case float_round_up: + if ( zx.sign ) goto noIncrement; + break; + } + zx.sig.a1 += 0x80; + zx.sig.a0 += ( zx.sig.a1 == 0 ); + if ( zx.sig.a0 == LIT64( 0x0100000000000000 ) ) { + zx.sig.a0 = LIT64( 0x0080000000000000 ); + ++zx.exp; + } + } + noIncrement: + return zx; + +} + +static floatX int32ToFloatX( int32 a ) +{ + floatX ax; + + ax.isNaN = FALSE; + ax.isInf = FALSE; + ax.sign = ( a < 0 ); + ax.sig.a1 = 0; + ax.sig.a0 = ax.sign ? - (bits64) a : a; + if ( a == 0 ) { + ax.isZero = TRUE; + return ax; + } + ax.isZero = FALSE; + ax.sig.a0 <<= 24; + ax.exp = 31; + while ( ax.sig.a0 < LIT64( 0x0080000000000000 ) ) { + ax.sig.a0 <<= 1; + --ax.exp; + } + return ax; + +} + +static int32 floatXToInt32( floatX ax ) +{ + int8 savedExceptionFlags; + int32 shiftCount; + int32 z; + + if ( ax.isInf || ax.isNaN ) { + slow_float_exception_flags |= float_flag_invalid; + return ( ax.isInf & ax.sign ) ? (sbits32) 0x80000000 : 0x7FFFFFFF; + } + if ( ax.isZero ) return 0; + savedExceptionFlags = slow_float_exception_flags; + shiftCount = 52 - ax.exp; + if ( 56 < shiftCount ) { + ax.sig.a1 = 1; + ax.sig.a0 = 0; + } + else { + while ( 0 < shiftCount ) { + ax.sig = shortShift128RightJamming( ax.sig, 1 ); + --shiftCount; + } + } + ax = roundFloatXTo53( FALSE, ax ); + ax.sig = shortShift128RightJamming( ax.sig, 3 ); + z = ax.sig.a0; + if ( ax.sign ) z = - z; + if ( ( shiftCount < 0 ) + || ( ax.sig.a0>>32 ) + || ( ( z != 0 ) && ( ( ax.sign ^ ( z < 0 ) ) != 0 ) ) + ) { + slow_float_exception_flags = savedExceptionFlags | float_flag_invalid; + return ax.sign ? (sbits32) 0x80000000 : 0x7FFFFFFF; + } + return z; + +} + +static floatX int64ToFloatX( int64 a ) +{ + uint64 absA; + floatX ax; + + ax.isNaN = FALSE; + ax.isInf = FALSE; + ax.sign = ( a < 0 ); + ax.sig.a1 = ax.sign ? - a : a; + ax.sig.a0 = 0; + if ( a == 0 ) { + ax.isZero = TRUE; + return ax; + } + ax.isZero = FALSE; + ax.sig = shortShift128Left( ax.sig, 56 ); + ax.exp = 63; + while ( ax.sig.a0 < LIT64( 0x0080000000000000 ) ) { + ax.sig = shortShift128Left( ax.sig, 1 ); + --ax.exp; + } + return ax; + +} + +static int64 floatXToInt64( floatX ax ) +{ + int8 savedExceptionFlags; + int32 shiftCount; + int64 z; + + if ( ax.isInf || ax.isNaN ) { + slow_float_exception_flags |= float_flag_invalid; + return + ( ax.isInf & ax.sign ) ? (sbits64) LIT64( 0x8000000000000000 ) + : LIT64( 0x7FFFFFFFFFFFFFFF ); + } + if ( ax.isZero ) return 0; + savedExceptionFlags = slow_float_exception_flags; + shiftCount = 112 - ax.exp; + if ( 116 < shiftCount ) { + ax.sig.a1 = 1; + ax.sig.a0 = 0; + } + else { + while ( 0 < shiftCount ) { + ax.sig = shortShift128RightJamming( ax.sig, 1 ); + --shiftCount; + } + } + ax = roundFloatXTo113( FALSE, ax ); + ax.sig = shortShift128RightJamming( ax.sig, 7 ); + z = ax.sig.a1; + if ( ax.sign ) z = - z; + if ( ( shiftCount < 0 ) + || ax.sig.a0 + || ( ( z != 0 ) && ( ( ax.sign ^ ( z < 0 ) ) != 0 ) ) + ) { + slow_float_exception_flags = savedExceptionFlags | float_flag_invalid; + return + ax.sign ? (sbits64) LIT64( 0x8000000000000000 ) + : LIT64( 0x7FFFFFFFFFFFFFFF ); + } + return z; + +} + +static floatX float32ToFloatX( float32 a ) +{ + int16 expField; + floatX ax; + + ax.isNaN = FALSE; + ax.isInf = FALSE; + ax.isZero = FALSE; + ax.sign = ( ( a & 0x80000000 ) != 0 ); + expField = ( a>>23 ) & 0xFF; + ax.sig.a1 = 0; + ax.sig.a0 = a & 0x007FFFFF; + ax.sig.a0 <<= 32; + if ( expField == 0 ) { + if ( ax.sig.a0 == 0 ) { + ax.isZero = TRUE; + } + else { + expField = 1 - 0x7F; + do { + ax.sig.a0 <<= 1; + --expField; + } while ( ax.sig.a0 < LIT64( 0x0080000000000000 ) ); + ax.exp = expField; + } + } + else if ( expField == 0xFF ) { + if ( ax.sig.a0 == 0 ) { + ax.isInf = TRUE; + } + else { + ax.isNaN = TRUE; + } + } + else { + ax.sig.a0 |= LIT64( 0x0080000000000000 ); + ax.exp = expField - 0x7F; + } + return ax; + +} + +static float32 floatXToFloat32( floatX zx ) +{ + floatX savedZ; + flag isTiny; + int32 expField; + float32 z; + + if ( zx.isZero ) return zx.sign ? 0x80000000 : 0; + if ( zx.isInf ) return zx.sign ? 0xFF800000 : 0x7F800000; + if ( zx.isNaN ) return 0xFFFFFFFF; + while ( LIT64( 0x0100000000000000 ) <= zx.sig.a0 ) { + zx.sig = shortShift128RightJamming( zx.sig, 1 ); + ++zx.exp; + } + while ( zx.sig.a0 < LIT64( 0x0080000000000000 ) ) { + zx.sig = shortShift128Left( zx.sig, 1 ); + --zx.exp; + } + savedZ = zx; + isTiny = + ( slow_float_detect_tininess == float_tininess_before_rounding ) + && ( zx.exp + 0x7F <= 0 ); + zx = roundFloatXTo24( isTiny, zx ); + expField = zx.exp + 0x7F; + if ( 0xFF <= expField ) { + slow_float_exception_flags |= + float_flag_overflow | float_flag_inexact; + if ( zx.sign ) { + switch ( slow_float_rounding_mode ) { + case float_round_nearest_even: + case float_round_down: + z = 0xFF800000; + break; + case float_round_to_zero: + case float_round_up: + z = 0xFF7FFFFF; + break; + } + } + else { + switch ( slow_float_rounding_mode ) { + case float_round_nearest_even: + case float_round_up: + z = 0x7F800000; + break; + case float_round_to_zero: + case float_round_down: + z = 0x7F7FFFFF; + break; + } + } + return z; + } + if ( expField <= 0 ) { + isTiny = TRUE; + zx = savedZ; + expField = zx.exp + 0x7F; + if ( expField < -27 ) { + zx.sig.a1 = ( zx.sig.a0 != 0 ) || ( zx.sig.a1 != 0 ); + zx.sig.a0 = 0; + } + else { + while ( expField <= 0 ) { + zx.sig = shortShift128RightJamming( zx.sig, 1 ); + ++expField; + } + } + zx = roundFloatXTo24( isTiny, zx ); + expField = ( LIT64( 0x0080000000000000 ) <= zx.sig.a0 ) ? 1 : 0; + } + z = expField; + z <<= 23; + if ( zx.sign ) z |= 0x80000000; + z |= ( zx.sig.a0>>32 ) & 0x007FFFFF; + return z; + +} + +static floatX float64ToFloatX( float64 a ) +{ + int16 expField; + floatX ax; + + ax.isNaN = FALSE; + ax.isInf = FALSE; + ax.isZero = FALSE; + ax.sign = ( ( a & LIT64( 0x8000000000000000 ) ) != 0 ); + expField = ( a>>52 ) & 0x7FF; + ax.sig.a1 = 0; + ax.sig.a0 = a & LIT64( 0x000FFFFFFFFFFFFF ); + if ( expField == 0 ) { + if ( ax.sig.a0 == 0 ) { + ax.isZero = TRUE; + } + else { + expField = 1 - 0x3FF; + do { + ax.sig.a0 <<= 1; + --expField; + } while ( ax.sig.a0 < LIT64( 0x0010000000000000 ) ); + ax.exp = expField; + } + } + else if ( expField == 0x7FF ) { + if ( ax.sig.a0 == 0 ) { + ax.isInf = TRUE; + } + else { + ax.isNaN = TRUE; + } + } + else { + ax.exp = expField - 0x3FF; + ax.sig.a0 |= LIT64( 0x0010000000000000 ); + } + ax.sig.a0 <<= 3; + return ax; + +} + +static float64 floatXToFloat64( floatX zx ) +{ + floatX savedZ; + flag isTiny; + int32 expField; + float64 z; + + if ( zx.isZero ) return zx.sign ? LIT64( 0x8000000000000000 ) : 0; + if ( zx.isInf ) { + return + zx.sign ? LIT64( 0xFFF0000000000000 ) + : LIT64( 0x7FF0000000000000 ); + } + if ( zx.isNaN ) return LIT64( 0xFFFFFFFFFFFFFFFF ); + while ( LIT64( 0x0100000000000000 ) <= zx.sig.a0 ) { + zx.sig = shortShift128RightJamming( zx.sig, 1 ); + ++zx.exp; + } + while ( zx.sig.a0 < LIT64( 0x0080000000000000 ) ) { + zx.sig = shortShift128Left( zx.sig, 1 ); + --zx.exp; + } + savedZ = zx; + isTiny = + ( slow_float_detect_tininess == float_tininess_before_rounding ) + && ( zx.exp + 0x3FF <= 0 ); + zx = roundFloatXTo53( isTiny, zx ); + expField = zx.exp + 0x3FF; + if ( 0x7FF <= expField ) { + slow_float_exception_flags |= + float_flag_overflow | float_flag_inexact; + if ( zx.sign ) { + switch ( slow_float_rounding_mode ) { + case float_round_nearest_even: + case float_round_down: + z = LIT64( 0xFFF0000000000000 ); + break; + case float_round_to_zero: + case float_round_up: + z = LIT64( 0xFFEFFFFFFFFFFFFF ); + break; + } + } + else { + switch ( slow_float_rounding_mode ) { + case float_round_nearest_even: + case float_round_up: + z = LIT64( 0x7FF0000000000000 ); + break; + case float_round_to_zero: + case float_round_down: + z = LIT64( 0x7FEFFFFFFFFFFFFF ); + break; + } + } + return z; + } + if ( expField <= 0 ) { + isTiny = TRUE; + zx = savedZ; + expField = zx.exp + 0x3FF; + if ( expField < -56 ) { + zx.sig.a1 = ( zx.sig.a0 != 0 ) || ( zx.sig.a1 != 0 ); + zx.sig.a0 = 0; + } + else { + while ( expField <= 0 ) { + zx.sig = shortShift128RightJamming( zx.sig, 1 ); + ++expField; + } + } + zx = roundFloatXTo53( isTiny, zx ); + expField = ( LIT64( 0x0080000000000000 ) <= zx.sig.a0 ) ? 1 : 0; + } + zx.sig.a0 >>= 3; + z = expField; + z <<= 52; + if ( zx.sign ) z |= LIT64( 0x8000000000000000 ); + z |= zx.sig.a0 & LIT64( 0x000FFFFFFFFFFFFF ); + return z; + +} + +#ifdef FLOATX80 + +static floatX floatx80ToFloatX( floatx80 a ) +{ + int32 expField; + floatX ax; + + ax.isNaN = FALSE; + ax.isInf = FALSE; + ax.isZero = FALSE; + ax.sign = ( ( a.high & 0x8000 ) != 0 ); + expField = a.high & 0x7FFF; + ax.sig.a1 = a.low; + ax.sig.a0 = 0; + if ( expField == 0 ) { + if ( ax.sig.a1 == 0 ) { + ax.isZero = TRUE; + } + else { + expField = 1 - 0x3FFF; + while ( ax.sig.a1 < LIT64( 0x8000000000000000 ) ) { + ax.sig.a1 <<= 1; + --expField; + } + ax.exp = expField; + } + } + else if ( expField == 0x7FFF ) { + if ( ( ax.sig.a1 & LIT64( 0x7FFFFFFFFFFFFFFF ) ) == 0 ) { + ax.isInf = TRUE; + } + else { + ax.isNaN = TRUE; + } + } + else { + ax.exp = expField - 0x3FFF; + } + ax.sig = shortShift128Left( ax.sig, 56 ); + return ax; + +} + +static floatx80 floatXToFloatx80( floatX zx ) +{ + floatX savedZ; + flag isTiny; + int32 expField; + floatx80 z; + + if ( zx.isZero ) { + z.low = 0; + z.high = zx.sign ? 0x8000 : 0; + return z; + } + if ( zx.isInf ) { + z.low = LIT64( 0x8000000000000000 ); + z.high = zx.sign ? 0xFFFF : 0x7FFF; + return z; + } + if ( zx.isNaN ) { + z.low = LIT64( 0xFFFFFFFFFFFFFFFF ); + z.high = 0xFFFF; + return z; + } + while ( LIT64( 0x0100000000000000 ) <= zx.sig.a0 ) { + zx.sig = shortShift128RightJamming( zx.sig, 1 ); + ++zx.exp; + } + while ( zx.sig.a0 < LIT64( 0x0080000000000000 ) ) { + zx.sig = shortShift128Left( zx.sig, 1 ); + --zx.exp; + } + savedZ = zx; + isTiny = + ( slow_float_detect_tininess == float_tininess_before_rounding ) + && ( zx.exp + 0x3FFF <= 0 ); + switch ( slow_floatx80_rounding_precision ) { + case 32: + zx = roundFloatXTo24( isTiny, zx ); + break; + case 64: + zx = roundFloatXTo53( isTiny, zx ); + break; + default: + zx = roundFloatXTo64( isTiny, zx ); + break; + } + expField = zx.exp + 0x3FFF; + if ( 0x7FFF <= expField ) { + slow_float_exception_flags |= + float_flag_overflow | float_flag_inexact; + if ( zx.sign ) { + switch ( slow_float_rounding_mode ) { + case float_round_nearest_even: + case float_round_down: + z.low = LIT64( 0x8000000000000000 ); + z.high = 0xFFFF; + break; + case float_round_to_zero: + case float_round_up: + switch ( slow_floatx80_rounding_precision ) { + case 32: + z.low = LIT64( 0xFFFFFF0000000000 ); + break; + case 64: + z.low = LIT64( 0xFFFFFFFFFFFFF800 ); + break; + default: + z.low = LIT64( 0xFFFFFFFFFFFFFFFF ); + break; + } + z.high = 0xFFFE; + break; + } + } + else { + switch ( slow_float_rounding_mode ) { + case float_round_nearest_even: + case float_round_up: + z.low = LIT64( 0x8000000000000000 ); + z.high = 0x7FFF; + break; + case float_round_to_zero: + case float_round_down: + switch ( slow_floatx80_rounding_precision ) { + case 32: + z.low = LIT64( 0xFFFFFF0000000000 ); + break; + case 64: + z.low = LIT64( 0xFFFFFFFFFFFFF800 ); + break; + default: + z.low = LIT64( 0xFFFFFFFFFFFFFFFF ); + break; + } + z.high = 0x7FFE; + break; + } + } + return z; + } + if ( expField <= 0 ) { + isTiny = TRUE; + zx = savedZ; + expField = zx.exp + 0x3FFF; + if ( expField < -70 ) { + zx.sig.a1 = ( zx.sig.a0 != 0 ) || ( zx.sig.a1 != 0 ); + zx.sig.a0 = 0; + } + else { + while ( expField <= 0 ) { + zx.sig = shortShift128RightJamming( zx.sig, 1 ); + ++expField; + } + } + switch ( slow_floatx80_rounding_precision ) { + case 32: + zx = roundFloatXTo24( isTiny, zx ); + break; + case 64: + zx = roundFloatXTo53( isTiny, zx ); + break; + default: + zx = roundFloatXTo64( isTiny, zx ); + break; + } + expField = ( LIT64( 0x0080000000000000 ) <= zx.sig.a0 ) ? 1 : 0; + } + zx.sig = shortShift128RightJamming( zx.sig, 56 ); + z.low = zx.sig.a1; + z.high = expField; + if ( zx.sign ) z.high |= 0x8000; + return z; + +} + +#endif + +#ifdef FLOAT128 + +static floatX float128ToFloatX( float128 a ) +{ + int32 expField; + floatX ax; + + ax.isNaN = FALSE; + ax.isInf = FALSE; + ax.isZero = FALSE; + ax.sign = ( ( a.high & LIT64( 0x8000000000000000 ) ) != 0 ); + expField = ( a.high>>48 ) & 0x7FFF; + ax.sig.a1 = a.low; + ax.sig.a0 = a.high & LIT64( 0x0000FFFFFFFFFFFF ); + if ( expField == 0 ) { + if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) { + ax.isZero = TRUE; + } + else { + expField = 1 - 0x3FFF; + do { + ax.sig = shortShift128Left( ax.sig, 1 ); + --expField; + } while ( ax.sig.a0 < LIT64( 0x0001000000000000 ) ); + ax.exp = expField; + } + } + else if ( expField == 0x7FFF ) { + if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) { + ax.isInf = TRUE; + } + else { + ax.isNaN = TRUE; + } + } + else { + ax.exp = expField - 0x3FFF; + ax.sig.a0 |= LIT64( 0x0001000000000000 ); + } + ax.sig = shortShift128Left( ax.sig, 7 ); + return ax; + +} + +static float128 floatXToFloat128( floatX zx ) +{ + floatX savedZ; + flag isTiny; + int32 expField; + float128 z; + + if ( zx.isZero ) { + z.low = 0; + z.high = zx.sign ? LIT64( 0x8000000000000000 ) : 0; + return z; + } + if ( zx.isInf ) { + z.low = 0; + z.high = + zx.sign ? LIT64( 0xFFFF000000000000 ) + : LIT64( 0x7FFF000000000000 ); + return z; + } + if ( zx.isNaN ) { + z.high = z.low = LIT64( 0xFFFFFFFFFFFFFFFF ); + return z; + } + while ( LIT64( 0x0100000000000000 ) <= zx.sig.a0 ) { + zx.sig = shortShift128RightJamming( zx.sig, 1 ); + ++zx.exp; + } + while ( zx.sig.a0 < LIT64( 0x0080000000000000 ) ) { + zx.sig = shortShift128Left( zx.sig, 1 ); + --zx.exp; + } + savedZ = zx; + isTiny = + ( slow_float_detect_tininess == float_tininess_before_rounding ) + && ( zx.exp + 0x3FFF <= 0 ); + zx = roundFloatXTo113( isTiny, zx ); + expField = zx.exp + 0x3FFF; + if ( 0x7FFF <= expField ) { + slow_float_exception_flags |= + float_flag_overflow | float_flag_inexact; + if ( zx.sign ) { + switch ( slow_float_rounding_mode ) { + case float_round_nearest_even: + case float_round_down: + z.low = 0; + z.high = LIT64( 0xFFFF000000000000 ); + break; + case float_round_to_zero: + case float_round_up: + z.low = LIT64( 0xFFFFFFFFFFFFFFFF ); + z.high = LIT64( 0xFFFEFFFFFFFFFFFF ); + break; + } + } + else { + switch ( slow_float_rounding_mode ) { + case float_round_nearest_even: + case float_round_up: + z.low = 0; + z.high = LIT64( 0x7FFF000000000000 ); + break; + case float_round_to_zero: + case float_round_down: + z.low = LIT64( 0xFFFFFFFFFFFFFFFF ); + z.high = LIT64( 0x7FFEFFFFFFFFFFFF ); + break; + } + } + return z; + } + if ( expField <= 0 ) { + isTiny = TRUE; + zx = savedZ; + expField = zx.exp + 0x3FFF; + if ( expField < -120 ) { + zx.sig.a1 = ( zx.sig.a0 != 0 ) || ( zx.sig.a1 != 0 ); + zx.sig.a0 = 0; + } + else { + while ( expField <= 0 ) { + zx.sig = shortShift128RightJamming( zx.sig, 1 ); + ++expField; + } + } + zx = roundFloatXTo113( isTiny, zx ); + expField = ( LIT64( 0x0080000000000000 ) <= zx.sig.a0 ) ? 1 : 0; + } + zx.sig = shortShift128RightJamming( zx.sig, 7 ); + z.low = zx.sig.a1; + z.high = expField; + z.high <<= 48; + if ( zx.sign ) z.high |= LIT64( 0x8000000000000000 ); + z.high |= zx.sig.a0 & LIT64( 0x0000FFFFFFFFFFFF ); + return z; + +} + +#endif + +static floatX floatXInvalid( void ) +{ + + slow_float_exception_flags |= float_flag_invalid; + return floatXNaN; + +} + +static floatX floatXRoundToInt( floatX ax ) +{ + int32 shiftCount, i; + + if ( ax.isNaN || ax.isInf ) return ax; + shiftCount = 112 - ax.exp; + if ( shiftCount <= 0 ) return ax; + if ( 119 < shiftCount ) { + ax.exp = 112; + ax.sig.a1 = ! ax.isZero; + ax.sig.a0 = 0; + } + else { + while ( 0 < shiftCount ) { + ax.sig = shortShift128RightJamming( ax.sig, 1 ); + ++ax.exp; + --shiftCount; + } + } + ax = roundFloatXTo113( FALSE, ax ); + if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) ax.isZero = TRUE; + return ax; + +} + +static floatX floatXAdd( floatX ax, floatX bx ) +{ + int32 expDiff; + floatX zx; + + if ( ax.isNaN ) return ax; + if ( bx.isNaN ) return bx; + if ( ax.isInf && bx.isInf ) { + if ( ax.sign == bx.sign ) return ax; + return floatXInvalid(); + } + if ( ax.isInf ) return ax; + if ( bx.isInf ) return bx; + if ( ax.isZero && bx.isZero ) { + if ( ax.sign == bx.sign ) return ax; + goto completeCancellation; + } + if ( ( ax.sign != bx.sign ) + && ( ax.exp == bx.exp ) + && eq128( ax.sig, bx.sig ) + ) { + completeCancellation: + return + ( slow_float_rounding_mode == float_round_down ) ? + floatXNegativeZero + : floatXPositiveZero; + } + if ( ax.isZero ) return bx; + if ( bx.isZero ) return ax; + expDiff = ax.exp - bx.exp; + if ( expDiff < 0 ) { + zx = ax; + zx.exp = bx.exp; + if ( expDiff < -120 ) { + zx.sig.a1 = 1; + zx.sig.a0 = 0; + } + else { + while ( expDiff < 0 ) { + zx.sig = shortShift128RightJamming( zx.sig, 1 ); + ++expDiff; + } + } + if ( ax.sign != bx.sign ) zx.sig = neg128( zx.sig ); + zx.sign = bx.sign; + zx.sig = add128( zx.sig, bx.sig ); + } + else { + zx = bx; + zx.exp = ax.exp; + if ( 120 < expDiff ) { + zx.sig.a1 = 1; + zx.sig.a0 = 0; + } + else { + while ( 0 < expDiff ) { + zx.sig = shortShift128RightJamming( zx.sig, 1 ); + --expDiff; + } + } + if ( ax.sign != bx.sign ) zx.sig = neg128( zx.sig ); + zx.sign = ax.sign; + zx.sig = add128( zx.sig, ax.sig ); + } + if ( zx.sig.a0 & LIT64( 0x8000000000000000 ) ) { + zx.sig = neg128( zx.sig ); + zx.sign = ! zx.sign; + } + return zx; + +} + +static floatX floatXMul( floatX ax, floatX bx ) +{ + int8 bitNum; + floatX zx; + + if ( ax.isNaN ) return ax; + if ( bx.isNaN ) return bx; + if ( ax.isInf ) { + if ( bx.isZero ) return floatXInvalid(); + if ( bx.sign ) ax.sign = ! ax.sign; + return ax; + } + if ( bx.isInf ) { + if ( ax.isZero ) return floatXInvalid(); + if ( ax.sign ) bx.sign = ! bx.sign; + return bx; + } + zx = ax; + zx.sign ^= bx.sign; + if ( ax.isZero || bx.isZero ) { + return zx.sign ? floatXNegativeZero : floatXPositiveZero; + } + zx.exp += bx.exp + 1; + zx.sig.a1 = 0; + zx.sig.a0 = 0; + for ( bitNum = 0; bitNum < 119; ++bitNum ) { + if ( bx.sig.a1 & 2 ) zx.sig = add128( zx.sig, ax.sig ); + bx.sig = shortShift128RightJamming( bx.sig, 1 ); + zx.sig = shortShift128RightJamming( zx.sig, 1 ); + } + return zx; + +} + +static floatX floatXDiv( floatX ax, floatX bx ) +{ + bits128X negBSig; + int8 bitNum; + floatX zx; + + if ( ax.isNaN ) return ax; + if ( bx.isNaN ) return bx; + if ( ax.isInf ) { + if ( bx.isInf ) return floatXInvalid(); + if ( bx.sign ) ax.sign = ! ax.sign; + return ax; + } + if ( bx.isZero ) { + if ( ax.isZero ) return floatXInvalid(); + slow_float_exception_flags |= float_flag_divbyzero; + if ( ax.sign ) bx.sign = ! bx.sign; + bx.isZero = FALSE; + bx.isInf = TRUE; + return bx; + } + zx = ax; + zx.sign ^= bx.sign; + if ( ax.isZero || bx.isInf ) { + return zx.sign ? floatXNegativeZero : floatXPositiveZero; + } + zx.exp -= bx.exp + 1; + zx.sig.a1 = 0; + zx.sig.a0 = 0; + negBSig = neg128( bx.sig ); + for ( bitNum = 0; bitNum < 120; ++bitNum ) { + if ( le128( bx.sig, ax.sig ) ) { + zx.sig.a1 |= 1; + ax.sig = add128( ax.sig, negBSig ); + } + ax.sig = shortShift128Left( ax.sig, 1 ); + zx.sig = shortShift128Left( zx.sig, 1 ); + } + if ( ax.sig.a0 || ax.sig.a1 ) zx.sig.a1 |= 1; + return zx; + +} + +static floatX floatXRem( floatX ax, floatX bx ) +{ + bits128X negBSig; + flag lastQuotientBit; + bits128X savedASig; + + if ( ax.isNaN ) return ax; + if ( bx.isNaN ) return bx; + if ( ax.isInf || bx.isZero ) return floatXInvalid(); + if ( ax.isZero || bx.isInf ) return ax; + --bx.exp; + if ( ax.exp < bx.exp ) return ax; + bx.sig = shortShift128Left( bx.sig, 1 ); + negBSig = neg128( bx.sig ); + while ( bx.exp < ax.exp ) { + if ( le128( bx.sig, ax.sig ) ) ax.sig = add128( ax.sig, negBSig ); + ax.sig = shortShift128Left( ax.sig, 1 ); + --ax.exp; + } + lastQuotientBit = le128( bx.sig, ax.sig ); + if ( lastQuotientBit ) ax.sig = add128( ax.sig, negBSig ); + savedASig = ax.sig; + ax.sig = neg128( add128( ax.sig, negBSig ) ); + if ( lt128( ax.sig, savedASig ) ) { + ax.sign = ! ax.sign; + } + else if ( lt128( savedASig, ax.sig ) ) { + ax.sig = savedASig; + } + else { + if ( lastQuotientBit ) { + ax.sign = ! ax.sign; + } + else { + ax.sig = savedASig; + } + } + if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) ax.isZero = TRUE; + return ax; + +} + +static floatX floatXSqrt( floatX ax ) +{ + int8 bitNum; + bits128X bitSig, savedASig; + floatX zx; + + if ( ax.isNaN || ax.isZero ) return ax; + if ( ax.sign ) return floatXInvalid(); + if ( ax.isInf ) return ax; + zx = ax; + zx.exp >>= 1; + if ( ( ax.exp & 1 ) == 0 ) ax.sig = shortShift128RightJamming( ax.sig, 1 ); + zx.sig.a1 = 0; + zx.sig.a0 = 0; + bitSig.a1 = 0; + bitSig.a0 = LIT64( 0x0080000000000000 ); + for ( bitNum = 0; bitNum < 120; ++bitNum ) { + savedASig = ax.sig; + ax.sig = add128( ax.sig, neg128( zx.sig ) ); + ax.sig = shortShift128Left( ax.sig, 1 ); + ax.sig = add128( ax.sig, neg128( bitSig ) ); + if ( ax.sig.a0 & LIT64( 0x8000000000000000 ) ) { + ax.sig = shortShift128Left( savedASig, 1 ); + } + else { + zx.sig.a1 |= bitSig.a1; + zx.sig.a0 |= bitSig.a0; + } + bitSig = shortShift128RightJamming( bitSig, 1 ); + } + if ( ax.sig.a0 || ax.sig.a1 ) zx.sig.a1 |= 1; + return zx; + +} + +static flag floatXEq( floatX ax, floatX bx ) +{ + + if ( ax.isNaN || bx.isNaN ) return FALSE; + if ( ax.isZero && bx.isZero ) return TRUE; + if ( ax.sign != bx.sign ) return FALSE; + if ( ax.isInf || bx.isInf ) return ax.isInf && bx.isInf; + return ( ax.exp == bx.exp ) && eq128( ax.sig, bx.sig ); + +} + +static flag floatXLe( floatX ax, floatX bx ) +{ + + if ( ax.isNaN || bx.isNaN ) return FALSE; + if ( ax.isZero && bx.isZero ) return TRUE; + if ( ax.sign != bx.sign ) return ax.sign; + if ( ax.sign ) { + if ( ax.isInf || bx.isZero ) return TRUE; + if ( bx.isInf || ax.isZero ) return FALSE; + if ( bx.exp < ax.exp ) return TRUE; + if ( ax.exp < bx.exp ) return FALSE; + return le128( bx.sig, ax.sig ); + } + else { + if ( bx.isInf || ax.isZero ) return TRUE; + if ( ax.isInf || bx.isZero ) return FALSE; + if ( ax.exp < bx.exp ) return TRUE; + if ( bx.exp < ax.exp ) return FALSE; + return le128( ax.sig, bx.sig ); + } + +} + +static flag floatXLt( floatX ax, floatX bx ) +{ + + if ( ax.isNaN || bx.isNaN ) return FALSE; + if ( ax.isZero && bx.isZero ) return FALSE; + if ( ax.sign != bx.sign ) return ax.sign; + if ( ax.isInf && bx.isInf ) return FALSE; + if ( ax.sign ) { + if ( ax.isInf || bx.isZero ) return TRUE; + if ( bx.isInf || ax.isZero ) return FALSE; + if ( bx.exp < ax.exp ) return TRUE; + if ( ax.exp < bx.exp ) return FALSE; + return lt128( bx.sig, ax.sig ); + } + else { + if ( bx.isInf || ax.isZero ) return TRUE; + if ( ax.isInf || bx.isZero ) return FALSE; + if ( ax.exp < bx.exp ) return TRUE; + if ( bx.exp < ax.exp ) return FALSE; + return lt128( ax.sig, bx.sig ); + } + +} + +float32 slow_int32_to_float32( int32 a ) +{ + + return floatXToFloat32( int32ToFloatX( a ) ); + +} + +float64 slow_int32_to_float64( int32 a ) +{ + + return floatXToFloat64( int32ToFloatX( a ) ); + +} + +#ifdef FLOATX80 + +floatx80 slow_int32_to_floatx80( int32 a ) +{ + + return floatXToFloatx80( int32ToFloatX( a ) ); + +} + +#endif + +#ifdef FLOAT128 + +float128 slow_int32_to_float128( int32 a ) +{ + + return floatXToFloat128( int32ToFloatX( a ) ); + +} + +#endif + +float32 slow_int64_to_float32( int64 a ) +{ + + return floatXToFloat32( int64ToFloatX( a ) ); + +} + +float64 slow_int64_to_float64( int64 a ) +{ + + return floatXToFloat64( int64ToFloatX( a ) ); + +} + +#ifdef FLOATX80 + +floatx80 slow_int64_to_floatx80( int64 a ) +{ + + return floatXToFloatx80( int64ToFloatX( a ) ); + +} + +#endif + +#ifdef FLOAT128 + +float128 slow_int64_to_float128( int64 a ) +{ + + return floatXToFloat128( int64ToFloatX( a ) ); + +} + +#endif + +int32 slow_float32_to_int32( float32 a ) +{ + + return floatXToInt32( float32ToFloatX( a ) ); + +} + +int32 slow_float32_to_int32_round_to_zero( float32 a ) +{ + int8 savedRoundingMode; + int32 z; + + savedRoundingMode = slow_float_rounding_mode; + slow_float_rounding_mode = float_round_to_zero; + z = floatXToInt32( float32ToFloatX( a ) ); + slow_float_rounding_mode = savedRoundingMode; + return z; + +} + +int64 slow_float32_to_int64( float32 a ) +{ + + return floatXToInt64( float32ToFloatX( a ) ); + +} + +int64 slow_float32_to_int64_round_to_zero( float32 a ) +{ + int8 savedRoundingMode; + int64 z; + + savedRoundingMode = slow_float_rounding_mode; + slow_float_rounding_mode = float_round_to_zero; + z = floatXToInt64( float32ToFloatX( a ) ); + slow_float_rounding_mode = savedRoundingMode; + return z; + +} + +float64 slow_float32_to_float64( float32 a ) +{ + + return floatXToFloat64( float32ToFloatX( a ) ); + +} + +#ifdef FLOATX80 + +floatx80 slow_float32_to_floatx80( float32 a ) +{ + + return floatXToFloatx80( float32ToFloatX( a ) ); + +} + +#endif + +#ifdef FLOAT128 + +float128 slow_float32_to_float128( float32 a ) +{ + + return floatXToFloat128( float32ToFloatX( a ) ); + +} + +#endif + +float32 slow_float32_round_to_int( float32 a ) +{ + + return floatXToFloat32( floatXRoundToInt( float32ToFloatX( a ) ) ); + +} + +float32 slow_float32_add( float32 a, float32 b ) +{ + + return + floatXToFloat32( + floatXAdd( float32ToFloatX( a ), float32ToFloatX( b ) ) ); + +} + +float32 slow_float32_sub( float32 a, float32 b ) +{ + + b ^= 0x80000000; + return + floatXToFloat32( + floatXAdd( float32ToFloatX( a ), float32ToFloatX( b ) ) ); + +} + +float32 slow_float32_mul( float32 a, float32 b ) +{ + + return + floatXToFloat32( + floatXMul( float32ToFloatX( a ), float32ToFloatX( b ) ) ); + +} + +float32 slow_float32_div( float32 a, float32 b ) +{ + + return + floatXToFloat32( + floatXDiv( float32ToFloatX( a ), float32ToFloatX( b ) ) ); + +} + +float32 slow_float32_rem( float32 a, float32 b ) +{ + + return + floatXToFloat32( + floatXRem( float32ToFloatX( a ), float32ToFloatX( b ) ) ); + +} + +float32 slow_float32_sqrt( float32 a ) +{ + + return floatXToFloat32( floatXSqrt( float32ToFloatX( a ) ) ); + +} + +flag slow_float32_eq( float32 a, float32 b ) +{ + + return floatXEq( float32ToFloatX( a ), float32ToFloatX( b ) ); + +} + +flag slow_float32_le( float32 a, float32 b ) +{ + floatX ax, bx; + + ax = float32ToFloatX( a ); + bx = float32ToFloatX( b ); + if ( ax.isNaN || bx.isNaN ) { + slow_float_exception_flags |= float_flag_invalid; + } + return floatXLe( ax, bx ); + +} + +flag slow_float32_lt( float32 a, float32 b ) +{ + floatX ax, bx; + + ax = float32ToFloatX( a ); + bx = float32ToFloatX( b ); + if ( ax.isNaN || bx.isNaN ) { + slow_float_exception_flags |= float_flag_invalid; + } + return floatXLt( ax, bx ); + +} + +flag slow_float32_eq_signaling( float32 a, float32 b ) +{ + floatX ax, bx; + + ax = float32ToFloatX( a ); + bx = float32ToFloatX( b ); + if ( ax.isNaN || bx.isNaN ) { + slow_float_exception_flags |= float_flag_invalid; + } + return floatXEq( ax, bx ); + +} + +flag slow_float32_le_quiet( float32 a, float32 b ) +{ + + return floatXLe( float32ToFloatX( a ), float32ToFloatX( b ) ); + +} + +flag slow_float32_lt_quiet( float32 a, float32 b ) +{ + + return floatXLt( float32ToFloatX( a ), float32ToFloatX( b ) ); + +} + +int32 slow_float64_to_int32( float64 a ) +{ + + return floatXToInt32( float64ToFloatX( a ) ); + +} + +int32 slow_float64_to_int32_round_to_zero( float64 a ) +{ + int8 savedRoundingMode; + int32 z; + + savedRoundingMode = slow_float_rounding_mode; + slow_float_rounding_mode = float_round_to_zero; + z = floatXToInt32( float64ToFloatX( a ) ); + slow_float_rounding_mode = savedRoundingMode; + return z; + +} + +int64 slow_float64_to_int64( float64 a ) +{ + + return floatXToInt64( float64ToFloatX( a ) ); + +} + +int64 slow_float64_to_int64_round_to_zero( float64 a ) +{ + int8 savedRoundingMode; + int64 z; + + savedRoundingMode = slow_float_rounding_mode; + slow_float_rounding_mode = float_round_to_zero; + z = floatXToInt64( float64ToFloatX( a ) ); + slow_float_rounding_mode = savedRoundingMode; + return z; + +} + +float32 slow_float64_to_float32( float64 a ) +{ + + return floatXToFloat32( float64ToFloatX( a ) ); + +} + +#ifdef FLOATX80 + +floatx80 slow_float64_to_floatx80( float64 a ) +{ + + return floatXToFloatx80( float64ToFloatX( a ) ); + +} + +#endif + +#ifdef FLOAT128 + +float128 slow_float64_to_float128( float64 a ) +{ + + return floatXToFloat128( float64ToFloatX( a ) ); + +} + +#endif + +float64 slow_float64_round_to_int( float64 a ) +{ + + return floatXToFloat64( floatXRoundToInt( float64ToFloatX( a ) ) ); + +} + +float64 slow_float64_add( float64 a, float64 b ) +{ + + return + floatXToFloat64( + floatXAdd( float64ToFloatX( a ), float64ToFloatX( b ) ) ); + +} + +float64 slow_float64_sub( float64 a, float64 b ) +{ + + b ^= LIT64( 0x8000000000000000 ); + return + floatXToFloat64( + floatXAdd( float64ToFloatX( a ), float64ToFloatX( b ) ) ); + +} + +float64 slow_float64_mul( float64 a, float64 b ) +{ + + return + floatXToFloat64( + floatXMul( float64ToFloatX( a ), float64ToFloatX( b ) ) ); + +} + +float64 slow_float64_div( float64 a, float64 b ) +{ + + return + floatXToFloat64( + floatXDiv( float64ToFloatX( a ), float64ToFloatX( b ) ) ); + +} + +float64 slow_float64_rem( float64 a, float64 b ) +{ + + return + floatXToFloat64( + floatXRem( float64ToFloatX( a ), float64ToFloatX( b ) ) ); + +} + +float64 slow_float64_sqrt( float64 a ) +{ + + return floatXToFloat64( floatXSqrt( float64ToFloatX( a ) ) ); + +} + +flag slow_float64_eq( float64 a, float64 b ) +{ + + return floatXEq( float64ToFloatX( a ), float64ToFloatX( b ) ); + +} + +flag slow_float64_le( float64 a, float64 b ) +{ + floatX ax, bx; + + ax = float64ToFloatX( a ); + bx = float64ToFloatX( b ); + if ( ax.isNaN || bx.isNaN ) { + slow_float_exception_flags |= float_flag_invalid; + } + return floatXLe( ax, bx ); + +} + +flag slow_float64_lt( float64 a, float64 b ) +{ + floatX ax, bx; + + ax = float64ToFloatX( a ); + bx = float64ToFloatX( b ); + if ( ax.isNaN || bx.isNaN ) { + slow_float_exception_flags |= float_flag_invalid; + } + return floatXLt( ax, bx ); + +} + +flag slow_float64_eq_signaling( float64 a, float64 b ) +{ + floatX ax, bx; + + ax = float64ToFloatX( a ); + bx = float64ToFloatX( b ); + if ( ax.isNaN || bx.isNaN ) { + slow_float_exception_flags |= float_flag_invalid; + } + return floatXEq( ax, bx ); + +} + +flag slow_float64_le_quiet( float64 a, float64 b ) +{ + + return floatXLe( float64ToFloatX( a ), float64ToFloatX( b ) ); + +} + +flag slow_float64_lt_quiet( float64 a, float64 b ) +{ + + return floatXLt( float64ToFloatX( a ), float64ToFloatX( b ) ); + +} + +#ifdef FLOATX80 + +int32 slow_floatx80_to_int32( floatx80 a ) +{ + + return floatXToInt32( floatx80ToFloatX( a ) ); + +} + +int32 slow_floatx80_to_int32_round_to_zero( floatx80 a ) +{ + int8 savedRoundingMode; + int32 z; + + savedRoundingMode = slow_float_rounding_mode; + slow_float_rounding_mode = float_round_to_zero; + z = floatXToInt32( floatx80ToFloatX( a ) ); + slow_float_rounding_mode = savedRoundingMode; + return z; + +} + +int64 slow_floatx80_to_int64( floatx80 a ) +{ + + return floatXToInt64( floatx80ToFloatX( a ) ); + +} + +int64 slow_floatx80_to_int64_round_to_zero( floatx80 a ) +{ + int8 savedRoundingMode; + int64 z; + + savedRoundingMode = slow_float_rounding_mode; + slow_float_rounding_mode = float_round_to_zero; + z = floatXToInt64( floatx80ToFloatX( a ) ); + slow_float_rounding_mode = savedRoundingMode; + return z; + +} + +float32 slow_floatx80_to_float32( floatx80 a ) +{ + + return floatXToFloat32( floatx80ToFloatX( a ) ); + +} + +float64 slow_floatx80_to_float64( floatx80 a ) +{ + + return floatXToFloat64( floatx80ToFloatX( a ) ); + +} + +#ifdef FLOAT128 + +float128 slow_floatx80_to_float128( floatx80 a ) +{ + + return floatXToFloat128( floatx80ToFloatX( a ) ); + +} + +#endif + +floatx80 slow_floatx80_round_to_int( floatx80 a ) +{ + + return floatXToFloatx80( floatXRoundToInt( floatx80ToFloatX( a ) ) ); + +} + +floatx80 slow_floatx80_add( floatx80 a, floatx80 b ) +{ + + return + floatXToFloatx80( + floatXAdd( floatx80ToFloatX( a ), floatx80ToFloatX( b ) ) ); + +} + +floatx80 slow_floatx80_sub( floatx80 a, floatx80 b ) +{ + + b.high ^= 0x8000; + return + floatXToFloatx80( + floatXAdd( floatx80ToFloatX( a ), floatx80ToFloatX( b ) ) ); + +} + +floatx80 slow_floatx80_mul( floatx80 a, floatx80 b ) +{ + + return + floatXToFloatx80( + floatXMul( floatx80ToFloatX( a ), floatx80ToFloatX( b ) ) ); + +} + +floatx80 slow_floatx80_div( floatx80 a, floatx80 b ) +{ + + return + floatXToFloatx80( + floatXDiv( floatx80ToFloatX( a ), floatx80ToFloatX( b ) ) ); + +} + +floatx80 slow_floatx80_rem( floatx80 a, floatx80 b ) +{ + + return + floatXToFloatx80( + floatXRem( floatx80ToFloatX( a ), floatx80ToFloatX( b ) ) ); + +} + +floatx80 slow_floatx80_sqrt( floatx80 a ) +{ + + return floatXToFloatx80( floatXSqrt( floatx80ToFloatX( a ) ) ); + +} + +flag slow_floatx80_eq( floatx80 a, floatx80 b ) +{ + + return floatXEq( floatx80ToFloatX( a ), floatx80ToFloatX( b ) ); + +} + +flag slow_floatx80_le( floatx80 a, floatx80 b ) +{ + floatX ax, bx; + + ax = floatx80ToFloatX( a ); + bx = floatx80ToFloatX( b ); + if ( ax.isNaN || bx.isNaN ) { + slow_float_exception_flags |= float_flag_invalid; + } + return floatXLe( ax, bx ); + +} + +flag slow_floatx80_lt( floatx80 a, floatx80 b ) +{ + floatX ax, bx; + + ax = floatx80ToFloatX( a ); + bx = floatx80ToFloatX( b ); + if ( ax.isNaN || bx.isNaN ) { + slow_float_exception_flags |= float_flag_invalid; + } + return floatXLt( ax, bx ); + +} + +flag slow_floatx80_eq_signaling( floatx80 a, floatx80 b ) +{ + floatX ax, bx; + + ax = floatx80ToFloatX( a ); + bx = floatx80ToFloatX( b ); + if ( ax.isNaN || bx.isNaN ) { + slow_float_exception_flags |= float_flag_invalid; + } + return floatXEq( ax, bx ); + +} + +flag slow_floatx80_le_quiet( floatx80 a, floatx80 b ) +{ + + return floatXLe( floatx80ToFloatX( a ), floatx80ToFloatX( b ) ); + +} + +flag slow_floatx80_lt_quiet( floatx80 a, floatx80 b ) +{ + + return floatXLt( floatx80ToFloatX( a ), floatx80ToFloatX( b ) ); + +} + +#endif + +#ifdef FLOAT128 + +int32 slow_float128_to_int32( float128 a ) +{ + + return floatXToInt32( float128ToFloatX( a ) ); + +} + +int32 slow_float128_to_int32_round_to_zero( float128 a ) +{ + int8 savedRoundingMode; + int32 z; + + savedRoundingMode = slow_float_rounding_mode; + slow_float_rounding_mode = float_round_to_zero; + z = floatXToInt32( float128ToFloatX( a ) ); + slow_float_rounding_mode = savedRoundingMode; + return z; + +} + +int64 slow_float128_to_int64( float128 a ) +{ + + return floatXToInt64( float128ToFloatX( a ) ); + +} + +int64 slow_float128_to_int64_round_to_zero( float128 a ) +{ + int8 savedRoundingMode; + int64 z; + + savedRoundingMode = slow_float_rounding_mode; + slow_float_rounding_mode = float_round_to_zero; + z = floatXToInt64( float128ToFloatX( a ) ); + slow_float_rounding_mode = savedRoundingMode; + return z; + +} + +float32 slow_float128_to_float32( float128 a ) +{ + + return floatXToFloat32( float128ToFloatX( a ) ); + +} + +float64 slow_float128_to_float64( float128 a ) +{ + + return floatXToFloat64( float128ToFloatX( a ) ); + +} + +#ifdef FLOATX80 + +floatx80 slow_float128_to_floatx80( float128 a ) +{ + + return floatXToFloatx80( float128ToFloatX( a ) ); + +} + +#endif + +float128 slow_float128_round_to_int( float128 a ) +{ + + return floatXToFloat128( floatXRoundToInt( float128ToFloatX( a ) ) ); + +} + +float128 slow_float128_add( float128 a, float128 b ) +{ + + return + floatXToFloat128( + floatXAdd( float128ToFloatX( a ), float128ToFloatX( b ) ) ); + +} + +float128 slow_float128_sub( float128 a, float128 b ) +{ + + b.high ^= LIT64( 0x8000000000000000 ); + return + floatXToFloat128( + floatXAdd( float128ToFloatX( a ), float128ToFloatX( b ) ) ); + +} + +float128 slow_float128_mul( float128 a, float128 b ) +{ + + return + floatXToFloat128( + floatXMul( float128ToFloatX( a ), float128ToFloatX( b ) ) ); + +} + +float128 slow_float128_div( float128 a, float128 b ) +{ + + return + floatXToFloat128( + floatXDiv( float128ToFloatX( a ), float128ToFloatX( b ) ) ); + +} + +float128 slow_float128_rem( float128 a, float128 b ) +{ + + return + floatXToFloat128( + floatXRem( float128ToFloatX( a ), float128ToFloatX( b ) ) ); + +} + +float128 slow_float128_sqrt( float128 a ) +{ + + return floatXToFloat128( floatXSqrt( float128ToFloatX( a ) ) ); + +} + +flag slow_float128_eq( float128 a, float128 b ) +{ + + return floatXEq( float128ToFloatX( a ), float128ToFloatX( b ) ); + +} + +flag slow_float128_le( float128 a, float128 b ) +{ + floatX ax, bx; + + ax = float128ToFloatX( a ); + bx = float128ToFloatX( b ); + if ( ax.isNaN || bx.isNaN ) { + slow_float_exception_flags |= float_flag_invalid; + } + return floatXLe( ax, bx ); + +} + +flag slow_float128_lt( float128 a, float128 b ) +{ + floatX ax, bx; + + ax = float128ToFloatX( a ); + bx = float128ToFloatX( b ); + if ( ax.isNaN || bx.isNaN ) { + slow_float_exception_flags |= float_flag_invalid; + } + return floatXLt( ax, bx ); + +} + +flag slow_float128_eq_signaling( float128 a, float128 b ) +{ + floatX ax, bx; + + ax = float128ToFloatX( a ); + bx = float128ToFloatX( b ); + if ( ax.isNaN || bx.isNaN ) { + slow_float_exception_flags |= float_flag_invalid; + } + return floatXEq( ax, bx ); + +} + +flag slow_float128_le_quiet( float128 a, float128 b ) +{ + + return floatXLe( float128ToFloatX( a ), float128ToFloatX( b ) ); + +} + +flag slow_float128_lt_quiet( float128 a, float128 b ) +{ + + return floatXLt( float128ToFloatX( a ), float128ToFloatX( b ) ); + +} + +#endif + diff --git a/tools/test/testfloat/slowfloat.c b/tools/test/testfloat/slowfloat.c new file mode 100644 index 0000000..ea69f82 --- /dev/null +++ b/tools/test/testfloat/slowfloat.c @@ -0,0 +1,35 @@ + +/* +=============================================================================== + +This C source file is part of TestFloat, Release 2a, a package of programs +for testing the correctness of floating-point arithmetic complying to the +IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +#include "milieu.h" +#include "softfloat.h" +#include "slowfloat.h" + +#ifdef BITS64 +#include "slowfloat-64.c" +#else +#include "slowfloat-32.c" +#endif + diff --git a/tools/test/testfloat/slowfloat.h b/tools/test/testfloat/slowfloat.h new file mode 100644 index 0000000..45c6c6b --- /dev/null +++ b/tools/test/testfloat/slowfloat.h @@ -0,0 +1,167 @@ + +/* +=============================================================================== + +This C header file is part of TestFloat, Release 2a, a package of programs +for testing the correctness of floating-point arithmetic complying to the +IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +extern int8 slow_float_rounding_mode; +extern int8 slow_float_exception_flags; +extern int8 slow_float_detect_tininess; +#ifdef FLOATX80 +extern int8 slow_floatx80_rounding_precision; +#endif + +float32 slow_int32_to_float32( int32 ); +float64 slow_int32_to_float64( int32 ); +#ifdef FLOATX80 +floatx80 slow_int32_to_floatx80( int32 ); +#endif +#ifdef FLOAT128 +float128 slow_int32_to_float128( int32 ); +#endif +#ifdef BITS64 +float32 slow_int64_to_float32( int64 ); +float64 slow_int64_to_float64( int64 ); +#ifdef FLOATX80 +floatx80 slow_int64_to_floatx80( int64 ); +#endif +#ifdef FLOAT128 +float128 slow_int64_to_float128( int64 ); +#endif +#endif + +int32 slow_float32_to_int32( float32 ); +int32 slow_float32_to_int32_round_to_zero( float32 ); +#ifdef BITS64 +int64 slow_float32_to_int64( float32 ); +int64 slow_float32_to_int64_round_to_zero( float32 ); +#endif +float64 slow_float32_to_float64( float32 ); +#ifdef FLOATX80 +floatx80 slow_float32_to_floatx80( float32 ); +#endif +#ifdef FLOAT128 +float128 slow_float32_to_float128( float32 ); +#endif + +float32 slow_float32_round_to_int( float32 ); +float32 slow_float32_add( float32, float32 ); +float32 slow_float32_sub( float32, float32 ); +float32 slow_float32_mul( float32, float32 ); +float32 slow_float32_div( float32, float32 ); +float32 slow_float32_rem( float32, float32 ); +float32 slow_float32_sqrt( float32 ); +flag slow_float32_eq( float32, float32 ); +flag slow_float32_le( float32, float32 ); +flag slow_float32_lt( float32, float32 ); +flag slow_float32_eq_signaling( float32, float32 ); +flag slow_float32_le_quiet( float32, float32 ); +flag slow_float32_lt_quiet( float32, float32 ); + +int32 slow_float64_to_int32( float64 ); +int32 slow_float64_to_int32_round_to_zero( float64 ); +#ifdef BITS64 +int64 slow_float64_to_int64( float64 ); +int64 slow_float64_to_int64_round_to_zero( float64 ); +#endif +float32 slow_float64_to_float32( float64 ); +#ifdef FLOATX80 +floatx80 slow_float64_to_floatx80( float64 ); +#endif +#ifdef FLOAT128 +float128 slow_float64_to_float128( float64 ); +#endif + +float64 slow_float64_round_to_int( float64 ); +float64 slow_float64_add( float64, float64 ); +float64 slow_float64_sub( float64, float64 ); +float64 slow_float64_mul( float64, float64 ); +float64 slow_float64_div( float64, float64 ); +float64 slow_float64_rem( float64, float64 ); +float64 slow_float64_sqrt( float64 ); +flag slow_float64_eq( float64, float64 ); +flag slow_float64_le( float64, float64 ); +flag slow_float64_lt( float64, float64 ); +flag slow_float64_eq_signaling( float64, float64 ); +flag slow_float64_le_quiet( float64, float64 ); +flag slow_float64_lt_quiet( float64, float64 ); + +#ifdef FLOATX80 + +int32 slow_floatx80_to_int32( floatx80 ); +int32 slow_floatx80_to_int32_round_to_zero( floatx80 ); +#ifdef BITS64 +int64 slow_floatx80_to_int64( floatx80 ); +int64 slow_floatx80_to_int64_round_to_zero( floatx80 ); +#endif +float32 slow_floatx80_to_float32( floatx80 ); +float64 slow_floatx80_to_float64( floatx80 ); +#ifdef FLOAT128 +float128 slow_floatx80_to_float128( floatx80 ); +#endif + +floatx80 slow_floatx80_round_to_int( floatx80 ); +floatx80 slow_floatx80_add( floatx80, floatx80 ); +floatx80 slow_floatx80_sub( floatx80, floatx80 ); +floatx80 slow_floatx80_mul( floatx80, floatx80 ); +floatx80 slow_floatx80_div( floatx80, floatx80 ); +floatx80 slow_floatx80_rem( floatx80, floatx80 ); +floatx80 slow_floatx80_sqrt( floatx80 ); +flag slow_floatx80_eq( floatx80, floatx80 ); +flag slow_floatx80_le( floatx80, floatx80 ); +flag slow_floatx80_lt( floatx80, floatx80 ); +flag slow_floatx80_eq_signaling( floatx80, floatx80 ); +flag slow_floatx80_le_quiet( floatx80, floatx80 ); +flag slow_floatx80_lt_quiet( floatx80, floatx80 ); + +#endif + +#ifdef FLOAT128 + +int32 slow_float128_to_int32( float128 ); +int32 slow_float128_to_int32_round_to_zero( float128 ); +#ifdef BITS64 +int64 slow_float128_to_int64( float128 ); +int64 slow_float128_to_int64_round_to_zero( float128 ); +#endif +float32 slow_float128_to_float32( float128 ); +float64 slow_float128_to_float64( float128 ); +#ifdef FLOATX80 +floatx80 slow_float128_to_floatx80( float128 ); +#endif + +float128 slow_float128_round_to_int( float128 ); +float128 slow_float128_add( float128, float128 ); +float128 slow_float128_sub( float128, float128 ); +float128 slow_float128_mul( float128, float128 ); +float128 slow_float128_div( float128, float128 ); +float128 slow_float128_rem( float128, float128 ); +float128 slow_float128_sqrt( float128 ); +flag slow_float128_eq( float128, float128 ); +flag slow_float128_le( float128, float128 ); +flag slow_float128_lt( float128, float128 ); +flag slow_float128_eq_signaling( float128, float128 ); +flag slow_float128_le_quiet( float128, float128 ); +flag slow_float128_lt_quiet( float128, float128 ); + +#endif + diff --git a/tools/test/testfloat/sparc64/Makefile b/tools/test/testfloat/sparc64/Makefile new file mode 100644 index 0000000..a24834b --- /dev/null +++ b/tools/test/testfloat/sparc64/Makefile @@ -0,0 +1,105 @@ +# Copyright (c) 2010 by Peter Jeremy <peterjeremy@acm.org> +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../../lib/libc/softfloat/bits64 ${.CURDIR}/.. + +LIBC_DIR= ${.CURDIR}/../../../../lib/libc +EMUFLOAT_DIR= ${LIBC_DIR}/sparc64/fpu + +LN= ln -sf + +# Common source files +SRCS1= fail.c random.c softfloat.c testCases.c testLoops.c writeHex.c + +# Additional common sources to build testfloat/testemufloat +SRCS2= testFunction.c testfloat.c + +# Additional sources to build testemufloat +SRCS3= fpu.c fpu_add.c fpu_compare.c fpu_div.c fpu_emul.S fpu_explode.c \ + fpu_implode.c fpu_mul.c fpu_qp.c fpu_sqrt.c fpu_subr.c fpu_util.c + +# Additional sources to build testfloat +SRCS4= systflags.c systfloat.S systmodes.c + +# Additional sources to build testsoftfloat +SRCS5= slowfloat.c testsoftfloat.c + +SRCS= ${SRCS1} ${SRCS2} ${SRCS3} ${SRCS4} ${SRCS5} + +OBJ_TF= ${SRCS1:R:S/$/.o/g} ${SRCS2:R:S/$/.o/g} ${SRCS4:R:S/$/.o/g} +OBJ_TEF= ${SRCS1:R:S/$/.o/g} ${SRCS2:R:S/$/.o/g} ${SRCS3:R:S/$/.o/g} +OBJ_TSF= ${SRCS1:R:S/$/.o/g} ${SRCS5:R:S/$/.o/g} + +all: testfloat testemufloat testsoftfloat + +CFLAGS+= -I. -I${.CURDIR} -I${.CURDIR}/.. -I${LIBC_DIR}/sparc64/fpu \ + -I${LIBC_DIR}/sparc64/sys -I${LIBC_DIR}/softfloat/bits64 \ + -I${LIBC_DIR}/softfloat + +CLEANFILES+= fpu.c fpu_add.c fpu_compare.c fpu_div.c fpu_emu.h \ + fpu_explode.c fpu_implode.c fpu_mul.c fpu_qp.c fpu_sqrt.c fpu_subr.c \ + ${SRCS:R:S/$/.o/g} testfloat testemufloat testsoftfloat + +testsoftfloat: ${OBJ_TSF} + ${CC} ${CFLAGS} ${LDFLAGS} -o ${.TARGET} ${OBJ_TSF} + +testfloat: ${OBJ_TF} + ${CC} ${CFLAGS} ${LDFLAGS} -o ${.TARGET} ${OBJ_TF} + +testemufloat: ${OBJ_TEF} + ${CC} ${CFLAGS} ${LDFLAGS} -o ${.TARGET} ${OBJ_TEF} + +beforedepend: fpu_emu.h + +# The emulator code needs to be built with a local fpu_reg.h instead of +# the one in ${EMUFLOAT_DIR}. Unfortunately, C preprocessor semantics +# means that a header file in the same directory as the source file +# overrides any alternative header file location. In order to include +# the wanted header file, create symlinks pointing to the real files +# and compile through the symlink. +fpu.c: ${EMUFLOAT_DIR}/fpu.c + ${LN} ${.ALLSRC} ${.TARGET} +fpu_add.c: ${EMUFLOAT_DIR}/fpu_add.c + ${LN} ${.ALLSRC} ${.TARGET} +fpu_compare.c: ${EMUFLOAT_DIR}/fpu_compare.c + ${LN} ${.ALLSRC} ${.TARGET} +fpu_div.c: ${EMUFLOAT_DIR}/fpu_div.c + ${LN} ${.ALLSRC} ${.TARGET} +fpu_emu.h: ${EMUFLOAT_DIR}/fpu_emu.h + ${LN} ${.ALLSRC} ${.TARGET} +fpu_explode.c: ${EMUFLOAT_DIR}/fpu_explode.c + ${LN} ${.ALLSRC} ${.TARGET} +fpu_implode.c: ${EMUFLOAT_DIR}/fpu_implode.c + ${LN} ${.ALLSRC} ${.TARGET} +fpu_mul.c: ${EMUFLOAT_DIR}/fpu_mul.c + ${LN} ${.ALLSRC} ${.TARGET} +fpu_qp.c: ${EMUFLOAT_DIR}/fpu_qp.c + ${LN} ${.ALLSRC} ${.TARGET} +fpu_sqrt.c: ${EMUFLOAT_DIR}/fpu_sqrt.c + ${LN} ${.ALLSRC} ${.TARGET} +fpu_subr.c: ${EMUFLOAT_DIR}/fpu_subr.c + ${LN} ${.ALLSRC} ${.TARGET} + +.include <bsd.prog.mk> diff --git a/tools/test/testfloat/sparc64/fpu_emul.S b/tools/test/testfloat/sparc64/fpu_emul.S new file mode 100644 index 0000000..0872e89 --- /dev/null +++ b/tools/test/testfloat/sparc64/fpu_emul.S @@ -0,0 +1,186 @@ +/*- + * Copyright (c) 2010 by Peter Jeremy <peterjeremy@acm.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <machine/asm.h> +__FBSDID("$FreeBSD$"); + + .section "rodata1",#alloc + .align 8 + + .global insn_int32_to_float32 +insn_int32_to_float32: + fitos %f0,%f0 + + .global insn_int32_to_float64 +insn_int32_to_float64: + fitod %f0,%f0 + + .global insn_int32_to_float128 +insn_int32_to_float128: + fitoq %f0,%f0 + + .global insn_int64_to_float32 +insn_int64_to_float32: + fxtos %f0,%f0 + + .global insn_int64_to_float64 +insn_int64_to_float64: + fxtod %f0,%f0 + + .global insn_int64_to_float128 +insn_int64_to_float128: + fxtoq %f0,%f0 + + .global insn_float32_to_int32_round_to_zero +insn_float32_to_int32_round_to_zero: + fstoi %f0,%f0 + + .global insn_float32_to_int64_round_to_zero +insn_float32_to_int64_round_to_zero: + fstox %f0,%f0 + + .global insn_float32_to_float64 +insn_float32_to_float64: + fstod %f0,%f0 + + .global insn_float32_to_float128 +insn_float32_to_float128: + fstoq %f0,%f0 + + .global insn_float32_add +insn_float32_add: + fadds %f0,%f1,%f0 + + .global insn_float32_sub +insn_float32_sub: + fsubs %f0,%f1,%f0 + + .global insn_float32_mul +insn_float32_mul: + fmuls %f0,%f1,%f0 + + .global insn_float32_div +insn_float32_div: + fdivs %f0,%f1,%f0 + + .global insn_float32_sqrt +insn_float32_sqrt: + fsqrts %f0,%f0 + + .global insn_float32_cmp +insn_float32_cmp: + fcmps %fcc0,%f0,%f1 + + .global insn_float32_cmpe +insn_float32_cmpe: + fcmpes %fcc0,%f0,%f1 + + .global insn_float64_to_int32_round_to_zero +insn_float64_to_int32_round_to_zero: + fdtoi %f0,%f0 + + .global insn_float64_to_int64_round_to_zero +insn_float64_to_int64_round_to_zero: + fdtox %f0,%f0 + + .global insn_float64_to_float32 +insn_float64_to_float32: + fdtos %f0,%f0 + + .global insn_float64_to_float128 +insn_float64_to_float128: + fdtoq %f0,%f0 + + .global insn_float64_add +insn_float64_add: + faddd %f0,%f2,%f0 + + .global insn_float64_sub +insn_float64_sub: + fsubd %f0,%f2,%f0 + + .global insn_float64_mul +insn_float64_mul: + fmuld %f0,%f2,%f0 + + .global insn_float64_div +insn_float64_div: + fdivd %f0,%f2,%f0 + + .global insn_float64_sqrt +insn_float64_sqrt: + fsqrtd %f0,%f0 + + .global insn_float64_cmp +insn_float64_cmp: + fcmpd %fcc0,%f0,%f2 + + .global insn_float64_cmpe +insn_float64_cmpe: + fcmped %fcc0,%f0,%f2 + + .global insn_float128_to_int32_round_to_zero +insn_float128_to_int32_round_to_zero: + fqtoi %f0,%f0 + + .global insn_float128_to_int64_round_to_zero +insn_float128_to_int64_round_to_zero: + fqtox %f0,%f0 + + .global insn_float128_to_float32 +insn_float128_to_float32: + fqtos %f0,%f0 + + .global insn_float128_to_float64 +insn_float128_to_float64: + fqtod %f0,%f0 + + .global insn_float128_add +insn_float128_add: + faddq %f0,%f4,%f0 + + .global insn_float128_sub +insn_float128_sub: + fsubq %f0,%f4,%f0 + + .global insn_float128_mul +insn_float128_mul: + fmulq %f0,%f4,%f0 + + .global insn_float128_div +insn_float128_div: + fdivq %f0,%f4,%f0 + + .global insn_float128_sqrt +insn_float128_sqrt: + fsqrtq %f0,%f0 + + .global insn_float128_cmp +insn_float128_cmp: + fcmpq %fcc0,%f0,%f4 + + .global insn_float128_cmpe +insn_float128_cmpe: + fcmpeq %fcc0,%f0,%f4 diff --git a/tools/test/testfloat/sparc64/fpu_reg.h b/tools/test/testfloat/sparc64/fpu_reg.h new file mode 100644 index 0000000..76f7244 --- /dev/null +++ b/tools/test/testfloat/sparc64/fpu_reg.h @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 2010 by Peter Jeremy <peterjeremy@acm.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _TESTFLOAT_SPARC64_FPU_REG_H_ +#define _TESTFLOAT_SPARC64_FPU_REG_H_ + +#include <sys/types.h> +extern u_int32_t __fpreg[64]; + +static __inline u_int32_t +__fpu_getreg(int r) +{ + + return (__fpreg[r]); +} + +static __inline u_int64_t +__fpu_getreg64(int r) +{ + + return ((u_int64_t)__fpreg[r] << 32 | (u_int64_t)__fpreg[r + 1]); +} + +static __inline void +__fpu_setreg(int r, u_int32_t v) +{ + + __fpreg[r] = v; +} + +static __inline void +__fpu_setreg64(int r, u_int64_t v) +{ + + __fpreg[r] = (u_int32_t)(v >> 32); + __fpreg[r + 1] = (u_int32_t)v; +} + +#endif /* _TESTFLOAT_SPARC64_FPU_REG_H_ */ diff --git a/tools/test/testfloat/sparc64/fpu_util.c b/tools/test/testfloat/sparc64/fpu_util.c new file mode 100644 index 0000000..1b766e0 --- /dev/null +++ b/tools/test/testfloat/sparc64/fpu_util.c @@ -0,0 +1,706 @@ +/*- + * Copyright (c) 2010 by Peter Jeremy <peterjeremy@acm.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> + +#include <math.h> +#include <stdio.h> +#include <stdlib.h> + +#include "__sparc_utrap_private.h" +#include "fpu_extern.h" +#include "fpu_reg.h" + +static u_long ireg[32]; + +void +__utrap_panic(const char *msg) +{ + + fprintf(stderr, "panic: %s\n", msg); + exit(1); +} + +void __utrap_write(const char *msg) +{ + + fprintf(stderr, "%s", msg); +} + +u_long +__emul_fetch_reg(struct utrapframe *uf, int reg) +{ + + return (ireg[reg]); +} + +typedef unsigned char int8; +typedef unsigned int int32; +typedef unsigned long int64; +typedef unsigned int float32; +typedef unsigned long float64; +typedef struct { + unsigned long high, low; +} float128; +typedef unsigned long flag; + +struct utrapframe utf; + +u_int32_t __fpreg[64]; + +static __inline float128 +__fpu_getreg128(int r) +{ + float128 v; + + v.high = ((u_int64_t)__fpreg[r] << 32 | (u_int64_t)__fpreg[r + 1]); + v.low = ((u_int64_t)__fpreg[r + 2] << 32 | (u_int64_t)__fpreg[r + 3]); + return (v); +} + +static __inline void +__fpu_setreg128(int r, float128 v) +{ + + __fpreg[r] = (u_int32_t)(v.high >> 32); + __fpreg[r + 1] = (u_int32_t)v.high; + __fpreg[r + 2] = (u_int32_t)(v.low >> 32); + __fpreg[r + 3] = (u_int32_t)v.low; +} + +/* +------------------------------------------------------------------------------- +Clears the system's IEC/IEEE floating-point exception flags. Returns the +previous value of the flags. +------------------------------------------------------------------------------- +*/ +#include <fenv.h> +#include <ieeefp.h> + +int8 syst_float_flags_clear(void) +{ + int32 flags; + + flags = (utf.uf_fsr & FE_ALL_EXCEPT) >> 5; + utf.uf_fsr &= ~(u_long)FE_ALL_EXCEPT; + return (flags); +} + +static void +emul_trap(const u_int *insn, u_long mask) +{ + u_int32_t savreg[64]; + int i; + + for (i = 0; i < 64; i++) + savreg[i] = __fpreg[i]; + + utf.uf_fsr = (utf.uf_fsr & ~FSR_FTT_MASK) | + (FSR_FTT_UNFIN << FSR_FTT_SHIFT); + utf.uf_pc = (u_long)insn; + if (__fpu_exception(&utf) == 0) + __asm("stx %%fsr,%0" : "=m" (utf.uf_fsr)); + + for (i = 0; i < 64; i++) { + if (!(mask & (1UL << i)) && savreg[i] != __fpreg[i]) { + fprintf(stderr, "### %2d %08x != %08x\n", + i, savreg[i], __fpreg[i]); + } + } +} + +extern u_int insn_int32_to_float32; +extern u_int insn_int32_to_float64; +extern u_int insn_int32_to_float128; +extern u_int insn_int64_to_float32; +extern u_int insn_int64_to_float64; +extern u_int insn_int64_to_float128; +extern u_int insn_float32_to_int32_round_to_zero; +extern u_int insn_float32_to_int64_round_to_zero; +extern u_int insn_float32_to_float64; +extern u_int insn_float32_to_float128; +extern u_int insn_float32_add; +extern u_int insn_float32_sub; +extern u_int insn_float32_mul; +extern u_int insn_float32_div; +extern u_int insn_float32_sqrt; +extern u_int insn_float32_cmp; +extern u_int insn_float32_cmpe; +extern u_int insn_float64_to_int32_round_to_zero; +extern u_int insn_float64_to_int64_round_to_zero; +extern u_int insn_float64_to_float32; +extern u_int insn_float64_to_float128; +extern u_int insn_float64_add; +extern u_int insn_float64_sub; +extern u_int insn_float64_mul; +extern u_int insn_float64_div; +extern u_int insn_float64_sqrt; +extern u_int insn_float64_cmp; +extern u_int insn_float64_cmpe; +extern u_int insn_float128_to_int32_round_to_zero; +extern u_int insn_float128_to_int64_round_to_zero; +extern u_int insn_float128_to_float32; +extern u_int insn_float128_to_float64; +extern u_int insn_float128_add; +extern u_int insn_float128_sub; +extern u_int insn_float128_mul; +extern u_int insn_float128_div; +extern u_int insn_float128_sqrt; +extern u_int insn_float128_cmp; +extern u_int insn_float128_cmpe; + +float32 +syst_int32_to_float32(int32 a) +{ + + __fpu_setreg(0, a); + emul_trap(&insn_int32_to_float32, 0x1UL); + return (__fpu_getreg(0)); +} + +float64 +syst_int32_to_float64(int32 a) +{ + + __fpu_setreg(0, a); + emul_trap(&insn_int32_to_float64, 0x3UL); + return (__fpu_getreg64(0)); +} + +float128 +syst_int32_to_float128(int32 a) +{ + + __fpu_setreg(0, a); + emul_trap(&insn_int32_to_float128, 0xfUL); + return (__fpu_getreg128(0)); +} + +float32 +syst_int64_to_float32(int64 a) +{ + + __fpu_setreg64(0, a); + emul_trap(&insn_int64_to_float32, 0x1UL); + return (__fpu_getreg(0)); +} + +float64 +syst_int64_to_float64(int64 a) +{ + + __fpu_setreg64(0, a); + emul_trap(&insn_int64_to_float64, 0x3UL); + return (__fpu_getreg64(0)); +} + + +float128 +syst_int64_to_float128(int64 a) +{ + + __fpu_setreg64(0, a); + emul_trap(&insn_int64_to_float128, 0xfUL); + return (__fpu_getreg128(0)); +} + +int32 +syst_float32_to_int32_round_to_zero(float32 a) +{ + + __fpu_setreg(0, a); + emul_trap(&insn_float32_to_int32_round_to_zero, 0x1UL); + return (__fpu_getreg(0)); +} + +int64 +syst_float32_to_int64_round_to_zero(float32 a) +{ + + __fpu_setreg(0, a); + emul_trap(&insn_float32_to_int64_round_to_zero, 0x3UL); + return (__fpu_getreg64(0)); +} + +float64 +syst_float32_to_float64(float32 a) +{ + + __fpu_setreg(0, a); + emul_trap(&insn_float32_to_float64, 0x3UL); + return (__fpu_getreg64(0)); +} + +float128 +syst_float32_to_float128(float32 a) +{ + + __fpu_setreg(0, a); + emul_trap(&insn_float32_to_float128, 0xfUL); + return (__fpu_getreg128(0)); +} + +float32 +syst_float32_add(float32 a, float32 b) +{ + + __fpu_setreg(0, a); + __fpu_setreg(1, b); + emul_trap(&insn_float32_add, 0x1UL); + return (__fpu_getreg(0)); +} + +float32 +syst_float32_sub(float32 a, float32 b) +{ + + __fpu_setreg(0, a); + __fpu_setreg(1, b); + emul_trap(&insn_float32_sub, 0x1UL); + return (__fpu_getreg(0)); +} + +float32 +syst_float32_mul(float32 a, float32 b) +{ + + __fpu_setreg(0, a); + __fpu_setreg(1, b); + emul_trap(&insn_float32_mul, 0x1UL); + return (__fpu_getreg(0)); +} + +float32 +syst_float32_div(float32 a, float32 b) +{ + + __fpu_setreg(0, a); + __fpu_setreg(1, b); + emul_trap(&insn_float32_div, 0x1UL); + return (__fpu_getreg(0)); +} + +float32 +syst_float32_sqrt(float32 a) +{ + + __fpu_setreg(0, a); + emul_trap(&insn_float32_sqrt, 0x1UL); + return (__fpu_getreg(0)); +} + +flag syst_float32_eq(float32 a, float32 b) +{ + u_long r; + + __fpu_setreg(0, a); + __fpu_setreg(1, b); + emul_trap(&insn_float32_cmp, 0x0UL); + __asm __volatile("mov 0,%0; move %%fcc0,1,%0" : "=r" (r)); + return (r); +} + +flag syst_float32_le(float32 a, float32 b) +{ + u_long r; + + __fpu_setreg(0, a); + __fpu_setreg(1, b); + emul_trap(&insn_float32_cmpe, 0x0UL); + __asm __volatile("mov 0,%0; movle %%fcc0,1,%0" : "=r" (r)); + return (r); +} + +flag syst_float32_lt(float32 a, float32 b) +{ + u_long r; + + __fpu_setreg(0, a); + __fpu_setreg(1, b); + emul_trap(&insn_float32_cmpe, 0x0UL); + __asm __volatile("mov 0,%0; movl %%fcc0,1,%0" : "=r" (r)); + return (r); +} + +flag syst_float32_eq_signaling(float32 a, float32 b) +{ + u_long r; + + __fpu_setreg(0, a); + __fpu_setreg(1, b); + emul_trap(&insn_float32_cmpe, 0x0UL); + __asm __volatile("mov 0,%0; move %%fcc0,1,%0" : "=r" (r)); + return (r); +} + +flag syst_float32_le_quiet(float32 a, float32 b) +{ + u_long r; + + __fpu_setreg(0, a); + __fpu_setreg(1, b); + emul_trap(&insn_float32_cmp, 0x0UL); + __asm __volatile("mov 0,%0; movle %%fcc0,1,%0" : "=r" (r)); + return (r); +} + +flag syst_float32_lt_quiet(float32 a, float32 b) +{ + u_long r; + + __fpu_setreg(0, a); + __fpu_setreg(1, b); + emul_trap(&insn_float32_cmp, 0x0UL); + __asm __volatile("mov 0,%0; movl %%fcc0,1,%0" : "=r" (r)); + return (r); +} + +int32 +syst_float64_to_int32_round_to_zero(float64 a) +{ + + __fpu_setreg64(0, a); + emul_trap(&insn_float64_to_int32_round_to_zero, 0x1UL); + return (__fpu_getreg(0)); +} + +int64 +syst_float64_to_int64_round_to_zero(float64 a) +{ + + __fpu_setreg64(0, a); + emul_trap(&insn_float64_to_int64_round_to_zero, 0x3UL); + return (__fpu_getreg64(0)); +} + +float32 +syst_float64_to_float32(float64 a) +{ + + __fpu_setreg64(0, a); + emul_trap(&insn_float64_to_float32, 0x1UL); + return (__fpu_getreg(0)); +} + +float128 +syst_float64_to_float128(float64 a) +{ + + __fpu_setreg64(0, a); + emul_trap(&insn_float64_to_float128, 0xfUL); + return (__fpu_getreg128(0)); +} + +float64 +syst_float64_add(float64 a, float64 b) +{ + + __fpu_setreg64(0, a); + __fpu_setreg64(2, b); + emul_trap(&insn_float64_add, 0x3UL); + return (__fpu_getreg64(0)); +} + +float64 +syst_float64_sub(float64 a, float64 b) +{ + + __fpu_setreg64(0, a); + __fpu_setreg64(2, b); + emul_trap(&insn_float64_sub, 0x3UL); + return (__fpu_getreg64(0)); +} + +float64 +syst_float64_mul(float64 a, float64 b) +{ + + __fpu_setreg64(0, a); + __fpu_setreg64(2, b); + emul_trap(&insn_float64_mul, 0x3UL); + return (__fpu_getreg64(0)); +} + +float64 +syst_float64_div(float64 a, float64 b) +{ + + __fpu_setreg64(0, a); + __fpu_setreg64(2, b); + emul_trap(&insn_float64_div, 0x3UL); + return (__fpu_getreg64(0)); +} + +float64 +syst_float64_sqrt(float64 a) +{ + + __fpu_setreg64(0, a); + emul_trap(&insn_float64_sqrt, 0x3UL); + return (__fpu_getreg64(0)); +} + +flag syst_float64_eq(float64 a, float64 b) +{ + u_long r; + + __fpu_setreg64(0, a); + __fpu_setreg64(2, b); + emul_trap(&insn_float64_cmp, 0x0UL); + __asm __volatile("mov 0,%0; move %%fcc0,1,%0" : "=r" (r)); + return (r); +} + +flag syst_float64_le(float64 a, float64 b) +{ + u_long r; + + __fpu_setreg64(0, a); + __fpu_setreg64(2, b); + emul_trap(&insn_float64_cmpe, 0x0UL); + __asm __volatile("mov 0,%0; movle %%fcc0,1,%0" : "=r" (r)); + return (r); +} + +flag syst_float64_lt(float64 a, float64 b) +{ + u_long r; + + __fpu_setreg64(0, a); + __fpu_setreg64(2, b); + emul_trap(&insn_float64_cmpe, 0x0UL); + __asm __volatile("mov 0,%0; movl %%fcc0,1,%0" : "=r" (r)); + return (r); +} + +flag syst_float64_eq_signaling(float64 a, float64 b) +{ + u_long r; + + __fpu_setreg64(0, a); + __fpu_setreg64(2, b); + emul_trap(&insn_float64_cmpe, 0x0UL); + __asm __volatile("mov 0,%0; move %%fcc0,1,%0" : "=r" (r)); + return (r); +} + +flag syst_float64_le_quiet(float64 a, float64 b) +{ + u_long r; + + __fpu_setreg64(0, a); + __fpu_setreg64(2, b); + emul_trap(&insn_float64_cmp, 0x0UL); + __asm __volatile("mov 0,%0; movle %%fcc0,1,%0" : "=r" (r)); + return (r); +} + +flag syst_float64_lt_quiet(float64 a, float64 b) +{ + u_long r; + + __fpu_setreg64(0, a); + __fpu_setreg64(2, b); + emul_trap(&insn_float64_cmp, 0x0UL); + __asm __volatile("mov 0,%0; movl %%fcc0,1,%0" : "=r" (r)); + return (r); +} + +int32 +syst_float128_to_int32_round_to_zero(float128 a) +{ + + __fpu_setreg128(0, a); + emul_trap(&insn_float128_to_int32_round_to_zero, 0x1UL); + return (__fpu_getreg(0)); +} + +int64 +syst_float128_to_int64_round_to_zero(float128 a) +{ + + __fpu_setreg128(0, a); + emul_trap(&insn_float128_to_int64_round_to_zero, 0x3UL); + return (__fpu_getreg64(0)); +} + +float32 +syst_float128_to_float32(float128 a) +{ + + __fpu_setreg128(0, a); + emul_trap(&insn_float128_to_float32, 0x1UL); + return (__fpu_getreg(0)); +} + +float64 +syst_float128_to_float64(float128 a) +{ + + __fpu_setreg128(0, a); + emul_trap(&insn_float128_to_float64, 0x3UL); + return (__fpu_getreg64(0)); +} + +float128 +syst_float128_add(float128 a, float128 b) +{ + + __fpu_setreg128(0, a); + __fpu_setreg128(4, b); + emul_trap(&insn_float128_add, 0xfUL); + return (__fpu_getreg128(0)); +} + +float128 +syst_float128_sub(float128 a, float128 b) +{ + + __fpu_setreg128(0, a); + __fpu_setreg128(4, b); + emul_trap(&insn_float128_sub, 0xfUL); + return (__fpu_getreg128(0)); +} + +float128 +syst_float128_mul(float128 a, float128 b) +{ + + __fpu_setreg128(0, a); + __fpu_setreg128(4, b); + emul_trap(&insn_float128_mul, 0xfUL); + return (__fpu_getreg128(0)); +} + +float128 +syst_float128_div(float128 a, float128 b) +{ + + __fpu_setreg128(0, a); + __fpu_setreg128(4, b); + emul_trap(&insn_float128_div, 0xfUL); + return (__fpu_getreg128(0)); +} + +float128 +syst_float128_sqrt(float128 a) +{ + + __fpu_setreg128(0, a); + emul_trap(&insn_float128_sqrt, 0xfUL); + return (__fpu_getreg128(0)); +} + +flag syst_float128_eq(float128 a, float128 b) +{ + u_long r; + + __fpu_setreg128(0, a); + __fpu_setreg128(4, b); + emul_trap(&insn_float128_cmp, 0x0UL); + __asm __volatile("mov 0,%0; move %%fcc0,1,%0" : "=r" (r)); + return (r); +} + +flag syst_float128_le(float128 a, float128 b) +{ + u_long r; + + __fpu_setreg128(0, a); + __fpu_setreg128(4, b); + emul_trap(&insn_float128_cmpe, 0x0UL); + __asm __volatile("mov 0,%0; movle %%fcc0,1,%0" : "=r" (r)); + return (r); +} + +flag syst_float128_lt(float128 a, float128 b) +{ + u_long r; + + __fpu_setreg128(0, a); + __fpu_setreg128(4, b); + emul_trap(&insn_float128_cmpe, 0x0UL); + __asm __volatile("mov 0,%0; movl %%fcc0,1,%0" : "=r" (r)); + return (r); +} + +flag syst_float128_eq_signaling(float128 a, float128 b) +{ + u_long r; + + __fpu_setreg128(0, a); + __fpu_setreg128(4, b); + emul_trap(&insn_float128_cmpe, 0x0UL); + __asm __volatile("mov 0,%0; move %%fcc0,1,%0" : "=r" (r)); + return (r); +} + +flag syst_float128_le_quiet(float128 a, float128 b) +{ + u_long r; + + __fpu_setreg128(0, a); + __fpu_setreg128(4, b); + emul_trap(&insn_float128_cmp, 0x0UL); + __asm __volatile("mov 0,%0; movle %%fcc0,1,%0" : "=r" (r)); + return (r); +} + +flag syst_float128_lt_quiet(float128 a, float128 b) +{ + u_long r; + + __fpu_setreg128(0, a); + __fpu_setreg128(4, b); + emul_trap(&insn_float128_cmp, 0x0UL); + __asm __volatile("mov 0,%0; movl %%fcc0,1,%0" : "=r" (r)); + return (r); +} + + +/* +------------------------------------------------------------------------------- +Sets the system's IEC/IEEE floating-point rounding mode. +------------------------------------------------------------------------------- +*/ +void syst_float_set_rounding_mode(int8 roundingMode) +{ + + utf.uf_fsr &= ~FSR_RD_MASK; + utf.uf_fsr |= FSR_RD((unsigned int)roundingMode & 0x03); +} + +/* +------------------------------------------------------------------------------- +Does nothing. +------------------------------------------------------------------------------- +*/ +void syst_float_set_rounding_precision(int8 precision) +{ + +} diff --git a/tools/test/testfloat/sparc64/libc_private.h b/tools/test/testfloat/sparc64/libc_private.h new file mode 100644 index 0000000..5e7d1bc --- /dev/null +++ b/tools/test/testfloat/sparc64/libc_private.h @@ -0,0 +1,30 @@ +/*- + * Copyright (c) 2010 by Peter Jeremy <peterjeremy@acm.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ +/* + * This file has no content and is solely to satisfy a #include in + * the FP emulator code. + */ diff --git a/tools/test/testfloat/sparc64/milieu.h b/tools/test/testfloat/sparc64/milieu.h new file mode 100644 index 0000000..26491d1 --- /dev/null +++ b/tools/test/testfloat/sparc64/milieu.h @@ -0,0 +1,56 @@ +#ifndef TESTFLOAT_SPARC64_MILIEU_H_ +#define TESTFLOAT_SPARC64_MILIEU_H_ + +/* +=============================================================================== + +This C header file is part of TestFloat, Release 2a, a package of programs +for testing the correctness of floating-point arithmetic complying to the +IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +/* $FreeBSD$ */ + +/* +------------------------------------------------------------------------------- +Include common integer types and flags. +------------------------------------------------------------------------------- +*/ +#include "sparc64.h" + +/* +------------------------------------------------------------------------------- +If the `BITS64' macro is defined by the processor header file but the +version of SoftFloat being used/tested is the 32-bit one (`bits32'), the +`BITS64' macro must be undefined here. +------------------------------------------------------------------------------- +#undef BITS64 +*/ + +/* +------------------------------------------------------------------------------- +Symbolic Boolean literals. +------------------------------------------------------------------------------- +*/ +enum { + FALSE = 0, + TRUE = 1 +}; + +#endif diff --git a/tools/test/testfloat/sparc64/namespace.h b/tools/test/testfloat/sparc64/namespace.h new file mode 100644 index 0000000..5e7d1bc --- /dev/null +++ b/tools/test/testfloat/sparc64/namespace.h @@ -0,0 +1,30 @@ +/*- + * Copyright (c) 2010 by Peter Jeremy <peterjeremy@acm.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ +/* + * This file has no content and is solely to satisfy a #include in + * the FP emulator code. + */ diff --git a/tools/test/testfloat/sparc64/softfloat.h b/tools/test/testfloat/sparc64/softfloat.h new file mode 100644 index 0000000..f804b9c --- /dev/null +++ b/tools/test/testfloat/sparc64/softfloat.h @@ -0,0 +1,267 @@ +#ifndef TESTFLOAT_SPARC64_SOFTFLOAT_H +#define TESTFLOAT_SPARC64_SOFTFLOAT_H + +/*============================================================================ + +This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic +Package, Release 2b. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. + +=============================================================================*/ + +/* $FreeBSD$ */ + +#include <machine/ieeefp.h> + +/*---------------------------------------------------------------------------- +| The macro `FLOATX80' must be defined to enable the extended double-precision +| floating-point format `floatx80'. If this macro is not defined, the +| `floatx80' type will not be defined, and none of the functions that either +| input or output the `floatx80' type will be defined. The same applies to +| the `FLOAT128' macro and the quadruple-precision format `float128'. +*----------------------------------------------------------------------------*/ +#define FLOATX80 +#define FLOAT128 + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE floating-point types. +*----------------------------------------------------------------------------*/ +typedef unsigned int float32; +typedef unsigned long float64; +#ifdef FLOATX80 +typedef struct { + unsigned short high; + unsigned long low; +} floatx80; +#endif +#ifdef FLOAT128 +typedef struct { + unsigned long high, low; +} float128; +#endif + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE floating-point underflow tininess-detection mode. +*----------------------------------------------------------------------------*/ +extern int float_detect_tininess; +enum { + float_tininess_after_rounding = 0, + float_tininess_before_rounding = 1 +}; + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE floating-point rounding mode. +*----------------------------------------------------------------------------*/ +extern fp_rnd_t float_rounding_mode; +enum { + float_round_nearest_even = 0, + float_round_to_zero = 1, + float_round_up = 2, + float_round_down = 3 +}; + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE floating-point exception flags. +*----------------------------------------------------------------------------*/ +typedef int fp_except; +extern fp_except float_exception_flags; +enum { + float_flag_inexact = 1, + float_flag_divbyzero = 2, + float_flag_underflow = 4, + float_flag_overflow = 8, + float_flag_invalid = 16 +}; + +/*---------------------------------------------------------------------------- +| Routine to raise any or all of the software IEC/IEEE floating-point +| exception flags. +*----------------------------------------------------------------------------*/ +void float_raise( int ); + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE integer-to-floating-point conversion routines. +*----------------------------------------------------------------------------*/ +float32 int32_to_float32( int ); +float64 int32_to_float64( int ); +#ifdef FLOATX80 +floatx80 int32_to_floatx80( int ); +#endif +#ifdef FLOAT128 +float128 int32_to_float128( int ); +#endif +float32 int64_to_float32( long ); +float64 int64_to_float64( long ); +#ifdef FLOATX80 +floatx80 int64_to_floatx80( long ); +#endif +#ifdef FLOAT128 +float128 int64_to_float128( long ); +#endif + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE single-precision conversion routines. +*----------------------------------------------------------------------------*/ +int float32_to_int32( float32 ); +int float32_to_int32_round_to_zero( float32 ); +long float32_to_int64( float32 ); +long float32_to_int64_round_to_zero( float32 ); +float64 float32_to_float64( float32 ); +#ifdef FLOATX80 +floatx80 float32_to_floatx80( float32 ); +#endif +#ifdef FLOAT128 +float128 float32_to_float128( float32 ); +#endif + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE single-precision operations. +*----------------------------------------------------------------------------*/ +float32 float32_round_to_int( float32 ); +float32 float32_add( float32, float32 ); +float32 float32_sub( float32, float32 ); +float32 float32_mul( float32, float32 ); +float32 float32_div( float32, float32 ); +float32 float32_rem( float32, float32 ); +float32 float32_sqrt( float32 ); +int float32_eq( float32, float32 ); +int float32_le( float32, float32 ); +int float32_lt( float32, float32 ); +int float32_eq_signaling( float32, float32 ); +int float32_le_quiet( float32, float32 ); +int float32_lt_quiet( float32, float32 ); +int float32_is_signaling_nan( float32 ); + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE double-precision conversion routines. +*----------------------------------------------------------------------------*/ +int float64_to_int32( float64 ); +int float64_to_int32_round_to_zero( float64 ); +long float64_to_int64( float64 ); +long float64_to_int64_round_to_zero( float64 ); +float32 float64_to_float32( float64 ); +#ifdef FLOATX80 +floatx80 float64_to_floatx80( float64 ); +#endif +#ifdef FLOAT128 +float128 float64_to_float128( float64 ); +#endif + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE double-precision operations. +*----------------------------------------------------------------------------*/ +float64 float64_round_to_int( float64 ); +float64 float64_add( float64, float64 ); +float64 float64_sub( float64, float64 ); +float64 float64_mul( float64, float64 ); +float64 float64_div( float64, float64 ); +float64 float64_rem( float64, float64 ); +float64 float64_sqrt( float64 ); +int float64_eq( float64, float64 ); +int float64_le( float64, float64 ); +int float64_lt( float64, float64 ); +int float64_eq_signaling( float64, float64 ); +int float64_le_quiet( float64, float64 ); +int float64_lt_quiet( float64, float64 ); +int float64_is_signaling_nan( float64 ); + +#ifdef FLOATX80 + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE extended double-precision conversion routines. +*----------------------------------------------------------------------------*/ +int floatx80_to_int32( floatx80 ); +int floatx80_to_int32_round_to_zero( floatx80 ); +long floatx80_to_int64( floatx80 ); +long floatx80_to_int64_round_to_zero( floatx80 ); +float32 floatx80_to_float32( floatx80 ); +float64 floatx80_to_float64( floatx80 ); +#ifdef FLOAT128 +float128 floatx80_to_float128( floatx80 ); +#endif + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE extended double-precision rounding precision. Valid +| values are 32, 64, and 80. +*----------------------------------------------------------------------------*/ +extern int floatx80_rounding_precision; + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE extended double-precision operations. +*----------------------------------------------------------------------------*/ +floatx80 floatx80_round_to_int( floatx80 ); +floatx80 floatx80_add( floatx80, floatx80 ); +floatx80 floatx80_sub( floatx80, floatx80 ); +floatx80 floatx80_mul( floatx80, floatx80 ); +floatx80 floatx80_div( floatx80, floatx80 ); +floatx80 floatx80_rem( floatx80, floatx80 ); +floatx80 floatx80_sqrt( floatx80 ); +int floatx80_eq( floatx80, floatx80 ); +int floatx80_le( floatx80, floatx80 ); +int floatx80_lt( floatx80, floatx80 ); +int floatx80_eq_signaling( floatx80, floatx80 ); +int floatx80_le_quiet( floatx80, floatx80 ); +int floatx80_lt_quiet( floatx80, floatx80 ); +int floatx80_is_signaling_nan( floatx80 ); + +#endif + +#ifdef FLOAT128 + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE quadruple-precision conversion routines. +*----------------------------------------------------------------------------*/ +int float128_to_int32( float128 ); +int float128_to_int32_round_to_zero( float128 ); +long float128_to_int64( float128 ); +long float128_to_int64_round_to_zero( float128 ); +float32 float128_to_float32( float128 ); +float64 float128_to_float64( float128 ); +#ifdef FLOATX80 +floatx80 float128_to_floatx80( float128 ); +#endif + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE quadruple-precision operations. +*----------------------------------------------------------------------------*/ +float128 float128_round_to_int( float128 ); +float128 float128_add( float128, float128 ); +float128 float128_sub( float128, float128 ); +float128 float128_mul( float128, float128 ); +float128 float128_div( float128, float128 ); +float128 float128_rem( float128, float128 ); +float128 float128_sqrt( float128 ); +int float128_eq( float128, float128 ); +int float128_le( float128, float128 ); +int float128_lt( float128, float128 ); +int float128_eq_signaling( float128, float128 ); +int float128_le_quiet( float128, float128 ); +int float128_lt_quiet( float128, float128 ); +int float128_is_signaling_nan( float128 ); + +#endif + +#endif diff --git a/tools/test/testfloat/sparc64/sparc64.h b/tools/test/testfloat/sparc64/sparc64.h new file mode 100644 index 0000000..959a78c --- /dev/null +++ b/tools/test/testfloat/sparc64/sparc64.h @@ -0,0 +1,93 @@ +/*- + * Copyright (c) 2010 by Peter Jeremy <peterjeremy@acm.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/*---------------------------------------------------------------------------- +| One of the macros `BIGENDIAN' or `LITTLEENDIAN' must be defined. +*----------------------------------------------------------------------------*/ +#define BIGENDIAN + +/*---------------------------------------------------------------------------- +| The macro `BITS64' can be defined to indicate that 64-bit integer types are +| supported by the compiler. +*----------------------------------------------------------------------------*/ +#define BITS64 + +/*---------------------------------------------------------------------------- +| Each of the following `typedef's defines the most convenient type that holds +| integers of at least as many bits as specified. For example, `uint8' should +| be the most convenient type that can hold unsigned integers of as many as +| 8 bits. The `flag' type must be able to hold either a 0 or 1. For most +| implementations of C, `flag', `uint8', and `int8' should all be `typedef'ed +| to the same as `int'. +*----------------------------------------------------------------------------*/ +typedef int flag; +typedef int uint8; +typedef int int8; +typedef int uint16; +typedef int int16; +typedef unsigned int uint32; +typedef signed int int32; +#ifdef BITS64 +typedef unsigned long int uint64; +typedef signed long int int64; +#endif + +/*---------------------------------------------------------------------------- +| Each of the following `typedef's defines a type that holds integers +| of _exactly_ the number of bits specified. For instance, for most +| implementation of C, `bits16' and `sbits16' should be `typedef'ed to +| `unsigned short int' and `signed short int' (or `short int'), respectively. +*----------------------------------------------------------------------------*/ +typedef unsigned char bits8; +typedef signed char sbits8; +typedef unsigned short int bits16; +typedef signed short int sbits16; +typedef unsigned int bits32; +typedef signed int sbits32; +#ifdef BITS64 +typedef unsigned long int bits64; +typedef signed long int sbits64; +#endif + +#ifdef BITS64 +/*---------------------------------------------------------------------------- +| The `LIT64' macro takes as its argument a textual integer literal and +| if necessary ``marks'' the literal as having a 64-bit integer type. +| For example, the GNU C Compiler (`gcc') requires that 64-bit literals be +| appended with the letters `LL' standing for `long long', which is `gcc's +| name for the 64-bit integer type. Some compilers may allow `LIT64' to be +| defined as the identity macro: `#define LIT64( a ) a'. +*----------------------------------------------------------------------------*/ +#define LIT64( a ) a##L +#endif + +/*---------------------------------------------------------------------------- +| The macro `INLINE' can be used before functions that should be inlined. If +| a compiler does not support explicit inlining, this macro should be defined +| to be `static'. +*----------------------------------------------------------------------------*/ +#define INLINE extern inline diff --git a/tools/test/testfloat/sparc64/systflags.c b/tools/test/testfloat/sparc64/systflags.c new file mode 100644 index 0000000..9187fac --- /dev/null +++ b/tools/test/testfloat/sparc64/systflags.c @@ -0,0 +1,73 @@ +/*- + * Copyright (c) 2010 by Peter Jeremy <peterjeremy@acm.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* +=============================================================================== + +This C source file is part of TestFloat, Release 2a, a package of programs +for testing the correctness of floating-point arithmetic complying to the +IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#pragma STDC FENV_ACCESS ON +#include <fenv.h> +#include <ieeefp.h> +#include "milieu.h" +#include "systflags.h" + +/* +------------------------------------------------------------------------------- +Clears the system's IEC/IEEE floating-point exception flags. Returns the +previous value of the flags. +------------------------------------------------------------------------------- +*/ +int8 syst_float_flags_clear( void ) +{ + fexcept_t flags; + + fegetexceptflag(&flags, FE_ALL_EXCEPT); + feclearexcept(FE_ALL_EXCEPT); + return (flags >> 5); +} + diff --git a/tools/test/testfloat/sparc64/systfloat.S b/tools/test/testfloat/sparc64/systfloat.S new file mode 100644 index 0000000..09e97d1 --- /dev/null +++ b/tools/test/testfloat/sparc64/systfloat.S @@ -0,0 +1,1120 @@ +/*- + * Copyright (c) 2010 by Peter Jeremy <peterjeremy@acm.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* +=============================================================================== + +This GNU assembler source file is part of TestFloat, Release 2a, a package +of programs for testing the correctness of floating-point arithmetic +complying to the IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +#include <machine/asm.h> +__FBSDID("$FreeBSD$"); + + .text + +/* + .macro i2f32 src=%i0,dst=%f0 + st \src,[%sp+2231] + ld [%sp+2231],\dst + .endm + + .macro i2f64 src=%i0,dst=%f0 + stx \src,[%sp+2231] + ldd [%sp+2231],\dst + .endm + + .macro f2i32 src=%f0,dst=%i0 + st \src,[%sp+2231] + ld [%sp+2231],\dst + .endm + + .macro f2i64 src=%f0,dst=%i0 + std \src,[%sp+2231] + ldx [%sp+2231],\dst + .endm +*/ +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_int32_to_float32 +syst_int32_to_float32: + save %sp,-192,%sp + + st %i0,[%sp+2231] + ld [%sp+2231],%f0 + fitos %f0,%f0 + st %f0,[%sp+2231] + ld [%sp+2231],%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_int32_to_float64 +syst_int32_to_float64: + save %sp,-192,%sp + + st %i0,[%sp+2231] + ld [%sp+2231],%f0 + fitod %f0,%f0 + std %f0,[%sp+2231] + ldx [%sp+2231],%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_int32_to_float128 +syst_int32_to_float128: + save %sp,-192,%sp + + st %i0,[%sp+2231] + ld [%sp+2231],%f0 + fitoq %f0,%f0 + std %f0,[%sp+2231] + ldx [%sp+2231],%i0 + std %f2,[%sp+2231] + ldx [%sp+2231],%i1 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_int64_to_float32 +syst_int64_to_float32: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + fxtos %f0,%f0 + st %f0,[%sp+2231] + ld [%sp+2231],%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_int64_to_float64 +syst_int64_to_float64: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + fxtod %f0,%f0 + std %f0,[%sp+2231] + ldx [%sp+2231],%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_int64_to_float128 +syst_int64_to_float128: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + fxtoq %f0,%f0 + std %f0,[%sp+2231] + ldx [%sp+2231],%i0 + std %f2,[%sp+2231] + ldx [%sp+2231],%i1 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float32_to_int32_round_to_zero +syst_float32_to_int32_round_to_zero: + save %sp,-192,%sp + + st %i0,[%sp+2231] + ld [%sp+2231],%f0 + fstoi %f0,%f0 + st %f0,[%sp+2231] + ld [%sp+2231],%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float32_to_int64_round_to_zero +syst_float32_to_int64_round_to_zero: + save %sp,-192,%sp + + st %i0,[%sp+2231] + ld [%sp+2231],%f0 + fstox %f0,%f0 + std %f0,[%sp+2231] + ldx [%sp+2231],%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float32_to_float64 +syst_float32_to_float64: + save %sp,-192,%sp + + st %i0,[%sp+2231] + ld [%sp+2231],%f0 + fstod %f0,%f0 + std %f0,[%sp+2231] + ldx [%sp+2231],%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float32_to_float128 +syst_float32_to_float128: + save %sp,-192,%sp + + st %i0,[%sp+2231] + ld [%sp+2231],%f0 + fstoq %f0,%f0 + std %f0,[%sp+2231] + ldx [%sp+2231],%i0 + std %f2,[%sp+2231] + ldx [%sp+2231],%i1 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float32_add +syst_float32_add: + save %sp,-192,%sp + + st %i0,[%sp+2231] + ld [%sp+2231],%f0 + st %i1,[%sp+2231] + ld [%sp+2231],%f1 + fadds %f0,%f1,%f0 + st %f0,[%sp+2231] + ld [%sp+2231],%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float32_sub +syst_float32_sub: + save %sp,-192,%sp + + st %i0,[%sp+2231] + ld [%sp+2231],%f0 + st %i1,[%sp+2231] + ld [%sp+2231],%f1 + fsubs %f0,%f1,%f0 + st %f0,[%sp+2231] + ld [%sp+2231],%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float32_mul +syst_float32_mul: + save %sp,-192,%sp + + st %i0,[%sp+2231] + ld [%sp+2231],%f0 + st %i1,[%sp+2231] + ld [%sp+2231],%f1 + fmuls %f0,%f1,%f0 + st %f0,[%sp+2231] + ld [%sp+2231],%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float32_div +syst_float32_div: + save %sp,-192,%sp + + st %i0,[%sp+2231] + ld [%sp+2231],%f0 + st %i1,[%sp+2231] + ld [%sp+2231],%f1 + fdivs %f0,%f1,%f0 + st %f0,[%sp+2231] + ld [%sp+2231],%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float32_sqrt +syst_float32_sqrt: + save %sp,-192,%sp + + st %i0,[%sp+2231] + ld [%sp+2231],%f0 + fsqrts %f0,%f0 + st %f0,[%sp+2231] + ld [%sp+2231],%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float32_eq +syst_float32_eq: + save %sp,-192,%sp + + st %i0,[%sp+2231] + ld [%sp+2231],%f0 + st %i1,[%sp+2231] + ld [%sp+2231],%f1 + fcmps %fcc0,%f0,%f1 + mov 0,%i0 + move %fcc0,1,%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float32_le +syst_float32_le: + save %sp,-192,%sp + + st %i0,[%sp+2231] + ld [%sp+2231],%f0 + st %i1,[%sp+2231] + ld [%sp+2231],%f1 + fcmpes %fcc0,%f0,%f1 + mov 0,%i0 + movle %fcc0,1,%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float32_lt +syst_float32_lt: + save %sp,-192,%sp + + st %i0,[%sp+2231] + ld [%sp+2231],%f0 + st %i1,[%sp+2231] + ld [%sp+2231],%f1 + fcmpes %fcc0,%f0,%f1 + mov 0,%i0 + movl %fcc0,1,%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float32_eq_signaling +syst_float32_eq_signaling: + save %sp,-192,%sp + + st %i0,[%sp+2231] + ld [%sp+2231],%f0 + st %i1,[%sp+2231] + ld [%sp+2231],%f1 + fcmpes %fcc0,%f0,%f1 + mov 0,%i0 + move %fcc0,1,%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float32_le_quiet +syst_float32_le_quiet: + save %sp,-192,%sp + + st %i0,[%sp+2231] + ld [%sp+2231],%f0 + st %i1,[%sp+2231] + ld [%sp+2231],%f1 + fcmps %fcc0,%f0,%f1 + mov 0,%i0 + movle %fcc0,1,%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float32_lt_quiet +syst_float32_lt_quiet: + save %sp,-192,%sp + + st %i0,[%sp+2231] + ld [%sp+2231],%f0 + st %i1,[%sp+2231] + ld [%sp+2231],%f1 + fcmps %fcc0,%f0,%f1 + mov 0,%i0 + movl %fcc0,1,%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float64_to_int32_round_to_zero +syst_float64_to_int32_round_to_zero: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + fdtoi %f0,%f0 + st %f0,[%sp+2231] + ld [%sp+2231],%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float64_to_int64_round_to_zero +syst_float64_to_int64_round_to_zero: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + fdtox %f0,%f0 + std %f0,[%sp+2231] + ldx [%sp+2231],%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float64_to_float32 +syst_float64_to_float32: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + fdtos %f0,%f0 + st %f0,[%sp+2231] + ld [%sp+2231],%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float64_to_float128 +syst_float64_to_float128: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + fdtoq %f0,%f0 + std %f0,[%sp+2231] + ldx [%sp+2231],%i0 + std %f2,[%sp+2231] + ldx [%sp+2231],%i1 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float64_add +syst_float64_add: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + stx %i1,[%sp+2231] + ldd [%sp+2231],%f2 + faddd %f0,%f2,%f0 + std %f0,[%sp+2231] + ldx [%sp+2231],%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float64_sub +syst_float64_sub: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + stx %i1,[%sp+2231] + ldd [%sp+2231],%f2 + fsubd %f0,%f2,%f0 + std %f0,[%sp+2231] + ldx [%sp+2231],%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float64_mul +syst_float64_mul: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + stx %i1,[%sp+2231] + ldd [%sp+2231],%f2 + fmuld %f0,%f2,%f0 + std %f0,[%sp+2231] + ldx [%sp+2231],%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float64_div +syst_float64_div: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + stx %i1,[%sp+2231] + ldd [%sp+2231],%f2 + fdivd %f0,%f2,%f0 + std %f0,[%sp+2231] + ldx [%sp+2231],%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float64_sqrt +syst_float64_sqrt: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + fsqrtd %f0,%f0 + std %f0,[%sp+2231] + ldx [%sp+2231],%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float64_eq +syst_float64_eq: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + stx %i1,[%sp+2231] + ldd [%sp+2231],%f2 + fcmpd %fcc0,%f0,%f2 + mov 0,%i0 + move %fcc0,1,%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float64_le +syst_float64_le: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + stx %i1,[%sp+2231] + ldd [%sp+2231],%f2 + fcmped %fcc0,%f0,%f2 + mov 0,%i0 + movle %fcc0,1,%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float64_lt +syst_float64_lt: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + stx %i1,[%sp+2231] + ldd [%sp+2231],%f2 + fcmped %fcc0,%f0,%f2 + mov 0,%i0 + movl %fcc0,1,%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float64_eq_signaling +syst_float64_eq_signaling: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + stx %i1,[%sp+2231] + ldd [%sp+2231],%f2 + fcmped %fcc0,%f0,%f2 + mov 0,%i0 + move %fcc0,1,%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float64_le_quiet +syst_float64_le_quiet: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + stx %i1,[%sp+2231] + ldd [%sp+2231],%f2 + fcmpd %fcc0,%f0,%f2 + mov 0,%i0 + movle %fcc0,1,%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float64_lt_quiet +syst_float64_lt_quiet: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + stx %i1,[%sp+2231] + ldd [%sp+2231],%f2 + fcmpd %fcc0,%f0,%f2 + mov 0,%i0 + movl %fcc0,1,%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float128_to_int32_round_to_zero +syst_float128_to_int32_round_to_zero: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + stx %i1,[%sp+2231] + ldd [%sp+2231],%f2 + fqtoi %f0,%f0 + st %f0,[%sp+2231] + ld [%sp+2231],%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float128_to_int64_round_to_zero +syst_float128_to_int64_round_to_zero: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + stx %i1,[%sp+2231] + ldd [%sp+2231],%f2 + fqtox %f0,%f0 + std %f0,[%sp+2231] + ldx [%sp+2231],%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float128_to_float32 +syst_float128_to_float32: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + stx %i1,[%sp+2231] + ldd [%sp+2231],%f2 + fqtos %f0,%f0 + st %f0,[%sp+2231] + ld [%sp+2231],%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float128_to_float64 +syst_float128_to_float64: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + stx %i1,[%sp+2231] + ldd [%sp+2231],%f2 + fqtod %f0,%f0 + std %f0,[%sp+2231] + ldx [%sp+2231],%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float128_add +syst_float128_add: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + stx %i1,[%sp+2231] + ldd [%sp+2231],%f2 + stx %i2,[%sp+2231] + ldd [%sp+2231],%f4 + stx %i3,[%sp+2231] + ldd [%sp+2231],%f6 + faddq %f0,%f4,%f0 + std %f0,[%sp+2231] + ldx [%sp+2231],%i0 + std %f2,[%sp+2231] + ldx [%sp+2231],%i1 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float128_sub +syst_float128_sub: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + stx %i1,[%sp+2231] + ldd [%sp+2231],%f2 + stx %i2,[%sp+2231] + ldd [%sp+2231],%f4 + stx %i3,[%sp+2231] + ldd [%sp+2231],%f6 + fsubq %f0,%f4,%f0 + std %f0,[%sp+2231] + ldx [%sp+2231],%i0 + std %f2,[%sp+2231] + ldx [%sp+2231],%i1 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float128_mul +syst_float128_mul: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + stx %i1,[%sp+2231] + ldd [%sp+2231],%f2 + stx %i2,[%sp+2231] + ldd [%sp+2231],%f4 + stx %i3,[%sp+2231] + ldd [%sp+2231],%f6 + fmulq %f0,%f4,%f0 + std %f0,[%sp+2231] + ldx [%sp+2231],%i0 + std %f2,[%sp+2231] + ldx [%sp+2231],%i1 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float128_div +syst_float128_div: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + stx %i1,[%sp+2231] + ldd [%sp+2231],%f2 + stx %i2,[%sp+2231] + ldd [%sp+2231],%f4 + stx %i3,[%sp+2231] + ldd [%sp+2231],%f6 + fdivq %f0,%f4,%f0 + std %f0,[%sp+2231] + ldx [%sp+2231],%i0 + std %f2,[%sp+2231] + ldx [%sp+2231],%i1 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float128_sqrt +syst_float128_sqrt: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + stx %i1,[%sp+2231] + ldd [%sp+2231],%f2 + fsqrtq %f0,%f0 + std %f0,[%sp+2231] + ldx [%sp+2231],%i0 + std %f2,[%sp+2231] + ldx [%sp+2231],%i1 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float128_eq +syst_float128_eq: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + stx %i1,[%sp+2231] + ldd [%sp+2231],%f2 + stx %i2,[%sp+2231] + ldd [%sp+2231],%f4 + stx %i3,[%sp+2231] + ldd [%sp+2231],%f6 + fcmpq %fcc0,%f0,%f4 + mov 0,%i0 + move %fcc0,1,%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float128_le +syst_float128_le: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + stx %i1,[%sp+2231] + ldd [%sp+2231],%f2 + stx %i2,[%sp+2231] + ldd [%sp+2231],%f4 + stx %i3,[%sp+2231] + ldd [%sp+2231],%f6 + fcmpeq %fcc0,%f0,%f4 + mov 0,%i0 + movle %fcc0,1,%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float128_lt +syst_float128_lt: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + stx %i1,[%sp+2231] + ldd [%sp+2231],%f2 + stx %i2,[%sp+2231] + ldd [%sp+2231],%f4 + stx %i3,[%sp+2231] + ldd [%sp+2231],%f6 + fcmpeq %fcc0,%f0,%f4 + mov 0,%i0 + movl %fcc0,1,%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float128_eq_signaling +syst_float128_eq_signaling: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + stx %i1,[%sp+2231] + ldd [%sp+2231],%f2 + stx %i2,[%sp+2231] + ldd [%sp+2231],%f4 + stx %i3,[%sp+2231] + ldd [%sp+2231],%f6 + fcmpeq %fcc0,%f0,%f4 + mov 0,%i0 + move %fcc0,1,%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float128_le_quiet +syst_float128_le_quiet: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + stx %i1,[%sp+2231] + ldd [%sp+2231],%f2 + stx %i2,[%sp+2231] + ldd [%sp+2231],%f4 + stx %i3,[%sp+2231] + ldd [%sp+2231],%f6 + fcmpq %fcc0,%f0,%f4 + mov 0,%i0 + movle %fcc0,1,%i0 + + ret + restore + +/* +------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +*/ + .align 4 + .global syst_float128_lt_quiet +syst_float128_lt_quiet: + save %sp,-192,%sp + + stx %i0,[%sp+2231] + ldd [%sp+2231],%f0 + stx %i1,[%sp+2231] + ldd [%sp+2231],%f2 + stx %i2,[%sp+2231] + ldd [%sp+2231],%f4 + stx %i3,[%sp+2231] + ldd [%sp+2231],%f6 + fcmpq %fcc0,%f0,%f4 + mov 0,%i0 + movl %fcc0,1,%i0 + + ret + restore diff --git a/tools/test/testfloat/sparc64/systfloat.h b/tools/test/testfloat/sparc64/systfloat.h new file mode 100644 index 0000000..c1db1eb --- /dev/null +++ b/tools/test/testfloat/sparc64/systfloat.h @@ -0,0 +1,216 @@ + +/* +=============================================================================== + +This C header file is part of TestFloat, Release 2a, a package of programs +for testing the correctness of floating-point arithmetic complying to the +IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +/* $FreeBSD$ */ + +#include "softfloat.h" +#include "milieu.h" + +/* +------------------------------------------------------------------------------- +The following macros are defined to indicate that the corresponding +functions exist. +------------------------------------------------------------------------------- +*/ +#define SYST_INT32_TO_FLOAT32 +#define SYST_INT32_TO_FLOAT64 +#define SYST_INT32_TO_FLOAT128 +#define SYST_INT64_TO_FLOAT32 +#define SYST_INT64_TO_FLOAT64 +#define SYST_INT64_TO_FLOAT128 +#define SYST_FLOAT32_TO_INT32_ROUND_TO_ZERO +#define SYST_FLOAT32_TO_INT64_ROUND_TO_ZERO +#define SYST_FLOAT32_TO_FLOAT64 +#define SYST_FLOAT32_TO_FLOAT128 +#define SYST_FLOAT32_ADD +#define SYST_FLOAT32_SUB +#define SYST_FLOAT32_MUL +#define SYST_FLOAT32_DIV +#define SYST_FLOAT32_SQRT +#define SYST_FLOAT32_EQ +#define SYST_FLOAT32_LE +#define SYST_FLOAT32_LT +#define SYST_FLOAT32_EQ_SIGNALING +#define SYST_FLOAT32_LE_QUIET +#define SYST_FLOAT32_LT_QUIET +#define SYST_FLOAT64_TO_INT32_ROUND_TO_ZERO +#define SYST_FLOAT64_TO_INT64_ROUND_TO_ZERO +#define SYST_FLOAT64_TO_FLOAT32 +#define SYST_FLOAT64_TO_FLOAT128 +#define SYST_FLOAT64_ADD +#define SYST_FLOAT64_SUB +#define SYST_FLOAT64_MUL +#define SYST_FLOAT64_DIV +#define SYST_FLOAT64_SQRT +#define SYST_FLOAT64_EQ +#define SYST_FLOAT64_LE +#define SYST_FLOAT64_LT +#define SYST_FLOAT64_EQ_SIGNALING +#define SYST_FLOAT64_LE_QUIET +#define SYST_FLOAT64_LT_QUIET +#define SYST_FLOAT128_TO_INT32_ROUND_TO_ZERO +#define SYST_FLOAT128_TO_INT64_ROUND_TO_ZERO +#define SYST_FLOAT128_TO_FLOAT32 +#define SYST_FLOAT128_TO_FLOAT64 +#define SYST_FLOAT128_ADD +#define SYST_FLOAT128_SUB +#define SYST_FLOAT128_MUL +#define SYST_FLOAT128_DIV +#define SYST_FLOAT128_SQRT +#define SYST_FLOAT128_EQ +#define SYST_FLOAT128_LE +#define SYST_FLOAT128_LT +#define SYST_FLOAT128_EQ_SIGNALING +#define SYST_FLOAT128_LE_QUIET +#define SYST_FLOAT128_LT_QUIET + +/* +------------------------------------------------------------------------------- +System function declarations. (Some of these functions may not exist.) +------------------------------------------------------------------------------- +*/ +float32 syst_int32_to_float32( int32 ); +float64 syst_int32_to_float64( int32 ); +#ifdef FLOATX80 +floatx80 syst_int32_to_floatx80( int32 ); +#endif +#ifdef FLOAT128 +float128 syst_int32_to_float128( int32 ); +#endif +#ifdef BITS64 +float32 syst_int64_to_float32( int64 ); +float64 syst_int64_to_float64( int64 ); +#ifdef FLOATX80 +floatx80 syst_int64_to_floatx80( int64 ); +#endif +#ifdef FLOAT128 +float128 syst_int64_to_float128( int64 ); +#endif +#endif +int32 syst_float32_to_int32( float32 ); +int32 syst_float32_to_int32_round_to_zero( float32 ); +#ifdef BITS64 +int64 syst_float32_to_int64( float32 ); +int64 syst_float32_to_int64_round_to_zero( float32 ); +#endif +float64 syst_float32_to_float64( float32 ); +#ifdef FLOATX80 +floatx80 syst_float32_to_floatx80( float32 ); +#endif +#ifdef FLOAT128 +float128 syst_float32_to_float128( float32 ); +#endif +float32 syst_float32_round_to_int( float32 ); +float32 syst_float32_add( float32, float32 ); +float32 syst_float32_sub( float32, float32 ); +float32 syst_float32_mul( float32, float32 ); +float32 syst_float32_div( float32, float32 ); +float32 syst_float32_rem( float32, float32 ); +float32 syst_float32_sqrt( float32 ); +flag syst_float32_eq( float32, float32 ); +flag syst_float32_le( float32, float32 ); +flag syst_float32_lt( float32, float32 ); +flag syst_float32_eq_signaling( float32, float32 ); +flag syst_float32_le_quiet( float32, float32 ); +flag syst_float32_lt_quiet( float32, float32 ); +int32 syst_float64_to_int32( float64 ); +int32 syst_float64_to_int32_round_to_zero( float64 ); +#ifdef BITS64 +int64 syst_float64_to_int64( float64 ); +int64 syst_float64_to_int64_round_to_zero( float64 ); +#endif +float32 syst_float64_to_float32( float64 ); +#ifdef FLOATX80 +floatx80 syst_float64_to_floatx80( float64 ); +#endif +#ifdef FLOAT128 +float128 syst_float64_to_float128( float64 ); +#endif +float64 syst_float64_round_to_int( float64 ); +float64 syst_float64_add( float64, float64 ); +float64 syst_float64_sub( float64, float64 ); +float64 syst_float64_mul( float64, float64 ); +float64 syst_float64_div( float64, float64 ); +float64 syst_float64_rem( float64, float64 ); +float64 syst_float64_sqrt( float64 ); +flag syst_float64_eq( float64, float64 ); +flag syst_float64_le( float64, float64 ); +flag syst_float64_lt( float64, float64 ); +flag syst_float64_eq_signaling( float64, float64 ); +flag syst_float64_le_quiet( float64, float64 ); +flag syst_float64_lt_quiet( float64, float64 ); +#ifdef FLOATX80 +int32 syst_floatx80_to_int32( floatx80 ); +int32 syst_floatx80_to_int32_round_to_zero( floatx80 ); +#ifdef BITS64 +int64 syst_floatx80_to_int64( floatx80 ); +int64 syst_floatx80_to_int64_round_to_zero( floatx80 ); +#endif +float32 syst_floatx80_to_float32( floatx80 ); +float64 syst_floatx80_to_float64( floatx80 ); +#ifdef FLOAT128 +float128 syst_floatx80_to_float128( floatx80 ); +#endif +floatx80 syst_floatx80_round_to_int( floatx80 ); +floatx80 syst_floatx80_add( floatx80, floatx80 ); +floatx80 syst_floatx80_sub( floatx80, floatx80 ); +floatx80 syst_floatx80_mul( floatx80, floatx80 ); +floatx80 syst_floatx80_div( floatx80, floatx80 ); +floatx80 syst_floatx80_rem( floatx80, floatx80 ); +floatx80 syst_floatx80_sqrt( floatx80 ); +flag syst_floatx80_eq( floatx80, floatx80 ); +flag syst_floatx80_le( floatx80, floatx80 ); +flag syst_floatx80_lt( floatx80, floatx80 ); +flag syst_floatx80_eq_signaling( floatx80, floatx80 ); +flag syst_floatx80_le_quiet( floatx80, floatx80 ); +flag syst_floatx80_lt_quiet( floatx80, floatx80 ); +#endif +#ifdef FLOAT128 +int32 syst_float128_to_int32( float128 ); +int32 syst_float128_to_int32_round_to_zero( float128 ); +#ifdef BITS64 +int64 syst_float128_to_int64( float128 ); +int64 syst_float128_to_int64_round_to_zero( float128 ); +#endif +float32 syst_float128_to_float32( float128 ); +float64 syst_float128_to_float64( float128 ); +#ifdef FLOATX80 +floatx80 syst_float128_to_floatx80( float128 ); +#endif +float128 syst_float128_round_to_int( float128 ); +float128 syst_float128_add( float128, float128 ); +float128 syst_float128_sub( float128, float128 ); +float128 syst_float128_mul( float128, float128 ); +float128 syst_float128_div( float128, float128 ); +float128 syst_float128_rem( float128, float128 ); +float128 syst_float128_sqrt( float128 ); +flag syst_float128_eq( float128, float128 ); +flag syst_float128_le( float128, float128 ); +flag syst_float128_lt( float128, float128 ); +flag syst_float128_eq_signaling( float128, float128 ); +flag syst_float128_le_quiet( float128, float128 ); +flag syst_float128_lt_quiet( float128, float128 ); +#endif + diff --git a/tools/test/testfloat/sparc64/systmodes.c b/tools/test/testfloat/sparc64/systmodes.c new file mode 100644 index 0000000..2677059 --- /dev/null +++ b/tools/test/testfloat/sparc64/systmodes.c @@ -0,0 +1,54 @@ + +/* +=============================================================================== + +This C source file is part of TestFloat, Release 2a, a package of programs +for testing the correctness of floating-point arithmetic complying to the +IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <ieeefp.h> +#include "milieu.h" +#include "systmodes.h" + +/* +------------------------------------------------------------------------------- +Sets the system's IEC/IEEE floating-point rounding mode. +------------------------------------------------------------------------------- +*/ +void syst_float_set_rounding_mode( int8 roundingMode ) +{ + + (void) fpsetround( roundingMode ); + +} + +/* +------------------------------------------------------------------------------- +Does nothing. +------------------------------------------------------------------------------- +*/ +void syst_float_set_rounding_precision( int8 precision ) +{ + +} + diff --git a/tools/test/testfloat/sparc64/un-namespace.h b/tools/test/testfloat/sparc64/un-namespace.h new file mode 100644 index 0000000..5e7d1bc --- /dev/null +++ b/tools/test/testfloat/sparc64/un-namespace.h @@ -0,0 +1,30 @@ +/*- + * Copyright (c) 2010 by Peter Jeremy <peterjeremy@acm.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ +/* + * This file has no content and is solely to satisfy a #include in + * the FP emulator code. + */ diff --git a/tools/test/testfloat/systemBugs.txt b/tools/test/testfloat/systemBugs.txt new file mode 100644 index 0000000..a0d171a --- /dev/null +++ b/tools/test/testfloat/systemBugs.txt @@ -0,0 +1,323 @@ + +Known Floating-point Bugs Detected by TestFloat + +John R. Hauser +1997 December 15 + + +------------------------------------------------------------------------------- +Introduction + +Several popular systems have bugs that TestFloat is very likely to run +across. The ones I know of are documented here. First off, TestFloat finds +no errors in the following processors/machines: + + AMD 486 DX4's + Sun UltraSPARC 1's and 2's + +On the other hand, bugs are found in these processors/machines: + + Older Intel Pentiums (with the divide bug) + Intel Pentium Pros + Sun SPARCstation 1's and IPX's + Sun SPARCstation 10's + HP Precision Architecture processors, with HP-UX prior to version 10.10 + +For some reason, most of the bugs found involve conversions from floating- +point to integer formats. + +The bugs are shown as actual TestFloat error lines, along with a brief +explanation. The error lines given are not necesarily exhaustive and were +not necessarily output in the order shown. + +This document does not pretend to be an authoritative bug listing for all +commercial processors. The vast majority of processors are absent from this +list because I have never run TestFloat on such machines and I thus have no +knowledge of what bugs TestFloat might find in them. + +The latest version of this file can be found at the Web page `http:// +http.cs.berkeley.edu/~jhauser/arithmetic/testfloat.html'. + + +------------------------------------------------------------------------------- +Older Intel Pentiums (with the divide bug) + +The following conversion problems are found on Pentiums that also suffer +from the infamous floating-point divide bug. These bugs have been fixed on +newer Pentiums. (TestFloat does not find the divide bug.) + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +floatx80_to_int32 + +-- A few small fractions are treated as though they were zero. + + Errors found in floatx80_to_int32, rounding nearest_even: + 3FFB.8000000000000000 soft: 00000000 ....x syst: 00000000 ..... + 3FFC.8000000000000000 soft: 00000000 ....x syst: 00000000 ..... + 3FFC.C000000000000000 soft: 00000000 ....x syst: 00000000 ..... + BFFB.8000000000000000 soft: 00000000 ....x syst: 00000000 ..... + BFFC.8000000000000000 soft: 00000000 ....x syst: 00000000 ..... + Errors found in floatx80_to_int32, rounding to_zero: + 3FFB.8000000000000000 soft: 00000000 ....x syst: 00000000 ..... + 3FFC.8000000000000000 soft: 00000000 ....x syst: 00000000 ..... + 3FFC.C000000000000000 soft: 00000000 ....x syst: 00000000 ..... + BFFB.8000000000000000 soft: 00000000 ....x syst: 00000000 ..... + BFFC.8000000000000000 soft: 00000000 ....x syst: 00000000 ..... + BFFC.C000000000000000 soft: 00000000 ....x syst: 00000000 ..... + Errors found in floatx80_to_int32, rounding down: + 3FFB.8000000000000000 soft: 00000000 ....x syst: 00000000 ..... + 3FFC.8000000000000000 soft: 00000000 ....x syst: 00000000 ..... + 3FFC.C000000000000000 soft: 00000000 ....x syst: 00000000 ..... + BFFB.8000000000000000 soft: FFFFFFFF ....x syst: 00000000 ..... + BFFC.8000000000000000 soft: FFFFFFFF ....x syst: 00000000 ..... + BFFC.C000000000000000 soft: FFFFFFFF ....x syst: 00000000 ..... + Errors found in floatx80_to_int32, rounding up: + 3FFB.8000000000000000 soft: 00000001 ....x syst: 00000000 ..... + 3FFC.8000000000000000 soft: 00000001 ....x syst: 00000000 ..... + 3FFC.C000000000000000 soft: 00000001 ....x syst: 00000000 ..... + BFFB.8000000000000000 soft: 00000000 ....x syst: 00000000 ..... + BFFC.8000000000000000 soft: 00000000 ....x syst: 00000000 ..... + + 3FFB.8000000000000000 is the fraction 1/16; 3FFC.8000000000000000 is 1/8; + and 3FFC.C000000000000000 is 3/16. Both positive and negative inputs are + affected. + +-- Some (all?) positive floating-point values between 2^32 - 1/2 + (401E.FFFFFFFF00000000) and 2^32 (401F.0000000000000000) are rounded to + zero when the rounding mode is nearest/even or up. + + Errors found in floatx80_to_int32, rounding nearest_even: + 401E.FFFFFFFF80000000 soft: 7FFFFFFF v.... syst: 00000000 ....x + 401E.FFFFFFFFC00001FE soft: 7FFFFFFF v.... syst: 00000000 ....x + 401E.FFFFFFFFF8000000 soft: 7FFFFFFF v.... syst: 00000000 ....x + 401E.FFFFFFFFFEC00000 soft: 7FFFFFFF v.... syst: 00000000 ....x + 401E.FFFFFFFFFF002000 soft: 7FFFFFFF v.... syst: 00000000 ....x + 401E.FFFFFFFFFFC00000 soft: 7FFFFFFF v.... syst: 00000000 ....x + 401E.FFFFFFFFFFE00000 soft: 7FFFFFFF v.... syst: 00000000 ....x + 401E.FFFFFFFFFFFD7FFE soft: 7FFFFFFF v.... syst: 00000000 ....x + 401E.FFFFFFFFFFFFFFFE soft: 7FFFFFFF v.... syst: 00000000 ....x + 401E.FFFFFFFFFFFFFFFF soft: 7FFFFFFF v.... syst: 00000000 ....x + Errors found in floatx80_to_int32, rounding up: + 401E.FFFFFFFF00800000 soft: 7FFFFFFF v.... syst: 00000000 ....x + 401E.FFFFFFFF80000000 soft: 7FFFFFFF v.... syst: 00000000 ....x + 401E.FFFFFFFFEFFFC000 soft: 7FFFFFFF v.... syst: 00000000 ....x + 401E.FFFFFFFFFC000000 soft: 7FFFFFFF v.... syst: 00000000 ....x + 401E.FFFFFFFFFE7FFFFF soft: 7FFFFFFF v.... syst: 00000000 ....x + 401E.FFFFFFFFFFF00000 soft: 7FFFFFFF v.... syst: 00000000 ....x + 401E.FFFFFFFFFFFE0800 soft: 7FFFFFFF v.... syst: 00000000 ....x + 401E.FFFFFFFFFFFF7FFB soft: 7FFFFFFF v.... syst: 00000000 ....x + 401E.FFFFFFFFFFFFFFFE soft: 7FFFFFFF v.... syst: 00000000 ....x + 401E.FFFFFFFFFFFFFFFF soft: 7FFFFFFF v.... syst: 00000000 ....x + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + +------------------------------------------------------------------------------- +Intel Pentium Pros + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +floatx80_to_int32 + +-- The inexact flag is sometimes raised instead of the invalid flag for + floating-point inputs under -(2^32) (C01F.0000000000000000). This bug is + sporadic. It appears to be deterministic but dependent on the sequence + of operations executed. + + Errors found in floatx80_to_int32, rounding nearest_even: + C01F.C000000000000002 soft: 80000000 v.... syst: 80000000 ....x + C021.F00000000000003F soft: 80000000 v.... syst: 80000000 ....x + Errors found in floatx80_to_int32, rounding to_zero: + C021.F00000000000003F soft: 80000000 v.... syst: 80000000 ....x + Errors found in floatx80_to_int32, rounding up: + C01F.C000000000000007 soft: 80000000 v.... syst: 80000000 ....x + C01F.C000000000001000 soft: 80000000 v.... syst: 80000000 ....x + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + +------------------------------------------------------------------------------- +Sun SPARCstation 1's and IPX's + +Some older SPARCstations appear confused about whether underflow tininess is +detected before or after rounding. For conversions from double precision +to single precision, tininess is detected after rounding, while for all +quadruple-precision operations it is detected before rounding. Single- and +double-precision multipies go both ways: + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +float32_mul, float64_mul + +-- For multiplies, underflow tininess is detected _before_ rounding if one + of the inputs is subnormal, and _after_ rounding otherwise. If tininess + is assumed to be detected before rounding, the following errors are + generated: + + Errors found in float32_mul, rounding nearest_even: + 001.000001 07E.7FFFFE soft: 001.000000 ...ux syst: 001.000000 ....x + 001.000001 87E.7FFFFE soft: 801.000000 ...ux syst: 801.000000 ....x + 001.000002 07E.7FFFFC soft: 001.000000 ...ux syst: 001.000000 ....x + 001.000002 87E.7FFFFC soft: 801.000000 ...ux syst: 801.000000 ....x + 001.000004 07E.7FFFF8 soft: 001.000000 ...ux syst: 001.000000 ....x + Errors found in float32_mul, rounding down: + 001.000001 87E.7FFFFE soft: 801.000000 ...ux syst: 801.000000 ....x + 001.000002 87E.7FFFFC soft: 801.000000 ...ux syst: 801.000000 ....x + 001.000004 87E.7FFFF8 soft: 801.000000 ...ux syst: 801.000000 ....x + 001.000008 87E.7FFFF0 soft: 801.000000 ...ux syst: 801.000000 ....x + 001.000010 87E.7FFFE0 soft: 801.000000 ...ux syst: 801.000000 ....x + Errors found in float32_mul, rounding up: + 001.000001 07E.7FFFFE soft: 001.000000 ...ux syst: 001.000000 ....x + 001.000002 07E.7FFFFC soft: 001.000000 ...ux syst: 001.000000 ....x + 001.000004 07E.7FFFF8 soft: 001.000000 ...ux syst: 001.000000 ....x + 001.000008 07E.7FFFF0 soft: 001.000000 ...ux syst: 001.000000 ....x + 001.000010 07E.7FFFE0 soft: 001.000000 ...ux syst: 001.000000 ....x + Errors found in float64_mul, rounding nearest_even: + 001.0000000000001 3FE.FFFFFFFFFFFFE + soft: 001.0000000000000 ...ux syst: 001.0000000000000 ....x + 001.0000000000001 BFE.FFFFFFFFFFFFE + soft: 801.0000000000000 ...ux syst: 801.0000000000000 ....x + 001.0000000000002 3FE.FFFFFFFFFFFFC + soft: 001.0000000000000 ...ux syst: 001.0000000000000 ....x + 001.0000000000002 BFE.FFFFFFFFFFFFC + soft: 801.0000000000000 ...ux syst: 801.0000000000000 ....x + 001.0000000000004 3FE.FFFFFFFFFFFF8 + soft: 001.0000000000000 ...ux syst: 001.0000000000000 ....x + Errors found in float64_mul, rounding down: + 001.0000000000001 BFE.FFFFFFFFFFFFE + soft: 801.0000000000000 ...ux syst: 801.0000000000000 ....x + 001.0000000000002 BFE.FFFFFFFFFFFFC + soft: 801.0000000000000 ...ux syst: 801.0000000000000 ....x + 001.0000000000004 BFE.FFFFFFFFFFFF8 + soft: 801.0000000000000 ...ux syst: 801.0000000000000 ....x + 001.0000000000008 BFE.FFFFFFFFFFFF0 + soft: 801.0000000000000 ...ux syst: 801.0000000000000 ....x + 001.0000000000010 BFE.FFFFFFFFFFFE0 + soft: 801.0000000000000 ...ux syst: 801.0000000000000 ....x + Errors found in float64_mul, rounding up: + 001.0000000000001 3FE.FFFFFFFFFFFFE + soft: 001.0000000000000 ...ux syst: 001.0000000000000 ....x + 001.0000000000002 3FE.FFFFFFFFFFFFC + soft: 001.0000000000000 ...ux syst: 001.0000000000000 ....x + 001.0000000000004 3FE.FFFFFFFFFFFF8 + soft: 001.0000000000000 ...ux syst: 001.0000000000000 ....x + 001.0000000000008 3FE.FFFFFFFFFFFF0 + soft: 001.0000000000000 ...ux syst: 001.0000000000000 ....x + 001.0000000000010 3FE.FFFFFFFFFFFE0 + soft: 001.0000000000000 ...ux syst: 001.0000000000000 ....x + + If we assume tininess should be detected after rounding, we get the + following errors: + + Errors found in float32_mul, rounding nearest_even: + 000.7FFC00 07F.000400 soft: 001.000000 ....x syst: 001.000000 ...ux + 000.7FFC00 87F.000400 soft: 801.000000 ....x syst: 801.000000 ...ux + 000.7FFE00 07F.000200 soft: 001.000000 ....x syst: 001.000000 ...ux + 000.7FFE00 87F.000200 soft: 801.000000 ....x syst: 801.000000 ...ux + 000.7FFF00 07F.000100 soft: 001.000000 ....x syst: 001.000000 ...ux + Errors found in float32_mul, rounding down: + 000.7FFC00 87F.000400 soft: 801.000000 ....x syst: 801.000000 ...ux + 000.7FFE00 87F.000200 soft: 801.000000 ....x syst: 801.000000 ...ux + 000.7FFF00 87F.000100 soft: 801.000000 ....x syst: 801.000000 ...ux + 000.7FFF80 87F.000080 soft: 801.000000 ....x syst: 801.000000 ...ux + 000.7FFFC0 87F.000040 soft: 801.000000 ....x syst: 801.000000 ...ux + Errors found in float32_mul, rounding up: + 000.7FFC00 07F.000400 soft: 001.000000 ....x syst: 001.000000 ...ux + 000.7FFE00 07F.000200 soft: 001.000000 ....x syst: 001.000000 ...ux + 000.7FFF00 07F.000100 soft: 001.000000 ....x syst: 001.000000 ...ux + 000.7FFF80 07F.000080 soft: 001.000000 ....x syst: 001.000000 ...ux + 000.7FFFC0 07F.000040 soft: 001.000000 ....x syst: 001.000000 ...ux + Errors found in float64_mul, rounding nearest_even: + 000.FFFFFFE000000 3FF.0000002000000 + soft: 001.0000000000000 ....x syst: 001.0000000000000 ...ux + 000.FFFFFFE000000 BFF.0000002000000 + soft: 801.0000000000000 ....x syst: 801.0000000000000 ...ux + 000.FFFFFFF000000 3FF.0000001000000 + soft: 001.0000000000000 ....x syst: 001.0000000000000 ...ux + 000.FFFFFFF000000 BFF.0000001000000 + soft: 801.0000000000000 ....x syst: 801.0000000000000 ...ux + 000.FFFFFFF800000 3FF.0000000800000 + soft: 001.0000000000000 ....x syst: 001.0000000000000 ...ux + Errors found in float64_mul, rounding down: + 000.FFFFFFE000000 BFF.0000002000000 + soft: 801.0000000000000 ....x syst: 801.0000000000000 ...ux + 000.FFFFFFF000000 BFF.0000001000000 + soft: 801.0000000000000 ....x syst: 801.0000000000000 ...ux + 000.FFFFFFF800000 BFF.0000000800000 + soft: 801.0000000000000 ....x syst: 801.0000000000000 ...ux + 000.FFFFFFFC00000 BFF.0000000400000 + soft: 801.0000000000000 ....x syst: 801.0000000000000 ...ux + 000.FFFFFFFE00000 BFF.0000000200000 + soft: 801.0000000000000 ....x syst: 801.0000000000000 ...ux + Errors found in float64_mul, rounding up: + 000.FFFFFFE000000 3FF.0000002000000 + soft: 001.0000000000000 ....x syst: 001.0000000000000 ...ux + 000.FFFFFFF000000 3FF.0000001000000 + soft: 001.0000000000000 ....x syst: 001.0000000000000 ...ux + 000.FFFFFFF800000 3FF.0000000800000 + soft: 001.0000000000000 ....x syst: 001.0000000000000 ...ux + 000.FFFFFFFC00000 3FF.0000000400000 + soft: 001.0000000000000 ....x syst: 001.0000000000000 ...ux + 000.FFFFFFFE00000 3FF.0000000200000 + soft: 001.0000000000000 ....x syst: 001.0000000000000 ...ux + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + +------------------------------------------------------------------------------- +Sun SPARCstation 10's + +Like other SPARCstations, some SPARCstation 10's are inconsistent regarding +underflow tininess, detecting it after rounding for single- and double- +precision operations and before rounding for quadruple-precision operations. +The following bug has also been observed. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +float32_to_int32_round_to_zero, float64_to_int32_round_to_zero + +-- Single- and double-precision NaNs are converted to the integer zero. + (The invalid exception flag is raised correctly.) + + Errors found in float32_to_int32_round_to_zero: + 8FF.5D36AC soft: 7FFFFFFF v.... syst: 00000000 v.... + 0FF.7FFFC0 soft: 7FFFFFFF v.... syst: 00000000 v.... + 8FF.7C0000 soft: 7FFFFFFF v.... syst: 00000000 v.... + 0FF.2AB7ED soft: 7FFFFFFF v.... syst: 00000000 v.... + 0FF.03FFFF soft: 7FFFFFFF v.... syst: 00000000 v.... + Errors found in float64_to_int32_round_to_zero: + 7FF.45AD84DB2524A soft: 7FFFFFFF v.... syst: 00000000 v.... + 7FF.CFEE063EE0512 soft: 7FFFFFFF v.... syst: 00000000 v.... + 7FF.89FF03AB7DBA2 soft: 7FFFFFFF v.... syst: 00000000 v.... + 7FF.FFFFFFFFFF800 soft: 7FFFFFFF v.... syst: 00000000 v.... + FFF.68A6410E91BF6 soft: 7FFFFFFF v.... syst: 00000000 v.... + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + +------------------------------------------------------------------------------- +HP Precision Architecture processors, with HP-UX prior to version 10.10 + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +float32_to_int32_round_to_zero, float64_to_int32_round_to_zero + +-- When the floating-point value is too large, the overflow and inexact + exception flags are raised instead of the invalid flag. + + Errors found in float32_to_int32_round_to_zero: + 89E.000007 soft: 80000000 v.... syst: 80000000 ..o.x + 0A2.000020 soft: 7FFFFFFF v.... syst: 7FFFFFFF ..o.x + 8FA.7C0000 soft: 80000000 v.... syst: 80000000 ..o.x + Errors found in float64_to_int32_round_to_zero: + 7FD.0448700002F1C soft: 7FFFFFFF v.... syst: 7FFFFFFF ..o.x + DAA.F000000000000 soft: 80000000 v.... syst: 80000000 ..o.x + 41E.063DA00005E65 soft: 7FFFFFFF v.... syst: 7FFFFFFF ..o.x + 47E.FFFF800000000 soft: 7FFFFFFF v.... syst: 7FFFFFFF ..o.x + 51F.0000000000004 soft: 7FFFFFFF v.... syst: 7FFFFFFF ..o.x + DDA.0000001FFFFFF soft: 80000000 v.... syst: 80000000 ..o.x + D70.00000000003FF soft: 80000000 v.... syst: 80000000 ..o.x + C7E.0000100000000 soft: 80000000 v.... syst: 80000000 ..o.x + 47E.000000000007F soft: 7FFFFFFF v.... syst: 7FFFFFFF ..o.x + D57.000000000FFFF soft: 80000000 v.... syst: 80000000 ..o.x + + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + diff --git a/tools/test/testfloat/systflags.h b/tools/test/testfloat/systflags.h new file mode 100644 index 0000000..23e6b23 --- /dev/null +++ b/tools/test/testfloat/systflags.h @@ -0,0 +1,33 @@ + +/* +=============================================================================== + +This C header file is part of TestFloat, Release 2a, a package of programs +for testing the correctness of floating-point arithmetic complying to the +IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +/* +------------------------------------------------------------------------------- +Target-specific function for clearing the system's IEC/IEEE floating-point +exception flags. The previous value of the flags is returned. +------------------------------------------------------------------------------- +*/ +int8 syst_float_flags_clear( void ); + diff --git a/tools/test/testfloat/systfloat.c b/tools/test/testfloat/systfloat.c new file mode 100644 index 0000000..08548c4 --- /dev/null +++ b/tools/test/testfloat/systfloat.c @@ -0,0 +1,553 @@ + +/* +=============================================================================== + +This C source file is part of TestFloat, Release 2a, a package of programs +for testing the correctness of floating-point arithmetic complying to the +IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +#include <math.h> +#include "milieu.h" +#include "softfloat.h" +#include "systfloat.h" + +float32 syst_int32_to_float32( int32 a ) +{ + float32 z; + + *( (float *) &z ) = a; + return z; + +} + +float64 syst_int32_to_float64( int32 a ) +{ + float64 z; + + *( (double *) &z ) = a; + return z; + +} + +#if defined( FLOATX80 ) && defined( LONG_DOUBLE_IS_FLOATX80 ) + +floatx80 syst_int32_to_floatx80( int32 a ) +{ + floatx80 z; + + *( (long double *) &z ) = a; + return z; + +} + +#endif + +#if defined( FLOAT128 ) && defined( LONG_DOUBLE_IS_FLOAT128 ) + +float128 syst_int32_to_float128( int32 a ) +{ + float128 z; + + *( (long double *) &z ) = a; + return z; + +} + +#endif + +#ifdef BITS64 + +float32 syst_int64_to_float32( int64 a ) +{ + float32 z; + + *( (float *) &z ) = a; + return z; + +} + +float64 syst_int64_to_float64( int64 a ) +{ + float64 z; + + *( (double *) &z ) = a; + return z; + +} + +#if defined( FLOATX80 ) && defined( LONG_DOUBLE_IS_FLOATX80 ) + +floatx80 syst_int64_to_floatx80( int64 a ) +{ + floatx80 z; + + *( (long double *) &z ) = a; + return z; + +} + +#endif + +#if defined( FLOAT128 ) && defined( LONG_DOUBLE_IS_FLOAT128 ) + +float128 syst_int64_to_float128( int64 a ) +{ + float128 z; + + *( (long double *) &z ) = a; + return z; + +} + +#endif + +#endif + +int32 syst_float32_to_int32_round_to_zero( float32 a ) +{ + + return *( (float *) &a ); + +} + +#ifdef BITS64 + +int64 syst_float32_to_int64_round_to_zero( float32 a ) +{ + + return *( (float *) &a ); + +} + +#endif + +float64 syst_float32_to_float64( float32 a ) +{ + float64 z; + + *( (double *) &z ) = *( (float *) &a ); + return z; + +} + +#if defined( FLOATX80 ) && defined( LONG_DOUBLE_IS_FLOATX80 ) + +floatx80 syst_float32_to_floatx80( float32 a ) +{ + floatx80 z; + + *( (long double *) &z ) = *( (float *) &a ); + return z; + +} + +#endif + +#if defined( FLOAT128 ) && defined( LONG_DOUBLE_IS_FLOAT128 ) + +float128 syst_float32_to_float128( float32 a ) +{ + float128 z; + + *( (long double *) &z ) = *( (float *) &a ); + return z; + +} + +#endif + +float32 syst_float32_add( float32 a, float32 b ) +{ + float32 z; + + *( (float *) &z ) = *( (float *) &a ) + *( (float *) &b ); + return z; + +} + +float32 syst_float32_sub( float32 a, float32 b ) +{ + float32 z; + + *( (float *) &z ) = *( (float *) &a ) - *( (float *) &b ); + return z; + +} + +float32 syst_float32_mul( float32 a, float32 b ) +{ + float32 z; + + *( (float *) &z ) = *( (float *) &a ) * *( (float *) &b ); + return z; + +} + +float32 syst_float32_div( float32 a, float32 b ) +{ + float32 z; + + *( (float *) &z ) = *( (float *) &a ) / *( (float *) &b ); + return z; + +} + +flag syst_float32_eq( float32 a, float32 b ) +{ + + return ( *( (float *) &a ) == *( (float *) &b ) ); + +} + +flag syst_float32_le( float32 a, float32 b ) +{ + + return ( *( (float *) &a ) <= *( (float *) &b ) ); + +} + +flag syst_float32_lt( float32 a, float32 b ) +{ + + return ( *( (float *) &a ) < *( (float *) &b ) ); + +} + +int32 syst_float64_to_int32_round_to_zero( float64 a ) +{ + + return *( (double *) &a ); + +} + +#ifdef BITS64 + +int64 syst_float64_to_int64_round_to_zero( float64 a ) +{ + + return *( (double *) &a ); + +} + +#endif + +float32 syst_float64_to_float32( float64 a ) +{ + float32 z; + + *( (float *) &z ) = *( (double *) &a ); + return z; + +} + +#if defined( FLOATX80 ) && defined( LONG_DOUBLE_IS_FLOATX80 ) + +floatx80 syst_float64_to_floatx80( float64 a ) +{ + floatx80 z; + + *( (long double *) &z ) = *( (double *) &a ); + return z; + +} + +#endif + +#if defined( FLOAT128 ) && defined( LONG_DOUBLE_IS_FLOAT128 ) + +float128 syst_float64_to_float128( float64 a ) +{ + float128 z; + + *( (long double *) &z ) = *( (double *) &a ); + return z; + +} + +#endif + +float64 syst_float64_add( float64 a, float64 b ) +{ + float64 z; + + *( (double *) &z ) = *( (double *) &a ) + *( (double *) &b ); + return z; + +} + +float64 syst_float64_sub( float64 a, float64 b ) +{ + float64 z; + + *( (double *) &z ) = *( (double *) &a ) - *( (double *) &b ); + return z; + +} + +float64 syst_float64_mul( float64 a, float64 b ) +{ + float64 z; + + *( (double *) &z ) = *( (double *) &a ) * *( (double *) &b ); + return z; + +} + +float64 syst_float64_div( float64 a, float64 b ) +{ + float64 z; + + *( (double *) &z ) = *( (double *) &a ) / *( (double *) &b ); + return z; + +} + +float64 syst_float64_sqrt( float64 a ) +{ + float64 z; + + *( (double *) &z ) = sqrt( *( (double *) &a ) ); + return z; + +} + +flag syst_float64_eq( float64 a, float64 b ) +{ + + return ( *( (double *) &a ) == *( (double *) &b ) ); + +} + +flag syst_float64_le( float64 a, float64 b ) +{ + + return ( *( (double *) &a ) <= *( (double *) &b ) ); + +} + +flag syst_float64_lt( float64 a, float64 b ) +{ + + return ( *( (double *) &a ) < *( (double *) &b ) ); + +} + +#if defined( FLOATX80 ) && defined( LONG_DOUBLE_IS_FLOATX80 ) + +int32 syst_floatx80_to_int32_round_to_zero( floatx80 a ) +{ + + return *( (long double *) &a ); + +} + +#ifdef BITS64 + +int64 syst_floatx80_to_int64_round_to_zero( floatx80 a ) +{ + + return *( (long double *) &a ); + +} + +#endif + +float32 syst_floatx80_to_float32( floatx80 a ) +{ + float32 z; + + *( (float *) &z ) = *( (long double *) &a ); + return z; + +} + +float64 syst_floatx80_to_float64( floatx80 a ) +{ + float64 z; + + *( (double *) &z ) = *( (long double *) &a ); + return z; + +} + +floatx80 syst_floatx80_add( floatx80 a, floatx80 b ) +{ + floatx80 z; + + *( (long double *) &z ) = + *( (long double *) &a ) + *( (long double *) &b ); + return z; + +} + +floatx80 syst_floatx80_sub( floatx80 a, floatx80 b ) +{ + floatx80 z; + + *( (long double *) &z ) = + *( (long double *) &a ) - *( (long double *) &b ); + return z; + +} + +floatx80 syst_floatx80_mul( floatx80 a, floatx80 b ) +{ + floatx80 z; + + *( (long double *) &z ) = + *( (long double *) &a ) * *( (long double *) &b ); + return z; + +} + +floatx80 syst_floatx80_div( floatx80 a, floatx80 b ) +{ + floatx80 z; + + *( (long double *) &z ) = + *( (long double *) &a ) / *( (long double *) &b ); + return z; + +} + +flag syst_floatx80_eq( floatx80 a, floatx80 b ) +{ + + return ( *( (long double *) &a ) == *( (long double *) &b ) ); + +} + +flag syst_floatx80_le( floatx80 a, floatx80 b ) +{ + + return ( *( (long double *) &a ) <= *( (long double *) &b ) ); + +} + +flag syst_floatx80_lt( floatx80 a, floatx80 b ) +{ + + return ( *( (long double *) &a ) < *( (long double *) &b ) ); + +} + +#endif + +#if defined( FLOAT128 ) && defined( LONG_DOUBLE_IS_FLOAT128 ) + +int32 syst_float128_to_int32_round_to_zero( float128 a ) +{ + + return *( (long double *) &a ); + +} + +#ifdef BITS64 + +int64 syst_float128_to_int64_round_to_zero( float128 a ) +{ + + return *( (long double *) &a ); + +} + +#endif + +float32 syst_float128_to_float32( float128 a ) +{ + float32 z; + + *( (float *) &z ) = *( (long double *) &a ); + return z; + +} + +float64 syst_float128_to_float64( float128 a ) +{ + float64 z; + + *( (double *) &z ) = *( (long double *) &a ); + return z; + +} + +float128 syst_float128_add( float128 a, float128 b ) +{ + float128 z; + + *( (long double *) &z ) = + *( (long double *) &a ) + *( (long double *) &b ); + return z; + +} + +float128 syst_float128_sub( float128 a, float128 b ) +{ + float128 z; + + *( (long double *) &z ) = + *( (long double *) &a ) - *( (long double *) &b ); + return z; + +} + +float128 syst_float128_mul( float128 a, float128 b ) +{ + float128 z; + + *( (long double *) &z ) = + *( (long double *) &a ) * *( (long double *) &b ); + return z; + +} + +float128 syst_float128_div( float128 a, float128 b ) +{ + float128 z; + + *( (long double *) &z ) = + *( (long double *) &a ) / *( (long double *) &b ); + return z; + +} + +flag syst_float128_eq( float128 a, float128 b ) +{ + + return ( *( (long double *) &a ) == *( (long double *) &b ) ); + +} + +flag syst_float128_le( float128 a, float128 b ) +{ + + return ( *( (long double *) &a ) <= *( (long double *) &b ) ); + +} + +flag syst_float128_lt( float128 a, float128 b ) +{ + + return ( *( (long double *) &a ) < *( (long double *) &b ) ); + +} + +#endif + diff --git a/tools/test/testfloat/systmodes.h b/tools/test/testfloat/systmodes.h new file mode 100644 index 0000000..b2befa4 --- /dev/null +++ b/tools/test/testfloat/systmodes.h @@ -0,0 +1,42 @@ + +/* +=============================================================================== + +This C header file is part of TestFloat, Release 2a, a package of programs +for testing the correctness of floating-point arithmetic complying to the +IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +/* +------------------------------------------------------------------------------- +Target-specific function for setting the system's IEC/IEEE floating-point +rounding mode. Other system modes are also initialized as necessary (for +example, exception trapping may be disabled). +------------------------------------------------------------------------------- +*/ +void syst_float_set_rounding_mode( int8 ); + +/* +------------------------------------------------------------------------------- +Target-specific function for setting the IEC/IEEE rounding precision of +subsequent extended double-precision operations performed by the system. +------------------------------------------------------------------------------- +*/ +void syst_float_set_rounding_precision( int8 ); + diff --git a/tools/test/testfloat/testCases.c b/tools/test/testfloat/testCases.c new file mode 100644 index 0000000..e2d8f42 --- /dev/null +++ b/tools/test/testfloat/testCases.c @@ -0,0 +1,3682 @@ + +/* +=============================================================================== + +This C source file is part of TestFloat, Release 2a, a package of programs +for testing the correctness of floating-point arithmetic complying to the +IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include "milieu.h" +#include "fail.h" +#include "random.h" +#include "softfloat.h" +#include "testCases.h" + +typedef struct { + int16 expNum, term1Num, term2Num; + flag done; +} sequenceT; + +enum { + int32NumP1 = 124 +}; + +static const uint32 int32P1[ int32NumP1 ] = { + 0x00000000, + 0x00000001, + 0x00000002, + 0x00000004, + 0x00000008, + 0x00000010, + 0x00000020, + 0x00000040, + 0x00000080, + 0x00000100, + 0x00000200, + 0x00000400, + 0x00000800, + 0x00001000, + 0x00002000, + 0x00004000, + 0x00008000, + 0x00010000, + 0x00020000, + 0x00040000, + 0x00080000, + 0x00100000, + 0x00200000, + 0x00400000, + 0x00800000, + 0x01000000, + 0x02000000, + 0x04000000, + 0x08000000, + 0x10000000, + 0x20000000, + 0x40000000, + 0x80000000, + 0xC0000000, + 0xE0000000, + 0xF0000000, + 0xF8000000, + 0xFC000000, + 0xFE000000, + 0xFF000000, + 0xFF800000, + 0xFFC00000, + 0xFFE00000, + 0xFFF00000, + 0xFFF80000, + 0xFFFC0000, + 0xFFFE0000, + 0xFFFF0000, + 0xFFFF8000, + 0xFFFFC000, + 0xFFFFE000, + 0xFFFFF000, + 0xFFFFF800, + 0xFFFFFC00, + 0xFFFFFE00, + 0xFFFFFF00, + 0xFFFFFF80, + 0xFFFFFFC0, + 0xFFFFFFE0, + 0xFFFFFFF0, + 0xFFFFFFF8, + 0xFFFFFFFC, + 0xFFFFFFFE, + 0xFFFFFFFF, + 0xFFFFFFFD, + 0xFFFFFFFB, + 0xFFFFFFF7, + 0xFFFFFFEF, + 0xFFFFFFDF, + 0xFFFFFFBF, + 0xFFFFFF7F, + 0xFFFFFEFF, + 0xFFFFFDFF, + 0xFFFFFBFF, + 0xFFFFF7FF, + 0xFFFFEFFF, + 0xFFFFDFFF, + 0xFFFFBFFF, + 0xFFFF7FFF, + 0xFFFEFFFF, + 0xFFFDFFFF, + 0xFFFBFFFF, + 0xFFF7FFFF, + 0xFFEFFFFF, + 0xFFDFFFFF, + 0xFFBFFFFF, + 0xFF7FFFFF, + 0xFEFFFFFF, + 0xFDFFFFFF, + 0xFBFFFFFF, + 0xF7FFFFFF, + 0xEFFFFFFF, + 0xDFFFFFFF, + 0xBFFFFFFF, + 0x7FFFFFFF, + 0x3FFFFFFF, + 0x1FFFFFFF, + 0x0FFFFFFF, + 0x07FFFFFF, + 0x03FFFFFF, + 0x01FFFFFF, + 0x00FFFFFF, + 0x007FFFFF, + 0x003FFFFF, + 0x001FFFFF, + 0x000FFFFF, + 0x0007FFFF, + 0x0003FFFF, + 0x0001FFFF, + 0x0000FFFF, + 0x00007FFF, + 0x00003FFF, + 0x00001FFF, + 0x00000FFF, + 0x000007FF, + 0x000003FF, + 0x000001FF, + 0x000000FF, + 0x0000007F, + 0x0000003F, + 0x0000001F, + 0x0000000F, + 0x00000007, + 0x00000003 +}; + +static int32 int32NextP1( sequenceT *sequencePtr ) +{ + uint8 termNum; + int32 z; + + termNum = sequencePtr->term1Num; + z = int32P1[ termNum ]; + ++termNum; + if ( int32NumP1 <= termNum ) { + termNum = 0; + sequencePtr->done = TRUE; + } + sequencePtr->term1Num = termNum; + return (sbits32) z; + +} + +static const int32 int32NumP2 = ( int32NumP1 * int32NumP1 + int32NumP1 ) / 2; + +static int32 int32NextP2( sequenceT *sequencePtr ) +{ + uint8 term1Num, term2Num; + int32 z; + + term2Num = sequencePtr->term2Num; + term1Num = sequencePtr->term1Num; + z = int32P1[ term1Num ] + int32P1[ term2Num ]; + ++term2Num; + if ( int32NumP1 <= term2Num ) { + ++term1Num; + if ( int32NumP1 <= term1Num ) { + term1Num = 0; + sequencePtr->done = TRUE; + } + term2Num = term1Num; + sequencePtr->term1Num = term1Num; + } + sequencePtr->term2Num = term2Num; + return (sbits32) z; + +} + +static int32 int32RandomP3( void ) +{ + + return + (sbits32) ( + int32P1[ randomUint8() % int32NumP1 ] + + int32P1[ randomUint8() % int32NumP1 ] + + int32P1[ randomUint8() % int32NumP1 ] + ); + +} + +enum { + int32NumPInfWeightMasks = 29 +}; + +static const uint32 int32PInfWeightMasks[ int32NumPInfWeightMasks ] = { + 0xFFFFFFFF, + 0x7FFFFFFF, + 0x3FFFFFFF, + 0x1FFFFFFF, + 0x0FFFFFFF, + 0x07FFFFFF, + 0x03FFFFFF, + 0x01FFFFFF, + 0x00FFFFFF, + 0x007FFFFF, + 0x003FFFFF, + 0x001FFFFF, + 0x000FFFFF, + 0x0007FFFF, + 0x0003FFFF, + 0x0001FFFF, + 0x0000FFFF, + 0x00007FFF, + 0x00003FFF, + 0x00001FFF, + 0x00000FFF, + 0x000007FF, + 0x000003FF, + 0x000001FF, + 0x000000FF, + 0x0000007F, + 0x0000003F, + 0x0000001F, + 0x0000000F +}; + +static const uint32 int32PInfWeightOffsets[ int32NumPInfWeightMasks ] = { + 0x00000000, + 0xC0000000, + 0xE0000000, + 0xF0000000, + 0xF8000000, + 0xFC000000, + 0xFE000000, + 0xFF000000, + 0xFF800000, + 0xFFC00000, + 0xFFE00000, + 0xFFF00000, + 0xFFF80000, + 0xFFFC0000, + 0xFFFE0000, + 0xFFFF0000, + 0xFFFF8000, + 0xFFFFC000, + 0xFFFFE000, + 0xFFFFF000, + 0xFFFFF800, + 0xFFFFFC00, + 0xFFFFFE00, + 0xFFFFFF00, + 0xFFFFFF80, + 0xFFFFFFC0, + 0xFFFFFFE0, + 0xFFFFFFF0, + 0xFFFFFFF8 +}; + +static int32 int32RandomPInf( void ) +{ + int8 weightMaskNum; + + weightMaskNum = randomUint8() % int32NumPInfWeightMasks; + return + (sbits32) ( + ( randomUint32() & int32PInfWeightMasks[ weightMaskNum ] ) + + int32PInfWeightOffsets[ weightMaskNum ] + ); + +} + +#ifdef BITS64 + +enum { + int64NumP1 = 252 +}; + +static const uint64 int64P1[ int64NumP1 ] = { + LIT64( 0x0000000000000000 ), + LIT64( 0x0000000000000001 ), + LIT64( 0x0000000000000002 ), + LIT64( 0x0000000000000004 ), + LIT64( 0x0000000000000008 ), + LIT64( 0x0000000000000010 ), + LIT64( 0x0000000000000020 ), + LIT64( 0x0000000000000040 ), + LIT64( 0x0000000000000080 ), + LIT64( 0x0000000000000100 ), + LIT64( 0x0000000000000200 ), + LIT64( 0x0000000000000400 ), + LIT64( 0x0000000000000800 ), + LIT64( 0x0000000000001000 ), + LIT64( 0x0000000000002000 ), + LIT64( 0x0000000000004000 ), + LIT64( 0x0000000000008000 ), + LIT64( 0x0000000000010000 ), + LIT64( 0x0000000000020000 ), + LIT64( 0x0000000000040000 ), + LIT64( 0x0000000000080000 ), + LIT64( 0x0000000000100000 ), + LIT64( 0x0000000000200000 ), + LIT64( 0x0000000000400000 ), + LIT64( 0x0000000000800000 ), + LIT64( 0x0000000001000000 ), + LIT64( 0x0000000002000000 ), + LIT64( 0x0000000004000000 ), + LIT64( 0x0000000008000000 ), + LIT64( 0x0000000010000000 ), + LIT64( 0x0000000020000000 ), + LIT64( 0x0000000040000000 ), + LIT64( 0x0000000080000000 ), + LIT64( 0x0000000100000000 ), + LIT64( 0x0000000200000000 ), + LIT64( 0x0000000400000000 ), + LIT64( 0x0000000800000000 ), + LIT64( 0x0000001000000000 ), + LIT64( 0x0000002000000000 ), + LIT64( 0x0000004000000000 ), + LIT64( 0x0000008000000000 ), + LIT64( 0x0000010000000000 ), + LIT64( 0x0000020000000000 ), + LIT64( 0x0000040000000000 ), + LIT64( 0x0000080000000000 ), + LIT64( 0x0000100000000000 ), + LIT64( 0x0000200000000000 ), + LIT64( 0x0000400000000000 ), + LIT64( 0x0000800000000000 ), + LIT64( 0x0001000000000000 ), + LIT64( 0x0002000000000000 ), + LIT64( 0x0004000000000000 ), + LIT64( 0x0008000000000000 ), + LIT64( 0x0010000000000000 ), + LIT64( 0x0020000000000000 ), + LIT64( 0x0040000000000000 ), + LIT64( 0x0080000000000000 ), + LIT64( 0x0100000000000000 ), + LIT64( 0x0200000000000000 ), + LIT64( 0x0400000000000000 ), + LIT64( 0x0800000000000000 ), + LIT64( 0x1000000000000000 ), + LIT64( 0x2000000000000000 ), + LIT64( 0x4000000000000000 ), + LIT64( 0x8000000000000000 ), + LIT64( 0xC000000000000000 ), + LIT64( 0xE000000000000000 ), + LIT64( 0xF000000000000000 ), + LIT64( 0xF800000000000000 ), + LIT64( 0xFC00000000000000 ), + LIT64( 0xFE00000000000000 ), + LIT64( 0xFF00000000000000 ), + LIT64( 0xFF80000000000000 ), + LIT64( 0xFFC0000000000000 ), + LIT64( 0xFFE0000000000000 ), + LIT64( 0xFFF0000000000000 ), + LIT64( 0xFFF8000000000000 ), + LIT64( 0xFFFC000000000000 ), + LIT64( 0xFFFE000000000000 ), + LIT64( 0xFFFF000000000000 ), + LIT64( 0xFFFF800000000000 ), + LIT64( 0xFFFFC00000000000 ), + LIT64( 0xFFFFE00000000000 ), + LIT64( 0xFFFFF00000000000 ), + LIT64( 0xFFFFF80000000000 ), + LIT64( 0xFFFFFC0000000000 ), + LIT64( 0xFFFFFE0000000000 ), + LIT64( 0xFFFFFF0000000000 ), + LIT64( 0xFFFFFF8000000000 ), + LIT64( 0xFFFFFFC000000000 ), + LIT64( 0xFFFFFFE000000000 ), + LIT64( 0xFFFFFFF000000000 ), + LIT64( 0xFFFFFFF800000000 ), + LIT64( 0xFFFFFFFC00000000 ), + LIT64( 0xFFFFFFFE00000000 ), + LIT64( 0xFFFFFFFF00000000 ), + LIT64( 0xFFFFFFFF80000000 ), + LIT64( 0xFFFFFFFFC0000000 ), + LIT64( 0xFFFFFFFFE0000000 ), + LIT64( 0xFFFFFFFFF0000000 ), + LIT64( 0xFFFFFFFFF8000000 ), + LIT64( 0xFFFFFFFFFC000000 ), + LIT64( 0xFFFFFFFFFE000000 ), + LIT64( 0xFFFFFFFFFF000000 ), + LIT64( 0xFFFFFFFFFF800000 ), + LIT64( 0xFFFFFFFFFFC00000 ), + LIT64( 0xFFFFFFFFFFE00000 ), + LIT64( 0xFFFFFFFFFFF00000 ), + LIT64( 0xFFFFFFFFFFF80000 ), + LIT64( 0xFFFFFFFFFFFC0000 ), + LIT64( 0xFFFFFFFFFFFE0000 ), + LIT64( 0xFFFFFFFFFFFF0000 ), + LIT64( 0xFFFFFFFFFFFF8000 ), + LIT64( 0xFFFFFFFFFFFFC000 ), + LIT64( 0xFFFFFFFFFFFFE000 ), + LIT64( 0xFFFFFFFFFFFFF000 ), + LIT64( 0xFFFFFFFFFFFFF800 ), + LIT64( 0xFFFFFFFFFFFFFC00 ), + LIT64( 0xFFFFFFFFFFFFFE00 ), + LIT64( 0xFFFFFFFFFFFFFF00 ), + LIT64( 0xFFFFFFFFFFFFFF80 ), + LIT64( 0xFFFFFFFFFFFFFFC0 ), + LIT64( 0xFFFFFFFFFFFFFFE0 ), + LIT64( 0xFFFFFFFFFFFFFFF0 ), + LIT64( 0xFFFFFFFFFFFFFFF8 ), + LIT64( 0xFFFFFFFFFFFFFFFC ), + LIT64( 0xFFFFFFFFFFFFFFFE ), + LIT64( 0xFFFFFFFFFFFFFFFF ), + LIT64( 0xFFFFFFFFFFFFFFFD ), + LIT64( 0xFFFFFFFFFFFFFFFB ), + LIT64( 0xFFFFFFFFFFFFFFF7 ), + LIT64( 0xFFFFFFFFFFFFFFEF ), + LIT64( 0xFFFFFFFFFFFFFFDF ), + LIT64( 0xFFFFFFFFFFFFFFBF ), + LIT64( 0xFFFFFFFFFFFFFF7F ), + LIT64( 0xFFFFFFFFFFFFFEFF ), + LIT64( 0xFFFFFFFFFFFFFDFF ), + LIT64( 0xFFFFFFFFFFFFFBFF ), + LIT64( 0xFFFFFFFFFFFFF7FF ), + LIT64( 0xFFFFFFFFFFFFEFFF ), + LIT64( 0xFFFFFFFFFFFFDFFF ), + LIT64( 0xFFFFFFFFFFFFBFFF ), + LIT64( 0xFFFFFFFFFFFF7FFF ), + LIT64( 0xFFFFFFFFFFFEFFFF ), + LIT64( 0xFFFFFFFFFFFDFFFF ), + LIT64( 0xFFFFFFFFFFFBFFFF ), + LIT64( 0xFFFFFFFFFFF7FFFF ), + LIT64( 0xFFFFFFFFFFEFFFFF ), + LIT64( 0xFFFFFFFFFFDFFFFF ), + LIT64( 0xFFFFFFFFFFBFFFFF ), + LIT64( 0xFFFFFFFFFF7FFFFF ), + LIT64( 0xFFFFFFFFFEFFFFFF ), + LIT64( 0xFFFFFFFFFDFFFFFF ), + LIT64( 0xFFFFFFFFFBFFFFFF ), + LIT64( 0xFFFFFFFFF7FFFFFF ), + LIT64( 0xFFFFFFFFEFFFFFFF ), + LIT64( 0xFFFFFFFFDFFFFFFF ), + LIT64( 0xFFFFFFFFBFFFFFFF ), + LIT64( 0xFFFFFFFF7FFFFFFF ), + LIT64( 0xFFFFFFFEFFFFFFFF ), + LIT64( 0xFFFFFFFDFFFFFFFF ), + LIT64( 0xFFFFFFFBFFFFFFFF ), + LIT64( 0xFFFFFFF7FFFFFFFF ), + LIT64( 0xFFFFFFEFFFFFFFFF ), + LIT64( 0xFFFFFFDFFFFFFFFF ), + LIT64( 0xFFFFFFBFFFFFFFFF ), + LIT64( 0xFFFFFF7FFFFFFFFF ), + LIT64( 0xFFFFFEFFFFFFFFFF ), + LIT64( 0xFFFFFDFFFFFFFFFF ), + LIT64( 0xFFFFFBFFFFFFFFFF ), + LIT64( 0xFFFFF7FFFFFFFFFF ), + LIT64( 0xFFFFEFFFFFFFFFFF ), + LIT64( 0xFFFFDFFFFFFFFFFF ), + LIT64( 0xFFFFBFFFFFFFFFFF ), + LIT64( 0xFFFF7FFFFFFFFFFF ), + LIT64( 0xFFFEFFFFFFFFFFFF ), + LIT64( 0xFFFDFFFFFFFFFFFF ), + LIT64( 0xFFFBFFFFFFFFFFFF ), + LIT64( 0xFFF7FFFFFFFFFFFF ), + LIT64( 0xFFEFFFFFFFFFFFFF ), + LIT64( 0xFFDFFFFFFFFFFFFF ), + LIT64( 0xFFBFFFFFFFFFFFFF ), + LIT64( 0xFF7FFFFFFFFFFFFF ), + LIT64( 0xFEFFFFFFFFFFFFFF ), + LIT64( 0xFDFFFFFFFFFFFFFF ), + LIT64( 0xFBFFFFFFFFFFFFFF ), + LIT64( 0xF7FFFFFFFFFFFFFF ), + LIT64( 0xEFFFFFFFFFFFFFFF ), + LIT64( 0xDFFFFFFFFFFFFFFF ), + LIT64( 0xBFFFFFFFFFFFFFFF ), + LIT64( 0x7FFFFFFFFFFFFFFF ), + LIT64( 0x3FFFFFFFFFFFFFFF ), + LIT64( 0x1FFFFFFFFFFFFFFF ), + LIT64( 0x0FFFFFFFFFFFFFFF ), + LIT64( 0x07FFFFFFFFFFFFFF ), + LIT64( 0x03FFFFFFFFFFFFFF ), + LIT64( 0x01FFFFFFFFFFFFFF ), + LIT64( 0x00FFFFFFFFFFFFFF ), + LIT64( 0x007FFFFFFFFFFFFF ), + LIT64( 0x003FFFFFFFFFFFFF ), + LIT64( 0x001FFFFFFFFFFFFF ), + LIT64( 0x000FFFFFFFFFFFFF ), + LIT64( 0x0007FFFFFFFFFFFF ), + LIT64( 0x0003FFFFFFFFFFFF ), + LIT64( 0x0001FFFFFFFFFFFF ), + LIT64( 0x0000FFFFFFFFFFFF ), + LIT64( 0x00007FFFFFFFFFFF ), + LIT64( 0x00003FFFFFFFFFFF ), + LIT64( 0x00001FFFFFFFFFFF ), + LIT64( 0x00000FFFFFFFFFFF ), + LIT64( 0x000007FFFFFFFFFF ), + LIT64( 0x000003FFFFFFFFFF ), + LIT64( 0x000001FFFFFFFFFF ), + LIT64( 0x000000FFFFFFFFFF ), + LIT64( 0x0000007FFFFFFFFF ), + LIT64( 0x0000003FFFFFFFFF ), + LIT64( 0x0000001FFFFFFFFF ), + LIT64( 0x0000000FFFFFFFFF ), + LIT64( 0x00000007FFFFFFFF ), + LIT64( 0x00000003FFFFFFFF ), + LIT64( 0x00000001FFFFFFFF ), + LIT64( 0x00000000FFFFFFFF ), + LIT64( 0x000000007FFFFFFF ), + LIT64( 0x000000003FFFFFFF ), + LIT64( 0x000000001FFFFFFF ), + LIT64( 0x000000000FFFFFFF ), + LIT64( 0x0000000007FFFFFF ), + LIT64( 0x0000000003FFFFFF ), + LIT64( 0x0000000001FFFFFF ), + LIT64( 0x0000000000FFFFFF ), + LIT64( 0x00000000007FFFFF ), + LIT64( 0x00000000003FFFFF ), + LIT64( 0x00000000001FFFFF ), + LIT64( 0x00000000000FFFFF ), + LIT64( 0x000000000007FFFF ), + LIT64( 0x000000000003FFFF ), + LIT64( 0x000000000001FFFF ), + LIT64( 0x000000000000FFFF ), + LIT64( 0x0000000000007FFF ), + LIT64( 0x0000000000003FFF ), + LIT64( 0x0000000000001FFF ), + LIT64( 0x0000000000000FFF ), + LIT64( 0x00000000000007FF ), + LIT64( 0x00000000000003FF ), + LIT64( 0x00000000000001FF ), + LIT64( 0x00000000000000FF ), + LIT64( 0x000000000000007F ), + LIT64( 0x000000000000003F ), + LIT64( 0x000000000000001F ), + LIT64( 0x000000000000000F ), + LIT64( 0x0000000000000007 ), + LIT64( 0x0000000000000003 ) +}; + +static int64 int64NextP1( sequenceT *sequencePtr ) +{ + uint8 termNum; + int64 z; + + termNum = sequencePtr->term1Num; + z = int64P1[ termNum ]; + ++termNum; + if ( int64NumP1 <= termNum ) { + termNum = 0; + sequencePtr->done = TRUE; + } + sequencePtr->term1Num = termNum; + return (sbits64) z; + +} + +static const int64 int64NumP2 = ( int64NumP1 * int64NumP1 + int64NumP1 ) / 2; + +static int64 int64NextP2( sequenceT *sequencePtr ) +{ + uint8 term1Num, term2Num; + int64 z; + + term2Num = sequencePtr->term2Num; + term1Num = sequencePtr->term1Num; + z = int64P1[ term1Num ] + int64P1[ term2Num ]; + ++term2Num; + if ( int64NumP1 <= term2Num ) { + ++term1Num; + if ( int64NumP1 <= term1Num ) { + term1Num = 0; + sequencePtr->done = TRUE; + } + term2Num = term1Num; + sequencePtr->term1Num = term1Num; + } + sequencePtr->term2Num = term2Num; + return (sbits64) z; + +} + +static int64 int64RandomP3( void ) +{ + + return + (sbits64) ( + int64P1[ randomUint8() % int64NumP1 ] + + int64P1[ randomUint8() % int64NumP1 ] + + int64P1[ randomUint8() % int64NumP1 ] + ); + +} + +enum { + int64NumPInfWeightMasks = 61 +}; + +static const uint64 int64PInfWeightMasks[ int64NumPInfWeightMasks ] = { + LIT64( 0xFFFFFFFFFFFFFFFF ), + LIT64( 0x7FFFFFFFFFFFFFFF ), + LIT64( 0x3FFFFFFFFFFFFFFF ), + LIT64( 0x1FFFFFFFFFFFFFFF ), + LIT64( 0x0FFFFFFFFFFFFFFF ), + LIT64( 0x07FFFFFFFFFFFFFF ), + LIT64( 0x03FFFFFFFFFFFFFF ), + LIT64( 0x01FFFFFFFFFFFFFF ), + LIT64( 0x00FFFFFFFFFFFFFF ), + LIT64( 0x007FFFFFFFFFFFFF ), + LIT64( 0x003FFFFFFFFFFFFF ), + LIT64( 0x001FFFFFFFFFFFFF ), + LIT64( 0x000FFFFFFFFFFFFF ), + LIT64( 0x0007FFFFFFFFFFFF ), + LIT64( 0x0003FFFFFFFFFFFF ), + LIT64( 0x0001FFFFFFFFFFFF ), + LIT64( 0x0000FFFFFFFFFFFF ), + LIT64( 0x00007FFFFFFFFFFF ), + LIT64( 0x00003FFFFFFFFFFF ), + LIT64( 0x00001FFFFFFFFFFF ), + LIT64( 0x00000FFFFFFFFFFF ), + LIT64( 0x000007FFFFFFFFFF ), + LIT64( 0x000003FFFFFFFFFF ), + LIT64( 0x000001FFFFFFFFFF ), + LIT64( 0x000000FFFFFFFFFF ), + LIT64( 0x0000007FFFFFFFFF ), + LIT64( 0x0000003FFFFFFFFF ), + LIT64( 0x0000001FFFFFFFFF ), + LIT64( 0x0000000FFFFFFFFF ), + LIT64( 0x00000007FFFFFFFF ), + LIT64( 0x00000003FFFFFFFF ), + LIT64( 0x00000001FFFFFFFF ), + LIT64( 0x00000000FFFFFFFF ), + LIT64( 0x000000007FFFFFFF ), + LIT64( 0x000000003FFFFFFF ), + LIT64( 0x000000001FFFFFFF ), + LIT64( 0x000000000FFFFFFF ), + LIT64( 0x0000000007FFFFFF ), + LIT64( 0x0000000003FFFFFF ), + LIT64( 0x0000000001FFFFFF ), + LIT64( 0x0000000000FFFFFF ), + LIT64( 0x00000000007FFFFF ), + LIT64( 0x00000000003FFFFF ), + LIT64( 0x00000000001FFFFF ), + LIT64( 0x00000000000FFFFF ), + LIT64( 0x000000000007FFFF ), + LIT64( 0x000000000003FFFF ), + LIT64( 0x000000000001FFFF ), + LIT64( 0x000000000000FFFF ), + LIT64( 0x0000000000007FFF ), + LIT64( 0x0000000000003FFF ), + LIT64( 0x0000000000001FFF ), + LIT64( 0x0000000000000FFF ), + LIT64( 0x00000000000007FF ), + LIT64( 0x00000000000003FF ), + LIT64( 0x00000000000001FF ), + LIT64( 0x00000000000000FF ), + LIT64( 0x000000000000007F ), + LIT64( 0x000000000000003F ), + LIT64( 0x000000000000001F ), + LIT64( 0x000000000000000F ) +}; + +static const uint64 int64PInfWeightOffsets[ int64NumPInfWeightMasks ] = { + LIT64( 0x0000000000000000 ), + LIT64( 0xC000000000000000 ), + LIT64( 0xE000000000000000 ), + LIT64( 0xF000000000000000 ), + LIT64( 0xF800000000000000 ), + LIT64( 0xFC00000000000000 ), + LIT64( 0xFE00000000000000 ), + LIT64( 0xFF00000000000000 ), + LIT64( 0xFF80000000000000 ), + LIT64( 0xFFC0000000000000 ), + LIT64( 0xFFE0000000000000 ), + LIT64( 0xFFF0000000000000 ), + LIT64( 0xFFF8000000000000 ), + LIT64( 0xFFFC000000000000 ), + LIT64( 0xFFFE000000000000 ), + LIT64( 0xFFFF000000000000 ), + LIT64( 0xFFFF800000000000 ), + LIT64( 0xFFFFC00000000000 ), + LIT64( 0xFFFFE00000000000 ), + LIT64( 0xFFFFF00000000000 ), + LIT64( 0xFFFFF80000000000 ), + LIT64( 0xFFFFFC0000000000 ), + LIT64( 0xFFFFFE0000000000 ), + LIT64( 0xFFFFFF0000000000 ), + LIT64( 0xFFFFFF8000000000 ), + LIT64( 0xFFFFFFC000000000 ), + LIT64( 0xFFFFFFE000000000 ), + LIT64( 0xFFFFFFF000000000 ), + LIT64( 0xFFFFFFF800000000 ), + LIT64( 0xFFFFFFFC00000000 ), + LIT64( 0xFFFFFFFE00000000 ), + LIT64( 0xFFFFFFFF00000000 ), + LIT64( 0xFFFFFFFF80000000 ), + LIT64( 0xFFFFFFFFC0000000 ), + LIT64( 0xFFFFFFFFE0000000 ), + LIT64( 0xFFFFFFFFF0000000 ), + LIT64( 0xFFFFFFFFF8000000 ), + LIT64( 0xFFFFFFFFFC000000 ), + LIT64( 0xFFFFFFFFFE000000 ), + LIT64( 0xFFFFFFFFFF000000 ), + LIT64( 0xFFFFFFFFFF800000 ), + LIT64( 0xFFFFFFFFFFC00000 ), + LIT64( 0xFFFFFFFFFFE00000 ), + LIT64( 0xFFFFFFFFFFF00000 ), + LIT64( 0xFFFFFFFFFFF80000 ), + LIT64( 0xFFFFFFFFFFFC0000 ), + LIT64( 0xFFFFFFFFFFFE0000 ), + LIT64( 0xFFFFFFFFFFFF0000 ), + LIT64( 0xFFFFFFFFFFFF8000 ), + LIT64( 0xFFFFFFFFFFFFC000 ), + LIT64( 0xFFFFFFFFFFFFE000 ), + LIT64( 0xFFFFFFFFFFFFF000 ), + LIT64( 0xFFFFFFFFFFFFF800 ), + LIT64( 0xFFFFFFFFFFFFFC00 ), + LIT64( 0xFFFFFFFFFFFFFE00 ), + LIT64( 0xFFFFFFFFFFFFFF00 ), + LIT64( 0xFFFFFFFFFFFFFF80 ), + LIT64( 0xFFFFFFFFFFFFFFC0 ), + LIT64( 0xFFFFFFFFFFFFFFE0 ), + LIT64( 0xFFFFFFFFFFFFFFF0 ), + LIT64( 0xFFFFFFFFFFFFFFF8 ) +}; + +static int64 int64RandomPInf( void ) +{ + int8 weightMaskNum; + + weightMaskNum = randomUint8() % int64NumPInfWeightMasks; + return + (sbits64) ( + ( randomUint64() & int64PInfWeightMasks[ weightMaskNum ] ) + + int64PInfWeightOffsets[ weightMaskNum ] + ); + +} + +#endif + +enum { + float32NumQIn = 22, + float32NumQOut = 50, + float32NumP1 = 4, + float32NumP2 = 88 +}; + +static const uint32 float32QIn[ float32NumQIn ] = { + 0x00000000, /* positive, subnormal */ + 0x00800000, /* positive, -126 */ + 0x33800000, /* positive, -24 */ + 0x3E800000, /* positive, -2 */ + 0x3F000000, /* positive, -1 */ + 0x3F800000, /* positive, 0 */ + 0x40000000, /* positive, 1 */ + 0x40800000, /* positive, 2 */ + 0x4B800000, /* positive, 24 */ + 0x7F000000, /* positive, 127 */ + 0x7F800000, /* positive, infinity or NaN */ + 0x80000000, /* negative, subnormal */ + 0x80800000, /* negative, -126 */ + 0xB3800000, /* negative, -24 */ + 0xBE800000, /* negative, -2 */ + 0xBF000000, /* negative, -1 */ + 0xBF800000, /* negative, 0 */ + 0xC0000000, /* negative, 1 */ + 0xC0800000, /* negative, 2 */ + 0xCB800000, /* negative, 24 */ + 0xFE800000, /* negative, 126 */ + 0xFF800000 /* negative, infinity or NaN */ +}; + +static const uint32 float32QOut[ float32NumQOut ] = { + 0x00000000, /* positive, subnormal */ + 0x00800000, /* positive, -126 */ + 0x01000000, /* positive, -125 */ + 0x33800000, /* positive, -24 */ + 0x3D800000, /* positive, -4 */ + 0x3E000000, /* positive, -3 */ + 0x3E800000, /* positive, -2 */ + 0x3F000000, /* positive, -1 */ + 0x3F800000, /* positive, 0 */ + 0x40000000, /* positive, 1 */ + 0x40800000, /* positive, 2 */ + 0x41000000, /* positive, 3 */ + 0x41800000, /* positive, 4 */ + 0x4B800000, /* positive, 24 */ + 0x4E000000, /* positive, 29 */ + 0x4E800000, /* positive, 30 */ + 0x4F000000, /* positive, 31 */ + 0x4F800000, /* positive, 32 */ + 0x5E000000, /* positive, 61 */ + 0x5E800000, /* positive, 62 */ + 0x5F000000, /* positive, 63 */ + 0x5F800000, /* positive, 64 */ + 0x7E800000, /* positive, 126 */ + 0x7F000000, /* positive, 127 */ + 0x7F800000, /* positive, infinity or NaN */ + 0x80000000, /* negative, subnormal */ + 0x80800000, /* negative, -126 */ + 0x81000000, /* negative, -125 */ + 0xB3800000, /* negative, -24 */ + 0xBD800000, /* negative, -4 */ + 0xBE000000, /* negative, -3 */ + 0xBE800000, /* negative, -2 */ + 0xBF000000, /* negative, -1 */ + 0xBF800000, /* negative, 0 */ + 0xC0000000, /* negative, 1 */ + 0xC0800000, /* negative, 2 */ + 0xC1000000, /* negative, 3 */ + 0xC1800000, /* negative, 4 */ + 0xCB800000, /* negative, 24 */ + 0xCE000000, /* negative, 29 */ + 0xCE800000, /* negative, 30 */ + 0xCF000000, /* negative, 31 */ + 0xCF800000, /* negative, 32 */ + 0xDE000000, /* negative, 61 */ + 0xDE800000, /* negative, 62 */ + 0xDF000000, /* negative, 63 */ + 0xDF800000, /* negative, 64 */ + 0xFE800000, /* negative, 126 */ + 0xFF000000, /* negative, 127 */ + 0xFF800000 /* negative, infinity or NaN */ +}; + +static const uint32 float32P1[ float32NumP1 ] = { + 0x00000000, + 0x00000001, + 0x007FFFFF, + 0x007FFFFE +}; + +static const uint32 float32P2[ float32NumP2 ] = { + 0x00000000, + 0x00000001, + 0x00000002, + 0x00000004, + 0x00000008, + 0x00000010, + 0x00000020, + 0x00000040, + 0x00000080, + 0x00000100, + 0x00000200, + 0x00000400, + 0x00000800, + 0x00001000, + 0x00002000, + 0x00004000, + 0x00008000, + 0x00010000, + 0x00020000, + 0x00040000, + 0x00080000, + 0x00100000, + 0x00200000, + 0x00400000, + 0x00600000, + 0x00700000, + 0x00780000, + 0x007C0000, + 0x007E0000, + 0x007F0000, + 0x007F8000, + 0x007FC000, + 0x007FE000, + 0x007FF000, + 0x007FF800, + 0x007FFC00, + 0x007FFE00, + 0x007FFF00, + 0x007FFF80, + 0x007FFFC0, + 0x007FFFE0, + 0x007FFFF0, + 0x007FFFF8, + 0x007FFFFC, + 0x007FFFFE, + 0x007FFFFF, + 0x007FFFFD, + 0x007FFFFB, + 0x007FFFF7, + 0x007FFFEF, + 0x007FFFDF, + 0x007FFFBF, + 0x007FFF7F, + 0x007FFEFF, + 0x007FFDFF, + 0x007FFBFF, + 0x007FF7FF, + 0x007FEFFF, + 0x007FDFFF, + 0x007FBFFF, + 0x007F7FFF, + 0x007EFFFF, + 0x007DFFFF, + 0x007BFFFF, + 0x0077FFFF, + 0x006FFFFF, + 0x005FFFFF, + 0x003FFFFF, + 0x001FFFFF, + 0x000FFFFF, + 0x0007FFFF, + 0x0003FFFF, + 0x0001FFFF, + 0x0000FFFF, + 0x00007FFF, + 0x00003FFF, + 0x00001FFF, + 0x00000FFF, + 0x000007FF, + 0x000003FF, + 0x000001FF, + 0x000000FF, + 0x0000007F, + 0x0000003F, + 0x0000001F, + 0x0000000F, + 0x00000007, + 0x00000003 +}; + +static const uint32 float32NumQInP1 = float32NumQIn * float32NumP1; +static const uint32 float32NumQOutP1 = float32NumQOut * float32NumP1; + +static float32 float32NextQInP1( sequenceT *sequencePtr ) +{ + uint8 expNum, sigNum; + float32 z; + + sigNum = sequencePtr->term1Num; + expNum = sequencePtr->expNum; + z = float32QIn[ expNum ] | float32P1[ sigNum ]; + ++sigNum; + if ( float32NumP1 <= sigNum ) { + sigNum = 0; + ++expNum; + if ( float32NumQIn <= expNum ) { + expNum = 0; + sequencePtr->done = TRUE; + } + sequencePtr->expNum = expNum; + } + sequencePtr->term1Num = sigNum; + return z; + +} + +static float32 float32NextQOutP1( sequenceT *sequencePtr ) +{ + uint8 expNum, sigNum; + float32 z; + + sigNum = sequencePtr->term1Num; + expNum = sequencePtr->expNum; + z = float32QOut[ expNum ] | float32P1[ sigNum ]; + ++sigNum; + if ( float32NumP1 <= sigNum ) { + sigNum = 0; + ++expNum; + if ( float32NumQOut <= expNum ) { + expNum = 0; + sequencePtr->done = TRUE; + } + sequencePtr->expNum = expNum; + } + sequencePtr->term1Num = sigNum; + return z; + +} + +static const uint32 float32NumQInP2 = float32NumQIn * float32NumP2; +static const uint32 float32NumQOutP2 = float32NumQOut * float32NumP2; + +static float32 float32NextQInP2( sequenceT *sequencePtr ) +{ + uint8 expNum, sigNum; + float32 z; + + sigNum = sequencePtr->term1Num; + expNum = sequencePtr->expNum; + z = float32QIn[ expNum ] | float32P2[ sigNum ]; + ++sigNum; + if ( float32NumP2 <= sigNum ) { + sigNum = 0; + ++expNum; + if ( float32NumQIn <= expNum ) { + expNum = 0; + sequencePtr->done = TRUE; + } + sequencePtr->expNum = expNum; + } + sequencePtr->term1Num = sigNum; + return z; + +} + +static float32 float32NextQOutP2( sequenceT *sequencePtr ) +{ + uint8 expNum, sigNum; + float32 z; + + sigNum = sequencePtr->term1Num; + expNum = sequencePtr->expNum; + z = float32QOut[ expNum ] | float32P2[ sigNum ]; + ++sigNum; + if ( float32NumP2 <= sigNum ) { + sigNum = 0; + ++expNum; + if ( float32NumQOut <= expNum ) { + expNum = 0; + sequencePtr->done = TRUE; + } + sequencePtr->expNum = expNum; + } + sequencePtr->term1Num = sigNum; + return z; + +} + +static float32 float32RandomQOutP3( void ) +{ + + return + float32QOut[ randomUint8() % float32NumQOut ] + | ( ( float32P2[ randomUint8() % float32NumP2 ] + + float32P2[ randomUint8() % float32NumP2 ] ) + & 0x007FFFFF ); + +} + +static float32 float32RandomQOutPInf( void ) +{ + + return + float32QOut[ randomUint8() % float32NumQOut ] + | ( randomUint32() & 0x007FFFFF ); + +} + +enum { + float32NumQInfWeightMasks = 7 +}; + +static const uint32 float32QInfWeightMasks[ float32NumQInfWeightMasks ] = { + 0x7F800000, + 0x7F800000, + 0x3F800000, + 0x1F800000, + 0x0F800000, + 0x07800000, + 0x03800000 +}; + +static const uint32 float32QInfWeightOffsets[ float32NumQInfWeightMasks ] = { + 0x00000000, + 0x00000000, + 0x20000000, + 0x30000000, + 0x38000000, + 0x3C000000, + 0x3E000000 +}; + +static float32 float32RandomQInfP3( void ) +{ + int8 weightMaskNum; + + weightMaskNum = randomUint8() % float32NumQInfWeightMasks; + return + ( ( (uint32) ( randomUint8() & 1 ) )<<31 ) + | ( ( ( ( (uint32) ( randomUint16() & 0x1FF ) )<<23 ) + & float32QInfWeightMasks[ weightMaskNum ] ) + + float32QInfWeightOffsets[ weightMaskNum ] + ) + | ( ( float32P2[ randomUint8() % float32NumP2 ] + + float32P2[ randomUint8() % float32NumP2 ] ) + & 0x007FFFFF ); + +} + +static float32 float32RandomQInfPInf( void ) +{ + int8 weightMaskNum; + + weightMaskNum = randomUint8() % float32NumQInfWeightMasks; + return + ( ( (uint32) ( randomUint8() & 1 ) )<<31 ) + | ( ( ( ( (uint32) ( randomUint16() & 0x1FF ) )<<23 ) + & float32QInfWeightMasks[ weightMaskNum ] ) + + float32QInfWeightOffsets[ weightMaskNum ] + ) + | ( randomUint32() & 0x007FFFFF ); + +} + +static float32 float32Random( void ) +{ + + switch ( randomUint8() & 7 ) { + case 0: + case 1: + case 2: + return float32RandomQOutP3(); + case 3: + return float32RandomQOutPInf(); + case 4: + case 5: + case 6: + return float32RandomQInfP3(); + default: + return float32RandomQInfPInf(); + } + +} + +#ifdef BITS64 +#define SETFLOAT64( z, zHigh, zLow ) z = ( ( (float64) zHigh )<<32 ) | zLow +#else +#define SETFLOAT64( z, zHigh, zLow ) z.low = zLow; z.high = zHigh +#endif + +enum { + float64NumQIn = 22, + float64NumQOut = 64, + float64NumP1 = 4, + float64NumP2 = 204 +}; + +static const uint32 float64QIn[ float64NumQIn ] = { + 0x00000000, /* positive, subnormal */ + 0x00100000, /* positive, -1022 */ + 0x3CA00000, /* positive, -53 */ + 0x3FD00000, /* positive, -2 */ + 0x3FE00000, /* positive, -1 */ + 0x3FF00000, /* positive, 0 */ + 0x40000000, /* positive, 1 */ + 0x40100000, /* positive, 2 */ + 0x43400000, /* positive, 53 */ + 0x7FE00000, /* positive, 1023 */ + 0x7FF00000, /* positive, infinity or NaN */ + 0x80000000, /* negative, subnormal */ + 0x80100000, /* negative, -1022 */ + 0xBCA00000, /* negative, -53 */ + 0xBFD00000, /* negative, -2 */ + 0xBFE00000, /* negative, -1 */ + 0xBFF00000, /* negative, 0 */ + 0xC0000000, /* negative, 1 */ + 0xC0100000, /* negative, 2 */ + 0xC3400000, /* negative, 53 */ + 0xFFE00000, /* negative, 1023 */ + 0xFFF00000 /* negative, infinity or NaN */ +}; + +static const uint32 float64QOut[ float64NumQOut ] = { + 0x00000000, /* positive, subnormal */ + 0x00100000, /* positive, -1022 */ + 0x00200000, /* positive, -1021 */ + 0x37E00000, /* positive, -129 */ + 0x37F00000, /* positive, -128 */ + 0x38000000, /* positive, -127 */ + 0x38100000, /* positive, -126 */ + 0x3CA00000, /* positive, -53 */ + 0x3FB00000, /* positive, -4 */ + 0x3FC00000, /* positive, -3 */ + 0x3FD00000, /* positive, -2 */ + 0x3FE00000, /* positive, -1 */ + 0x3FF00000, /* positive, 0 */ + 0x40000000, /* positive, 1 */ + 0x40100000, /* positive, 2 */ + 0x40200000, /* positive, 3 */ + 0x40300000, /* positive, 4 */ + 0x41C00000, /* positive, 29 */ + 0x41D00000, /* positive, 30 */ + 0x41E00000, /* positive, 31 */ + 0x41F00000, /* positive, 32 */ + 0x43400000, /* positive, 53 */ + 0x43C00000, /* positive, 61 */ + 0x43D00000, /* positive, 62 */ + 0x43E00000, /* positive, 63 */ + 0x43F00000, /* positive, 64 */ + 0x47E00000, /* positive, 127 */ + 0x47F00000, /* positive, 128 */ + 0x48000000, /* positive, 129 */ + 0x7FD00000, /* positive, 1022 */ + 0x7FE00000, /* positive, 1023 */ + 0x7FF00000, /* positive, infinity or NaN */ + 0x80000000, /* negative, subnormal */ + 0x80100000, /* negative, -1022 */ + 0x80200000, /* negative, -1021 */ + 0xB7E00000, /* negative, -129 */ + 0xB7F00000, /* negative, -128 */ + 0xB8000000, /* negative, -127 */ + 0xB8100000, /* negative, -126 */ + 0xBCA00000, /* negative, -53 */ + 0xBFB00000, /* negative, -4 */ + 0xBFC00000, /* negative, -3 */ + 0xBFD00000, /* negative, -2 */ + 0xBFE00000, /* negative, -1 */ + 0xBFF00000, /* negative, 0 */ + 0xC0000000, /* negative, 1 */ + 0xC0100000, /* negative, 2 */ + 0xC0200000, /* negative, 3 */ + 0xC0300000, /* negative, 4 */ + 0xC1C00000, /* negative, 29 */ + 0xC1D00000, /* negative, 30 */ + 0xC1E00000, /* negative, 31 */ + 0xC1F00000, /* negative, 32 */ + 0xC3400000, /* negative, 53 */ + 0xC3C00000, /* negative, 61 */ + 0xC3D00000, /* negative, 62 */ + 0xC3E00000, /* negative, 63 */ + 0xC3F00000, /* negative, 64 */ + 0xC7E00000, /* negative, 127 */ + 0xC7F00000, /* negative, 128 */ + 0xC8000000, /* negative, 129 */ + 0xFFD00000, /* negative, 1022 */ + 0xFFE00000, /* negative, 1023 */ + 0xFFF00000 /* negative, infinity or NaN */ +}; + +static const struct { bits32 high, low; } float64P1[ float64NumP1 ] = { + { 0x00000000, 0x00000000 }, + { 0x00000000, 0x00000001 }, + { 0x000FFFFF, 0xFFFFFFFF }, + { 0x000FFFFF, 0xFFFFFFFE } +}; + +static const struct { bits32 high, low; } float64P2[ float64NumP2 ] = { + { 0x00000000, 0x00000000 }, + { 0x00000000, 0x00000001 }, + { 0x00000000, 0x00000002 }, + { 0x00000000, 0x00000004 }, + { 0x00000000, 0x00000008 }, + { 0x00000000, 0x00000010 }, + { 0x00000000, 0x00000020 }, + { 0x00000000, 0x00000040 }, + { 0x00000000, 0x00000080 }, + { 0x00000000, 0x00000100 }, + { 0x00000000, 0x00000200 }, + { 0x00000000, 0x00000400 }, + { 0x00000000, 0x00000800 }, + { 0x00000000, 0x00001000 }, + { 0x00000000, 0x00002000 }, + { 0x00000000, 0x00004000 }, + { 0x00000000, 0x00008000 }, + { 0x00000000, 0x00010000 }, + { 0x00000000, 0x00020000 }, + { 0x00000000, 0x00040000 }, + { 0x00000000, 0x00080000 }, + { 0x00000000, 0x00100000 }, + { 0x00000000, 0x00200000 }, + { 0x00000000, 0x00400000 }, + { 0x00000000, 0x00800000 }, + { 0x00000000, 0x01000000 }, + { 0x00000000, 0x02000000 }, + { 0x00000000, 0x04000000 }, + { 0x00000000, 0x08000000 }, + { 0x00000000, 0x10000000 }, + { 0x00000000, 0x20000000 }, + { 0x00000000, 0x40000000 }, + { 0x00000000, 0x80000000 }, + { 0x00000001, 0x00000000 }, + { 0x00000002, 0x00000000 }, + { 0x00000004, 0x00000000 }, + { 0x00000008, 0x00000000 }, + { 0x00000010, 0x00000000 }, + { 0x00000020, 0x00000000 }, + { 0x00000040, 0x00000000 }, + { 0x00000080, 0x00000000 }, + { 0x00000100, 0x00000000 }, + { 0x00000200, 0x00000000 }, + { 0x00000400, 0x00000000 }, + { 0x00000800, 0x00000000 }, + { 0x00001000, 0x00000000 }, + { 0x00002000, 0x00000000 }, + { 0x00004000, 0x00000000 }, + { 0x00008000, 0x00000000 }, + { 0x00010000, 0x00000000 }, + { 0x00020000, 0x00000000 }, + { 0x00040000, 0x00000000 }, + { 0x00080000, 0x00000000 }, + { 0x000C0000, 0x00000000 }, + { 0x000E0000, 0x00000000 }, + { 0x000F0000, 0x00000000 }, + { 0x000F8000, 0x00000000 }, + { 0x000FC000, 0x00000000 }, + { 0x000FE000, 0x00000000 }, + { 0x000FF000, 0x00000000 }, + { 0x000FF800, 0x00000000 }, + { 0x000FFC00, 0x00000000 }, + { 0x000FFE00, 0x00000000 }, + { 0x000FFF00, 0x00000000 }, + { 0x000FFF80, 0x00000000 }, + { 0x000FFFC0, 0x00000000 }, + { 0x000FFFE0, 0x00000000 }, + { 0x000FFFF0, 0x00000000 }, + { 0x000FFFF8, 0x00000000 }, + { 0x000FFFFC, 0x00000000 }, + { 0x000FFFFE, 0x00000000 }, + { 0x000FFFFF, 0x00000000 }, + { 0x000FFFFF, 0x80000000 }, + { 0x000FFFFF, 0xC0000000 }, + { 0x000FFFFF, 0xE0000000 }, + { 0x000FFFFF, 0xF0000000 }, + { 0x000FFFFF, 0xF8000000 }, + { 0x000FFFFF, 0xFC000000 }, + { 0x000FFFFF, 0xFE000000 }, + { 0x000FFFFF, 0xFF000000 }, + { 0x000FFFFF, 0xFF800000 }, + { 0x000FFFFF, 0xFFC00000 }, + { 0x000FFFFF, 0xFFE00000 }, + { 0x000FFFFF, 0xFFF00000 }, + { 0x000FFFFF, 0xFFF80000 }, + { 0x000FFFFF, 0xFFFC0000 }, + { 0x000FFFFF, 0xFFFE0000 }, + { 0x000FFFFF, 0xFFFF0000 }, + { 0x000FFFFF, 0xFFFF8000 }, + { 0x000FFFFF, 0xFFFFC000 }, + { 0x000FFFFF, 0xFFFFE000 }, + { 0x000FFFFF, 0xFFFFF000 }, + { 0x000FFFFF, 0xFFFFF800 }, + { 0x000FFFFF, 0xFFFFFC00 }, + { 0x000FFFFF, 0xFFFFFE00 }, + { 0x000FFFFF, 0xFFFFFF00 }, + { 0x000FFFFF, 0xFFFFFF80 }, + { 0x000FFFFF, 0xFFFFFFC0 }, + { 0x000FFFFF, 0xFFFFFFE0 }, + { 0x000FFFFF, 0xFFFFFFF0 }, + { 0x000FFFFF, 0xFFFFFFF8 }, + { 0x000FFFFF, 0xFFFFFFFC }, + { 0x000FFFFF, 0xFFFFFFFE }, + { 0x000FFFFF, 0xFFFFFFFF }, + { 0x000FFFFF, 0xFFFFFFFD }, + { 0x000FFFFF, 0xFFFFFFFB }, + { 0x000FFFFF, 0xFFFFFFF7 }, + { 0x000FFFFF, 0xFFFFFFEF }, + { 0x000FFFFF, 0xFFFFFFDF }, + { 0x000FFFFF, 0xFFFFFFBF }, + { 0x000FFFFF, 0xFFFFFF7F }, + { 0x000FFFFF, 0xFFFFFEFF }, + { 0x000FFFFF, 0xFFFFFDFF }, + { 0x000FFFFF, 0xFFFFFBFF }, + { 0x000FFFFF, 0xFFFFF7FF }, + { 0x000FFFFF, 0xFFFFEFFF }, + { 0x000FFFFF, 0xFFFFDFFF }, + { 0x000FFFFF, 0xFFFFBFFF }, + { 0x000FFFFF, 0xFFFF7FFF }, + { 0x000FFFFF, 0xFFFEFFFF }, + { 0x000FFFFF, 0xFFFDFFFF }, + { 0x000FFFFF, 0xFFFBFFFF }, + { 0x000FFFFF, 0xFFF7FFFF }, + { 0x000FFFFF, 0xFFEFFFFF }, + { 0x000FFFFF, 0xFFDFFFFF }, + { 0x000FFFFF, 0xFFBFFFFF }, + { 0x000FFFFF, 0xFF7FFFFF }, + { 0x000FFFFF, 0xFEFFFFFF }, + { 0x000FFFFF, 0xFDFFFFFF }, + { 0x000FFFFF, 0xFBFFFFFF }, + { 0x000FFFFF, 0xF7FFFFFF }, + { 0x000FFFFF, 0xEFFFFFFF }, + { 0x000FFFFF, 0xDFFFFFFF }, + { 0x000FFFFF, 0xBFFFFFFF }, + { 0x000FFFFF, 0x7FFFFFFF }, + { 0x000FFFFE, 0xFFFFFFFF }, + { 0x000FFFFD, 0xFFFFFFFF }, + { 0x000FFFFB, 0xFFFFFFFF }, + { 0x000FFFF7, 0xFFFFFFFF }, + { 0x000FFFEF, 0xFFFFFFFF }, + { 0x000FFFDF, 0xFFFFFFFF }, + { 0x000FFFBF, 0xFFFFFFFF }, + { 0x000FFF7F, 0xFFFFFFFF }, + { 0x000FFEFF, 0xFFFFFFFF }, + { 0x000FFDFF, 0xFFFFFFFF }, + { 0x000FFBFF, 0xFFFFFFFF }, + { 0x000FF7FF, 0xFFFFFFFF }, + { 0x000FEFFF, 0xFFFFFFFF }, + { 0x000FDFFF, 0xFFFFFFFF }, + { 0x000FBFFF, 0xFFFFFFFF }, + { 0x000F7FFF, 0xFFFFFFFF }, + { 0x000EFFFF, 0xFFFFFFFF }, + { 0x000DFFFF, 0xFFFFFFFF }, + { 0x000BFFFF, 0xFFFFFFFF }, + { 0x0007FFFF, 0xFFFFFFFF }, + { 0x0003FFFF, 0xFFFFFFFF }, + { 0x0001FFFF, 0xFFFFFFFF }, + { 0x0000FFFF, 0xFFFFFFFF }, + { 0x00007FFF, 0xFFFFFFFF }, + { 0x00003FFF, 0xFFFFFFFF }, + { 0x00001FFF, 0xFFFFFFFF }, + { 0x00000FFF, 0xFFFFFFFF }, + { 0x000007FF, 0xFFFFFFFF }, + { 0x000003FF, 0xFFFFFFFF }, + { 0x000001FF, 0xFFFFFFFF }, + { 0x000000FF, 0xFFFFFFFF }, + { 0x0000007F, 0xFFFFFFFF }, + { 0x0000003F, 0xFFFFFFFF }, + { 0x0000001F, 0xFFFFFFFF }, + { 0x0000000F, 0xFFFFFFFF }, + { 0x00000007, 0xFFFFFFFF }, + { 0x00000003, 0xFFFFFFFF }, + { 0x00000001, 0xFFFFFFFF }, + { 0x00000000, 0xFFFFFFFF }, + { 0x00000000, 0x7FFFFFFF }, + { 0x00000000, 0x3FFFFFFF }, + { 0x00000000, 0x1FFFFFFF }, + { 0x00000000, 0x0FFFFFFF }, + { 0x00000000, 0x07FFFFFF }, + { 0x00000000, 0x03FFFFFF }, + { 0x00000000, 0x01FFFFFF }, + { 0x00000000, 0x00FFFFFF }, + { 0x00000000, 0x007FFFFF }, + { 0x00000000, 0x003FFFFF }, + { 0x00000000, 0x001FFFFF }, + { 0x00000000, 0x000FFFFF }, + { 0x00000000, 0x0007FFFF }, + { 0x00000000, 0x0003FFFF }, + { 0x00000000, 0x0001FFFF }, + { 0x00000000, 0x0000FFFF }, + { 0x00000000, 0x00007FFF }, + { 0x00000000, 0x00003FFF }, + { 0x00000000, 0x00001FFF }, + { 0x00000000, 0x00000FFF }, + { 0x00000000, 0x000007FF }, + { 0x00000000, 0x000003FF }, + { 0x00000000, 0x000001FF }, + { 0x00000000, 0x000000FF }, + { 0x00000000, 0x0000007F }, + { 0x00000000, 0x0000003F }, + { 0x00000000, 0x0000001F }, + { 0x00000000, 0x0000000F }, + { 0x00000000, 0x00000007 }, + { 0x00000000, 0x00000003 } +}; + +static const uint32 float64NumQInP1 = float64NumQIn * float64NumP1; +static const uint32 float64NumQOutP1 = float64NumQOut * float64NumP1; + +static float64 float64NextQInP1( sequenceT *sequencePtr ) +{ + uint8 expNum, sigNum; + float64 z; + + sigNum = sequencePtr->term1Num; + expNum = sequencePtr->expNum; + SETFLOAT64( + z, + float64QIn[ expNum ] | float64P1[ sigNum ].high, + float64P1[ sigNum ].low + ); + ++sigNum; + if ( float64NumP1 <= sigNum ) { + sigNum = 0; + ++expNum; + if ( float64NumQIn <= expNum ) { + expNum = 0; + sequencePtr->done = TRUE; + } + sequencePtr->expNum = expNum; + } + sequencePtr->term1Num = sigNum; + return z; + +} + +static float64 float64NextQOutP1( sequenceT *sequencePtr ) +{ + uint8 expNum, sigNum; + float64 z; + + sigNum = sequencePtr->term1Num; + expNum = sequencePtr->expNum; + SETFLOAT64( + z, + float64QOut[ expNum ] | float64P1[ sigNum ].high, + float64P1[ sigNum ].low + ); + ++sigNum; + if ( float64NumP1 <= sigNum ) { + sigNum = 0; + ++expNum; + if ( float64NumQOut <= expNum ) { + expNum = 0; + sequencePtr->done = TRUE; + } + sequencePtr->expNum = expNum; + } + sequencePtr->term1Num = sigNum; + return z; + +} + +static const uint32 float64NumQInP2 = float64NumQIn * float64NumP2; +static const uint32 float64NumQOutP2 = float64NumQOut * float64NumP2; + +static float64 float64NextQInP2( sequenceT *sequencePtr ) +{ + uint8 expNum, sigNum; + float64 z; + + sigNum = sequencePtr->term1Num; + expNum = sequencePtr->expNum; + SETFLOAT64( + z, + float64QIn[ expNum ] | float64P2[ sigNum ].high, + float64P2[ sigNum ].low + ); + ++sigNum; + if ( float64NumP2 <= sigNum ) { + sigNum = 0; + ++expNum; + if ( float64NumQIn <= expNum ) { + expNum = 0; + sequencePtr->done = TRUE; + } + sequencePtr->expNum = expNum; + } + sequencePtr->term1Num = sigNum; + return z; + +} + +static float64 float64NextQOutP2( sequenceT *sequencePtr ) +{ + uint8 expNum, sigNum; + float64 z; + + sigNum = sequencePtr->term1Num; + expNum = sequencePtr->expNum; + SETFLOAT64( + z, + float64QOut[ expNum ] | float64P2[ sigNum ].high, + float64P2[ sigNum ].low + ); + ++sigNum; + if ( float64NumP2 <= sigNum ) { + sigNum = 0; + ++expNum; + if ( float64NumQOut <= expNum ) { + expNum = 0; + sequencePtr->done = TRUE; + } + sequencePtr->expNum = expNum; + } + sequencePtr->term1Num = sigNum; + return z; + +} + +static float64 float64RandomQOutP3( void ) +{ + int8 sigNum1, sigNum2; + uint32 sig1Low, sig2Low, zLow; + float64 z; + + sigNum1 = randomUint8() % float64NumP2; + sigNum2 = randomUint8() % float64NumP2; + sig1Low = float64P2[ sigNum1 ].low; + sig2Low = float64P2[ sigNum2 ].low; + zLow = sig1Low + sig2Low; + SETFLOAT64( + z, + float64QOut[ randomUint8() % float64NumQOut ] + | ( ( float64P2[ sigNum1 ].high + + float64P2[ sigNum2 ].high + + ( zLow < sig1Low ) + ) + & 0x000FFFFF + ), + zLow + ); + return z; + +} + +static float64 float64RandomQOutPInf( void ) +{ + float64 z; + + SETFLOAT64( + z, + float64QOut[ randomUint8() % float64NumQOut ] + | ( randomUint32() & 0x000FFFFF ), + randomUint32() + ); + return z; + +} + +enum { + float64NumQInfWeightMasks = 10 +}; + +static const uint32 float64QInfWeightMasks[ float64NumQInfWeightMasks ] = { + 0x7FF00000, + 0x7FF00000, + 0x3FF00000, + 0x1FF00000, + 0x0FF00000, + 0x07F00000, + 0x03F00000, + 0x01F00000, + 0x00F00000, + 0x00700000 +}; + +static const uint32 float64QInfWeightOffsets[ float64NumQInfWeightMasks ] = { + 0x00000000, + 0x00000000, + 0x20000000, + 0x30000000, + 0x38000000, + 0x3C000000, + 0x3E000000, + 0x3F000000, + 0x3F800000, + 0x3FC00000 +}; + +static float64 float64RandomQInfP3( void ) +{ + int8 sigNum1, sigNum2; + uint32 sig1Low, sig2Low, zLow; + int8 weightMaskNum; + float64 z; + + sigNum1 = randomUint8() % float64NumP2; + sigNum2 = randomUint8() % float64NumP2; + sig1Low = float64P2[ sigNum1 ].low; + sig2Low = float64P2[ sigNum2 ].low; + zLow = sig1Low + sig2Low; + weightMaskNum = randomUint8() % float64NumQInfWeightMasks; + SETFLOAT64( + z, + ( ( (uint32) ( randomUint8() & 1 ) )<<31 ) + | ( ( ( ( (uint32) ( randomUint16() & 0xFFF ) )<<20 ) + & float64QInfWeightMasks[ weightMaskNum ] ) + + float64QInfWeightOffsets[ weightMaskNum ] + ) + | ( ( float64P2[ sigNum1 ].high + + float64P2[ sigNum2 ].high + + ( zLow < sig1Low ) + ) + & 0x000FFFFF + ), + zLow + ); + return z; + +} + +static float64 float64RandomQInfPInf( void ) +{ + int8 weightMaskNum; + float64 z; + + weightMaskNum = randomUint8() % float64NumQInfWeightMasks; + SETFLOAT64( + z, + ( ( (uint32) ( randomUint8() & 1 ) )<<31 ) + | ( ( ( ( (uint32) ( randomUint16() & 0xFFF ) )<<20 ) + & float64QInfWeightMasks[ weightMaskNum ] ) + + float64QInfWeightOffsets[ weightMaskNum ] + ) + | ( randomUint32() & 0x000FFFFF ), + randomUint32() + ); + return z; + +} + +static float64 float64Random( void ) +{ + + switch ( randomUint8() & 7 ) { + case 0: + case 1: + case 2: + return float64RandomQOutP3(); + case 3: + return float64RandomQOutPInf(); + case 4: + case 5: + case 6: + return float64RandomQInfP3(); + default: + return float64RandomQInfPInf(); + } + +} + +#ifdef FLOATX80 + +enum { + floatx80NumQIn = 22, + floatx80NumQOut = 76, + floatx80NumP1 = 4, + floatx80NumP2 = 248 +}; + +static const uint16 floatx80QIn[ floatx80NumQIn ] = { + 0x0000, /* positive, subnormal */ + 0x0001, /* positive, -16382 */ + 0x3FBF, /* positive, -64 */ + 0x3FFD, /* positive, -2 */ + 0x3FFE, /* positive, -1 */ + 0x3FFF, /* positive, 0 */ + 0x4000, /* positive, 1 */ + 0x4001, /* positive, 2 */ + 0x403F, /* positive, 64 */ + 0x7FFE, /* positive, 16383 */ + 0x7FFF, /* positive, infinity or NaN */ + 0x8000, /* negative, subnormal */ + 0x8001, /* negative, -16382 */ + 0xBFBF, /* negative, -64 */ + 0xBFFD, /* negative, -2 */ + 0xBFFE, /* negative, -1 */ + 0xBFFF, /* negative, 0 */ + 0xC000, /* negative, 1 */ + 0xC001, /* negative, 2 */ + 0xC03F, /* negative, 64 */ + 0xFFFE, /* negative, 16383 */ + 0xFFFF /* negative, infinity or NaN */ +}; + +static const uint16 floatx80QOut[ floatx80NumQOut ] = { + 0x0000, /* positive, subnormal */ + 0x0001, /* positive, -16382 */ + 0x0002, /* positive, -16381 */ + 0x3BFE, /* positive, -1025 */ + 0x3BFF, /* positive, -1024 */ + 0x3C00, /* positive, -1023 */ + 0x3C01, /* positive, -1022 */ + 0x3F7E, /* positive, -129 */ + 0x3F7F, /* positive, -128 */ + 0x3F80, /* positive, -127 */ + 0x3F81, /* positive, -126 */ + 0x3FBF, /* positive, -64 */ + 0x3FFB, /* positive, -4 */ + 0x3FFC, /* positive, -3 */ + 0x3FFD, /* positive, -2 */ + 0x3FFE, /* positive, -1 */ + 0x3FFF, /* positive, 0 */ + 0x4000, /* positive, 1 */ + 0x4001, /* positive, 2 */ + 0x4002, /* positive, 3 */ + 0x4003, /* positive, 4 */ + 0x401C, /* positive, 29 */ + 0x401D, /* positive, 30 */ + 0x401E, /* positive, 31 */ + 0x401F, /* positive, 32 */ + 0x403C, /* positive, 61 */ + 0x403D, /* positive, 62 */ + 0x403E, /* positive, 63 */ + 0x403F, /* positive, 64 */ + 0x407E, /* positive, 127 */ + 0x407F, /* positive, 128 */ + 0x4080, /* positive, 129 */ + 0x43FE, /* positive, 1023 */ + 0x43FF, /* positive, 1024 */ + 0x4400, /* positive, 1025 */ + 0x7FFD, /* positive, 16382 */ + 0x7FFE, /* positive, 16383 */ + 0x7FFF, /* positive, infinity or NaN */ + 0x8000, /* negative, subnormal */ + 0x8001, /* negative, -16382 */ + 0x8002, /* negative, -16381 */ + 0xBBFE, /* negative, -1025 */ + 0xBBFF, /* negative, -1024 */ + 0xBC00, /* negative, -1023 */ + 0xBC01, /* negative, -1022 */ + 0xBF7E, /* negative, -129 */ + 0xBF7F, /* negative, -128 */ + 0xBF80, /* negative, -127 */ + 0xBF81, /* negative, -126 */ + 0xBFBF, /* negative, -64 */ + 0xBFFB, /* negative, -4 */ + 0xBFFC, /* negative, -3 */ + 0xBFFD, /* negative, -2 */ + 0xBFFE, /* negative, -1 */ + 0xBFFF, /* negative, 0 */ + 0xC000, /* negative, 1 */ + 0xC001, /* negative, 2 */ + 0xC002, /* negative, 3 */ + 0xC003, /* negative, 4 */ + 0xC01C, /* negative, 29 */ + 0xC01D, /* negative, 30 */ + 0xC01E, /* negative, 31 */ + 0xC01F, /* negative, 32 */ + 0xC03C, /* negative, 61 */ + 0xC03D, /* negative, 62 */ + 0xC03E, /* negative, 63 */ + 0xC03F, /* negative, 64 */ + 0xC07E, /* negative, 127 */ + 0xC07F, /* negative, 128 */ + 0xC080, /* negative, 129 */ + 0xC3FE, /* negative, 1023 */ + 0xC3FF, /* negative, 1024 */ + 0xC400, /* negative, 1025 */ + 0xFFFD, /* negative, 16382 */ + 0xFFFE, /* negative, 16383 */ + 0xFFFF /* negative, infinity or NaN */ +}; + +static const bits64 floatx80P1[ floatx80NumP1 ] = { + LIT64( 0x0000000000000000 ), + LIT64( 0x0000000000000001 ), + LIT64( 0x7FFFFFFFFFFFFFFF ), + LIT64( 0x7FFFFFFFFFFFFFFE ) +}; + +static const bits64 floatx80P2[ floatx80NumP2 ] = { + LIT64( 0x0000000000000000 ), + LIT64( 0x0000000000000001 ), + LIT64( 0x0000000000000002 ), + LIT64( 0x0000000000000004 ), + LIT64( 0x0000000000000008 ), + LIT64( 0x0000000000000010 ), + LIT64( 0x0000000000000020 ), + LIT64( 0x0000000000000040 ), + LIT64( 0x0000000000000080 ), + LIT64( 0x0000000000000100 ), + LIT64( 0x0000000000000200 ), + LIT64( 0x0000000000000400 ), + LIT64( 0x0000000000000800 ), + LIT64( 0x0000000000001000 ), + LIT64( 0x0000000000002000 ), + LIT64( 0x0000000000004000 ), + LIT64( 0x0000000000008000 ), + LIT64( 0x0000000000010000 ), + LIT64( 0x0000000000020000 ), + LIT64( 0x0000000000040000 ), + LIT64( 0x0000000000080000 ), + LIT64( 0x0000000000100000 ), + LIT64( 0x0000000000200000 ), + LIT64( 0x0000000000400000 ), + LIT64( 0x0000000000800000 ), + LIT64( 0x0000000001000000 ), + LIT64( 0x0000000002000000 ), + LIT64( 0x0000000004000000 ), + LIT64( 0x0000000008000000 ), + LIT64( 0x0000000010000000 ), + LIT64( 0x0000000020000000 ), + LIT64( 0x0000000040000000 ), + LIT64( 0x0000000080000000 ), + LIT64( 0x0000000100000000 ), + LIT64( 0x0000000200000000 ), + LIT64( 0x0000000400000000 ), + LIT64( 0x0000000800000000 ), + LIT64( 0x0000001000000000 ), + LIT64( 0x0000002000000000 ), + LIT64( 0x0000004000000000 ), + LIT64( 0x0000008000000000 ), + LIT64( 0x0000010000000000 ), + LIT64( 0x0000020000000000 ), + LIT64( 0x0000040000000000 ), + LIT64( 0x0000080000000000 ), + LIT64( 0x0000100000000000 ), + LIT64( 0x0000200000000000 ), + LIT64( 0x0000400000000000 ), + LIT64( 0x0000800000000000 ), + LIT64( 0x0001000000000000 ), + LIT64( 0x0002000000000000 ), + LIT64( 0x0004000000000000 ), + LIT64( 0x0008000000000000 ), + LIT64( 0x0010000000000000 ), + LIT64( 0x0020000000000000 ), + LIT64( 0x0040000000000000 ), + LIT64( 0x0080000000000000 ), + LIT64( 0x0100000000000000 ), + LIT64( 0x0200000000000000 ), + LIT64( 0x0400000000000000 ), + LIT64( 0x0800000000000000 ), + LIT64( 0x1000000000000000 ), + LIT64( 0x2000000000000000 ), + LIT64( 0x4000000000000000 ), + LIT64( 0x6000000000000000 ), + LIT64( 0x7000000000000000 ), + LIT64( 0x7800000000000000 ), + LIT64( 0x7C00000000000000 ), + LIT64( 0x7E00000000000000 ), + LIT64( 0x7F00000000000000 ), + LIT64( 0x7F80000000000000 ), + LIT64( 0x7FC0000000000000 ), + LIT64( 0x7FE0000000000000 ), + LIT64( 0x7FF0000000000000 ), + LIT64( 0x7FF8000000000000 ), + LIT64( 0x7FFC000000000000 ), + LIT64( 0x7FFE000000000000 ), + LIT64( 0x7FFF000000000000 ), + LIT64( 0x7FFF800000000000 ), + LIT64( 0x7FFFC00000000000 ), + LIT64( 0x7FFFE00000000000 ), + LIT64( 0x7FFFF00000000000 ), + LIT64( 0x7FFFF80000000000 ), + LIT64( 0x7FFFFC0000000000 ), + LIT64( 0x7FFFFE0000000000 ), + LIT64( 0x7FFFFF0000000000 ), + LIT64( 0x7FFFFF8000000000 ), + LIT64( 0x7FFFFFC000000000 ), + LIT64( 0x7FFFFFE000000000 ), + LIT64( 0x7FFFFFF000000000 ), + LIT64( 0x7FFFFFF800000000 ), + LIT64( 0x7FFFFFFC00000000 ), + LIT64( 0x7FFFFFFE00000000 ), + LIT64( 0x7FFFFFFF00000000 ), + LIT64( 0x7FFFFFFF80000000 ), + LIT64( 0x7FFFFFFFC0000000 ), + LIT64( 0x7FFFFFFFE0000000 ), + LIT64( 0x7FFFFFFFF0000000 ), + LIT64( 0x7FFFFFFFF8000000 ), + LIT64( 0x7FFFFFFFFC000000 ), + LIT64( 0x7FFFFFFFFE000000 ), + LIT64( 0x7FFFFFFFFF000000 ), + LIT64( 0x7FFFFFFFFF800000 ), + LIT64( 0x7FFFFFFFFFC00000 ), + LIT64( 0x7FFFFFFFFFE00000 ), + LIT64( 0x7FFFFFFFFFF00000 ), + LIT64( 0x7FFFFFFFFFF80000 ), + LIT64( 0x7FFFFFFFFFFC0000 ), + LIT64( 0x7FFFFFFFFFFE0000 ), + LIT64( 0x7FFFFFFFFFFF0000 ), + LIT64( 0x7FFFFFFFFFFF8000 ), + LIT64( 0x7FFFFFFFFFFFC000 ), + LIT64( 0x7FFFFFFFFFFFE000 ), + LIT64( 0x7FFFFFFFFFFFF000 ), + LIT64( 0x7FFFFFFFFFFFF800 ), + LIT64( 0x7FFFFFFFFFFFFC00 ), + LIT64( 0x7FFFFFFFFFFFFE00 ), + LIT64( 0x7FFFFFFFFFFFFF00 ), + LIT64( 0x7FFFFFFFFFFFFF80 ), + LIT64( 0x7FFFFFFFFFFFFFC0 ), + LIT64( 0x7FFFFFFFFFFFFFE0 ), + LIT64( 0x7FFFFFFFFFFFFFF0 ), + LIT64( 0x7FFFFFFFFFFFFFF8 ), + LIT64( 0x7FFFFFFFFFFFFFFC ), + LIT64( 0x7FFFFFFFFFFFFFFE ), + LIT64( 0x7FFFFFFFFFFFFFFF ), + LIT64( 0x7FFFFFFFFFFFFFFD ), + LIT64( 0x7FFFFFFFFFFFFFFB ), + LIT64( 0x7FFFFFFFFFFFFFF7 ), + LIT64( 0x7FFFFFFFFFFFFFEF ), + LIT64( 0x7FFFFFFFFFFFFFDF ), + LIT64( 0x7FFFFFFFFFFFFFBF ), + LIT64( 0x7FFFFFFFFFFFFF7F ), + LIT64( 0x7FFFFFFFFFFFFEFF ), + LIT64( 0x7FFFFFFFFFFFFDFF ), + LIT64( 0x7FFFFFFFFFFFFBFF ), + LIT64( 0x7FFFFFFFFFFFF7FF ), + LIT64( 0x7FFFFFFFFFFFEFFF ), + LIT64( 0x7FFFFFFFFFFFDFFF ), + LIT64( 0x7FFFFFFFFFFFBFFF ), + LIT64( 0x7FFFFFFFFFFF7FFF ), + LIT64( 0x7FFFFFFFFFFEFFFF ), + LIT64( 0x7FFFFFFFFFFDFFFF ), + LIT64( 0x7FFFFFFFFFFBFFFF ), + LIT64( 0x7FFFFFFFFFF7FFFF ), + LIT64( 0x7FFFFFFFFFEFFFFF ), + LIT64( 0x7FFFFFFFFFDFFFFF ), + LIT64( 0x7FFFFFFFFFBFFFFF ), + LIT64( 0x7FFFFFFFFF7FFFFF ), + LIT64( 0x7FFFFFFFFEFFFFFF ), + LIT64( 0x7FFFFFFFFDFFFFFF ), + LIT64( 0x7FFFFFFFFBFFFFFF ), + LIT64( 0x7FFFFFFFF7FFFFFF ), + LIT64( 0x7FFFFFFFEFFFFFFF ), + LIT64( 0x7FFFFFFFDFFFFFFF ), + LIT64( 0x7FFFFFFFBFFFFFFF ), + LIT64( 0x7FFFFFFF7FFFFFFF ), + LIT64( 0x7FFFFFFEFFFFFFFF ), + LIT64( 0x7FFFFFFDFFFFFFFF ), + LIT64( 0x7FFFFFFBFFFFFFFF ), + LIT64( 0x7FFFFFF7FFFFFFFF ), + LIT64( 0x7FFFFFEFFFFFFFFF ), + LIT64( 0x7FFFFFDFFFFFFFFF ), + LIT64( 0x7FFFFFBFFFFFFFFF ), + LIT64( 0x7FFFFF7FFFFFFFFF ), + LIT64( 0x7FFFFEFFFFFFFFFF ), + LIT64( 0x7FFFFDFFFFFFFFFF ), + LIT64( 0x7FFFFBFFFFFFFFFF ), + LIT64( 0x7FFFF7FFFFFFFFFF ), + LIT64( 0x7FFFEFFFFFFFFFFF ), + LIT64( 0x7FFFDFFFFFFFFFFF ), + LIT64( 0x7FFFBFFFFFFFFFFF ), + LIT64( 0x7FFF7FFFFFFFFFFF ), + LIT64( 0x7FFEFFFFFFFFFFFF ), + LIT64( 0x7FFDFFFFFFFFFFFF ), + LIT64( 0x7FFBFFFFFFFFFFFF ), + LIT64( 0x7FF7FFFFFFFFFFFF ), + LIT64( 0x7FEFFFFFFFFFFFFF ), + LIT64( 0x7FDFFFFFFFFFFFFF ), + LIT64( 0x7FBFFFFFFFFFFFFF ), + LIT64( 0x7F7FFFFFFFFFFFFF ), + LIT64( 0x7EFFFFFFFFFFFFFF ), + LIT64( 0x7DFFFFFFFFFFFFFF ), + LIT64( 0x7BFFFFFFFFFFFFFF ), + LIT64( 0x77FFFFFFFFFFFFFF ), + LIT64( 0x6FFFFFFFFFFFFFFF ), + LIT64( 0x5FFFFFFFFFFFFFFF ), + LIT64( 0x3FFFFFFFFFFFFFFF ), + LIT64( 0x1FFFFFFFFFFFFFFF ), + LIT64( 0x0FFFFFFFFFFFFFFF ), + LIT64( 0x07FFFFFFFFFFFFFF ), + LIT64( 0x03FFFFFFFFFFFFFF ), + LIT64( 0x01FFFFFFFFFFFFFF ), + LIT64( 0x00FFFFFFFFFFFFFF ), + LIT64( 0x007FFFFFFFFFFFFF ), + LIT64( 0x003FFFFFFFFFFFFF ), + LIT64( 0x001FFFFFFFFFFFFF ), + LIT64( 0x000FFFFFFFFFFFFF ), + LIT64( 0x0007FFFFFFFFFFFF ), + LIT64( 0x0003FFFFFFFFFFFF ), + LIT64( 0x0001FFFFFFFFFFFF ), + LIT64( 0x0000FFFFFFFFFFFF ), + LIT64( 0x00007FFFFFFFFFFF ), + LIT64( 0x00003FFFFFFFFFFF ), + LIT64( 0x00001FFFFFFFFFFF ), + LIT64( 0x00000FFFFFFFFFFF ), + LIT64( 0x000007FFFFFFFFFF ), + LIT64( 0x000003FFFFFFFFFF ), + LIT64( 0x000001FFFFFFFFFF ), + LIT64( 0x000000FFFFFFFFFF ), + LIT64( 0x0000007FFFFFFFFF ), + LIT64( 0x0000003FFFFFFFFF ), + LIT64( 0x0000001FFFFFFFFF ), + LIT64( 0x0000000FFFFFFFFF ), + LIT64( 0x00000007FFFFFFFF ), + LIT64( 0x00000003FFFFFFFF ), + LIT64( 0x00000001FFFFFFFF ), + LIT64( 0x00000000FFFFFFFF ), + LIT64( 0x000000007FFFFFFF ), + LIT64( 0x000000003FFFFFFF ), + LIT64( 0x000000001FFFFFFF ), + LIT64( 0x000000000FFFFFFF ), + LIT64( 0x0000000007FFFFFF ), + LIT64( 0x0000000003FFFFFF ), + LIT64( 0x0000000001FFFFFF ), + LIT64( 0x0000000000FFFFFF ), + LIT64( 0x00000000007FFFFF ), + LIT64( 0x00000000003FFFFF ), + LIT64( 0x00000000001FFFFF ), + LIT64( 0x00000000000FFFFF ), + LIT64( 0x000000000007FFFF ), + LIT64( 0x000000000003FFFF ), + LIT64( 0x000000000001FFFF ), + LIT64( 0x000000000000FFFF ), + LIT64( 0x0000000000007FFF ), + LIT64( 0x0000000000003FFF ), + LIT64( 0x0000000000001FFF ), + LIT64( 0x0000000000000FFF ), + LIT64( 0x00000000000007FF ), + LIT64( 0x00000000000003FF ), + LIT64( 0x00000000000001FF ), + LIT64( 0x00000000000000FF ), + LIT64( 0x000000000000007F ), + LIT64( 0x000000000000003F ), + LIT64( 0x000000000000001F ), + LIT64( 0x000000000000000F ), + LIT64( 0x0000000000000007 ), + LIT64( 0x0000000000000003 ) +}; + +static const uint32 floatx80NumQInP1 = floatx80NumQIn * floatx80NumP1; +static const uint32 floatx80NumQOutP1 = floatx80NumQOut * floatx80NumP1; + +static floatx80 floatx80NextQInP1( sequenceT *sequencePtr ) +{ + int16 expNum, sigNum; + floatx80 z; + + sigNum = sequencePtr->term1Num; + expNum = sequencePtr->expNum; + z.low = floatx80P1[ sigNum ]; + z.high = floatx80QIn[ expNum ]; + if ( z.high & 0x7FFF ) z.low |= LIT64( 0x8000000000000000 ); + ++sigNum; + if ( floatx80NumP1 <= sigNum ) { + sigNum = 0; + ++expNum; + if ( floatx80NumQIn <= expNum ) { + expNum = 0; + sequencePtr->done = TRUE; + } + sequencePtr->expNum = expNum; + } + sequencePtr->term1Num = sigNum; + return z; + +} + +static floatx80 floatx80NextQOutP1( sequenceT *sequencePtr ) +{ + int16 expNum, sigNum; + floatx80 z; + + sigNum = sequencePtr->term1Num; + expNum = sequencePtr->expNum; + z.low = floatx80P1[ sigNum ]; + z.high = floatx80QOut[ expNum ]; + if ( z.high & 0x7FFF ) z.low |= LIT64( 0x8000000000000000 ); + ++sigNum; + if ( floatx80NumP1 <= sigNum ) { + sigNum = 0; + ++expNum; + if ( floatx80NumQOut <= expNum ) { + expNum = 0; + sequencePtr->done = TRUE; + } + sequencePtr->expNum = expNum; + } + sequencePtr->term1Num = sigNum; + return z; + +} + +static const uint32 floatx80NumQInP2 = floatx80NumQIn * floatx80NumP2; +static const uint32 floatx80NumQOutP2 = floatx80NumQOut * floatx80NumP2; + +static floatx80 floatx80NextQInP2( sequenceT *sequencePtr ) +{ + int16 expNum, sigNum; + floatx80 z; + + sigNum = sequencePtr->term1Num; + expNum = sequencePtr->expNum; + z.low = floatx80P2[ sigNum ]; + z.high = floatx80QIn[ expNum ]; + if ( z.high & 0x7FFF ) z.low |= LIT64( 0x8000000000000000 ); + ++sigNum; + if ( floatx80NumP2 <= sigNum ) { + sigNum = 0; + ++expNum; + if ( floatx80NumQIn <= expNum ) { + expNum = 0; + sequencePtr->done = TRUE; + } + sequencePtr->expNum = expNum; + } + sequencePtr->term1Num = sigNum; + return z; + +} + +static floatx80 floatx80NextQOutP2( sequenceT *sequencePtr ) +{ + int16 expNum, sigNum; + floatx80 z; + + sigNum = sequencePtr->term1Num; + expNum = sequencePtr->expNum; + z.low = floatx80P2[ sigNum ]; + z.high = floatx80QOut[ expNum ]; + if ( z.high & 0x7FFF ) z.low |= LIT64( 0x8000000000000000 ); + ++sigNum; + if ( floatx80NumP2 <= sigNum ) { + sigNum = 0; + ++expNum; + if ( floatx80NumQOut <= expNum ) { + expNum = 0; + sequencePtr->done = TRUE; + } + sequencePtr->expNum = expNum; + } + sequencePtr->term1Num = sigNum; + return z; + +} + +static floatx80 floatx80RandomQOutP3( void ) +{ + floatx80 z; + + z.low = + ( floatx80P2[ randomUint8() % floatx80NumP2 ] + + floatx80P2[ randomUint8() % floatx80NumP2 ] ) + & LIT64( 0x7FFFFFFFFFFFFFFF ); + z.high = floatx80QOut[ randomUint8() % floatx80NumQOut ]; + if ( z.high & 0x7FFF ) z.low |= LIT64( 0x8000000000000000 ); + return z; + +} + +static floatx80 floatx80RandomQOutPInf( void ) +{ + floatx80 z; + + z.low = randomUint64() & LIT64( 0x7FFFFFFFFFFFFFFF ); + z.high = floatx80QOut[ randomUint8() % floatx80NumQOut ]; + if ( z.high & 0x7FFF ) z.low |= LIT64( 0x8000000000000000 ); + return z; + +} + +enum { + floatx80NumQInfWeightMasks = 14 +}; + +static const uint16 floatx80QInfWeightMasks[ floatx80NumQInfWeightMasks ] = { + 0x7FFF, + 0x7FFF, + 0x3FFF, + 0x1FFF, + 0x07FF, + 0x07FF, + 0x03FF, + 0x01FF, + 0x00FF, + 0x007F, + 0x003F, + 0x001F, + 0x000F, + 0x0007 +}; + +static const uint16 floatx80QInfWeightOffsets[ floatx80NumQInfWeightMasks ] = { + 0x0000, + 0x0000, + 0x2000, + 0x3000, + 0x3800, + 0x3C00, + 0x3E00, + 0x3F00, + 0x3F80, + 0x3FC0, + 0x3FE0, + 0x3FF0, + 0x3FF8, + 0x3FFC +}; + +static floatx80 floatx80RandomQInfP3( void ) +{ + int8 weightMaskNum; + floatx80 z; + + z.low = + ( floatx80P2[ randomUint8() % floatx80NumP2 ] + + floatx80P2[ randomUint8() % floatx80NumP2 ] ) + & LIT64( 0x7FFFFFFFFFFFFFFF ); + weightMaskNum = randomUint8() % floatx80NumQInfWeightMasks; + z.high = + ( randomUint16() & floatx80QInfWeightMasks[ weightMaskNum ] ) + + floatx80QInfWeightOffsets[ weightMaskNum ]; + if ( z.high ) z.low |= LIT64( 0x8000000000000000 ); + z.high |= ( (uint16) ( randomUint8() & 1 ) )<<15; + return z; + +} + +static floatx80 floatx80RandomQInfPInf( void ) +{ + int8 weightMaskNum; + floatx80 z; + + z.low = randomUint64() & LIT64( 0x7FFFFFFFFFFFFFFF ); + weightMaskNum = randomUint8() % floatx80NumQInfWeightMasks; + z.high = + ( randomUint16() & floatx80QInfWeightMasks[ weightMaskNum ] ) + + floatx80QInfWeightOffsets[ weightMaskNum ]; + if ( z.high ) z.low |= LIT64( 0x8000000000000000 ); + z.high |= ( (uint16) ( randomUint8() & 1 ) )<<15; + return z; + +} + +static floatx80 floatx80Random( void ) +{ + + switch ( randomUint8() & 7 ) { + case 0: + case 1: + case 2: + return floatx80RandomQOutP3(); + case 3: + return floatx80RandomQOutPInf(); + case 4: + case 5: + case 6: + return floatx80RandomQInfP3(); + default: + return floatx80RandomQInfPInf(); + } + +} + +#endif + +#ifdef FLOAT128 + +enum { + float128NumQIn = 22, + float128NumQOut = 78, + float128NumP1 = 4, + float128NumP2 = 443 +}; + +static const uint64 float128QIn[ float128NumQIn ] = { + LIT64( 0x0000000000000000 ), /* positive, subnormal */ + LIT64( 0x0001000000000000 ), /* positive, -16382 */ + LIT64( 0x3F8E000000000000 ), /* positive, -113 */ + LIT64( 0x3FFD000000000000 ), /* positive, -2 */ + LIT64( 0x3FFE000000000000 ), /* positive, -1 */ + LIT64( 0x3FFF000000000000 ), /* positive, 0 */ + LIT64( 0x4000000000000000 ), /* positive, 1 */ + LIT64( 0x4001000000000000 ), /* positive, 2 */ + LIT64( 0x4070000000000000 ), /* positive, 113 */ + LIT64( 0x7FFE000000000000 ), /* positive, 16383 */ + LIT64( 0x7FFF000000000000 ), /* positive, infinity or NaN */ + LIT64( 0x8000000000000000 ), /* negative, subnormal */ + LIT64( 0x8001000000000000 ), /* negative, -16382 */ + LIT64( 0xBF8E000000000000 ), /* negative, -113 */ + LIT64( 0xBFFD000000000000 ), /* negative, -2 */ + LIT64( 0xBFFE000000000000 ), /* negative, -1 */ + LIT64( 0xBFFF000000000000 ), /* negative, 0 */ + LIT64( 0xC000000000000000 ), /* negative, 1 */ + LIT64( 0xC001000000000000 ), /* negative, 2 */ + LIT64( 0xC070000000000000 ), /* negative, 113 */ + LIT64( 0xFFFE000000000000 ), /* negative, 16383 */ + LIT64( 0xFFFF000000000000 ) /* negative, infinity or NaN */ +}; + +static const uint64 float128QOut[ float128NumQOut ] = { + LIT64( 0x0000000000000000 ), /* positive, subnormal */ + LIT64( 0x0001000000000000 ), /* positive, -16382 */ + LIT64( 0x0002000000000000 ), /* positive, -16381 */ + LIT64( 0x3BFE000000000000 ), /* positive, -1025 */ + LIT64( 0x3BFF000000000000 ), /* positive, -1024 */ + LIT64( 0x3C00000000000000 ), /* positive, -1023 */ + LIT64( 0x3C01000000000000 ), /* positive, -1022 */ + LIT64( 0x3F7E000000000000 ), /* positive, -129 */ + LIT64( 0x3F7F000000000000 ), /* positive, -128 */ + LIT64( 0x3F80000000000000 ), /* positive, -127 */ + LIT64( 0x3F81000000000000 ), /* positive, -126 */ + LIT64( 0x3F8E000000000000 ), /* positive, -113 */ + LIT64( 0x3FFB000000000000 ), /* positive, -4 */ + LIT64( 0x3FFC000000000000 ), /* positive, -3 */ + LIT64( 0x3FFD000000000000 ), /* positive, -2 */ + LIT64( 0x3FFE000000000000 ), /* positive, -1 */ + LIT64( 0x3FFF000000000000 ), /* positive, 0 */ + LIT64( 0x4000000000000000 ), /* positive, 1 */ + LIT64( 0x4001000000000000 ), /* positive, 2 */ + LIT64( 0x4002000000000000 ), /* positive, 3 */ + LIT64( 0x4003000000000000 ), /* positive, 4 */ + LIT64( 0x401C000000000000 ), /* positive, 29 */ + LIT64( 0x401D000000000000 ), /* positive, 30 */ + LIT64( 0x401E000000000000 ), /* positive, 31 */ + LIT64( 0x401F000000000000 ), /* positive, 32 */ + LIT64( 0x403C000000000000 ), /* positive, 61 */ + LIT64( 0x403D000000000000 ), /* positive, 62 */ + LIT64( 0x403E000000000000 ), /* positive, 63 */ + LIT64( 0x403F000000000000 ), /* positive, 64 */ + LIT64( 0x4070000000000000 ), /* positive, 113 */ + LIT64( 0x407E000000000000 ), /* positive, 127 */ + LIT64( 0x407F000000000000 ), /* positive, 128 */ + LIT64( 0x4080000000000000 ), /* positive, 129 */ + LIT64( 0x43FE000000000000 ), /* positive, 1023 */ + LIT64( 0x43FF000000000000 ), /* positive, 1024 */ + LIT64( 0x4400000000000000 ), /* positive, 1025 */ + LIT64( 0x7FFD000000000000 ), /* positive, 16382 */ + LIT64( 0x7FFE000000000000 ), /* positive, 16383 */ + LIT64( 0x7FFF000000000000 ), /* positive, infinity or NaN */ + LIT64( 0x8000000000000000 ), /* negative, subnormal */ + LIT64( 0x8001000000000000 ), /* negative, -16382 */ + LIT64( 0x8002000000000000 ), /* negative, -16381 */ + LIT64( 0xBBFE000000000000 ), /* negative, -1025 */ + LIT64( 0xBBFF000000000000 ), /* negative, -1024 */ + LIT64( 0xBC00000000000000 ), /* negative, -1023 */ + LIT64( 0xBC01000000000000 ), /* negative, -1022 */ + LIT64( 0xBF7E000000000000 ), /* negative, -129 */ + LIT64( 0xBF7F000000000000 ), /* negative, -128 */ + LIT64( 0xBF80000000000000 ), /* negative, -127 */ + LIT64( 0xBF81000000000000 ), /* negative, -126 */ + LIT64( 0xBF8E000000000000 ), /* negative, -113 */ + LIT64( 0xBFFB000000000000 ), /* negative, -4 */ + LIT64( 0xBFFC000000000000 ), /* negative, -3 */ + LIT64( 0xBFFD000000000000 ), /* negative, -2 */ + LIT64( 0xBFFE000000000000 ), /* negative, -1 */ + LIT64( 0xBFFF000000000000 ), /* negative, 0 */ + LIT64( 0xC000000000000000 ), /* negative, 1 */ + LIT64( 0xC001000000000000 ), /* negative, 2 */ + LIT64( 0xC002000000000000 ), /* negative, 3 */ + LIT64( 0xC003000000000000 ), /* negative, 4 */ + LIT64( 0xC01C000000000000 ), /* negative, 29 */ + LIT64( 0xC01D000000000000 ), /* negative, 30 */ + LIT64( 0xC01E000000000000 ), /* negative, 31 */ + LIT64( 0xC01F000000000000 ), /* negative, 32 */ + LIT64( 0xC03C000000000000 ), /* negative, 61 */ + LIT64( 0xC03D000000000000 ), /* negative, 62 */ + LIT64( 0xC03E000000000000 ), /* negative, 63 */ + LIT64( 0xC03F000000000000 ), /* negative, 64 */ + LIT64( 0xC070000000000000 ), /* negative, 113 */ + LIT64( 0xC07E000000000000 ), /* negative, 127 */ + LIT64( 0xC07F000000000000 ), /* negative, 128 */ + LIT64( 0xC080000000000000 ), /* negative, 129 */ + LIT64( 0xC3FE000000000000 ), /* negative, 1023 */ + LIT64( 0xC3FF000000000000 ), /* negative, 1024 */ + LIT64( 0xC400000000000000 ), /* negative, 1025 */ + LIT64( 0xFFFD000000000000 ), /* negative, 16382 */ + LIT64( 0xFFFE000000000000 ), /* negative, 16383 */ + LIT64( 0xFFFF000000000000 ) /* negative, infinity or NaN */ +}; + +static const struct { bits64 high, low; } float128P1[ float128NumP1 ] = { + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000000001 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFE ) } +}; + +static const struct { bits64 high, low; } float128P2[ float128NumP2 ] = { + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000000001 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000000002 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000000004 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000000008 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000000010 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000000020 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000000040 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000000080 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000000100 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000000200 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000000400 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000000800 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000001000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000002000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000004000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000008000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000010000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000020000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000040000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000080000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000100000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000200000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000400000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000800000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000001000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000002000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000004000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000008000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000010000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000020000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000040000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000080000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000100000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000200000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000400000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000800000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000001000000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000002000000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000004000000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000008000000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000010000000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000020000000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000040000000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000080000000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000100000000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000200000000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000400000000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000800000000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0001000000000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0002000000000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0004000000000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0008000000000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0010000000000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0020000000000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0040000000000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0080000000000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0100000000000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0200000000000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0400000000000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0800000000000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x1000000000000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x2000000000000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x4000000000000000 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x8000000000000000 ) }, + { LIT64( 0x0000000000000001 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000000000002 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000000000004 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000000000008 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000000000010 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000000000020 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000000000040 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000000000080 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000000000100 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000000000200 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000000000400 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000000000800 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000000001000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000000002000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000000004000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000000008000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000000010000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000000020000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000000040000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000000080000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000000100000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000000200000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000000400000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000000800000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000001000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000002000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000004000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000008000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000010000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000020000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000040000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000080000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000100000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000200000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000400000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000000800000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000001000000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000002000000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000004000000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000008000000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000010000000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000020000000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000040000000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000080000000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000100000000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000200000000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000400000000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000800000000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000C00000000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000E00000000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000F00000000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000F80000000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FC0000000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FE0000000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FF0000000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FF8000000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFC000000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFE000000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFF000000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFF800000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFC00000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFE00000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFF00000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFF80000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFC0000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFE0000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFF0000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFF8000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFFC000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFFE000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFFF000000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFFF800000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFFFC00000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFFFE00000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFFFF00000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFFFF80000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFFFFC0000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFFFFE0000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFFFFF0000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFFFFF8000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFFFFFC000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFFFFFE000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFFFFFF000 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFFFFFF800 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFFFFFFC00 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFFFFFFE00 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFFFFFFF00 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFFFFFFF80 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFC0 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFE0 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFF0 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFF8 ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFC ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFE ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0x0000000000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0x8000000000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xC000000000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xE000000000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xF000000000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xF800000000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFC00000000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFE00000000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFF00000000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFF80000000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFC0000000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFE0000000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFF0000000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFF8000000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFC000000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFE000000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFF000000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFF800000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFC00000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFE00000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFF00000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFF80000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFC0000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFE0000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFF0000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFF8000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFC000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFE000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFF000000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFF800000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFC00000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFE00000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFF00000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFF80000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFC0000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFE0000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFF0000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFF8000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFC000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFE000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFF000000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFF800000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFC00000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFE00000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFF00000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFF80000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFC0000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFE0000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFF0000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFF8000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFC000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFE000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFF000 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFF800 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFC00 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFE00 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFF00 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFF80 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFC0 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFE0 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFF0 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFF8 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFC ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFE ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFD ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFB ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFF7 ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFEF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFDF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFBF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFF7F ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFEFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFDFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFBFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFF7FF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFEFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFDFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFBFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFF7FFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFEFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFDFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFBFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFF7FFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFEFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFDFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFBFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFF7FFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFEFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFDFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFBFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFF7FFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFEFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFDFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFFBFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFF7FFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFEFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFDFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFFBFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFF7FFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFEFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFDFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFFBFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFF7FFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFEFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFDFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFFBFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFF7FFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFEFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFDFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFFBFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFF7FFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFEFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFDFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFFBFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFF7FFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFEFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFDFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFFBFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFF7FFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFEFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFDFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xFBFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xF7FFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xEFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xDFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0xBFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFF ), LIT64( 0x7FFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFD ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFFB ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFF7 ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFEF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFDF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFFBF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFF7F ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFEFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFDFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFFBFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFF7FF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFEFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFDFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFFBFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFF7FFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFEFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFDFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFFBFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFF7FFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFEFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFDFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFFBFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFF7FFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFEFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFDFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFFBFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFF7FFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFEFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFDFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFFBFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFF7FFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFEFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFDFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFFBFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFF7FFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFEFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFDFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FFBFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FF7FFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FEFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FDFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000FBFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000F7FFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000EFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000DFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000BFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x00007FFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x00003FFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x00001FFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x00000FFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x000007FFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x000003FFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x000001FFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x000000FFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000007FFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000003FFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000001FFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000000FFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x00000007FFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x00000003FFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x00000001FFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x00000000FFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x000000007FFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x000000003FFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x000000001FFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x000000000FFFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000000007FFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000000003FFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000000001FFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000000000FFFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x00000000007FFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x00000000003FFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x00000000001FFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x00000000000FFFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x000000000007FFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x000000000003FFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x000000000001FFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x000000000000FFFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000000000007FFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000000000003FFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000000000001FFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000000000000FFF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x00000000000007FF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x00000000000003FF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x00000000000001FF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x00000000000000FF ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x000000000000007F ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x000000000000003F ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x000000000000001F ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x000000000000000F ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000000000000007 ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000000000000003 ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000000000000001 ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0xFFFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x7FFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x3FFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x1FFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0FFFFFFFFFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x07FFFFFFFFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x03FFFFFFFFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x01FFFFFFFFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x00FFFFFFFFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x007FFFFFFFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x003FFFFFFFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x001FFFFFFFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x000FFFFFFFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0007FFFFFFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0003FFFFFFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0001FFFFFFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000FFFFFFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x00007FFFFFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x00003FFFFFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x00001FFFFFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x00000FFFFFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x000007FFFFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x000003FFFFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x000001FFFFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x000000FFFFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000007FFFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000003FFFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000001FFFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000FFFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x00000007FFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x00000003FFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x00000001FFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x00000000FFFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x000000007FFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x000000003FFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x000000001FFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x000000000FFFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000007FFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000003FFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000001FFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000FFFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x00000000007FFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x00000000003FFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x00000000001FFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x00000000000FFFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x000000000007FFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x000000000003FFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x000000000001FFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x000000000000FFFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000007FFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000003FFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000001FFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000000FFF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x00000000000007FF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x00000000000003FF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x00000000000001FF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x00000000000000FF ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x000000000000007F ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x000000000000003F ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x000000000000001F ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x000000000000000F ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000000007 ) }, + { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000000003 ) } +}; + +static const uint32 float128NumQInP1 = float128NumQIn * float128NumP1; +static const uint32 float128NumQOutP1 = float128NumQOut * float128NumP1; + +static float128 float128NextQInP1( sequenceT *sequencePtr ) +{ + int16 expNum, sigNum; + float128 z; + + sigNum = sequencePtr->term1Num; + expNum = sequencePtr->expNum; + z.low = float128P1[ sigNum ].low; + z.high = float128QIn[ expNum ] | float128P1[ sigNum ].high; + ++sigNum; + if ( float128NumP1 <= sigNum ) { + sigNum = 0; + ++expNum; + if ( float128NumQIn <= expNum ) { + expNum = 0; + sequencePtr->done = TRUE; + } + sequencePtr->expNum = expNum; + } + sequencePtr->term1Num = sigNum; + return z; + +} + +static float128 float128NextQOutP1( sequenceT *sequencePtr ) +{ + int16 expNum, sigNum; + float128 z; + + sigNum = sequencePtr->term1Num; + expNum = sequencePtr->expNum; + z.low = float128P1[ sigNum ].low; + z.high = float128QOut[ expNum ] | float128P1[ sigNum ].high; + ++sigNum; + if ( float128NumP1 <= sigNum ) { + sigNum = 0; + ++expNum; + if ( float128NumQOut <= expNum ) { + expNum = 0; + sequencePtr->done = TRUE; + } + sequencePtr->expNum = expNum; + } + sequencePtr->term1Num = sigNum; + return z; + +} + +static const uint32 float128NumQInP2 = float128NumQIn * float128NumP2; +static const uint32 float128NumQOutP2 = float128NumQOut * float128NumP2; + +static float128 float128NextQInP2( sequenceT *sequencePtr ) +{ + int16 expNum, sigNum; + float128 z; + + sigNum = sequencePtr->term1Num; + expNum = sequencePtr->expNum; + z.low = float128P2[ sigNum ].low; + z.high = float128QIn[ expNum ] | float128P2[ sigNum ].high; + ++sigNum; + if ( float128NumP2 <= sigNum ) { + sigNum = 0; + ++expNum; + if ( float128NumQIn <= expNum ) { + expNum = 0; + sequencePtr->done = TRUE; + } + sequencePtr->expNum = expNum; + } + sequencePtr->term1Num = sigNum; + return z; + +} + +static float128 float128NextQOutP2( sequenceT *sequencePtr ) +{ + int16 expNum, sigNum; + float128 z; + + sigNum = sequencePtr->term1Num; + expNum = sequencePtr->expNum; + z.low = float128P2[ sigNum ].low; + z.high = float128QOut[ expNum ] | float128P2[ sigNum ].high; + ++sigNum; + if ( float128NumP2 <= sigNum ) { + sigNum = 0; + ++expNum; + if ( float128NumQOut <= expNum ) { + expNum = 0; + sequencePtr->done = TRUE; + } + sequencePtr->expNum = expNum; + } + sequencePtr->term1Num = sigNum; + return z; + +} + +static float128 float128RandomQOutP3( void ) +{ + int16 sigNum1, sigNum2; + uint64 sig1Low, sig2Low; + float128 z; + + sigNum1 = randomUint8() % float128NumP2; + sigNum2 = randomUint8() % float128NumP2; + sig1Low = float128P2[ sigNum1 ].low; + sig2Low = float128P2[ sigNum2 ].low; + z.low = sig1Low + sig2Low; + z.high = + float128QOut[ randomUint8() % float128NumQOut ] + | ( ( float128P2[ sigNum1 ].high + + float128P2[ sigNum2 ].high + + ( z.low < sig1Low ) + ) + & LIT64( 0x0000FFFFFFFFFFFF ) + ); + return z; + +} + +static float128 float128RandomQOutPInf( void ) +{ + float128 z; + + z.low = randomUint64(); + z.high = + float128QOut[ randomUint8() % float128NumQOut ] + | ( randomUint64() & LIT64( 0x0000FFFFFFFFFFFF ) ); + return z; + +} + +enum { + float128NumQInfWeightMasks = 14 +}; + +static const uint64 float128QInfWeightMasks[ float128NumQInfWeightMasks ] = { + LIT64( 0x7FFF000000000000 ), + LIT64( 0x7FFF000000000000 ), + LIT64( 0x3FFF000000000000 ), + LIT64( 0x1FFF000000000000 ), + LIT64( 0x07FF000000000000 ), + LIT64( 0x07FF000000000000 ), + LIT64( 0x03FF000000000000 ), + LIT64( 0x01FF000000000000 ), + LIT64( 0x00FF000000000000 ), + LIT64( 0x007F000000000000 ), + LIT64( 0x003F000000000000 ), + LIT64( 0x001F000000000000 ), + LIT64( 0x000F000000000000 ), + LIT64( 0x0007000000000000 ) +}; + +static const uint64 float128QInfWeightOffsets[ float128NumQInfWeightMasks ] = { + LIT64( 0x0000000000000000 ), + LIT64( 0x0000000000000000 ), + LIT64( 0x2000000000000000 ), + LIT64( 0x3000000000000000 ), + LIT64( 0x3800000000000000 ), + LIT64( 0x3C00000000000000 ), + LIT64( 0x3E00000000000000 ), + LIT64( 0x3F00000000000000 ), + LIT64( 0x3F80000000000000 ), + LIT64( 0x3FC0000000000000 ), + LIT64( 0x3FE0000000000000 ), + LIT64( 0x3FF0000000000000 ), + LIT64( 0x3FF8000000000000 ), + LIT64( 0x3FFC000000000000 ) +}; + +static float128 float128RandomQInfP3( void ) +{ + int16 sigNum1, sigNum2; + uint64 sig1Low, sig2Low; + int8 weightMaskNum; + float128 z; + + sigNum1 = randomUint8() % float128NumP2; + sigNum2 = randomUint8() % float128NumP2; + sig1Low = float128P2[ sigNum1 ].low; + sig2Low = float128P2[ sigNum2 ].low; + z.low = sig1Low + sig2Low; + weightMaskNum = randomUint8() % float128NumQInfWeightMasks; + z.high = + ( ( (uint64) ( randomUint8() & 1 ) )<<63 ) + | ( ( ( ( (uint64) randomUint16() )<<48 ) + & float128QInfWeightMasks[ weightMaskNum ] ) + + float128QInfWeightOffsets[ weightMaskNum ] + ) + | ( ( float128P2[ sigNum1 ].high + + float128P2[ sigNum2 ].high + + ( z.low < sig1Low ) + ) + & LIT64( 0x0000FFFFFFFFFFFF ) + ); + return z; + +} + +static float128 float128RandomQInfPInf( void ) +{ + int8 weightMaskNum; + float128 z; + + weightMaskNum = randomUint8() % float128NumQInfWeightMasks; + z.low = randomUint64(); + z.high = + ( ( (uint64) ( randomUint8() & 1 ) )<<63 ) + | ( ( ( ( (uint64) randomUint16() )<<48 ) + & float128QInfWeightMasks[ weightMaskNum ] ) + + float128QInfWeightOffsets[ weightMaskNum ] + ) + | ( randomUint64() & LIT64( 0x0000FFFFFFFFFFFF ) ); + return z; + +} + +static float128 float128Random( void ) +{ + + switch ( randomUint8() & 7 ) { + case 0: + case 1: + case 2: + return float128RandomQOutP3(); + case 3: + return float128RandomQOutPInf(); + case 4: + case 5: + case 6: + return float128RandomQInfP3(); + default: + return float128RandomQInfPInf(); + } + +} + +#endif + +static int8 level = 0; + +void testCases_setLevel( int8 levelIn ) +{ + + if ( ( levelIn < 1 ) || ( 2 < levelIn ) ) { + fail( "Invalid testing level: %d", levelIn ); + } + level = levelIn; + +} + +static int8 sequenceType; +static sequenceT sequenceA, sequenceB; +static int8 subcase; + +uint32 testCases_total; +flag testCases_done; + +static float32 current_a_float32; +static float32 current_b_float32; +static float64 current_a_float64; +static float64 current_b_float64; +#ifdef FLOATX80 +static floatx80 current_a_floatx80; +static floatx80 current_b_floatx80; +#endif +#ifdef FLOAT128 +static float128 current_a_float128; +static float128 current_b_float128; +#endif + +void testCases_initSequence( int8 sequenceTypeIn ) +{ + + sequenceType = sequenceTypeIn; + sequenceA.term2Num = 0; + sequenceA.term1Num = 0; + sequenceA.expNum = 0; + sequenceA.done = FALSE; + sequenceB.term2Num = 0; + sequenceB.term1Num = 0; + sequenceB.expNum = 0; + sequenceB.done = FALSE; + subcase = 0; + switch ( level ) { + case 1: + switch ( sequenceTypeIn ) { + case testCases_sequence_a_int32: + testCases_total = 3 * int32NumP1; + break; +#ifdef BITS64 + case testCases_sequence_a_int64: + testCases_total = 3 * int64NumP1; + break; +#endif + case testCases_sequence_a_float32: + testCases_total = 3 * float32NumQOutP1; + break; + case testCases_sequence_ab_float32: + testCases_total = 6 * float32NumQInP1 * float32NumQInP1; + current_a_float32 = float32NextQInP1( &sequenceA ); + break; + case testCases_sequence_a_float64: + testCases_total = 3 * float64NumQOutP1; + break; + case testCases_sequence_ab_float64: + testCases_total = 6 * float64NumQInP1 * float64NumQInP1; + current_a_float64 = float64NextQInP1( &sequenceA ); + break; +#ifdef FLOATX80 + case testCases_sequence_a_floatx80: + testCases_total = 3 * floatx80NumQOutP1; + break; + case testCases_sequence_ab_floatx80: + testCases_total = 6 * floatx80NumQInP1 * floatx80NumQInP1; + current_a_floatx80 = floatx80NextQInP1( &sequenceA ); + break; +#endif +#ifdef FLOAT128 + case testCases_sequence_a_float128: + testCases_total = 3 * float128NumQOutP1; + break; + case testCases_sequence_ab_float128: + testCases_total = 6 * float128NumQInP1 * float128NumQInP1; + current_a_float128 = float128NextQInP1( &sequenceA ); + break; +#endif + } + break; + case 2: + switch ( sequenceTypeIn ) { + case testCases_sequence_a_int32: + testCases_total = 2 * int32NumP2; + break; +#ifdef BITS64 + case testCases_sequence_a_int64: + testCases_total = 2 * int64NumP2; + break; +#endif + case testCases_sequence_a_float32: + testCases_total = 2 * float32NumQOutP2; + break; + case testCases_sequence_ab_float32: + testCases_total = 2 * float32NumQInP2 * float32NumQInP2; + current_a_float32 = float32NextQInP2( &sequenceA ); + break; + case testCases_sequence_a_float64: + testCases_total = 2 * float64NumQOutP2; + break; + case testCases_sequence_ab_float64: + testCases_total = 2 * float64NumQInP2 * float64NumQInP2; + current_a_float64 = float64NextQInP2( &sequenceA ); + break; +#ifdef FLOATX80 + case testCases_sequence_a_floatx80: + testCases_total = 2 * floatx80NumQOutP2; + break; + case testCases_sequence_ab_floatx80: + testCases_total = 2 * floatx80NumQInP2 * floatx80NumQInP2; + current_a_floatx80 = floatx80NextQInP2( &sequenceA ); + break; +#endif +#ifdef FLOAT128 + case testCases_sequence_a_float128: + testCases_total = 2 * float128NumQOutP2; + break; + case testCases_sequence_ab_float128: + testCases_total = 2 * float128NumQInP2 * float128NumQInP2; + current_a_float128 = float128NextQInP2( &sequenceA ); + break; +#endif + } + break; + } + testCases_done = FALSE; + +} + +int32 testCases_a_int32; +#ifdef BITS64 +int64 testCases_a_int64; +#endif +float32 testCases_a_float32; +float32 testCases_b_float32; +float64 testCases_a_float64; +float64 testCases_b_float64; +#ifdef FLOATX80 +floatx80 testCases_a_floatx80; +floatx80 testCases_b_floatx80; +#endif +#ifdef FLOAT128 +float128 testCases_a_float128; +float128 testCases_b_float128; +#endif + +void testCases_next( void ) +{ + + switch ( level ) { + case 1: + switch ( sequenceType ) { + case testCases_sequence_a_int32: + switch ( subcase ) { + case 0: + testCases_a_int32 = int32RandomP3(); + break; + case 1: + testCases_a_int32 = int32RandomPInf(); + break; + case 2: + testCases_a_int32 = int32NextP1( &sequenceA ); + testCases_done = sequenceA.done; + subcase = -1; + break; + } + ++subcase; + break; +#ifdef BITS64 + case testCases_sequence_a_int64: + switch ( subcase ) { + case 0: + testCases_a_int64 = int64RandomP3(); + break; + case 1: + testCases_a_int64 = int64RandomPInf(); + break; + case 2: + testCases_a_int64 = int64NextP1( &sequenceA ); + testCases_done = sequenceA.done; + subcase = -1; + break; + } + ++subcase; + break; +#endif + case testCases_sequence_a_float32: + switch ( subcase ) { + case 0: + case 1: + testCases_a_float32 = float32Random(); + break; + case 2: + testCases_a_float32 = float32NextQOutP1( &sequenceA ); + testCases_done = sequenceA.done; + subcase = -1; + break; + } + ++subcase; + break; + case testCases_sequence_ab_float32: + switch ( subcase ) { + case 0: + if ( sequenceB.done ) { + sequenceB.done = FALSE; + current_a_float32 = float32NextQInP1( &sequenceA ); + } + current_b_float32 = float32NextQInP1( &sequenceB ); + case 2: + case 4: + testCases_a_float32 = float32Random(); + testCases_b_float32 = float32Random(); + break; + case 1: + testCases_a_float32 = current_a_float32; + testCases_b_float32 = float32Random(); + break; + case 3: + testCases_a_float32 = float32Random(); + testCases_b_float32 = current_b_float32; + break; + case 5: + testCases_a_float32 = current_a_float32; + testCases_b_float32 = current_b_float32; + testCases_done = sequenceA.done & sequenceB.done; + subcase = -1; + break; + } + ++subcase; + break; + case testCases_sequence_a_float64: + switch ( subcase ) { + case 0: + case 1: + testCases_a_float64 = float64Random(); + break; + case 2: + testCases_a_float64 = float64NextQOutP1( &sequenceA ); + testCases_done = sequenceA.done; + subcase = -1; + break; + } + ++subcase; + break; + case testCases_sequence_ab_float64: + switch ( subcase ) { + case 0: + if ( sequenceB.done ) { + sequenceB.done = FALSE; + current_a_float64 = float64NextQInP1( &sequenceA ); + } + current_b_float64 = float64NextQInP1( &sequenceB ); + case 2: + case 4: + testCases_a_float64 = float64Random(); + testCases_b_float64 = float64Random(); + break; + case 1: + testCases_a_float64 = current_a_float64; + testCases_b_float64 = float64Random(); + break; + case 3: + testCases_a_float64 = float64Random(); + testCases_b_float64 = current_b_float64; + break; + case 5: + testCases_a_float64 = current_a_float64; + testCases_b_float64 = current_b_float64; + testCases_done = sequenceA.done & sequenceB.done; + subcase = -1; + break; + } + ++subcase; + break; +#ifdef FLOATX80 + case testCases_sequence_a_floatx80: + switch ( subcase ) { + case 0: + case 1: + testCases_a_floatx80 = floatx80Random(); + break; + case 2: + testCases_a_floatx80 = floatx80NextQOutP1( &sequenceA ); + testCases_done = sequenceA.done; + subcase = -1; + break; + } + ++subcase; + break; + case testCases_sequence_ab_floatx80: + switch ( subcase ) { + case 0: + if ( sequenceB.done ) { + sequenceB.done = FALSE; + current_a_floatx80 = floatx80NextQInP1( &sequenceA ); + } + current_b_floatx80 = floatx80NextQInP1( &sequenceB ); + case 2: + case 4: + testCases_a_floatx80 = floatx80Random(); + testCases_b_floatx80 = floatx80Random(); + break; + case 1: + testCases_a_floatx80 = current_a_floatx80; + testCases_b_floatx80 = floatx80Random(); + break; + case 3: + testCases_a_floatx80 = floatx80Random(); + testCases_b_floatx80 = current_b_floatx80; + break; + case 5: + testCases_a_floatx80 = current_a_floatx80; + testCases_b_floatx80 = current_b_floatx80; + testCases_done = sequenceA.done & sequenceB.done; + subcase = -1; + break; + } + ++subcase; + break; +#endif +#ifdef FLOAT128 + case testCases_sequence_a_float128: + switch ( subcase ) { + case 0: + case 1: + testCases_a_float128 = float128Random(); + break; + case 2: + testCases_a_float128 = float128NextQOutP1( &sequenceA ); + testCases_done = sequenceA.done; + subcase = -1; + break; + } + ++subcase; + break; + case testCases_sequence_ab_float128: + switch ( subcase ) { + case 0: + if ( sequenceB.done ) { + sequenceB.done = FALSE; + current_a_float128 = float128NextQInP1( &sequenceA ); + } + current_b_float128 = float128NextQInP1( &sequenceB ); + case 2: + case 4: + testCases_a_float128 = float128Random(); + testCases_b_float128 = float128Random(); + break; + case 1: + testCases_a_float128 = current_a_float128; + testCases_b_float128 = float128Random(); + break; + case 3: + testCases_a_float128 = float128Random(); + testCases_b_float128 = current_b_float128; + break; + case 5: + testCases_a_float128 = current_a_float128; + testCases_b_float128 = current_b_float128; + testCases_done = sequenceA.done & sequenceB.done; + subcase = -1; + break; + } + ++subcase; + break; +#endif + } + break; + case 2: + switch ( sequenceType ) { + case testCases_sequence_a_int32: + switch ( subcase ) { + case 0: + testCases_a_int32 = int32RandomP3(); + break; + case 2: + testCases_a_int32 = int32RandomPInf(); + break; + case 3: + subcase = -1; + case 1: + testCases_a_int32 = int32NextP2( &sequenceA ); + testCases_done = sequenceA.done; + break; + } + ++subcase; + break; +#ifdef BITS64 + case testCases_sequence_a_int64: + switch ( subcase ) { + case 0: + testCases_a_int64 = int64RandomP3(); + break; + case 2: + testCases_a_int64 = int64RandomPInf(); + break; + case 3: + subcase = -1; + case 1: + testCases_a_int64 = int64NextP2( &sequenceA ); + testCases_done = sequenceA.done; + break; + } + ++subcase; + break; +#endif + case testCases_sequence_a_float32: + switch ( subcase ) { + case 0: + testCases_a_float32 = float32Random(); + break; + case 1: + testCases_a_float32 = float32NextQOutP2( &sequenceA ); + testCases_done = sequenceA.done; + subcase = -1; + break; + } + ++subcase; + break; + case testCases_sequence_ab_float32: + switch ( subcase ) { + case 0: + testCases_a_float32 = float32Random(); + testCases_b_float32 = float32Random(); + break; + case 1: + if ( sequenceB.done ) { + sequenceB.done = FALSE; + current_a_float32 = float32NextQInP2( &sequenceA ); + } + testCases_a_float32 = current_a_float32; + testCases_b_float32 = float32NextQInP2( &sequenceB ); + testCases_done = sequenceA.done & sequenceB.done; + subcase = -1; + break; + } + ++subcase; + break; + case testCases_sequence_a_float64: + switch ( subcase ) { + case 0: + testCases_a_float64 = float64Random(); + break; + case 1: + testCases_a_float64 = float64NextQOutP2( &sequenceA ); + testCases_done = sequenceA.done; + subcase = -1; + break; + } + ++subcase; + break; + case testCases_sequence_ab_float64: + switch ( subcase ) { + case 0: + testCases_a_float64 = float64Random(); + testCases_b_float64 = float64Random(); + break; + case 1: + if ( sequenceB.done ) { + sequenceB.done = FALSE; + current_a_float64 = float64NextQInP2( &sequenceA ); + } + testCases_a_float64 = current_a_float64; + testCases_b_float64 = float64NextQInP2( &sequenceB ); + testCases_done = sequenceA.done & sequenceB.done; + subcase = -1; + break; + } + ++subcase; + break; +#ifdef FLOATX80 + case testCases_sequence_a_floatx80: + switch ( subcase ) { + case 0: + testCases_a_floatx80 = floatx80Random(); + break; + case 1: + testCases_a_floatx80 = floatx80NextQOutP2( &sequenceA ); + testCases_done = sequenceA.done; + subcase = -1; + break; + } + ++subcase; + break; + case testCases_sequence_ab_floatx80: + switch ( subcase ) { + case 0: + testCases_a_floatx80 = floatx80Random(); + testCases_b_floatx80 = floatx80Random(); + break; + case 1: + if ( sequenceB.done ) { + sequenceB.done = FALSE; + current_a_floatx80 = floatx80NextQInP2( &sequenceA ); + } + testCases_a_floatx80 = current_a_floatx80; + testCases_b_floatx80 = floatx80NextQInP2( &sequenceB ); + testCases_done = sequenceA.done & sequenceB.done; + subcase = -1; + break; + } + ++subcase; + break; +#endif +#ifdef FLOAT128 + case testCases_sequence_a_float128: + switch ( subcase ) { + case 0: + testCases_a_float128 = float128Random(); + break; + case 1: + testCases_a_float128 = float128NextQOutP2( &sequenceA ); + testCases_done = sequenceA.done; + subcase = -1; + break; + } + ++subcase; + break; + case testCases_sequence_ab_float128: + switch ( subcase ) { + case 0: + testCases_a_float128 = float128Random(); + testCases_b_float128 = float128Random(); + break; + case 1: + if ( sequenceB.done ) { + sequenceB.done = FALSE; + current_a_float128 = float128NextQInP2( &sequenceA ); + } + testCases_a_float128 = current_a_float128; + testCases_b_float128 = float128NextQInP2( &sequenceB ); + testCases_done = sequenceA.done & sequenceB.done; + subcase = -1; + break; + } + ++subcase; + break; +#endif + } + break; + } + +} + diff --git a/tools/test/testfloat/testCases.h b/tools/test/testfloat/testCases.h new file mode 100644 index 0000000..ed6ea2b --- /dev/null +++ b/tools/test/testfloat/testCases.h @@ -0,0 +1,69 @@ + +/* +=============================================================================== + +This C header file is part of TestFloat, Release 2a, a package of programs +for testing the correctness of floating-point arithmetic complying to the +IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +void testCases_setLevel( int8 ); + +void testCases_initSequence( int8 ); +enum { + testCases_sequence_a_int32, +#ifdef BITS64 + testCases_sequence_a_int64, +#endif + testCases_sequence_a_float32, + testCases_sequence_ab_float32, + testCases_sequence_a_float64, + testCases_sequence_ab_float64, +#ifdef FLOATX80 + testCases_sequence_a_floatx80, + testCases_sequence_ab_floatx80, +#endif +#ifdef FLOAT128 + testCases_sequence_a_float128, + testCases_sequence_ab_float128, +#endif +}; + +extern uint32 testCases_total; +extern flag testCases_done; + +void testCases_next( void ); + +extern int32 testCases_a_int32; +#ifdef BITS64 +extern int64 testCases_a_int64; +#endif +extern float32 testCases_a_float32; +extern float32 testCases_b_float32; +extern float64 testCases_a_float64; +extern float64 testCases_b_float64; +#ifdef FLOATX80 +extern floatx80 testCases_a_floatx80; +extern floatx80 testCases_b_floatx80; +#endif +#ifdef FLOAT128 +extern float128 testCases_a_float128; +extern float128 testCases_b_float128; +#endif + diff --git a/tools/test/testfloat/testFunction.c b/tools/test/testfloat/testFunction.c new file mode 100644 index 0000000..687563b --- /dev/null +++ b/tools/test/testfloat/testFunction.c @@ -0,0 +1,1149 @@ + +/* +=============================================================================== + +This C source file is part of TestFloat, Release 2a, a package of programs +for testing the correctness of floating-point arithmetic complying to the +IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +#include "milieu.h" +#include "softfloat.h" +#include "testCases.h" +#include "testLoops.h" +#include "systmodes.h" +#include "systflags.h" +#include "systfloat.h" +#include "testFunction.h" + +const functionT functions[ NUM_FUNCTIONS ] = { + { 0, 0, 0, 0 }, + { "int32_to_float32", 1, FALSE, TRUE }, + { "int32_to_float64", 1, FALSE, FALSE }, + { "int32_to_floatx80", 1, FALSE, FALSE }, + { "int32_to_float128", 1, FALSE, FALSE }, + { "int64_to_float32", 1, FALSE, TRUE }, + { "int64_to_float64", 1, FALSE, TRUE }, + { "int64_to_floatx80", 1, FALSE, FALSE }, + { "int64_to_float128", 1, FALSE, FALSE }, + { "float32_to_int32", 1, FALSE, TRUE }, + { "float32_to_int32_round_to_zero", 1, FALSE, FALSE }, + { "float32_to_int64", 1, FALSE, TRUE }, + { "float32_to_int64_round_to_zero", 1, FALSE, FALSE }, + { "float32_to_float64", 1, FALSE, FALSE }, + { "float32_to_floatx80", 1, FALSE, FALSE }, + { "float32_to_float128", 1, FALSE, FALSE }, + { "float32_round_to_int", 1, FALSE, TRUE }, + { "float32_add", 2, FALSE, TRUE }, + { "float32_sub", 2, FALSE, TRUE }, + { "float32_mul", 2, FALSE, TRUE }, + { "float32_div", 2, FALSE, TRUE }, + { "float32_rem", 2, FALSE, FALSE }, + { "float32_sqrt", 1, FALSE, TRUE }, + { "float32_eq", 2, FALSE, FALSE }, + { "float32_le", 2, FALSE, FALSE }, + { "float32_lt", 2, FALSE, FALSE }, + { "float32_eq_signaling", 2, FALSE, FALSE }, + { "float32_le_quiet", 2, FALSE, FALSE }, + { "float32_lt_quiet", 2, FALSE, FALSE }, + { "float64_to_int32", 1, FALSE, TRUE }, + { "float64_to_int32_round_to_zero", 1, FALSE, FALSE }, + { "float64_to_int64", 1, FALSE, TRUE }, + { "float64_to_int64_round_to_zero", 1, FALSE, FALSE }, + { "float64_to_float32", 1, FALSE, TRUE }, + { "float64_to_floatx80", 1, FALSE, FALSE }, + { "float64_to_float128", 1, FALSE, FALSE }, + { "float64_round_to_int", 1, FALSE, TRUE }, + { "float64_add", 2, FALSE, TRUE }, + { "float64_sub", 2, FALSE, TRUE }, + { "float64_mul", 2, FALSE, TRUE }, + { "float64_div", 2, FALSE, TRUE }, + { "float64_rem", 2, FALSE, FALSE }, + { "float64_sqrt", 1, FALSE, TRUE }, + { "float64_eq", 2, FALSE, FALSE }, + { "float64_le", 2, FALSE, FALSE }, + { "float64_lt", 2, FALSE, FALSE }, + { "float64_eq_signaling", 2, FALSE, FALSE }, + { "float64_le_quiet", 2, FALSE, FALSE }, + { "float64_lt_quiet", 2, FALSE, FALSE }, + { "floatx80_to_int32", 1, FALSE, TRUE }, + { "floatx80_to_int32_round_to_zero", 1, FALSE, FALSE }, + { "floatx80_to_int64", 1, FALSE, TRUE }, + { "floatx80_to_int64_round_to_zero", 1, FALSE, FALSE }, + { "floatx80_to_float32", 1, FALSE, TRUE }, + { "floatx80_to_float64", 1, FALSE, TRUE }, + { "floatx80_to_float128", 1, FALSE, FALSE }, + { "floatx80_round_to_int", 1, FALSE, TRUE }, + { "floatx80_add", 2, TRUE, TRUE }, + { "floatx80_sub", 2, TRUE, TRUE }, + { "floatx80_mul", 2, TRUE, TRUE }, + { "floatx80_div", 2, TRUE, TRUE }, + { "floatx80_rem", 2, FALSE, FALSE }, + { "floatx80_sqrt", 1, TRUE, TRUE }, + { "floatx80_eq", 2, FALSE, FALSE }, + { "floatx80_le", 2, FALSE, FALSE }, + { "floatx80_lt", 2, FALSE, FALSE }, + { "floatx80_eq_signaling", 2, FALSE, FALSE }, + { "floatx80_le_quiet", 2, FALSE, FALSE }, + { "floatx80_lt_quiet", 2, FALSE, FALSE }, + { "float128_to_int32", 1, FALSE, TRUE }, + { "float128_to_int32_round_to_zero", 1, FALSE, FALSE }, + { "float128_to_int64", 1, FALSE, TRUE }, + { "float128_to_int64_round_to_zero", 1, FALSE, FALSE }, + { "float128_to_float32", 1, FALSE, TRUE }, + { "float128_to_float64", 1, FALSE, TRUE }, + { "float128_to_floatx80", 1, FALSE, TRUE }, + { "float128_round_to_int", 1, FALSE, TRUE }, + { "float128_add", 2, FALSE, TRUE }, + { "float128_sub", 2, FALSE, TRUE }, + { "float128_mul", 2, FALSE, TRUE }, + { "float128_div", 2, FALSE, TRUE }, + { "float128_rem", 2, FALSE, FALSE }, + { "float128_sqrt", 1, FALSE, TRUE }, + { "float128_eq", 2, FALSE, FALSE }, + { "float128_le", 2, FALSE, FALSE }, + { "float128_lt", 2, FALSE, FALSE }, + { "float128_eq_signaling", 2, FALSE, FALSE }, + { "float128_le_quiet", 2, FALSE, FALSE }, + { "float128_lt_quiet", 2, FALSE, FALSE }, +}; + +const flag functionExists[ NUM_FUNCTIONS ] = { + 0, +#ifdef SYST_INT32_TO_FLOAT32 + 1, +#else + 0, +#endif +#ifdef SYST_INT32_TO_FLOAT64 + 1, +#else + 0, +#endif +#ifdef SYST_INT32_TO_FLOATX80 + 1, +#else + 0, +#endif +#ifdef SYST_INT32_TO_FLOAT128 + 1, +#else + 0, +#endif +#ifdef SYST_INT64_TO_FLOAT32 + 1, +#else + 0, +#endif +#ifdef SYST_INT64_TO_FLOAT64 + 1, +#else + 0, +#endif +#ifdef SYST_INT64_TO_FLOATX80 + 1, +#else + 0, +#endif +#ifdef SYST_INT64_TO_FLOAT128 + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT32_TO_INT32 + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT32_TO_INT32_ROUND_TO_ZERO + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT32_TO_INT64 + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT32_TO_INT64_ROUND_TO_ZERO + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT32_TO_FLOAT64 + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT32_TO_FLOATX80 + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT32_TO_FLOAT128 + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT32_ROUND_TO_INT + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT32_ADD + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT32_SUB + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT32_MUL + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT32_DIV + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT32_REM + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT32_SQRT + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT32_EQ + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT32_LE + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT32_LT + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT32_EQ_SIGNALING + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT32_LE_QUIET + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT32_LT_QUIET + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT64_TO_INT32 + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT64_TO_INT32_ROUND_TO_ZERO + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT64_TO_INT64 + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT64_TO_INT64_ROUND_TO_ZERO + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT64_TO_FLOAT32 + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT64_TO_FLOATX80 + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT64_TO_FLOAT128 + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT64_ROUND_TO_INT + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT64_ADD + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT64_SUB + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT64_MUL + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT64_DIV + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT64_REM + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT64_SQRT + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT64_EQ + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT64_LE + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT64_LT + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT64_EQ_SIGNALING + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT64_LE_QUIET + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT64_LT_QUIET + 1, +#else + 0, +#endif +#ifdef SYST_FLOATX80_TO_INT32 + 1, +#else + 0, +#endif +#ifdef SYST_FLOATX80_TO_INT32_ROUND_TO_ZERO + 1, +#else + 0, +#endif +#ifdef SYST_FLOATX80_TO_INT64 + 1, +#else + 0, +#endif +#ifdef SYST_FLOATX80_TO_INT64_ROUND_TO_ZERO + 1, +#else + 0, +#endif +#ifdef SYST_FLOATX80_TO_FLOAT32 + 1, +#else + 0, +#endif +#ifdef SYST_FLOATX80_TO_FLOAT64 + 1, +#else + 0, +#endif +#ifdef SYST_FLOATX80_TO_FLOAT128 + 1, +#else + 0, +#endif +#ifdef SYST_FLOATX80_ROUND_TO_INT + 1, +#else + 0, +#endif +#ifdef SYST_FLOATX80_ADD + 1, +#else + 0, +#endif +#ifdef SYST_FLOATX80_SUB + 1, +#else + 0, +#endif +#ifdef SYST_FLOATX80_MUL + 1, +#else + 0, +#endif +#ifdef SYST_FLOATX80_DIV + 1, +#else + 0, +#endif +#ifdef SYST_FLOATX80_REM + 1, +#else + 0, +#endif +#ifdef SYST_FLOATX80_SQRT + 1, +#else + 0, +#endif +#ifdef SYST_FLOATX80_EQ + 1, +#else + 0, +#endif +#ifdef SYST_FLOATX80_LE + 1, +#else + 0, +#endif +#ifdef SYST_FLOATX80_LT + 1, +#else + 0, +#endif +#ifdef SYST_FLOATX80_EQ_SIGNALING + 1, +#else + 0, +#endif +#ifdef SYST_FLOATX80_LE_QUIET + 1, +#else + 0, +#endif +#ifdef SYST_FLOATX80_LT_QUIET + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT128_TO_INT32 + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT128_TO_INT32_ROUND_TO_ZERO + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT128_TO_INT64 + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT128_TO_INT64_ROUND_TO_ZERO + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT128_TO_FLOAT32 + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT128_TO_FLOAT64 + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT128_TO_FLOATX80 + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT128_ROUND_TO_INT + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT128_ADD + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT128_SUB + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT128_MUL + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT128_DIV + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT128_REM + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT128_SQRT + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT128_EQ + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT128_LE + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT128_LT + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT128_EQ_SIGNALING + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT128_LE_QUIET + 1, +#else + 0, +#endif +#ifdef SYST_FLOAT128_LT_QUIET + 1, +#else + 0, +#endif +}; + +static void + testFunctionVariety( + uint8 functionCode, int8 roundingPrecision, int8 roundingMode ) +{ + uint8 roundingCode; + + functionName = functions[ functionCode ].name; +#ifdef FLOATX80 + if ( roundingPrecision == 32 ) { + roundingPrecisionName = "32"; + } + else if ( roundingPrecision == 64 ) { + roundingPrecisionName = "64"; + } + else if ( roundingPrecision == 80 ) { + roundingPrecisionName = "80"; + } + else { + roundingPrecision = 80; + roundingPrecisionName = 0; + } + floatx80_rounding_precision = roundingPrecision; + syst_float_set_rounding_precision( roundingPrecision ); +#endif + switch ( roundingMode ) { + case 0: + roundingModeName = 0; + roundingCode = float_round_nearest_even; + break; + case ROUND_NEAREST_EVEN: + roundingModeName = "nearest_even"; + roundingCode = float_round_nearest_even; + break; + case ROUND_TO_ZERO: + roundingModeName = "to_zero"; + roundingCode = float_round_to_zero; + break; + case ROUND_DOWN: + roundingModeName = "down"; + roundingCode = float_round_down; + break; + case ROUND_UP: + roundingModeName = "up"; + roundingCode = float_round_up; + break; + } + float_rounding_mode = roundingCode; + syst_float_set_rounding_mode( roundingCode ); + fputs( "Testing ", stderr ); + writeFunctionName( stderr ); + fputs( ".\n", stderr ); + switch ( functionCode ) { +#ifdef SYST_INT32_TO_FLOAT32 + case INT32_TO_FLOAT32: + test_a_int32_z_float32( int32_to_float32, syst_int32_to_float32 ); + break; +#endif +#ifdef SYST_INT32_TO_FLOAT64 + case INT32_TO_FLOAT64: + test_a_int32_z_float64( int32_to_float64, syst_int32_to_float64 ); + break; +#endif +#ifdef SYST_INT32_TO_FLOATX80 + case INT32_TO_FLOATX80: + test_a_int32_z_floatx80( int32_to_floatx80, syst_int32_to_floatx80 ); + break; +#endif +#ifdef SYST_INT32_TO_FLOAT128 + case INT32_TO_FLOAT128: + test_a_int32_z_float128( int32_to_float128, syst_int32_to_float128 ); + break; +#endif +#ifdef SYST_INT64_TO_FLOAT32 + case INT64_TO_FLOAT32: + test_a_int64_z_float32( int64_to_float32, syst_int64_to_float32 ); + break; +#endif +#ifdef SYST_INT64_TO_FLOAT64 + case INT64_TO_FLOAT64: + test_a_int64_z_float64( int64_to_float64, syst_int64_to_float64 ); + break; +#endif +#ifdef SYST_INT64_TO_FLOATX80 + case INT64_TO_FLOATX80: + test_a_int64_z_floatx80( int64_to_floatx80, syst_int64_to_floatx80 ); + break; +#endif +#ifdef SYST_INT64_TO_FLOAT128 + case INT64_TO_FLOAT128: + test_a_int64_z_float128( int64_to_float128, syst_int64_to_float128 ); + break; +#endif +#ifdef SYST_FLOAT32_TO_INT32 + case FLOAT32_TO_INT32: + test_a_float32_z_int32( float32_to_int32, syst_float32_to_int32 ); + break; +#endif +#ifdef SYST_FLOAT32_TO_INT32_ROUND_TO_ZERO + case FLOAT32_TO_INT32_ROUND_TO_ZERO: + test_a_float32_z_int32( + float32_to_int32_round_to_zero, + syst_float32_to_int32_round_to_zero + ); + break; +#endif +#ifdef SYST_FLOAT32_TO_INT64 + case FLOAT32_TO_INT64: + test_a_float32_z_int64( float32_to_int64, syst_float32_to_int64 ); + break; +#endif +#ifdef SYST_FLOAT32_TO_INT64_ROUND_TO_ZERO + case FLOAT32_TO_INT64_ROUND_TO_ZERO: + test_a_float32_z_int64( + float32_to_int64_round_to_zero, + syst_float32_to_int64_round_to_zero + ); + break; +#endif +#ifdef SYST_FLOAT32_TO_FLOAT64 + case FLOAT32_TO_FLOAT64: + test_a_float32_z_float64( + float32_to_float64, syst_float32_to_float64 ); + break; +#endif +#ifdef SYST_FLOAT32_TO_FLOATX80 + case FLOAT32_TO_FLOATX80: + test_a_float32_z_floatx80( + float32_to_floatx80, syst_float32_to_floatx80 ); + break; +#endif +#ifdef SYST_FLOAT32_TO_FLOAT128 + case FLOAT32_TO_FLOAT128: + test_a_float32_z_float128( + float32_to_float128, syst_float32_to_float128 ); + break; +#endif +#ifdef SYST_FLOAT32_ROUND_TO_INT + case FLOAT32_ROUND_TO_INT: + test_az_float32( float32_round_to_int, syst_float32_round_to_int ); + break; +#endif +#ifdef SYST_FLOAT32_ADD + case FLOAT32_ADD: + test_abz_float32( float32_add, syst_float32_add ); + break; +#endif +#ifdef SYST_FLOAT32_SUB + case FLOAT32_SUB: + test_abz_float32( float32_sub, syst_float32_sub ); + break; +#endif +#ifdef SYST_FLOAT32_MUL + case FLOAT32_MUL: + test_abz_float32( float32_mul, syst_float32_mul ); + break; +#endif +#ifdef SYST_FLOAT32_DIV + case FLOAT32_DIV: + test_abz_float32( float32_div, syst_float32_div ); + break; +#endif +#ifdef SYST_FLOAT32_REM + case FLOAT32_REM: + test_abz_float32( float32_rem, syst_float32_rem ); + break; +#endif +#ifdef SYST_FLOAT32_SQRT + case FLOAT32_SQRT: + test_az_float32( float32_sqrt, syst_float32_sqrt ); + break; +#endif +#ifdef SYST_FLOAT32_EQ + case FLOAT32_EQ: + test_ab_float32_z_flag( float32_eq, syst_float32_eq ); + break; +#endif +#ifdef SYST_FLOAT32_LE + case FLOAT32_LE: + test_ab_float32_z_flag( float32_le, syst_float32_le ); + break; +#endif +#ifdef SYST_FLOAT32_LT + case FLOAT32_LT: + test_ab_float32_z_flag( float32_lt, syst_float32_lt ); + break; +#endif +#ifdef SYST_FLOAT32_EQ_SIGNALING + case FLOAT32_EQ_SIGNALING: + test_ab_float32_z_flag( + float32_eq_signaling, syst_float32_eq_signaling ); + break; +#endif +#ifdef SYST_FLOAT32_LE_QUIET + case FLOAT32_LE_QUIET: + test_ab_float32_z_flag( float32_le_quiet, syst_float32_le_quiet ); + break; +#endif +#ifdef SYST_FLOAT32_LT_QUIET + case FLOAT32_LT_QUIET: + test_ab_float32_z_flag( float32_lt_quiet, syst_float32_lt_quiet ); + break; +#endif +#ifdef SYST_FLOAT64_TO_INT32 + case FLOAT64_TO_INT32: + test_a_float64_z_int32( float64_to_int32, syst_float64_to_int32 ); + break; +#endif +#ifdef SYST_FLOAT64_TO_INT32_ROUND_TO_ZERO + case FLOAT64_TO_INT32_ROUND_TO_ZERO: + test_a_float64_z_int32( + float64_to_int32_round_to_zero, + syst_float64_to_int32_round_to_zero + ); + break; +#endif +#ifdef SYST_FLOAT64_TO_INT64 + case FLOAT64_TO_INT64: + test_a_float64_z_int64( float64_to_int64, syst_float64_to_int64 ); + break; +#endif +#ifdef SYST_FLOAT64_TO_INT64_ROUND_TO_ZERO + case FLOAT64_TO_INT64_ROUND_TO_ZERO: + test_a_float64_z_int64( + float64_to_int64_round_to_zero, + syst_float64_to_int64_round_to_zero + ); + break; +#endif +#ifdef SYST_FLOAT64_TO_FLOAT32 + case FLOAT64_TO_FLOAT32: + test_a_float64_z_float32( + float64_to_float32, syst_float64_to_float32 ); + break; +#endif +#ifdef SYST_FLOAT64_TO_FLOATX80 + case FLOAT64_TO_FLOATX80: + test_a_float64_z_floatx80( + float64_to_floatx80, syst_float64_to_floatx80 ); + break; +#endif +#ifdef SYST_FLOAT64_TO_FLOAT128 + case FLOAT64_TO_FLOAT128: + test_a_float64_z_float128( + float64_to_float128, syst_float64_to_float128 ); + break; +#endif +#ifdef SYST_FLOAT64_ROUND_TO_INT + case FLOAT64_ROUND_TO_INT: + test_az_float64( float64_round_to_int, syst_float64_round_to_int ); + break; +#endif +#ifdef SYST_FLOAT64_ADD + case FLOAT64_ADD: + test_abz_float64( float64_add, syst_float64_add ); + break; +#endif +#ifdef SYST_FLOAT64_SUB + case FLOAT64_SUB: + test_abz_float64( float64_sub, syst_float64_sub ); + break; +#endif +#ifdef SYST_FLOAT64_MUL + case FLOAT64_MUL: + test_abz_float64( float64_mul, syst_float64_mul ); + break; +#endif +#ifdef SYST_FLOAT64_DIV + case FLOAT64_DIV: + test_abz_float64( float64_div, syst_float64_div ); + break; +#endif +#ifdef SYST_FLOAT64_REM + case FLOAT64_REM: + test_abz_float64( float64_rem, syst_float64_rem ); + break; +#endif +#ifdef SYST_FLOAT64_SQRT + case FLOAT64_SQRT: + test_az_float64( float64_sqrt, syst_float64_sqrt ); + break; +#endif +#ifdef SYST_FLOAT64_EQ + case FLOAT64_EQ: + test_ab_float64_z_flag( float64_eq, syst_float64_eq ); + break; +#endif +#ifdef SYST_FLOAT64_LE + case FLOAT64_LE: + test_ab_float64_z_flag( float64_le, syst_float64_le ); + break; +#endif +#ifdef SYST_FLOAT64_LT + case FLOAT64_LT: + test_ab_float64_z_flag( float64_lt, syst_float64_lt ); + break; +#endif +#ifdef SYST_FLOAT64_EQ_SIGNALING + case FLOAT64_EQ_SIGNALING: + test_ab_float64_z_flag( + float64_eq_signaling, syst_float64_eq_signaling ); + break; +#endif +#ifdef SYST_FLOAT64_LE_QUIET + case FLOAT64_LE_QUIET: + test_ab_float64_z_flag( float64_le_quiet, syst_float64_le_quiet ); + break; +#endif +#ifdef SYST_FLOAT64_LT_QUIET + case FLOAT64_LT_QUIET: + test_ab_float64_z_flag( float64_lt_quiet, syst_float64_lt_quiet ); + break; +#endif +#ifdef SYST_FLOATX80_TO_INT32 + case FLOATX80_TO_INT32: + test_a_floatx80_z_int32( floatx80_to_int32, syst_floatx80_to_int32 ); + break; +#endif +#ifdef SYST_FLOATX80_TO_INT32_ROUND_TO_ZERO + case FLOATX80_TO_INT32_ROUND_TO_ZERO: + test_a_floatx80_z_int32( + floatx80_to_int32_round_to_zero, + syst_floatx80_to_int32_round_to_zero + ); + break; +#endif +#ifdef SYST_FLOATX80_TO_INT64 + case FLOATX80_TO_INT64: + test_a_floatx80_z_int64( floatx80_to_int64, syst_floatx80_to_int64 ); + break; +#endif +#ifdef SYST_FLOATX80_TO_INT64_ROUND_TO_ZERO + case FLOATX80_TO_INT64_ROUND_TO_ZERO: + test_a_floatx80_z_int64( + floatx80_to_int64_round_to_zero, + syst_floatx80_to_int64_round_to_zero + ); + break; +#endif +#ifdef SYST_FLOATX80_TO_FLOAT32 + case FLOATX80_TO_FLOAT32: + test_a_floatx80_z_float32( + floatx80_to_float32, syst_floatx80_to_float32 ); + break; +#endif +#ifdef SYST_FLOATX80_TO_FLOAT64 + case FLOATX80_TO_FLOAT64: + test_a_floatx80_z_float64( + floatx80_to_float64, syst_floatx80_to_float64 ); + break; +#endif +#ifdef SYST_FLOATX80_TO_FLOAT128 + case FLOATX80_TO_FLOAT128: + test_a_floatx80_z_float128( + floatx80_to_float128, syst_floatx80_to_float128 ); + break; +#endif +#ifdef SYST_FLOATX80_ROUND_TO_INT + case FLOATX80_ROUND_TO_INT: + test_az_floatx80( floatx80_round_to_int, syst_floatx80_round_to_int ); + break; +#endif +#ifdef SYST_FLOATX80_ADD + case FLOATX80_ADD: + test_abz_floatx80( floatx80_add, syst_floatx80_add ); + break; +#endif +#ifdef SYST_FLOATX80_SUB + case FLOATX80_SUB: + test_abz_floatx80( floatx80_sub, syst_floatx80_sub ); + break; +#endif +#ifdef SYST_FLOATX80_MUL + case FLOATX80_MUL: + test_abz_floatx80( floatx80_mul, syst_floatx80_mul ); + break; +#endif +#ifdef SYST_FLOATX80_DIV + case FLOATX80_DIV: + test_abz_floatx80( floatx80_div, syst_floatx80_div ); + break; +#endif +#ifdef SYST_FLOATX80_REM + case FLOATX80_REM: + test_abz_floatx80( floatx80_rem, syst_floatx80_rem ); + break; +#endif +#ifdef SYST_FLOATX80_SQRT + case FLOATX80_SQRT: + test_az_floatx80( floatx80_sqrt, syst_floatx80_sqrt ); + break; +#endif +#ifdef SYST_FLOATX80_EQ + case FLOATX80_EQ: + test_ab_floatx80_z_flag( floatx80_eq, syst_floatx80_eq ); + break; +#endif +#ifdef SYST_FLOATX80_LE + case FLOATX80_LE: + test_ab_floatx80_z_flag( floatx80_le, syst_floatx80_le ); + break; +#endif +#ifdef SYST_FLOATX80_LT + case FLOATX80_LT: + test_ab_floatx80_z_flag( floatx80_lt, syst_floatx80_lt ); + break; +#endif +#ifdef SYST_FLOATX80_EQ_SIGNALING + case FLOATX80_EQ_SIGNALING: + test_ab_floatx80_z_flag( + floatx80_eq_signaling, syst_floatx80_eq_signaling ); + break; +#endif +#ifdef SYST_FLOATX80_LE_QUIET + case FLOATX80_LE_QUIET: + test_ab_floatx80_z_flag( floatx80_le_quiet, syst_floatx80_le_quiet ); + break; +#endif +#ifdef SYST_FLOATX80_LT_QUIET + case FLOATX80_LT_QUIET: + test_ab_floatx80_z_flag( floatx80_lt_quiet, syst_floatx80_lt_quiet ); + break; +#endif +#ifdef SYST_FLOAT128_TO_INT32 + case FLOAT128_TO_INT32: + test_a_float128_z_int32( float128_to_int32, syst_float128_to_int32 ); + break; +#endif +#ifdef SYST_FLOAT128_TO_INT32_ROUND_TO_ZERO + case FLOAT128_TO_INT32_ROUND_TO_ZERO: + test_a_float128_z_int32( + float128_to_int32_round_to_zero, + syst_float128_to_int32_round_to_zero + ); + break; +#endif +#ifdef SYST_FLOAT128_TO_INT64 + case FLOAT128_TO_INT64: + test_a_float128_z_int64( float128_to_int64, syst_float128_to_int64 ); + break; +#endif +#ifdef SYST_FLOAT128_TO_INT64_ROUND_TO_ZERO + case FLOAT128_TO_INT64_ROUND_TO_ZERO: + test_a_float128_z_int64( + float128_to_int64_round_to_zero, + syst_float128_to_int64_round_to_zero + ); + break; +#endif +#ifdef SYST_FLOAT128_TO_FLOAT32 + case FLOAT128_TO_FLOAT32: + test_a_float128_z_float32( + float128_to_float32, syst_float128_to_float32 ); + break; +#endif +#ifdef SYST_FLOAT128_TO_FLOAT64 + case FLOAT128_TO_FLOAT64: + test_a_float128_z_float64( + float128_to_float64, syst_float128_to_float64 ); + break; +#endif +#ifdef SYST_FLOAT128_TO_FLOATX80 + case FLOAT128_TO_FLOATX80: + test_a_float128_z_floatx80( + float128_to_floatx80, syst_float128_to_floatx80 ); + break; +#endif +#ifdef SYST_FLOAT128_ROUND_TO_INT + case FLOAT128_ROUND_TO_INT: + test_az_float128( float128_round_to_int, syst_float128_round_to_int ); + break; +#endif +#ifdef SYST_FLOAT128_ADD + case FLOAT128_ADD: + test_abz_float128( float128_add, syst_float128_add ); + break; +#endif +#ifdef SYST_FLOAT128_SUB + case FLOAT128_SUB: + test_abz_float128( float128_sub, syst_float128_sub ); + break; +#endif +#ifdef SYST_FLOAT128_MUL + case FLOAT128_MUL: + test_abz_float128( float128_mul, syst_float128_mul ); + break; +#endif +#ifdef SYST_FLOAT128_DIV + case FLOAT128_DIV: + test_abz_float128( float128_div, syst_float128_div ); + break; +#endif +#ifdef SYST_FLOAT128_REM + case FLOAT128_REM: + test_abz_float128( float128_rem, syst_float128_rem ); + break; +#endif +#ifdef SYST_FLOAT128_SQRT + case FLOAT128_SQRT: + test_az_float128( float128_sqrt, syst_float128_sqrt ); + break; +#endif +#ifdef SYST_FLOAT128_EQ + case FLOAT128_EQ: + test_ab_float128_z_flag( float128_eq, syst_float128_eq ); + break; +#endif +#ifdef SYST_FLOAT128_LE + case FLOAT128_LE: + test_ab_float128_z_flag( float128_le, syst_float128_le ); + break; +#endif +#ifdef SYST_FLOAT128_LT + case FLOAT128_LT: + test_ab_float128_z_flag( float128_lt, syst_float128_lt ); + break; +#endif +#ifdef SYST_FLOAT128_EQ_SIGNALING + case FLOAT128_EQ_SIGNALING: + test_ab_float128_z_flag( + float128_eq_signaling, syst_float128_eq_signaling ); + break; +#endif +#ifdef SYST_FLOAT128_LE_QUIET + case FLOAT128_LE_QUIET: + test_ab_float128_z_flag( float128_le_quiet, syst_float128_le_quiet ); + break; +#endif +#ifdef SYST_FLOAT128_LT_QUIET + case FLOAT128_LT_QUIET: + test_ab_float128_z_flag( float128_lt_quiet, syst_float128_lt_quiet ); + break; +#endif + } + if ( ( errorStop && anyErrors ) || stop ) exitWithStatus(); + +} + +void + testFunction( + uint8 functionCode, int8 roundingPrecisionIn, int8 roundingModeIn ) +{ + int8 roundingPrecision, roundingMode; + + roundingPrecision = 32; + for (;;) { + if ( ! functions[ functionCode ].roundingPrecision ) { + roundingPrecision = 0; + } + else if ( roundingPrecisionIn ) { + roundingPrecision = roundingPrecisionIn; + } + for ( roundingMode = 1; + roundingMode < NUM_ROUNDINGMODES; + ++roundingMode + ) { + if ( ! functions[ functionCode ].roundingMode ) { + roundingMode = 0; + } + else if ( roundingModeIn ) { + roundingMode = roundingModeIn; + } + testFunctionVariety( + functionCode, roundingPrecision, roundingMode ); + if ( roundingModeIn || ! roundingMode ) break; + } + if ( roundingPrecisionIn || ! roundingPrecision ) break; + if ( roundingPrecision == 80 ) { + break; + } + else if ( roundingPrecision == 64 ) { + roundingPrecision = 80; + } + else if ( roundingPrecision == 32 ) { + roundingPrecision = 64; + } + } + +} + diff --git a/tools/test/testfloat/testFunction.h b/tools/test/testfloat/testFunction.h new file mode 100644 index 0000000..04bf856 --- /dev/null +++ b/tools/test/testfloat/testFunction.h @@ -0,0 +1,135 @@ + +/* +=============================================================================== + +This C header file is part of TestFloat, Release 2a, a package of programs +for testing the correctness of floating-point arithmetic complying to the +IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +enum { + INT32_TO_FLOAT32 = 1, + INT32_TO_FLOAT64, + INT32_TO_FLOATX80, + INT32_TO_FLOAT128, + INT64_TO_FLOAT32, + INT64_TO_FLOAT64, + INT64_TO_FLOATX80, + INT64_TO_FLOAT128, + FLOAT32_TO_INT32, + FLOAT32_TO_INT32_ROUND_TO_ZERO, + FLOAT32_TO_INT64, + FLOAT32_TO_INT64_ROUND_TO_ZERO, + FLOAT32_TO_FLOAT64, + FLOAT32_TO_FLOATX80, + FLOAT32_TO_FLOAT128, + FLOAT32_ROUND_TO_INT, + FLOAT32_ADD, + FLOAT32_SUB, + FLOAT32_MUL, + FLOAT32_DIV, + FLOAT32_REM, + FLOAT32_SQRT, + FLOAT32_EQ, + FLOAT32_LE, + FLOAT32_LT, + FLOAT32_EQ_SIGNALING, + FLOAT32_LE_QUIET, + FLOAT32_LT_QUIET, + FLOAT64_TO_INT32, + FLOAT64_TO_INT32_ROUND_TO_ZERO, + FLOAT64_TO_INT64, + FLOAT64_TO_INT64_ROUND_TO_ZERO, + FLOAT64_TO_FLOAT32, + FLOAT64_TO_FLOATX80, + FLOAT64_TO_FLOAT128, + FLOAT64_ROUND_TO_INT, + FLOAT64_ADD, + FLOAT64_SUB, + FLOAT64_MUL, + FLOAT64_DIV, + FLOAT64_REM, + FLOAT64_SQRT, + FLOAT64_EQ, + FLOAT64_LE, + FLOAT64_LT, + FLOAT64_EQ_SIGNALING, + FLOAT64_LE_QUIET, + FLOAT64_LT_QUIET, + FLOATX80_TO_INT32, + FLOATX80_TO_INT32_ROUND_TO_ZERO, + FLOATX80_TO_INT64, + FLOATX80_TO_INT64_ROUND_TO_ZERO, + FLOATX80_TO_FLOAT32, + FLOATX80_TO_FLOAT64, + FLOATX80_TO_FLOAT128, + FLOATX80_ROUND_TO_INT, + FLOATX80_ADD, + FLOATX80_SUB, + FLOATX80_MUL, + FLOATX80_DIV, + FLOATX80_REM, + FLOATX80_SQRT, + FLOATX80_EQ, + FLOATX80_LE, + FLOATX80_LT, + FLOATX80_EQ_SIGNALING, + FLOATX80_LE_QUIET, + FLOATX80_LT_QUIET, + FLOAT128_TO_INT32, + FLOAT128_TO_INT32_ROUND_TO_ZERO, + FLOAT128_TO_INT64, + FLOAT128_TO_INT64_ROUND_TO_ZERO, + FLOAT128_TO_FLOAT32, + FLOAT128_TO_FLOAT64, + FLOAT128_TO_FLOATX80, + FLOAT128_ROUND_TO_INT, + FLOAT128_ADD, + FLOAT128_SUB, + FLOAT128_MUL, + FLOAT128_DIV, + FLOAT128_REM, + FLOAT128_SQRT, + FLOAT128_EQ, + FLOAT128_LE, + FLOAT128_LT, + FLOAT128_EQ_SIGNALING, + FLOAT128_LE_QUIET, + FLOAT128_LT_QUIET, + NUM_FUNCTIONS +}; + +typedef struct { + char *name; + int8 numInputs; + flag roundingPrecision, roundingMode; +} functionT; +extern const functionT functions[ NUM_FUNCTIONS ]; +extern const flag functionExists[ NUM_FUNCTIONS ]; + +enum { + ROUND_NEAREST_EVEN = 1, + ROUND_TO_ZERO, + ROUND_DOWN, + ROUND_UP, + NUM_ROUNDINGMODES +}; + +void testFunction( uint8, int8, int8 ); + diff --git a/tools/test/testfloat/testLoops.c b/tools/test/testfloat/testLoops.c new file mode 100644 index 0000000..8ba92f3 --- /dev/null +++ b/tools/test/testfloat/testLoops.c @@ -0,0 +1,2713 @@ + +/* +=============================================================================== + +This C source file is part of TestFloat, Release 2a, a package of programs +for testing the correctness of floating-point arithmetic complying to the +IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +#include <stdlib.h> +#include <stdio.h> +#include "milieu.h" +#include "softfloat.h" +#include "testCases.h" +#include "writeHex.h" +#include "testLoops.h" + +volatile flag stop = FALSE; + +char *trueName, *testName; +flag forever, errorStop; +uint32 maxErrorCount = 0; +flag checkNaNs = FALSE; +int8 *trueFlagsPtr; +int8 ( *testFlagsFunctionPtr )( void ); +char *functionName; +char *roundingPrecisionName, *roundingModeName, *tininessModeName; +flag anyErrors = FALSE; + +void writeFunctionName( FILE *stream ) +{ + + fputs( functionName, stream ); + if ( roundingModeName ) { + if ( roundingPrecisionName ) { + fputs( ", precision ", stream ); + fputs( roundingPrecisionName, stream ); + } + fputs( ", rounding ", stream ); + fputs( roundingModeName, stream ); + if ( tininessModeName ) { + fputs( ", tininess ", stream ); + fputs( tininessModeName, stream ); + fputs( " rounding", stream ); + } + } + +} + +void exitWithStatus( void ) +{ + + exit( anyErrors ? EXIT_FAILURE : EXIT_SUCCESS ); + +} + +static uint32 tenthousandsCount, errorCount = 0; + +static void writeTestsTotal( void ) +{ + + if ( forever ) { + fputs( "Unbounded tests.\n", stderr ); + } + else { + fprintf( stderr, "\r%d tests total.\n", testCases_total ); + } + +} + +static void writeTestsPerformed( int16 count ) +{ + + if ( tenthousandsCount ) { + fprintf( + stderr, "\r%d%04d tests performed", tenthousandsCount, count ); + } + else { + fprintf( stderr, "\r%d tests performed", count ); + } + if ( errorCount ) { + fprintf( + stderr, + "; %d error%s found.\n", + errorCount, + ( errorCount == 1 ) ? "" : "s" + ); + } + else { + fputs( ".\n", stderr ); + fputs( "No errors found in ", stdout ); + writeFunctionName( stdout ); + fputs( ".\n", stdout ); + fflush( stdout ); + } + +} + +static void checkEarlyExit( void ) +{ + + ++tenthousandsCount; + if ( stop ) { + writeTestsPerformed( 0 ); + exitWithStatus(); + } + fprintf( stderr, "\r%3d0000", tenthousandsCount ); + +} + +static void writeErrorFound( int16 count ) +{ + + fputc( '\r', stderr ); + if ( errorCount == 1 ) { + fputs( "Errors found in ", stdout ); + writeFunctionName( stdout ); + fputs( ":\n", stdout ); + } + if ( stop ) { + writeTestsPerformed( count ); + exitWithStatus(); + } + anyErrors = TRUE; + +} + +INLINE void writeInput_a_int32( void ) +{ + + writeHex_bits32( testCases_a_int32, stdout ); + +} + +#ifdef BITS64 + +INLINE void writeInput_a_int64( void ) +{ + + writeHex_bits64( testCases_a_int64, stdout ); + +} + +#endif + +INLINE void writeInput_a_float32( void ) +{ + + writeHex_float32( testCases_a_float32, stdout ); + +} + +static void writeInputs_ab_float32( void ) +{ + + writeHex_float32( testCases_a_float32, stdout ); + fputs( " ", stdout ); + writeHex_float32( testCases_b_float32, stdout ); + +} + +INLINE void writeInput_a_float64( void ) +{ + + writeHex_float64( testCases_a_float64, stdout ); + +} + +static void writeInputs_ab_float64( void ) +{ + + writeHex_float64( testCases_a_float64, stdout ); + fputs( " ", stdout ); + writeHex_float64( testCases_b_float64, stdout ); + +} + +#ifdef FLOATX80 + +INLINE void writeInput_a_floatx80( void ) +{ + + writeHex_floatx80( testCases_a_floatx80, stdout ); + +} + +static void writeInputs_ab_floatx80( void ) +{ + + writeHex_floatx80( testCases_a_floatx80, stdout ); + fputs( " ", stdout ); + writeHex_floatx80( testCases_b_floatx80, stdout ); + +} + +#endif + +#ifdef FLOAT128 + +INLINE void writeInput_a_float128( void ) +{ + + writeHex_float128( testCases_a_float128, stdout ); + +} + +static void writeInputs_ab_float128( void ) +{ + + writeHex_float128( testCases_a_float128, stdout ); + fputs( " ", stdout ); + writeHex_float128( testCases_b_float128, stdout ); + +} + +#endif + +static void + writeOutputs_z_flag( + flag trueZ, uint8 trueFlags, flag testZ, uint8 testFlags ) +{ + + fputs( trueName, stdout ); + fputs( ": ", stdout ); + writeHex_flag( trueZ, stdout ); + fputc( ' ', stdout ); + writeHex_float_flags( trueFlags, stdout ); + fputs( " ", stdout ); + fputs( testName, stdout ); + fputs( ": ", stdout ); + writeHex_flag( testZ, stdout ); + fputc( ' ', stdout ); + writeHex_float_flags( testFlags, stdout ); + fputc( '\n', stdout ); + +} + +static void + writeOutputs_z_int32( + int32 trueZ, uint8 trueFlags, int32 testZ, uint8 testFlags ) +{ + + fputs( trueName, stdout ); + fputs( ": ", stdout ); + writeHex_bits32( trueZ, stdout ); + fputc( ' ', stdout ); + writeHex_float_flags( trueFlags, stdout ); + fputs( " ", stdout ); + fputs( testName, stdout ); + fputs( ": ", stdout ); + writeHex_bits32( testZ, stdout ); + fputc( ' ', stdout ); + writeHex_float_flags( testFlags, stdout ); + fputc( '\n', stdout ); + +} + +#ifdef BITS64 + +static void + writeOutputs_z_int64( + int64 trueZ, uint8 trueFlags, int64 testZ, uint8 testFlags ) +{ + + fputs( trueName, stdout ); + fputs( ": ", stdout ); + writeHex_bits64( trueZ, stdout ); + fputc( ' ', stdout ); + writeHex_float_flags( trueFlags, stdout ); + fputs( " ", stdout ); + fputs( testName, stdout ); + fputs( ": ", stdout ); + writeHex_bits64( testZ, stdout ); + fputc( ' ', stdout ); + writeHex_float_flags( testFlags, stdout ); + fputc( '\n', stdout ); + +} + +#endif + +static void + writeOutputs_z_float32( + float32 trueZ, uint8 trueFlags, float32 testZ, uint8 testFlags ) +{ + + fputs( trueName, stdout ); + fputs( ": ", stdout ); + writeHex_float32( trueZ, stdout ); + fputc( ' ', stdout ); + writeHex_float_flags( trueFlags, stdout ); + fputs( " ", stdout ); + fputs( testName, stdout ); + fputs( ": ", stdout ); + writeHex_float32( testZ, stdout ); + fputc( ' ', stdout ); + writeHex_float_flags( testFlags, stdout ); + fputc( '\n', stdout ); + +} + +static void + writeOutputs_z_float64( + float64 trueZ, uint8 trueFlags, float64 testZ, uint8 testFlags ) +{ + + fputs( trueName, stdout ); + fputs( ": ", stdout ); + writeHex_float64( trueZ, stdout ); + fputc( ' ', stdout ); + writeHex_float_flags( trueFlags, stdout ); + fputs( " ", stdout ); + fputs( testName, stdout ); + fputs( ": ", stdout ); + writeHex_float64( testZ, stdout ); + fputc( ' ', stdout ); + writeHex_float_flags( testFlags, stdout ); + fputc( '\n', stdout ); + +} + +#ifdef FLOATX80 + +static void + writeOutputs_z_floatx80( + floatx80 trueZ, uint8 trueFlags, floatx80 testZ, uint8 testFlags ) +{ + + fputs( trueName, stdout ); + fputs( ": ", stdout ); + writeHex_floatx80( trueZ, stdout ); + fputc( ' ', stdout ); + writeHex_float_flags( trueFlags, stdout ); + fputs( " ", stdout ); + fputs( testName, stdout ); + fputs( ": ", stdout ); + writeHex_floatx80( testZ, stdout ); + fputc( ' ', stdout ); + writeHex_float_flags( testFlags, stdout ); + fputc( '\n', stdout ); + +} + +#endif + +#ifdef FLOAT128 + +static void + writeOutputs_z_float128( + float128 trueZ, uint8 trueFlags, float128 testZ, uint8 testFlags ) +{ + + fputs( trueName, stdout ); + fputs( ": ", stdout ); + writeHex_float128( trueZ, stdout ); + fputc( ' ', stdout ); + writeHex_float_flags( trueFlags, stdout ); + fputs( "\n\t", stdout ); + fputs( testName, stdout ); + fputs( ": ", stdout ); + writeHex_float128( testZ, stdout ); + fputc( ' ', stdout ); + writeHex_float_flags( testFlags, stdout ); + fputc( '\n', stdout ); + +} + +#endif + +INLINE flag float32_isNaN( float32 a ) +{ + + return 0x7F800000 < ( a & 0x7FFFFFFF ); + +} + +#ifdef BITS64 + +INLINE flag float64_same( float64 a, float64 b ) +{ + + return a == b; + +} + +INLINE flag float64_isNaN( float64 a ) +{ + + return LIT64( 0x7FF0000000000000 ) < ( a & LIT64( 0x7FFFFFFFFFFFFFFF ) ); + +} + +#else + +INLINE flag float64_same( float64 a, float64 b ) +{ + + return ( a.high == b.high ) && ( a.low == b.low ); + +} + +INLINE flag float64_isNaN( float64 a ) +{ + bits32 absAHigh; + + absAHigh = a.high & 0x7FFFFFFF; + return + ( 0x7FF00000 < absAHigh ) || ( ( absAHigh == 0x7FF00000 ) && a.low ); + +} + +#endif + +#ifdef FLOATX80 + +INLINE flag floatx80_same( floatx80 a, floatx80 b ) +{ + + return ( a.high == b.high ) && ( a.low == b.low ); + +} + +INLINE flag floatx80_isNaN( floatx80 a ) +{ + + return ( ( a.high & 0x7FFF ) == 0x7FFF ) && a.low; + +} + +#endif + +#ifdef FLOAT128 + +INLINE flag float128_same( float128 a, float128 b ) +{ + + return ( a.high == b.high ) && ( a.low == b.low ); + +} + +INLINE flag float128_isNaN( float128 a ) +{ + bits64 absAHigh; + + absAHigh = a.high & LIT64( 0x7FFFFFFFFFFFFFFF ); + return + ( LIT64( 0x7FFF000000000000 ) < absAHigh ) + || ( ( absAHigh == LIT64( 0x7FFF000000000000 ) ) && a.low ); + +} + +#endif + +void + test_a_int32_z_float32( + float32 trueFunction( int32 ), float32 testFunction( int32 ) ) +{ + int16 count; + float32 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_int32 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_int32 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_int32 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ( trueZ != testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && float32_isNaN( trueZ ) + && float32_isNaN( testZ ) + && ! float32_is_signaling_nan( testZ ) + && ( trueFlags == testFlags ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_int32(); + fputs( " ", stdout ); + writeOutputs_z_float32( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +void + test_a_int32_z_float64( + float64 trueFunction( int32 ), float64 testFunction( int32 ) ) +{ + int16 count; + float64 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_int32 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_int32 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_int32 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ! float64_same( trueZ, testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && float64_isNaN( trueZ ) + && float64_isNaN( testZ ) + && ! float64_is_signaling_nan( testZ ) + && ( trueFlags == testFlags ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_int32(); + fputs( " ", stdout ); + writeOutputs_z_float64( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +#ifdef FLOATX80 + +void + test_a_int32_z_floatx80( + floatx80 trueFunction( int32 ), floatx80 testFunction( int32 ) ) +{ + int16 count; + floatx80 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_int32 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_int32 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_int32 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ! floatx80_same( trueZ, testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && floatx80_isNaN( trueZ ) + && floatx80_isNaN( testZ ) + && ! floatx80_is_signaling_nan( testZ ) + && ( trueFlags == testFlags ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_int32(); + fputs( " ", stdout ); + writeOutputs_z_floatx80( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +#endif + +#ifdef FLOAT128 + +void + test_a_int32_z_float128( + float128 trueFunction( int32 ), float128 testFunction( int32 ) ) +{ + int16 count; + float128 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_int32 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_int32 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_int32 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ! float128_same( trueZ, testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && float128_isNaN( trueZ ) + && float128_isNaN( testZ ) + && ! float128_is_signaling_nan( testZ ) + && ( trueFlags == testFlags ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_int32(); + fputs( "\n\t", stdout ); + writeOutputs_z_float128( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +#endif + +#ifdef BITS64 + +void + test_a_int64_z_float32( + float32 trueFunction( int64 ), float32 testFunction( int64 ) ) +{ + int16 count; + float32 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_int64 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_int64 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_int64 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ( trueZ != testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && float32_isNaN( trueZ ) + && float32_isNaN( testZ ) + && ! float32_is_signaling_nan( testZ ) + && ( trueFlags == testFlags ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_int64(); + fputs( " ", stdout ); + writeOutputs_z_float32( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +void + test_a_int64_z_float64( + float64 trueFunction( int64 ), float64 testFunction( int64 ) ) +{ + int16 count; + float64 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_int64 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_int64 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_int64 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ! float64_same( trueZ, testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && float64_isNaN( trueZ ) + && float64_isNaN( testZ ) + && ! float64_is_signaling_nan( testZ ) + && ( trueFlags == testFlags ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_int64(); + fputs( " ", stdout ); + writeOutputs_z_float64( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +#ifdef FLOATX80 + +void + test_a_int64_z_floatx80( + floatx80 trueFunction( int64 ), floatx80 testFunction( int64 ) ) +{ + int16 count; + floatx80 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_int64 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_int64 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_int64 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ! floatx80_same( trueZ, testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && floatx80_isNaN( trueZ ) + && floatx80_isNaN( testZ ) + && ! floatx80_is_signaling_nan( testZ ) + && ( trueFlags == testFlags ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_int64(); + fputs( " ", stdout ); + writeOutputs_z_floatx80( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +#endif + +#ifdef FLOAT128 + +void + test_a_int64_z_float128( + float128 trueFunction( int64 ), float128 testFunction( int64 ) ) +{ + int16 count; + float128 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_int64 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_int64 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_int64 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ! float128_same( trueZ, testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && float128_isNaN( trueZ ) + && float128_isNaN( testZ ) + && ! float128_is_signaling_nan( testZ ) + && ( trueFlags == testFlags ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_int64(); + fputs( "\n\t", stdout ); + writeOutputs_z_float128( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +#endif + +#endif + +void + test_a_float32_z_int32( + int32 trueFunction( float32 ), int32 testFunction( float32 ) ) +{ + int16 count; + int32 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_float32 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_float32 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_float32 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ( trueZ != testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && float32_is_signaling_nan( testCases_a_float32 ) ) { + trueFlags |= float_flag_invalid; + } + if ( ( trueZ == 0x7FFFFFFF ) + && ( ( testZ == 0x7FFFFFFF ) + || ( testZ == (sbits32) 0x80000000 ) ) + && ( trueFlags == float_flag_invalid ) + && ( testFlags == float_flag_invalid ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_float32(); + fputs( " ", stdout ); + writeOutputs_z_int32( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +#ifdef BITS64 + +void + test_a_float32_z_int64( + int64 trueFunction( float32 ), int64 testFunction( float32 ) ) +{ + int16 count; + int64 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_float32 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_float32 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_float32 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ( trueZ != testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && float32_is_signaling_nan( testCases_a_float32 ) ) { + trueFlags |= float_flag_invalid; + } + if ( ( trueZ == LIT64( 0x7FFFFFFFFFFFFFFF ) ) + && ( ( testZ == LIT64( 0x7FFFFFFFFFFFFFFF ) ) + || ( testZ == (sbits64) LIT64( 0x8000000000000000 ) ) ) + && ( trueFlags == float_flag_invalid ) + && ( testFlags == float_flag_invalid ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_float32(); + fputs( " ", stdout ); + writeOutputs_z_int64( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +#endif + +void + test_a_float32_z_float64( + float64 trueFunction( float32 ), float64 testFunction( float32 ) ) +{ + int16 count; + float64 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_float32 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_float32 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_float32 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ! float64_same( trueZ, testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && float32_is_signaling_nan( testCases_a_float32 ) ) { + trueFlags |= float_flag_invalid; + } + if ( ! checkNaNs + && float64_isNaN( trueZ ) + && float64_isNaN( testZ ) + && ! float64_is_signaling_nan( testZ ) + && ( trueFlags == testFlags ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_float32(); + fputs( " ", stdout ); + writeOutputs_z_float64( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +#ifdef FLOATX80 + +void + test_a_float32_z_floatx80( + floatx80 trueFunction( float32 ), floatx80 testFunction( float32 ) ) +{ + int16 count; + floatx80 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_float32 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_float32 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_float32 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ! floatx80_same( trueZ, testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && float32_is_signaling_nan( testCases_a_float32 ) ) { + trueFlags |= float_flag_invalid; + } + if ( ! checkNaNs + && floatx80_isNaN( trueZ ) + && floatx80_isNaN( testZ ) + && ! floatx80_is_signaling_nan( testZ ) + && ( trueFlags == testFlags ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_float32(); + fputs( "\n\t", stdout ); + writeOutputs_z_floatx80( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +#endif + +#ifdef FLOAT128 + +void + test_a_float32_z_float128( + float128 trueFunction( float32 ), float128 testFunction( float32 ) ) +{ + int16 count; + float128 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_float32 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_float32 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_float32 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ! float128_same( trueZ, testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && float32_is_signaling_nan( testCases_a_float32 ) ) { + trueFlags |= float_flag_invalid; + } + if ( ! checkNaNs + && float128_isNaN( trueZ ) + && float128_isNaN( testZ ) + && ! float128_is_signaling_nan( testZ ) + && ( trueFlags == testFlags ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_float32(); + fputs( "\n\t", stdout ); + writeOutputs_z_float128( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +#endif + +void + test_az_float32( + float32 trueFunction( float32 ), float32 testFunction( float32 ) ) +{ + int16 count; + float32 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_float32 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_float32 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_float32 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ( trueZ != testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && float32_is_signaling_nan( testCases_a_float32 ) ) { + trueFlags |= float_flag_invalid; + } + if ( ! checkNaNs + && float32_isNaN( trueZ ) + && float32_isNaN( testZ ) + && ! float32_is_signaling_nan( testZ ) + && ( trueFlags == testFlags ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_float32(); + fputs( " ", stdout ); + writeOutputs_z_float32( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +void + test_ab_float32_z_flag( + flag trueFunction( float32, float32 ), + flag testFunction( float32, float32 ) + ) +{ + int16 count; + flag trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_ab_float32 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_float32, testCases_b_float32 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_float32, testCases_b_float32 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ( trueZ != testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && ( float32_is_signaling_nan( testCases_a_float32 ) + || float32_is_signaling_nan( testCases_b_float32 ) ) + ) { + trueFlags |= float_flag_invalid; + } + if ( ( trueZ != testZ ) || ( trueFlags != testFlags ) ) { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInputs_ab_float32(); + fputs( " ", stdout ); + writeOutputs_z_flag( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + return; + +} + +void + test_abz_float32( + float32 trueFunction( float32, float32 ), + float32 testFunction( float32, float32 ) + ) +{ + int16 count; + float32 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_ab_float32 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_float32, testCases_b_float32 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_float32, testCases_b_float32 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ( trueZ != testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && ( float32_is_signaling_nan( testCases_a_float32 ) + || float32_is_signaling_nan( testCases_b_float32 ) ) + ) { + trueFlags |= float_flag_invalid; + } + if ( ! checkNaNs + && float32_isNaN( trueZ ) + && float32_isNaN( testZ ) + && ! float32_is_signaling_nan( testZ ) + && ( trueFlags == testFlags ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInputs_ab_float32(); + fputs( " ", stdout ); + writeOutputs_z_float32( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + return; + +} + +void + test_a_float64_z_int32( + int32 trueFunction( float64 ), int32 testFunction( float64 ) ) +{ + int16 count; + int32 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_float64 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_float64 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_float64 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ( trueZ != testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && float64_is_signaling_nan( testCases_a_float64 ) ) { + trueFlags |= float_flag_invalid; + } + if ( ( trueZ == 0x7FFFFFFF ) + && ( ( testZ == 0x7FFFFFFF ) + || ( testZ == (sbits32) 0x80000000 ) ) + && ( trueFlags == float_flag_invalid ) + && ( testFlags == float_flag_invalid ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_float64(); + fputs( " ", stdout ); + writeOutputs_z_int32( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +#ifdef BITS64 + +void + test_a_float64_z_int64( + int64 trueFunction( float64 ), int64 testFunction( float64 ) ) +{ + int16 count; + int64 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_float64 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_float64 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_float64 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ( trueZ != testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && float64_is_signaling_nan( testCases_a_float64 ) ) { + trueFlags |= float_flag_invalid; + } + if ( ( trueZ == LIT64( 0x7FFFFFFFFFFFFFFF ) ) + && ( ( testZ == LIT64( 0x7FFFFFFFFFFFFFFF ) ) + || ( testZ == (sbits64) LIT64( 0x8000000000000000 ) ) ) + && ( trueFlags == float_flag_invalid ) + && ( testFlags == float_flag_invalid ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_float64(); + fputs( " ", stdout ); + writeOutputs_z_int64( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +#endif + +void + test_a_float64_z_float32( + float32 trueFunction( float64 ), float32 testFunction( float64 ) ) +{ + int16 count; + float32 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_float64 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_float64 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_float64 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ( trueZ != testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && float64_is_signaling_nan( testCases_a_float64 ) ) { + trueFlags |= float_flag_invalid; + } + if ( ! checkNaNs + && float32_isNaN( trueZ ) + && float32_isNaN( testZ ) + && ! float32_is_signaling_nan( testZ ) + && ( trueFlags == testFlags ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_float64(); + fputs( " ", stdout ); + writeOutputs_z_float32( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +#ifdef FLOATX80 + +void + test_a_float64_z_floatx80( + floatx80 trueFunction( float64 ), floatx80 testFunction( float64 ) ) +{ + int16 count; + floatx80 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_float64 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_float64 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_float64 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ! floatx80_same( trueZ, testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && float64_is_signaling_nan( testCases_a_float64 ) ) { + trueFlags |= float_flag_invalid; + } + if ( ! checkNaNs + && floatx80_isNaN( trueZ ) + && floatx80_isNaN( testZ ) + && ! floatx80_is_signaling_nan( testZ ) + && ( trueFlags == testFlags ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_float64(); + fputs( "\n\t", stdout ); + writeOutputs_z_floatx80( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +#endif + +#ifdef FLOAT128 + +void + test_a_float64_z_float128( + float128 trueFunction( float64 ), float128 testFunction( float64 ) ) +{ + int16 count; + float128 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_float64 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_float64 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_float64 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ! float128_same( trueZ, testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && float64_is_signaling_nan( testCases_a_float64 ) ) { + trueFlags |= float_flag_invalid; + } + if ( ! checkNaNs + && float128_isNaN( trueZ ) + && float128_isNaN( testZ ) + && ! float128_is_signaling_nan( testZ ) + && ( trueFlags == testFlags ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_float64(); + fputs( "\n\t", stdout ); + writeOutputs_z_float128( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +#endif + +void + test_az_float64( + float64 trueFunction( float64 ), float64 testFunction( float64 ) ) +{ + int16 count; + float64 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_float64 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_float64 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_float64 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ! float64_same( trueZ, testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && float64_is_signaling_nan( testCases_a_float64 ) ) { + trueFlags |= float_flag_invalid; + } + if ( ! checkNaNs + && float64_isNaN( trueZ ) + && float64_isNaN( testZ ) + && ! float64_is_signaling_nan( testZ ) + && ( trueFlags == testFlags ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_float64(); + fputs( " ", stdout ); + writeOutputs_z_float64( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +void + test_ab_float64_z_flag( + flag trueFunction( float64, float64 ), + flag testFunction( float64, float64 ) + ) +{ + int16 count; + flag trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_ab_float64 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_float64, testCases_b_float64 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_float64, testCases_b_float64 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ( trueZ != testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && ( float64_is_signaling_nan( testCases_a_float64 ) + || float64_is_signaling_nan( testCases_b_float64 ) ) + ) { + trueFlags |= float_flag_invalid; + } + if ( ( trueZ != testZ ) || ( trueFlags != testFlags ) ) { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInputs_ab_float64(); + fputs( " ", stdout ); + writeOutputs_z_flag( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + return; + +} + +void + test_abz_float64( + float64 trueFunction( float64, float64 ), + float64 testFunction( float64, float64 ) + ) +{ + int16 count; + float64 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_ab_float64 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_float64, testCases_b_float64 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_float64, testCases_b_float64 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ! float64_same( trueZ, testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && ( float64_is_signaling_nan( testCases_a_float64 ) + || float64_is_signaling_nan( testCases_b_float64 ) ) + ) { + trueFlags |= float_flag_invalid; + } + if ( ! checkNaNs + && float64_isNaN( trueZ ) + && float64_isNaN( testZ ) + && ! float64_is_signaling_nan( testZ ) + && ( trueFlags == testFlags ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInputs_ab_float64(); + fputs( "\n\t", stdout ); + writeOutputs_z_float64( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + return; + +} + +#ifdef FLOATX80 + +void + test_a_floatx80_z_int32( + int32 trueFunction( floatx80 ), int32 testFunction( floatx80 ) ) +{ + int16 count; + int32 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_floatx80 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_floatx80 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_floatx80 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ( trueZ != testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && floatx80_is_signaling_nan( testCases_a_floatx80 ) ) { + trueFlags |= float_flag_invalid; + } + if ( ( trueZ == 0x7FFFFFFF ) + && ( ( testZ == 0x7FFFFFFF ) + || ( testZ == (sbits32) 0x80000000 ) ) + && ( trueFlags == float_flag_invalid ) + && ( testFlags == float_flag_invalid ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_floatx80(); + fputs( " ", stdout ); + writeOutputs_z_int32( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +#ifdef BITS64 + +void + test_a_floatx80_z_int64( + int64 trueFunction( floatx80 ), int64 testFunction( floatx80 ) ) +{ + int16 count; + int64 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_floatx80 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_floatx80 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_floatx80 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ( trueZ != testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && floatx80_is_signaling_nan( testCases_a_floatx80 ) ) { + trueFlags |= float_flag_invalid; + } + if ( ( trueZ == LIT64( 0x7FFFFFFFFFFFFFFF ) ) + && ( ( testZ == LIT64( 0x7FFFFFFFFFFFFFFF ) ) + || ( testZ == (sbits64) LIT64( 0x8000000000000000 ) ) ) + && ( trueFlags == float_flag_invalid ) + && ( testFlags == float_flag_invalid ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_floatx80(); + fputs( " ", stdout ); + writeOutputs_z_int64( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +#endif + +void + test_a_floatx80_z_float32( + float32 trueFunction( floatx80 ), float32 testFunction( floatx80 ) ) +{ + int16 count; + float32 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_floatx80 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_floatx80 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_floatx80 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ( trueZ != testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && floatx80_is_signaling_nan( testCases_a_floatx80 ) ) { + trueFlags |= float_flag_invalid; + } + if ( ! checkNaNs + && float32_isNaN( trueZ ) + && float32_isNaN( testZ ) + && ! float32_is_signaling_nan( testZ ) + && ( trueFlags == testFlags ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_floatx80(); + fputs( " ", stdout ); + writeOutputs_z_float32( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +void + test_a_floatx80_z_float64( + float64 trueFunction( floatx80 ), float64 testFunction( floatx80 ) ) +{ + int16 count; + float64 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_floatx80 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_floatx80 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_floatx80 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ! float64_same( trueZ, testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && floatx80_is_signaling_nan( testCases_a_floatx80 ) ) { + trueFlags |= float_flag_invalid; + } + if ( ! checkNaNs + && float64_isNaN( trueZ ) + && float64_isNaN( testZ ) + && ! float64_is_signaling_nan( testZ ) + && ( trueFlags == testFlags ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_floatx80(); + fputs( "\n\t", stdout ); + writeOutputs_z_float64( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +#ifdef FLOAT128 + +void + test_a_floatx80_z_float128( + float128 trueFunction( floatx80 ), float128 testFunction( floatx80 ) ) +{ + int16 count; + float128 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_floatx80 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_floatx80 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_floatx80 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ! float128_same( trueZ, testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && floatx80_is_signaling_nan( testCases_a_floatx80 ) ) { + trueFlags |= float_flag_invalid; + } + if ( ! checkNaNs + && float128_isNaN( trueZ ) + && float128_isNaN( testZ ) + && ! float128_is_signaling_nan( testZ ) + && ( trueFlags == testFlags ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_floatx80(); + fputs( "\n\t", stdout ); + writeOutputs_z_float128( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +#endif + +void + test_az_floatx80( + floatx80 trueFunction( floatx80 ), floatx80 testFunction( floatx80 ) ) +{ + int16 count; + floatx80 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_floatx80 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_floatx80 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_floatx80 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ! floatx80_same( trueZ, testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && floatx80_is_signaling_nan( testCases_a_floatx80 ) ) { + trueFlags |= float_flag_invalid; + } + if ( ! checkNaNs + && floatx80_isNaN( trueZ ) + && floatx80_isNaN( testZ ) + && ! floatx80_is_signaling_nan( testZ ) + && ( trueFlags == testFlags ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_floatx80(); + fputs( "\n\t", stdout ); + writeOutputs_z_floatx80( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +void + test_ab_floatx80_z_flag( + flag trueFunction( floatx80, floatx80 ), + flag testFunction( floatx80, floatx80 ) + ) +{ + int16 count; + flag trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_ab_floatx80 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_floatx80, testCases_b_floatx80 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_floatx80, testCases_b_floatx80 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ( trueZ != testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && ( floatx80_is_signaling_nan( testCases_a_floatx80 ) + || floatx80_is_signaling_nan( testCases_b_floatx80 ) ) + ) { + trueFlags |= float_flag_invalid; + } + if ( ( trueZ != testZ ) || ( trueFlags != testFlags ) ) { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInputs_ab_floatx80(); + fputs( " ", stdout ); + writeOutputs_z_flag( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + return; + +} + +void + test_abz_floatx80( + floatx80 trueFunction( floatx80, floatx80 ), + floatx80 testFunction( floatx80, floatx80 ) + ) +{ + int16 count; + floatx80 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_ab_floatx80 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_floatx80, testCases_b_floatx80 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_floatx80, testCases_b_floatx80 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ! floatx80_same( trueZ, testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && ( floatx80_is_signaling_nan( testCases_a_floatx80 ) + || floatx80_is_signaling_nan( testCases_b_floatx80 ) ) + ) { + trueFlags |= float_flag_invalid; + } + if ( ! checkNaNs + && floatx80_isNaN( trueZ ) + && floatx80_isNaN( testZ ) + && ! floatx80_is_signaling_nan( testZ ) + && ( trueFlags == testFlags ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInputs_ab_floatx80(); + fputs( "\n\t", stdout ); + writeOutputs_z_floatx80( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + return; + +} + +#endif + +#ifdef FLOAT128 + +void + test_a_float128_z_int32( + int32 trueFunction( float128 ), int32 testFunction( float128 ) ) +{ + int16 count; + int32 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_float128 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_float128 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_float128 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ( trueZ != testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && float128_is_signaling_nan( testCases_a_float128 ) ) { + trueFlags |= float_flag_invalid; + } + if ( ( trueZ == 0x7FFFFFFF ) + && ( ( testZ == 0x7FFFFFFF ) + || ( testZ == (sbits32) 0x80000000 ) ) + && ( trueFlags == float_flag_invalid ) + && ( testFlags == float_flag_invalid ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_float128(); + fputs( " ", stdout ); + writeOutputs_z_int32( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +#ifdef BITS64 + +void + test_a_float128_z_int64( + int64 trueFunction( float128 ), int64 testFunction( float128 ) ) +{ + int16 count; + int64 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_float128 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_float128 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_float128 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ( trueZ != testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && float128_is_signaling_nan( testCases_a_float128 ) ) { + trueFlags |= float_flag_invalid; + } + if ( ( trueZ == LIT64( 0x7FFFFFFFFFFFFFFF ) ) + && ( ( testZ == LIT64( 0x7FFFFFFFFFFFFFFF ) ) + || ( testZ == (sbits64) LIT64( 0x8000000000000000 ) ) ) + && ( trueFlags == float_flag_invalid ) + && ( testFlags == float_flag_invalid ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_float128(); + fputs( "\n\t", stdout ); + writeOutputs_z_int64( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +#endif + +void + test_a_float128_z_float32( + float32 trueFunction( float128 ), float32 testFunction( float128 ) ) +{ + int16 count; + float32 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_float128 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_float128 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_float128 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ( trueZ != testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && float128_is_signaling_nan( testCases_a_float128 ) ) { + trueFlags |= float_flag_invalid; + } + if ( ! checkNaNs + && float32_isNaN( trueZ ) + && float32_isNaN( testZ ) + && ! float32_is_signaling_nan( testZ ) + && ( trueFlags == testFlags ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_float128(); + fputs( " ", stdout ); + writeOutputs_z_float32( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +void + test_a_float128_z_float64( + float64 trueFunction( float128 ), float64 testFunction( float128 ) ) +{ + int16 count; + float64 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_float128 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_float128 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_float128 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ! float64_same( trueZ, testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && float128_is_signaling_nan( testCases_a_float128 ) ) { + trueFlags |= float_flag_invalid; + } + if ( ! checkNaNs + && float64_isNaN( trueZ ) + && float64_isNaN( testZ ) + && ! float64_is_signaling_nan( testZ ) + && ( trueFlags == testFlags ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_float128(); + fputs( "\n\t", stdout ); + writeOutputs_z_float64( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +#ifdef FLOATX80 + +void + test_a_float128_z_floatx80( + floatx80 trueFunction( float128 ), floatx80 testFunction( float128 ) ) +{ + int16 count; + floatx80 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_float128 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_float128 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_float128 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ! floatx80_same( trueZ, testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && float128_is_signaling_nan( testCases_a_float128 ) ) { + trueFlags |= float_flag_invalid; + } + if ( ! checkNaNs + && floatx80_isNaN( trueZ ) + && floatx80_isNaN( testZ ) + && ! floatx80_is_signaling_nan( testZ ) + && ( trueFlags == testFlags ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_float128(); + fputs( "\n\t", stdout ); + writeOutputs_z_floatx80( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +#endif + +void + test_az_float128( + float128 trueFunction( float128 ), float128 testFunction( float128 ) ) +{ + int16 count; + float128 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_a_float128 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_float128 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_float128 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ! float128_same( trueZ, testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && float128_is_signaling_nan( testCases_a_float128 ) ) { + trueFlags |= float_flag_invalid; + } + if ( ! checkNaNs + && float128_isNaN( trueZ ) + && float128_isNaN( testZ ) + && ! float128_is_signaling_nan( testZ ) + && ( trueFlags == testFlags ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInput_a_float128(); + fputs( "\n\t", stdout ); + writeOutputs_z_float128( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + +} + +void + test_ab_float128_z_flag( + flag trueFunction( float128, float128 ), + flag testFunction( float128, float128 ) + ) +{ + int16 count; + flag trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_ab_float128 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_float128, testCases_b_float128 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_float128, testCases_b_float128 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ( trueZ != testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && ( float128_is_signaling_nan( testCases_a_float128 ) + || float128_is_signaling_nan( testCases_b_float128 ) ) + ) { + trueFlags |= float_flag_invalid; + } + if ( ( trueZ != testZ ) || ( trueFlags != testFlags ) ) { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInputs_ab_float128(); + fputs( "\n\t", stdout ); + writeOutputs_z_flag( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + return; + +} + +void + test_abz_float128( + float128 trueFunction( float128, float128 ), + float128 testFunction( float128, float128 ) + ) +{ + int16 count; + float128 trueZ, testZ; + uint8 trueFlags, testFlags; + + errorCount = 0; + tenthousandsCount = 0; + count = 10000; + testCases_initSequence( testCases_sequence_ab_float128 ); + writeTestsTotal(); + while ( ! testCases_done || forever ) { + testCases_next(); + *trueFlagsPtr = 0; + trueZ = trueFunction( testCases_a_float128, testCases_b_float128 ); + trueFlags = *trueFlagsPtr; + (void) testFlagsFunctionPtr(); + testZ = testFunction( testCases_a_float128, testCases_b_float128 ); + testFlags = testFlagsFunctionPtr(); + --count; + if ( count == 0 ) { + checkEarlyExit(); + count = 10000; + } + if ( ! float128_same( trueZ, testZ ) || ( trueFlags != testFlags ) ) { + if ( ! checkNaNs + && ( float128_is_signaling_nan( testCases_a_float128 ) + || float128_is_signaling_nan( testCases_b_float128 ) ) + ) { + trueFlags |= float_flag_invalid; + } + if ( ! checkNaNs + && float128_isNaN( trueZ ) + && float128_isNaN( testZ ) + && ! float128_is_signaling_nan( testZ ) + && ( trueFlags == testFlags ) + ) { + /* no problem */ + } + else { + ++errorCount; + writeErrorFound( 10000 - count ); + writeInputs_ab_float128(); + fputs( "\n\t", stdout ); + writeOutputs_z_float128( trueZ, trueFlags, testZ, testFlags ); + fflush( stdout ); + if ( errorCount == maxErrorCount ) goto exit; + } + } + } + exit: + writeTestsPerformed( 10000 - count ); + return; + +} + +#endif + diff --git a/tools/test/testfloat/testLoops.h b/tools/test/testfloat/testLoops.h new file mode 100644 index 0000000..c3b0847 --- /dev/null +++ b/tools/test/testfloat/testLoops.h @@ -0,0 +1,143 @@ + +/* +=============================================================================== + +This C header file is part of TestFloat, Release 2a, a package of programs +for testing the correctness of floating-point arithmetic complying to the +IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +#include <stdio.h> + +extern volatile flag stop; + +extern char *trueName, *testName; +extern flag forever, errorStop; +extern uint32 maxErrorCount; +extern flag checkNaNs; +extern int8 *trueFlagsPtr; +extern int8 ( *testFlagsFunctionPtr )( void ); +extern char *functionName; +extern char *roundingPrecisionName, *roundingModeName, *tininessModeName; +extern flag anyErrors; + +void writeFunctionName( FILE * ); +void exitWithStatus( void ); + +void test_a_int32_z_float32( float32 ( int32 ), float32 ( int32 ) ); +void test_a_int32_z_float64( float64 ( int32 ), float64 ( int32 ) ); +#ifdef FLOATX80 +void test_a_int32_z_floatx80( floatx80 ( int32 ), floatx80 ( int32 ) ); +#endif +#ifdef FLOAT128 +void test_a_int32_z_float128( float128 ( int32 ), float128 ( int32 ) ); +#endif +#ifdef BITS64 +void test_a_int64_z_float32( float32 ( int64 ), float32 ( int64 ) ); +void test_a_int64_z_float64( float64 ( int64 ), float64 ( int64 ) ); +#ifdef FLOATX80 +void test_a_int64_z_floatx80( floatx80 ( int64 ), floatx80 ( int64 ) ); +#endif +#ifdef FLOAT128 +void test_a_int64_z_float128( float128 ( int64 ), float128 ( int64 ) ); +#endif +#endif + +void test_a_float32_z_int32( int32 ( float32 ), int32 ( float32 ) ); +#ifdef BITS64 +void test_a_float32_z_int64( int64 ( float32 ), int64 ( float32 ) ); +#endif +void test_a_float32_z_float64( float64 ( float32 ), float64 ( float32 ) ); +#ifdef FLOATX80 +void test_a_float32_z_floatx80( floatx80 ( float32 ), floatx80 ( float32 ) ); +#endif +#ifdef FLOAT128 +void test_a_float32_z_float128( float128 ( float32 ), float128 ( float32 ) ); +#endif +void test_az_float32( float32 ( float32 ), float32 ( float32 ) ); +void + test_ab_float32_z_flag( + flag ( float32, float32 ), flag ( float32, float32 ) ); +void + test_abz_float32( + float32 ( float32, float32 ), float32 ( float32, float32 ) ); + +void test_a_float64_z_int32( int32 ( float64 ), int32 ( float64 ) ); +#ifdef BITS64 +void test_a_float64_z_int64( int64 ( float64 ), int64 ( float64 ) ); +#endif +void test_a_float64_z_float32( float32 ( float64 ), float32 ( float64 ) ); +#ifdef FLOATX80 +void test_a_float64_z_floatx80( floatx80 ( float64 ), floatx80 ( float64 ) ); +#endif +#ifdef FLOAT128 +void test_a_float64_z_float128( float128 ( float64 ), float128 ( float64 ) ); +#endif +void test_az_float64( float64 ( float64 ), float64 ( float64 ) ); +void + test_ab_float64_z_flag( + flag ( float64, float64 ), flag ( float64, float64 ) ); +void + test_abz_float64( + float64 ( float64, float64 ), float64 ( float64, float64 ) ); + +#ifdef FLOATX80 + +void test_a_floatx80_z_int32( int32 ( floatx80 ), int32 ( floatx80 ) ); +#ifdef BITS64 +void test_a_floatx80_z_int64( int64 ( floatx80 ), int64 ( floatx80 ) ); +#endif +void test_a_floatx80_z_float32( float32 ( floatx80 ), float32 ( floatx80 ) ); +void test_a_floatx80_z_float64( float64 ( floatx80 ), float64 ( floatx80 ) ); +#ifdef FLOAT128 +void + test_a_floatx80_z_float128( float128 ( floatx80 ), float128 ( floatx80 ) ); +#endif +void test_az_floatx80( floatx80 ( floatx80 ), floatx80 ( floatx80 ) ); +void + test_ab_floatx80_z_flag( + flag ( floatx80, floatx80 ), flag ( floatx80, floatx80 ) ); +void + test_abz_floatx80( + floatx80 ( floatx80, floatx80 ), floatx80 ( floatx80, floatx80 ) ); + +#endif + +#ifdef FLOAT128 + +void test_a_float128_z_int32( int32 ( float128 ), int32 ( float128 ) ); +#ifdef BITS64 +void test_a_float128_z_int64( int64 ( float128 ), int64 ( float128 ) ); +#endif +void test_a_float128_z_float32( float32 ( float128 ), float32 ( float128 ) ); +void test_a_float128_z_float64( float64 ( float128 ), float64 ( float128 ) ); +#ifdef FLOATX80 +void + test_a_float128_z_floatx80( floatx80 ( float128 ), floatx80 ( float128 ) ); +#endif +void test_az_float128( float128 ( float128 ), float128 ( float128 ) ); +void + test_ab_float128_z_flag( + flag ( float128, float128 ), flag ( float128, float128 ) ); +void + test_abz_float128( + float128 ( float128, float128 ), float128 ( float128, float128 ) ); + +#endif + diff --git a/tools/test/testfloat/testfloat-history.txt b/tools/test/testfloat/testfloat-history.txt new file mode 100644 index 0000000..61520b3 --- /dev/null +++ b/tools/test/testfloat/testfloat-history.txt @@ -0,0 +1,57 @@ + +History of Major Changes to TestFloat, up to Release 2a + +John R. Hauser +1998 December 17 + + +The TestFloat releases parallel those of SoftFloat, on which TestFloat is +based. Each TestFloat release also incorporates all bug fixes from the +corresponding release of SoftFloat. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Release 2a (1998 December) + +-- Added support for testing conversions between floating-point and 64-bit + integers. + +-- Improved the makefiles. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Release 2 (1997 June) + +-- Integrated the generation of test cases and the checking of system + results into a single program. (Before they were separate programs, + normally joined by explicit command-line pipes.) + +-- Improved the sequence of test cases. + +-- Added support for testing extended double precision and quadruple + precision. + +-- Made program output more readable, and added new command arguments. + +-- Reduced dependence on the quality of the standard `random' function for + generating test cases. (Previously naively expected `random' to be able + to generate good random bits for the entire machine word width.) + +-- Created `testsoftfloat', with its own simpler complete software floating- + point (``slowfloat'') for comparison purposes. + +-- Made some changes to the source file structure, including renaming + `environment.h' to `milieu.h' (to avoid confusion with environment + variables). + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Release 1a (1996 July) + +-- Added the `-tininessbefore' and `-tininessafter' options to control + whether tininess should be detected before or after rounding. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Release 1 (1996 July) + +-- Original release. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/tools/test/testfloat/testfloat-source.txt b/tools/test/testfloat/testfloat-source.txt new file mode 100644 index 0000000..b8f7e9b --- /dev/null +++ b/tools/test/testfloat/testfloat-source.txt @@ -0,0 +1,444 @@ + +TestFloat Release 2a Source Documentation + +John R. Hauser +1998 December 16 + + +------------------------------------------------------------------------------- +Introduction + +TestFloat is a program for testing that a floating-point implementation +conforms to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +All standard operations supported by the system can be tested, except for +conversions to and from decimal. Any of the following machine formats can +be tested: single precision, double precision, extended double precision, +and/or quadruple precision. Testing extended double-precision or quadruple- +precision formats requires a C compiler that supports 64-bit integer +arithmetic. + +This document gives information needed for compiling and/or porting +TestFloat. + +The source code for TestFloat is intended to be relatively machine- +independent. TestFloat is written in C, and should be compilable using +any ISO/ANSI C compiler. At the time of this writing, the program has +been successfully compiled using the GNU C Compiler (`gcc') for several +platforms. Because ISO/ANSI C does not provide access to some features +of IEC/IEEE floating-point such as the exception flags, porting TestFloat +unfortunately involves some machine-dependent coding. + +TestFloat depends on SoftFloat, which is a software implementation of +floating-point that conforms to the IEC/IEEE Standard. SoftFloat is not +included with the TestFloat sources. It can be obtained from the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/SoftFloat.html'. + +In addition to a program for testing a machine's floating-point, the +TestFloat package includes a variant for testing SoftFloat called +`testsoftfloat'. The sources for both programs are intermixed, and both are +described here. + +The first release of TestFloat (Release 1) was called _FloatTest_. The old +name has been obsolete for some time. + + +------------------------------------------------------------------------------- +Limitations + +TestFloat as written requires an ISO/ANSI-style C compiler. No attempt has +been made to accomodate compilers that are not ISO-conformant. Older ``K&R- +style'' compilers are not adequate for compiling TestFloat. All testing I +have done so far has been with the GNU C Compiler. Compilation with other +compilers should be possible but has not been tested. + +The TestFloat sources assume that source code file names can be longer than +8 characters. In order to compile under an MS-DOS-style system, many of the +source files will need to be renamed, and the source and makefiles edited +appropriately. Once compiled, the TestFloat program does not depend on the +existence of long file names. + +The underlying machine is assumed to be binary with a word size that is a +power of 2. Bytes are 8 bits. Testing of extended double-precision and +quadruple-precision formats depends on the C compiler implementing a 64-bit +integer type. If the largest integer type supported by the C compiler is +32 bits, only single- and double-precision operations can be tested. + + +------------------------------------------------------------------------------- +Contents + + Introduction + Limitations + Contents + Legal Notice + TestFloat Source Directory Structure + Target-Independent Modules + Target-Specific Modules + Target-Specific Header Files + processors/*.h + testfloat/*/milieu.h + Target-Specific Floating-Point Subroutines + Steps to Creating the TestFloat Executables + Improving the Random Number Generator + Contact Information + + + +------------------------------------------------------------------------------- +Legal Notice + +TestFloat was written by John R. Hauser. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + + +------------------------------------------------------------------------------- +TestFloat Source Directory Structure + +Because TestFloat is targeted to multiple platforms, its source code +is slightly scattered between target-specific and target-independent +directories and files. The directory structure is as follows: + + processors + testfloat + templates + 386-Win32-gcc + SPARC-Solaris-gcc + +The two topmost directories and their contents are: + + testfloat - Most of the source code needed for TestFloat. + processors - Target-specific header files that are not specific to + TestFloat. + +Within the `testfloat' directory are subdirectories for each of the +targeted platforms. The TestFloat source code is distributed with targets +`386-Win32-gcc' and `SPARC-Solaris-gcc' (and perhaps others) already +prepared. These can be used as examples for porting to new targets. Source +files that are not within these target-specific subdirectories are intended +to be target-independent. + +The naming convention used for the target-specific directories is +`<processor>-<executable-type>-<compiler>'. The names of the supplied +target directories should be interpreted as follows: + + <processor>: + 386 - Intel 386-compatible processor. + SPARC - SPARC processor (as used by Sun machines). + <executable-type>: + Win32 - Microsoft Win32 executable. + Solaris - Sun Solaris executable. + <compiler>: + gcc - GNU C Compiler. + +You do not need to maintain this convention if you do not want to. + +Alongside the supplied target-specific directories there is a `templates' +directory containing a set of ``generic'' target-specific source files. +A new target directory can be created by copying the `templates' directory +and editing the files inside. (Complete instructions for porting TestFloat +to a new target are in the section _Steps_to_Creating_the_TestFloat_ +_Executables_.) Note that the `templates' directory will not work as a +target directory without some editing. To avoid confusion, it would be wise +to refrain from editing the files inside `templates' directly. + +In addition to the distributed sources, TestFloat depends on the existence +of an appropriately-compiled SoftFloat binary and the corresponding header +file `softfloat.h'. SoftFloat is not included with the TestFloat sources. +It can be obtained from the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ +arithmetic/SoftFloat.html'. + +As distributed, the makefiles for TestFloat assume the existence of three +sibling directories: + + processors + softfloat + testfloat + +Only the `processors' and `testfloat' directories are included in the +TestFloat package. The `softfloat' directory is assumed to contain a +target-specific subdirectory within which the SoftFloat header file and +compiled binary can be found. (See the source documentation accompanying +SoftFloat.) The `processors' directory distributed with TestFloat is +intended to be identical to that included with the SoftFloat source. + +These are the defaults, but other organizations of the sources are possible. +The TestFloat makefiles and `milieu.h' files (see below) are easily edited +to accomodate other arrangements. + + +------------------------------------------------------------------------------- +Target-Independent Modules + +The TestFloat program is composed of a number of modules, some target- +specific and some target-independent. The target-independent modules are as +follows: + +-- The `fail' module provides a common routine for writing an error message + and aborting. + +-- The `random' module generates random integer values. + +-- The `writeHex' module defines routines for writing the various types in + the hexadecimal form used by TestFloat. + +-- The `testCases' module generates test cases for the various types. + +-- The `testLoops' module contains various routines for exercising two + implementations of a function and reporting any differences observed. + +-- The `slowfloat' module provides the simple floating-point implementation + used by `testsoftfloat' for comparing against SoftFloat. The heart + of `slowfloat' is found in either `slowfloat-32' or `slowfloat-64', + depending on whether the `BITS64' macro is defined. + +-- The `systfloat' module gives a SoftFloat-like interface to the machine's + floating-point. + +-- The `testFunction' module implements `testfloat's main loop for testing a + function for all of the relevant rounding modes and rounding precisions. + (The `testsoftfloat' program contains its own version of this code.) + +-- The `testfloat' and `testsoftfloat' modules are the main modules for the + `testfloat' and `testsoftfloat' programs. + +Except possibly for `systfloat', these modules should not need to be +modified. + +The `systfloat' module uses the floating-point operations of the C language +to access a machine's floating-point. Unfortunately, some IEC/IEEE +floating-point operations are not accessible within ISO/ANSI C. The +following machine functions cannot be tested unless an alternate `systfloat' +module is provided: + + <float>_to_int32 (rounded according to rounding mode) + <float>_to_int64 (rounded according to rounding mode) + <float>_round_to_int + <float>_rem + <float>_sqrt, except float64_sqrt + <float>_eq_signaling + <float>_le_quiet + <float>_lt_quiet + +The `-list' option to `testfloat' will show the operations the program is +prepared to test. The section _Target-Specific_Floating-Point_Subroutines_ +later in this document explains how to create a target-specific `systfloat' +module to change the set of testable functions. + + +------------------------------------------------------------------------------- +Target-Specific Modules + +No target-specific modules are needed for `testsoftfloat'. + +The `testfloat' program uses two target-specific modules: + +-- The `systmodes' module defines functions for setting the modes + controlling the system's floating-point, including the rounding mode and + the rounding precision for extended double precision. + +-- The `systflags' module provides a function for clearing and examining the + system's floating-point exception flags. + +These modules must be supplied for each target. They can be implemented in +any way desired, so long as all is reflected in the target's makefile. For +the targets that come with the distributed source, each of these modules is +implemented as a single assembly language or C language source file. + + +------------------------------------------------------------------------------- +Target-Specific Header Files + +The purpose of the two target-specific header files is detailed below. +In the following, the `*' symbol is used in place of the name of a specific +target, such as `386-Win32-gcc' or `SPARC-Solaris-gcc', or in place of some +other text as explained below. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +processors/*.h + +The target-specific `processors' header file defines integer types +of various sizes, and also defines certain C preprocessor macros that +characterize the target. The two examples supplied are `386-gcc.h' and +`SPARC-gcc.h'. The naming convention used for processor header files is +`<processor>-<compiler>.h'. The `processors' header file used to compile +TestFloat should be the same as that used to compile SoftFloat. + +If 64-bit integers are supported by the compiler, the macro name `BITS64' +should be defined here along with the corresponding 64-bit integer +types. In addition, the function-like macro `LIT64' must be defined for +constructing 64-bit integer literals (constants). The `LIT64' macro is used +consistently in the TestFloat code to annotate 64-bit literals. + +If an inlining attribute (such as an `inline' keyword) is provided by the +compiler, the macro `INLINE' should be defined to the appropriate keyword. +If not, `INLINE' can be set to the keyword `static'. The `INLINE' macro +appears in the TestFloat source code before every function that should be +inlined by the compiler. + +For maximum flexibility, the TestFloat source files do not include the +`processors' header file directly; rather, this file is included by the +target-specific `milieu.h' header, and `milieu.h' is included by the source +files. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +testfloat/*/milieu.h + +The `milieu.h' header file provides declarations that are needed to +compile TestFloat. In particular, it is through this header file that +the appropriate `processors' header is included to characterize the target +processor. In addition, deviations from ISO/ANSI C by the compiler (such as +names not properly declared in system header files) are corrected in this +header if possible. + +If the preprocessor macro `BITS64' is defined in the `processors' header +file but only the 32-bit version of SoftFloat is actually used, the `BITS64' +macro should be undefined here after the `processors' header has defined it. + +If the C compiler implements the `long double' floating-point type of C +as extended double precision, then `LONG_DOUBLE_IS_FLOATX80' should be +defined here. Alternatively, if the C `long double' type is implemented as +quadruple precision, `LONG_DOUBLE_IS_FLOAT128' should be defined. At most +one of these macros should be defined. A C compiler is allowed to implement +`long double' the same as `double', in which case neither of these macros +should be defined. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + +------------------------------------------------------------------------------- +Target-Specific Floating-Point Subroutines + +This section applies only to `testfloat' and not to `testsoftfloat'. + +By default, TestFloat tests a machine's floating-point by testing the +floating-point operations of the C language. Unfortunately, some IEC/IEEE +floating-point operations are not defined within ISO/ANSI C. If a machine +implements such ``non-C'' operations, target-specific subroutines for +the operations can be supplied to allow TestFloat to test these machine +features. Typically, such subroutines will need to be written in assembly +language, although equivalent functions can sometimes be found among the +system's software libraries. + +The following machine functions cannot be tested by TestFloat unless target- +specific subroutines are supplied for them: + + <float>_to_int32 (rounded according to rounding mode) + <float>_to_int64 (rounded according to rounding mode) + <float>_round_to_int + <float>_rem + <float>_sqrt, except float64_sqrt + <float>_eq_signaling + <float>_le_quiet + <float>_lt_quiet + +In addition to these, none of the `floatx80' functions can be tested by +default if the C `long double' type is something other than extended double +precision; and likewise, none of the `float128' functions can be tested by +default if `long double' is not quadruple precision. Since `long double' +cannot be both extended double precision and quadruple precision at the +same time, at least one of these types cannot be tested by TestFloat without +appropriate subroutines being supplied for that type. (On the other hand, +few systems implement _both_ extended double-precision and quadruple- +precision floating-point; and unless a system does implement both, it does +not need both tested.) + +Note that the `-list' option to `testfloat' will show the operations +TestFloat is prepared to test. + +TestFloat's `systfloat' module supplies the system version of the functions +to be tested. The names of the `systfloat' subroutines are the same as the +function names used as arguments to the `testfloat' command but with `syst_' +prefixed--thus, for example, `syst_float32_add' and `syst_int32_to_float32'. +The default `systfloat' module maps these system functions to the standard +C operations; so `syst_float32_add', for example, is implemented using the +C `+' operation for the single-precision `float' type. For each system +function supplied by `systfloat', a corresponding `SYST_<function>' +preprocessor macro is defined in `systfloat.h' to indicate that the function +exists to be tested (e.g., `SYST_FLOAT32_ADD'). The `systfloat.h' header +file also declares function prototypes for the `systfloat' functions. + +(The `systfloat.h' file that comes with the TestFloat package declares +prototypes for all of the possible `systfloat' functions, whether defined in +`systfloat' or not. There is no penalty for declaring a function prototype +that is never used.) + +A target-specific version of the `systfloat' module can easily be created to +replace the generic one. This in fact has been done for the example targets +`386-Win32-gcc' and `SPARC-Solaris-gcc'. For each target, an assembly +language `systfloat.S' has been created in the target directory along with +a corresponding `systfloat.h' header file defining the `SYST_<function>' +macros for the functions implemented. The makefiles of the targets have +been edited to use these target-specific versions of `systfloat' rather than +the generic one. + +The `systfloat' modules of the example targets have been written entirely +in assembly language in order to bypass any peculiarities of the C compiler. +Although this is probably a good idea, it is certainly not required. + + +------------------------------------------------------------------------------- +Steps to Creating the TestFloat Executables + +Porting and/or compiling TestFloat involves the following steps: + +1. Port SoftFloat and create a SoftFloat binary. (Refer to the + documentation accompanying SoftFloat.) + +2. If one does not already exist, create an appropriate target-specific + subdirectory under `testfloat' by copying the given `templates' + directory. The remaining steps occur within the target-specific + subdirectory. + +3. Edit the files `milieu.h' and `Makefile' to reflect the current + environment. + +4. Make `testsoftfloat' by executing `make testsoftfloat' (or `make + testsoftfloat.exe', or whatever the `testsoftfloat' executable is + called). Verify that SoftFloat is working correctly by testing it with + `testsoftfloat'. + +If you only wanted `testsoftfloat', you are done. The steps for `testfloat' +continue: + +5. In the target-specific subdirectory, implement the `systmodes' and + `systflags' modules. (The `syst_float_set_rounding_precision' function + need not do anything if the system does not support extended double + precision.) + +6. If the target machine supports standard floating-point functions that are + not accessible within ISO/ANSI C, or if the C compiler cannot be trusted + to use the machine's floating-point directly, create a target-specific + `systfloat' module. + +7. In the target-specific subdirectory, execute `make'. + + +------------------------------------------------------------------------------- +Improving the Random Number Generator + +If you are serious about using TestFloat for testing floating-point, you +should consider replacing the supplied `random.c' with a better target- +specific one. The standard C `rand' function is rather poor on some +systems, and consequently `random.c' has been written to assume very little +about the quality of `rand'. As a result, the `rand' function is called +more frequently than it might need to be, shortening the time before +the random number generator repeats, and possibly wasting time as well. +If `rand' is better on your system, or if another better random number +generator is available (such as `rand48' on most Unix systems), TestFloat +can be improved by overriding the given `random.c' with a target-specific +one. + + +------------------------------------------------------------------------------- +Contact Information + +At the time of this writing, the most up-to-date information about +TestFloat and the latest release can be found at the Web page `http:// +HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + + diff --git a/tools/test/testfloat/testfloat.c b/tools/test/testfloat/testfloat.c new file mode 100644 index 0000000..5a19d88 --- /dev/null +++ b/tools/test/testfloat/testfloat.c @@ -0,0 +1,299 @@ + +/* +=============================================================================== + +This C source file is part of TestFloat, Release 2a, a package of programs +for testing the correctness of floating-point arithmetic complying to the +IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stdlib.h> +#include <signal.h> +#include <string.h> +#include "milieu.h" +#include "fail.h" +#include "softfloat.h" +#include "testCases.h" +#include "testLoops.h" +#include "systflags.h" +#include "testFunction.h" + +static void catchSIGINT( int signalCode ) +{ + + if ( stop ) exit( EXIT_FAILURE ); + stop = TRUE; + +} + +int +main( int argc, char **argv ) +{ + char *argPtr; + flag functionArgument; + uint8 functionCode; + int8 operands, roundingPrecision, roundingMode; + + fail_programName = "testfloat"; + if ( argc <= 1 ) goto writeHelpMessage; + testCases_setLevel( 1 ); + trueName = "soft"; + testName = "syst"; + errorStop = FALSE; + forever = FALSE; + maxErrorCount = 20; + trueFlagsPtr = &float_exception_flags; + testFlagsFunctionPtr = syst_float_flags_clear; + tininessModeName = 0; + functionArgument = FALSE; + functionCode = 0; + operands = 0; + roundingPrecision = 0; + roundingMode = 0; + --argc; + ++argv; + while ( argc && ( argPtr = argv[ 0 ] ) ) { + if ( argPtr[ 0 ] == '-' ) ++argPtr; + if ( strcmp( argPtr, "help" ) == 0 ) { + writeHelpMessage: + fputs( +"testfloat [<option>...] <function>\n" +" <option>: (* is default)\n" +" -help --Write this message and exit.\n" +" -list --List all testable functions and exit.\n" +" -level <num> --Testing level <num> (1 or 2).\n" +" * -level 1\n" +" -errors <num> --Stop each function test after <num> errors.\n" +" * -errors 20\n" +" -errorstop --Exit after first function with any error.\n" +" -forever --Test one function repeatedly (implies `-level 2').\n" +" -checkNaNs --Check for bitwise correctness of NaN results.\n" +#ifdef FLOATX80 +" -precision32 --Only test rounding precision equivalent to float32.\n" +" -precision64 --Only test rounding precision equivalent to float64.\n" +" -precision80 --Only test maximum rounding precision.\n" +#endif +" -nearesteven --Only test rounding to nearest/even.\n" +" -tozero --Only test rounding to zero.\n" +" -down --Only test rounding down.\n" +" -up --Only test rounding up.\n" +" -tininessbefore --Underflow tininess detected before rounding.\n" +" -tininessafter --Underflow tininess detected after rounding.\n" +" <function>:\n" +" int32_to_<float> <float>_add <float>_eq\n" +" <float>_to_int32 <float>_sub <float>_le\n" +" <float>_to_int32_round_to_zero <float>_mul <float>_lt\n" +#ifdef BITS64 +" int64_to_<float> <float>_div <float>_eq_signaling\n" +" <float>_to_int64 <float>_rem <float>_le_quiet\n" +" <float>_to_int64_round_to_zero <float>_lt_quiet\n" +" <float>_to_<float>\n" +" <float>_round_to_int\n" +" <float>_sqrt\n" +#else +" <float>_to_<float> <float>_div <float>_eq_signaling\n" +" <float>_round_to_int <float>_rem <float>_le_quiet\n" +" <float>_sqrt <float>_lt_quiet\n" +#endif +" -all1 --All 1-operand functions.\n" +" -all2 --All 2-operand functions.\n" +" -all --All functions.\n" +" <float>:\n" +" float32 --Single precision.\n" +" float64 --Double precision.\n" +#ifdef FLOATX80 +" floatx80 --Extended double precision.\n" +#endif +#ifdef FLOAT128 +" float128 --Quadruple precision.\n" +#endif + , + stdout + ); + return EXIT_SUCCESS; + } + else if ( strcmp( argPtr, "list" ) == 0 ) { + for ( functionCode = 1; + functionCode < NUM_FUNCTIONS; + ++functionCode + ) { + if ( functionExists[ functionCode ] ) { + puts( functions[ functionCode ].name ); + } + } + return EXIT_SUCCESS; + } + else if ( strcmp( argPtr, "level" ) == 0 ) { + if ( argc < 2 ) goto optionError; + testCases_setLevel( atoi( argv[ 1 ] ) ); + --argc; + ++argv; + } + else if ( strcmp( argPtr, "level1" ) == 0 ) { + testCases_setLevel( 1 ); + } + else if ( strcmp( argPtr, "level2" ) == 0 ) { + testCases_setLevel( 2 ); + } + else if ( strcmp( argPtr, "errors" ) == 0 ) { + if ( argc < 2 ) { + optionError: + fail( "`%s' option requires numeric argument", argv[ 0 ] ); + } + maxErrorCount = atoi( argv[ 1 ] ); + --argc; + ++argv; + } + else if ( strcmp( argPtr, "errorstop" ) == 0 ) { + errorStop = TRUE; + } + else if ( strcmp( argPtr, "forever" ) == 0 ) { + testCases_setLevel( 2 ); + forever = TRUE; + } + else if ( ( strcmp( argPtr, "checkNaNs" ) == 0 ) + || ( strcmp( argPtr, "checknans" ) == 0 ) ) { + checkNaNs = TRUE; + } +#ifdef FLOATX80 + else if ( strcmp( argPtr, "precision32" ) == 0 ) { + roundingPrecision = 32; + } + else if ( strcmp( argPtr, "precision64" ) == 0 ) { + roundingPrecision = 64; + } + else if ( strcmp( argPtr, "precision80" ) == 0 ) { + roundingPrecision = 80; + } +#endif + else if ( ( strcmp( argPtr, "nearesteven" ) == 0 ) + || ( strcmp( argPtr, "nearest_even" ) == 0 ) ) { + roundingMode = ROUND_NEAREST_EVEN; + } + else if ( ( strcmp( argPtr, "tozero" ) == 0 ) + || ( strcmp( argPtr, "to_zero" ) == 0 ) ) { + roundingMode = ROUND_TO_ZERO; + } + else if ( strcmp( argPtr, "down" ) == 0 ) { + roundingMode = ROUND_DOWN; + } + else if ( strcmp( argPtr, "up" ) == 0 ) { + roundingMode = ROUND_UP; + } + else if ( strcmp( argPtr, "tininessbefore" ) == 0 ) { + float_detect_tininess = float_tininess_before_rounding; + } + else if ( strcmp( argPtr, "tininessafter" ) == 0 ) { + float_detect_tininess = float_tininess_after_rounding; + } + else if ( strcmp( argPtr, "all1" ) == 0 ) { + functionArgument = TRUE; + functionCode = 0; + operands = 1; + } + else if ( strcmp( argPtr, "all2" ) == 0 ) { + functionArgument = TRUE; + functionCode = 0; + operands = 2; + } + else if ( strcmp( argPtr, "all" ) == 0 ) { + functionArgument = TRUE; + functionCode = 0; + operands = 0; + } + else { + for ( functionCode = 1; + functionCode < NUM_FUNCTIONS; + ++functionCode + ) { + if ( strcmp( argPtr, functions[ functionCode ].name ) == 0 ) { + break; + } + } + if ( functionCode == NUM_FUNCTIONS ) { + fail( "Invalid option or function `%s'", argv[ 0 ] ); + } + if ( ! functionExists[ functionCode ] ) { + fail( + "Function `%s' is not supported or cannot be tested", + argPtr + ); + } + functionArgument = TRUE; + } + --argc; + ++argv; + } + if ( ! functionArgument ) fail( "Function argument required" ); + (void) signal( SIGINT, catchSIGINT ); + (void) signal( SIGTERM, catchSIGINT ); + if ( functionCode ) { + if ( forever ) { + if ( ! roundingPrecision ) roundingPrecision = 80; + if ( ! roundingMode ) roundingMode = ROUND_NEAREST_EVEN; + } + testFunction( functionCode, roundingPrecision, roundingMode ); + } + else { + if ( forever ) { + fail( "Can only test one function with `-forever' option" ); + } + if ( operands == 1 ) { + for ( functionCode = 1; + functionCode < NUM_FUNCTIONS; + ++functionCode + ) { + if ( functionExists[ functionCode ] + && ( functions[ functionCode ].numInputs == 1 ) ) { + testFunction( + functionCode, roundingPrecision, roundingMode ); + } + } + } + else if ( operands == 2 ) { + for ( functionCode = 1; + functionCode < NUM_FUNCTIONS; + ++functionCode + ) { + if ( functionExists[ functionCode ] + && ( functions[ functionCode ].numInputs == 2 ) ) { + testFunction( + functionCode, roundingPrecision, roundingMode ); + } + } + } + else { + for ( functionCode = 1; + functionCode < NUM_FUNCTIONS; + ++functionCode + ) { + if ( functionExists[ functionCode ] ) { + testFunction( + functionCode, roundingPrecision, roundingMode ); + } + } + } + } + exitWithStatus(); + +} + diff --git a/tools/test/testfloat/testfloat.txt b/tools/test/testfloat/testfloat.txt new file mode 100644 index 0000000..6e72c1d --- /dev/null +++ b/tools/test/testfloat/testfloat.txt @@ -0,0 +1,771 @@ + +TestFloat Release 2a General Documentation + +John R. Hauser +1998 December 16 + + +------------------------------------------------------------------------------- +Introduction + +TestFloat is a program for testing that a floating-point implementation +conforms to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +All standard operations supported by the system can be tested, except for +conversions to and from decimal. Any of the following machine formats can +be tested: single precision, double precision, extended double precision, +and/or quadruple precision. + +TestFloat actually comes in two variants: one is a program for testing +a machine's floating-point, and the other is a program for testing +the SoftFloat software implementation of floating-point. (Information +about SoftFloat can be found at the SoftFloat Web page, `http:// +HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/SoftFloat.html'.) The version that +tests SoftFloat is expected to be of interest only to people compiling the +SoftFloat sources. However, because the two versions share much in common, +they are discussed together in all the TestFloat documentation. + +This document explains how to use the TestFloat programs. It does not +attempt to define or explain the IEC/IEEE Standard for floating-point. +Details about the standard are available elsewhere. + +The first release of TestFloat (Release 1) was called _FloatTest_. The old +name has been obsolete for some time. + + +------------------------------------------------------------------------------- +Limitations + +TestFloat's output is not always easily interpreted. Detailed knowledge +of the IEC/IEEE Standard and its vagaries is needed to use TestFloat +responsibly. + +TestFloat performs relatively simple tests designed to check the fundamental +soundness of the floating-point under test. TestFloat may also at times +manage to find rarer and more subtle bugs, but it will probably only find +such bugs by accident. Software that purposefully seeks out various kinds +of subtle floating-point bugs can be found through links posted on the +TestFloat Web page (`http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/ +TestFloat.html'). + + +------------------------------------------------------------------------------- +Contents + + Introduction + Limitations + Contents + Legal Notice + What TestFloat Does + Executing TestFloat + Functions Tested by TestFloat + Conversion Functions + Standard Arithmetic Functions + Remainder and Round-to-Integer Functions + Comparison Functions + Interpreting TestFloat Output + Variations Allowed by the IEC/IEEE Standard + Underflow + NaNs + Conversions to Integer + TestFloat Options + -help + -list + -level <num> + -errors <num> + -errorstop + -forever + -checkNaNs + -precision32, -precision64, -precision80 + -nearesteven, -tozero, -down, -up + -tininessbefore, -tininessafter + Function Sets + Contact Information + + + +------------------------------------------------------------------------------- +Legal Notice + +TestFloat was written by John R. Hauser. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + + +------------------------------------------------------------------------------- +What TestFloat Does + +TestFloat tests a system's floating-point by comparing its behavior with +that of TestFloat's own internal floating-point implemented in software. +For each operation tested, TestFloat generates a large number of test cases, +made up of simple pattern tests intermixed with weighted random inputs. +The cases generated should be adequate for testing carry chain propagations, +plus the rounding of adds, subtracts, multiplies, and simple operations like +conversions. TestFloat makes a point of checking all boundary cases of the +arithmetic, including underflows, overflows, invalid operations, subnormal +inputs, zeros (positive and negative), infinities, and NaNs. For the +interesting operations like adds and multiplies, literally millions of test +cases can be checked. + +TestFloat is not remarkably good at testing difficult rounding cases for +divisions and square roots. It also makes no attempt to find bugs specific +to SRT divisions and the like (such as the infamous Pentium divide bug). +Software that tests for such failures can be found through links on the +TestFloat Web page, `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/ +TestFloat.html'. + +NOTE! +It is the responsibility of the user to verify that the discrepancies +TestFloat finds actually represent faults in the system being tested. +Advice to help with this task is provided later in this document. +Furthermore, even if TestFloat finds no fault with a floating-point +implementation, that in no way guarantees that the implementation is bug- +free. + +For each operation, TestFloat can test all four rounding modes required +by the IEC/IEEE Standard. TestFloat verifies not only that the numeric +results of an operation are correct, but also that the proper floating-point +exception flags are raised. All five exception flags are tested, including +the inexact flag. TestFloat does not attempt to verify that the floating- +point exception flags are actually implemented as sticky flags. + +For machines that implement extended double precision with rounding +precision control (such as Intel's 80x86), TestFloat can test the add, +subtract, multiply, divide, and square root functions at all the standard +rounding precisions. The rounding precision can be set equivalent to single +precision, to double precision, or to the full extended double precision. +Rounding precision control can only be applied to the extended double- +precision format and only for the five standard arithmetic operations: add, +subtract, multiply, divide, and square root. Other functions can be tested +only at full precision. + +As a rule, TestFloat is not particular about the bit patterns of NaNs that +appear as function results. Any NaN is considered as good a result as +another. This laxness can be overridden so that TestFloat checks for +particular bit patterns within NaN results. See the sections _Variations_ +_Allowed_by_the_IEC/IEEE_Standard_ and _TestFloat_Options_ for details. + +Not all IEC/IEEE Standard functions are supported by all machines. +TestFloat can only test functions that exist on the machine. But even if +a function is supported by the machine, TestFloat may still not be able +to test the function if it is not accessible through standard ISO C (the +programming language in which TestFloat is written) and if the person who +compiled TestFloat did not provide an alternate means for TestFloat to +invoke the machine function. + +TestFloat compares a machine's floating-point against the SoftFloat software +implementation of floating-point, also written by me. SoftFloat is built +into the TestFloat executable and does not need to be supplied by the user. +If SoftFloat is wanted for some other reason (to compile a new version +of TestFloat, for instance), it can be found separately at the Web page +`http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/SoftFloat.html'. + +For testing SoftFloat itself, the TestFloat package includes a program that +compares SoftFloat's floating-point against _another_ software floating- +point implementation. The second software floating-point is simpler and +slower than SoftFloat, and is completely independent of SoftFloat. Although +the second software floating-point cannot be guaranteed to be bug-free, the +chance that it would mimic any of SoftFloat's bugs is remote. Consequently, +an error in one or the other floating-point version should appear as an +unexpected discrepancy between the two implementations. Note that testing +SoftFloat should only be necessary when compiling a new TestFloat executable +or when compiling SoftFloat for some other reason. + + +------------------------------------------------------------------------------- +Executing TestFloat + +TestFloat is intended to be executed from a command line interpreter. The +`testfloat' program is invoked as follows: + + testfloat [<option>...] <function> + +Here square brackets ([]) indicate optional items, while angled brackets +(<>) denote parameters to be filled in. + +The `<function>' argument is a name like `float32_add' or `float64_to_int32'. +The complete list of function names is given in the next section, +_Functions_Tested_by_TestFloat_. It is also possible to test all machine +functions in a single invocation. The various options to TestFloat are +detailed in the section _TestFloat_Options_ later in this document. If +`testfloat' is executed without any arguments, a summary of TestFloat usage +is written. + +TestFloat will ordinarily test a function for all four rounding modes, one +after the other. If the rounding mode is not supposed to have any affect +on the results--for instance, some operations do not require rounding--only +the nearest/even rounding mode is checked. For extended double-precision +operations affected by rounding precision control, TestFloat also tests all +three rounding precision modes, one after the other. Testing can be limited +to a single rounding mode and/or rounding precision with appropriate options +(see _TestFloat_Options_). + +As it executes, TestFloat writes status information to the standard error +output, which should be the screen by default. In order for this status to +be displayed properly, the standard error stream should not be redirected +to a file. The discrepancies TestFloat finds are written to the standard +output stream, which is easily redirected to a file if desired. Ordinarily, +the errors TestFloat reports and the ongoing status information appear +intermixed on the same screen. + +The version of TestFloat for testing SoftFloat is called `testsoftfloat'. +It is invoked the same as `testfloat', + + testsoftfloat [<option>...] <function> + +and operates similarly. + + +------------------------------------------------------------------------------- +Functions Tested by TestFloat + +TestFloat tests all operations required by the IEC/IEEE Standard except for +conversions to and from decimal. The operations are + +-- Conversions among the supported floating-point formats, and also between + integers (32-bit and 64-bit) and any of the floating-point formats. + +-- The usual add, subtract, multiply, divide, and square root operations + for all supported floating-point formats. + +-- For each format, the floating-point remainder operation defined by the + IEC/IEEE Standard. + +-- For each floating-point format, a ``round to integer'' operation that + rounds to the nearest integer value in the same format. (The floating- + point formats can hold integer values, of course.) + +-- Comparisons between two values in the same floating-point format. + +Detailed information about these functions is given below. In the function +names used by TestFloat, single precision is called `float32', double +precision is `float64', extended double precision is `floatx80', and +quadruple precision is `float128'. TestFloat uses the same names for +functions as SoftFloat. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Conversion Functions + +All conversions among the floating-point formats and all conversion between +a floating-point format and 32-bit and 64-bit signed integers can be tested. +The conversion functions are: + + int32_to_float32 int64_to_float32 + int32_to_float64 int64_to_float32 + int32_to_floatx80 int64_to_floatx80 + int32_to_float128 int64_to_float128 + + float32_to_int32 float32_to_int64 + float32_to_int32 float64_to_int64 + floatx80_to_int32 floatx80_to_int64 + float128_to_int32 float128_to_int64 + + float32_to_float64 float32_to_floatx80 float32_to_float128 + float64_to_float32 float64_to_floatx80 float64_to_float128 + floatx80_to_float32 floatx80_to_float64 floatx80_to_float128 + float128_to_float32 float128_to_float64 float128_to_floatx80 + +These conversions all round according to the current rounding mode as +necessary. Conversions from a smaller to a larger floating-point format are +always exact and so require no rounding. Conversions from 32-bit integers +to double precision or to any larger floating-point format are also exact, +and likewise for conversions from 64-bit integers to extended double and +quadruple precisions. + +ISO/ANSI C requires that conversions to integers be rounded toward zero. +Such conversions can be tested with the following functions that ignore any +rounding mode: + + float32_to_int32_round_to_zero float32_to_int64_round_to_zero + float64_to_int32_round_to_zero float64_to_int64_round_to_zero + floatx80_to_int32_round_to_zero floatx80_to_int64_round_to_zero + float128_to_int32_round_to_zero float128_to_int64_round_to_zero + +TestFloat assumes that conversions from floating-point to integer should +raise the invalid exception if the source value cannot be rounded to a +representable integer of the desired size (32 or 64 bits). If such a +conversion overflows, TestFloat expects the largest integer with the same +sign as the operand to be returned. If the floating-point operand is a NaN, +TestFloat allows either the largest postive or largest negative integer to +be returned. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Standard Arithmetic Functions + +The following standard arithmetic functions can be tested: + + float32_add float32_sub float32_mul float32_div float32_sqrt + float64_add float64_sub float64_mul float64_div float64_sqrt + floatx80_add floatx80_sub floatx80_mul floatx80_div floatx80_sqrt + float128_add float128_sub float128_mul float128_div float128_sqrt + +The extended double-precision (`floatx80') functions can be rounded to +reduced precision under rounding precision control. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Remainder and Round-to-Integer Functions + +For each format, TestFloat can test the IEC/IEEE Standard remainder and +round-to-integer functions. The remainder functions are: + + float32_rem + float64_rem + floatx80_rem + float128_rem + +The round-to-integer functions are: + + float32_round_to_int + float64_round_to_int + floatx80_round_to_int + float128_round_to_int + +The remainder functions are always exact and so do not require rounding. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Comparison Functions + +The following floating-point comparison functions can be tested: + + float32_eq float32_le float32_lt + float64_eq float64_le float64_lt + floatx80_eq floatx80_le floatx80_lt + float128_eq float128_le float128_lt + +The abbreviation `eq' stands for ``equal'' (=); `le' stands for ``less than +or equal'' (<=); and `lt' stands for ``less than'' (<). + +The IEC/IEEE Standard specifies that the less-than-or-equal and less-than +functions raise the invalid exception if either input is any kind of NaN. +The equal functions, for their part, are defined not to raise the invalid +exception on quiet NaNs. For completeness, the following additional +functions can be tested if supported: + + float32_eq_signaling float32_le_quiet float32_lt_quiet + float64_eq_signaling float64_le_quiet float64_lt_quiet + floatx80_eq_signaling floatx80_le_quiet floatx80_lt_quiet + float128_eq_signaling float128_le_quiet float128_lt_quiet + +The `signaling' equal functions are identical to the standard functions +except that the invalid exception should be raised for any NaN input. +Likewise, the `quiet' comparison functions should be identical to their +counterparts except that the invalid exception is not raised for quiet NaNs. + +Obviously, no comparison functions ever require rounding. Any rounding mode +is ignored. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + +------------------------------------------------------------------------------- +Interpreting TestFloat Output + +The ``errors'' reported by TestFloat may or may not really represent errors +in the system being tested. For each test case tried, TestFloat performs +the same floating-point operation for the two implementations being compared +and reports any unexpected difference in the results. The two results could +differ for several reasons: + +-- The IEC/IEEE Standard allows for some variation in how conforming + floating-point behaves. Two implementations can occasionally give + different results without either being incorrect. + +-- The trusted floating-point emulation could be faulty. This could be + because there is a bug in the way the enulation is coded, or because a + mistake was made when the code was compiled for the current system. + +-- TestFloat may not work properly, reporting discrepancies that do not + exist. + +-- Lastly, the floating-point being tested could actually be faulty. + +It is the responsibility of the user to determine the causes for the +discrepancies TestFloat reports. Making this determination can require +detailed knowledge about the IEC/IEEE Standard. Assuming TestFloat is +working properly, any differences found will be due to either the first or +last of these reasons. Variations in the IEC/IEEE Standard that could lead +to false error reports are discussed in the section _Variations_Allowed_by_ +_the_IEC/IEEE_Standard_. + +For each error (or apparent error) TestFloat reports, a line of text +is written to the default output. If a line would be longer than 79 +characters, it is divided. The first part of each error line begins in the +leftmost column, and any subsequent ``continuation'' lines are indented with +a tab. + +Each error reported by `testfloat' is of the form: + + <inputs> soft: <output-from-emulation> syst: <output-from-system> + +The `<inputs>' are the inputs to the operation. Each output is shown as a +pair: the result value first, followed by the exception flags. The `soft' +label stands for ``software'' (or ``SoftFloat''), while `syst' stands for +``system,'' the machine's floating-point. + +For example, two typical error lines could be + + 800.7FFF00 87F.000100 soft: 001.000000 ....x syst: 001.000000 ...ux + 081.000004 000.1FFFFF soft: 001.000000 ....x syst: 001.000000 ...ux + +In the first line, the inputs are `800.7FFF00' and `87F.000100'. The +internal emulation result is `001.000000' with flags `....x', and the +system result is the same but with flags `...ux'. All the items composed of +hexadecimal digits and a single period represent floating-point values (here +single precision). These cases were reported as errors because the flag +results differ. + +In addition to the exception flags, there are seven data types that may +be represented. Four are floating-point types: single precision, double +precision, extended double precision, and quadruple precision. The +remaining three types are 32-bit and 64-bit two's-complement integers and +Boolean values (the results of comparison operations). Boolean values are +represented as a single character, either a `0' or a `1'. 32-bit integers +are written as 8 hexadecimal digits in two's-complement form. Thus, +`FFFFFFFF' is -1, and `7FFFFFFF' is the largest positive 32-bit integer. +64-bit integers are the same except with 16 hexadecimal digits. + +Floating-point values are written in a correspondingly primitive form. +Double-precision values are represented by 16 hexadecimal digits that give +the raw bits of the floating-point encoding. A period separates the 3rd and +4th hexadecimal digits to mark the division between the exponent bits and +fraction bits. Some notable double-precision values include: + + 000.0000000000000 +0 + 3FF.0000000000000 1 + 400.0000000000000 2 + 7FF.0000000000000 +infinity + + 800.0000000000000 -0 + BFF.0000000000000 -1 + C00.0000000000000 -2 + FFF.0000000000000 -infinity + + 3FE.FFFFFFFFFFFFF largest representable number preceding +1 + +The following categories are easily distinguished (assuming the `x's are not +all 0): + + 000.xxxxxxxxxxxxx positive subnormal (denormalized) numbers + 7FF.xxxxxxxxxxxxx positive NaNs + 800.xxxxxxxxxxxxx negative subnormal numbers + FFF.xxxxxxxxxxxxx negative NaNs + +Quadruple-precision values are written the same except with 4 hexadecimal +digits for the sign and exponent and 28 for the fraction. Notable values +include: + + 0000.0000000000000000000000000000 +0 + 3FFF.0000000000000000000000000000 1 + 4000.0000000000000000000000000000 2 + 7FFF.0000000000000000000000000000 +infinity + + 8000.0000000000000000000000000000 -0 + BFFF.0000000000000000000000000000 -1 + C000.0000000000000000000000000000 -2 + FFFF.0000000000000000000000000000 -infinity + + 3FFE.FFFFFFFFFFFFFFFFFFFFFFFFFFFF largest representable number + preceding +1 + +Extended double-precision values are a little unusual in that the leading +significand bit is not hidden as with other formats. When correctly +encoded, the leading significand bit of an extended double-precision value +will be 0 if the value is zero or subnormal, and will be 1 otherwise. +Hence, the same values listed above appear in extended double-precision as +follows (note the leading `8' digit in the significands): + + 0000.0000000000000000 +0 + 3FFF.8000000000000000 1 + 4000.8000000000000000 2 + 7FFF.8000000000000000 +infinity + + 8000.0000000000000000 -0 + BFFF.8000000000000000 -1 + C000.8000000000000000 -2 + FFFF.8000000000000000 -infinity + + 3FFE.FFFFFFFFFFFFFFFF largest representable number preceding +1 + +The representation of single-precision values is unusual for a different +reason. Because the subfields of standard single-precision do not fall +on neat 4-bit boundaries, single-precision outputs are slightly perturbed. +These are written as 9 hexadecimal digits, with a period separating the 3rd +and 4th hexadecimal digits. Broken out into bits, the 9 hexademical digits +cover the single-precision subfields as follows: + + x000 .... .... . .... .... .... .... .... .... sign (1 bit) + .... xxxx xxxx . .... .... .... .... .... .... exponent (8 bits) + .... .... .... . 0xxx xxxx xxxx xxxx xxxx xxxx fraction (23 bits) + +As shown in this schematic, the first hexadecimal digit contains only +the sign, and will be either `0' or `8'. The next two digits give the +biased exponent as an 8-bit integer. This is followed by a period and +6 hexadecimal digits of fraction. The most significant hexadecimal digit +of the fraction can be at most a `7'. + +Notable single-precision values include: + + 000.000000 +0 + 07F.000000 1 + 080.000000 2 + 0FF.000000 +infinity + + 800.000000 -0 + 87F.000000 -1 + 880.000000 -2 + 8FF.000000 -infinity + + 07E.7FFFFF largest representable number preceding +1 + +Again, certain categories are easily distinguished (assuming the `x's are +not all 0): + + 000.xxxxxx positive subnormal (denormalized) numbers + 0FF.xxxxxx positive NaNs + 800.xxxxxx negative subnormal numbers + 8FF.xxxxxx negative NaNs + +Lastly, exception flag values are represented by five characters, one +character per flag. Each flag is written as either a letter or a period +(`.') according to whether the flag was set or not by the operation. A +period indicates the flag was not set. The letter used to indicate a set +flag depends on the flag: + + v invalid flag + z division-by-zero flag + o overflow flag + u underflow flag + x inexact flag + +For example, the notation `...ux' indicates that the underflow and inexact +exception flags were set and that the other three flags (invalid, division- +by-zero, and overflow) were not set. The exception flags are always shown +following the value returned as the result of the operation. + +The output from `testsoftfloat' is of the same form, except that the results +are labeled `true' and `soft': + + <inputs> true: <simple-software-result> soft: <SoftFloat-result> + +The ``true'' result is from the simpler, slower software floating-point, +which, although not necessarily correct, is more likely to be right than +the SoftFloat (`soft') result. + + +------------------------------------------------------------------------------- +Variations Allowed by the IEC/IEEE Standard + +The IEC/IEEE Standard admits some variation among conforming +implementations. Because TestFloat expects the two implementations being +compared to deliver bit-for-bit identical results under most circumstances, +this leeway in the standard can result in false errors being reported if +the two implementations do not make the same choices everywhere the standard +provides an option. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Underflow + +The standard specifies that the underflow exception flag is to be raised +when two conditions are met simultaneously: (1) _tininess_ and (2) _loss_ +_of_accuracy_. A result is tiny when its magnitude is nonzero yet smaller +than any normalized floating-point number. The standard allows tininess to +be determined either before or after a result is rounded to the destination +precision. If tininess is detected before rounding, some borderline cases +will be flagged as underflows even though the result after rounding actually +lies within the normal floating-point range. By detecting tininess after +rounding, a system can avoid some unnecessary signaling of underflow. + +Loss of accuracy occurs when the subnormal format is not sufficient +to represent an underflowed result accurately. The standard allows +loss of accuracy to be detected either as an _inexact_result_ or as a +_denormalization_loss_. If loss of accuracy is detected as an inexact +result, the underflow flag is raised whenever an underflowed quantity +cannot be exactly represented in the subnormal format (that is, whenever the +inexact flag is also raised). A denormalization loss, on the other hand, +occurs only when the subnormal format is not able to represent the result +that would have been returned if the destination format had infinite range. +Some underflowed results are inexact but do not suffer a denormalization +loss. By detecting loss of accuracy as a denormalization loss, a system can +once again avoid some unnecessary signaling of underflow. + +The `-tininessbefore' and `-tininessafter' options can be used to control +whether TestFloat expects tininess on underflow to be detected before or +after rounding. (See _TestFloat_Options_ below.) One or the other is +selected as the default when TestFloat is compiled, but these command +options allow the default to be overridden. + +Most (possibly all) systems detect loss of accuracy as an inexact result. +The current version of TestFloat can only test for this case. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +NaNs + +The IEC/IEEE Standard gives the floating-point formats a large number of +NaN encodings and specifies that NaNs are to be returned as results under +certain conditions. However, the standard allows an implementation almost +complete freedom over _which_ NaN to return in each situation. + +By default, TestFloat does not check the bit patterns of NaN results. When +the result of an operation should be a NaN, any NaN is considered as good +as another. This laxness can be overridden with the `-checkNaNs' option. +(See _TestFloat_Options_ below.) In order for this option to be sensible, +TestFloat must have been compiled so that its internal floating-point +implementation (SoftFloat) generates the proper NaN results for the system +being tested. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Conversions to Integer + +Conversion of a floating-point value to an integer format will fail if the +source value is a NaN or if it is too large. The IEC/IEEE Standard does not +specify what value should be returned as the integer result in these cases. +Moreover, according to the standard, the invalid exception can be raised or +an unspecified alternative mechanism may be used to signal such cases. + +TestFloat assumes that conversions to integer will raise the invalid +exception if the source value cannot be rounded to a representable integer. +When the conversion overflows, TestFloat expects the largest integer with +the same sign as the operand to be returned. If the floating-point operand +is a NaN, TestFloat allows either the largest postive or largest negative +integer to be returned. The current version of TestFloat provides no means +to alter these conventions. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + +------------------------------------------------------------------------------- +TestFloat Options + +The `testfloat' (and `testsoftfloat') program accepts several command +options. If mutually contradictory options are given, the last one has +priority. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +-help + +The `-help' option causes a summary of program usage to be written, after +which the program exits. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +-list + +The `-list' option causes a list of testable functions to be written, +after which the program exits. Some machines do not implement all of the +functions TestFloat can test, plus it may not be possible to test functions +that are inaccessible from the C language. + +The `testsoftfloat' program does not have this option. All SoftFloat +functions can be tested by `testsoftfloat'. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +-level <num> + +The `-level' option sets the level of testing. The argument to `-level' can +be either 1 or 2. The default is level 1. Level 2 performs many more tests +than level 1. Testing at level 2 can take as much as a day (even longer for +`testsoftfloat'), but can reveal bugs not found by level 1. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +-errors <num> + +The `-errors' option instructs TestFloat to report no more than the +specified number of errors for any combination of function, rounding mode, +etc. The argument to `-errors' must be a nonnegative decimal number. Once +the specified number of error reports has been generated, TestFloat ends the +current test and begins the next one, if any. The default is `-errors 20'. + +Against intuition, `-errors 0' causes TestFloat to report every error it +finds. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +-errorstop + +The `-errorstop' option causes the program to exit after the first function +for which any errors are reported. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +-forever + +The `-forever' option causes a single operation to be repeatedly tested. +Only one rounding mode and/or rounding precision can be tested in a single +invocation. If not specified, the rounding mode defaults to nearest/even. +For extended double-precision operations, the rounding precision defaults +to full extended double precision. The testing level is set to 2 by this +option. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +-checkNaNs + +The `-checkNaNs' option causes TestFloat to verify the bitwise correctness +of NaN results. In order for this option to be sensible, TestFloat must +have been compiled so that its internal floating-point implementation +(SoftFloat) generates the proper NaN results for the system being tested. + +This option is not available to `testsoftfloat'. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +-precision32, -precision64, -precision80 + +For extended double-precision functions affected by rounding precision +control, the `-precision32' option restricts testing to only the cases +in which rounding precision is equivalent to single precision. The other +rounding precision options are not tested. Likewise, the `-precision64' +and `-precision80' options fix the rounding precision equivalent to double +precision or extended double precision, respectively. These options are +ignored for functions not affected by rounding precision control. + +These options are not available if extended double precision is not +supported by the machine or if extended double precision functions cannot be +tested. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +-nearesteven, -tozero, -down, -up + +The `-nearesteven' option restricts testing to only the cases in which the +rounding mode is nearest/even. The other rounding mode options are not +tested. Likewise, `-tozero' forces rounding to zero; `-down' forces +rounding down; and `-up' forces rounding up. These options are ignored for +functions that are exact and thus do not round. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +-tininessbefore, -tininessafter + +The `-tininessbefore' option indicates that the system detects tininess +on underflow before rounding. The `-tininessafter' option indicates that +tininess is detected after rounding. TestFloat alters its expectations +accordingly. These options override the default selected when TestFloat was +compiled. Choosing the wrong one of these two options should cause error +reports for some (not all) functions. + +For `testsoftfloat', these options operate more like the rounding precision +and rounding mode options, in that they restrict the tests performed by +`testsoftfloat'. By default, `testsoftfloat' tests both cases for any +function for which there is a difference. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + +------------------------------------------------------------------------------- +Function Sets + +Just as TestFloat can test an operation for all four rounding modes in +sequence, multiple operations can be tested with a single invocation of +TestFloat. Three sets are recognized: `-all1', `-all2', and `-all'. The +set `-all1' comprises all one-operand functions; `-all2' is all two-operand +functions; and `-all' is all functions. A function set can be used in place +of a function name in the TestFloat command line, such as + + testfloat [<option>...] -all + + +------------------------------------------------------------------------------- +Contact Information + +At the time of this writing, the most up-to-date information about +TestFloat and the latest release can be found at the Web page `http:// +HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + + diff --git a/tools/test/testfloat/testsoftfloat.c b/tools/test/testfloat/testsoftfloat.c new file mode 100644 index 0000000..2689ee3 --- /dev/null +++ b/tools/test/testfloat/testsoftfloat.c @@ -0,0 +1,1044 @@ + +/* +=============================================================================== + +This C source file is part of TestFloat, Release 2a, a package of programs +for testing the correctness of floating-point arithmetic complying to the +IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stdlib.h> +#include <signal.h> +#include <string.h> +#include "milieu.h" +#include "fail.h" +#include "softfloat.h" +#include "slowfloat.h" +#include "testCases.h" +#include "testLoops.h" + +static void catchSIGINT( int signalCode ) +{ + + if ( stop ) exit( EXIT_FAILURE ); + stop = TRUE; + +} + +int8 clearFlags( void ) +{ + int8 flags; + + flags = float_exception_flags; + float_exception_flags = 0; + return flags; + +} + +enum { + INT32_TO_FLOAT32 = 1, + INT32_TO_FLOAT64, +#ifdef FLOATX80 + INT32_TO_FLOATX80, +#endif +#ifdef FLOAT128 + INT32_TO_FLOAT128, +#endif +#ifdef BITS64 + INT64_TO_FLOAT32, + INT64_TO_FLOAT64, +#ifdef FLOATX80 + INT64_TO_FLOATX80, +#endif +#ifdef FLOAT128 + INT64_TO_FLOAT128, +#endif +#endif + FLOAT32_TO_INT32, + FLOAT32_TO_INT32_ROUND_TO_ZERO, +#ifdef BITS64 + FLOAT32_TO_INT64, + FLOAT32_TO_INT64_ROUND_TO_ZERO, +#endif + FLOAT32_TO_FLOAT64, +#ifdef FLOATX80 + FLOAT32_TO_FLOATX80, +#endif +#ifdef FLOAT128 + FLOAT32_TO_FLOAT128, +#endif + FLOAT32_ROUND_TO_INT, + FLOAT32_ADD, + FLOAT32_SUB, + FLOAT32_MUL, + FLOAT32_DIV, + FLOAT32_REM, + FLOAT32_SQRT, + FLOAT32_EQ, + FLOAT32_LE, + FLOAT32_LT, + FLOAT32_EQ_SIGNALING, + FLOAT32_LE_QUIET, + FLOAT32_LT_QUIET, + FLOAT64_TO_INT32, + FLOAT64_TO_INT32_ROUND_TO_ZERO, +#ifdef BITS64 + FLOAT64_TO_INT64, + FLOAT64_TO_INT64_ROUND_TO_ZERO, +#endif + FLOAT64_TO_FLOAT32, +#ifdef FLOATX80 + FLOAT64_TO_FLOATX80, +#endif +#ifdef FLOAT128 + FLOAT64_TO_FLOAT128, +#endif + FLOAT64_ROUND_TO_INT, + FLOAT64_ADD, + FLOAT64_SUB, + FLOAT64_MUL, + FLOAT64_DIV, + FLOAT64_REM, + FLOAT64_SQRT, + FLOAT64_EQ, + FLOAT64_LE, + FLOAT64_LT, + FLOAT64_EQ_SIGNALING, + FLOAT64_LE_QUIET, + FLOAT64_LT_QUIET, +#ifdef FLOATX80 + FLOATX80_TO_INT32, + FLOATX80_TO_INT32_ROUND_TO_ZERO, +#ifdef BITS64 + FLOATX80_TO_INT64, + FLOATX80_TO_INT64_ROUND_TO_ZERO, +#endif + FLOATX80_TO_FLOAT32, + FLOATX80_TO_FLOAT64, +#ifdef FLOAT128 + FLOATX80_TO_FLOAT128, +#endif + FLOATX80_ROUND_TO_INT, + FLOATX80_ADD, + FLOATX80_SUB, + FLOATX80_MUL, + FLOATX80_DIV, + FLOATX80_REM, + FLOATX80_SQRT, + FLOATX80_EQ, + FLOATX80_LE, + FLOATX80_LT, + FLOATX80_EQ_SIGNALING, + FLOATX80_LE_QUIET, + FLOATX80_LT_QUIET, +#endif +#ifdef FLOAT128 + FLOAT128_TO_INT32, + FLOAT128_TO_INT32_ROUND_TO_ZERO, +#ifdef BITS64 + FLOAT128_TO_INT64, + FLOAT128_TO_INT64_ROUND_TO_ZERO, +#endif + FLOAT128_TO_FLOAT32, + FLOAT128_TO_FLOAT64, +#ifdef FLOATX80 + FLOAT128_TO_FLOATX80, +#endif + FLOAT128_ROUND_TO_INT, + FLOAT128_ADD, + FLOAT128_SUB, + FLOAT128_MUL, + FLOAT128_DIV, + FLOAT128_REM, + FLOAT128_SQRT, + FLOAT128_EQ, + FLOAT128_LE, + FLOAT128_LT, + FLOAT128_EQ_SIGNALING, + FLOAT128_LE_QUIET, + FLOAT128_LT_QUIET, +#endif + NUM_FUNCTIONS +}; +static struct { + char *name; + int8 numInputs; + flag roundingPrecision, roundingMode; + flag tininessMode, tininessModeAtReducedPrecision; +} functions[ NUM_FUNCTIONS ] = { + { 0, 0, 0, 0, 0, 0 }, + { "int32_to_float32", 1, FALSE, TRUE, FALSE, FALSE }, + { "int32_to_float64", 1, FALSE, FALSE, FALSE, FALSE }, +#ifdef FLOATX80 + { "int32_to_floatx80", 1, FALSE, FALSE, FALSE, FALSE }, +#endif +#ifdef FLOAT128 + { "int32_to_float128", 1, FALSE, FALSE, FALSE, FALSE }, +#endif +#ifdef BITS64 + { "int64_to_float32", 1, FALSE, TRUE, FALSE, FALSE }, + { "int64_to_float64", 1, FALSE, TRUE, FALSE, FALSE }, +#ifdef FLOATX80 + { "int64_to_floatx80", 1, FALSE, FALSE, FALSE, FALSE }, +#endif +#ifdef FLOAT128 + { "int64_to_float128", 1, FALSE, FALSE, FALSE, FALSE }, +#endif +#endif + { "float32_to_int32", 1, FALSE, TRUE, FALSE, FALSE }, + { "float32_to_int32_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE }, +#ifdef BITS64 + { "float32_to_int64", 1, FALSE, TRUE, FALSE, FALSE }, + { "float32_to_int64_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE }, +#endif + { "float32_to_float64", 1, FALSE, FALSE, FALSE, FALSE }, +#ifdef FLOATX80 + { "float32_to_floatx80", 1, FALSE, FALSE, FALSE, FALSE }, +#endif +#ifdef FLOAT128 + { "float32_to_float128", 1, FALSE, FALSE, FALSE, FALSE }, +#endif + { "float32_round_to_int", 1, FALSE, TRUE, FALSE, FALSE }, + { "float32_add", 2, FALSE, TRUE, FALSE, FALSE }, + { "float32_sub", 2, FALSE, TRUE, FALSE, FALSE }, + { "float32_mul", 2, FALSE, TRUE, TRUE, FALSE }, + { "float32_div", 2, FALSE, TRUE, FALSE, FALSE }, + { "float32_rem", 2, FALSE, FALSE, FALSE, FALSE }, + { "float32_sqrt", 1, FALSE, TRUE, FALSE, FALSE }, + { "float32_eq", 2, FALSE, FALSE, FALSE, FALSE }, + { "float32_le", 2, FALSE, FALSE, FALSE, FALSE }, + { "float32_lt", 2, FALSE, FALSE, FALSE, FALSE }, + { "float32_eq_signaling", 2, FALSE, FALSE, FALSE, FALSE }, + { "float32_le_quiet", 2, FALSE, FALSE, FALSE, FALSE }, + { "float32_lt_quiet", 2, FALSE, FALSE, FALSE, FALSE }, + { "float64_to_int32", 1, FALSE, TRUE, FALSE, FALSE }, + { "float64_to_int32_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE }, +#ifdef BITS64 + { "float64_to_int64", 1, FALSE, TRUE, FALSE, FALSE }, + { "float64_to_int64_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE }, +#endif + { "float64_to_float32", 1, FALSE, TRUE, TRUE, FALSE }, +#ifdef FLOATX80 + { "float64_to_floatx80", 1, FALSE, FALSE, FALSE, FALSE }, +#endif +#ifdef FLOAT128 + { "float64_to_float128", 1, FALSE, FALSE, FALSE, FALSE }, +#endif + { "float64_round_to_int", 1, FALSE, TRUE, FALSE, FALSE }, + { "float64_add", 2, FALSE, TRUE, FALSE, FALSE }, + { "float64_sub", 2, FALSE, TRUE, FALSE, FALSE }, + { "float64_mul", 2, FALSE, TRUE, TRUE, FALSE }, + { "float64_div", 2, FALSE, TRUE, FALSE, FALSE }, + { "float64_rem", 2, FALSE, FALSE, FALSE, FALSE }, + { "float64_sqrt", 1, FALSE, TRUE, FALSE, FALSE }, + { "float64_eq", 2, FALSE, FALSE, FALSE, FALSE }, + { "float64_le", 2, FALSE, FALSE, FALSE, FALSE }, + { "float64_lt", 2, FALSE, FALSE, FALSE, FALSE }, + { "float64_eq_signaling", 2, FALSE, FALSE, FALSE, FALSE }, + { "float64_le_quiet", 2, FALSE, FALSE, FALSE, FALSE }, + { "float64_lt_quiet", 2, FALSE, FALSE, FALSE, FALSE }, +#ifdef FLOATX80 + { "floatx80_to_int32", 1, FALSE, TRUE, FALSE, FALSE }, + { "floatx80_to_int32_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE }, +#ifdef BITS64 + { "floatx80_to_int64", 1, FALSE, TRUE, FALSE, FALSE }, + { "floatx80_to_int64_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE }, +#endif + { "floatx80_to_float32", 1, FALSE, TRUE, TRUE, FALSE }, + { "floatx80_to_float64", 1, FALSE, TRUE, TRUE, FALSE }, +#ifdef FLOAT128 + { "floatx80_to_float128", 1, FALSE, FALSE, FALSE, FALSE }, +#endif + { "floatx80_round_to_int", 1, FALSE, TRUE, FALSE, FALSE }, + { "floatx80_add", 2, TRUE, TRUE, FALSE, TRUE }, + { "floatx80_sub", 2, TRUE, TRUE, FALSE, TRUE }, + { "floatx80_mul", 2, TRUE, TRUE, TRUE, TRUE }, + { "floatx80_div", 2, TRUE, TRUE, FALSE, TRUE }, + { "floatx80_rem", 2, FALSE, FALSE, FALSE, FALSE }, + { "floatx80_sqrt", 1, TRUE, TRUE, FALSE, FALSE }, + { "floatx80_eq", 2, FALSE, FALSE, FALSE, FALSE }, + { "floatx80_le", 2, FALSE, FALSE, FALSE, FALSE }, + { "floatx80_lt", 2, FALSE, FALSE, FALSE, FALSE }, + { "floatx80_eq_signaling", 2, FALSE, FALSE, FALSE, FALSE }, + { "floatx80_le_quiet", 2, FALSE, FALSE, FALSE, FALSE }, + { "floatx80_lt_quiet", 2, FALSE, FALSE, FALSE, FALSE }, +#endif +#ifdef FLOAT128 + { "float128_to_int32", 1, FALSE, TRUE, FALSE, FALSE }, + { "float128_to_int32_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE }, +#ifdef BITS64 + { "float128_to_int64", 1, FALSE, TRUE, FALSE, FALSE }, + { "float128_to_int64_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE }, +#endif + { "float128_to_float32", 1, FALSE, TRUE, TRUE, FALSE }, + { "float128_to_float64", 1, FALSE, TRUE, TRUE, FALSE }, +#ifdef FLOATX80 + { "float128_to_floatx80", 1, FALSE, TRUE, TRUE, FALSE }, +#endif + { "float128_round_to_int", 1, FALSE, TRUE, FALSE, FALSE }, + { "float128_add", 2, FALSE, TRUE, FALSE, FALSE }, + { "float128_sub", 2, FALSE, TRUE, FALSE, FALSE }, + { "float128_mul", 2, FALSE, TRUE, TRUE, FALSE }, + { "float128_div", 2, FALSE, TRUE, FALSE, FALSE }, + { "float128_rem", 2, FALSE, FALSE, FALSE, FALSE }, + { "float128_sqrt", 1, FALSE, TRUE, FALSE, FALSE }, + { "float128_eq", 2, FALSE, FALSE, FALSE, FALSE }, + { "float128_le", 2, FALSE, FALSE, FALSE, FALSE }, + { "float128_lt", 2, FALSE, FALSE, FALSE, FALSE }, + { "float128_eq_signaling", 2, FALSE, FALSE, FALSE, FALSE }, + { "float128_le_quiet", 2, FALSE, FALSE, FALSE, FALSE }, + { "float128_lt_quiet", 2, FALSE, FALSE, FALSE, FALSE }, +#endif +}; + +enum { + ROUND_NEAREST_EVEN = 1, + ROUND_TO_ZERO, + ROUND_DOWN, + ROUND_UP, + NUM_ROUNDINGMODES +}; +enum { + TININESS_BEFORE_ROUNDING = 1, + TININESS_AFTER_ROUNDING, + NUM_TININESSMODES +}; + +static void + testFunctionVariety( + uint8 functionCode, + int8 roundingPrecision, + int8 roundingMode, + int8 tininessMode + ) +{ + uint8 roundingCode; + int8 tininessCode; + + functionName = functions[ functionCode ].name; + if ( roundingPrecision == 32 ) { + roundingPrecisionName = "32"; + } + else if ( roundingPrecision == 64 ) { + roundingPrecisionName = "64"; + } + else if ( roundingPrecision == 80 ) { + roundingPrecisionName = "80"; + } + else { + roundingPrecisionName = 0; + } +#ifdef FLOATX80 + floatx80_rounding_precision = roundingPrecision; + slow_floatx80_rounding_precision = roundingPrecision; +#endif + switch ( roundingMode ) { + default: + roundingModeName = 0; + roundingCode = float_round_nearest_even; + break; + case ROUND_NEAREST_EVEN: + roundingModeName = "nearest_even"; + roundingCode = float_round_nearest_even; + break; + case ROUND_TO_ZERO: + roundingModeName = "to_zero"; + roundingCode = float_round_to_zero; + break; + case ROUND_DOWN: + roundingModeName = "down"; + roundingCode = float_round_down; + break; + case ROUND_UP: + roundingModeName = "up"; + roundingCode = float_round_up; + break; + } + float_rounding_mode = roundingCode; + slow_float_rounding_mode = roundingCode; + switch ( tininessMode ) { + default: + tininessModeName = 0; + tininessCode = float_tininess_after_rounding; + break; + case TININESS_BEFORE_ROUNDING: + tininessModeName = "before"; + tininessCode = float_tininess_before_rounding; + break; + case TININESS_AFTER_ROUNDING: + tininessModeName = "after"; + tininessCode = float_tininess_after_rounding; + break; + } + float_detect_tininess = tininessCode; + slow_float_detect_tininess = tininessCode; + fputs( "Testing ", stderr ); + writeFunctionName( stderr ); + fputs( ".\n", stderr ); + switch ( functionCode ) { + case INT32_TO_FLOAT32: + test_a_int32_z_float32( slow_int32_to_float32, int32_to_float32 ); + break; + case INT32_TO_FLOAT64: + test_a_int32_z_float64( slow_int32_to_float64, int32_to_float64 ); + break; +#ifdef FLOATX80 + case INT32_TO_FLOATX80: + test_a_int32_z_floatx80( slow_int32_to_floatx80, int32_to_floatx80 ); + break; +#endif +#ifdef FLOAT128 + case INT32_TO_FLOAT128: + test_a_int32_z_float128( slow_int32_to_float128, int32_to_float128 ); + break; +#endif +#ifdef BITS64 + case INT64_TO_FLOAT32: + test_a_int64_z_float32( slow_int64_to_float32, int64_to_float32 ); + break; + case INT64_TO_FLOAT64: + test_a_int64_z_float64( slow_int64_to_float64, int64_to_float64 ); + break; +#ifdef FLOATX80 + case INT64_TO_FLOATX80: + test_a_int64_z_floatx80( slow_int64_to_floatx80, int64_to_floatx80 ); + break; +#endif +#ifdef FLOAT128 + case INT64_TO_FLOAT128: + test_a_int64_z_float128( slow_int64_to_float128, int64_to_float128 ); + break; +#endif +#endif + case FLOAT32_TO_INT32: + test_a_float32_z_int32( slow_float32_to_int32, float32_to_int32 ); + break; + case FLOAT32_TO_INT32_ROUND_TO_ZERO: + test_a_float32_z_int32( + slow_float32_to_int32_round_to_zero, + float32_to_int32_round_to_zero + ); + break; +#ifdef BITS64 + case FLOAT32_TO_INT64: + test_a_float32_z_int64( slow_float32_to_int64, float32_to_int64 ); + break; + case FLOAT32_TO_INT64_ROUND_TO_ZERO: + test_a_float32_z_int64( + slow_float32_to_int64_round_to_zero, + float32_to_int64_round_to_zero + ); + break; +#endif + case FLOAT32_TO_FLOAT64: + test_a_float32_z_float64( + slow_float32_to_float64, float32_to_float64 ); + break; +#ifdef FLOATX80 + case FLOAT32_TO_FLOATX80: + test_a_float32_z_floatx80( + slow_float32_to_floatx80, float32_to_floatx80 ); + break; +#endif +#ifdef FLOAT128 + case FLOAT32_TO_FLOAT128: + test_a_float32_z_float128( + slow_float32_to_float128, float32_to_float128 ); + break; +#endif + case FLOAT32_ROUND_TO_INT: + test_az_float32( slow_float32_round_to_int, float32_round_to_int ); + break; + case FLOAT32_ADD: + test_abz_float32( slow_float32_add, float32_add ); + break; + case FLOAT32_SUB: + test_abz_float32( slow_float32_sub, float32_sub ); + break; + case FLOAT32_MUL: + test_abz_float32( slow_float32_mul, float32_mul ); + break; + case FLOAT32_DIV: + test_abz_float32( slow_float32_div, float32_div ); + break; + case FLOAT32_REM: + test_abz_float32( slow_float32_rem, float32_rem ); + break; + case FLOAT32_SQRT: + test_az_float32( slow_float32_sqrt, float32_sqrt ); + break; + case FLOAT32_EQ: + test_ab_float32_z_flag( slow_float32_eq, float32_eq ); + break; + case FLOAT32_LE: + test_ab_float32_z_flag( slow_float32_le, float32_le ); + break; + case FLOAT32_LT: + test_ab_float32_z_flag( slow_float32_lt, float32_lt ); + break; + case FLOAT32_EQ_SIGNALING: + test_ab_float32_z_flag( + slow_float32_eq_signaling, float32_eq_signaling ); + break; + case FLOAT32_LE_QUIET: + test_ab_float32_z_flag( slow_float32_le_quiet, float32_le_quiet ); + break; + case FLOAT32_LT_QUIET: + test_ab_float32_z_flag( slow_float32_lt_quiet, float32_lt_quiet ); + break; + case FLOAT64_TO_INT32: + test_a_float64_z_int32( slow_float64_to_int32, float64_to_int32 ); + break; + case FLOAT64_TO_INT32_ROUND_TO_ZERO: + test_a_float64_z_int32( + slow_float64_to_int32_round_to_zero, + float64_to_int32_round_to_zero + ); + break; +#ifdef BITS64 + case FLOAT64_TO_INT64: + test_a_float64_z_int64( slow_float64_to_int64, float64_to_int64 ); + break; + case FLOAT64_TO_INT64_ROUND_TO_ZERO: + test_a_float64_z_int64( + slow_float64_to_int64_round_to_zero, + float64_to_int64_round_to_zero + ); + break; +#endif + case FLOAT64_TO_FLOAT32: + test_a_float64_z_float32( + slow_float64_to_float32, float64_to_float32 ); + break; +#ifdef FLOATX80 + case FLOAT64_TO_FLOATX80: + test_a_float64_z_floatx80( + slow_float64_to_floatx80, float64_to_floatx80 ); + break; +#endif +#ifdef FLOAT128 + case FLOAT64_TO_FLOAT128: + test_a_float64_z_float128( + slow_float64_to_float128, float64_to_float128 ); + break; +#endif + case FLOAT64_ROUND_TO_INT: + test_az_float64( slow_float64_round_to_int, float64_round_to_int ); + break; + case FLOAT64_ADD: + test_abz_float64( slow_float64_add, float64_add ); + break; + case FLOAT64_SUB: + test_abz_float64( slow_float64_sub, float64_sub ); + break; + case FLOAT64_MUL: + test_abz_float64( slow_float64_mul, float64_mul ); + break; + case FLOAT64_DIV: + test_abz_float64( slow_float64_div, float64_div ); + break; + case FLOAT64_REM: + test_abz_float64( slow_float64_rem, float64_rem ); + break; + case FLOAT64_SQRT: + test_az_float64( slow_float64_sqrt, float64_sqrt ); + break; + case FLOAT64_EQ: + test_ab_float64_z_flag( slow_float64_eq, float64_eq ); + break; + case FLOAT64_LE: + test_ab_float64_z_flag( slow_float64_le, float64_le ); + break; + case FLOAT64_LT: + test_ab_float64_z_flag( slow_float64_lt, float64_lt ); + break; + case FLOAT64_EQ_SIGNALING: + test_ab_float64_z_flag( + slow_float64_eq_signaling, float64_eq_signaling ); + break; + case FLOAT64_LE_QUIET: + test_ab_float64_z_flag( slow_float64_le_quiet, float64_le_quiet ); + break; + case FLOAT64_LT_QUIET: + test_ab_float64_z_flag( slow_float64_lt_quiet, float64_lt_quiet ); + break; +#ifdef FLOATX80 + case FLOATX80_TO_INT32: + test_a_floatx80_z_int32( slow_floatx80_to_int32, floatx80_to_int32 ); + break; + case FLOATX80_TO_INT32_ROUND_TO_ZERO: + test_a_floatx80_z_int32( + slow_floatx80_to_int32_round_to_zero, + floatx80_to_int32_round_to_zero + ); + break; +#ifdef BITS64 + case FLOATX80_TO_INT64: + test_a_floatx80_z_int64( slow_floatx80_to_int64, floatx80_to_int64 ); + break; + case FLOATX80_TO_INT64_ROUND_TO_ZERO: + test_a_floatx80_z_int64( + slow_floatx80_to_int64_round_to_zero, + floatx80_to_int64_round_to_zero + ); + break; +#endif + case FLOATX80_TO_FLOAT32: + test_a_floatx80_z_float32( + slow_floatx80_to_float32, floatx80_to_float32 ); + break; + case FLOATX80_TO_FLOAT64: + test_a_floatx80_z_float64( + slow_floatx80_to_float64, floatx80_to_float64 ); + break; +#ifdef FLOAT128 + case FLOATX80_TO_FLOAT128: + test_a_floatx80_z_float128( + slow_floatx80_to_float128, floatx80_to_float128 ); + break; +#endif + case FLOATX80_ROUND_TO_INT: + test_az_floatx80( slow_floatx80_round_to_int, floatx80_round_to_int ); + break; + case FLOATX80_ADD: + test_abz_floatx80( slow_floatx80_add, floatx80_add ); + break; + case FLOATX80_SUB: + test_abz_floatx80( slow_floatx80_sub, floatx80_sub ); + break; + case FLOATX80_MUL: + test_abz_floatx80( slow_floatx80_mul, floatx80_mul ); + break; + case FLOATX80_DIV: + test_abz_floatx80( slow_floatx80_div, floatx80_div ); + break; + case FLOATX80_REM: + test_abz_floatx80( slow_floatx80_rem, floatx80_rem ); + break; + case FLOATX80_SQRT: + test_az_floatx80( slow_floatx80_sqrt, floatx80_sqrt ); + break; + case FLOATX80_EQ: + test_ab_floatx80_z_flag( slow_floatx80_eq, floatx80_eq ); + break; + case FLOATX80_LE: + test_ab_floatx80_z_flag( slow_floatx80_le, floatx80_le ); + break; + case FLOATX80_LT: + test_ab_floatx80_z_flag( slow_floatx80_lt, floatx80_lt ); + break; + case FLOATX80_EQ_SIGNALING: + test_ab_floatx80_z_flag( + slow_floatx80_eq_signaling, floatx80_eq_signaling ); + break; + case FLOATX80_LE_QUIET: + test_ab_floatx80_z_flag( slow_floatx80_le_quiet, floatx80_le_quiet ); + break; + case FLOATX80_LT_QUIET: + test_ab_floatx80_z_flag( slow_floatx80_lt_quiet, floatx80_lt_quiet ); + break; +#endif +#ifdef FLOAT128 + case FLOAT128_TO_INT32: + test_a_float128_z_int32( slow_float128_to_int32, float128_to_int32 ); + break; + case FLOAT128_TO_INT32_ROUND_TO_ZERO: + test_a_float128_z_int32( + slow_float128_to_int32_round_to_zero, + float128_to_int32_round_to_zero + ); + break; +#ifdef BITS64 + case FLOAT128_TO_INT64: + test_a_float128_z_int64( slow_float128_to_int64, float128_to_int64 ); + break; + case FLOAT128_TO_INT64_ROUND_TO_ZERO: + test_a_float128_z_int64( + slow_float128_to_int64_round_to_zero, + float128_to_int64_round_to_zero + ); + break; +#endif + case FLOAT128_TO_FLOAT32: + test_a_float128_z_float32( + slow_float128_to_float32, float128_to_float32 ); + break; + case FLOAT128_TO_FLOAT64: + test_a_float128_z_float64( + slow_float128_to_float64, float128_to_float64 ); + break; +#ifdef FLOATX80 + case FLOAT128_TO_FLOATX80: + test_a_float128_z_floatx80( + slow_float128_to_floatx80, float128_to_floatx80 ); + break; +#endif + case FLOAT128_ROUND_TO_INT: + test_az_float128( slow_float128_round_to_int, float128_round_to_int ); + break; + case FLOAT128_ADD: + test_abz_float128( slow_float128_add, float128_add ); + break; + case FLOAT128_SUB: + test_abz_float128( slow_float128_sub, float128_sub ); + break; + case FLOAT128_MUL: + test_abz_float128( slow_float128_mul, float128_mul ); + break; + case FLOAT128_DIV: + test_abz_float128( slow_float128_div, float128_div ); + break; + case FLOAT128_REM: + test_abz_float128( slow_float128_rem, float128_rem ); + break; + case FLOAT128_SQRT: + test_az_float128( slow_float128_sqrt, float128_sqrt ); + break; + case FLOAT128_EQ: + test_ab_float128_z_flag( slow_float128_eq, float128_eq ); + break; + case FLOAT128_LE: + test_ab_float128_z_flag( slow_float128_le, float128_le ); + break; + case FLOAT128_LT: + test_ab_float128_z_flag( slow_float128_lt, float128_lt ); + break; + case FLOAT128_EQ_SIGNALING: + test_ab_float128_z_flag( + slow_float128_eq_signaling, float128_eq_signaling ); + break; + case FLOAT128_LE_QUIET: + test_ab_float128_z_flag( slow_float128_le_quiet, float128_le_quiet ); + break; + case FLOAT128_LT_QUIET: + test_ab_float128_z_flag( slow_float128_lt_quiet, float128_lt_quiet ); + break; +#endif + } + if ( ( errorStop && anyErrors ) || stop ) exitWithStatus(); + +} + +static void + testFunction( + uint8 functionCode, + int8 roundingPrecisionIn, + int8 roundingModeIn, + int8 tininessModeIn + ) +{ + int8 roundingPrecision, roundingMode, tininessMode; + + roundingPrecision = 32; + for (;;) { + if ( ! functions[ functionCode ].roundingPrecision ) { + roundingPrecision = 0; + } + else if ( roundingPrecisionIn ) { + roundingPrecision = roundingPrecisionIn; + } + for ( roundingMode = 1; + roundingMode < NUM_ROUNDINGMODES; + ++roundingMode + ) { + if ( ! functions[ functionCode ].roundingMode ) { + roundingMode = 0; + } + else if ( roundingModeIn ) { + roundingMode = roundingModeIn; + } + for ( tininessMode = 1; + tininessMode < NUM_TININESSMODES; + ++tininessMode + ) { + if ( ( roundingPrecision == 32 ) + || ( roundingPrecision == 64 ) ) { + if ( ! functions[ functionCode ] + .tininessModeAtReducedPrecision + ) { + tininessMode = 0; + } + else if ( tininessModeIn ) { + tininessMode = tininessModeIn; + } + } + else { + if ( ! functions[ functionCode ].tininessMode ) { + tininessMode = 0; + } + else if ( tininessModeIn ) { + tininessMode = tininessModeIn; + } + } + testFunctionVariety( + functionCode, roundingPrecision, roundingMode, tininessMode + ); + if ( tininessModeIn || ! tininessMode ) break; + } + if ( roundingModeIn || ! roundingMode ) break; + } + if ( roundingPrecisionIn || ! roundingPrecision ) break; + if ( roundingPrecision == 80 ) { + break; + } + else if ( roundingPrecision == 64 ) { + roundingPrecision = 80; + } + else if ( roundingPrecision == 32 ) { + roundingPrecision = 64; + } + } + +} + +int +main( int argc, char **argv ) +{ + char *argPtr; + flag functionArgument; + uint8 functionCode; + int8 operands, roundingPrecision, roundingMode, tininessMode; + + fail_programName = "testsoftfloat"; + if ( argc <= 1 ) goto writeHelpMessage; + testCases_setLevel( 1 ); + trueName = "true"; + testName = "soft"; + errorStop = FALSE; + forever = FALSE; + maxErrorCount = 20; + trueFlagsPtr = &slow_float_exception_flags; + testFlagsFunctionPtr = clearFlags; + functionArgument = FALSE; + functionCode = 0; + operands = 0; + roundingPrecision = 0; + roundingMode = 0; + tininessMode = 0; + --argc; + ++argv; + while ( argc && ( argPtr = argv[ 0 ] ) ) { + if ( argPtr[ 0 ] == '-' ) ++argPtr; + if ( strcmp( argPtr, "help" ) == 0 ) { + writeHelpMessage: + fputs( +"testsoftfloat [<option>...] <function>\n" +" <option>: (* is default)\n" +" -help --Write this message and exit.\n" +" -level <num> --Testing level <num> (1 or 2).\n" +" * -level 1\n" +" -errors <num> --Stop each function test after <num> errors.\n" +" * -errors 20\n" +" -errorstop --Exit after first function with any error.\n" +" -forever --Test one function repeatedly (implies `-level 2').\n" +#ifdef FLOATX80 +" -precision32 --Only test rounding precision equivalent to float32.\n" +" -precision64 --Only test rounding precision equivalent to float64.\n" +" -precision80 --Only test maximum rounding precision.\n" +#endif +" -nearesteven --Only test rounding to nearest/even.\n" +" -tozero --Only test rounding to zero.\n" +" -down --Only test rounding down.\n" +" -up --Only test rounding up.\n" +" -tininessbefore --Only test underflow tininess before rounding.\n" +" -tininessafter --Only test underflow tininess after rounding.\n" +" <function>:\n" +" int32_to_<float> <float>_add <float>_eq\n" +" <float>_to_int32 <float>_sub <float>_le\n" +" <float>_to_int32_round_to_zero <float>_mul <float>_lt\n" +#ifdef BITS64 +" int64_to_<float> <float>_div <float>_eq_signaling\n" +" <float>_to_int64 <float>_rem <float>_le_quiet\n" +" <float>_to_int64_round_to_zero <float>_lt_quiet\n" +" <float>_to_<float>\n" +" <float>_round_to_int\n" +" <float>_sqrt\n" +#else +" <float>_to_<float> <float>_div <float>_eq_signaling\n" +" <float>_round_to_int <float>_rem <float>_le_quiet\n" +" <float>_sqrt <float>_lt_quiet\n" +#endif +" -all1 --All 1-operand functions.\n" +" -all2 --All 2-operand functions.\n" +" -all --All functions.\n" +" <float>:\n" +" float32 --Single precision.\n" +" float64 --Double precision.\n" +#ifdef FLOATX80 +" floatx80 --Extended double precision.\n" +#endif +#ifdef FLOAT128 +" float128 --Quadruple precision.\n" +#endif + , + stdout + ); + return EXIT_SUCCESS; + } + else if ( strcmp( argPtr, "level" ) == 0 ) { + if ( argc < 2 ) goto optionError; + testCases_setLevel( atoi( argv[ 1 ] ) ); + --argc; + ++argv; + } + else if ( strcmp( argPtr, "level1" ) == 0 ) { + testCases_setLevel( 1 ); + } + else if ( strcmp( argPtr, "level2" ) == 0 ) { + testCases_setLevel( 2 ); + } + else if ( strcmp( argPtr, "errors" ) == 0 ) { + if ( argc < 2 ) { + optionError: + fail( "`%s' option requires numeric argument", argv[ 0 ] ); + } + maxErrorCount = atoi( argv[ 1 ] ); + --argc; + ++argv; + } + else if ( strcmp( argPtr, "errorstop" ) == 0 ) { + errorStop = TRUE; + } + else if ( strcmp( argPtr, "forever" ) == 0 ) { + testCases_setLevel( 2 ); + forever = TRUE; + } +#ifdef FLOATX80 + else if ( strcmp( argPtr, "precision32" ) == 0 ) { + roundingPrecision = 32; + } + else if ( strcmp( argPtr, "precision64" ) == 0 ) { + roundingPrecision = 64; + } + else if ( strcmp( argPtr, "precision80" ) == 0 ) { + roundingPrecision = 80; + } +#endif + else if ( ( strcmp( argPtr, "nearesteven" ) == 0 ) + || ( strcmp( argPtr, "nearest_even" ) == 0 ) ) { + roundingMode = ROUND_NEAREST_EVEN; + } + else if ( ( strcmp( argPtr, "tozero" ) == 0 ) + || ( strcmp( argPtr, "to_zero" ) == 0 ) ) { + roundingMode = ROUND_TO_ZERO; + } + else if ( strcmp( argPtr, "down" ) == 0 ) { + roundingMode = ROUND_DOWN; + } + else if ( strcmp( argPtr, "up" ) == 0 ) { + roundingMode = ROUND_UP; + } + else if ( strcmp( argPtr, "tininessbefore" ) == 0 ) { + tininessMode = TININESS_BEFORE_ROUNDING; + } + else if ( strcmp( argPtr, "tininessafter" ) == 0 ) { + tininessMode = TININESS_AFTER_ROUNDING; + } + else if ( strcmp( argPtr, "all1" ) == 0 ) { + functionArgument = TRUE; + functionCode = 0; + operands = 1; + } + else if ( strcmp( argPtr, "all2" ) == 0 ) { + functionArgument = TRUE; + functionCode = 0; + operands = 2; + } + else if ( strcmp( argPtr, "all" ) == 0 ) { + functionArgument = TRUE; + functionCode = 0; + operands = 0; + } + else { + for ( functionCode = 1; + functionCode < NUM_FUNCTIONS; + ++functionCode + ) { + if ( strcmp( argPtr, functions[ functionCode ].name ) == 0 ) { + break; + } + } + if ( functionCode == NUM_FUNCTIONS ) { + fail( "Invalid option or function `%s'", argv[ 0 ] ); + } + functionArgument = TRUE; + } + --argc; + ++argv; + } + if ( ! functionArgument ) fail( "Function argument required" ); + (void) signal( SIGINT, catchSIGINT ); + (void) signal( SIGTERM, catchSIGINT ); + if ( functionCode ) { + if ( forever ) { + if ( ! roundingPrecision ) roundingPrecision = 80; + if ( ! roundingMode ) roundingMode = ROUND_NEAREST_EVEN; + } + testFunction( + functionCode, roundingPrecision, roundingMode, tininessMode ); + } + else { + if ( operands == 1 ) { + for ( functionCode = 1; + functionCode < NUM_FUNCTIONS; + ++functionCode + ) { + if ( functions[ functionCode ].numInputs == 1 ) { + testFunction( + functionCode, + roundingPrecision, + roundingMode, + tininessMode + ); + } + } + } + else if ( operands == 2 ) { + for ( functionCode = 1; + functionCode < NUM_FUNCTIONS; + ++functionCode + ) { + if ( functions[ functionCode ].numInputs == 2 ) { + testFunction( + functionCode, + roundingPrecision, + roundingMode, + tininessMode + ); + } + } + } + else { + for ( functionCode = 1; + functionCode < NUM_FUNCTIONS; + ++functionCode + ) { + testFunction( + functionCode, roundingPrecision, roundingMode, tininessMode + ); + } + } + } + exitWithStatus(); + +} + diff --git a/tools/test/testfloat/writeHex.c b/tools/test/testfloat/writeHex.c new file mode 100644 index 0000000..f304aed --- /dev/null +++ b/tools/test/testfloat/writeHex.c @@ -0,0 +1,183 @@ + +/* +=============================================================================== + +This C source file is part of TestFloat, Release 2a, a package of programs +for testing the correctness of floating-point arithmetic complying to the +IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +#include <stdio.h> +#include "milieu.h" +#include "softfloat.h" +#include "writeHex.h" + +void writeHex_flag( flag a, FILE *stream ) +{ + + fputc( a ? '1' : '0', stream ); + +} + +static void writeHex_bits8( bits8 a, FILE *stream ) +{ + int digit; + + digit = ( a>>4 ) & 0xF; + if ( 9 < digit ) digit += 'A' - ( '0' + 10 ); + fputc( '0' + digit, stream ); + digit = a & 0xF; + if ( 9 < digit ) digit += 'A' - ( '0' + 10 ); + fputc( '0' + digit, stream ); + +} + +static void writeHex_bits12( int16 a, FILE *stream ) +{ + int digit; + + digit = ( a>>8 ) & 0xF; + if ( 9 < digit ) digit += 'A' - ( '0' + 10 ); + fputc( '0' + digit, stream ); + digit = ( a>>4 ) & 0xF; + if ( 9 < digit ) digit += 'A' - ( '0' + 10 ); + fputc( '0' + digit, stream ); + digit = a & 0xF; + if ( 9 < digit ) digit += 'A' - ( '0' + 10 ); + fputc( '0' + digit, stream ); + +} + +static void writeHex_bits16( bits16 a, FILE *stream ) +{ + int digit; + + digit = ( a>>12 ) & 0xF; + if ( 9 < digit ) digit += 'A' - ( '0' + 10 ); + fputc( '0' + digit, stream ); + digit = ( a>>8 ) & 0xF; + if ( 9 < digit ) digit += 'A' - ( '0' + 10 ); + fputc( '0' + digit, stream ); + digit = ( a>>4 ) & 0xF; + if ( 9 < digit ) digit += 'A' - ( '0' + 10 ); + fputc( '0' + digit, stream ); + digit = a & 0xF; + if ( 9 < digit ) digit += 'A' - ( '0' + 10 ); + fputc( '0' + digit, stream ); + +} + +void writeHex_bits32( bits32 a, FILE *stream ) +{ + + writeHex_bits16( a>>16, stream ); + writeHex_bits16( a, stream ); + +} + +#ifdef BITS64 + +void writeHex_bits64( bits64 a, FILE *stream ) +{ + + writeHex_bits32( a>>32, stream ); + writeHex_bits32( a, stream ); + +} + +#endif + +void writeHex_float32( float32 a, FILE *stream ) +{ + + fputc( ( ( (sbits32) a ) < 0 ) ? '8' : '0', stream ); + writeHex_bits8( a>>23, stream ); + fputc( '.', stream ); + writeHex_bits8( ( a>>16 ) & 0x7F, stream ); + writeHex_bits16( a, stream ); + +} + +#ifdef BITS64 + +void writeHex_float64( float64 a, FILE *stream ) +{ + + writeHex_bits12( a>>52, stream ); + fputc( '.', stream ); + writeHex_bits12( a>>40, stream ); + writeHex_bits8( a>>32, stream ); + writeHex_bits32( a, stream ); + +} + +#else + +void writeHex_float64( float64 a, FILE *stream ) +{ + + writeHex_bits12( a.high>>20, stream ); + fputc( '.', stream ); + writeHex_bits12( a.high>>8, stream ); + writeHex_bits8( a.high, stream ); + writeHex_bits32( a.low, stream ); + +} + +#endif + +#ifdef FLOATX80 + +void writeHex_floatx80( floatx80 a, FILE *stream ) +{ + + writeHex_bits16( a.high, stream ); + fputc( '.', stream ); + writeHex_bits64( a.low, stream ); + +} + +#endif + +#ifdef FLOAT128 + +void writeHex_float128( float128 a, FILE *stream ) +{ + + writeHex_bits16( a.high>>48, stream ); + fputc( '.', stream ); + writeHex_bits16( a.high>>32, stream ); + writeHex_bits32( a.high, stream ); + writeHex_bits64( a.low, stream ); + +} + +#endif + +void writeHex_float_flags( uint8 flags, FILE *stream ) +{ + + fputc( flags & float_flag_invalid ? 'v' : '.', stream ); + fputc( flags & float_flag_divbyzero ? 'z' : '.', stream ); + fputc( flags & float_flag_overflow ? 'o' : '.', stream ); + fputc( flags & float_flag_underflow ? 'u' : '.', stream ); + fputc( flags & float_flag_inexact ? 'x' : '.', stream ); + +} + diff --git a/tools/test/testfloat/writeHex.h b/tools/test/testfloat/writeHex.h new file mode 100644 index 0000000..0dde44c --- /dev/null +++ b/tools/test/testfloat/writeHex.h @@ -0,0 +1,42 @@ + +/* +=============================================================================== + +This C header file is part of TestFloat, Release 2a, a package of programs +for testing the correctness of floating-point arithmetic complying to the +IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +#include <stdio.h> + +void writeHex_flag( flag, FILE * ); +void writeHex_bits32( bits32, FILE * ); +#ifdef BITS64 +void writeHex_bits64( bits64, FILE * ); +#endif +void writeHex_float32( float32, FILE * ); +void writeHex_float64( float64, FILE * ); +#ifdef FLOATX80 +void writeHex_floatx80( floatx80, FILE * ); +#endif +#ifdef FLOAT128 +void writeHex_float128( float128, FILE * ); +#endif +void writeHex_float_flags( uint8, FILE * ); + |