Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-08-28 09:11:40

0001 /***************************************************************************
0002  * Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *
0003  * Martin Renou                                                             *
0004  * Copyright (c) QuantStack                                                 *
0005  * Copyright (c) Serge Guelton                                              *
0006  *                                                                          *
0007  * Distributed under the terms of the BSD 3-Clause License.                 *
0008  *                                                                          *
0009  * The full license is in the file LICENSE, distributed with this software. *
0010  ****************************************************************************/
0011 
0012 #ifndef XSIMD_TRAITS_HPP
0013 #define XSIMD_TRAITS_HPP
0014 
0015 #include <type_traits>
0016 
0017 #include "xsimd_batch.hpp"
0018 
0019 /**
0020  * high level type traits
0021  *
0022  * @defgroup batch_traits Type traits
0023  *
0024  **/
0025 
0026 namespace xsimd
0027 {
0028 
0029     /**************************************
0030      * simd_traits and revert_simd_traits *
0031      **************************************/
0032 
0033     template <class T, class A = default_arch>
0034     struct has_simd_register : types::has_simd_register<T, A>
0035     {
0036     };
0037 
0038     template <class T, class A>
0039     struct has_simd_register<std::complex<T>, A> : has_simd_register<T, A>
0040     {
0041     };
0042 
0043     namespace detail
0044     {
0045         template <class T, bool>
0046         struct simd_traits_impl;
0047 
0048         template <class T>
0049         struct simd_traits_impl<T, false>
0050         {
0051             using type = T;
0052             using bool_type = bool;
0053             static constexpr size_t size = 1;
0054         };
0055 
0056         template <class T>
0057         constexpr size_t simd_traits_impl<T, false>::size;
0058 
0059         template <class T>
0060         struct simd_traits_impl<T, true>
0061         {
0062             using type = batch<T>;
0063             using bool_type = typename type::batch_bool_type;
0064             static constexpr size_t size = type::size;
0065         };
0066 
0067         template <class T>
0068         constexpr size_t simd_traits_impl<T, true>::size;
0069 
0070         template <class T, class A>
0071         struct static_check_supported_config_emitter
0072         {
0073 
0074             static_assert(A::supported(),
0075                           "usage of batch type with unsupported architecture");
0076             static_assert(!A::supported() || xsimd::has_simd_register<T, A>::value,
0077                           "usage of batch type with unsupported type");
0078         };
0079 
0080         template <class T, class A>
0081         struct static_check_supported_config_emitter<std::complex<T>, A> : static_check_supported_config_emitter<T, A>
0082         {
0083         };
0084 
0085 #ifdef XSIMD_ENABLE_XTL_COMPLEX
0086         template <class T, class A, bool i3ec>
0087         struct static_check_supported_config_emitter<xtl::xcomplex<T, T, i3ec>, A> : static_check_supported_config_emitter<T, A>
0088         {
0089         };
0090 #endif
0091 
0092         // consistency checker
0093         template <class T, class A>
0094         XSIMD_INLINE void static_check_supported_config()
0095         {
0096             (void)static_check_supported_config_emitter<T, A>();
0097         }
0098     }
0099 
0100     template <class T>
0101     struct simd_traits : detail::simd_traits_impl<T, xsimd::has_simd_register<T>::value>
0102     {
0103     };
0104 
0105     template <class T>
0106     struct simd_traits<std::complex<T>>
0107         : detail::simd_traits_impl<std::complex<T>, xsimd::has_simd_register<T>::value>
0108     {
0109     };
0110 
0111 #ifdef XSIMD_ENABLE_XTL_COMPLEX
0112     template <class T, bool i3ec>
0113     struct simd_traits<xtl::xcomplex<T, T, i3ec>>
0114         : detail::simd_traits_impl<std::complex<T>, xsimd::has_simd_register<T>::value>
0115     {
0116     };
0117 #endif
0118 
0119     template <class T>
0120     struct revert_simd_traits
0121     {
0122         using type = T;
0123         static constexpr size_t size = simd_traits<type>::size;
0124     };
0125 
0126     template <class T>
0127     constexpr size_t revert_simd_traits<T>::size;
0128 
0129     template <class T>
0130     struct revert_simd_traits<batch<T>>
0131     {
0132         using type = T;
0133         static constexpr size_t size = batch<T>::size;
0134     };
0135 
0136     template <class T>
0137     constexpr size_t revert_simd_traits<batch<T>>::size;
0138 
0139     template <class T>
0140     using simd_type = typename simd_traits<T>::type;
0141 
0142     template <class T>
0143     using simd_bool_type = typename simd_traits<T>::bool_type;
0144 
0145     template <class T>
0146     using revert_simd_type = typename revert_simd_traits<T>::type;
0147 
0148     /********************
0149      * simd_return_type *
0150      ********************/
0151 
0152     namespace detail
0153     {
0154         template <class T1, class T2>
0155         struct simd_condition
0156         {
0157             static constexpr bool value = (std::is_same<T1, T2>::value && !std::is_same<T1, bool>::value) || (std::is_same<T1, bool>::value && !std::is_same<T2, bool>::value) || std::is_same<T1, float>::value || std::is_same<T1, double>::value || std::is_same<T1, int8_t>::value || std::is_same<T1, uint8_t>::value || std::is_same<T1, int16_t>::value || std::is_same<T1, uint16_t>::value || std::is_same<T1, int32_t>::value || std::is_same<T1, uint32_t>::value || std::is_same<T1, int64_t>::value || std::is_same<T1, uint64_t>::value || std::is_same<T1, char>::value || detail::is_complex<T1>::value;
0158         };
0159 
0160         template <class T1, class T2, class A>
0161         struct simd_return_type_impl
0162             : std::enable_if<simd_condition<T1, T2>::value, batch<T2, A>>
0163         {
0164         };
0165 
0166         template <class T2, class A>
0167         struct simd_return_type_impl<bool, T2, A>
0168             : std::enable_if<simd_condition<bool, T2>::value, batch_bool<T2, A>>
0169         {
0170         };
0171 
0172         template <class T2, class A>
0173         struct simd_return_type_impl<bool, std::complex<T2>, A>
0174             : std::enable_if<simd_condition<bool, T2>::value, batch_bool<T2, A>>
0175         {
0176         };
0177 
0178         template <class T1, class T2, class A>
0179         struct simd_return_type_impl<std::complex<T1>, T2, A>
0180             : std::enable_if<simd_condition<T1, T2>::value, batch<std::complex<T2>, A>>
0181         {
0182         };
0183 
0184         template <class T1, class T2, class A>
0185         struct simd_return_type_impl<std::complex<T1>, std::complex<T2>, A>
0186             : std::enable_if<simd_condition<T1, T2>::value, batch<std::complex<T2>, A>>
0187         {
0188         };
0189 
0190 #ifdef XSIMD_ENABLE_XTL_COMPLEX
0191         template <class T1, class T2, bool I3EC, class A>
0192         struct simd_return_type_impl<xtl::xcomplex<T1, T1, I3EC>, T2, A>
0193             : std::enable_if<simd_condition<T1, T2>::value, batch<std::complex<T2>, A>>
0194         {
0195         };
0196 
0197         template <class T1, class T2, bool I3EC, class A>
0198         struct simd_return_type_impl<xtl::xcomplex<T1, T1, I3EC>, std::complex<T2>, A>
0199             : std::enable_if<simd_condition<T1, T2>::value, batch<std::complex<T2>, A>>
0200         {
0201         };
0202 
0203         template <class T1, class T2, bool I3EC, class A>
0204         struct simd_return_type_impl<xtl::xcomplex<T1, T1, I3EC>, xtl::xcomplex<T2, T2, I3EC>, A>
0205             : std::enable_if<simd_condition<T1, T2>::value, batch<std::complex<T2>, A>>
0206         {
0207         };
0208 
0209         template <class T1, class T2, bool I3EC, class A>
0210         struct simd_return_type_impl<std::complex<T1>, xtl::xcomplex<T2, T2, I3EC>, A>
0211             : std::enable_if<simd_condition<T1, T2>::value, batch<std::complex<T2>, A>>
0212         {
0213         };
0214 #endif
0215     }
0216 
0217     template <class T1, class T2, class A = default_arch>
0218     using simd_return_type = typename detail::simd_return_type_impl<T1, T2, A>::type;
0219 
0220     /**
0221      * @ingroup batch_traits
0222      *
0223      * type traits that inherits from @c std::true_type for @c batch<...> types and from
0224      * @c std::false_type otherwise.
0225      *
0226      * @tparam T type to analyze.
0227      */
0228     template <class T>
0229     struct is_batch;
0230 
0231     template <class T>
0232     struct is_batch : std::false_type
0233     {
0234     };
0235 
0236     template <class T, class A>
0237     struct is_batch<batch<T, A>> : std::true_type
0238     {
0239     };
0240 
0241     /**
0242      * @ingroup batch_traits
0243      *
0244      * type traits that inherits from @c std::true_type for @c batch_bool<...> types and from
0245      * @c std::false_type otherwise.
0246      *
0247      * @tparam T type to analyze.
0248      */
0249 
0250     template <class T>
0251     struct is_batch_bool : std::false_type
0252     {
0253     };
0254 
0255     template <class T, class A>
0256     struct is_batch_bool<batch_bool<T, A>> : std::true_type
0257     {
0258     };
0259 
0260     /**
0261      * @ingroup batch_traits
0262      *
0263      * type traits that inherits from @c std::true_type for @c batch<std::complex<...>>
0264      * types and from @c std::false_type otherwise.
0265      *
0266      * @tparam T type to analyze.
0267      */
0268 
0269     template <class T>
0270     struct is_batch_complex : std::false_type
0271     {
0272     };
0273 
0274     template <class T, class A>
0275     struct is_batch_complex<batch<std::complex<T>, A>> : std::true_type
0276     {
0277     };
0278 
0279     /**
0280      * @ingroup batch_traits
0281      *
0282      * type traits whose @c type field is set to @c T::value_type if @c
0283      * is_batch<T>::value and to @c T otherwise.
0284      *
0285      * @tparam T type to analyze.
0286      */
0287     template <class T>
0288     struct scalar_type
0289     {
0290         using type = T;
0291     };
0292     template <class T, class A>
0293     struct scalar_type<batch<T, A>>
0294     {
0295         using type = T;
0296     };
0297 
0298     template <class T>
0299     using scalar_type_t = typename scalar_type<T>::type;
0300 
0301     /**
0302      * @ingroup batch_traits
0303      *
0304      * type traits whose @c type field is set to @c T::value_type if @c
0305      * is_batch_bool<T>::value and to @c bool otherwise.
0306      *
0307      * @tparam T type to analyze.
0308      */
0309     template <class T>
0310     struct mask_type
0311     {
0312         using type = bool;
0313     };
0314     template <class T, class A>
0315     struct mask_type<batch<T, A>>
0316     {
0317         using type = typename batch<T, A>::batch_bool_type;
0318     };
0319 
0320     template <class T>
0321     using mask_type_t = typename mask_type<T>::type;
0322 }
0323 
0324 #endif