/**************** ** denormalize ** ***************** ** Denormalize an internal-representation number. This means ** shifting it right until its exponent is equivalent to ** minimum_exponent. (You have to do this often in order ** to perform additions and subtractions). */ static void denormalize(InternalFPF *ptr, int minimum_exponent) { long exponent_difference; if (IsMantissaZero(ptr->mantissa)) { printf("Error: zero significand in denormalize\n"); } exponent_difference = ptr->exp-minimum_exponent; if (exponent_difference < 0) { /* ** The number is subnormal */ exponent_difference = -exponent_difference; if (exponent_difference >= (INTERNAL_FPF_PRECISION * 16)) { /* Underflow */ SetInternalFPFZero(ptr, ptr->sign); } else { ptr->exp+=exponent_difference; StickyShiftRightMant(ptr, exponent_difference); } } return; }
void denormalize(InternalFPF *ptr) { SetInternalFPFZero(ptr); }
/********************** ** DivideInternalFPF ** *********************** ** Divide internal FPF number x by y. Return result in z. */ static void DivideInternalFPF(InternalFPF *x, InternalFPF *y, InternalFPF *z) { int i; int j; u16 carry; u16 extra_bits[INTERNAL_FPF_PRECISION]; InternalFPF locx; /* Local for x number */ /* ** As with preceding function, the following switch ** statement selects among the various possible ** operands. */ switch ((x->type * IFPF_TYPE_COUNT) + y->type) { case ZERO_ZERO: case INFINITY_INFINITY: SetInternalFPFNaN(z); break; case ZERO_SUBNORMAL: case ZERO_NORMAL: if (IsMantissaZero(y->mantissa)) { SetInternalFPFNaN(z); break; } case ZERO_INFINITY: case SUBNORMAL_INFINITY: case NORMAL_INFINITY: SetInternalFPFZero(z, x->sign ^ y->sign); break; case SUBNORMAL_ZERO: case NORMAL_ZERO: if (IsMantissaZero(x->mantissa)) { SetInternalFPFNaN(z); break; } case INFINITY_ZERO: case INFINITY_SUBNORMAL: case INFINITY_NORMAL: SetInternalFPFInfinity(z, 0); z->sign = x->sign ^ y->sign; 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 NORMAL_SUBNORMAL: case SUBNORMAL_NORMAL: case NORMAL_NORMAL: /* ** Make local copy of x number, since we'll be ** altering it in the process of dividing. */ memmove((void *)&locx,(void *)x,sizeof(InternalFPF)); /* ** Check for unnormal zero arguments */ if (IsMantissaZero(locx.mantissa)) { if (IsMantissaZero(y->mantissa)) SetInternalFPFNaN(z); else SetInternalFPFZero(z, 0); break; } if (IsMantissaZero(y->mantissa)) { SetInternalFPFInfinity(z, 0); break; } /* ** Initialize the result */ z->type = x->type; z->sign = x->sign ^ y->sign; z->exp = x->exp - y->exp + ((INTERNAL_FPF_PRECISION * 16 * 2)); for (i=0; i<INTERNAL_FPF_PRECISION; i++) { z->mantissa[i] = 0; extra_bits[i] = 0; } while ((z->mantissa[0] & 0x8000) == 0) { carry = 0; ShiftMantLeft1(&carry, locx.mantissa); ShiftMantLeft1(&carry, extra_bits); /* ** Time to subtract yet? */ if (carry == 0) for (j=0; j<INTERNAL_FPF_PRECISION; j++) { if (y->mantissa[j] > extra_bits[j]) { carry = 0; goto no_subtract; } if (y->mantissa[j] < extra_bits[j]) break; } /* ** Divisor (y) <= dividend (x), subtract */ carry = 0; for (j=(INTERNAL_FPF_PRECISION-1); j>=0; j--) Sub16Bits(&carry, &extra_bits[j], extra_bits[j], y->mantissa[j]); carry = 1; /* 1 shifted into quotient */ no_subtract: ShiftMantLeft1(&carry, z->mantissa); z->exp--; } break; case NAN_NAN: choose_nan(x, y, z, 0); break; } /* ** Math complete...do rounding */ RoundInternalFPF(z); }