diff --git a/extra/simd_math.c b/extra/simd_math.c index 1a67435..7194102 100644 --- a/extra/simd_math.c +++ b/extra/simd_math.c @@ -174,6 +174,33 @@ simd_vector simd_exp(simd_vector x) return y; } +//---------------------------------------------------------------------------------------------------------------------- +// based on https://github.com/jeremybarnes/cephes/blob/master/single/exp2f.c +simd_vector simd_exp2(simd_vector x) +{ + // clamp values + x = simd_clamp(x, simd_splat(-127.f), simd_splat(127.f)); + simd_vector equal_to_zero = simd_cmp_eq(x, simd_splat_zero()); + + simd_vector i0 = simd_floor(x); + x = simd_sub(x, i0); + + simd_vector above_half = simd_cmp_gt(x, simd_splat(.5f)); + simd_vector one = simd_splat(1.f); + i0 = simd_select(i0, simd_add(i0, one), above_half); + x = simd_select(x, simd_sub(x, one), above_half); + + simd_vector px = simd_fmad(x, simd_splat(1.535336188319500E-004f), simd_splat(1.339887440266574E-003f)); + px = simd_fmad(px, x, simd_splat(9.618437357674640E-003f)); + px = simd_fmad(px, x, simd_splat(5.550332471162809E-002f)); + px = simd_fmad(px, x, simd_splat(2.402264791363012E-001f)); + px = simd_fmad(px, x, simd_splat(6.931472028550421E-001f)); + px = simd_fmad(px, x, one); + px = simd_ldexp(px, i0); + + return simd_select(px, one, equal_to_zero); +} + //---------------------------------------------------------------------------------------------------------------------- // based on http://gruntthepeon.free.fr/ssemath/ void simd_sincos(simd_vector x, simd_vector* s, simd_vector* c) diff --git a/extra/simd_math.h b/extra/simd_math.h index 66b653b..60d35d1 100644 --- a/extra/simd_math.h +++ b/extra/simd_math.h @@ -45,6 +45,9 @@ simd_vector simd_log2(simd_vector x); // max error : 1.108270880e-07 simd_vector simd_exp(simd_vector x); +// max error : 1.042427087e-07 +simd_vector simd_exp2(simd_vector x); + // max error : 4.768371582e-07 simd_vector simd_cbrt(simd_vector x); diff --git a/tests/test_simd_math.h b/tests/test_simd_math.h index 0f3d905..95ec5b2 100644 --- a/tests/test_simd_math.h +++ b/tests/test_simd_math.h @@ -157,6 +157,7 @@ SUITE(exponentiation) RUN_TESTp(generic_test, logf, simd_log, FLT_EPSILON, 1000.f, 1.e-06f, true, "simd_log"); RUN_TESTp(generic_test, log2f, simd_log2, FLT_EPSILON, 1.e20f, 3.e-07f, true, "simd_log2"); RUN_TESTp(generic_test, expf, simd_exp, -87.f, 87.f, 1.e-06f, true, "simd_exp"); + RUN_TESTp(generic_test, exp2f, simd_exp2, -126.f, 126.f, 2.e-07f, true, "simd_exp2"); RUN_TESTp(generic_test, expf, simd_approx_exp, -87.f, 87.f, 2.e-03f, true, "simd_approx_exp"); RUN_TESTp(generic_test, cbrtf, simd_cbrt, -100.f, 100.f, 2.e-07f, true, "simd_cbrt"); }