1*5f757f3fSDimitry Andric // -*- C++ -*- 2*5f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 3*5f757f3fSDimitry Andric // 4*5f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5*5f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 6*5f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7*5f757f3fSDimitry Andric // 8*5f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 9*5f757f3fSDimitry Andric 10*5f757f3fSDimitry Andric #ifndef _LIBCPP_EXPERIMENTAL___SIMD_SIMD_H 11*5f757f3fSDimitry Andric #define _LIBCPP_EXPERIMENTAL___SIMD_SIMD_H 12*5f757f3fSDimitry Andric 13*5f757f3fSDimitry Andric #include <__type_traits/is_same.h> 14*5f757f3fSDimitry Andric #include <__type_traits/remove_cvref.h> 15*5f757f3fSDimitry Andric #include <__utility/forward.h> 16*5f757f3fSDimitry Andric #include <cstddef> 17*5f757f3fSDimitry Andric #include <experimental/__config> 18*5f757f3fSDimitry Andric #include <experimental/__simd/abi_tag.h> 19*5f757f3fSDimitry Andric #include <experimental/__simd/declaration.h> 20*5f757f3fSDimitry Andric #include <experimental/__simd/internal_declaration.h> 21*5f757f3fSDimitry Andric #include <experimental/__simd/reference.h> 22*5f757f3fSDimitry Andric #include <experimental/__simd/traits.h> 23*5f757f3fSDimitry Andric #include <experimental/__simd/utility.h> 24*5f757f3fSDimitry Andric 25*5f757f3fSDimitry Andric #if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) 26*5f757f3fSDimitry Andric 27*5f757f3fSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL 28*5f757f3fSDimitry Andric inline namespace parallelism_v2 { 29*5f757f3fSDimitry Andric 30*5f757f3fSDimitry Andric // class template simd [simd.class] 31*5f757f3fSDimitry Andric // TODO: implement simd class 32*5f757f3fSDimitry Andric template <class _Tp, class _Abi> 33*5f757f3fSDimitry Andric class simd { 34*5f757f3fSDimitry Andric using _Impl = __simd_operations<_Tp, _Abi>; 35*5f757f3fSDimitry Andric using _Storage = typename _Impl::_SimdStorage; 36*5f757f3fSDimitry Andric 37*5f757f3fSDimitry Andric _Storage __s_; 38*5f757f3fSDimitry Andric 39*5f757f3fSDimitry Andric public: 40*5f757f3fSDimitry Andric using value_type = _Tp; 41*5f757f3fSDimitry Andric using reference = __simd_reference<_Tp, _Storage, value_type>; 42*5f757f3fSDimitry Andric using mask_type = simd_mask<_Tp, _Abi>; 43*5f757f3fSDimitry Andric using abi_type = _Abi; 44*5f757f3fSDimitry Andric 45*5f757f3fSDimitry Andric static _LIBCPP_HIDE_FROM_ABI constexpr size_t size() noexcept { return simd_size_v<value_type, abi_type>; } 46*5f757f3fSDimitry Andric 47*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI simd() noexcept = default; 48*5f757f3fSDimitry Andric 49*5f757f3fSDimitry Andric // broadcast constructor 50*5f757f3fSDimitry Andric template <class _Up, enable_if_t<__can_broadcast_v<value_type, __remove_cvref_t<_Up>>, int> = 0> 51*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI simd(_Up&& __v) noexcept : __s_(_Impl::__broadcast(static_cast<value_type>(__v))) {} 52*5f757f3fSDimitry Andric 53*5f757f3fSDimitry Andric // implicit type conversion constructor 54*5f757f3fSDimitry Andric template <class _Up, 55*5f757f3fSDimitry Andric enable_if_t<!is_same_v<_Up, _Tp> && is_same_v<abi_type, simd_abi::fixed_size<size()>> && 56*5f757f3fSDimitry Andric __is_non_narrowing_convertible_v<_Up, value_type>, 57*5f757f3fSDimitry Andric int> = 0> 58*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI simd(const simd<_Up, simd_abi::fixed_size<size()>>& __v) noexcept { 59*5f757f3fSDimitry Andric for (size_t __i = 0; __i < size(); __i++) { 60*5f757f3fSDimitry Andric (*this)[__i] = static_cast<value_type>(__v[__i]); 61*5f757f3fSDimitry Andric } 62*5f757f3fSDimitry Andric } 63*5f757f3fSDimitry Andric 64*5f757f3fSDimitry Andric // generator constructor 65*5f757f3fSDimitry Andric template <class _Generator, enable_if_t<__can_generate_v<value_type, _Generator, size()>, int> = 0> 66*5f757f3fSDimitry Andric explicit _LIBCPP_HIDE_FROM_ABI simd(_Generator&& __g) noexcept 67*5f757f3fSDimitry Andric : __s_(_Impl::__generate(std::forward<_Generator>(__g))) {} 68*5f757f3fSDimitry Andric 69*5f757f3fSDimitry Andric // scalar access [simd.subscr] 70*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI reference operator[](size_t __i) noexcept { return reference(__s_, __i); } 71*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI value_type operator[](size_t __i) const noexcept { return __s_.__get(__i); } 72*5f757f3fSDimitry Andric }; 73*5f757f3fSDimitry Andric 74*5f757f3fSDimitry Andric template <class _Tp, class _Abi> 75*5f757f3fSDimitry Andric inline constexpr bool is_simd_v<simd<_Tp, _Abi>> = true; 76*5f757f3fSDimitry Andric 77*5f757f3fSDimitry Andric template <class _Tp> 78*5f757f3fSDimitry Andric using native_simd = simd<_Tp, simd_abi::native<_Tp>>; 79*5f757f3fSDimitry Andric 80*5f757f3fSDimitry Andric template <class _Tp, int _Np> 81*5f757f3fSDimitry Andric using fixed_size_simd = simd<_Tp, simd_abi::fixed_size<_Np>>; 82*5f757f3fSDimitry Andric 83*5f757f3fSDimitry Andric } // namespace parallelism_v2 84*5f757f3fSDimitry Andric _LIBCPP_END_NAMESPACE_EXPERIMENTAL 85*5f757f3fSDimitry Andric 86*5f757f3fSDimitry Andric #endif // _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) 87*5f757f3fSDimitry Andric #endif // _LIBCPP_EXPERIMENTAL___SIMD_SIMD_H 88