fpc.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,417 行 · 第 1/3 页
C
1,417 行
if( isDstNeg ) fneg( dst, dst );
} else if( f_isZero( src1 ) && f_isZero( src2 ) ) {
*(uint32*)dst = FLOAT_NAN;
} else if( f_isZero( src1 ) ) {
*(uint32*)dst = FLOAT_POS_ZERO;
if( isDstNeg ) fneg( dst, dst );
} else if( f_isZero( src2 ) ) {
*(uint32*)dst = FLOAT_POS_INF;
if( isDstNeg ) fneg( dst, dst );
} else {
parseFloat( *(float*)src1, &f1, &e1 );
parseFloat( *(float*)src2, &f2, &e2 );
mp_init( &num1, f1 );
mp_init( &num2, f2 );
mp_init( &rem, 0 );
if( mp_lt( &num1, &num2 ) ) {
adjust = 1;
e1--;
}
newexp = e1 - e2 + float_bias;
if( newexp <= 0 && newexp > -23 ) {
mp_shiftleft( &num1, &num1, 22 + newexp + adjust );
} else {
mp_shiftleft( &num1, &num1, 23 + adjust );
}
mp_div( &num1, &rem, &num1, &num2 );
mp_mulsc( &rem, &rem, 2 );
rc = mp_cmp( &rem, &num2 );
if( (rc == 0 && (rem.num[0] & 2)) || rc == -1 ) {
/* round up */
mp_addsc( &num1, &num1, 1 );
}
if( newexp <= 0 && newexp > -23 ) {
/* denormalized result */
uint64 temp;
mp_touint64( &temp, &num1 );
makeFloat( dst, temp, 0 - float_bias );
} else {
mp_tofloat( dst, &num1 );
changeFloatExponent( dst, dst, e1 - e2 - 23 );
}
if( isDstNeg ) fneg( dst, dst );
mp_free( &num1 );
mp_free( &num2 );
mp_free( &rem );
}
}
void frem( void *dst, void *src1, void *src2 ) {
uint64 f1, f2;
int e1, e2;
mpnum num1, num2, zero;
int emin;
int newexp;
/* special cases */
if( f_isNan( src1 ) || f_isNan( src2 ) ) {
*(uint32*)dst = FLOAT_NAN;
} else if( f_isInf( src1 ) || f_isZero( src2 ) ) {
*(uint32*)dst = FLOAT_NAN;
} else if( f_isZero( src1 ) || f_isInf( src2 ) ) {
*(uint32*)dst = *(uint32*)src1;
} else {
parseFloat( *(float*)src1, &f1, &e1 );
parseFloat( *(float*)src2, &f2, &e2 );
mp_init( &num1, f1 );
mp_init( &num2, f2 );
mp_init( &zero, 0 );
emin = min( e1, e2 );
if( e2 > e1 ) {
mp_shiftleft( &num2, &num2, e2 - e1 );
} else {
mp_shiftleft( &num1, &num1, e1 - e2 );
}
mp_div( &num1, &num2, &num1, &num2 ); /* num2 will get the remainder */
if( mp_eq( &num2, &zero ) ) {
*(uint32*)dst = FLOAT_POS_ZERO;
} else {
newexp = emin - 24 + mp_bitsize( &num2 ) + float_bias;
if( newexp <= 0 && newexp > -24 ) {
/* denormalized result */
uint64 temp;
mp_binround( &num2, &num2, -newexp + 1 );
mp_shiftright( &num2, &num2, -newexp + 1 );
mp_touint64( &temp, &num2 );
makeFloat( dst, temp, 0 - float_bias );
} else {
mp_tofloat( dst, &num2 );
changeFloatExponent( dst, dst, emin - 23 );
}
}
if( f_isNeg( src1 ) ) fneg( dst, dst );
mp_free( &num1 );
mp_free( &num2 );
mp_free( &zero );
}
}
void fneg( void *dst, void *src ) {
memcpy( dst, src, 4 );
if( !d_isNan( dst ) ) {
((char*)dst)[3] ^= 128;
}
}
void eadd( void *dst, void *src1, void *src2 ) {
uint64 f1, f2;
int e1, e2;
int diff;
int emax, emin;
mpnum num1, num2, zero;
int isNeg1 = e_isNeg( src1 );
int isNeg2 = e_isNeg( src2 );
int isNeg;
int newexp;
/* special cases */
if( e_isNan( src1 ) || e_isNan( src2 ) ) {
makeExtNan( dst );
} else if( e_isPosInf( src1 ) && e_isNegInf( src2 ) ) {
makeExtNan( dst );
} else if( e_isNegInf( src1 ) && e_isPosInf( src2 ) ) {
makeExtNan( dst );
} else if( e_isPosInf( src1 ) || e_isPosInf( src2 ) ) {
makeExtPosInf( dst );
} else if( e_isNegInf( src1 ) || e_isNegInf( src2 ) ) {
makeExtNegInf( dst );
} else if( e_isPosZero( src1 ) && e_isNegZero( src2 ) ) {
makeExtPosZero( dst );
} else if( e_isNegZero( src1 ) && e_isPosZero( src2 ) ) {
makeExtPosZero( dst );
} else if( e_isPosZero( src1 ) && e_isPosZero( src2 ) ) {
makeExtPosZero( dst );
} else if( e_isNegZero( src1 ) && e_isNegZero( src2 ) ) {
makeExtNegZero( dst );
} else if( e_isZero( src1 ) ) {
memcpy( dst, src2, 10 );
} else if( e_isZero( src2 ) ) {
memcpy( dst, src1, 10 );
} else {
parseExtended( (char*)src1, &f1, &e1 );
parseExtended( (char*)src2, &f2, &e2 );
diff = abs( (e1 - e2) );
emax = max( e1, e2 );
emin = min( e1, e2 );
mp_init( &num1, f1 );
mp_init( &num2, f2 );
mp_init( &zero, 0 );
if( e1 > e2 ) {
mp_shiftleft( &num1, &num1, (uint64)diff );
} else if( e2 > e1 ) {
mp_shiftleft( &num2, &num2, (uint64)diff );
}
if( (isNeg1 && isNeg2) || (!isNeg1 && !isNeg2 ) ) {
mp_add( &num1, &num1, &num2 );
if( isNeg1 ) isNeg = TRUE;
} else {
if( mp_gt( &num1, &num2 ) ) {
mp_sub( &num1, &num1, &num2 );
if( isNeg1 ) isNeg = TRUE;
} else {
mp_sub( &num1, &num2, &num1 );
if( isNeg2 ) isNeg = TRUE;
}
}
if( mp_eq( &num1, &zero ) ) {
makeExtPosZero( dst );
} else {
newexp = emax - diff - 64 + mp_bitsize( &num1 ) + extended_bias;
if( newexp <= 0 && newexp > -64 ) {
/* denormalized result */
uint64 temp;
mp_binround( &num1, &num1, -(emin + extended_bias) + 1 );
mp_shiftright( &num1, &num1, -(emin + extended_bias) + 1 );
mp_touint64( &temp, &num1 );
makeExtended( dst, temp, 0 - extended_bias );
} else {
mp_toextended( dst, &num1 );
changeExtendedExponent( dst, dst, emax - diff - 63 );
}
if( isNeg ) eneg( dst, dst );
}
mp_free( &num1 );
mp_free( &num2 );
mp_free( &zero );
}
}
void esub( void *dst, void *src1, void *src2 ) {
char nsrc2[10];
eneg( &nsrc2, src2 );
eadd( dst, src1, &nsrc2 );
}
void emul( void *dst, void *src1, void *src2 ) {
uint64 f1, f2;
int e1, e2;
mpnum num1, num2;
int isNeg1 = e_isNeg( src1 );
int isNeg2 = e_isNeg( src2 );
int isDstNeg = (isNeg1 && !isNeg2) || (!isNeg1 && isNeg2);
int newexp;
/* special cases */
if( e_isNan( src1 ) || e_isNan( src2 ) ) {
makeExtNan( dst );
} else if( e_isInf( src1 ) && e_isZero( src2 ) ) {
makeExtNan( dst );
} else if( e_isZero( src1 ) && e_isInf( src2 ) ) {
makeExtNan( dst );
} else if( e_isInf( src1 ) ) {
makeExtPosInf( dst );
if( isDstNeg ) eneg( dst, dst );
} else if( e_isInf( src2 ) ) {
makeExtPosInf( dst );
if( isDstNeg ) eneg( dst, dst );
} else if( e_isZero( src1 ) || e_isZero( src2 ) ) {
makeExtPosZero( dst );
if( isDstNeg ) eneg( dst, dst );
} else {
parseExtended( (char*)src1, &f1, &e1 );
parseExtended( (char*)src2, &f2, &e2 );
mp_init( &num1, f1 );
mp_init( &num2, f2 );
mp_mul( &num1, &num1, &num2 );
newexp = e1 + e2 - 127 + mp_bitsize( &num1 ) + extended_bias;
if( newexp <= 0 && newexp > -64 ) {
/* denormalized result */
uint64 temp;
mp_binround( &num1, &num1, -newexp + 64 );
mp_shiftright( &num1, &num1, -newexp + 64 );
mp_touint64( &temp, &num1 );
makeExtended( dst, temp, 0 - extended_bias );
} else {
mp_toextended( dst, &num1 );
changeExtendedExponent( dst, dst, e1 + e2 - 126 );
}
if( isDstNeg ) eneg( dst, dst );
mp_free( &num1 );
mp_free( &num2 );
}
}
void ediv( void *dst, void *src1, void *src2 ) {
uint64 f1, f2;
int e1, e2;
mpnum num1, num2, rem;
int isNeg1 = e_isNeg( src1 );
int isNeg2 = e_isNeg( src2 );
int isDstNeg = (isNeg1 && !isNeg2) || (!isNeg1 && isNeg2);
int newexp, rc;
int adjust = 0;
/* special cases */
if( e_isNan( src1 ) || e_isNan( src2 ) ) {
makeExtNan( dst );
} else if( e_isInf( src1 ) && e_isInf( src2 ) ) {
makeExtNan( dst );
} else if( e_isInf( src1 ) ) {
makeExtPosInf( dst );
if( isDstNeg ) eneg( dst, dst );
} else if( e_isInf( src2 ) ) {
makeExtPosZero( dst );
if( isDstNeg ) eneg( dst, dst );
} else if( e_isZero( src1 ) && e_isZero( src2 ) ) {
makeExtNan( dst );
} else if( e_isZero( src1 ) ) {
makeExtPosZero( dst );
if( isDstNeg ) eneg( dst, dst );
} else if( e_isZero( src2 ) ) {
makeExtPosInf( dst );
if( isDstNeg ) eneg( dst, dst );
} else {
parseExtended( (char*)src1, &f1, &e1 );
parseExtended( (char*)src2, &f2, &e2 );
mp_init( &num1, f1 );
mp_init( &num2, f2 );
mp_init( &rem, 0 );
if( mp_lt( &num1, &num2 ) ) {
adjust = 1;
e1--;
}
newexp = e1 - e2 + extended_bias;
if( newexp <= 0 && newexp > -63 ) {
mp_shiftleft( &num1, &num1, 62 + newexp + adjust );
} else {
mp_shiftleft( &num1, &num1, 63 + adjust );
}
mp_div( &num1, &rem, &num1, &num2 );
mp_mulsc( &rem, &rem, 2 );
rc = mp_cmp( &rem, &num2 );
if( (rc == 0 && (rem.num[0] & 2)) || rc == -1 ) {
/* round up */
mp_addsc( &num1, &num1, 1 );
}
if( newexp <= 0 && newexp > -63 ) {
/* denormalized result */
uint64 temp;
mp_touint64( &temp, &num1 );
makeExtended( dst, temp, 0 - extended_bias );
} else {
mp_toextended( dst, &num1 );
changeExtendedExponent( dst, dst, e1 - e2 - 63 );
}
if( isDstNeg ) eneg( dst, dst );
mp_free( &num1 );
mp_free( &num2 );
mp_free( &rem );
}
}
void erem( void *dst, void *src1, void *src2 ) {
uint64 f1, f2;
int e1, e2;
mpnum num1, num2, zero;
int emin;
int newexp;
/* special cases */
if( e_isNan( src1 ) || e_isNan( src2 ) ) {
makeExtNan( dst );
} else if( e_isInf( src1 ) || e_isZero( src2 ) ) {
makeExtNan( dst );
} else if( e_isZero( src1 ) || e_isInf( src2 ) ) {
memcpy( dst, src1, 10 );
} else {
parseExtended( (char*)src1, &f1, &e1 );
parseExtended( (char*)src2, &f2, &e2 );
mp_init( &num1, f1 );
mp_init( &num2, f2 );
mp_init( &zero, 0 );
emin = min( e1, e2 );
if( e2 > e1 ) {
mp_shiftleft( &num2, &num2, e2 - e1 );
} else {
mp_shiftleft( &num1, &num1, e1 - e2 );
}
mp_div( &num1, &num2, &num1, &num2 ); /* num2 will get the remainder */
if( mp_eq( &num2, &zero ) ) {
makeExtPosZero( dst );
} else {
newexp = emin - 64 + mp_bitsize( &num2 ) + extended_bias;
if( newexp <= 0 && newexp >= -64 ) {
/* denormalized result */
uint64 temp;
mp_binround( &num2, &num2, -newexp + 1 );
mp_shiftright( &num2, &num2, -newexp + 1 );
mp_touint64( &temp, &num2 );
makeExtended( dst, temp, 0 - extended_bias );
} else {
mp_toextended( dst, &num2 );
changeExtendedExponent( dst, dst, emin - 63 );
}
}
if( e_isNeg( src1 ) ) eneg( dst, dst );
mp_free( &num1 );
mp_free( &num2 );
mp_free( &zero );
}
}
void eneg( void *dst, void *src ) {
memcpy( dst, src, 10 );
if( !d_isNan( dst ) ) {
((char*)dst)[9] ^= 128;
}
}
void f2d( void *dst, void *src )
{
uint64 f;
int e;
if( f_isNan( src ) ) {
*(uint64*)dst = DOUBLE_NAN;
} else if( f_isPosInf( src ) ) {
*(uint64*)dst = DOUBLE_POS_INF;
} else if( f_isNegInf( src ) ) {
*(uint64*)dst = DOUBLE_NEG_INF;
} else if( f_isPosZero( src ) ) {
*(uint64*)dst = DOUBLE_POS_ZERO;
} else if( f_isNegZero( src ) ) {
*(uint64*)dst = DOUBLE_NEG_ZERO;
} else {
parseFloat( *(float*)src, &f, &e );
f <<= 29;
makeDouble( (double*)dst, f, e );
if( f_isNeg( src ) ) {
dneg( dst, dst );
}
}
}
void d2f( void *dst, void *src ) {
uint64 f;
int e;
mpnum temp;
if( d_isNan( src ) ) {
*(uint32*)dst = FLOAT_NAN;
} else if( d_isPosInf( src ) ) {
*(uint32*)dst = FLOAT_POS_INF;
} else if( d_isNegInf( src ) ) {
*(uint32*)dst = FLOAT_NEG_INF;
} else if( d_isPosZero( src ) ) {
*(uint32*)dst = FLOAT_POS_ZERO;
} else if( d_isNegZero( src ) ) {
*(uint32*)dst = FLOAT_NEG_ZERO;
} else {
parseDouble( *(double*)src, &f, &e );
mp_init( &temp, f );
if( e + float_bias <= 0 && e + float_bias > -24 ) {
mp_binround( &temp, &temp, 29 - (e + float_bias) + 1 );
mp_shiftright( &temp, &temp, 29 - (e + float_bias) + 1 );
} else {
mp_binround( &temp, &temp, 29 );
mp_shiftright( &temp, &temp, 29 );
}
mp_touint64( &f, &temp );
makeFloat( (float*)dst, f, e );
mp_free( &temp );
if( d_isNeg( src ) ) {
fneg( dst, dst );
}
}
}
void e2d( void *dst, void *src ) {
uint64 f;
int e;
mpnum temp;
if( e_isNan( src ) ) {
*(uint64*)dst = DOUBLE_NAN;
} else if( e_isPosInf( src ) ) {
*(uint64*)dst = DOUBLE_POS_INF;
} else if( e_isNegInf( src ) ) {
*(uint64*)dst = DOUBLE_NEG_INF;
} else if( e_isPosZero( src ) ) {
*(uint64*)dst = DOUBLE_POS_ZERO;
} else if( e_isNegZero( src ) ) {
*(uint64*)dst = DOUBLE_NEG_ZERO;
} else {
parseExtended( (char*)src, &f, &e );
mp_init( &temp, f );
if( e + double_bias <= 0 && e + double_bias > -53 ) {
mp_binround( &temp, &temp, 11 - (e + double_bias) + 1 );
mp_shiftright( &temp, &temp, 11 - (e + double_bias) + 1 );
} else {
mp_binround( &temp, &temp, 11 );
mp_shiftright( &temp, &temp, 11 );
}
mp_touint64( &f, &temp );
makeDouble( (double*)dst, f, e );
mp_free( &temp );
if( e_isNeg( src ) ) {
dneg( dst, dst );
}
}
}
void d2e( void *dst, void *src ) {
uint64 f;
int e;
if( d_isNan( src ) ) {
makeExtNan( dst );
} else if( d_isPosInf( src ) ) {
makeExtPosInf( dst );
} else if( d_isNegInf( src ) ) {
makeExtNegInf( dst );
} else if( d_isPosZero( src ) ) {
makeExtPosZero( dst );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?