freebsd-dev/lib/msun/src
Bruce Evans 16638b5585 Optimized by eliminating the special case for 0.67434 <= |x| < pi/4.
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.
2005-11-24 02:04:26 +00:00
..
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 Fixed some magic numbers. 2005-11-13 00:08:23 +00:00
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 As for the float trig functions, use a minimax polynomial that is 2005-11-12 18:20:09 +00:00
e_pow.c
e_powf.c
e_rem_pio2.c
e_rem_pio2f.c Simplified setiing up args for __kernel_rem_pio2(). We already have x 2005-11-23 03:03:09 +00:00
e_remainder.c
e_remainderf.c
e_scalb.c
e_scalbf.c
e_sinh.c
e_sinhf.c Fixed some magic numbers. 2005-11-13 00:41:46 +00:00
e_sqrt.c
e_sqrtf.c
k_cos.c Use a better algorithm for reducing the error in __kernel_cos[f](). 2005-10-26 12:36:18 +00:00
k_cosf.c Mess up the "kernel" float trig function .c files with ifdefs so that 2005-11-21 04:57:12 +00:00
k_rem_pio2.c
k_rem_pio2f.c Fixed range reduction for large multiples of pi/2 on systems with 2005-10-11 07:56:05 +00:00
k_sin.c Updated the comment about the optimization for tiny x (the previous 2005-11-02 13:06:49 +00:00
k_sinf.c Mess up the "kernel" float trig function .c files with ifdefs so that 2005-11-21 04:57:12 +00:00
k_tan.c Moved the optimization for tiny x from __kernel_tan[f](x) to tan[f](x) 2005-11-02 14:01:45 +00:00
k_tanf.c Optimized by eliminating the special case for 0.67434 <= |x| < pi/4. 2005-11-24 02:04:26 +00:00
math_private.h Use only double precision for "kernel" tanf (except for returning float). 2005-11-23 14:27:56 +00:00
math.h Implement truncl() based on floorl(). 2005-04-16 21:12:47 +00:00
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 Revert the last change, the conversion from long double to double can raise 2005-04-28 19:45:55 +00:00
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 Moved the optimization for tiny x from __kernel_{cos,sin}[f](x) to 2005-10-24 14:08:36 +00:00
s_cosf.c Mess up the "kernel" float trig function .c files with ifdefs so that 2005-11-21 04:57:12 +00:00
s_creal.c
s_crealf.c
s_creall.c
s_erf.c
s_erff.c
s_exp2.c Implement exp2() and exp2f(). 2005-04-05 02:57:15 +00:00
s_exp2f.c Implement exp2() and exp2f(). 2005-04-05 02:57:15 +00:00
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 Revert the last change, the conversion from long double to double can raise 2005-04-28 19:45:55 +00:00
s_fma.c Fix the double rounding problem with subnormals, and 2005-03-18 02:27:59 +00:00
s_fmaf.c
s_fmal.c Fix the double rounding problem with subnormals, and 2005-03-18 02:27:59 +00:00
s_fmax.c
s_fmaxf.c
s_fmaxl.c
s_fmin.c
s_fminf.c
s_fminl.c
s_frexp.c Replace strong references with weak references. There's no 2005-03-07 21:27:37 +00:00
s_frexpf.c
s_frexpl.c Implement frexpl. 2005-03-07 04:54:51 +00:00
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 These files should include s_lround.c instead of s_lrint.c. 2005-04-08 00:52:27 +00:00
s_llroundf.c These files should include s_lround.c instead of s_lrint.c. 2005-04-08 00:52:27 +00:00
s_llroundl.c Add roundl(), lroundl(), and llroundl(). 2005-04-08 01:24:08 +00:00
s_log1p.c
s_log1pf.c
s_logb.c
s_logbf.c
s_lrint.c
s_lrintf.c
s_lround.c Fix a (coincidentally harmless) bug. 2005-04-08 00:52:16 +00:00
s_lroundf.c These files should include s_lround.c instead of s_lrint.c. 2005-04-08 00:52:27 +00:00
s_lroundl.c Add roundl(), lroundl(), and llroundl(). 2005-04-08 01:24:08 +00:00
s_modf.c
s_modff.c
s_nearbyint.c
s_nextafter.c Replace strong references with weak references. There's no 2005-03-07 21:27:37 +00:00
s_nextafterf.c - Try harder to trick gcc into not optimizing away statements 2005-03-07 04:55:58 +00:00
s_nextafterl.c Implement nexttoward and nextafterl; the latter is also known as 2005-03-07 04:56:46 +00:00
s_nexttoward.c Implement nexttoward and nextafterl; the latter is also known as 2005-03-07 04:56:46 +00:00
s_nexttowardf.c Implement nexttowardf. This is used on both platforms with 11-bit 2005-03-07 04:57:38 +00:00
s_remquo.c Implement and document remquo() and remquof(). 2005-03-25 04:40:44 +00:00
s_remquof.c Implement and document remquo() and remquof(). 2005-03-25 04:40:44 +00:00
s_rint.c Remove an obsolete sentence from a comment. 2005-03-07 20:28:26 +00:00
s_rintf.c
s_round.c
s_roundf.c
s_roundl.c Add roundl(), lroundl(), and llroundl(). 2005-04-08 01:24:08 +00:00
s_scalbln.c - Implement scalblnl. 2005-03-07 04:57:50 +00:00
s_scalbn.c Replace strong references with weak references. There's no 2005-03-07 21:27:37 +00:00
s_scalbnf.c
s_scalbnl.c
s_signbit.c
s_signgam.c
s_significand.c
s_significandf.c
s_sin.c Moved the optimization for tiny x from __kernel_{cos,sin}[f](x) to 2005-10-24 14:08:36 +00:00
s_sinf.c Mess up the "kernel" float trig function .c files with ifdefs so that 2005-11-21 04:57:12 +00:00
s_tan.c Moved the optimization for tiny x from __kernel_tan[f](x) to tan[f](x) 2005-11-02 14:01:45 +00:00
s_tanf.c Use only double precision for "kernel" tanf (except for returning float). 2005-11-23 14:27:56 +00:00
s_tanh.c
s_tanhf.c
s_trunc.c
s_truncf.c
s_truncl.c Revert the last change, the conversion from long double to double can raise 2005-04-28 19:45:55 +00:00
w_cabs.c
w_cabsf.c
w_drem.c
w_dremf.c