int floatx80_ftan(floatx80 &a) { UINT64 aSig0, aSig1 = 0; INT32 aExp, zExp, expDiff; int aSign, zSign; int q = 0; aSig0 = extractFloatx80Frac(a); aExp = extractFloatx80Exp(a); aSign = extractFloatx80Sign(a); /* invalid argument */ if (aExp == 0x7FFF) { if ((UINT64) (aSig0<<1)) { a = propagateFloatx80NaNOneArg(a); return 0; } float_raise(float_flag_invalid); a = floatx80_default_nan; return 0; } if (aExp == 0) { if (aSig0 == 0) return 0; // float_raise(float_flag_denormal); /* handle pseudo denormals */ if (! (aSig0 & U64(0x8000000000000000))) { float_raise(float_flag_inexact | float_flag_underflow); return 0; } normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); } zSign = aSign; zExp = EXP_BIAS; expDiff = aExp - zExp; /* argument is out-of-range */ if (expDiff >= 63) return -1; float_raise(float_flag_inexact); if (expDiff < -1) { // doesn't require reduction if (expDiff <= -68) { a = packFloatx80(aSign, aExp, aSig0); return 0; } zExp = aExp; } else { q = reduce_trig_arg(expDiff, zSign, aSig0, aSig1); } /* **************************** */ /* argument reduction completed */ /* **************************** */ /* using float128 for approximation */ float128 r = normalizeRoundAndPackFloat128(0, zExp-0x10, aSig0, aSig1); float128 sin_r = poly_sin(r); float128 cos_r = poly_cos(r); if (q & 0x1) { r = float128_div(cos_r, sin_r); zSign = ! zSign; } else { r = float128_div(sin_r, cos_r); } a = float128_to_floatx80(r); if (zSign) a = floatx80_chs(a); return 0; }
int ftan(floatx80 &a, float_status_t &status) { Bit64u aSig0, aSig1 = 0; Bit32s aExp, zExp, expDiff; int aSign, zSign; int q = 0; // handle unsupported extended double-precision floating encodings if (floatx80_is_unsupported(a)) { goto invalid; } aSig0 = extractFloatx80Frac(a); aExp = extractFloatx80Exp(a); aSign = extractFloatx80Sign(a); /* invalid argument */ if (aExp == 0x7FFF) { if ((Bit64u) (aSig0<<1)) { a = propagateFloatx80NaN(a, status); return 0; } invalid: float_raise(status, float_flag_invalid); a = floatx80_default_nan; return 0; } if (aExp == 0) { if (aSig0 == 0) return 0; float_raise(status, float_flag_denormal); /* handle pseudo denormals */ if (! (aSig0 & BX_CONST64(0x8000000000000000))) { float_raise(status, float_flag_inexact | float_flag_underflow); return 0; } normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); } zSign = aSign; zExp = EXP_BIAS; expDiff = aExp - zExp; /* argument is out-of-range */ if (expDiff >= 63) return -1; float_raise(status, float_flag_inexact); if (expDiff < -1) { // doesn't require reduction if (expDiff <= -68) { a = packFloatx80(aSign, aExp, aSig0); return 0; } zExp = aExp; } else { q = reduce_trig_arg(expDiff, zSign, aSig0, aSig1); } /* **************************** */ /* argument reduction completed */ /* **************************** */ /* using float128 for approximation */ float128 r = normalizeRoundAndPackFloat128(0, zExp-0x10, aSig0, aSig1, status); float128 sin_r = poly_sin(r, status); float128 cos_r = poly_cos(r, status); if (q & 0x1) { r = float128_div(cos_r, sin_r, status); zSign = ! zSign; } else { r = float128_div(sin_r, cos_r, status); } a = float128_to_floatx80(r, status); if (zSign) floatx80_chs(a); return 0; }
int sf_fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a) { UINT64 aSig0, aSig1 = 0; INT32 aExp, zExp, expDiff; int aSign, zSign; int q = 0; aSig0 = extractFloatx80Frac(a); aExp = extractFloatx80Exp(a); aSign = extractFloatx80Sign(a); /* invalid argument */ if (aExp == 0x7FFF) { if ((UINT64) (aSig0<<1)) { sincos_invalid(sin_a, cos_a, propagateFloatx80NaNOneArg(a)); return 0; } float_raise(float_flag_invalid); sincos_invalid(sin_a, cos_a, floatx80_default_nan); return 0; } if (aExp == 0) { if (aSig0 == 0) { sincos_tiny_argument(sin_a, cos_a, a); return 0; } // float_raise(float_flag_denormal); /* handle pseudo denormals */ if (! (aSig0 & U64(0x8000000000000000))) { float_raise(float_flag_inexact); if (sin_a) float_raise(float_flag_underflow); sincos_tiny_argument(sin_a, cos_a, a); return 0; } normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); } zSign = aSign; zExp = EXP_BIAS; expDiff = aExp - zExp; /* argument is out-of-range */ if (expDiff >= 63) return -1; float_raise(float_flag_inexact); if (expDiff < -1) { // doesn't require reduction if (expDiff <= -68) { a = packFloatx80(aSign, aExp, aSig0); sincos_tiny_argument(sin_a, cos_a, a); return 0; } zExp = aExp; } else { q = reduce_trig_arg(expDiff, zSign, aSig0, aSig1); } /* **************************** */ /* argument reduction completed */ /* **************************** */ /* using float128 for approximation */ float128 r = normalizeRoundAndPackFloat128(0, zExp-0x10, aSig0, aSig1); if (aSign) q = -q; if (sin_a) *sin_a = sincos_approximation(zSign, r, q); if (cos_a) *cos_a = sincos_approximation(zSign, r, q+1); return 0; }