From 735ddf26403efe5d8df41bd53f9c1edec0b627b3 Mon Sep 17 00:00:00 2001 From: gnezdo Date: Fri, 21 Jan 2022 03:13:10 +0000 Subject: [PATCH] Optimization for tiny x in cos and sin Subset of FreeBSD commit 4339c67c485f0b1f7699863fc29f6c06862d1dde: Moved the optimization for tiny x from __kernel_{cos,sin}[f](x) to {cos_sin}[f](x) so that x doesn't need to be reclassified in the "kernel" functions to determine if it is tiny (it still needs to be reclassified in the cosine case for other reasons that will go away). ... Parts of the original change were applied separately before. Suggested by kettenis@ OK mbuhl@, tested by mbuhl@ and phessler@ --- lib/libm/src/k_cosf.c | 3 --- lib/libm/src/k_sin.c | 6 +----- lib/libm/src/k_sinf.c | 6 +----- lib/libm/src/s_cosf.c | 7 ++++++- lib/libm/src/s_sin.c | 6 +++++- lib/libm/src/s_sinf.c | 6 +++++- 6 files changed, 18 insertions(+), 16 deletions(-) diff --git a/lib/libm/src/k_cosf.c b/lib/libm/src/k_cosf.c index 853c08286ba..e6f571296a8 100644 --- a/lib/libm/src/k_cosf.c +++ b/lib/libm/src/k_cosf.c @@ -32,9 +32,6 @@ __kernel_cosf(float x, float y) int32_t ix; GET_FLOAT_WORD(ix,x); ix &= 0x7fffffff; /* ix = |x|'s high word*/ - if(ix<0x32000000) { /* if x < 2**27 */ - if(((int)x)==0) return one; /* generate inexact */ - } z = x*x; r = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*C6))))); if(ix < 0x3e99999a) /* if |x| < 0.3 */ diff --git a/lib/libm/src/k_sin.c b/lib/libm/src/k_sin.c index 8b3d6272372..a560f738071 100644 --- a/lib/libm/src/k_sin.c +++ b/lib/libm/src/k_sin.c @@ -54,11 +54,7 @@ double __kernel_sin(double x, double y, int iy) { double z,r,v; - int32_t ix; - GET_HIGH_WORD(ix,x); - ix &= 0x7fffffff; /* high word of x */ - if(ix<0x3e400000) /* |x| < 2**-27 */ - {if((int)x==0) return x;} /* generate inexact */ + z = x*x; v = z*x; r = S2+z*(S3+z*(S4+z*(S5+z*S6))); diff --git a/lib/libm/src/k_sinf.c b/lib/libm/src/k_sinf.c index ba17317490c..a0cf753557c 100644 --- a/lib/libm/src/k_sinf.c +++ b/lib/libm/src/k_sinf.c @@ -29,11 +29,7 @@ float __kernel_sinf(float x, float y, int iy) { float z,r,v; - int32_t ix; - GET_FLOAT_WORD(ix,x); - ix &= 0x7fffffff; /* high word of x */ - if(ix<0x32000000) /* |x| < 2**-27 */ - {if((int)x==0) return x;} /* generate inexact */ + z = x*x; v = z*x; r = S2+z*(S3+z*(S4+z*(S5+z*S6))); diff --git a/lib/libm/src/s_cosf.c b/lib/libm/src/s_cosf.c index 16cdd648cf5..5c3b5614085 100644 --- a/lib/libm/src/s_cosf.c +++ b/lib/libm/src/s_cosf.c @@ -26,7 +26,12 @@ cosf(float x) /* |x| ~< pi/4 */ ix &= 0x7fffffff; - if(ix <= 0x3f490fd8) return __kernel_cosf(x,z); + if(ix <= 0x3f490fd8) { + if(ix<0x39800000) /* if x < 2**-12 */ + if(((int)x)==0) return 1.0; /* generate inexact */ + return __kernel_cosf(x,z); + } + /* cos(Inf or NaN) is NaN */ else if (ix>=0x7f800000) return x-x; diff --git a/lib/libm/src/s_sin.c b/lib/libm/src/s_sin.c index 058486a696b..c99fd894744 100644 --- a/lib/libm/src/s_sin.c +++ b/lib/libm/src/s_sin.c @@ -57,7 +57,11 @@ sin(double x) /* |x| ~< pi/4 */ ix &= 0x7fffffff; - if(ix <= 0x3fe921fb) return __kernel_sin(x,z,0); + if(ix <= 0x3fe921fb) { + if(ix<0x3e400000) /* |x| < 2**-27 */ + {if((int)x==0) return x;} /* generate inexact */ + return __kernel_sin(x,z,0); + } /* sin(Inf or NaN) is NaN */ else if (ix>=0x7ff00000) return x-x; diff --git a/lib/libm/src/s_sinf.c b/lib/libm/src/s_sinf.c index 1214212ddb3..2e9e416b21d 100644 --- a/lib/libm/src/s_sinf.c +++ b/lib/libm/src/s_sinf.c @@ -26,7 +26,11 @@ sinf(float x) /* |x| ~< pi/4 */ ix &= 0x7fffffff; - if(ix <= 0x3f490fd8) return __kernel_sinf(x,z,0); + if(ix <= 0x3f490fd8) { + if(ix<0x39800000) /* if x < 2**-12 */ + if(((int)x)==0) return x; /* generate inexact */ + return __kernel_sinf(x,z,0); + } /* sin(Inf or NaN) is NaN */ else if (ix>=0x7f800000) return x-x; -- 2.20.1