ieee754.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 650 行 · 第 1/2 页
C
650 行
cfloat *IEEECFToCF
/****************/
( cfloat *cf
, CF_PRECISION prec )
{
cfloat *new_cf = IEEECheckRange( cf, prec );
if( new_cf == cf ) {
new_cf = IEEECFToCFNotSpecial( cf, prec );
}
return( new_cf );
}
cfloat * IEEECFDiv
/****************/
( cfloat *left
, cfloat *right
, CF_PRECISION prec )
{
cfloat *new_val;
if( IEEEIsSpecialValue( left ) || IEEEIsSpecialValue( right ) ) {
// at least one is Nan, PosInf, or NegInf
if( left == IEEEGetNaN() || right == IEEEGetNaN() ) {
return IEEEGetNaN(); // NaN / float = float / NaN = NaN
} else {
// if neither was NaN, at least one must be inf
cfloat *inf;
cfloat *other;
if( IEEEIsInf( left ) ) {
inf = left;
other = right;
} else {
DbgAssert( IEEEIsInf( right ) );
inf = right;
other = left;
}
if( IEEEIsInf( other ) ) {
return IEEEGetNaN(); // inf / inf = NaN
}
// only one infinity
if( left == inf ) {
// left is infinity, right is not
if( CFGetPosNeg( left ) * CFGetPosNeg( right ) < 0 ) {
return( IEEEGetNegInf() ); // inf / -ve or -inf / +ve = -inf
} else {
return( IEEEGetPosInf() ); // inf / +ve or -inf / -ve = +inf
}
} else {
DbgAssert( right == inf );
// right is infinity
if( CFGetPosNeg( left ) * CFGetPosNeg( right ) < 0 ) {
// -ve/inf or +ve/-inf = -0
return( CFNegate( CFCnvI32F( 0 ) ) );
} else {
return( CFCnvI32F( 0 ) ); // +ve/inf or -ve/-inf = 0
}
}
}
} else if( CFTest( right ) ) {
// right is not zero
if( CFTest( left ) ) {
// left is not zero
new_val = IEEECFToCF( CFDiv( left, right ), prec );
} else {
// left is zero (-0.0 or 0.0)
new_val = IEEECFToCF( CFCopy( left ), prec );
}
} else {
// right is zero
if( CFTest( left ) ) {
// left not zero
if( ( CFTest( left ) * CFGetZeroSign( right ) ) > 0 ) {
// zero or two positives: positive infinity
new_val = IEEEGetPosInf();
} else {
// one negative: negative infinity
new_val = IEEEGetNegInf();
}
} else {
// both are zero: NaN
new_val = IEEEGetNaN();
}
}
return( new_val );
}
cfloat * IEEECFMod // IEEE MODULUS
/****************/
( cfloat *left
, cfloat *right
, CF_PRECISION prec )
{
cfloat *retn = NULL;
if( IEEEIsSpecialValue( left ) || IEEEIsSpecialValue( right ) ) {
if( IEEEIsSpecialValue( left ) // NaN%float=inf%float=-inf%float=NaN
|| right == IEEEGetNaN() // float % NaN = Nan
|| CFTest( right ) == 0 ) { // float % 0 = Nan
retn = IEEEGetNaN();
} else if( IEEEIsInf( right ) ) {
// finite / inf = finite
retn = left;
}
} else if( CFTest( left ) == 0 ) {
retn = left; // 0 % finite = 0
} else if( CFTest( right ) == 0 ) {
// x % 0 = NaN
retn = IEEEGetNaN();
} else {
// left / right = result;
// left % right = ( left - (right * result ) );
cfloat *result;
result = CFTrunc( CFDiv( left, right ) );
retn = IEEECFToCF( CFSub( left, CFMul( right, result ) ), prec );
}
DbgAssert( retn != NULL );
return( retn );
}
cfloat * IEEECFMul // IEEE MULTIPLY
/****************/
( cfloat *left
, cfloat *right
, CF_PRECISION prec )
{
if( IEEEIsSpecialValue( left ) || IEEEIsSpecialValue( right ) ) {
// JLS 15.16.1
if( left == IEEEGetNaN() || right == IEEEGetNaN() ) {
return IEEEGetNaN(); // NaN * float = float* NaN = NaN
} else {
// if neither was NaN, at least one must be inf
cfloat *inf;
cfloat *other;
if( IEEEIsInf( left ) ) {
inf = left;
other = right;
} else {
DbgAssert( IEEEIsInf( right ) );
inf = right;
other = left;
}
if( CFGetSign( other ) == 0 ) {
return( IEEEGetNaN() ); // inf * zero = zero * inf = NaN
} else {
// num * inf = inf * num = inf
// sign of result is determined by signs of inf and num
if( ( CFGetSign( inf ) * CFGetSign( other ) ) > 0 ) {
return IEEEGetPosInf();
} else {
return IEEEGetNegInf();
}
}
}
} else {
return( IEEECFToCF( CFMul( left, right ), prec ) );
}
}
cfloat * IEEECFNegate
/*******************/
( cfloat *f
, CF_PRECISION prec )
{
if( f == PosInf ) {
return NegInf;
} else if( f == NegInf ) {
return PosInf;
} else if( f == NaN ) {
return f;
} else {
// CFNegate doesn't make a copy so we have to call CFCopyNegate
// as upper layers expect to be able to discard operands after
// result of operation is returned
return( CFCopyNegate( f ) );
}
}
cfloat * IEEECFAdd // IEEE ADDITION
/****************/
( cfloat *left
, cfloat *right
, CF_PRECISION prec )
{
cfloat *retn = NULL;
if( IEEEIsSpecialValue( left ) || IEEEIsSpecialValue( right ) ) {
// JLS 15.17.2
if( left == IEEEGetNaN() || right == IEEEGetNaN() ) {
retn = IEEEGetNaN(); // NaN + float = float + NaN = NaN
} else {
cfloat *inf;
cfloat *other;
// one or both are infinity;
if( IEEEIsInf( left ) ) {
inf = left;
other = right;
} else {
inf = right;
other = left;
}
if( IEEEIsInf( other ) ) {
// both are infinite
if( CFGetPosNeg( inf ) * CFGetPosNeg( other ) < 0 ) {
// inf + -inf = -inf + inf = NaN
retn = IEEEGetNaN();
} else {
// both inf, same sign:
// -inf + -inf = -inf
// inf + inf = inf
retn = left;
}
} else {
// one infinite, one finite
// float + inf = inf
retn = inf;
}
}
} else {
// not a special value
if( CFTest( left ) * CFTest( right ) == 0 ) {
// one or both is zero
if( CFTest( left ) != 0 ) {
retn = left; // float + 0 = float
} else if( CFTest( right ) != 0 ) {
retn = right; // 0 + float = float
} else {
//both zero
if( CFGetZeroSign( left ) * CFGetZeroSign( right ) < 0 ) {
// opposite sign, return +ve zero
if( CFGetZeroSign( left ) > 0 ) {
retn = left;
} else {
retn = right;
}
} else {
// same sign, return either
retn = left;
}
}
} else {
// neither is zero
retn = CFAdd( left, right );
if( CFTest( retn ) == 0 ) {
// a zero result should be +ve zero
CFSetZeroSign( retn, 1 );
} else {
retn = IEEECFToCF( retn, prec );
}
}
}
DbgAssert( retn != NULL );
return retn;
}
//---------------------- comparison functions ---------------------
static int compareInf
( cfloat *left
, cfloat *right )
{
if( left == right ) { // inf cmp inf or
return 0; // -inf cmp -inf
} else {
if( left == IEEEGetNegInf() ) { // -inf cmp num or
return( -1 ); // -inf cmp inf
} else if( right == IEEEGetPosInf() ) { // num cmp inf or
return( -1 ); // -inf cmp inf
} else {
return( 1 ); // inf cmp num
// num cmp -inf
}
}
}
cf_bool IEEECFCmp // IEEE COMPARISON
/***************/
( cfloat *left
, cfloat *right
, CF_COMPARE cmp )
{
cf_bool retn = -2;
int result;
if( IEEEIsSpecialValue( left ) || IEEEIsSpecialValue( right ) ) {
if( left == IEEEGetNaN() || right == IEEEGetNaN() ) {
if( cmp == CF_CMP_NE ) { // val != NaN = val != NaN = true
return( CF_TRUE ); // n.b. NaN != NaN = true
} else {
// at least one NaN
return( CF_FALSE );
}
} else {
// at least one must be infinite
result = compareInf( left, right );
}
} else {
result = CFCompare( left, right );
}
DbgAssert( result == -1 || result == 1 || result == 0 );
switch( cmp ) {
case CF_CMP_NONE :
DbgNever();
break;
case CF_CMP_LT :
retn = ( result < 0 );
break;
case CF_CMP_LE :
retn = ( result <= 0 );
break;
case CF_CMP_GT :
retn = ( result > 0 );
break;
case CF_CMP_GE :
retn = ( result >= 0 );
break;
case CF_CMP_EQ :
retn = ( result == 0 );
break;
case CF_CMP_NE :
retn = ( result != 0 );
break;
}
return( retn );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?