mirror of
https://git.musl-libc.org/git/musl
synced 2025-01-08 07:42:09 +03:00
first try at writing an efficient and "correct" exp10
this is a nonstandard function so it's not clear what conditions it should satisfy. my intent is that it be fast and exact for positive integral exponents when the result fits in the destination type, and fast and correctly rounded for small negative integral exponents. otherwise we aim for at most 1ulp error; it seems to differ from pow by at most 1ulp and it's often 2-5 times faster than pow.
This commit is contained in:
parent
63374ee233
commit
f681975577
@ -387,6 +387,10 @@ float y1f(float);
|
||||
long double y1l(long double);
|
||||
float ynf(int, float);
|
||||
long double ynl(int, long double);
|
||||
|
||||
double exp10(double);
|
||||
float exp10f(float);
|
||||
long double exp10l(long double);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
19
src/math/exp10.c
Normal file
19
src/math/exp10.c
Normal file
@ -0,0 +1,19 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <math.h>
|
||||
|
||||
double exp10(double x)
|
||||
{
|
||||
static const double p10[] = {
|
||||
1e-15, 1e-14, 1e-13, 1e-12, 1e-11, 1e-10,
|
||||
1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1,
|
||||
1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
|
||||
1e10, 1e11, 1e12, 1e13, 1e14, 1e15
|
||||
};
|
||||
double n, y = modf(x, &n);
|
||||
if (fabs(n) < 16) {
|
||||
if (!y) return p10[(int)n+15];
|
||||
y = exp2(3.32192809488736234787031942948939 * y);
|
||||
return y * p10[(int)n+15];
|
||||
}
|
||||
return pow(10.0, x);
|
||||
}
|
17
src/math/exp10f.c
Normal file
17
src/math/exp10f.c
Normal file
@ -0,0 +1,17 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <math.h>
|
||||
|
||||
float exp10f(float x)
|
||||
{
|
||||
static const float p10[] = {
|
||||
1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1,
|
||||
1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7
|
||||
};
|
||||
float n, y = modff(x, &n);
|
||||
if (fabsf(n) < 8) {
|
||||
if (!y) return p10[(int)n+7];
|
||||
y = exp2f(3.32192809488736234787031942948939f * y);
|
||||
return y * p10[(int)n+7];
|
||||
}
|
||||
return exp2(3.32192809488736234787031942948939 * x);
|
||||
}
|
19
src/math/exp10l.c
Normal file
19
src/math/exp10l.c
Normal file
@ -0,0 +1,19 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <math.h>
|
||||
|
||||
long double exp10l(long double x)
|
||||
{
|
||||
static const long double p10[] = {
|
||||
1e-15, 1e-14, 1e-13, 1e-12, 1e-11, 1e-10,
|
||||
1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1,
|
||||
1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
|
||||
1e10, 1e11, 1e12, 1e13, 1e14, 1e15
|
||||
};
|
||||
long double n, y = modfl(x, &n);
|
||||
if (fabsl(n) < 16) {
|
||||
if (!y) return p10[(int)n+15];
|
||||
y = exp2l(3.32192809488736234787031942948939L * y);
|
||||
return y * p10[(int)n+15];
|
||||
}
|
||||
return powl(10.0, x);
|
||||
}
|
Loading…
Reference in New Issue
Block a user