|
@@ -1259,3 +1259,175 @@ float32 float32_mul( struct roundingData *roundData, float32 a, float32 b )
|
|
|
}
|
|
|
zExp = aExp + bExp - 0x7F;
|
|
|
aSig = ( aSig | 0x00800000 )<<7;
|
|
|
+ bSig = ( bSig | 0x00800000 )<<8;
|
|
|
+ shift64RightJamming( ( (bits64) aSig ) * bSig, 32, &zSig64 );
|
|
|
+ zSig = zSig64;
|
|
|
+ if ( 0 <= (sbits32) ( zSig<<1 ) ) {
|
|
|
+ zSig <<= 1;
|
|
|
+ --zExp;
|
|
|
+ }
|
|
|
+ return roundAndPackFloat32( roundData, zSign, zExp, zSig );
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+Returns the result of dividing the single-precision floating-point value `a'
|
|
|
+by the corresponding value `b'. The operation is performed according to the
|
|
|
+IEC/IEEE Standard for Binary Floating-point Arithmetic.
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+*/
|
|
|
+float32 float32_div( struct roundingData *roundData, float32 a, float32 b )
|
|
|
+{
|
|
|
+ flag aSign, bSign, zSign;
|
|
|
+ int16 aExp, bExp, zExp;
|
|
|
+ bits32 aSig, bSig, zSig;
|
|
|
+
|
|
|
+ aSig = extractFloat32Frac( a );
|
|
|
+ aExp = extractFloat32Exp( a );
|
|
|
+ aSign = extractFloat32Sign( a );
|
|
|
+ bSig = extractFloat32Frac( b );
|
|
|
+ bExp = extractFloat32Exp( b );
|
|
|
+ bSign = extractFloat32Sign( b );
|
|
|
+ zSign = aSign ^ bSign;
|
|
|
+ if ( aExp == 0xFF ) {
|
|
|
+ if ( aSig ) return propagateFloat32NaN( a, b );
|
|
|
+ if ( bExp == 0xFF ) {
|
|
|
+ if ( bSig ) return propagateFloat32NaN( a, b );
|
|
|
+ roundData->exception |= float_flag_invalid;
|
|
|
+ return float32_default_nan;
|
|
|
+ }
|
|
|
+ return packFloat32( zSign, 0xFF, 0 );
|
|
|
+ }
|
|
|
+ if ( bExp == 0xFF ) {
|
|
|
+ if ( bSig ) return propagateFloat32NaN( a, b );
|
|
|
+ return packFloat32( zSign, 0, 0 );
|
|
|
+ }
|
|
|
+ if ( bExp == 0 ) {
|
|
|
+ if ( bSig == 0 ) {
|
|
|
+ if ( ( aExp | aSig ) == 0 ) {
|
|
|
+ roundData->exception |= float_flag_invalid;
|
|
|
+ return float32_default_nan;
|
|
|
+ }
|
|
|
+ roundData->exception |= float_flag_divbyzero;
|
|
|
+ return packFloat32( zSign, 0xFF, 0 );
|
|
|
+ }
|
|
|
+ normalizeFloat32Subnormal( bSig, &bExp, &bSig );
|
|
|
+ }
|
|
|
+ if ( aExp == 0 ) {
|
|
|
+ if ( aSig == 0 ) return packFloat32( zSign, 0, 0 );
|
|
|
+ normalizeFloat32Subnormal( aSig, &aExp, &aSig );
|
|
|
+ }
|
|
|
+ zExp = aExp - bExp + 0x7D;
|
|
|
+ aSig = ( aSig | 0x00800000 )<<7;
|
|
|
+ bSig = ( bSig | 0x00800000 )<<8;
|
|
|
+ if ( bSig <= ( aSig + aSig ) ) {
|
|
|
+ aSig >>= 1;
|
|
|
+ ++zExp;
|
|
|
+ }
|
|
|
+ {
|
|
|
+ bits64 tmp = ( (bits64) aSig )<<32;
|
|
|
+ do_div( tmp, bSig );
|
|
|
+ zSig = tmp;
|
|
|
+ }
|
|
|
+ if ( ( zSig & 0x3F ) == 0 ) {
|
|
|
+ zSig |= ( ( (bits64) bSig ) * zSig != ( (bits64) aSig )<<32 );
|
|
|
+ }
|
|
|
+ return roundAndPackFloat32( roundData, zSign, zExp, zSig );
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+Returns the remainder of the single-precision floating-point value `a'
|
|
|
+with respect to the corresponding value `b'. The operation is performed
|
|
|
+according to the IEC/IEEE Standard for Binary Floating-point Arithmetic.
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+*/
|
|
|
+float32 float32_rem( struct roundingData *roundData, float32 a, float32 b )
|
|
|
+{
|
|
|
+ flag aSign, bSign, zSign;
|
|
|
+ int16 aExp, bExp, expDiff;
|
|
|
+ bits32 aSig, bSig;
|
|
|
+ bits32 q;
|
|
|
+ bits64 aSig64, bSig64, q64;
|
|
|
+ bits32 alternateASig;
|
|
|
+ sbits32 sigMean;
|
|
|
+
|
|
|
+ aSig = extractFloat32Frac( a );
|
|
|
+ aExp = extractFloat32Exp( a );
|
|
|
+ aSign = extractFloat32Sign( a );
|
|
|
+ bSig = extractFloat32Frac( b );
|
|
|
+ bExp = extractFloat32Exp( b );
|
|
|
+ bSign = extractFloat32Sign( b );
|
|
|
+ if ( aExp == 0xFF ) {
|
|
|
+ if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) {
|
|
|
+ return propagateFloat32NaN( a, b );
|
|
|
+ }
|
|
|
+ roundData->exception |= float_flag_invalid;
|
|
|
+ return float32_default_nan;
|
|
|
+ }
|
|
|
+ if ( bExp == 0xFF ) {
|
|
|
+ if ( bSig ) return propagateFloat32NaN( a, b );
|
|
|
+ return a;
|
|
|
+ }
|
|
|
+ if ( bExp == 0 ) {
|
|
|
+ if ( bSig == 0 ) {
|
|
|
+ roundData->exception |= float_flag_invalid;
|
|
|
+ return float32_default_nan;
|
|
|
+ }
|
|
|
+ normalizeFloat32Subnormal( bSig, &bExp, &bSig );
|
|
|
+ }
|
|
|
+ if ( aExp == 0 ) {
|
|
|
+ if ( aSig == 0 ) return a;
|
|
|
+ normalizeFloat32Subnormal( aSig, &aExp, &aSig );
|
|
|
+ }
|
|
|
+ expDiff = aExp - bExp;
|
|
|
+ aSig |= 0x00800000;
|
|
|
+ bSig |= 0x00800000;
|
|
|
+ if ( expDiff < 32 ) {
|
|
|
+ aSig <<= 8;
|
|
|
+ bSig <<= 8;
|
|
|
+ if ( expDiff < 0 ) {
|
|
|
+ if ( expDiff < -1 ) return a;
|
|
|
+ aSig >>= 1;
|
|
|
+ }
|
|
|
+ q = ( bSig <= aSig );
|
|
|
+ if ( q ) aSig -= bSig;
|
|
|
+ if ( 0 < expDiff ) {
|
|
|
+ bits64 tmp = ( (bits64) aSig )<<32;
|
|
|
+ do_div( tmp, bSig );
|
|
|
+ q = tmp;
|
|
|
+ q >>= 32 - expDiff;
|
|
|
+ bSig >>= 2;
|
|
|
+ aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ aSig >>= 2;
|
|
|
+ bSig >>= 2;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if ( bSig <= aSig ) aSig -= bSig;
|
|
|
+ aSig64 = ( (bits64) aSig )<<40;
|
|
|
+ bSig64 = ( (bits64) bSig )<<40;
|
|
|
+ expDiff -= 64;
|
|
|
+ while ( 0 < expDiff ) {
|
|
|
+ q64 = estimateDiv128To64( aSig64, 0, bSig64 );
|
|
|
+ q64 = ( 2 < q64 ) ? q64 - 2 : 0;
|
|
|
+ aSig64 = - ( ( bSig * q64 )<<38 );
|
|
|
+ expDiff -= 62;
|
|
|
+ }
|
|
|
+ expDiff += 64;
|
|
|
+ q64 = estimateDiv128To64( aSig64, 0, bSig64 );
|
|
|
+ q64 = ( 2 < q64 ) ? q64 - 2 : 0;
|
|
|
+ q = q64>>( 64 - expDiff );
|
|
|
+ bSig <<= 6;
|
|
|
+ aSig = ( ( aSig64>>33 )<<( expDiff - 1 ) ) - bSig * q;
|
|
|
+ }
|
|
|
+ do {
|
|
|
+ alternateASig = aSig;
|
|
|
+ ++q;
|
|
|
+ aSig -= bSig;
|
|
|
+ } while ( 0 <= (sbits32) aSig );
|
|
|
+ sigMean = aSig + alternateASig;
|