/*************************************************************************** * 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_EXP_REDUCTION_HPP #define XSIMD_EXP_REDUCTION_HPP #include "xsimd_horner.hpp" #include "xsimd_numerical_constant.hpp" #include "xsimd_rounding.hpp" namespace xsimd { struct exp_tag { }; struct exp2_tag { }; struct exp10_tag { }; namespace detail { /********************** * exp_reduction_base * **********************/ template struct exp_reduction_base; template struct exp_reduction_base { static constexpr B maxlog() noexcept { return xsimd::maxlog(); } static constexpr B minlog() noexcept { return xsimd::minlog(); } }; template struct exp_reduction_base { static constexpr B maxlog() noexcept { return xsimd::maxlog2(); } static constexpr B minlog() noexcept { return xsimd::minlog2(); } }; template struct exp_reduction_base { static constexpr B maxlog() noexcept { return xsimd::maxlog10(); } static constexpr B minlog() noexcept { return xsimd::minlog10(); } }; /***************** * exp_reduction * *****************/ template struct exp_reduction; /* origin: boost/simd/arch/common/detail/generic/f_expo_reduction.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 exp_reduction : exp_reduction_base { static inline B approx(const B& x) { B y = horner(x); return ++fma(y, x * x, x); } static inline B reduce(const B& a, B& x) { B k = nearbyint(invlog_2() * a); x = fnma(k, log_2hi(), a); x = fnma(k, log_2lo(), x); return k; } }; template struct exp_reduction : exp_reduction_base { static inline B approx(const B& x) { B y = horner(x); return ++fma(y, x * x, x * log_2()); } static inline B reduce(const B& a, B& x) { B k = nearbyint(a); x = (a - k); return k; } }; template struct exp_reduction : exp_reduction_base { static inline B approx(const B& x) { return ++(horner(x) * x); } static inline B reduce(const B& a, B& x) { B k = nearbyint(invlog10_2() * a); x = fnma(k, log10_2hi(), a); x -= k * log10_2lo(); return k; } }; /* origin: boost/simd/arch/common/detail/generic/d_expo_reduction.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 exp_reduction : exp_reduction_base { static inline B approx(const B& x) { B t = x * x; return fnma(t, horner(t), x); } static inline B reduce(const B& a, B& hi, B& lo, B& x) { B k = nearbyint(invlog_2() * a); hi = fnma(k, log_2hi(), a); lo = k * log_2lo(); x = hi - lo; return k; } static inline B finalize(const B& x, const B& c, const B& hi, const B& lo) { return B(1.) - (((lo - (x * c) / (B(2.) - c)) - hi)); } }; template struct exp_reduction : exp_reduction_base { static inline B approx(const B& x) { B t = x * x; return fnma(t, horner(t), x); } static inline B reduce(const B& a, B&, B&, B& x) { B k = nearbyint(a); x = (a - k) * log_2(); return k; } static inline B finalize(const B& x, const B& c, const B&, const B&) { return B(1.) + x + x * c / (B(2.) - c); } }; template struct exp_reduction : exp_reduction_base { static inline B approx(const B& x) { B xx = x * x; B px = x * horner(xx); B x2 = px / (horner1(xx) - px); return ++(x2 + x2); } static inline B reduce(const B& a, B&, B&, B& x) { B k = nearbyint(invlog10_2() * a); x = fnma(k, log10_2hi(), a); x = fnma(k, log10_2lo(), x); return k; } static inline B finalize(const B&, const B& c, const B&, const B&) { return c; } }; } } #endif