Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:25:51

0001 /*  This file is part of the Vc library. {{{
0002 Copyright © 2009-2015 Matthias Kretz <kretz@kde.org>
0003 
0004 Redistribution and use in source and binary forms, with or without
0005 modification, are permitted provided that the following conditions are met:
0006     * Redistributions of source code must retain the above copyright
0007       notice, this list of conditions and the following disclaimer.
0008     * Redistributions in binary form must reproduce the above copyright
0009       notice, this list of conditions and the following disclaimer in the
0010       documentation and/or other materials provided with the distribution.
0011     * Neither the names of contributing organizations nor the
0012       names of its contributors may be used to endorse or promote products
0013       derived from this software without specific prior written permission.
0014 
0015 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
0016 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
0017 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0018 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
0019 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
0020 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
0021 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0022 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0023 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
0024 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0025 
0026 }}}*/
0027 
0028 #ifndef VC_COMMON_TRIGONOMETRIC_H_
0029 #define VC_COMMON_TRIGONOMETRIC_H_
0030 
0031 #include "macros.h"
0032 
0033 #ifdef Vc_HAVE_LIBMVEC
0034 extern "C" {
0035 __m128 _ZGVbN4v_sinf(__m128);
0036 __m128d _ZGVbN2v_sin(__m128d);
0037 __m128 _ZGVbN4v_cosf(__m128);
0038 __m128d _ZGVbN2v_cos(__m128d);
0039 __m256 _ZGVdN8v_sinf(__m256);
0040 __m256d _ZGVdN4v_sin(__m256d);
0041 __m256 _ZGVdN8v_cosf(__m256);
0042 __m256d _ZGVdN4v_cos(__m256d);
0043 }
0044 #endif
0045 
0046 namespace Vc_VERSIONED_NAMESPACE
0047 {
0048 namespace Detail
0049 {
0050 template<Vc::Implementation Impl> struct MapImpl { enum Dummy { Value = Impl }; };
0051 template<> struct MapImpl<Vc::SSE42Impl> { enum Dummy { Value = MapImpl<Vc::SSE41Impl>::Value }; };
0052 
0053 template<Vc::Implementation Impl> using TrigonometricImplementation =
0054     ImplementationT<MapImpl<Impl>::Value
0055 #if defined(Vc_IMPL_XOP) && defined(Vc_IMPL_FMA4)
0056     + Vc::XopInstructions
0057     + Vc::Fma4Instructions
0058 #endif
0059     >;
0060 }  // namespace Detail
0061 
0062 namespace Common
0063 {
0064 template<typename Impl> struct Trigonometric
0065 {
0066     template<typename T> static T Vc_VDECL sin(const T &_x);
0067     template<typename T> static T Vc_VDECL cos(const T &_x);
0068     template<typename T> static void Vc_VDECL sincos(const T &_x, T *_sin, T *_cos);
0069     template<typename T> static T Vc_VDECL asin (const T &_x);
0070     template<typename T> static T Vc_VDECL atan (const T &_x);
0071     template<typename T> static T Vc_VDECL atan2(const T &y, const T &x);
0072 };
0073 }  // namespace Common
0074 
0075 #if defined Vc_IMPL_SSE || defined DOXYGEN
0076 // this is either SSE, AVX, or AVX2
0077 namespace Detail
0078 {
0079 template <typename T, typename Abi>
0080 using Trig = Common::Trigonometric<Detail::TrigonometricImplementation<
0081     (std::is_same<Abi, VectorAbi::Sse>::value
0082          ? SSE42Impl
0083          : std::is_same<Abi, VectorAbi::Avx>::value ? AVXImpl : ScalarImpl)>>;
0084 }  // namespace Detail
0085 
0086 #ifdef Vc_HAVE_LIBMVEC
0087 Vc_INTRINSIC __m128  sin_dispatch(__m128  x) { return ::_ZGVbN4v_sinf(x); }
0088 Vc_INTRINSIC __m128d sin_dispatch(__m128d x) { return ::_ZGVbN2v_sin (x); }
0089 Vc_INTRINSIC __m128  cos_dispatch(__m128  x) { return ::_ZGVbN4v_cosf(x); }
0090 Vc_INTRINSIC __m128d cos_dispatch(__m128d x) { return ::_ZGVbN2v_cos (x); }
0091 #ifdef Vc_IMPL_AVX
0092 Vc_INTRINSIC __m256  sin_dispatch(__m256  x) { return ::_ZGVdN8v_sinf(x); }
0093 Vc_INTRINSIC __m256d sin_dispatch(__m256d x) { return ::_ZGVdN4v_sin (x); }
0094 Vc_INTRINSIC __m256  cos_dispatch(__m256  x) { return ::_ZGVdN8v_cosf(x); }
0095 Vc_INTRINSIC __m256d cos_dispatch(__m256d x) { return ::_ZGVdN4v_cos (x); }
0096 #endif
0097 
0098 template <typename T, typename Abi>
0099 Vc_INTRINSIC Vector<T, detail::not_fixed_size_abi<Abi>> sin(const Vector<T, Abi> &x)
0100 {
0101     return sin_dispatch(x.data());
0102 }
0103 template <typename T, typename Abi>
0104 Vc_INTRINSIC Vector<T, detail::not_fixed_size_abi<Abi>> cos(const Vector<T, Abi> &x)
0105 {
0106     return cos_dispatch(x.data());
0107 }
0108 #else
0109 /**
0110  * \ingroup Math
0111  * Returns the sine of all input values in \p x.
0112  *
0113  * \param x The values to apply the sine function on.
0114  *
0115  * \returns the sine of \p x.
0116  *
0117  * \note The single-precision implementation has a precision of max. 2 ulp (mean 0.17 ulp)
0118  * in the range [-8192, 8192].
0119  * (testSin< float_v> with a maximal distance of 2 to the reference (mean: 0.310741))
0120  *
0121  * \note The double-precision implementation has a precision of max. 3 ulp (mean 1040 ulp)
0122  * in the range [-8192, 8192].
0123  * (testSin<double_v> with a maximal distance of 1 to the reference (mean: 0.170621))
0124  *
0125  * \note The precision and execution latency depends on:
0126  *       - `Abi` (e.g. Scalar uses the `<cmath>` implementation
0127  *       - whether `Vc_HAVE_LIBMVEC` is defined
0128  *       - for the `<cmath>` fallback, the implementations differ (e.g. MacOS vs. Linux
0129  * vs. Windows; fpmath=sse vs. fpmath=387)
0130  *
0131  * \note Vc versions before 1.4 had different precision.
0132  */
0133 template <typename T, typename Abi>
0134 Vc_INTRINSIC Vector<T, detail::not_fixed_size_abi<Abi>> sin(const Vector<T, Abi> &x)
0135 {
0136     return Detail::Trig<T, Abi>::sin(x);
0137 }
0138 
0139 /**
0140  * \ingroup Math
0141  * Returns the cosine of all input values in \p x.
0142  *
0143  * \param x The values to apply the cosine function on.
0144  * \returns the cosine of \p x.
0145  *
0146  * \note The single-precision implementation has a precision of max. 2 ulp (mean 0.18 ulp) in the range [-8192, 8192].
0147  * \note The double-precision implementation has a precision of max. 3 ulp (mean 1160 ulp) in the range [-8192, 8192].
0148  * \note Vc versions before 1.4 had different precision.
0149  */
0150 template <typename T, typename Abi>
0151 Vc_INTRINSIC Vector<T, detail::not_fixed_size_abi<Abi>> cos(const Vector<T, Abi> &x)
0152 {
0153     return Detail::Trig<T, Abi>::cos(x);
0154 }
0155 #endif
0156 
0157 /**
0158  * \ingroup Math
0159  * Returns the arcsine of all input values in \p x.
0160  *
0161  * \param x The values to apply the arcsine function on.
0162  * \returns the arcsine of \p x.
0163  *
0164  * \note The single-precision implementation has an error of max. 2 ulp (mean 0.3 ulp).
0165  * \note The double-precision implementation has an error of max. 36 ulp (mean 0.4 ulp).
0166  */
0167 template <typename T, typename Abi>
0168 Vc_INTRINSIC Vector<T, detail::not_fixed_size_abi<Abi>> asin(const Vector<T, Abi> &x)
0169 {
0170     return Detail::Trig<T, Abi>::asin(x);
0171 }
0172 
0173 /**
0174  * \ingroup Math
0175  * Returns the arctangent of all input values in \p x.
0176  *
0177  * \param x The values to apply the arctangent function on.
0178  * \returns the arctangent of \p x.
0179  * \note The single-precision implementation has an error of max. 3 ulp (mean 0.4 ulp) in the range [-8192, 8192].
0180  * \note The double-precision implementation has an error of max. 2 ulp (mean 0.1 ulp) in the range [-8192, 8192].
0181  */
0182 template <typename T, typename Abi>
0183 Vc_INTRINSIC Vector<T, detail::not_fixed_size_abi<Abi>> atan(const Vector<T, Abi> &x)
0184 {
0185     return Detail::Trig<T, Abi>::atan(x);
0186 }
0187 
0188 /**
0189  * \ingroup Math
0190  * Returns the arctangent of all input values in \p x and \p y.
0191  *
0192  * Calculates the angle given the lengths of the opposite and adjacent legs in a right
0193  * triangle.
0194  * \param y The opposite leg.
0195  * \param x The adjacent leg.
0196  * \returns the arctangent of \p y / \p x.
0197  */
0198 template <typename T, typename Abi>
0199 Vc_INTRINSIC Vector<T, detail::not_fixed_size_abi<Abi>> atan2(const Vector<T, Abi> &y,
0200                                                               const Vector<T, Abi> &x)
0201 {
0202     return Detail::Trig<T, Abi>::atan2(y, x);
0203 }
0204 
0205 /**
0206  * \ingroup Math
0207  *
0208  * \param x Input value to both sine and cosine.
0209  * \param sin A non-null pointer to a potentially uninitialized object of type Vector.
0210  *            When \c sincos returns, `*sin` contains the result of `sin(x)`.
0211  * \param cos A non-null pointer to a potentially uninitialized object of type Vector.
0212  *            When \c sincos returns, `*cos` contains the result of `cos(x)`.
0213  *
0214  * \see sin, cos
0215  */
0216 template <typename T, typename Abi>
0217 Vc_INTRINSIC void sincos(const Vector<T, Abi> &x,
0218                          Vector<T, detail::not_fixed_size_abi<Abi>> *sin,
0219                          Vector<T, Abi> *cos)
0220 {
0221     Detail::Trig<T, Abi>::sincos(x, sin, cos);
0222 }
0223 #endif
0224 }  // namespace Vc_VERSIONED_NAMESPACE
0225 
0226 #endif  // VC_COMMON_TRIGONOMETRIC_H_