📄 fp-bit.c
字号:
fractype quotient; if (isnan (a)) { return a; } if (isnan (b)) { return b; } a->sign = a->sign ^ b->sign; if (isinf (a) || iszero (a)) { if (a->class == b->class) return nan (); return a; } if (isinf (b)) { a->fraction.ll = 0; a->normal_exp = 0; return a; } if (iszero (b)) { a->class = CLASS_INFINITY; return a; } /* Calculate the mantissa by multiplying both 64bit numbers to get a 128 bit number */ { /* 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 *res; unpack_d ((FLO_union_type *) & arg_a, &a); unpack_d ((FLO_union_type *) & arg_b, &b); res = _fpdiv_parts (&a, &b); return pack_d (res);}#endifint __fpcmp_parts (fp_number_type * a, fp_number_type *b);#if defined(L_fpcmp_parts_sf) || defined(L_fpcmp_parts_df)/* according to the demo, fpcmp returns a comparison with 0... thus a<b -> -1 a==b -> 0 a>b -> +1 */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;}#endif#if defined(L_compare_sf) || defined(L_compare_df)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);}#endif#ifndef US_SOFTWARE_GOFAST/* These should be optimized for their specific tasks someday. */#if defined(L_eq_sf) || defined(L_eq_df)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) ;}#endif#if defined(L_ne_sf) || defined(L_ne_df)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) ;}#endif#if defined(L_gt_sf) || defined(L_gt_df)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);}#endif#if defined(L_ge_sf) || defined(L_ge_df)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) ;}#endif#if defined(L_lt_sf) || defined(L_lt_df)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);}#endif#if defined(L_le_sf) || defined(L_le_df)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#endif /* ! US_SOFTWARE_GOFAST */#if defined(L_si_to_sf) || defined(L_si_to_df)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 == (SItype) 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);}#endif#if defined(L_sf_to_si) || defined(L_df_to_si)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)-1 : MAX_SI_INT; /* 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);}#endif#if defined(L_sf_to_usi) || defined(L_df_to_usi)#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; /* it is a negative number */ if (a.sign) return 0; /* get reasonable MAX_USI_INT... */ if (isinf (&a)) return MAX_USI_INT; /* 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 << (a.normal_exp - (FRACBITS + NGARDS)); else return a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);}#endif#endif#if defined(L_negate_sf) || defined(L_negate_df)FLO_typenegate (FLO_type arg_a){ fp_number_type a; unpack_d ((FLO_union_type *) & arg_a, &a); flip_sign (&a); return pack_d (&a);}#endif#ifdef FLOAT#if defined(L_make_sf)SFtype__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);}#endif#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);#if defined(L_sf_to_df)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#endif#ifndef FLOATextern SFtype __make_fp (fp_class_type, unsigned int, int, USItype);#if defined(L_make_df)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);}#endif#if defined(L_df_to_sf)SFtypedf_to_sf (DFtype arg_a){ fp_number_type in; USItype sffrac; unpack_d ((FLO_union_type *) & arg_a, &in); sffrac = in.fraction.ll >> F_D_BITOFF; /* We set the lowest guard bit in SFFRAC if we discarded any non zero bits. */ if ((in.fraction.ll & (((USItype) 1 << F_D_BITOFF) - 1)) != 0) sffrac |= 1; return __make_fp (in.class, in.sign, in.normal_exp, sffrac);}#endif#endif#endif /* !EXTENDED_FLOAT_STUBS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -