/*************************************************************************** * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * 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 XTENSOR_SIMD_HPP #define XTENSOR_SIMD_HPP #include #include #include "xutils.hpp" #ifdef XTENSOR_USE_XSIMD #include // #include #if defined(_MSV_VER) && (_MSV_VER < 1910) template inline xsimd::batch_bool isnan(const xsimd::batch& b) { return xsimd::isnan(b); } #endif namespace xt_simd { template using aligned_allocator = xsimd::aligned_allocator; using aligned_mode = xsimd::aligned_mode; using unaligned_mode = xsimd::unaligned_mode; template using allocator_alignment = xsimd::allocator_alignment; template using allocator_alignment_t = xsimd::allocator_alignment_t; template using container_alignment = xsimd::container_alignment; template using container_alignment_t = xsimd::container_alignment_t; template using simd_traits = xsimd::simd_traits; template using revert_simd_traits = xsimd::revert_simd_traits; template using simd_type = xsimd::simd_type; template using simd_bool_type = xsimd::simd_bool_type; template using revert_simd_type = xsimd::revert_simd_type; template using simd_return_type = xsimd::simd_return_type; using xsimd::broadcast_as; using xsimd::get_alignment_offset; using xsimd::load_as; using xsimd::select; using xsimd::store_as; template using is_batch_bool = xsimd::is_batch_bool; template using is_batch_complex = xsimd::is_batch_complex; template using simd_condition = xsimd::detail::simd_condition; } #else // XTENSOR_USE_XSIMD namespace xt_simd { template class aligned_allocator; struct aligned_mode { }; struct unaligned_mode { }; template struct allocator_alignment { using type = unaligned_mode; }; template using allocator_alignment_t = typename allocator_alignment::type; template struct container_alignment { using type = unaligned_mode; }; template using container_alignment_t = typename container_alignment::type; template struct simd_traits { using type = T; using bool_type = bool; using batch_bool = bool; static constexpr std::size_t size = 1; }; template struct revert_simd_traits { using type = T; static constexpr std::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; template inline simd_type broadcast_as(const T& value) { return value; } template inline simd_type load_as(const T* src, aligned_mode) { return *src; } template inline simd_type load_as(const T* src, unaligned_mode) { return *src; } template inline void store_as(R* dst, const simd_type& src, aligned_mode) { *dst = src; } template inline void store_as(R* dst, const simd_type& src, unaligned_mode) { *dst = src; } template inline T select(bool cond, const T& t1, const T& t2) { return cond ? t1 : t2; } template inline std::size_t get_alignment_offset(const T* /*p*/, std::size_t size, std::size_t /*block_size*/) { return size; } template using simd_return_type = simd_type; template struct is_batch_bool : std::false_type { }; template struct is_batch_complex : std::false_type { }; template struct simd_condition : std::true_type { }; } #endif // XTENSOR_USE_XSIMD namespace xt { using xt_simd::aligned_mode; using xt_simd::unaligned_mode; struct inner_aligned_mode { }; namespace detail { template struct driven_align_mode_impl { using type = std::conditional_t::value, A1, ::xt_simd::unaligned_mode>; }; template struct driven_align_mode_impl { using type = A; }; } template struct driven_align_mode { using type = typename detail::driven_align_mode_impl::type; }; template using driven_align_mode_t = typename detail::driven_align_mode_impl::type; namespace detail { template struct has_load_simd : std::false_type { }; template struct has_load_simd< E, T, void_t().template load_simd(typename E::size_type(0)))>> : std::true_type { }; template ::value> struct has_simd_interface_impl : has_load_simd { }; template struct has_simd_interface_impl : std::false_type { }; } template ::value_type> struct has_simd_interface : detail::has_simd_interface_impl { }; template struct has_simd_type : std::integral_constant>::value> { }; namespace detail { template struct has_simd_apply_impl : std::false_type { }; template struct has_simd_apply_impl)>> : std::true_type { }; } template struct has_simd_apply : detail::has_simd_apply_impl { }; template using bool_load_type = std::conditional_t::value, uint8_t, T>; template struct forbid_simd : std::false_type { }; template struct forbid_simd> : std::true_type { }; template struct forbid_simd> : std::true_type { }; template struct forbid_simd> : std::true_type { }; template struct forbid_simd> : std::true_type { }; template struct container_simd_return_type : std::enable_if::value, xt_simd::simd_return_type>> { }; template using container_simd_return_type_t = typename container_simd_return_type::type; } #endif