/*************************************************************************** * 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_TRAITS_HPP #define XSIMD_TRAITS_HPP #include #include "../types/xsimd_base.hpp" #include "xsimd_types_include.hpp" #undef XSIMD_BATCH_INT_SIZE #undef XSIMD_BATCH_FLOAT_SIZE #undef XSIMD_BATCH_DOUBLE_SIZE #if XSIMD_X86_INSTR_SET >= XSIMD_X86_AVX512_VERSION #define XSIMD_BATCH_INT8_SIZE 64 #define XSIMD_BATCH_INT16_SIZE 32 #define XSIMD_BATCH_INT32_SIZE 16 #define XSIMD_BATCH_INT64_SIZE 8 #define XSIMD_BATCH_FLOAT_SIZE 16 #define XSIMD_BATCH_DOUBLE_SIZE 8 #elif XSIMD_X86_INSTR_SET >= XSIMD_X86_AVX_VERSION #define XSIMD_BATCH_INT8_SIZE 32 #define XSIMD_BATCH_INT16_SIZE 16 #define XSIMD_BATCH_INT32_SIZE 8 #define XSIMD_BATCH_INT64_SIZE 4 #define XSIMD_BATCH_FLOAT_SIZE 8 #define XSIMD_BATCH_DOUBLE_SIZE 4 #elif XSIMD_X86_INSTR_SET >= XSIMD_X86_SSE2_VERSION #define XSIMD_BATCH_INT8_SIZE 16 #define XSIMD_BATCH_INT16_SIZE 8 #define XSIMD_BATCH_INT32_SIZE 4 #define XSIMD_BATCH_INT64_SIZE 2 #define XSIMD_BATCH_FLOAT_SIZE 4 #define XSIMD_BATCH_DOUBLE_SIZE 2 #elif XSIMD_ARM_INSTR_SET >= XSIMD_ARM7_NEON_VERSION #define XSIMD_BATCH_INT8_SIZE 16 #define XSIMD_BATCH_INT16_SIZE 8 #define XSIMD_BATCH_INT32_SIZE 4 #define XSIMD_BATCH_INT64_SIZE 2 #define XSIMD_BATCH_FLOAT_SIZE 4 #if XSIMD_ARM_INSTR_SET >= XSIMD_ARM8_64_NEON_VERSION #define XSIMD_BATCH_DOUBLE_SIZE 2 #elif defined(XSIMD_ENABLE_FALLBACK) #define XSIMD_BATCH_DOUBLE_SIZE 1 #endif #endif namespace xsimd { template struct simd_traits { using type = T; using bool_type = bool; static constexpr size_t size = 1; }; template struct revert_simd_traits { using type = T; static constexpr size_t size = simd_traits::size; }; template using simd_type = typename simd_traits::type; template using simd_bool_type = typename simd_traits::bool_type; template using revert_simd_type = typename revert_simd_traits::type; #ifdef XSIMD_BATCH_FLOAT_SIZE template <> struct simd_traits { using type = batch; using bool_type = simd_batch_traits::batch_bool_type; static constexpr size_t size = type::size; }; template <> struct revert_simd_traits> { using type = int8_t; static constexpr size_t size = simd_traits::size; }; template <> struct simd_traits { using type = batch; using bool_type = simd_batch_traits::batch_bool_type; static constexpr size_t size = type::size; }; template <> struct revert_simd_traits> { using type = uint8_t; static constexpr size_t size = simd_traits::size; }; template <> struct simd_traits { using type = batch; using bool_type = simd_batch_traits::batch_bool_type; static constexpr size_t size = type::size; }; template <> struct revert_simd_traits> { using type = int16_t; static constexpr size_t size = simd_traits::size; }; template <> struct simd_traits { using type = batch; using bool_type = simd_batch_traits::batch_bool_type; static constexpr size_t size = type::size; }; template <> struct revert_simd_traits> { using type = uint16_t; static constexpr size_t size = simd_traits::size; }; template <> struct simd_traits : std::conditional::value, simd_traits, simd_traits>::type { }; template <> struct simd_traits { using type = batch; using bool_type = simd_batch_traits::batch_bool_type; static constexpr size_t size = type::size; }; template <> struct revert_simd_traits> { using type = int32_t; static constexpr size_t size = simd_traits::size; }; template <> struct simd_traits { using type = batch; using bool_type = simd_batch_traits::batch_bool_type; static constexpr size_t size = type::size; }; template <> struct revert_simd_traits> { using type = uint32_t; static constexpr size_t size = simd_traits::size; }; // On some architectures long is a different type from int32_t or int64_t #ifdef XSIMD_32_BIT_ABI template <> struct simd_traits : simd_traits { }; template <> struct revert_simd_traits> { using type = long; static constexpr size_t size = simd_traits::size; }; template <> struct simd_traits : simd_traits { }; template <> struct revert_simd_traits> { using type = unsigned long; static constexpr size_t size = simd_traits::size; }; #endif // XSIMD_32_BIT_ABI template <> struct simd_traits { using type = batch; using bool_type = simd_batch_traits::batch_bool_type; static constexpr size_t size = type::size; }; template <> struct revert_simd_traits> { using type = int64_t; static constexpr size_t size = simd_traits::size; }; template <> struct simd_traits { using type = batch; using bool_type = simd_batch_traits::batch_bool_type; static constexpr size_t size = type::size; }; template <> struct revert_simd_traits> { using type = uint64_t; static constexpr size_t size = simd_traits::size; }; template <> struct simd_traits { using type = batch; using bool_type = simd_batch_traits::batch_bool_type; static constexpr size_t size = type::size; }; template <> struct revert_simd_traits> { using type = float; static constexpr size_t size = simd_traits::size; }; template <> struct simd_traits> { using type = batch, XSIMD_BATCH_FLOAT_SIZE>; using bool_type = simd_batch_traits::batch_bool_type; static constexpr size_t size = type::size; }; template <> struct revert_simd_traits, XSIMD_BATCH_FLOAT_SIZE>> { using type = std::complex; static constexpr size_t size = simd_traits::size; }; #ifdef XSIMD_ENABLE_XTL_COMPLEX template struct simd_traits> { using type = batch, XSIMD_BATCH_FLOAT_SIZE>; using bool_type = typename simd_batch_traits::batch_bool_type; static constexpr size_t size = type::size; }; template struct revert_simd_traits, XSIMD_BATCH_FLOAT_SIZE>> { using type = xtl::xcomplex; static constexpr size_t size = simd_traits::size; }; #endif // XSIMD_ENABLE_XTL_COMPLEX #endif // XSIMD_BATCH_FLOAT_SIZE #ifdef XSIMD_BATCH_DOUBLE_SIZE template <> struct simd_traits { using type = batch; using bool_type = simd_batch_traits::batch_bool_type; static constexpr size_t size = type::size; }; template <> struct revert_simd_traits> { using type = double; static constexpr size_t size = simd_traits::size; }; template <> struct simd_traits> { using type = batch, XSIMD_BATCH_DOUBLE_SIZE>; using bool_type = simd_batch_traits::batch_bool_type; static constexpr size_t size = type::size; }; template <> struct revert_simd_traits, XSIMD_BATCH_DOUBLE_SIZE>> { using type = std::complex; static constexpr size_t size = simd_traits::size; }; #ifdef XSIMD_ENABLE_XTL_COMPLEX template struct simd_traits> { using type = batch, XSIMD_BATCH_DOUBLE_SIZE>; using bool_type = typename simd_batch_traits::batch_bool_type; static constexpr size_t size = type::size; }; template struct revert_simd_traits, XSIMD_BATCH_DOUBLE_SIZE>> { using type = xtl::xcomplex; static constexpr size_t size = simd_traits::size; }; #endif // XSIMD_ENABLE_XTL_COMPLEX #endif // XSIMD_BATCH_DOUBLE_SIZE /******************** * simd_return_type * ********************/ namespace detail { template struct simd_condition { static constexpr bool value = (std::is_same::value && !std::is_same::value) || (std::is_same::value && !std::is_same::value) || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value || detail::is_complex::value; }; template struct simd_return_type_impl : std::enable_if::value, batch> { }; template struct simd_return_type_impl : std::conditional::value, simd_return_type_impl, simd_return_type_impl>::type { }; template struct simd_return_type_impl : std::enable_if::value, batch_bool> { }; template struct simd_return_type_impl, T2, N> : std::enable_if::value, batch, N>> { }; template struct simd_return_type_impl, std::complex, N> : std::enable_if::value, batch, N>> { }; #ifdef XSIMD_ENABLE_XTL_COMPLEX template struct simd_return_type_impl, T2, N> : std::enable_if::value, batch, N>> { }; template struct simd_return_type_impl, xtl::xcomplex, N> : std::enable_if::value, batch, N>> { }; #endif // XSIMD_ENABLE_XTL_COMPLEX } template ::size> using simd_return_type = typename detail::simd_return_type_impl::type; /************ * is_batch * ************/ template struct is_batch : std::false_type { }; template struct is_batch> : std::true_type { }; /***************** * is_batch_bool * *****************/ template struct is_batch_bool : std::false_type { }; template struct is_batch_bool> : std::true_type { }; /******************** * is_batch_complex * ********************/ template struct is_batch_complex : std::false_type { }; template struct is_batch_complex, N>> : std::true_type { }; #ifdef XSIMD_ENABLE_XTL_COMPLEX template struct is_batch_complex, N>> : std::true_type { }; #endif //XSIMD_ENABLE_XTL_COMPLEX } #endif