1e78f53d1SNikolas Klauser // -*- C++ -*- 2e78f53d1SNikolas Klauser //===----------------------------------------------------------------------===// 3e78f53d1SNikolas Klauser // 4e78f53d1SNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5e78f53d1SNikolas Klauser // See https://llvm.org/LICENSE.txt for license information. 6e78f53d1SNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7e78f53d1SNikolas Klauser // 8e78f53d1SNikolas Klauser //===----------------------------------------------------------------------===// 9e78f53d1SNikolas Klauser 10*ce777190SNikolas Klauser #ifndef _LIBCPP___CXX03_EXPERIMENTAL___SIMD_SIMD_H 11*ce777190SNikolas Klauser #define _LIBCPP___CXX03_EXPERIMENTAL___SIMD_SIMD_H 12e78f53d1SNikolas Klauser 1373fbae83SNikolas Klauser #include <__cxx03/__type_traits/is_same.h> 1473fbae83SNikolas Klauser #include <__cxx03/__type_traits/remove_cvref.h> 1573fbae83SNikolas Klauser #include <__cxx03/__utility/forward.h> 1673fbae83SNikolas Klauser #include <__cxx03/cstddef> 1773fbae83SNikolas Klauser #include <__cxx03/experimental/__config> 1873fbae83SNikolas Klauser #include <__cxx03/experimental/__simd/declaration.h> 1973fbae83SNikolas Klauser #include <__cxx03/experimental/__simd/reference.h> 2073fbae83SNikolas Klauser #include <__cxx03/experimental/__simd/traits.h> 2173fbae83SNikolas Klauser #include <__cxx03/experimental/__simd/utility.h> 22e78f53d1SNikolas Klauser 23e78f53d1SNikolas Klauser #if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) 24e78f53d1SNikolas Klauser 25e78f53d1SNikolas Klauser _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL 26e78f53d1SNikolas Klauser inline namespace parallelism_v2 { 27e78f53d1SNikolas Klauser 28e78f53d1SNikolas Klauser // class template simd [simd.class] 29e78f53d1SNikolas Klauser // TODO: implement simd class 30e78f53d1SNikolas Klauser template <class _Tp, class _Abi> 31e78f53d1SNikolas Klauser class simd { 32e78f53d1SNikolas Klauser using _Impl = __simd_operations<_Tp, _Abi>; 33e78f53d1SNikolas Klauser using _Storage = typename _Impl::_SimdStorage; 34e78f53d1SNikolas Klauser 35e78f53d1SNikolas Klauser _Storage __s_; 36e78f53d1SNikolas Klauser 37e78f53d1SNikolas Klauser public: 38e78f53d1SNikolas Klauser using value_type = _Tp; 39e78f53d1SNikolas Klauser using reference = __simd_reference<_Tp, _Storage, value_type>; 40e78f53d1SNikolas Klauser using mask_type = simd_mask<_Tp, _Abi>; 41e78f53d1SNikolas Klauser using abi_type = _Abi; 42e78f53d1SNikolas Klauser 43e78f53d1SNikolas Klauser static _LIBCPP_HIDE_FROM_ABI constexpr size_t size() noexcept { return simd_size_v<value_type, abi_type>; } 44e78f53d1SNikolas Klauser 45e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI simd() noexcept = default; 46e78f53d1SNikolas Klauser 47e78f53d1SNikolas Klauser // broadcast constructor 48e78f53d1SNikolas Klauser template <class _Up, enable_if_t<__can_broadcast_v<value_type, __remove_cvref_t<_Up>>, int> = 0> 49e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI simd(_Up&& __v) noexcept : __s_(_Impl::__broadcast(static_cast<value_type>(__v))) {} 50e78f53d1SNikolas Klauser 51e78f53d1SNikolas Klauser // implicit type conversion constructor 52e78f53d1SNikolas Klauser template <class _Up, 53e78f53d1SNikolas Klauser enable_if_t<!is_same_v<_Up, _Tp> && is_same_v<abi_type, simd_abi::fixed_size<size()>> && 54e78f53d1SNikolas Klauser __is_non_narrowing_convertible_v<_Up, value_type>, 55e78f53d1SNikolas Klauser int> = 0> 56e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI simd(const simd<_Up, simd_abi::fixed_size<size()>>& __v) noexcept { 57e78f53d1SNikolas Klauser for (size_t __i = 0; __i < size(); __i++) { 58e78f53d1SNikolas Klauser (*this)[__i] = static_cast<value_type>(__v[__i]); 59e78f53d1SNikolas Klauser } 60e78f53d1SNikolas Klauser } 61e78f53d1SNikolas Klauser 62e78f53d1SNikolas Klauser // generator constructor 63e78f53d1SNikolas Klauser template <class _Generator, enable_if_t<__can_generate_v<value_type, _Generator, size()>, int> = 0> 64e78f53d1SNikolas Klauser explicit _LIBCPP_HIDE_FROM_ABI simd(_Generator&& __g) noexcept 65e78f53d1SNikolas Klauser : __s_(_Impl::__generate(std::forward<_Generator>(__g))) {} 66e78f53d1SNikolas Klauser 67e78f53d1SNikolas Klauser // load constructor 68e78f53d1SNikolas Klauser template <class _Up, class _Flags, enable_if_t<__is_vectorizable_v<_Up> && is_simd_flag_type_v<_Flags>, int> = 0> 69e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI simd(const _Up* __mem, _Flags) { 70e78f53d1SNikolas Klauser _Impl::__load(__s_, _Flags::template __apply<simd>(__mem)); 71e78f53d1SNikolas Klauser } 72e78f53d1SNikolas Klauser 73e78f53d1SNikolas Klauser // copy functions 74e78f53d1SNikolas Klauser template <class _Up, class _Flags, enable_if_t<__is_vectorizable_v<_Up> && is_simd_flag_type_v<_Flags>, int> = 0> 75e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI void copy_from(const _Up* __mem, _Flags) { 76e78f53d1SNikolas Klauser _Impl::__load(__s_, _Flags::template __apply<simd>(__mem)); 77e78f53d1SNikolas Klauser } 78e78f53d1SNikolas Klauser 79e78f53d1SNikolas Klauser template <class _Up, class _Flags, enable_if_t<__is_vectorizable_v<_Up> && is_simd_flag_type_v<_Flags>, int> = 0> 80e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI void copy_to(_Up* __mem, _Flags) const { 81e78f53d1SNikolas Klauser _Impl::__store(__s_, _Flags::template __apply<simd>(__mem)); 82e78f53d1SNikolas Klauser } 83e78f53d1SNikolas Klauser 84e78f53d1SNikolas Klauser // scalar access [simd.subscr] 85e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI reference operator[](size_t __i) noexcept { return reference(__s_, __i); } 86e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI value_type operator[](size_t __i) const noexcept { return __s_.__get(__i); } 87e78f53d1SNikolas Klauser }; 88e78f53d1SNikolas Klauser 89e78f53d1SNikolas Klauser template <class _Tp, class _Abi> 90e78f53d1SNikolas Klauser inline constexpr bool is_simd_v<simd<_Tp, _Abi>> = true; 91e78f53d1SNikolas Klauser 92e78f53d1SNikolas Klauser template <class _Tp> 93e78f53d1SNikolas Klauser using native_simd = simd<_Tp, simd_abi::native<_Tp>>; 94e78f53d1SNikolas Klauser 95e78f53d1SNikolas Klauser template <class _Tp, int _Np> 96e78f53d1SNikolas Klauser using fixed_size_simd = simd<_Tp, simd_abi::fixed_size<_Np>>; 97e78f53d1SNikolas Klauser 98e78f53d1SNikolas Klauser } // namespace parallelism_v2 99e78f53d1SNikolas Klauser _LIBCPP_END_NAMESPACE_EXPERIMENTAL 100e78f53d1SNikolas Klauser 101e78f53d1SNikolas Klauser #endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) 102*ce777190SNikolas Klauser #endif // _LIBCPP___CXX03_EXPERIMENTAL___SIMD_SIMD_H 103