struct fp_ext * fp_fsgldiv(struct fp_ext *dest, struct fp_ext *src) { int exp; unsigned long quot, rem; dprint(PINSTR, "fsgldiv\n"); fp_dyadic_check(dest, src); /* calculate the correct sign now, as it's necessary for infinities */ dest->sign = src->sign ^ dest->sign; /* Handle infinities */ if (IS_INF(dest)) { /* infinity / infinity = NaN (quiet, as always) */ if (IS_INF(src)) fp_set_nan(dest); /* infinity / anything else = infinity (with approprate sign) */ return dest; } if (IS_INF(src)) { /* anything / infinity = zero (with appropriate sign) */ dest->exp = 0; dest->mant.m64 = 0; dest->lowmant = 0; return dest; } /* zeroes */ if (IS_ZERO(dest)) { /* zero / zero = NaN */ if (IS_ZERO(src)) fp_set_nan(dest); /* zero / anything else = zero */ return dest; } if (IS_ZERO(src)) { /* anything / zero = infinity (with appropriate sign) */ fp_set_sr(FPSR_EXC_DZ); dest->exp = 0x7fff; dest->mant.m64 = 0; return dest; } exp = dest->exp - src->exp + 0x3fff; dest->mant.m32[0] &= 0xffffff00; src->mant.m32[0] &= 0xffffff00; /* do the 32-bit divide */ if (dest->mant.m32[0] >= src->mant.m32[0]) { fp_sub64(dest->mant, src->mant); fp_div64(quot, rem, dest->mant.m32[0], 0, src->mant.m32[0]); dest->mant.m32[0] = 0x80000000 | (quot >> 1); dest->mant.m32[1] = (quot & 1) | rem; /* only for rounding */ } else {
struct fp_ext * fp_fsgldiv(struct fp_ext *dest, struct fp_ext *src) { int exp; unsigned long quot, rem; dprint(PINSTR, "fsgldiv\n"); fp_dyadic_check(dest, src); /* */ dest->sign = src->sign ^ dest->sign; /* */ if (IS_INF(dest)) { /* */ if (IS_INF(src)) fp_set_nan(dest); /* */ return dest; } if (IS_INF(src)) { /* */ dest->exp = 0; dest->mant.m64 = 0; dest->lowmant = 0; return dest; } /* */ if (IS_ZERO(dest)) { /* */ if (IS_ZERO(src)) fp_set_nan(dest); /* */ return dest; } if (IS_ZERO(src)) { /* */ fp_set_sr(FPSR_EXC_DZ); dest->exp = 0x7fff; dest->mant.m64 = 0; return dest; } exp = dest->exp - src->exp + 0x3fff; dest->mant.m32[0] &= 0xffffff00; src->mant.m32[0] &= 0xffffff00; /* */ if (dest->mant.m32[0] >= src->mant.m32[0]) { fp_sub64(dest->mant, src->mant); fp_div64(quot, rem, dest->mant.m32[0], 0, src->mant.m32[0]); dest->mant.m32[0] = 0x80000000 | (quot >> 1); dest->mant.m32[1] = (quot & 1) | rem; /* */ } else {
struct fp_ext * fp_fsglmul(struct fp_ext *dest, struct fp_ext *src) { int exp; dprint(PINSTR, "fsglmul\n"); fp_dyadic_check(dest, src); /* calculate the correct sign now, as it's necessary for infinities */ dest->sign = src->sign ^ dest->sign; /* Handle infinities */ if (IS_INF(dest)) { if (IS_ZERO(src)) fp_set_nan(dest); return dest; } if (IS_INF(src)) { if (IS_ZERO(dest)) fp_set_nan(dest); else fp_copy_ext(dest, src); return dest; } /* Of course, as we all know, zero * anything = zero. You may not have known that it might be a positive or negative zero... */ if (IS_ZERO(dest) || IS_ZERO(src)) { dest->exp = 0; dest->mant.m64 = 0; dest->lowmant = 0; return dest; } exp = dest->exp + src->exp - 0x3ffe; /* do a 32-bit multiply */ fp_mul64(dest->mant.m32[0], dest->mant.m32[1], dest->mant.m32[0] & 0xffffff00, src->mant.m32[0] & 0xffffff00); if (exp >= 0x7fff) { fp_set_ovrflw(dest); return dest; } dest->exp = exp; if (exp < 0) { fp_set_sr(FPSR_EXC_UNFL); fp_denormalize(dest, -exp); } return dest; }
struct fp_ext * fp_fsglmul(struct fp_ext *dest, struct fp_ext *src) { int exp; dprint(PINSTR, "fsglmul\n"); fp_dyadic_check(dest, src); /* */ dest->sign = src->sign ^ dest->sign; /* */ if (IS_INF(dest)) { if (IS_ZERO(src)) fp_set_nan(dest); return dest; } if (IS_INF(src)) { if (IS_ZERO(dest)) fp_set_nan(dest); else fp_copy_ext(dest, src); return dest; } /* */ if (IS_ZERO(dest) || IS_ZERO(src)) { dest->exp = 0; dest->mant.m64 = 0; dest->lowmant = 0; return dest; } exp = dest->exp + src->exp - 0x3ffe; /* */ fp_mul64(dest->mant.m32[0], dest->mant.m32[1], dest->mant.m32[0] & 0xffffff00, src->mant.m32[0] & 0xffffff00); if (exp >= 0x7fff) { fp_set_ovrflw(dest); return dest; } dest->exp = exp; if (exp < 0) { fp_set_sr(FPSR_EXC_UNFL); fp_denormalize(dest, -exp); } return dest; }
struct fp_ext * fp_fadd(struct fp_ext *dest, struct fp_ext *src) { int diff; dprint(PINSTR, "fadd\n"); fp_dyadic_check(dest, src); if (IS_INF(dest)) { /* infinity - infinity == NaN */ if (IS_INF(src) && (src->sign != dest->sign)) fp_set_nan(dest); return dest; } if (IS_INF(src)) { fp_copy_ext(dest, src); return dest; } if (IS_ZERO(dest)) { if (IS_ZERO(src)) { if (src->sign != dest->sign) { if (FPDATA->rnd == FPCR_ROUND_RM) dest->sign = 1; else dest->sign = 0; } } else fp_copy_ext(dest, src); return dest; } dest->lowmant = src->lowmant = 0; if ((diff = dest->exp - src->exp) > 0) fp_denormalize(src, diff); else if ((diff = -diff) > 0) fp_denormalize(dest, diff); if (dest->sign == src->sign) { if (fp_addmant(dest, src)) if (!fp_addcarry(dest)) return dest; } else { if (dest->mant.m64 < src->mant.m64) { fp_submant(dest, src, dest); dest->sign = !dest->sign; } else fp_submant(dest, dest, src); } return dest; }
struct fp_ext * fp_fgetexp(struct fp_ext *dest, struct fp_ext *src) { dprint(PINSTR, "fgetexp\n"); fp_monadic_check(dest, src); if (IS_INF(dest)) { fp_set_nan(dest); return dest; } if (IS_ZERO(dest)) return dest; fp_conv_long2ext(dest, (int)dest->exp - 0x3FFF); fp_normalize_ext(dest); return dest; }
struct fp_ext * fp_fsqrt(struct fp_ext *dest, struct fp_ext *src) { struct fp_ext tmp, src2; int i, exp; dprint(PINSTR, "fsqrt\n"); fp_monadic_check(dest, src); if (IS_ZERO(dest)) return dest; if (dest->sign) { fp_set_nan(dest); return dest; } if (IS_INF(dest)) return dest; /* * sqrt(m) * 2^(p) , if e = 2*p * sqrt(m*2^e) = * sqrt(2*m) * 2^(p) , if e = 2*p + 1 * * So we use the last bit of the exponent to decide wether to * use the m or 2*m. * * Since only the fractional part of the mantissa is stored and * the integer part is assumed to be one, we place a 1 or 2 into * the fixed point representation. */ exp = dest->exp; dest->exp = 0x3FFF; if (!(exp & 1)) /* lowest bit of exponent is set */ dest->exp++; fp_copy_ext(&src2, dest); /* * The taylor row around a for sqrt(x) is: * sqrt(x) = sqrt(a) + 1/(2*sqrt(a))*(x-a) + R * With a=1 this gives: * sqrt(x) = 1 + 1/2*(x-1) * = 1/2*(1+x) */ fp_fadd(dest, &fp_one); dest->exp--; /* * 1/2 */ /* * We now apply the newton rule to the function * f(x) := x^2 - r * which has a null point on x = sqrt(r). * * It gives: * x' := x - f(x)/f'(x) * = x - (x^2 -r)/(2*x) * = x - (x - r/x)/2 * = (2*x - x + r/x)/2 * = (x + r/x)/2 */ for (i = 0; i < 9; i++) { fp_copy_ext(&tmp, &src2); fp_fdiv(&tmp, dest); fp_fadd(dest, &tmp); dest->exp--; } dest->exp += (exp - 0x3FFF) / 2; return dest; }
struct fp_ext * fp_fdiv(struct fp_ext *dest, struct fp_ext *src) { union fp_mant128 temp; int exp; dprint(PINSTR, "fdiv\n"); fp_dyadic_check(dest, src); /* calculate the correct sign now, as it's necessary for infinities */ dest->sign = src->sign ^ dest->sign; /* Handle infinities */ if (IS_INF(dest)) { /* infinity / infinity = NaN (quiet, as always) */ if (IS_INF(src)) fp_set_nan(dest); /* infinity / anything else = infinity (with approprate sign) */ return dest; } if (IS_INF(src)) { /* anything / infinity = zero (with appropriate sign) */ dest->exp = 0; dest->mant.m64 = 0; dest->lowmant = 0; return dest; } /* zeroes */ if (IS_ZERO(dest)) { /* zero / zero = NaN */ if (IS_ZERO(src)) fp_set_nan(dest); /* zero / anything else = zero */ return dest; } if (IS_ZERO(src)) { /* anything / zero = infinity (with appropriate sign) */ fp_set_sr(FPSR_EXC_DZ); dest->exp = 0x7fff; dest->mant.m64 = 0; return dest; } exp = dest->exp - src->exp + 0x3fff; /* shift up the mantissa for denormalized numbers, so that the highest bit is set, this makes lots of things below easier */ if ((long)dest->mant.m32[0] >= 0) exp -= fp_overnormalize(dest); if ((long)src->mant.m32[0] >= 0) exp -= fp_overnormalize(src); /* now, do the 64-bit divide */ fp_dividemant(&temp, dest, src); /* normalize it back to 64 bits and stuff it back into the destination struct */ if (!temp.m32[0]) { exp--; fp_putmant128(dest, &temp, 32); } else fp_putmant128(dest, &temp, 31); if (exp >= 0x7fff) { fp_set_ovrflw(dest); return dest; } dest->exp = exp; if (exp < 0) { fp_set_sr(FPSR_EXC_UNFL); fp_denormalize(dest, -exp); } return dest; }
struct fp_ext * fp_fmul(struct fp_ext *dest, struct fp_ext *src) { union fp_mant128 temp; int exp; dprint(PINSTR, "fmul\n"); fp_dyadic_check(dest, src); /* calculate the correct sign now, as it's necessary for infinities */ dest->sign = src->sign ^ dest->sign; /* Handle infinities */ if (IS_INF(dest)) { if (IS_ZERO(src)) fp_set_nan(dest); return dest; } if (IS_INF(src)) { if (IS_ZERO(dest)) fp_set_nan(dest); else fp_copy_ext(dest, src); return dest; } /* Of course, as we all know, zero * anything = zero. You may not have known that it might be a positive or negative zero... */ if (IS_ZERO(dest) || IS_ZERO(src)) { dest->exp = 0; dest->mant.m64 = 0; dest->lowmant = 0; return dest; } exp = dest->exp + src->exp - 0x3ffe; /* shift up the mantissa for denormalized numbers, so that the highest bit is set, this makes the shift of the result below easier */ if ((long)dest->mant.m32[0] >= 0) exp -= fp_overnormalize(dest); if ((long)src->mant.m32[0] >= 0) exp -= fp_overnormalize(src); /* now, do a 64-bit multiply with expansion */ fp_multiplymant(&temp, dest, src); /* normalize it back to 64 bits and stuff it back into the destination struct */ if ((long)temp.m32[0] > 0) { exp--; fp_putmant128(dest, &temp, 1); } else fp_putmant128(dest, &temp, 0); if (exp >= 0x7fff) { fp_set_ovrflw(dest); return dest; } dest->exp = exp; if (exp < 0) { fp_set_sr(FPSR_EXC_UNFL); fp_denormalize(dest, -exp); } return dest; }
struct fp_ext * fp_fdiv(struct fp_ext *dest, struct fp_ext *src) { union fp_mant128 temp; int exp; dprint(PINSTR, "fdiv\n"); fp_dyadic_check(dest, src); /* */ dest->sign = src->sign ^ dest->sign; /* */ if (IS_INF(dest)) { /* */ if (IS_INF(src)) fp_set_nan(dest); /* */ return dest; } if (IS_INF(src)) { /* */ dest->exp = 0; dest->mant.m64 = 0; dest->lowmant = 0; return dest; } /* */ if (IS_ZERO(dest)) { /* */ if (IS_ZERO(src)) fp_set_nan(dest); /* */ return dest; } if (IS_ZERO(src)) { /* */ fp_set_sr(FPSR_EXC_DZ); dest->exp = 0x7fff; dest->mant.m64 = 0; return dest; } exp = dest->exp - src->exp + 0x3fff; /* */ if ((long)dest->mant.m32[0] >= 0) exp -= fp_overnormalize(dest); if ((long)src->mant.m32[0] >= 0) exp -= fp_overnormalize(src); /* */ fp_dividemant(&temp, dest, src); /* */ if (!temp.m32[0]) { exp--; fp_putmant128(dest, &temp, 32); } else fp_putmant128(dest, &temp, 31); if (exp >= 0x7fff) { fp_set_ovrflw(dest); return dest; } dest->exp = exp; if (exp < 0) { fp_set_sr(FPSR_EXC_UNFL); fp_denormalize(dest, -exp); } return dest; }
struct fp_ext * fp_fmul(struct fp_ext *dest, struct fp_ext *src) { union fp_mant128 temp; int exp; dprint(PINSTR, "fmul\n"); fp_dyadic_check(dest, src); /* */ dest->sign = src->sign ^ dest->sign; /* */ if (IS_INF(dest)) { if (IS_ZERO(src)) fp_set_nan(dest); return dest; } if (IS_INF(src)) { if (IS_ZERO(dest)) fp_set_nan(dest); else fp_copy_ext(dest, src); return dest; } /* */ if (IS_ZERO(dest) || IS_ZERO(src)) { dest->exp = 0; dest->mant.m64 = 0; dest->lowmant = 0; return dest; } exp = dest->exp + src->exp - 0x3ffe; /* */ if ((long)dest->mant.m32[0] >= 0) exp -= fp_overnormalize(dest); if ((long)src->mant.m32[0] >= 0) exp -= fp_overnormalize(src); /* */ fp_multiplymant(&temp, dest, src); /* */ if ((long)temp.m32[0] > 0) { exp--; fp_putmant128(dest, &temp, 1); } else fp_putmant128(dest, &temp, 0); if (exp >= 0x7fff) { fp_set_ovrflw(dest); return dest; } dest->exp = exp; if (exp < 0) { fp_set_sr(FPSR_EXC_UNFL); fp_denormalize(dest, -exp); } return dest; }