diff --git a/README.md b/README.md index ddf9828..2d2ca68 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Currently supported: - exp/exp2/exp10/expm1 - log/log2/log10/log1p - sinh/cosh/tanh -- arcsinh +- arcsinh/arccosh/ - sigmoid - Wright-Omega function - Dilogarithm function diff --git a/include/math_approx/math_approx.hpp b/include/math_approx/math_approx.hpp index 03aa4e0..bb3a47c 100644 --- a/include/math_approx/math_approx.hpp +++ b/include/math_approx/math_approx.hpp @@ -10,9 +10,8 @@ namespace math_approx #include "src/inverse_trig_approx.hpp" #include "src/pow_approx.hpp" #include "src/log_approx.hpp" -#include "src/tanh_approx.hpp" -#include "src/sinh_cosh_approx.hpp" -#include "src/asinh_approx.hpp" +#include "src/hyperbolic_trig_approx.hpp" +#include "src/inverse_hyperbolic_trig_approx.hpp" #include "src/sigmoid_approx.hpp" #include "src/wright_omega_approx.hpp" #include "src/polylogarithm_approx.hpp" diff --git a/include/math_approx/src/tanh_approx.hpp b/include/math_approx/src/hyperbolic_trig_approx.hpp similarity index 70% rename from include/math_approx/src/tanh_approx.hpp rename to include/math_approx/src/hyperbolic_trig_approx.hpp index 092a00d..059b921 100644 --- a/include/math_approx/src/tanh_approx.hpp +++ b/include/math_approx/src/hyperbolic_trig_approx.hpp @@ -1,9 +1,56 @@ #pragma once -#include "basic_math.hpp" +#include "pow_approx.hpp" namespace math_approx { +// ref: https://en.wikipedia.org/wiki/Hyperbolic_functions#Definitions +// sinh = (e^(2x) - 1) / (2e^x), cosh = (e^(2x) + 1) / (2e^x) +// let B = e^x, then sinh = (B^2 - 1) / (2B), cosh = (B^2 + 1) / (2B) +// simplifying, we get: sinh = 0.5 (B - 1/B), cosh = 0.5 (B + 1/B) + +/** Approximation of sinh(x), using exp(x) internally */ +template +constexpr T sinh (T x) +{ + using S = scalar_of_t; + auto B = exp (x); + auto Br = (S) 0.5 / B; + B *= (S) 0.5; + return B - Br; +} + +/** Approximation of cosh(x), using exp(x) internally */ +template +constexpr T cosh (T x) +{ + using S = scalar_of_t; + auto B = exp (x); + auto Br = (S) 0.5 / B; + B *= (S) 0.5; + return B + Br; +} + +/** + * Simultaneous pproximation of sinh(x) and cosh(x), + * using exp(x) internally. + * + * For more information see the comments above. + */ +template +constexpr auto sinh_cosh (T x) +{ + using S = scalar_of_t; + auto B = exp (x); + auto Br = (S) 0.5 / B; + B *= (S) 0.5; + + auto sinh = B - Br; + auto cosh = B + Br; + + return std::make_pair (sinh, cosh); +} + namespace tanh_detail { // These polynomial fits were generated from: https://www.wolframcloud.com/obj/chowdsp/Published/tanh_approx.nb diff --git a/include/math_approx/src/asinh_approx.hpp b/include/math_approx/src/inverse_hyperbolic_trig_approx.hpp similarity index 88% rename from include/math_approx/src/asinh_approx.hpp rename to include/math_approx/src/inverse_hyperbolic_trig_approx.hpp index c2db5e3..4436987 100644 --- a/include/math_approx/src/asinh_approx.hpp +++ b/include/math_approx/src/inverse_hyperbolic_trig_approx.hpp @@ -1,5 +1,6 @@ #pragma once +#include "basic_math.hpp" #include "log_approx.hpp" namespace math_approx @@ -55,11 +56,9 @@ template constexpr T asinh (T x) { using S = scalar_of_t; - using std::abs; - using std::sqrt; + using std::abs, std::sqrt; #if defined(XSIMD_HPP) - using xsimd::abs; - using xsimd::sqrt; + using xsimd::abs, xsimd::sqrt; #endif const auto sign = select (x > (S) 0, (T) (S) 1, select (x < (S) 0, (T) (S) -1, (T) (S) 0)); @@ -76,4 +75,18 @@ constexpr T asinh (T x) return sign * y; } -} // namespace math_approx + +template +constexpr T acosh (T x) +{ + using S = scalar_of_t; + using std::sqrt; +#if defined(XSIMD_HPP) + using xsimd::sqrt; +#endif + + const auto z0 = x - (S) 1; + const auto z1 = z0 + sqrt (z0 + z0 + z0 * z0); + return log1p (z1); +} +} diff --git a/include/math_approx/src/sinh_cosh_approx.hpp b/include/math_approx/src/sinh_cosh_approx.hpp deleted file mode 100644 index 6dab976..0000000 --- a/include/math_approx/src/sinh_cosh_approx.hpp +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once - -#include "pow_approx.hpp" - -namespace math_approx -{ -// ref: https://en.wikipedia.org/wiki/Hyperbolic_functions#Definitions -// sinh = (e^(2x) - 1) / (2e^x), cosh = (e^(2x) + 1) / (2e^x) -// let B = e^x, then sinh = (B^2 - 1) / (2B), cosh = (B^2 + 1) / (2B) -// simplifying, we get: sinh = 0.5 (B - 1/B), cosh = 0.5 (B + 1/B) - -/** Approximation of sinh(x), using exp(x) internally */ -template -constexpr T sinh (T x) -{ - using S = scalar_of_t; - auto B = exp (x); - auto Br = (S) 0.5 / B; - B *= (S) 0.5; - return B - Br; -} - -/** Approximation of cosh(x), using exp(x) internally */ -template -constexpr T cosh (T x) -{ - using S = scalar_of_t; - auto B = exp (x); - auto Br = (S) 0.5 / B; - B *= (S) 0.5; - return B + Br; -} - -/** - * Simultaneous pproximation of sinh(x) and cosh(x), - * using exp(x) internally. - * - * For more information see the comments above. - */ -template -constexpr auto sinh_cosh (T x) -{ - using S = scalar_of_t; - auto B = exp (x); - auto Br = (S) 0.5 / B; - B *= (S) 0.5; - - auto sinh = B - Br; - auto cosh = B + Br; - - return std::make_pair (sinh, cosh); -} -} // namespace math_approx diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 4f4420a..e4b953b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -28,13 +28,12 @@ function(setup_catch_test target) catch_discover_tests(${target} TEST_PREFIX ${target}_) endfunction(setup_catch_test) -setup_catch_test(tanh_approx_test) -setup_catch_test(sigmoid_approx_test) setup_catch_test(trig_approx_test) setup_catch_test(inverse_trig_approx_test) setup_catch_test(pow_approx_test) setup_catch_test(log_approx_test) +setup_catch_test(hyperbolic_trig_approx_test) +setup_catch_test(inverse_hyperbolic_trig_approx_test) +setup_catch_test(sigmoid_approx_test) setup_catch_test(wright_omega_approx_test) setup_catch_test(polylog_approx_test) -setup_catch_test(sinh_cosh_approx_test) -setup_catch_test(asinh_approx_test) diff --git a/test/src/sinh_cosh_approx_test.cpp b/test/src/hyperbolic_trig_approx_test.cpp similarity index 67% rename from test/src/sinh_cosh_approx_test.cpp rename to test/src/hyperbolic_trig_approx_test.cpp index 9acb6c9..30d0a27 100644 --- a/test/src/sinh_cosh_approx_test.cpp +++ b/test/src/hyperbolic_trig_approx_test.cpp @@ -145,3 +145,74 @@ TEST_CASE ("Cosh Approx Test") 0); } } + +TEST_CASE ("Tanh Approx Test") +{ +#if ! defined(WIN32) + const auto all_floats = test_helpers::all_32_bit_floats (-10.0f, 10.0f, 1.0e-2f); +#else + const auto all_floats = test_helpers::all_32_bit_floats (-10.0f, 10.0f, 1.0e-1f); +#endif + const auto y_exact = test_helpers::compute_all (all_floats, [] (auto x) + { return std::tanh (x); }); + + const auto test_approx = [&all_floats, &y_exact] (auto&& f_approx, float err_bound, float rel_err_bound, uint32_t ulp_bound) + { + const auto y_approx = test_helpers::compute_all (all_floats, f_approx); + + const auto error = test_helpers::compute_error (y_exact, y_approx); + const auto rel_error = test_helpers::compute_rel_error (y_exact, y_approx); + const auto ulp_error = test_helpers::compute_ulp_error (y_exact, y_approx); + + const auto max_error = test_helpers::abs_max (error); + const auto max_rel_error = test_helpers::abs_max (rel_error); + const auto max_ulp_error = *std::max_element (ulp_error.begin(), ulp_error.end()); + + std::cout << max_error << ", " << max_rel_error << ", " << max_ulp_error << std::endl; + REQUIRE (std::abs (max_error) < err_bound); + REQUIRE (std::abs (max_rel_error) < rel_err_bound); + if (ulp_bound > 0) + REQUIRE (max_ulp_error < ulp_bound); + }; + + SECTION ("11th-Order") + { + test_approx ([] (auto x) + { return math_approx::tanh<11> (x); }, + 2.5e-7f, + 4.0e-7f, + 7); + } + SECTION ("9th-Order") + { + test_approx ([] (auto x) + { return math_approx::tanh<9> (x); }, + 1.5e-6f, + 1.5e-6f, + 20); + } + SECTION ("7th-Order") + { + test_approx ([] (auto x) + { return math_approx::tanh<7> (x); }, + 1.5e-5f, + 1.5e-5f, + 230); + } + SECTION ("5th-Order") + { + test_approx ([] (auto x) + { return math_approx::tanh<5> (x); }, + 2.5e-4f, + 2.5e-4f, + 0); + } + SECTION ("3th-Order") + { + test_approx ([] (auto x) + { return math_approx::tanh<3> (x); }, + 4.0e-3f, + 4.0e-3f, + 0); + } +} diff --git a/test/src/asinh_approx_test.cpp b/test/src/inverse_hyperbolic_trig_approx_test.cpp similarity index 62% rename from test/src/asinh_approx_test.cpp rename to test/src/inverse_hyperbolic_trig_approx_test.cpp index 7a52464..3f3dfb1 100644 --- a/test/src/asinh_approx_test.cpp +++ b/test/src/inverse_hyperbolic_trig_approx_test.cpp @@ -52,3 +52,35 @@ TEMPLATE_TEST_CASE ("Asinh Approx Test", "", float, double) 2.5e-3f); } } + +TEMPLATE_TEST_CASE ("Acosh Approx Test", "", float, double) +{ + const auto all_floats = test_helpers::all_32_bit_floats (1.0f, 10.0f, 1.0e-2f); + const auto y_exact = test_helpers::compute_all (all_floats, [] (auto x) + { return std::acosh (x); }); + + SECTION ("6th-Order") + { + test_approx (all_floats, y_exact, [] (auto x) + { return math_approx::acosh<6> (x); }, + 3.5e-6f); + } + SECTION ("5th-Order") + { + test_approx (all_floats, y_exact, [] (auto x) + { return math_approx::acosh<5> (x); }, + 1.5e-5f); + } + SECTION ("4th-Order") + { + test_approx (all_floats, y_exact, [] (auto x) + { return math_approx::acosh<4> (x); }, + 8.5e-5f); + } + SECTION ("3th-Order") + { + test_approx (all_floats, y_exact, [] (auto x) + { return math_approx::acosh<3> (x); }, + 6.5e-4f); + } +} diff --git a/test/src/tanh_approx_test.cpp b/test/src/tanh_approx_test.cpp deleted file mode 100644 index 91b0130..0000000 --- a/test/src/tanh_approx_test.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include "test_helpers.hpp" -#include -#include - -#include - -TEST_CASE ("Tanh Approx Test") -{ -#if ! defined(WIN32) - const auto all_floats = test_helpers::all_32_bit_floats (-10.0f, 10.0f, 1.0e-2f); -#else - const auto all_floats = test_helpers::all_32_bit_floats (-10.0f, 10.0f, 1.0e-1f); -#endif - const auto y_exact = test_helpers::compute_all (all_floats, [] (auto x) - { return std::tanh (x); }); - - const auto test_approx = [&all_floats, &y_exact] (auto&& f_approx, float err_bound, float rel_err_bound, uint32_t ulp_bound) - { - const auto y_approx = test_helpers::compute_all (all_floats, f_approx); - - const auto error = test_helpers::compute_error (y_exact, y_approx); - const auto rel_error = test_helpers::compute_rel_error (y_exact, y_approx); - const auto ulp_error = test_helpers::compute_ulp_error (y_exact, y_approx); - - const auto max_error = test_helpers::abs_max (error); - const auto max_rel_error = test_helpers::abs_max (rel_error); - const auto max_ulp_error = *std::max_element (ulp_error.begin(), ulp_error.end()); - - std::cout << max_error << ", " << max_rel_error << ", " << max_ulp_error << std::endl; - REQUIRE (std::abs (max_error) < err_bound); - REQUIRE (std::abs (max_rel_error) < rel_err_bound); - if (ulp_bound > 0) - REQUIRE (max_ulp_error < ulp_bound); - }; - - SECTION ("11th-Order") - { - test_approx ([] (auto x) - { return math_approx::tanh<11> (x); }, - 2.5e-7f, - 4.0e-7f, - 7); - } - SECTION ("9th-Order") - { - test_approx ([] (auto x) - { return math_approx::tanh<9> (x); }, - 1.5e-6f, - 1.5e-6f, - 20); - } - SECTION ("7th-Order") - { - test_approx ([] (auto x) - { return math_approx::tanh<7> (x); }, - 1.5e-5f, - 1.5e-5f, - 230); - } - SECTION ("5th-Order") - { - test_approx ([] (auto x) - { return math_approx::tanh<5> (x); }, - 2.5e-4f, - 2.5e-4f, - 0); - } - SECTION ("3th-Order") - { - test_approx ([] (auto x) - { return math_approx::tanh<3> (x); }, - 4.0e-3f, - 4.0e-3f, - 0); - } -} diff --git a/tools/bench/CMakeLists.txt b/tools/bench/CMakeLists.txt index 5b5b279..8c036ef 100644 --- a/tools/bench/CMakeLists.txt +++ b/tools/bench/CMakeLists.txt @@ -10,12 +10,6 @@ CPMAddPackage( OPTIONS "BENCHMARK_ENABLE_TESTING Off" ) -add_executable(tanh_approx_bench tanh_bench.cpp) -target_link_libraries(tanh_approx_bench PRIVATE benchmark::benchmark math_approx) - -add_executable(sigmoid_approx_bench sigmoid_bench.cpp) -target_link_libraries(sigmoid_approx_bench PRIVATE benchmark::benchmark math_approx) - add_executable(trig_approx_bench trig_bench.cpp) target_link_libraries(trig_approx_bench PRIVATE benchmark::benchmark math_approx) @@ -28,14 +22,17 @@ target_link_libraries(pow_approx_bench PRIVATE benchmark::benchmark math_approx) add_executable(log_approx_bench log_bench.cpp) target_link_libraries(log_approx_bench PRIVATE benchmark::benchmark math_approx) +add_executable(hyperbolic_trig_approx_bench hyperbolic_trig_bench.cpp) +target_link_libraries(hyperbolic_trig_approx_bench PRIVATE benchmark::benchmark math_approx) + +add_executable(inverse_hyperbolic_trig_approx_bench inverse_hyperbolic_trig_bench.cpp) +target_link_libraries(inverse_hyperbolic_trig_approx_bench PRIVATE benchmark::benchmark math_approx) + +add_executable(sigmoid_approx_bench sigmoid_bench.cpp) +target_link_libraries(sigmoid_approx_bench PRIVATE benchmark::benchmark math_approx) + add_executable(wright_omega_approx_bench wright_omega_bench.cpp) target_link_libraries(wright_omega_approx_bench PRIVATE benchmark::benchmark math_approx) add_executable(polylog_approx_bench polylog_bench.cpp) target_link_libraries(polylog_approx_bench PRIVATE benchmark::benchmark math_approx) - -add_executable(sinh_cosh_approx_bench sinh_cosh_bench.cpp) -target_link_libraries(sinh_cosh_approx_bench PRIVATE benchmark::benchmark math_approx) - -add_executable(asinh_approx_bench asinh_bench.cpp) -target_link_libraries(asinh_approx_bench PRIVATE benchmark::benchmark math_approx) diff --git a/tools/bench/asinh_bench.cpp b/tools/bench/asinh_bench.cpp deleted file mode 100644 index 31c7685..0000000 --- a/tools/bench/asinh_bench.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include -#include - -static constexpr size_t N = 2000; -const auto data = [] -{ - std::vector x; - x.resize (N, 0.0f); - for (size_t i = 0; i < N; ++i) - x[i] = -10.0f + 20.0f * (float) i / (float) N; - return x; -}(); - -#define ASINH_BENCH(name, func) \ -void name (benchmark::State& state) \ -{ \ -for (auto _ : state) \ -{ \ -for (auto& x : data) \ -{ \ -auto y = func (x); \ -benchmark::DoNotOptimize (y); \ -} \ -} \ -} \ -BENCHMARK (name); -ASINH_BENCH (asinh_std, std::asinh) -ASINH_BENCH (asinh_approx7, math_approx::asinh<7>) -ASINH_BENCH (asinh_approx6, math_approx::asinh<6>) -ASINH_BENCH (asinh_approx5, math_approx::asinh<5>) -ASINH_BENCH (asinh_approx4, math_approx::asinh<4>) -ASINH_BENCH (asinh_approx3, math_approx::asinh<3>) - -#define ASINH_SIMD_BENCH(name, func) \ -void name (benchmark::State& state) \ -{ \ -for (auto _ : state) \ -{ \ -for (auto& x : data) \ -{ \ -auto y = func (xsimd::broadcast (x)); \ -static_assert (std::is_same_v, decltype(y)>); \ -benchmark::DoNotOptimize (y); \ -} \ -} \ -} \ -BENCHMARK (name); -ASINH_SIMD_BENCH (asinh_xsimd, xsimd::asinh) -ASINH_SIMD_BENCH (asinh_simd_approx7, math_approx::asinh<7>) -ASINH_SIMD_BENCH (asinh_simd_approx6, math_approx::asinh<6>) -ASINH_SIMD_BENCH (asinh_simd_approx5, math_approx::asinh<5>) -ASINH_SIMD_BENCH (asinh_simd_approx4, math_approx::asinh<4>) -ASINH_SIMD_BENCH (asinh_simd_approx3, math_approx::asinh<3>) - -BENCHMARK_MAIN(); diff --git a/tools/bench/hyperbolic_trig_bench.cpp b/tools/bench/hyperbolic_trig_bench.cpp new file mode 100644 index 0000000..2c0ea41 --- /dev/null +++ b/tools/bench/hyperbolic_trig_bench.cpp @@ -0,0 +1,77 @@ +#include +#include + +static constexpr size_t N = 2000; +const auto data = [] +{ + std::vector x; + x.resize (N, 0.0f); + for (size_t i = 0; i < N; ++i) + x[i] = -10.0f + 20.0f * (float) i / (float) N; + return x; +}(); + +#define HTRIG_BENCH(name, func) \ +void name (benchmark::State& state) \ +{ \ +for (auto _ : state) \ +{ \ +for (auto& x : data) \ +{ \ +auto y = func (x); \ +benchmark::DoNotOptimize (y); \ +} \ +} \ +} \ +BENCHMARK (name); +HTRIG_BENCH (sinh_std, std::sinh) +HTRIG_BENCH (sinh_approx6, math_approx::sinh<6>) +HTRIG_BENCH (sinh_approx5, math_approx::sinh<5>) +HTRIG_BENCH (sinh_approx4, math_approx::sinh<4>) +HTRIG_BENCH (sinh_approx3, math_approx::sinh<3>) + +HTRIG_BENCH (cosh_std, std::sinh) +HTRIG_BENCH (cosh_approx6, math_approx::cosh<6>) +HTRIG_BENCH (cosh_approx5, math_approx::cosh<5>) +HTRIG_BENCH (cosh_approx4, math_approx::cosh<4>) +HTRIG_BENCH (cosh_approx3, math_approx::cosh<3>) + +HTRIG_BENCH (tanh_std, std::tanh) +HTRIG_BENCH (tanh_approx11, math_approx::tanh<11>) +HTRIG_BENCH (tanh_approx9, math_approx::tanh<9>) +HTRIG_BENCH (tanh_approx7, math_approx::tanh<7>) +HTRIG_BENCH (tanh_approx5, math_approx::tanh<5>) + +#define HTRIG_SIMD_BENCH(name, func) \ +void name (benchmark::State& state) \ +{ \ +for (auto _ : state) \ +{ \ +for (auto& x : data) \ +{ \ +auto y = func (xsimd::broadcast (x)); \ +static_assert (std::is_same_v, decltype(y)>); \ +benchmark::DoNotOptimize (y); \ +} \ +} \ +} \ +BENCHMARK (name); +HTRIG_SIMD_BENCH (sinh_xsimd, xsimd::tanh) +HTRIG_SIMD_BENCH (sinh_simd_approx6, math_approx::sinh<6>) +HTRIG_SIMD_BENCH (sinh_simd_approx5, math_approx::sinh<5>) +HTRIG_SIMD_BENCH (sinh_simd_approx4, math_approx::sinh<4>) +HTRIG_SIMD_BENCH (sinh_simd_approx3, math_approx::sinh<3>) + +HTRIG_SIMD_BENCH (cosh_xsimd, xsimd::tanh) +HTRIG_SIMD_BENCH (cosh_simd_approx6, math_approx::cosh<6>) +HTRIG_SIMD_BENCH (cosh_simd_approx5, math_approx::cosh<5>) +HTRIG_SIMD_BENCH (cosh_simd_approx4, math_approx::cosh<4>) +HTRIG_SIMD_BENCH (cosh_simd_approx3, math_approx::cosh<3>) + +HTRIG_SIMD_BENCH (tanh_xsimd, xsimd::tanh) +HTRIG_SIMD_BENCH (tanh_simd_approx11, math_approx::tanh<11>) +HTRIG_SIMD_BENCH (tanh_simd_approx9, math_approx::tanh<9>) +HTRIG_SIMD_BENCH (tanh_simd_approx7, math_approx::tanh<7>) +HTRIG_SIMD_BENCH (tanh_simd_approx5, math_approx::tanh<5>) + +BENCHMARK_MAIN(); diff --git a/tools/bench/inverse_hyperbolic_trig_bench.cpp b/tools/bench/inverse_hyperbolic_trig_bench.cpp new file mode 100644 index 0000000..195dc60 --- /dev/null +++ b/tools/bench/inverse_hyperbolic_trig_bench.cpp @@ -0,0 +1,78 @@ +#include +#include + +static constexpr size_t N = 2000; +const auto data_asinh = [] +{ + std::vector x; + x.resize (N, 0.0f); + for (size_t i = 0; i < N; ++i) + x[i] = -10.0f + 20.0f * (float) i / (float) N; + return x; +}(); + +const auto data_acosh = [] +{ + std::vector x; + x.resize (N, 0.0f); + for (size_t i = 0; i < N; ++i) + x[i] = 1.0f + 9.0f * (float) i / (float) N; + return x; +}(); + +#define INV_HTRIG_BENCH(name, func, data) \ +void name (benchmark::State& state) \ +{ \ +for (auto _ : state) \ +{ \ +for (auto& x : data) \ +{ \ +auto y = func (x); \ +benchmark::DoNotOptimize (y); \ +} \ +} \ +} \ +BENCHMARK (name); + +INV_HTRIG_BENCH (asinh_std, std::asinh, data_asinh) +INV_HTRIG_BENCH (asinh_approx7, math_approx::asinh<7>, data_asinh) +INV_HTRIG_BENCH (asinh_approx6, math_approx::asinh<6>, data_asinh) +INV_HTRIG_BENCH (asinh_approx5, math_approx::asinh<5>, data_asinh) +INV_HTRIG_BENCH (asinh_approx4, math_approx::asinh<4>, data_asinh) +INV_HTRIG_BENCH (asinh_approx3, math_approx::asinh<3>, data_asinh) + +INV_HTRIG_BENCH (acosh_std, std::acosh, data_acosh) +INV_HTRIG_BENCH (acosh_approx6, math_approx::acosh<6>, data_acosh) +INV_HTRIG_BENCH (acosh_approx5, math_approx::acosh<5>, data_acosh) +INV_HTRIG_BENCH (acosh_approx4, math_approx::acosh<4>, data_acosh) +INV_HTRIG_BENCH (acosh_approx3, math_approx::acosh<3>, data_acosh) + +#define INV_HTRIG_SIMD_BENCH(name, func, data) \ +void name (benchmark::State& state) \ +{ \ +for (auto _ : state) \ +{ \ +for (auto& x : data) \ +{ \ +auto y = func (xsimd::broadcast (x)); \ +static_assert (std::is_same_v, decltype(y)>); \ +benchmark::DoNotOptimize (y); \ +} \ +} \ +} \ +BENCHMARK (name); + +INV_HTRIG_SIMD_BENCH (asinh_xsimd, xsimd::asinh, data_asinh) +INV_HTRIG_SIMD_BENCH (asinh_simd_approx7, math_approx::asinh<7>, data_asinh) +INV_HTRIG_SIMD_BENCH (asinh_simd_approx6, math_approx::asinh<6>, data_asinh) +INV_HTRIG_SIMD_BENCH (asinh_simd_approx5, math_approx::asinh<5>, data_asinh) +INV_HTRIG_SIMD_BENCH (asinh_simd_approx4, math_approx::asinh<4>, data_asinh) +INV_HTRIG_SIMD_BENCH (asinh_simd_approx3, math_approx::asinh<3>, data_asinh) + +INV_HTRIG_SIMD_BENCH (acosh_xsimd, xsimd::acosh, data_acosh) +INV_HTRIG_SIMD_BENCH (acosh_simd_approx6, math_approx::acosh<6>, data_acosh) +INV_HTRIG_SIMD_BENCH (acosh_simd_approx5, math_approx::acosh<5>, data_acosh) +INV_HTRIG_SIMD_BENCH (acosh_simd_approx4, math_approx::acosh<4>, data_acosh) +INV_HTRIG_SIMD_BENCH (acosh_simd_approx3, math_approx::acosh<3>, data_acosh) + +BENCHMARK_MAIN(); diff --git a/tools/bench/sinh_cosh_bench.cpp b/tools/bench/sinh_cosh_bench.cpp deleted file mode 100644 index a32df9f..0000000 --- a/tools/bench/sinh_cosh_bench.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include -#include - -static constexpr size_t N = 2000; -const auto data = [] -{ - std::vector x; - x.resize (N, 0.0f); - for (size_t i = 0; i < N; ++i) - x[i] = -10.0f + 20.0f * (float) i / (float) N; - return x; -}(); - -#define TANH_BENCH(name, func) \ -void name (benchmark::State& state) \ -{ \ -for (auto _ : state) \ -{ \ -for (auto& x : data) \ -{ \ -auto y = func (x); \ -benchmark::DoNotOptimize (y); \ -} \ -} \ -} \ -BENCHMARK (name); -TANH_BENCH (sinh_std, std::sinh) -TANH_BENCH (sinh_approx6, math_approx::sinh<6>) -TANH_BENCH (sinh_approx5, math_approx::sinh<5>) -TANH_BENCH (sinh_approx4, math_approx::sinh<4>) -TANH_BENCH (sinh_approx3, math_approx::sinh<3>) - -TANH_BENCH (cosh_std, std::sinh) -TANH_BENCH (cosh_approx6, math_approx::cosh<6>) -TANH_BENCH (cosh_approx5, math_approx::cosh<5>) -TANH_BENCH (cosh_approx4, math_approx::cosh<4>) -TANH_BENCH (cosh_approx3, math_approx::cosh<3>) - -#define TANH_SIMD_BENCH(name, func) \ -void name (benchmark::State& state) \ -{ \ -for (auto _ : state) \ -{ \ -for (auto& x : data) \ -{ \ -auto y = func (xsimd::broadcast (x)); \ -static_assert (std::is_same_v, decltype(y)>); \ -benchmark::DoNotOptimize (y); \ -} \ -} \ -} \ -BENCHMARK (name); -TANH_SIMD_BENCH (sinh_xsimd, xsimd::tanh) -TANH_SIMD_BENCH (sinh_simd_approx6, math_approx::sinh<6>) -TANH_SIMD_BENCH (sinh_simd_approx5, math_approx::sinh<5>) -TANH_SIMD_BENCH (sinh_simd_approx4, math_approx::sinh<4>) -TANH_SIMD_BENCH (sinh_simd_approx3, math_approx::sinh<3>) - -TANH_SIMD_BENCH (cosh_xsimd, xsimd::tanh) -TANH_SIMD_BENCH (cosh_simd_approx6, math_approx::cosh<6>) -TANH_SIMD_BENCH (cosh_simd_approx5, math_approx::cosh<5>) -TANH_SIMD_BENCH (cosh_simd_approx4, math_approx::cosh<4>) -TANH_SIMD_BENCH (cosh_simd_approx3, math_approx::cosh<3>) - -BENCHMARK_MAIN(); diff --git a/tools/bench/tanh_bench.cpp b/tools/bench/tanh_bench.cpp deleted file mode 100644 index b9de365..0000000 --- a/tools/bench/tanh_bench.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include -#include - -static constexpr size_t N = 2000; -const auto data = [] -{ - std::vector x; - x.resize (N, 0.0f); - for (size_t i = 0; i < N; ++i) - x[i] = -10.0f + 20.0f * (float) i / (float) N; - return x; -}(); - -#define TANH_BENCH(name, func) \ -void name (benchmark::State& state) \ -{ \ - for (auto _ : state) \ - { \ - for (auto& x : data) \ - { \ - auto y = func (x); \ - benchmark::DoNotOptimize (y); \ - } \ - } \ -} \ -BENCHMARK (name); -TANH_BENCH (tanh_std, std::tanh) -TANH_BENCH (tanh_approx11, math_approx::tanh<11>) -TANH_BENCH (tanh_approx9, math_approx::tanh<9>) -TANH_BENCH (tanh_approx7, math_approx::tanh<7>) -TANH_BENCH (tanh_approx5, math_approx::tanh<5>) - -#define TANH_SIMD_BENCH(name, func) \ -void name (benchmark::State& state) \ -{ \ - for (auto _ : state) \ - { \ - for (auto& x : data) \ - { \ - auto y = func (xsimd::broadcast (x)); \ - static_assert (std::is_same_v, decltype(y)>); \ - benchmark::DoNotOptimize (y); \ - } \ - } \ -} \ -BENCHMARK (name); -TANH_SIMD_BENCH (tanh_xsimd, xsimd::tanh) -TANH_SIMD_BENCH (tanh_simd_approx11, math_approx::tanh<11>) -TANH_SIMD_BENCH (tanh_simd_approx9, math_approx::tanh<9>) -TANH_SIMD_BENCH (tanh_simd_approx7, math_approx::tanh<7>) -TANH_SIMD_BENCH (tanh_simd_approx5, math_approx::tanh<5>) - -BENCHMARK_MAIN(); diff --git a/tools/plotter/plotter.cpp b/tools/plotter/plotter.cpp index d939c12..344490c 100644 --- a/tools/plotter/plotter.cpp +++ b/tools/plotter/plotter.cpp @@ -61,12 +61,12 @@ void plot_function (std::span all_floats, int main() { plt::figure(); - const auto range = std::make_pair (-10.0f, 10.0f); + const auto range = std::make_pair (1.0f, 10.0f); static constexpr auto tol = 1.0e-2f; const auto all_floats = test_helpers::all_32_bit_floats (range.first, range.second, tol); - const auto y_exact = test_helpers::compute_all (all_floats, FLOAT_FUNC (std::atan)); - plot_error (all_floats, y_exact, FLOAT_FUNC ((math_approx::atan<4>) ), "atan-4"); + const auto y_exact = test_helpers::compute_all (all_floats, FLOAT_FUNC (std::acosh)); + plot_ulp_error (all_floats, y_exact, FLOAT_FUNC ((math_approx::acosh<6>) ), "acosh-6"); plt::legend ({ { "loc", "upper right" } }); plt::xlim (range.first, range.second);