Back to home page

EIC code displayed by LXR

 
 

    


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

0001 /*  This file is part of the Vc library. {{{
0002 Copyright © 2012-2016 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 COMMON_OPERATORS_H_
0029 #define COMMON_OPERATORS_H_
0030 #include "simdarray.h"
0031 #include "macros.h"
0032 
0033 namespace Vc_VERSIONED_NAMESPACE
0034 {
0035 namespace Detail
0036 {
0037 template <typename T, typename Abi, typename U>
0038 enable_if<!std::is_same<T, U>::value, U> is_convertible_to_any_vector(Vector<U, Abi>);
0039 template <typename T, typename Abi> T is_convertible_to_any_vector(Vector<T, Abi>);
0040 
0041 template <typename T, typename U, bool = std::is_integral<T>::value,
0042           bool = std::is_integral<U>::value>
0043 struct FundamentalReturnType;
0044 template <class T, class U>
0045 using fundamental_return_t = typename FundamentalReturnType<T, U>::type;
0046 
0047 template <typename T, typename U> struct FundamentalReturnType<T, U, false, false> {
0048     using type = typename std::conditional<
0049         std::is_arithmetic<U>::value,
0050         typename std::conditional<(sizeof(T) < sizeof(U)), U, T>::type,
0051         // U is not arithmetic, e.g. an enum or a type with e.g. operator int()
0052         T>::type;
0053 };
0054 template <typename T, typename U> struct FundamentalReturnType<T, U, true, false> {
0055     using type = typename std::conditional<
0056         std::is_arithmetic<U>::value, U,
0057         // U is not arithmetic, e.g. an enum or a type with e.g. operator int()
0058         T>::type;
0059 };
0060 template <typename T, typename U> struct FundamentalReturnType<T, U, false, true> {
0061     using type = T;
0062 };
0063 
0064 template <typename T> struct my_make_signed : public std::make_signed<T> {
0065 };
0066 template <> struct my_make_signed<bool> {
0067     using type = bool;
0068 };
0069 
0070 template <typename TT, typename UU>
0071 struct higher_conversion_rank {
0072     template <typename A>
0073     using fix_sign =
0074         typename std::conditional<(std::is_unsigned<TT>::value ||
0075                                    std::is_unsigned<UU>::value),
0076                                   typename std::make_unsigned<A>::type, A>::type;
0077     using T = typename my_make_signed<TT>::type;
0078     using U = typename my_make_signed<UU>::type;
0079     template <typename Test, typename Otherwise>
0080     using c = typename std::conditional<std::is_same<T, Test>::value ||
0081                                             std::is_same<U, Test>::value,
0082                                         Test, Otherwise>::type;
0083 
0084     using type = fix_sign<c<long long, c<long, c<int, c<short, c<signed char, void>>>>>>;
0085 };
0086 
0087 template <typename T, typename U> struct FundamentalReturnType<T, U, true, true> {
0088     template <bool B, class Then, class E>
0089     using c = typename std::conditional<B, Then, E>::type;
0090     using type =
0091         c<(sizeof(T) > sizeof(U)), T,
0092           c<(sizeof(T) < sizeof(U)), U, typename higher_conversion_rank<T, U>::type>>;
0093 };
0094 
0095 template <class V, class T, class Tq, class = void> struct ReturnTypeImpl {
0096     // no type => SFINAE
0097 };
0098 // 1. Vector × Vector
0099 template <class T, class U, class Abi, class Uq>
0100 struct ReturnTypeImpl<Vector<T, Abi>, Vector<U, Abi>, Uq, void> {
0101     using type = Vc::Vector<fundamental_return_t<T, U>, Abi>;
0102 };
0103 // 2. Vector × int
0104 template <class T, class Abi, class Uq>
0105 struct ReturnTypeImpl<Vector<T, Abi>, int, Uq, void> {
0106     // conversion from int is always allowed (because its the default when you hardcode a
0107     // number)
0108     using type = Vc::Vector<T, Abi>;
0109 };
0110 // 3. Vector × unsigned
0111 template <class T, class Abi, class Uq>
0112 struct ReturnTypeImpl<Vector<T, Abi>, uint, Uq, void> {
0113     // conversion from unsigned int is allowed for all integral Vector<T>, but ensures
0114     // unsigned result
0115     using type = Vc::Vector<
0116         typename std::conditional<std::is_integral<T>::value, std::make_unsigned<T>,
0117                                   std::enable_if<true, T>>::type::type,
0118         Abi>;
0119 };
0120 // 4. Vector × {enum, arithmetic}
0121 template <class T, class U, class Abi, class Uq>
0122 struct ReturnTypeImpl<
0123     Vector<T, Abi>, U, Uq,
0124     enable_if<!std::is_class<U>::value && !std::is_same<U, int>::value &&
0125                   !std::is_same<U, uint>::value &&
0126                   Traits::is_valid_vector_argument<fundamental_return_t<T, U>>::value,
0127               void>> {
0128     using type = Vc::Vector<fundamental_return_t<T, U>, Abi>;
0129 };
0130 // 5. Vector × UDT
0131 template <class T, class U, class Abi, class Uq>
0132 struct ReturnTypeImpl<
0133     Vector<T, Abi>, U, Uq,
0134     enable_if<std::is_class<U>::value && !Traits::is_simd_vector<U>::value &&
0135                   Traits::is_valid_vector_argument<decltype(
0136                       is_convertible_to_any_vector<T, Abi>(std::declval<Uq>()))>::value,
0137               void>> {
0138     using type =
0139         Vc::Vector<fundamental_return_t<T, decltype(is_convertible_to_any_vector<T, Abi>(
0140                                                std::declval<Uq>()))>,
0141                    Abi>;
0142 };
0143 template <class V, class Tq, class T = remove_cvref_t<Tq>>
0144 using ReturnType = typename ReturnTypeImpl<V, T, Tq>::type;
0145 
0146 template <class T> struct is_a_type : public std::true_type {
0147 };
0148 
0149 #ifdef Vc_ENABLE_FLOAT_BIT_OPERATORS
0150 #define Vc_TEST_FOR_BUILTIN_OPERATOR(op_) true
0151 #else
0152 #define Vc_TEST_FOR_BUILTIN_OPERATOR(op_)                                                \
0153     Detail::is_a_type<decltype(std::declval<typename R::value_type>()                    \
0154                                    op_ std::declval<typename R::value_type>())>::value
0155 #endif
0156 }  // namespace Detail
0157 
0158 #define Vc_GENERIC_OPERATOR(op_)                                                         \
0159     template <class T, class Abi, class U,                                               \
0160               class R = Detail::ReturnType<Vector<T, Abi>, U>>                           \
0161     Vc_ALWAYS_INLINE enable_if<Vc_TEST_FOR_BUILTIN_OPERATOR(op_) &&                      \
0162                                    std::is_convertible<Vector<T, Abi>, R>::value &&      \
0163                                    std::is_convertible<U, R>::value,                     \
0164                                R>                                                        \
0165     operator op_(Vector<T, Abi> x, U &&y)                                                \
0166     {                                                                                    \
0167         return Detail::operator op_(R(x), R(std::forward<U>(y)));                        \
0168     }                                                                                    \
0169     template <class T, class Abi, class U,                                               \
0170               class R = Detail::ReturnType<Vector<T, Abi>, U>>                           \
0171     Vc_ALWAYS_INLINE enable_if<Vc_TEST_FOR_BUILTIN_OPERATOR(op_) &&                      \
0172                                    !Traits::is_simd_vector<U>::value &&                  \
0173                                    std::is_convertible<Vector<T, Abi>, R>::value &&      \
0174                                    std::is_convertible<U, R>::value,                     \
0175                                R>                                                        \
0176     operator op_(U &&x, Vector<T, Abi> y)                                                \
0177     {                                                                                    \
0178         return Detail::operator op_(R(std::forward<U>(x)), R(y));                        \
0179     }                                                                                    \
0180     template <class T, class Abi, class U,                                               \
0181               class R = Detail::ReturnType<Vector<T, Abi>, U>>                           \
0182     Vc_ALWAYS_INLINE enable_if<Vc_TEST_FOR_BUILTIN_OPERATOR(op_) &&                      \
0183                                    std::is_convertible<Vector<T, Abi>, R>::value &&      \
0184                                    std::is_convertible<U, R>::value,                     \
0185                                Vector<T, Abi> &>                                         \
0186     operator op_##=(Vector<T, Abi> &x, U &&y)                                            \
0187     {                                                                                    \
0188         x = Detail::operator op_(R(x), R(std::forward<U>(y)));                           \
0189         return x;                                                                        \
0190     }
0191 
0192 #define Vc_LOGICAL_OPERATOR(op_)                                                         \
0193     template <class T, class Abi>                                                        \
0194     Vc_ALWAYS_INLINE typename Vector<T, Abi>::Mask operator op_(Vector<T, Abi> x,        \
0195                                                                 Vector<T, Abi> y)        \
0196     {                                                                                    \
0197         return !!x op_ !!y;                                                              \
0198     }                                                                                    \
0199     template <class T, class Abi, class U>                                               \
0200     Vc_ALWAYS_INLINE                                                                     \
0201         enable_if<std::is_convertible<Vector<T, Abi>, Vector<U, Abi>>::value &&          \
0202                       std::is_convertible<Vector<U, Abi>, Vector<T, Abi>>::value,        \
0203                   typename Detail::ReturnType<Vector<T, Abi>, Vector<U, Abi>>::Mask>     \
0204         operator op_(Vector<T, Abi> x, Vector<U, Abi> y)                                 \
0205     {                                                                                    \
0206         return !!x op_ !!y;                                                              \
0207     }                                                                                    \
0208     template <class T, class Abi, class U>                                               \
0209     Vc_ALWAYS_INLINE enable_if<std::is_same<bool, decltype(!std::declval<U>())>::value,  \
0210                                typename Vector<T, Abi>::Mask>                            \
0211     operator op_(Vector<T, Abi> x, U &&y)                                                \
0212     {                                                                                    \
0213         using M = typename Vector<T, Abi>::Mask;                                         \
0214         return !!x op_ M(!!std::forward<U>(y));                                          \
0215     }                                                                                    \
0216     template <class T, class Abi, class U>                                               \
0217     Vc_ALWAYS_INLINE enable_if<std::is_same<bool, decltype(!std::declval<U>())>::value,  \
0218                                typename Vector<T, Abi>::Mask>                            \
0219     operator op_(U &&x, Vector<T, Abi> y)                                                \
0220     {                                                                                    \
0221         using M = typename Vector<T, Abi>::Mask;                                         \
0222         return M(!!std::forward<U>(x)) op_ !!y;                                          \
0223     }
0224 
0225 #define Vc_COMPARE_OPERATOR(op_)                                                         \
0226     template <class T, class Abi, class U,                                               \
0227               class R = Detail::ReturnType<Vector<T, Abi>, U>>                           \
0228     Vc_ALWAYS_INLINE enable_if<std::is_convertible<Vector<T, Abi>, R>::value &&          \
0229                                    std::is_convertible<U, R>::value,                     \
0230                                typename R::Mask>                                         \
0231     operator op_(Vector<T, Abi> x, U &&y)                                                \
0232     {                                                                                    \
0233         return Detail::operator op_(R(x), R(std::forward<U>(y)));                        \
0234     }                                                                                    \
0235     template <class T, class Abi, class U,                                               \
0236               class R = Detail::ReturnType<Vector<T, Abi>, U>>                           \
0237     Vc_ALWAYS_INLINE                                                                     \
0238         enable_if<!Traits::is_simd_vector_internal<remove_cvref_t<U>>::value &&          \
0239                       std::is_convertible<Vector<T, Abi>, R>::value &&                   \
0240                       std::is_convertible<U, R>::value,                                  \
0241                   typename R::Mask>                                                      \
0242         operator op_(U &&x, Vector<T, Abi> y)                                            \
0243     {                                                                                    \
0244         return Detail::operator op_(R(std::forward<U>(x)), R(y));                        \
0245     }
0246 
0247 Vc_ALL_LOGICAL    (Vc_LOGICAL_OPERATOR);
0248 Vc_ALL_BINARY     (Vc_GENERIC_OPERATOR);
0249 Vc_ALL_ARITHMETICS(Vc_GENERIC_OPERATOR);
0250 Vc_ALL_COMPARES   (Vc_COMPARE_OPERATOR);
0251 
0252 #undef Vc_LOGICAL_OPERATOR
0253 #undef Vc_GENERIC_OPERATOR
0254 #undef Vc_COMPARE_OPERATOR
0255 #undef Vc_INVALID_OPERATOR
0256 
0257 }  // namespace Vc
0258 #endif  // COMMON_OPERATORS_H_