From 261358f1f5502138a0052792a7e1c922f81eadc4 Mon Sep 17 00:00:00 2001 From: David Alessio Date: Mon, 11 Jul 2016 07:02:50 -0600 Subject: [PATCH] This change should significantly improve the performance of single precision floating point math library functions. The vast majority of changes have to do with preventing the compiler from needlessly promoting floats to doubles, performing the calculation with doubles, only to demote the result to float. These changes only affect the math lib functions that return float. --- include/nuttx/math.h | 8 ++++++++ libc/libc.h | 3 ++- libc/math/Make.defs | 1 + libc/math/lib_acosf.c | 2 +- libc/math/lib_acoshf.c | 2 +- libc/math/lib_asinf.c | 4 ++-- libc/math/lib_asinhf.c | 2 +- libc/math/lib_atan2f.c | 8 ++++---- libc/math/lib_atanf.c | 2 +- libc/math/lib_atanhf.c | 2 +- libc/math/lib_ceilf.c | 4 ++-- libc/math/lib_cosf.c | 2 +- libc/math/lib_coshf.c | 2 +- libc/math/lib_erff.c | 16 ++++++++-------- libc/math/lib_expf.c | 8 ++++---- libc/math/lib_floorf.c | 4 ++-- libc/math/lib_frexpf.c | 2 +- libc/math/lib_ldexpf.c | 2 +- libc/math/lib_log10f.c | 2 +- libc/math/lib_log2f.c | 2 +- libc/math/lib_logf.c | 18 +++++++++--------- libc/math/lib_modff.c | 8 ++++---- libc/math/lib_rintf.c | 10 +++++----- libc/math/lib_sinf.c | 20 ++++++++++---------- libc/math/lib_sinhf.c | 2 +- libc/math/lib_sqrtf.c | 20 ++++++++++---------- libc/math/lib_tanhf.c | 2 +- 27 files changed, 84 insertions(+), 74 deletions(-) diff --git a/include/nuttx/math.h b/include/nuttx/math.h index 6ee91eab7e..d6963a5013 100644 --- a/include/nuttx/math.h +++ b/include/nuttx/math.h @@ -93,10 +93,15 @@ #define NAN (0.0/0.0) #define HUGE_VAL INFINITY +#define INFINITY_F (1.0F/0.0F) +#define NAN_F (0.0F/0.0F) + #define isnan(x) ((x) != (x)) #define isinf(x) (((x) == INFINITY) || ((x) == -INFINITY)) #define isfinite(x) (!(isinf(x)) && (x != NAN)) +#define isinf_f(x) (((x) == INFINITY_F) || ((x) == -INFINITY_F)) + /* Exponential and Logarithmic constants ************************************/ #define M_E 2.7182818284590452353602874713526625 @@ -116,6 +121,9 @@ #define M_2_PI 0.6366197723675813430755350534900574 #define M_2_SQRTPI 1.1283791670955125738961589031215452 +#define M_PI_F ((float)M_PI) +#define M_PI_2_F ((float)M_PI_2) + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ diff --git a/libc/libc.h b/libc/libc.h index 9cb1974fa9..9e947009f2 100644 --- a/libc/libc.h +++ b/libc/libc.h @@ -1,7 +1,7 @@ /**************************************************************************** * libc/libc.h * - * Copyright (C) 2007-2014 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2014, 2016 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -211,6 +211,7 @@ int lib_checkbase(int base, const char **pptr); /* Defined in lib_expi.c */ #ifdef CONFIG_LIBM +float lib_expif(size_t n); double lib_expi(size_t n); #endif diff --git a/libc/math/Make.defs b/libc/math/Make.defs index cf25a1ec76..a2acc7a93a 100644 --- a/libc/math/Make.defs +++ b/libc/math/Make.defs @@ -59,6 +59,7 @@ CSRCS += lib_tanhl.c lib_asinhl.c lib_acoshl.c lib_atanhl.c lib_erfl.c lib_copys CSRCS += lib_truncl.c CSRCS += lib_libexpi.c lib_libsqrtapprox.c +CSRCS += lib_libexpif.c # Add the floating point math directory to the build diff --git a/libc/math/lib_acosf.c b/libc/math/lib_acosf.c index 6719e54a67..12fe68da67 100644 --- a/libc/math/lib_acosf.c +++ b/libc/math/lib_acosf.c @@ -37,5 +37,5 @@ float acosf(float x) { - return (M_PI_2 - asinf(x)); + return (M_PI_2_F - asinf(x)); } diff --git a/libc/math/lib_acoshf.c b/libc/math/lib_acoshf.c index a676d6a40e..4b42e968d7 100644 --- a/libc/math/lib_acoshf.c +++ b/libc/math/lib_acoshf.c @@ -48,5 +48,5 @@ float acoshf(float x) { - return logf(x + sqrtf(x * x - 1)); + return logf(x + sqrtf(x * x - 1.0F)); } diff --git a/libc/math/lib_asinf.c b/libc/math/lib_asinf.c index e22d32fe79..ac17a53944 100644 --- a/libc/math/lib_asinf.c +++ b/libc/math/lib_asinf.c @@ -47,9 +47,9 @@ float asinf(float x) y_sin = sinf(y); y_cos = cosf(y); - if (y > M_PI_2 || y < -M_PI_2) + if (y > M_PI_2_F || y < -M_PI_2_F) { - y = fmodf(y, M_PI); + y = fmodf(y, M_PI_F); } if (y_sin + FLT_EPSILON >= x && y_sin - FLT_EPSILON <= x) diff --git a/libc/math/lib_asinhf.c b/libc/math/lib_asinhf.c index ba749a6569..4c26d038ea 100644 --- a/libc/math/lib_asinhf.c +++ b/libc/math/lib_asinhf.c @@ -48,5 +48,5 @@ float asinhf(float x) { - return logf(x + sqrtf(x * x + 1)); + return logf(x + sqrtf(x * x + 1.0F)); } diff --git a/libc/math/lib_atan2f.c b/libc/math/lib_atan2f.c index 5d766df99d..c600161408 100644 --- a/libc/math/lib_atan2f.c +++ b/libc/math/lib_atan2f.c @@ -43,22 +43,22 @@ float atan2f(float y, float x) } else if (y >= 0 && x < 0) { - return atanf(y / x) + M_PI; + return atanf(y / x) + M_PI_F; } else if (y < 0) { if (x == 0) { - return -M_PI_2; + return -M_PI_2_F; } else /* Can only be x < 0 */ { - return atanf(y / x) - M_PI; + return atanf(y / x) - M_PI_F; } } else if (y > 0 && x == 0) { - return M_PI_2; + return M_PI_2_F; } else /* if (y == 0 && x == 0) Undefined but returns normally 0 */ { diff --git a/libc/math/lib_atanf.c b/libc/math/lib_atanf.c index c9835c6f24..aef149ed9e 100644 --- a/libc/math/lib_atanf.c +++ b/libc/math/lib_atanf.c @@ -39,5 +39,5 @@ float atanf(float x) { - return asinf(x / sqrtf(x * x + 1)); + return asinf(x / sqrtf(x * x + 1.0F)); } diff --git a/libc/math/lib_atanhf.c b/libc/math/lib_atanhf.c index 60a6696f73..a54090f517 100644 --- a/libc/math/lib_atanhf.c +++ b/libc/math/lib_atanhf.c @@ -48,5 +48,5 @@ float atanhf(float x) { - return 0.5 * logf((1 + x) / (1 - x)); + return 0.5F * logf((1.0F + x) / (1.0F - x)); } diff --git a/libc/math/lib_ceilf.c b/libc/math/lib_ceilf.c index 8378141abd..830f2a4769 100644 --- a/libc/math/lib_ceilf.c +++ b/libc/math/lib_ceilf.c @@ -38,9 +38,9 @@ float ceilf(float x) { modff(x, &x); - if (x > 0.0) + if (x > 0.0F) { - x += 1.0; + x += 1.0F; } return x; diff --git a/libc/math/lib_cosf.c b/libc/math/lib_cosf.c index 55ba93c1c8..5532894b02 100644 --- a/libc/math/lib_cosf.c +++ b/libc/math/lib_cosf.c @@ -37,5 +37,5 @@ float cosf(float x) { - return sinf(x + M_PI_2); + return sinf(x + M_PI_2_F); } diff --git a/libc/math/lib_coshf.c b/libc/math/lib_coshf.c index 7cb575822f..37b4bf8e0f 100644 --- a/libc/math/lib_coshf.c +++ b/libc/math/lib_coshf.c @@ -38,5 +38,5 @@ float coshf(float x) { x = expf(x); - return ((x + (1.0 / x)) / 2.0); + return ((x + (1.0F / x)) / 2.0F); } diff --git a/libc/math/lib_erff.c b/libc/math/lib_erff.c index 75199c828c..364b7fe03c 100644 --- a/libc/math/lib_erff.c +++ b/libc/math/lib_erff.c @@ -57,14 +57,14 @@ float erff(float x) float t; float a1, a2, a3, a4, a5, p; - a1 = 0.254829592; - a2 = -0.284496736; - a3 = 1.421413741; - a4 = -1.453152027; - a5 = 1.061405429; - p = 0.3275911; + a1 = 0.254829592F; + a2 = -0.284496736F; + a3 = 1.421413741F; + a4 = -1.453152027F; + a5 = 1.061405429F; + p = 0.3275911F; sign = (x >= 0 ? 1 : -1); - t = 1.0/(1.0 + p*x); - return sign * (1.0 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * expf(-x * x)); + t = 1.0F/(1.0F + p*x); + return sign * (1.0F - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * expf(-x * x)); } diff --git a/libc/math/lib_expf.c b/libc/math/lib_expf.c index 4ce5208607..3e3cb02ed9 100644 --- a/libc/math/lib_expf.c +++ b/libc/math/lib_expf.c @@ -89,8 +89,8 @@ float expf(float x) /* Perform Taylor series approximation with eleven terms */ - value = 0.0; - x0 = 1.0; + value = 0.0F; + x0 = 1.0F; for (i = 0; i < 10; i++) { value += x0 * _flt_inv_fact[i]; @@ -99,11 +99,11 @@ float expf(float x) /* Multiply by exp of the integer component */ - value *= lib_expi(int_part); + value *= lib_expif(int_part); if (invert) { - return (1.0 / value); + return (1.0F / value); } else { diff --git a/libc/math/lib_floorf.c b/libc/math/lib_floorf.c index 4a4ef1a4f7..d2fac02d2d 100644 --- a/libc/math/lib_floorf.c +++ b/libc/math/lib_floorf.c @@ -38,9 +38,9 @@ float floorf(float x) { modff(x, &x); - if (x < 0.0) + if (x < 0.0F) { - x -= 1.0; + x -= 1.0F; } return x; diff --git a/libc/math/lib_frexpf.c b/libc/math/lib_frexpf.c index 6ec5aa7442..2f0421ccb9 100644 --- a/libc/math/lib_frexpf.c +++ b/libc/math/lib_frexpf.c @@ -38,5 +38,5 @@ float frexpf(float x, int *exponent) { *exponent = (int)ceilf(log2f(x)); - return x / ldexpf(1.0, *exponent); + return x / ldexpf(1.0F, *exponent); } diff --git a/libc/math/lib_ldexpf.c b/libc/math/lib_ldexpf.c index 12503438b8..d24d1384e7 100644 --- a/libc/math/lib_ldexpf.c +++ b/libc/math/lib_ldexpf.c @@ -37,5 +37,5 @@ float ldexpf(float x, int n) { - return (x * powf(2.0, (float)n)); + return (x * powf(2.0F, (float)n)); } diff --git a/libc/math/lib_log10f.c b/libc/math/lib_log10f.c index f0ec9b0589..aa810a0127 100644 --- a/libc/math/lib_log10f.c +++ b/libc/math/lib_log10f.c @@ -37,5 +37,5 @@ float log10f(float x) { - return (logf(x) / M_LN10); + return (logf(x) / (float)M_LN10); } diff --git a/libc/math/lib_log2f.c b/libc/math/lib_log2f.c index a2d351bb12..025b5de3b1 100644 --- a/libc/math/lib_log2f.c +++ b/libc/math/lib_log2f.c @@ -37,5 +37,5 @@ float log2f(float x) { - return (logf(x) / M_LN2); + return (logf(x) / (float)M_LN2); } diff --git a/libc/math/lib_logf.c b/libc/math/lib_logf.c index 80eff85c3c..2d097d228e 100644 --- a/libc/math/lib_logf.c +++ b/libc/math/lib_logf.c @@ -40,8 +40,8 @@ float logf(float x) { float y, y_old, ey, epsilon; - y = 0.0; - y_old = 1.0; + y = 0.0F; + y_old = 1.0F; epsilon = FLT_EPSILON; while (y > y_old + epsilon || y < y_old - epsilon) @@ -50,25 +50,25 @@ float logf(float x) ey = exp(y); y -= (ey - x) / ey; - if (y > 700.0) + if (y > 700.0F) { - y = 700.0; + y = 700.0F; } - if (y < -700.0) + if (y < -700.0F) { - y = -700.0; + y = -700.0F; } - epsilon = (fabs(y) > 1.0) ? fabs(y) * FLT_EPSILON : FLT_EPSILON; + epsilon = (fabsf(y) > 1.0F) ? fabsf(y) * FLT_EPSILON : FLT_EPSILON; } - if (y == 700.0) + if (y == 700.0F) { return INFINITY; } - if (y == -700.0) + if (y == -700.0F) { return INFINITY; } diff --git a/libc/math/lib_modff.c b/libc/math/lib_modff.c index ad07a4f70c..5934782b7b 100644 --- a/libc/math/lib_modff.c +++ b/libc/math/lib_modff.c @@ -37,14 +37,14 @@ float modff(float x, float *iptr) { - if (fabsf(x) >= 8388608.0) + if (fabsf(x) >= 8388608.0F) { *iptr = x; - return 0.0; + return 0.0F; } - else if (fabs(x) < 1.0) + else if (fabsf(x) < 1.0F) { - *iptr = 0.0; + *iptr = 0.0F; return x; } else diff --git a/libc/math/lib_rintf.c b/libc/math/lib_rintf.c index ca733e3d79..9a3c06df28 100644 --- a/libc/math/lib_rintf.c +++ b/libc/math/lib_rintf.c @@ -105,15 +105,15 @@ float rintf(float x) linteger = (long)x; fremainder = x - (float)linteger; - if (x < 0.0) + if (x < 0.0F) { /* fremainder should be in range 0 .. -1 */ - if (fremainder == -0.5) + if (fremainder == -0.5F) { linteger = ((linteger + 1) & ~1); } - else if (fremainder < -0.5) + else if (fremainder < -0.5F) { linteger--; } @@ -122,11 +122,11 @@ float rintf(float x) { /* fremainder should be in range 0 .. 1 */ - if (fremainder == 0.5) + if (fremainder == 0.5F) { linteger = ((linteger + 1) & ~1); } - else if (fremainder > 0.5) + else if (fremainder > 0.5F) { linteger++; } diff --git a/libc/math/lib_sinf.c b/libc/math/lib_sinf.c index 5f17eb212b..b7be087b90 100644 --- a/libc/math/lib_sinf.c +++ b/libc/math/lib_sinf.c @@ -58,31 +58,31 @@ float sinf(float x) /* Move x to [-pi, pi) */ - x = fmodf(x, 2 * M_PI); - if (x >= M_PI) + x = fmodf(x, 2 * M_PI_F); + if (x >= M_PI_F) { - x -= 2 * M_PI; + x -= 2 * M_PI_F; } - if (x < -M_PI) + if (x < -M_PI_F) { - x += 2 * M_PI; + x += 2 * M_PI_F; } /* Move x to [-pi/2, pi/2) */ - if (x >= M_PI_2) + if (x >= M_PI_2_F) { - x = M_PI - x; + x = M_PI_F - x; } - if (x < -M_PI_2) + if (x < -M_PI_2_F) { - x = -M_PI - x; + x = -M_PI_F - x; } x_squared = x * x; - sin_x = 0.0; + sin_x = 0.0F; /* Perform Taylor series approximation for sin(x) with six terms */ diff --git a/libc/math/lib_sinhf.c b/libc/math/lib_sinhf.c index 6b27f59508..baf353f34d 100644 --- a/libc/math/lib_sinhf.c +++ b/libc/math/lib_sinhf.c @@ -38,5 +38,5 @@ float sinhf(float x) { x = expf(x); - return ((x - (1.0 / x)) / 2.0); + return ((x - (1.0F / x)) / 2.0F); } diff --git a/libc/math/lib_sqrtf.c b/libc/math/lib_sqrtf.c index e1a107eb8b..918c1c9568 100644 --- a/libc/math/lib_sqrtf.c +++ b/libc/math/lib_sqrtf.c @@ -47,25 +47,25 @@ float sqrtf(float x) /* Filter out invalid/trivial inputs */ - if (x < 0.0) + if (x < 0.0F) { set_errno(EDOM); - return NAN; + return NAN_F; } if (isnan(x)) { - return NAN; + return NAN_F; } - if (isinf(x)) + if (isinf_f(x)) { - return INFINITY; + return INFINITY_F; } - if (x == 0.0) + if (x == 0.0F) { - return 0.0; + return 0.0F; } /* Guess square root (using bit manipulation) */ @@ -76,9 +76,9 @@ float sqrtf(float x) * definitely optimal */ - y = 0.5 * (y + x / y); - y = 0.5 * (y + x / y); - y = 0.5 * (y + x / y); + y = 0.5F * (y + x / y); + y = 0.5F * (y + x / y); + y = 0.5F * (y + x / y); return y; } diff --git a/libc/math/lib_tanhf.c b/libc/math/lib_tanhf.c index 70edb57ec4..ef56b133dc 100644 --- a/libc/math/lib_tanhf.c +++ b/libc/math/lib_tanhf.c @@ -38,7 +38,7 @@ float tanhf(float x) { float x0 = expf(x); - float x1 = 1.0 / x0; + float x1 = 1.0F / x0; return ((x0 + x1) / (x0 - x1)); }