emfloat.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,275 行 · 第 1/3 页
C
1,275 行
{
denormalize(ptr, MIN_EXP);
if (ptr->type != IFPF_IS_ZERO)
{
/* clear the extraneous bits */
ptr->mantissa[3] &= 0xfff8;
/* for (i=4; i<INTERNAL_FPF_PRECISION; i++)
{
ptr->mantissa[i] = 0;
}
*/
/*
** Check for overflow
*/
if ((unsigned)ptr->exp > MAX_EXP)
{
SetInternalFPFInfinity(ptr, ptr->sign);
}
}
}
return;
}
/*******************************************************
** ARITHMETIC OPERATIONS ON INTERNAL REPRESENTATION **
*******************************************************/
/***************
** choose_nan **
****************
** Called by routines that are forced to perform math on
** a pair of NaN's. This routine "selects" which NaN is
** to be returned.
*/
static void choose_nan(InternalFPF *x,
InternalFPF *y,
InternalFPF *z,
int intel_flag)
{
int i;
/*
** Compare the two mantissas,
** return the larger. Note that we will be emulating
** an 80387 in this operation.
*/
for (i=0; i<INTERNAL_FPF_PRECISION; i++)
{
if (x->mantissa[i] > y->mantissa[i])
{
memmove((void *)x,(void *)z,sizeof(InternalFPF));
return;
}
if (x->mantissa[i] < y->mantissa[i])
{
memmove((void *)y,(void *)z,sizeof(InternalFPF));
return;
}
}
/*
** They are equal
*/
if (!intel_flag)
/* if the operation is addition */
memmove((void *)x,(void *)z,sizeof(InternalFPF));
else
/* if the operation is multiplication */
memmove((void *)y,(void *)z,sizeof(InternalFPF));
return;
}
/**********************
** AddSubInternalFPF **
***********************
** Adding or subtracting internal-representation numbers.
** Internal-representation numbers pointed to by x and y are
** added/subtracted and the result returned in z.
*/
static void AddSubInternalFPF(uchar operation,
InternalFPF *x,
InternalFPF *y,
InternalFPF *z)
{
int exponent_difference;
u16 borrow;
u16 carry;
int i;
InternalFPF locx,locy; /* Needed since we alter them */
/*
** Following big switch statement handles the
** various combinations of operand types.
*/
switch ((x->type * IFPF_TYPE_COUNT) + y->type)
{
case ZERO_ZERO:
memmove((void *)x,(void *)z,sizeof(InternalFPF));
if (x->sign ^ y->sign ^ operation)
{
z->sign = 0; /* positive */
}
break;
case NAN_ZERO:
case NAN_SUBNORMAL:
case NAN_NORMAL:
case NAN_INFINITY:
case SUBNORMAL_ZERO:
case NORMAL_ZERO:
case INFINITY_ZERO:
case INFINITY_SUBNORMAL:
case INFINITY_NORMAL:
memmove((void *)x,(void *)z,sizeof(InternalFPF));
break;
case ZERO_NAN:
case SUBNORMAL_NAN:
case NORMAL_NAN:
case INFINITY_NAN:
memmove((void *)y,(void *)z,sizeof(InternalFPF));
break;
case ZERO_SUBNORMAL:
case ZERO_NORMAL:
case ZERO_INFINITY:
case SUBNORMAL_INFINITY:
case NORMAL_INFINITY:
memmove((void *)y,(void *)z,sizeof(InternalFPF));
z->sign ^= operation;
break;
case SUBNORMAL_SUBNORMAL:
case SUBNORMAL_NORMAL:
case NORMAL_SUBNORMAL:
case NORMAL_NORMAL:
/*
** Copy x and y to locals, since we may have
** to alter them.
*/
memmove((void *)&locx,(void *)x,sizeof(InternalFPF));
memmove((void *)&locy,(void *)y,sizeof(InternalFPF));
/* compute sum/difference */
exponent_difference = locx.exp-locy.exp;
if (exponent_difference == 0)
{
/*
** locx.exp == locy.exp
** so, no shifting required
*/
if (locx.type == IFPF_IS_SUBNORMAL ||
locy.type == IFPF_IS_SUBNORMAL)
z->type = IFPF_IS_SUBNORMAL;
else
z->type = IFPF_IS_NORMAL;
/*
** Assume that locx.mantissa > locy.mantissa
*/
z->sign = locx.sign;
z->exp= locx.exp;
}
else
if (exponent_difference > 0)
{
/*
** locx.exp > locy.exp
*/
StickyShiftRightMant(&locy,
exponent_difference);
z->type = locx.type;
z->sign = locx.sign;
z->exp = locx.exp;
}
else /* if (exponent_difference < 0) */
{
/*
** locx.exp < locy.exp
*/
StickyShiftRightMant(&locx,
-exponent_difference);
z->type = locy.type;
z->sign = locy.sign ^ operation;
z->exp = locy.exp;
}
if (locx.sign ^ locy.sign ^ operation)
{
/*
** Signs are different, subtract mantissas
*/
borrow = 0;
for (i=(INTERNAL_FPF_PRECISION-1); i>=0; i--)
Sub16Bits(&borrow,
&z->mantissa[i],
locx.mantissa[i],
locy.mantissa[i]);
if (borrow)
{
/* The y->mantissa was larger than the
** x->mantissa leaving a negative
** result. Change the result back to
** an unsigned number and flip the
** sign flag.
*/
z->sign = locy.sign ^ operation;
borrow = 0;
for (i=(INTERNAL_FPF_PRECISION-1); i>=0; i--)
{
Sub16Bits(&borrow,
&z->mantissa[i],
0,
z->mantissa[i]);
}
}
else
{
/* The assumption made above
** (i.e. x->mantissa >= y->mantissa)
** was correct. Therefore, do nothing.
** z->sign = x->sign;
*/
}
if (IsMantissaZero(z->mantissa))
{
z->type = IFPF_IS_ZERO;
z->sign = 0; /* positive */
}
else
if (locx.type == IFPF_IS_NORMAL ||
locy.type == IFPF_IS_NORMAL)
{
normalize(z);
}
}
else
{
/* signs are the same, add mantissas */
carry = 0;
for (i=(INTERNAL_FPF_PRECISION-1); i>=0; i--)
{
Add16Bits(&carry,
&z->mantissa[i],
locx.mantissa[i],
locy.mantissa[i]);
}
if (carry)
{
z->exp++;
carry=0;
ShiftMantRight1(&carry,z->mantissa);
z->mantissa[0] |= 0x8000;
z->type = IFPF_IS_NORMAL;
}
else
if (z->mantissa[0] & 0x8000)
z->type = IFPF_IS_NORMAL;
}
break;
case INFINITY_INFINITY:
SetInternalFPFNaN(z);
break;
case NAN_NAN:
choose_nan(x, y, z, 1);
break;
}
/*
** All the math is done; time to round.
*/
RoundInternalFPF(z);
return;
}
/************************
** MultiplyInternalFPF **
*************************
** Two internal-representation numbers x and y are multiplied; the
** result is returned in z.
*/
static void MultiplyInternalFPF(InternalFPF *x,
InternalFPF *y,
InternalFPF *z)
{
int i;
int j;
u16 carry;
u16 extra_bits[INTERNAL_FPF_PRECISION];
InternalFPF locy; /* Needed since this will be altered */
/*
** As in the preceding function, this large switch
** statement selects among the many combinations
** of operands.
*/
switch ((x->type * IFPF_TYPE_COUNT) + y->type)
{
case INFINITY_SUBNORMAL:
case INFINITY_NORMAL:
case INFINITY_INFINITY:
case ZERO_ZERO:
case ZERO_SUBNORMAL:
case ZERO_NORMAL:
memmove((void *)x,(void *)z,sizeof(InternalFPF));
z->sign ^= y->sign;
break;
case SUBNORMAL_INFINITY:
case NORMAL_INFINITY:
case SUBNORMAL_ZERO:
case NORMAL_ZERO:
memmove((void *)y,(void *)z,sizeof(InternalFPF));
z->sign ^= x->sign;
break;
case ZERO_INFINITY:
case INFINITY_ZERO:
SetInternalFPFNaN(z);
break;
case NAN_ZERO:
case NAN_SUBNORMAL:
case NAN_NORMAL:
case NAN_INFINITY:
memmove((void *)x,(void *)z,sizeof(InternalFPF));
break;
case ZERO_NAN:
case SUBNORMAL_NAN:
case NORMAL_NAN:
case INFINITY_NAN:
memmove((void *)y,(void *)z,sizeof(InternalFPF));
break;
case SUBNORMAL_SUBNORMAL:
case SUBNORMAL_NORMAL:
case NORMAL_SUBNORMAL:
case NORMAL_NORMAL:
/*
** Make a local copy of the y number, since we will be
** altering it in the process of multiplying.
*/
memmove((void *)&locy,(void *)y,sizeof(InternalFPF));
/*
** Check for unnormal zero arguments
*/
if (IsMantissaZero(x->mantissa) || IsMantissaZero(y->mantissa))
SetInternalFPFInfinity(z, 0);
/*
** Initialize the result
*/
if (x->type == IFPF_IS_SUBNORMAL ||
y->type == IFPF_IS_SUBNORMAL)
z->type = IFPF_IS_SUBNORMAL;
else
z->type = IFPF_IS_NORMAL;
z->sign = x->sign ^ y->sign;
z->exp = x->exp + y->exp ;
for (i=0; i<INTERNAL_FPF_PRECISION; i++)
{
z->mantissa[i] = 0;
extra_bits[i] = 0;
}
for (i=0; i<(INTERNAL_FPF_PRECISION*16); i++)
{
/*
** Get rightmost bit of the multiplier
*/
carry = 0;
ShiftMantRight1(&carry, locy.mantissa);
if (carry)
{
/*
** Add the multiplicand to the product
*/
carry = 0;
for (j=(INTERNAL_FPF_PRECISION-1); j>=0; j--)
Add16Bits(&carry,
&z->mantissa[j],
z->mantissa[j],
x->mantissa[j]);
}
else
{
carry = 0;
}
/*
** Shift the product right. Overflow bits get
** shifted into extra_bits. We'll use it later
** to help with the "sticky" bit.
*/
ShiftMantRight1(&carry, z->mantissa);
ShiftMantRight1(&carry, extra_bits);
}
/*
** Normalize
** Note that we use a "special" normalization routine
** because we need to use the extra bits. (These are
** bits that may have been shifted off the bottom that
** we want to reclaim...if we can.
*/
while ((z->mantissa[0] & 0x8000) == 0)
{
carry = 0;
ShiftMantLeft1(&carry, extra_bits);
ShiftMantLeft1(&carry, z->mantissa);
z->exp--;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?