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.

This commit is contained in:
David Alessio 2016-07-11 07:02:50 -06:00 committed by Gregory Nutt
parent 90917d9741
commit 261358f1f5
27 changed files with 84 additions and 74 deletions

View File

@ -93,10 +93,15 @@
#define NAN (0.0/0.0) #define NAN (0.0/0.0)
#define HUGE_VAL INFINITY #define HUGE_VAL INFINITY
#define INFINITY_F (1.0F/0.0F)
#define NAN_F (0.0F/0.0F)
#define isnan(x) ((x) != (x)) #define isnan(x) ((x) != (x))
#define isinf(x) (((x) == INFINITY) || ((x) == -INFINITY)) #define isinf(x) (((x) == INFINITY) || ((x) == -INFINITY))
#define isfinite(x) (!(isinf(x)) && (x != NAN)) #define isfinite(x) (!(isinf(x)) && (x != NAN))
#define isinf_f(x) (((x) == INFINITY_F) || ((x) == -INFINITY_F))
/* Exponential and Logarithmic constants ************************************/ /* Exponential and Logarithmic constants ************************************/
#define M_E 2.7182818284590452353602874713526625 #define M_E 2.7182818284590452353602874713526625
@ -116,6 +121,9 @@
#define M_2_PI 0.6366197723675813430755350534900574 #define M_2_PI 0.6366197723675813430755350534900574
#define M_2_SQRTPI 1.1283791670955125738961589031215452 #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 * Public Function Prototypes
****************************************************************************/ ****************************************************************************/

View File

@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
* libc/libc.h * 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 <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * 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 */ /* Defined in lib_expi.c */
#ifdef CONFIG_LIBM #ifdef CONFIG_LIBM
float lib_expif(size_t n);
double lib_expi(size_t n); double lib_expi(size_t n);
#endif #endif

View File

@ -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_truncl.c
CSRCS += lib_libexpi.c lib_libsqrtapprox.c CSRCS += lib_libexpi.c lib_libsqrtapprox.c
CSRCS += lib_libexpif.c
# Add the floating point math directory to the build # Add the floating point math directory to the build

View File

@ -37,5 +37,5 @@
float acosf(float x) float acosf(float x)
{ {
return (M_PI_2 - asinf(x)); return (M_PI_2_F - asinf(x));
} }

View File

@ -48,5 +48,5 @@
float acoshf(float x) float acoshf(float x)
{ {
return logf(x + sqrtf(x * x - 1)); return logf(x + sqrtf(x * x - 1.0F));
} }

View File

@ -47,9 +47,9 @@ float asinf(float x)
y_sin = sinf(y); y_sin = sinf(y);
y_cos = cosf(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) if (y_sin + FLT_EPSILON >= x && y_sin - FLT_EPSILON <= x)

View File

@ -48,5 +48,5 @@
float asinhf(float x) float asinhf(float x)
{ {
return logf(x + sqrtf(x * x + 1)); return logf(x + sqrtf(x * x + 1.0F));
} }

View File

@ -43,22 +43,22 @@ float atan2f(float y, float x)
} }
else if (y >= 0 && x < 0) else if (y >= 0 && x < 0)
{ {
return atanf(y / x) + M_PI; return atanf(y / x) + M_PI_F;
} }
else if (y < 0) else if (y < 0)
{ {
if (x == 0) if (x == 0)
{ {
return -M_PI_2; return -M_PI_2_F;
} }
else /* Can only be x < 0 */ 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) 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 */ else /* if (y == 0 && x == 0) Undefined but returns normally 0 */
{ {

View File

@ -39,5 +39,5 @@
float atanf(float x) float atanf(float x)
{ {
return asinf(x / sqrtf(x * x + 1)); return asinf(x / sqrtf(x * x + 1.0F));
} }

View File

@ -48,5 +48,5 @@
float atanhf(float x) float atanhf(float x)
{ {
return 0.5 * logf((1 + x) / (1 - x)); return 0.5F * logf((1.0F + x) / (1.0F - x));
} }

View File

@ -38,9 +38,9 @@
float ceilf(float x) float ceilf(float x)
{ {
modff(x, &x); modff(x, &x);
if (x > 0.0) if (x > 0.0F)
{ {
x += 1.0; x += 1.0F;
} }
return x; return x;

View File

@ -37,5 +37,5 @@
float cosf(float x) float cosf(float x)
{ {
return sinf(x + M_PI_2); return sinf(x + M_PI_2_F);
} }

View File

@ -38,5 +38,5 @@
float coshf(float x) float coshf(float x)
{ {
x = expf(x); x = expf(x);
return ((x + (1.0 / x)) / 2.0); return ((x + (1.0F / x)) / 2.0F);
} }

View File

@ -57,14 +57,14 @@ float erff(float x)
float t; float t;
float a1, a2, a3, a4, a5, p; float a1, a2, a3, a4, a5, p;
a1 = 0.254829592; a1 = 0.254829592F;
a2 = -0.284496736; a2 = -0.284496736F;
a3 = 1.421413741; a3 = 1.421413741F;
a4 = -1.453152027; a4 = -1.453152027F;
a5 = 1.061405429; a5 = 1.061405429F;
p = 0.3275911; p = 0.3275911F;
sign = (x >= 0 ? 1 : -1); sign = (x >= 0 ? 1 : -1);
t = 1.0/(1.0 + p*x); t = 1.0F/(1.0F + p*x);
return sign * (1.0 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * expf(-x * x)); return sign * (1.0F - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * expf(-x * x));
} }

View File

@ -89,8 +89,8 @@ float expf(float x)
/* Perform Taylor series approximation with eleven terms */ /* Perform Taylor series approximation with eleven terms */
value = 0.0; value = 0.0F;
x0 = 1.0; x0 = 1.0F;
for (i = 0; i < 10; i++) for (i = 0; i < 10; i++)
{ {
value += x0 * _flt_inv_fact[i]; value += x0 * _flt_inv_fact[i];
@ -99,11 +99,11 @@ float expf(float x)
/* Multiply by exp of the integer component */ /* Multiply by exp of the integer component */
value *= lib_expi(int_part); value *= lib_expif(int_part);
if (invert) if (invert)
{ {
return (1.0 / value); return (1.0F / value);
} }
else else
{ {

View File

@ -38,9 +38,9 @@
float floorf(float x) float floorf(float x)
{ {
modff(x, &x); modff(x, &x);
if (x < 0.0) if (x < 0.0F)
{ {
x -= 1.0; x -= 1.0F;
} }
return x; return x;

View File

@ -38,5 +38,5 @@
float frexpf(float x, int *exponent) float frexpf(float x, int *exponent)
{ {
*exponent = (int)ceilf(log2f(x)); *exponent = (int)ceilf(log2f(x));
return x / ldexpf(1.0, *exponent); return x / ldexpf(1.0F, *exponent);
} }

View File

@ -37,5 +37,5 @@
float ldexpf(float x, int n) float ldexpf(float x, int n)
{ {
return (x * powf(2.0, (float)n)); return (x * powf(2.0F, (float)n));
} }

View File

@ -37,5 +37,5 @@
float log10f(float x) float log10f(float x)
{ {
return (logf(x) / M_LN10); return (logf(x) / (float)M_LN10);
} }

View File

@ -37,5 +37,5 @@
float log2f(float x) float log2f(float x)
{ {
return (logf(x) / M_LN2); return (logf(x) / (float)M_LN2);
} }

View File

@ -40,8 +40,8 @@ float logf(float x)
{ {
float y, y_old, ey, epsilon; float y, y_old, ey, epsilon;
y = 0.0; y = 0.0F;
y_old = 1.0; y_old = 1.0F;
epsilon = FLT_EPSILON; epsilon = FLT_EPSILON;
while (y > y_old + epsilon || y < y_old - epsilon) while (y > y_old + epsilon || y < y_old - epsilon)
@ -50,25 +50,25 @@ float logf(float x)
ey = exp(y); ey = exp(y);
y -= (ey - x) / ey; 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; return INFINITY;
} }
if (y == -700.0) if (y == -700.0F)
{ {
return INFINITY; return INFINITY;
} }

View File

@ -37,14 +37,14 @@
float modff(float x, float *iptr) float modff(float x, float *iptr)
{ {
if (fabsf(x) >= 8388608.0) if (fabsf(x) >= 8388608.0F)
{ {
*iptr = x; *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; return x;
} }
else else

View File

@ -105,15 +105,15 @@ float rintf(float x)
linteger = (long)x; linteger = (long)x;
fremainder = x - (float)linteger; fremainder = x - (float)linteger;
if (x < 0.0) if (x < 0.0F)
{ {
/* fremainder should be in range 0 .. -1 */ /* fremainder should be in range 0 .. -1 */
if (fremainder == -0.5) if (fremainder == -0.5F)
{ {
linteger = ((linteger + 1) & ~1); linteger = ((linteger + 1) & ~1);
} }
else if (fremainder < -0.5) else if (fremainder < -0.5F)
{ {
linteger--; linteger--;
} }
@ -122,11 +122,11 @@ float rintf(float x)
{ {
/* fremainder should be in range 0 .. 1 */ /* fremainder should be in range 0 .. 1 */
if (fremainder == 0.5) if (fremainder == 0.5F)
{ {
linteger = ((linteger + 1) & ~1); linteger = ((linteger + 1) & ~1);
} }
else if (fremainder > 0.5) else if (fremainder > 0.5F)
{ {
linteger++; linteger++;
} }

View File

@ -58,31 +58,31 @@ float sinf(float x)
/* Move x to [-pi, pi) */ /* Move x to [-pi, pi) */
x = fmodf(x, 2 * M_PI); x = fmodf(x, 2 * M_PI_F);
if (x >= M_PI) 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) */ /* 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; x_squared = x * x;
sin_x = 0.0; sin_x = 0.0F;
/* Perform Taylor series approximation for sin(x) with six terms */ /* Perform Taylor series approximation for sin(x) with six terms */

View File

@ -38,5 +38,5 @@
float sinhf(float x) float sinhf(float x)
{ {
x = expf(x); x = expf(x);
return ((x - (1.0 / x)) / 2.0); return ((x - (1.0F / x)) / 2.0F);
} }

View File

@ -47,25 +47,25 @@ float sqrtf(float x)
/* Filter out invalid/trivial inputs */ /* Filter out invalid/trivial inputs */
if (x < 0.0) if (x < 0.0F)
{ {
set_errno(EDOM); set_errno(EDOM);
return NAN; return NAN_F;
} }
if (isnan(x)) 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) */ /* Guess square root (using bit manipulation) */
@ -76,9 +76,9 @@ float sqrtf(float x)
* definitely optimal * definitely optimal
*/ */
y = 0.5 * (y + x / y); y = 0.5F * (y + x / y);
y = 0.5 * (y + x / y); y = 0.5F * (y + x / y);
y = 0.5 * (y + x / y); y = 0.5F * (y + x / y);
return y; return y;
} }

View File

@ -38,7 +38,7 @@
float tanhf(float x) float tanhf(float x)
{ {
float x0 = expf(x); float x0 = expf(x);
float x1 = 1.0 / x0; float x1 = 1.0F / x0;
return ((x0 + x1) / (x0 - x1)); return ((x0 + x1) / (x0 - x1));
} }