📄 fp-bit.c
字号:
FLO_typesub (FLO_type arg_a, FLO_type arg_b){ fp_number_type a; fp_number_type b; fp_number_type tmp; fp_number_type *res; unpack_d ((FLO_union_type *) & arg_a, &a); unpack_d ((FLO_union_type *) & arg_b, &b); b.sign ^= 1; res = _fpadd_parts (&a, &b, &tmp); return pack_d (res);}static fp_number_type *_fpmul_parts ( fp_number_type * a, fp_number_type * b, fp_number_type * tmp){ fractype low = 0; fractype high = 0; if (isnan (a)) { a->sign = a->sign != b->sign; return a; } if (isnan (b)) { b->sign = a->sign != b->sign; return b; } if (isinf (a)) { if (iszero (b)) return nan (); a->sign = a->sign != b->sign; return a; } if (isinf (b)) { if (iszero (a)) { return nan (); } b->sign = a->sign != b->sign; return b; } if (iszero (a)) { a->sign = a->sign != b->sign; return a; } if (iszero (b)) { b->sign = a->sign != b->sign; return b; } /* Calculate the mantissa by multiplying both 64bit numbers to get a 128 bit number */ { fractype x = a->fraction.ll; fractype ylow = b->fraction.ll; fractype yhigh = 0; int bit;#if defined(NO_DI_MODE) { /* ??? This does multiplies one bit at a time. Optimize. */ for (bit = 0; bit < FRAC_NBITS; bit++) { int carry; if (x & 1) { carry = (low += ylow) < ylow; high += yhigh + carry; } yhigh <<= 1; if (ylow & FRACHIGH) { yhigh |= 1; } ylow <<= 1; x >>= 1; } }#elif defined(FLOAT) { /* Multiplying two 32 bit numbers to get a 64 bit number on a machine with DI, so we're safe */ DItype answer = (DItype)(a->fraction.ll) * (DItype)(b->fraction.ll); high = answer >> 32; low = answer; }#else /* Doing a 64*64 to 128 */ { UDItype nl = a->fraction.ll & 0xffffffff; UDItype nh = a->fraction.ll >> 32; UDItype ml = b->fraction.ll & 0xffffffff; UDItype mh = b->fraction.ll >>32; UDItype pp_ll = ml * nl; UDItype pp_hl = mh * nl; UDItype pp_lh = ml * nh; UDItype pp_hh = mh * nh; UDItype res2 = 0; UDItype res0 = 0; UDItype ps_hh__ = pp_hl + pp_lh; if (ps_hh__ < pp_hl) res2 += 0x100000000LL; pp_hl = (ps_hh__ << 32) & 0xffffffff00000000LL; res0 = pp_ll + pp_hl; if (res0 < pp_ll) res2++; res2 += ((ps_hh__ >> 32) & 0xffffffffL) + pp_hh; high = res2; low = res0; }#endif } tmp->normal_exp = a->normal_exp + b->normal_exp; tmp->sign = a->sign != b->sign;#ifdef FLOAT tmp->normal_exp += 2; /* ??????????????? */#else tmp->normal_exp += 4; /* ??????????????? */#endif while (high >= IMPLICIT_2) { tmp->normal_exp++; if (high & 1) { low >>= 1; low |= FRACHIGH; } high >>= 1; } while (high < IMPLICIT_1) { tmp->normal_exp--; high <<= 1; if (low & FRACHIGH) high |= 1; low <<= 1; } /* rounding is tricky. if we only round if it won't make us round later. */#if 0 if (low & FRACHIGH2) { if (((high & GARDMASK) != GARDMSB) && (((high + 1) & GARDMASK) == GARDMSB)) { /* don't round, it gets done again later. */ } else { high++; } }#endif if ((high & GARDMASK) == GARDMSB) { if (high & (1 << NGARDS)) { /* half way, so round to even */ high += GARDROUND + 1; } else if (low) { /* but we really weren't half way */ high += GARDROUND + 1; } } tmp->fraction.ll = high; tmp->class = CLASS_NUMBER; return tmp;}FLO_typemultiply (FLO_type arg_a, FLO_type arg_b){ fp_number_type a; fp_number_type b; fp_number_type tmp; fp_number_type *res; unpack_d ((FLO_union_type *) & arg_a, &a); unpack_d ((FLO_union_type *) & arg_b, &b); res = _fpmul_parts (&a, &b, &tmp); return pack_d (res);}static fp_number_type *_fpdiv_parts (fp_number_type * a, fp_number_type * b, fp_number_type * tmp){ fractype low = 0; fractype high = 0; fractype r0, r1, y0, y1, bit; fractype q; fractype numerator; fractype denominator; fractype quotient; fractype remainder; if (isnan (a)) { return a; } if (isnan (b)) { return b; } if (isinf (a) || iszero (a)) { if (a->class == b->class) return nan (); return a; } a->sign = a->sign ^ b->sign; if (isinf (b)) { a->fraction.ll = 0; a->normal_exp = 0; return a; } if (iszero (b)) { a->class = CLASS_INFINITY; return b; } /* Calculate the mantissa by multiplying both 64bit numbers to get a 128 bit number */ { int carry; intfrac d0, d1; /* weren't unsigned before ??? */ /* quotient = ( numerator / denominator) * 2^(numerator exponent - denominator exponent) */ a->normal_exp = a->normal_exp - b->normal_exp; numerator = a->fraction.ll; denominator = b->fraction.ll; if (numerator < denominator) { /* Fraction will be less than 1.0 */ numerator *= 2; a->normal_exp--; } bit = IMPLICIT_1; quotient = 0; /* ??? Does divide one bit at a time. Optimize. */ while (bit) { if (numerator >= denominator) { quotient |= bit; numerator -= denominator; } bit >>= 1; numerator *= 2; } if ((quotient & GARDMASK) == GARDMSB) { if (quotient & (1 << NGARDS)) { /* half way, so round to even */ quotient += GARDROUND + 1; } else if (numerator) { /* but we really weren't half way, more bits exist */ quotient += GARDROUND + 1; } } a->fraction.ll = quotient; return (a); }}FLO_typedivide (FLO_type arg_a, FLO_type arg_b){ fp_number_type a; fp_number_type b; fp_number_type tmp; fp_number_type *res; unpack_d ((FLO_union_type *) & arg_a, &a); unpack_d ((FLO_union_type *) & arg_b, &b); res = _fpdiv_parts (&a, &b, &tmp); return pack_d (res);}/* according to the demo, fpcmp returns a comparison with 0... thus a<b -> -1 a==b -> 0 a>b -> +1 */static int_fpcmp_parts (fp_number_type * a, fp_number_type * b){#if 0 /* either nan -> unordered. Must be checked outside of this routine. */ if (isnan (a) && isnan (b)) { return 1; /* still unordered! */ }#endif if (isnan (a) || isnan (b)) { return 1; /* how to indicate unordered compare? */ } if (isinf (a) && isinf (b)) { /* +inf > -inf, but +inf != +inf */ /* b \a| +inf(0)| -inf(1) ______\+--------+-------- +inf(0)| a==b(0)| a<b(-1) -------+--------+-------- -inf(1)| a>b(1) | a==b(0) -------+--------+-------- So since unordered must be non zero, just line up the columns... */ return b->sign - a->sign; } /* but not both... */ if (isinf (a)) { return a->sign ? -1 : 1; } if (isinf (b)) { return b->sign ? 1 : -1; } if (iszero (a) && iszero (b)) { return 0; } if (iszero (a)) { return b->sign ? 1 : -1; } if (iszero (b)) { return a->sign ? -1 : 1; } /* now both are "normal". */ if (a->sign != b->sign) { /* opposite signs */ return a->sign ? -1 : 1; } /* same sign; exponents? */ if (a->normal_exp > b->normal_exp) { return a->sign ? -1 : 1; } if (a->normal_exp < b->normal_exp) { return a->sign ? 1 : -1; } /* same exponents; check size. */ if (a->fraction.ll > b->fraction.ll) { return a->sign ? -1 : 1; } if (a->fraction.ll < b->fraction.ll) { return a->sign ? 1 : -1; } /* after all that, they're equal. */ return 0;}CMPtypecompare (FLO_type arg_a, FLO_type arg_b){ fp_number_type a; fp_number_type b; unpack_d ((FLO_union_type *) & arg_a, &a); unpack_d ((FLO_union_type *) & arg_b, &b); return _fpcmp_parts (&a, &b);}#ifndef US_SOFTWARE_GOFAST/* These should be optimized for their specific tasks someday. */CMPtype_eq_f2 (FLO_type arg_a, FLO_type arg_b){ fp_number_type a; fp_number_type b; unpack_d ((FLO_union_type *) & arg_a, &a); unpack_d ((FLO_union_type *) & arg_b, &b); if (isnan (&a) || isnan (&b)) return 1; /* false, truth == 0 */ return _fpcmp_parts (&a, &b) ;}CMPtype_ne_f2 (FLO_type arg_a, FLO_type arg_b){ fp_number_type a; fp_number_type b; unpack_d ((FLO_union_type *) & arg_a, &a); unpack_d ((FLO_union_type *) & arg_b, &b); if (isnan (&a) || isnan (&b)) return 1; /* true, truth != 0 */ return _fpcmp_parts (&a, &b) ;}CMPtype_gt_f2 (FLO_type arg_a, FLO_type arg_b){ fp_number_type a; fp_number_type b; unpack_d ((FLO_union_type *) & arg_a, &a); unpack_d ((FLO_union_type *) & arg_b, &b); if (isnan (&a) || isnan (&b)) return -1; /* false, truth > 0 */ return _fpcmp_parts (&a, &b);}CMPtype_ge_f2 (FLO_type arg_a, FLO_type arg_b){ fp_number_type a; fp_number_type b; unpack_d ((FLO_union_type *) & arg_a, &a); unpack_d ((FLO_union_type *) & arg_b, &b); if (isnan (&a) || isnan (&b)) return -1; /* false, truth >= 0 */ return _fpcmp_parts (&a, &b) ;}CMPtype_lt_f2 (FLO_type arg_a, FLO_type arg_b){ fp_number_type a; fp_number_type b; unpack_d ((FLO_union_type *) & arg_a, &a); unpack_d ((FLO_union_type *) & arg_b, &b); if (isnan (&a) || isnan (&b)) return 1; /* false, truth < 0 */ return _fpcmp_parts (&a, &b);}CMPtype_le_f2 (FLO_type arg_a, FLO_type arg_b){ fp_number_type a; fp_number_type b; unpack_d ((FLO_union_type *) & arg_a, &a); unpack_d ((FLO_union_type *) & arg_b, &b); if (isnan (&a) || isnan (&b)) return 1; /* false, truth <= 0 */ return _fpcmp_parts (&a, &b) ;}#endif /* ! US_SOFTWARE_GOFAST */FLO_typesi_to_float (SItype arg_a){ fp_number_type in; in.class = CLASS_NUMBER; in.sign = arg_a < 0; if (!arg_a) { in.class = CLASS_ZERO; } else { in.normal_exp = FRACBITS + NGARDS; if (in.sign) { /* Special case for minint, since there is no +ve integer representation for it */ if (arg_a == 0x80000000) { return -2147483648.0; } in.fraction.ll = (-arg_a); } else in.fraction.ll = arg_a; while (in.fraction.ll < (1LL << (FRACBITS + NGARDS))) { in.fraction.ll <<= 1; in.normal_exp -= 1; } } return pack_d (&in);}SItypefloat_to_si (FLO_type arg_a){ fp_number_type a; SItype tmp; unpack_d ((FLO_union_type *) & arg_a, &a); if (iszero (&a)) return 0; if (isnan (&a)) return 0; /* get reasonable MAX_SI_INT... */ if (isinf (&a)) return a.sign ? MAX_SI_INT : (-MAX_SI_INT)-1; /* it is a number, but a small one */ if (a.normal_exp < 0) return 0; if (a.normal_exp > 30) return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT; tmp = a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp); return a.sign ? (-tmp) : (tmp);}#ifdef US_SOFTWARE_GOFAST/* While libgcc2.c defines its own __fixunssfsi and __fixunsdfsi routines, we also define them for GOFAST because the ones in libgcc2.c have the wrong names and I'd rather define these here and keep GOFAST CYG-LOC's out of libgcc2.c. We can't define these here if not GOFAST because then there'd be duplicate copies. */USItypefloat_to_usi (FLO_type arg_a){ fp_number_type a; unpack_d ((FLO_union_type *) & arg_a, &a); if (iszero (&a)) return 0; if (isnan (&a)) return 0; /* get reasonable MAX_USI_INT... */ if (isinf (&a)) return a.sign ? MAX_USI_INT : 0; /* it is a negative number */ if (a.sign) return 0; /* it is a number, but a small one */ if (a.normal_exp < 0) return 0; if (a.normal_exp > 31) return MAX_USI_INT; else if (a.normal_exp > (FRACBITS + NGARDS)) return a.fraction.ll << ((FRACBITS + NGARDS) - a.normal_exp); else return a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);}#endifFLO_typenegate (FLO_type arg_a){ fp_number_type a; unpack_d ((FLO_union_type *) & arg_a, &a); flip_sign (&a); return pack_d (&a);}#ifdef FLOATSFtype__make_fp(fp_class_type class, unsigned int sign, int exp, USItype frac){ fp_number_type in; in.class = class; in.sign = sign; in.normal_exp = exp; in.fraction.ll = frac; return pack_d (&in);}#ifndef FLOAT_ONLY/* This enables one to build an fp library that supports float but not double. Otherwise, we would get an undefined reference to __make_dp. This is needed for some 8-bit ports that can't handle well values that are 8-bytes in size, so we just don't support double for them at all. */extern DFtype __make_dp (fp_class_type, unsigned int, int, UDItype frac);DFtypesf_to_df (SFtype arg_a){ fp_number_type in; unpack_d ((FLO_union_type *) & arg_a, &in); return __make_dp (in.class, in.sign, in.normal_exp, ((UDItype) in.fraction.ll) << F_D_BITOFF);}#endif#endif#ifndef FLOATextern SFtype __make_fp (fp_class_type, unsigned int, int, USItype);DFtype__make_dp (fp_class_type class, unsigned int sign, int exp, UDItype frac){ fp_number_type in; in.class = class; in.sign = sign; in.normal_exp = exp; in.fraction.ll = frac; return pack_d (&in);}SFtypedf_to_sf (DFtype arg_a){ fp_number_type in; unpack_d ((FLO_union_type *) & arg_a, &in); return __make_fp (in.class, in.sign, in.normal_exp, in.fraction.ll >> F_D_BITOFF);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -