/*************************************************************************** * Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and * * Martin Renou * * Copyright (c) QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XSIMD_HYPERBOLIC_HPP #define XSIMD_HYPERBOLIC_HPP #include #include "xsimd_exponential.hpp" #include "xsimd_fp_sign.hpp" #include "xsimd_logarithm.hpp" #include "xsimd_power.hpp" namespace xsimd { template batch_type_t average(const simd_base& x1, const simd_base& x2); /** * Computes the hyperbolic sine of the batch \c x. * @param x batch of floating point values. * @return the hyperbolic sine of \c x. */ template batch_type_t sinh(const simd_base& x); /** * Computes the hyperbolic cosine of the batch \c x. * @param x batch of floating point values. * @return the hyperbolic cosine of \c x. */ template batch_type_t cosh(const simd_base& x); /** * Computes the hyperbolic tangent of the batch \c x. * @param x batch of floating point values. * @return the hyperbolic tangent of \c x. */ template batch_type_t tanh(const simd_base& x); /** * Computes the inverse hyperbolic sine of the batch \c x. * @param x batch of floating point values. * @return the inverse hyperbolic sine of \c x. */ template batch_type_t asinh(const simd_base& x); /** * Computes the inverse hyperbolic cosine of the batch \c x. * @param x batch of floating point values. * @return the inverse hyperbolic cosine of \c x. */ template batch_type_t acosh(const simd_base& x); /** * Computes the inverse hyperbolic tangent of the batch \c x. * @param x batch of floating point values. * @return the inverse hyperbolic tangent of \c x. */ template batch_type_t atanh(const simd_base& x); /*************************** * average implementation * ***************************/ namespace detail { /* origin: boost/simd/arch/common/simd/function/average.hpp */ /* * ==================================================== * copyright 2016 NumScale SAS * * Distributed under the Boost Software License, Version 1.0. * (See copy at http://boost.org/LICENSE_1_0.txt) * ==================================================== */ template ::value> struct average_impl { static inline B compute(const B& x1, const B& x2) { return (x1 & x2) + ((x1 ^ x2) >> 1); } }; template struct average_impl { static inline B compute(const B& x1, const B& x2) { return fma(x1, B(0.5), x2 * B(0.5)); } }; } template inline batch_type_t average(const simd_base& x1, const simd_base& x2) { return detail::average_impl>::compute(x1(), x2()); } /*********************** * sinh implementation * ***********************/ namespace detail { /* origin: boost/simd/arch/common/detail/generic/sinh_kernel.hpp */ /* * ==================================================== * copyright 2016 NumScale SAS * * Distributed under the Boost Software License, Version 1.0. * (See copy at http://boost.org/LICENSE_1_0.txt) * ==================================================== */ template struct sinh_kernel_impl; template struct sinh_kernel_impl { static inline B compute(const B& x) { B sqrx = x * x; return horner(sqrx) * x; } }; template struct sinh_kernel_impl { static inline B compute(const B& x) { B sqrx = x * x; return fma(x, (horner(sqrx) / horner1(sqrx)) * sqrx, x); } }; template struct sinh_kernel { static inline B compute(const B& a) { using b_type = B; b_type half = b_type(0.5); b_type x = abs(a); auto lt1 = x < b_type(1.); b_type bts = bitofsign(a); b_type z(0.); if (any(lt1)) { z = sinh_kernel_impl::compute(x); if (all(lt1)) return z ^ bts; } auto test1 = x >(maxlog() - log_2()); b_type fac = select(test1, half, b_type(1.)); b_type tmp = exp(x * fac); b_type tmp1 = half * tmp; b_type r = select(test1, tmp1 * tmp, tmp1 - half / tmp); return select(lt1, z, r) ^ bts; } }; } /* origin: boost/simd/arch/common/simd/function/sinh.hpp */ /* * ==================================================== * copyright 2016 NumScale SAS * * Distributed under the Boost Software License, Version 1.0. * (See copy at http://boost.org/LICENSE_1_0.txt) * ==================================================== */ template inline batch_type_t sinh(const simd_base& a) { return detail::sinh_kernel>::compute(a()); } /*********************** * cosh implementation * ***********************/ /* origin: boost/simd/arch/common/simd/function/cosh.hpp */ /* * ==================================================== * copyright 2016 NumScale SAS * * Distributed under the Boost Software License, Version 1.0. * (See copy at http://boost.org/LICENSE_1_0.txt) * ==================================================== */ namespace detail { template struct cosh_kernel { static inline B compute(const B& a) { using b_type = B; b_type x = abs(a); auto test1 = x > (maxlog() - log_2()); b_type fac = select(test1, b_type(0.5), b_type(1.)); b_type tmp = exp(x * fac); b_type tmp1 = b_type(0.5) * tmp; return select(test1, tmp1 * tmp, average(tmp, b_type(1.) / tmp)); } }; } template inline batch_type_t cosh(const simd_base& a) { return detail::cosh_kernel>::compute(a()); } /*********************** * tanh implementation * ***********************/ namespace detail { /* origin: boost/simd/arch/common/detail/generic/tanh_kernel.hpp */ /* * ==================================================== * copyright 2016 NumScale SAS * * Distributed under the Boost Software License, Version 1.0. * (See copy at http://boost.org/LICENSE_1_0.txt) * ==================================================== */ template struct tanh_kernel_impl; template struct tanh_kernel_impl { static inline B tanh(const B& x) { B sqrx = x * x; return fma(horner(sqrx) * sqrx, x, x); } static inline B cotanh(const B& x) { return B(1.) / tanh(x); } }; template struct tanh_kernel_impl { static inline B tanh(const B& x) { B sqrx = x * x; return fma(sqrx * p(sqrx) / q(sqrx), x, x); } static inline B cotanh(const B& x) { B sqrx = x * x; B qval = q(sqrx); return qval / (x * fma(p(sqrx), sqrx, qval)); } static inline B p(const B& x) { return horner(x); } static inline B q(const B& x) { return horner1(x); } }; template struct tanh_kernel { static inline B compute(const B& a) { using b_type = B; b_type one(1.); b_type x = abs(a); auto test = x < (b_type(5.) / b_type(8.)); b_type bts = bitofsign(a); b_type z = one; if (any(test)) { z = tanh_kernel_impl::tanh(x); if (all(test)) return z ^ bts; } b_type r = fma(b_type(-2.), one / (one + exp(x + x)), one); return select(test, z, r) ^ bts; } }; } /* origin: boost/simd/arch/common/simd/function/tanh.hpp */ /* * ==================================================== * copyright 2016 NumScale SAS * * Distributed under the Boost Software License, Version 1.0. * (See copy at http://boost.org/LICENSE_1_0.txt) * ==================================================== */ template inline batch_type_t tanh(const simd_base& a) { return detail::tanh_kernel>::compute(a()); } /*********************** * sinh implementation * ***********************/ namespace detail { /* origin: boost/simd/arch/common/simd/function/asinh.hpp */ /* * ==================================================== * copyright 2016 NumScale SAS * * Distributed under the Boost Software License, Version 1.0. * (See copy at http://boost.org/LICENSE_1_0.txt) * ==================================================== */ template struct asinh_kernel; template struct asinh_kernel { static inline B compute(const B& a) { B x = abs(a); auto lthalf = x < B(0.5); B x2 = x * x; B bts = bitofsign(a); B z(0.); if (any(lthalf)) { z = horner(x2) * x; if (all(lthalf)) return z ^ bts; } B tmp = select(x > oneosqrteps(), x, average(x, hypot(B(1.), x))); #ifndef XSIMD_NO_NANS return select(xsimd::isnan(a), nan(), select(lthalf, z, log(tmp) + log_2()) ^ bts); #else return select(lthalf, z, log(tmp) + log_2()) ^ bts; #endif } }; template struct asinh_kernel { static inline B compute(const B& a) { B x = abs(a); auto test = x > oneosqrteps(); B z = select(test, x - B(1.), x + x * x / (B(1.) + hypot(B(1.), x))); #ifndef XSIMD_NO_INFINITIES z = select(x == infinity(), x, z); #endif B l1pz = log1p(z); z = select(test, l1pz + log_2(), l1pz); return bitofsign(a) ^ z; } }; } template inline batch_type_t asinh(const simd_base& x) { return detail::asinh_kernel>::compute(x()); } /************************ * acosh implementation * ************************/ /* origin: boost/simd/arch/common/simd/function/acosh.hpp */ /* * ==================================================== * copyright 2016 NumScale SAS * * Distributed under the Boost Software License, Version 1.0. * (See copy at http://boost.org/LICENSE_1_0.txt) * ==================================================== */ namespace detail { template struct acosh_kernel { static inline B compute(const B& a) { using b_type = B; b_type x = a - b_type(1.); auto test = x > oneotwoeps(); b_type z = select(test, a, x + sqrt(x + x + x * x)); b_type l1pz = log1p(z); return select(test, l1pz + log_2(), l1pz); } }; } template inline batch_type_t acosh(const simd_base& a) { return detail::acosh_kernel>::compute(a()); } /************************ * atanh implementation * ************************/ /* origin: boost/simd/arch/common/simd/function/acosh.hpp */ /* * ==================================================== * copyright 2016 NumScale SAS * * Distributed under the Boost Software License, Version 1.0. * (See copy at http://boost.org/LICENSE_1_0.txt) * ==================================================== */ namespace detail { template struct atanh_kernel { static inline B compute(const B& a) { using b_type = B; b_type x = abs(a); b_type t = x + x; b_type z = b_type(1.) - x; auto test = x < b_type(0.5); b_type tmp = select(test, x, t) / z; return bitofsign(a) ^ (b_type(0.5) * log1p(select(test, fma(t, tmp, t), tmp))); } }; } template inline batch_type_t atanh(const simd_base& a) { return detail::atanh_kernel>::compute(a()); } } #endif