16638b5585
A single polynomial approximation for tan(x) works in infinite precision up to |x| < pi/2, but in finite precision, to restrict the accumulated roundoff error to < 1 ulp, |x| must be restricted to less than about sqrt(0.5/((1.5+1.5)/3)) ~= 0.707. We restricted it a bit more to give a safety margin including some slop for optimizations. Now that we use double precision for the calculations, the accumulated roundoff error is in double-precision ulps so it can easily be made almost 2**29 times smaller than a single-precision ulp. Near x = pi/4 its maximum is about 0.5+(1.5+1.5)*x**2/3 ~= 1.117 double-precision ulps. The minimax polynomial needs to be different to work for the larger interval. I didn't increase its degree the old degree is just large enough to keep the final error less than 1 ulp and increasing the degree would be a pessimization. The maximum error is now ~0.80 ulps instead of ~0.53 ulps. The speedup from this optimization for uniformly distributed args in [-2pi, 2pi] is 28-43% on athlons, depending on how badly gcc selected and scheduled the instructions in the old version. The old version has some int-to-float conversions that are apparently difficult to schedule well, but gcc-3.3 somehow did everything ~10 cycles or ~10% faster than gcc-3.4, with the difference especially large on AXPs. On A64s, the problem seems to be related to documented penalties for moving single precision data to undead xmm registers. With this version, the speed is cycles is almost independent of the athlon and gcc version despite the large differences in instruction selection to use the FPU on AXPs and SSE on A64s. |
||
---|---|---|
.. | ||
e_acos.c | ||
e_acosf.c | ||
e_acosh.c | ||
e_acoshf.c | ||
e_asin.c | ||
e_asinf.c | ||
e_atan2.c | ||
e_atan2f.c | ||
e_atanh.c | ||
e_atanhf.c | ||
e_cosh.c | ||
e_coshf.c | ||
e_exp.c | ||
e_expf.c | ||
e_fmod.c | ||
e_fmodf.c | ||
e_gamma_r.c | ||
e_gamma.c | ||
e_gammaf_r.c | ||
e_gammaf.c | ||
e_hypot.c | ||
e_hypotf.c | ||
e_j0.c | ||
e_j0f.c | ||
e_j1.c | ||
e_j1f.c | ||
e_jn.c | ||
e_jnf.c | ||
e_lgamma_r.c | ||
e_lgamma.c | ||
e_lgammaf_r.c | ||
e_lgammaf.c | ||
e_log10.c | ||
e_log10f.c | ||
e_log.c | ||
e_logf.c | ||
e_pow.c | ||
e_powf.c | ||
e_rem_pio2.c | ||
e_rem_pio2f.c | ||
e_remainder.c | ||
e_remainderf.c | ||
e_scalb.c | ||
e_scalbf.c | ||
e_sinh.c | ||
e_sinhf.c | ||
e_sqrt.c | ||
e_sqrtf.c | ||
k_cos.c | ||
k_cosf.c | ||
k_rem_pio2.c | ||
k_rem_pio2f.c | ||
k_sin.c | ||
k_sinf.c | ||
k_tan.c | ||
k_tanf.c | ||
math_private.h | ||
math.h | ||
s_asinh.c | ||
s_asinhf.c | ||
s_atan.c | ||
s_atanf.c | ||
s_cbrt.c | ||
s_cbrtf.c | ||
s_ceil.c | ||
s_ceilf.c | ||
s_ceill.c | ||
s_cimag.c | ||
s_cimagf.c | ||
s_cimagl.c | ||
s_conj.c | ||
s_conjf.c | ||
s_conjl.c | ||
s_copysign.c | ||
s_copysignf.c | ||
s_copysignl.c | ||
s_cos.c | ||
s_cosf.c | ||
s_creal.c | ||
s_crealf.c | ||
s_creall.c | ||
s_erf.c | ||
s_erff.c | ||
s_exp2.c | ||
s_exp2f.c | ||
s_expm1.c | ||
s_expm1f.c | ||
s_fabs.c | ||
s_fabsf.c | ||
s_fabsl.c | ||
s_fdim.c | ||
s_finite.c | ||
s_finitef.c | ||
s_floor.c | ||
s_floorf.c | ||
s_floorl.c | ||
s_fma.c | ||
s_fmaf.c | ||
s_fmal.c | ||
s_fmax.c | ||
s_fmaxf.c | ||
s_fmaxl.c | ||
s_fmin.c | ||
s_fminf.c | ||
s_fminl.c | ||
s_frexp.c | ||
s_frexpf.c | ||
s_frexpl.c | ||
s_ilogb.c | ||
s_ilogbf.c | ||
s_ilogbl.c | ||
s_isfinite.c | ||
s_isnan.c | ||
s_isnormal.c | ||
s_llrint.c | ||
s_llrintf.c | ||
s_llround.c | ||
s_llroundf.c | ||
s_llroundl.c | ||
s_log1p.c | ||
s_log1pf.c | ||
s_logb.c | ||
s_logbf.c | ||
s_lrint.c | ||
s_lrintf.c | ||
s_lround.c | ||
s_lroundf.c | ||
s_lroundl.c | ||
s_modf.c | ||
s_modff.c | ||
s_nearbyint.c | ||
s_nextafter.c | ||
s_nextafterf.c | ||
s_nextafterl.c | ||
s_nexttoward.c | ||
s_nexttowardf.c | ||
s_remquo.c | ||
s_remquof.c | ||
s_rint.c | ||
s_rintf.c | ||
s_round.c | ||
s_roundf.c | ||
s_roundl.c | ||
s_scalbln.c | ||
s_scalbn.c | ||
s_scalbnf.c | ||
s_scalbnl.c | ||
s_signbit.c | ||
s_signgam.c | ||
s_significand.c | ||
s_significandf.c | ||
s_sin.c | ||
s_sinf.c | ||
s_tan.c | ||
s_tanf.c | ||
s_tanh.c | ||
s_tanhf.c | ||
s_trunc.c | ||
s_truncf.c | ||
s_truncl.c | ||
w_cabs.c | ||
w_cabsf.c | ||
w_drem.c | ||
w_dremf.c |