Commit e29db08c authored by Ganesh Ajjanagadde's avatar Ganesh Ajjanagadde

lavu/libm: add exp10 support

exp10 is a function available in GNU libm. Looks like no other common
libm has it. This adds support for it to FFmpeg.

There are essentially 2 ways of handling the fallback:
1. Using pow(10, x)
2. Using exp2(M_LOG2_10 * x).

First one represents a Pareto improvement, with no speed or accuracy
regression anywhere, but speed improvement limited to GNU libm.

Second one represents a slight accuracy loss (relative error ~ 1e-13)
for non GNU libm. Speedup of > 2x is obtained on non GNU libm platforms,
~30% on GNU libm. These are "average case numbers", another benefit is
the lack of triggering of the well-known terrible worst case paths
through pow.

Based on reviews, second one chosen. Comment added accordingly.
Reviewed-by: 's avatarHendrik Leppkes <h.leppkes@gmail.com>
Reviewed-by: 's avatarMichael Niedermayer <michael@niedermayer.cc>
Reviewed-by: 's avatarRonald S. Bultje <rsbultje@gmail.com>
Signed-off-by: 's avatarGanesh Ajjanagadde <gajjanagadde@gmail.com>
parent 520a5d33
...@@ -1815,6 +1815,8 @@ MATH_FUNCS=" ...@@ -1815,6 +1815,8 @@ MATH_FUNCS="
copysign copysign
cosf cosf
erf erf
exp10
exp10f
exp2 exp2
exp2f exp2f
expf expf
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "config.h" #include "config.h"
#include "attributes.h" #include "attributes.h"
#include "intfloat.h" #include "intfloat.h"
#include "mathematics.h"
#if HAVE_MIPSFPU && HAVE_INLINE_ASM #if HAVE_MIPSFPU && HAVE_INLINE_ASM
#include "libavutil/mips/libm_mips.h" #include "libavutil/mips/libm_mips.h"
...@@ -292,6 +293,24 @@ static inline double erf(double z) ...@@ -292,6 +293,24 @@ static inline double erf(double z)
#define exp2f(x) ((float)exp2(x)) #define exp2f(x) ((float)exp2(x))
#endif /* HAVE_EXP2F */ #endif /* HAVE_EXP2F */
/* Somewhat inaccurate fallbacks, relative error ~ 1e-13 concentrated on very
small and very large values. For perfection accuracy-wise, should use pow.
Speed benefits (>2x average, with no super slow paths) deemed to be worth the
accuracy tradeoff */
#if !HAVE_EXP10
static av_always_inline double exp10(double x)
{
return exp2(M_LOG2_10 * x);
}
#endif /* HAVE_EXP10 */
#if !HAVE_EXP10F
static av_always_inline float exp10f(float x)
{
return exp2f(M_LOG2_10 * x);
}
#endif /* HAVE_EXP10F */
#if !HAVE_ISINF #if !HAVE_ISINF
#undef isinf #undef isinf
/* Note: these do not follow the BSD/Apple/GNU convention of returning -1 for /* Note: these do not follow the BSD/Apple/GNU convention of returning -1 for
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment