/*************************************************************************** * 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_TRIGONOMETRIC_HPP #define XSIMD_TRIGONOMETRIC_HPP #include "xsimd_fp_sign.hpp" #include "xsimd_invtrigo.hpp" #include "xsimd_trigo_reduction.hpp" namespace xsimd { /** * Computes the sine of the batch \c x. * @param x batch of floating point values. * @return the sine of \c x. */ template batch_type_t sin(const simd_base& x); /** * Computes the cosine of the batch \c x. * @param x batch of floating point values. * @return the cosine of \c x. */ template batch_type_t cos(const simd_base& x); /** * Computes the sine and the cosine of the batch \c x. This method is faster * than calling sine and cosine independently. * @param x batch of floating point values. * @param si the sine of x. * @param co the cosine of x. */ template void sincos(const simd_base& x, batch_type_t& si, batch_type_t& co); /** * Computes the tangent of the batch \c x. * @param x batch of floating point values. * @return the tangent of \c x. */ template batch_type_t tan(const simd_base& x); /** * Computes the arc sine of the batch \c x. * @param x batch of floating point values. * @return the arc sine of \c x. */ template batch_type_t asin(const simd_base& x); /** * Computes the arc cosine of the batch \c x. * @param x batch of floating point values. * @return the arc cosine of \c x. */ template batch_type_t acos(const simd_base& x); /** * Computes the arc tangent of the batch \c x. * @param x batch of floating point values. * @return the arc tangent of \c x. */ template batch_type_t atan(const simd_base& x); /** * Computes the arc tangent of the batch \c x/y, using the signs of the * arguments to determine the correct quadrant. * @param x batch of floating point values. * @param y batch of floating point values. * @return the arc tangent of \c x/y. */ template batch_type_t atan2(const simd_base& y, const simd_base& x); namespace detail { /* origin: boost/simd/arch/common/detail/simd/trig_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) * ==================================================== */ template struct trigo_kernel { template static inline B sin(const B& a, Tag = Tag()) { const B x = abs(a); B xr = nan(); const B n = trigo_reducer::reduce(x, xr); auto tmp = select(n >= B(2.), B(1.), B(0.)); auto swap_bit = fma(B(-2.), tmp, n); auto sign_bit = bitofsign(a) ^ select(tmp != B(0.), signmask(), B(0.)); const B z = xr * xr; const B se = trigo_evaluation::sin_eval(z, xr); const B ce = trigo_evaluation::cos_eval(z); const B z1 = select(swap_bit == B(0.), se, ce); return z1 ^ sign_bit; } static inline B cos(const B& a) { const B x = abs(a); B xr = nan(); const B n = trigo_reducer::reduce(x, xr); auto tmp = select(n >= B(2.), B(1.), B(0.)); auto swap_bit = fma(B(-2.), tmp, n); auto sign_bit = select((swap_bit ^ tmp) != B(0.), signmask(), B(0.)); const B z = xr * xr; const B se = trigo_evaluation::sin_eval(z, xr); const B ce = trigo_evaluation::cos_eval(z); const B z1 = select(swap_bit != B(0.), se, ce); return z1 ^ sign_bit; } static inline B tan(const B& a) { const B x = abs(a); B xr = nan(); const B n = trigo_reducer::reduce(x, xr); auto tmp = select(n >= B(2.), B(1.), B(0.)); auto swap_bit = fma(B(-2.), tmp, n); auto test = (swap_bit == B(0.)); const B y = trigo_evaluation::tan_eval(xr, test); return y ^ bitofsign(a); } static inline void sincos(const B& a, B& si, B& co) { const B x = abs(a); B xr = nan(); const B n = trigo_reducer::reduce(x, xr); auto tmp = select(n >= B(2.), B(1.), B(0.)); auto swap_bit = fma(B(-2.), tmp, n); const B z = xr * xr; const B se = trigo_evaluation::sin_eval(z, xr); const B ce = trigo_evaluation::cos_eval(z); auto sin_sign_bit = bitofsign(a) ^ select(tmp != B(0.), signmask(), B(0.)); const B sin_z1 = select(swap_bit == B(0.), se, ce); si = sin_z1 ^ sin_sign_bit; auto cos_sign_bit = select((swap_bit ^ tmp) != B(0.), signmask(), B(0.)); const B cos_z1 = select(swap_bit != B(0.), se, ce); co = cos_z1 ^ cos_sign_bit; } }; } template inline batch_type_t sin(const simd_base& x) { return detail::trigo_kernel>::sin(x()); } template inline batch_type_t cos(const simd_base& x) { return detail::trigo_kernel>::cos(x()); } template inline void sincos(const simd_base& x, batch_type_t& si, batch_type_t& co) { detail::trigo_kernel>::sincos(x(), si, co); } template inline batch_type_t tan(const simd_base& x) { return detail::trigo_kernel>::tan(x()); } template inline batch_type_t asin(const simd_base& x) { return detail::invtrigo_kernel>::asin(x()); } template inline batch_type_t acos(const simd_base& x) { return detail::invtrigo_kernel>::acos(x()); } template inline batch_type_t atan(const simd_base& x) { return detail::invtrigo_kernel>::atan(x()); } template inline batch_type_t atan2(const simd_base& y, const simd_base& x) { return detail::invtrigo_kernel>::atan2(y(), x()); } } #endif