Skip to content

Commit

Permalink
Add arctanh implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
jatinchowdhury18 committed Jan 7, 2024
1 parent d999596 commit 58d98dc
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 4 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Currently supported:
- exp/exp2/exp10/expm1
- log/log2/log10/log1p
- sinh/cosh/tanh
- arcsinh/arccosh/
- arcsinh/arccosh/arctanh
- sigmoid
- Wright-Omega function
- Dilogarithm function
Expand Down
7 changes: 7 additions & 0 deletions include/math_approx/src/inverse_hyperbolic_trig_approx.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,11 @@ constexpr T acosh (T x)
const auto z1 = z0 + sqrt (z0 + z0 + z0 * z0);
return log1p<order> (z1);
}

template <int order, typename T>
constexpr T atanh (T x)
{
using S = scalar_of_t<T>;
return (S) 0.5 * log<order> (((S) 1 + x) / ((S) 1 - x));
}
}
32 changes: 32 additions & 0 deletions test/src/inverse_hyperbolic_trig_approx_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,35 @@ TEMPLATE_TEST_CASE ("Acosh Approx Test", "", float, double)
6.5e-4f);
}
}

TEMPLATE_TEST_CASE ("Atanh Approx Test", "", float, double)
{
const auto all_floats = test_helpers::all_32_bit_floats<TestType> (-0.9999f, 0.9999f, 1.0e-2f);
const auto y_exact = test_helpers::compute_all<TestType> (all_floats, [] (auto x)
{ return std::atanh (x); });

SECTION ("6th-Order")
{
test_approx<TestType> (all_floats, y_exact, [] (auto x)
{ return math_approx::atanh<6> (x); },
2.5e-6f);
}
SECTION ("5th-Order")
{
test_approx<TestType> (all_floats, y_exact, [] (auto x)
{ return math_approx::atanh<5> (x); },
6.5e-6f);
}
SECTION ("4th-Order")
{
test_approx<TestType> (all_floats, y_exact, [] (auto x)
{ return math_approx::atanh<4> (x); },
4.5e-5f);
}
SECTION ("3th-Order")
{
test_approx<TestType> (all_floats, y_exact, [] (auto x)
{ return math_approx::atanh<3> (x); },
3.5e-4f);
}
}
21 changes: 21 additions & 0 deletions tools/bench/inverse_hyperbolic_trig_bench.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ const auto data_acosh = []
return x;
}();

const auto data_atanh = []
{
std::vector<float> x;
x.resize (N, 0.0f);
for (size_t i = 0; i < N; ++i)
x[i] = -1.0f + 2.0f * (float) i / (float) N;
return x;
}();

#define INV_HTRIG_BENCH(name, func, data) \
void name (benchmark::State& state) \
{ \
Expand Down Expand Up @@ -47,6 +56,12 @@ 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)

INV_HTRIG_BENCH (atanh_std, std::atanh, data_atanh)
INV_HTRIG_BENCH (atanh_approx6, math_approx::atanh<6>, data_atanh)
INV_HTRIG_BENCH (atanh_approx5, math_approx::atanh<5>, data_atanh)
INV_HTRIG_BENCH (atanh_approx4, math_approx::atanh<4>, data_atanh)
INV_HTRIG_BENCH (atanh_approx3, math_approx::atanh<3>, data_atanh)

#define INV_HTRIG_SIMD_BENCH(name, func, data) \
void name (benchmark::State& state) \
{ \
Expand Down Expand Up @@ -75,4 +90,10 @@ 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)

INV_HTRIG_SIMD_BENCH (atanh_xsimd, xsimd::atanh, data_atanh)
INV_HTRIG_SIMD_BENCH (atanh_simd_approx6, math_approx::atanh<6>, data_atanh)
INV_HTRIG_SIMD_BENCH (atanh_simd_approx5, math_approx::atanh<5>, data_atanh)
INV_HTRIG_SIMD_BENCH (atanh_simd_approx4, math_approx::atanh<4>, data_atanh)
INV_HTRIG_SIMD_BENCH (atanh_simd_approx3, math_approx::atanh<3>, data_atanh)

BENCHMARK_MAIN();
6 changes: 3 additions & 3 deletions tools/plotter/plotter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,12 @@ void plot_function (std::span<const float> all_floats,
int main()
{
plt::figure();
const auto range = std::make_pair (1.0f, 10.0f);
const auto range = std::make_pair (-0.99f, 0.99f);
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<float> (all_floats, FLOAT_FUNC (std::acosh));
plot_ulp_error (all_floats, y_exact, FLOAT_FUNC ((math_approx::acosh<6>) ), "acosh-6");
const auto y_exact = test_helpers::compute_all<float> (all_floats, FLOAT_FUNC (std::atanh));
plot_error (all_floats, y_exact, FLOAT_FUNC ((math_approx::atanh<5>) ), "atanh_log-5");

plt::legend ({ { "loc", "upper right" } });
plt::xlim (range.first, range.second);
Expand Down

0 comments on commit 58d98dc

Please sign in to comment.