/*************************************************************************** * 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_EXPONENTIAL_HPP #define XSIMD_EXPONENTIAL_HPP #include "xsimd_exp_reduction.hpp" #include "xsimd_fp_manipulation.hpp" namespace xsimd { /** * Computes the natural exponential of the batch \c x. * @param x batch of floating point values. * @return the natural exponential of \c x. */ template batch_type_t exp(const simd_base& x); /** * Computes the base 2 exponential of the batch \c x. * @param x batch of floating point values. * @return the base 2 exponential of \c x. */ template batch_type_t exp2(const simd_base& x); /** * Computes the base 10 exponential of the batch \c x. * @param x batch of floating point values. * @return the base 10 exponential of \c x. */ template batch_type_t exp10(const simd_base& x); /** * Computes the natural exponential of the batch \c x, minus one. * @param x batch of floating point values. * @return the natural exponential of \c x, minus one. */ template batch_type_t expm1(const simd_base& x); /****************************** * exponential implementation * ******************************/ namespace detail { template struct exp_kernel; template struct exp_kernel { /* origin: boost/simd/arch/common/detail/simd/expo_base.hpp */ /* * ==================================================== * copyright 2016 NumScale SAS * * Distributed under the Boost Software License, Version 1.0. * (See copy at http://boost.org/LICENSE_1_0.txt) * ==================================================== */ static inline B compute(const B& a) { using reducer_t = exp_reduction; B x; B k = reducer_t::reduce(a, x); x = reducer_t::approx(x); x = select(a <= reducer_t::minlog(), B(0.), ldexp(x, to_int(k))); x = select(a >= reducer_t::maxlog(), infinity(), x); return x; } }; template struct exp_kernel { /* origin: boost/simd/arch/common/detail/simd/expo_base.hpp */ /* * ==================================================== * copyright 2016 NumScale SAS * * Distributed under the Boost Software License, Version 1.0. * (See copy at http://boost.org/LICENSE_1_0.txt) * ==================================================== */ static inline B compute(const B& a) { using reducer_t = exp_reduction; B hi, lo, x; B k = reducer_t::reduce(a, hi, lo, x); B c = reducer_t::approx(x); c = reducer_t::finalize(x, c, hi, lo); c = select(a <= reducer_t::minlog(), B(0.), ldexp(c, to_int(k))); c = select(a >= reducer_t::maxlog(), infinity(), c); return c; } }; } template inline batch_type_t exp(const simd_base& x) { return detail::exp_kernel, exp_tag>::compute(x()); } template inline batch_type_t exp2(const simd_base& x) { return detail::exp_kernel, exp2_tag>::compute(x()); } template inline batch_type_t exp10(const simd_base& x) { return detail::exp_kernel, exp10_tag>::compute(x()); } /************************ * expm1 implementation * ************************/ namespace detail { template struct expm1_kernel; template inline B expm1_real_impl(const B& x) { return select(x < logeps(), B(-1.), select(x > maxlog(), infinity(), expm1_kernel::compute_impl(x))); } template struct expm1_kernel { /* origin: boost/simd/arch/common/detail/generic/expm1_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) * ==================================================== */ static inline B compute_impl(const B& a) { B k = nearbyint(invlog_2() * a); B x = fnma(k, log_2hi(), a); x = fnma(k, log_2lo(), x); B hx = x * B(0.5); B hxs = x * hx; B r = horner(hxs); B t = fnma(r, hx, B(3.)); B e = hxs * ((r - t) / (B(6.) - x * t)); e = fms(x, e, hxs); using i_type = as_integer_t; i_type ik = to_int(k); B two2mk = bitwise_cast((maxexponent() - ik) << nmb()); B y = B(1.) - two2mk - (e - x); return ldexp(y, ik); } static inline B compute(const B& a) { return expm1_real_impl(a); } }; template struct expm1_kernel { /* origin: boost/simd/arch/common/detail/generic/expm1_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) * ==================================================== */ static inline B compute_impl(const B& a) { B k = nearbyint(invlog_2() * a); B hi = fnma(k, log_2hi(), a); B lo = k * log_2lo(); B x = hi - lo; B hxs = x * x * B(0.5); B r = horner(hxs); B t = B(3.) - r * B(0.5) * x; B e = hxs * ((r - t) / (B(6) - x * t)); B c = (hi - x) - lo; e = (x * (e - c) - c) - hxs; using i_type = as_integer_t; i_type ik = to_int(k); B two2mk = bitwise_cast((maxexponent() - ik) << nmb()); B ct1 = B(1.) - two2mk - (e - x); B ct2 = ++(x - (e + two2mk)); B y = select(k < B(20.), ct1, ct2); return ldexp(y, ik); } static inline B compute(const B& a) { return expm1_real_impl(a); } }; } template inline batch_type_t expm1(const simd_base& x) { return detail::expm1_kernel>::compute(x()); } } #endif