1*4ba319b5SDimitry Andric// -*- C++ -*- 2*4ba319b5SDimitry Andric//===------------------------------- simd ---------------------------------===// 3*4ba319b5SDimitry Andric// 4*4ba319b5SDimitry Andric// The LLVM Compiler Infrastructure 5*4ba319b5SDimitry Andric// 6*4ba319b5SDimitry Andric// This file is dual licensed under the MIT and the University of Illinois Open 7*4ba319b5SDimitry Andric// Source Licenses. See LICENSE.TXT for details. 8*4ba319b5SDimitry Andric// 9*4ba319b5SDimitry Andric//===----------------------------------------------------------------------===// 10*4ba319b5SDimitry Andric#ifndef _LIBCPP_EXPERIMENTAL_SIMD 11*4ba319b5SDimitry Andric#define _LIBCPP_EXPERIMENTAL_SIMD 12*4ba319b5SDimitry Andric 13*4ba319b5SDimitry Andric/* 14*4ba319b5SDimitry Andric experimental/simd synopsis 15*4ba319b5SDimitry Andric 16*4ba319b5SDimitry Andricnamespace std::experimental { 17*4ba319b5SDimitry Andric 18*4ba319b5SDimitry Andricinline namespace parallelism_v2 { 19*4ba319b5SDimitry Andric 20*4ba319b5SDimitry Andricnamespace simd_abi { 21*4ba319b5SDimitry Andric 22*4ba319b5SDimitry Andricstruct scalar {}; 23*4ba319b5SDimitry Andrictemplate <int N> struct fixed_size {}; 24*4ba319b5SDimitry Andrictemplate <typename T> inline constexpr int max_fixed_size = implementation-defined; 25*4ba319b5SDimitry Andrictemplate <typename T> using compatible = implementation-defined; 26*4ba319b5SDimitry Andrictemplate <typename T> using native = implementation-defined; 27*4ba319b5SDimitry Andric 28*4ba319b5SDimitry Andric} // simd_abi 29*4ba319b5SDimitry Andric 30*4ba319b5SDimitry Andricstruct element_aligned_tag {}; 31*4ba319b5SDimitry Andricstruct vector_aligned_tag {}; 32*4ba319b5SDimitry Andrictemplate <size_t> struct overaligned_tag {}; 33*4ba319b5SDimitry Andricinline constexpr element_aligned_tag element_aligned{}; 34*4ba319b5SDimitry Andricinline constexpr vector_aligned_tag vector_aligned{}; 35*4ba319b5SDimitry Andrictemplate <size_t N> inline constexpr overaligned_tag<N> overaligned{}; 36*4ba319b5SDimitry Andric 37*4ba319b5SDimitry Andric// traits [simd.traits] 38*4ba319b5SDimitry Andrictemplate <class T> struct is_abi_tag; 39*4ba319b5SDimitry Andrictemplate <class T> inline constexpr bool is_abi_tag_v = is_abi_tag<T>::value; 40*4ba319b5SDimitry Andric 41*4ba319b5SDimitry Andrictemplate <class T> struct is_simd; 42*4ba319b5SDimitry Andrictemplate <class T> inline constexpr bool is_simd_v = is_simd<T>::value; 43*4ba319b5SDimitry Andric 44*4ba319b5SDimitry Andrictemplate <class T> struct is_simd_mask; 45*4ba319b5SDimitry Andrictemplate <class T> inline constexpr bool is_simd_mask_v = is_simd_mask<T>::value; 46*4ba319b5SDimitry Andric 47*4ba319b5SDimitry Andrictemplate <class T> struct is_simd_flag_type; 48*4ba319b5SDimitry Andrictemplate <class T> inline constexpr bool is_simd_flag_type_v = is_simd_flag_type<T>::value; 49*4ba319b5SDimitry Andric 50*4ba319b5SDimitry Andrictemplate <class T, size_t N> struct abi_for_size { using type = see below; }; 51*4ba319b5SDimitry Andrictemplate <class T, size_t N> using abi_for_size_t = typename abi_for_size<T, N>::type; 52*4ba319b5SDimitry Andric 53*4ba319b5SDimitry Andrictemplate <class T, class Abi = simd_abi::compatible<T>> struct simd_size; 54*4ba319b5SDimitry Andrictemplate <class T, class Abi = simd_abi::compatible<T>> 55*4ba319b5SDimitry Andricinline constexpr size_t simd_size_v = simd_size<T, Abi>::value; 56*4ba319b5SDimitry Andric 57*4ba319b5SDimitry Andrictemplate <class T, class U = typename T::value_type> struct memory_alignment; 58*4ba319b5SDimitry Andrictemplate <class T, class U = typename T::value_type> 59*4ba319b5SDimitry Andricinline constexpr size_t memory_alignment_v = memory_alignment<T, U>::value; 60*4ba319b5SDimitry Andric 61*4ba319b5SDimitry Andric// class template simd [simd.class] 62*4ba319b5SDimitry Andrictemplate <class T, class Abi = simd_abi::compatible<T>> class simd; 63*4ba319b5SDimitry Andrictemplate <class T> using native_simd = simd<T, simd_abi::native<T>>; 64*4ba319b5SDimitry Andrictemplate <class T, int N> using fixed_size_simd = simd<T, simd_abi::fixed_size<N>>; 65*4ba319b5SDimitry Andric 66*4ba319b5SDimitry Andric// class template simd_mask [simd.mask.class] 67*4ba319b5SDimitry Andrictemplate <class T, class Abi = simd_abi::compatible<T>> class simd_mask; 68*4ba319b5SDimitry Andrictemplate <class T> using native_simd_mask = simd_mask<T, simd_abi::native<T>>; 69*4ba319b5SDimitry Andrictemplate <class T, int N> using fixed_size_simd_mask = simd_mask<T, simd_abi::fixed_size<N>>; 70*4ba319b5SDimitry Andric 71*4ba319b5SDimitry Andric// casts [simd.casts] 72*4ba319b5SDimitry Andrictemplate <class T, class U, class Abi> see below simd_cast(const simd<U, Abi>&); 73*4ba319b5SDimitry Andrictemplate <class T, class U, class Abi> see below static_simd_cast(const simd<U, Abi>&); 74*4ba319b5SDimitry Andric 75*4ba319b5SDimitry Andrictemplate <class T, class Abi> 76*4ba319b5SDimitry Andricfixed_size_simd<T, simd_size_v<T, Abi>> to_fixed_size(const simd<T, Abi>&) noexcept; 77*4ba319b5SDimitry Andrictemplate <class T, class Abi> 78*4ba319b5SDimitry Andricfixed_size_simd_mask<T, simd_size_v<T, Abi>> to_fixed_size(const simd_mask<T, Abi>&) noexcept; 79*4ba319b5SDimitry Andrictemplate <class T, size_t N> native_simd<T> to_native(const fixed_size_simd<T, N>&) noexcept; 80*4ba319b5SDimitry Andrictemplate <class T, size_t N> 81*4ba319b5SDimitry Andricnative_simd_mask<T> to_native(const fixed_size_simd_mask<T, N>> &) noexcept; 82*4ba319b5SDimitry Andrictemplate <class T, size_t N> simd<T> to_compatible(const fixed_size_simd<T, N>&) noexcept; 83*4ba319b5SDimitry Andrictemplate <class T, size_t N> simd_mask<T> to_compatible(const fixed_size_simd_mask<T, N>&) noexcept; 84*4ba319b5SDimitry Andric 85*4ba319b5SDimitry Andrictemplate <size_t... Sizes, class T, class Abi> 86*4ba319b5SDimitry Andrictuple<simd<T, abi_for_size_t<Sizes>>...> split(const simd<T, Abi>&); 87*4ba319b5SDimitry Andrictemplate <size_t... Sizes, class T, class Abi> 88*4ba319b5SDimitry Andrictuple<simd_mask<T, abi_for_size_t<Sizes>>...> split(const simd_mask<T, Abi>&); 89*4ba319b5SDimitry Andrictemplate <class V, class Abi> 90*4ba319b5SDimitry Andricarray<V, simd_size_v<typename V::value_type, Abi> / V::size()> split( 91*4ba319b5SDimitry Andricconst simd<typename V::value_type, Abi>&); 92*4ba319b5SDimitry Andrictemplate <class V, class Abi> 93*4ba319b5SDimitry Andricarray<V, simd_size_v<typename V::value_type, Abi> / V::size()> split( 94*4ba319b5SDimitry Andricconst simd_mask<typename V::value_type, Abi>&); 95*4ba319b5SDimitry Andric 96*4ba319b5SDimitry Andrictemplate <class T, class... Abis> 97*4ba319b5SDimitry Andricsimd<T, abi_for_size_t<T, (simd_size_v<T, Abis> + ...)>> concat(const simd<T, Abis>&...); 98*4ba319b5SDimitry Andrictemplate <class T, class... Abis> 99*4ba319b5SDimitry Andricsimd_mask<T, abi_for_size_t<T, (simd_size_v<T, Abis> + ...)>> concat(const simd_mask<T, Abis>&...); 100*4ba319b5SDimitry Andric 101*4ba319b5SDimitry Andric// reductions [simd.mask.reductions] 102*4ba319b5SDimitry Andrictemplate <class T, class Abi> bool all_of(const simd_mask<T, Abi>&) noexcept; 103*4ba319b5SDimitry Andrictemplate <class T, class Abi> bool any_of(const simd_mask<T, Abi>&) noexcept; 104*4ba319b5SDimitry Andrictemplate <class T, class Abi> bool none_of(const simd_mask<T, Abi>&) noexcept; 105*4ba319b5SDimitry Andrictemplate <class T, class Abi> bool some_of(const simd_mask<T, Abi>&) noexcept; 106*4ba319b5SDimitry Andrictemplate <class T, class Abi> int popcount(const simd_mask<T, Abi>&) noexcept; 107*4ba319b5SDimitry Andrictemplate <class T, class Abi> int find_first_set(const simd_mask<T, Abi>&); 108*4ba319b5SDimitry Andrictemplate <class T, class Abi> int find_last_set(const simd_mask<T, Abi>&); 109*4ba319b5SDimitry Andric 110*4ba319b5SDimitry Andricbool all_of(see below) noexcept; 111*4ba319b5SDimitry Andricbool any_of(see below) noexcept; 112*4ba319b5SDimitry Andricbool none_of(see below) noexcept; 113*4ba319b5SDimitry Andricbool some_of(see below) noexcept; 114*4ba319b5SDimitry Andricint popcount(see below) noexcept; 115*4ba319b5SDimitry Andricint find_first_set(see below) noexcept; 116*4ba319b5SDimitry Andricint find_last_set(see below) noexcept; 117*4ba319b5SDimitry Andric 118*4ba319b5SDimitry Andric// masked assignment [simd.whereexpr] 119*4ba319b5SDimitry Andrictemplate <class M, class T> class const_where_expression; 120*4ba319b5SDimitry Andrictemplate <class M, class T> class where_expression; 121*4ba319b5SDimitry Andric 122*4ba319b5SDimitry Andric// masked assignment [simd.mask.where] 123*4ba319b5SDimitry Andrictemplate <class T> struct nodeduce { using type = T; }; // exposition only 124*4ba319b5SDimitry Andric 125*4ba319b5SDimitry Andrictemplate <class T> using nodeduce_t = typename nodeduce<T>::type; // exposition only 126*4ba319b5SDimitry Andric 127*4ba319b5SDimitry Andrictemplate <class T, class Abi> 128*4ba319b5SDimitry Andricwhere_expression<simd_mask<T, Abi>, simd<T, Abi>> 129*4ba319b5SDimitry Andricwhere(const typename simd<T, Abi>::mask_type&, simd<T, Abi>&) noexcept; 130*4ba319b5SDimitry Andric 131*4ba319b5SDimitry Andrictemplate <class T, class Abi> 132*4ba319b5SDimitry Andricconst_where_expression<simd_mask<T, Abi>, const simd<T, Abi>> 133*4ba319b5SDimitry Andricwhere(const typename simd<T, Abi>::mask_type&, const simd<T, Abi>&) noexcept; 134*4ba319b5SDimitry Andric 135*4ba319b5SDimitry Andrictemplate <class T, class Abi> 136*4ba319b5SDimitry Andricwhere_expression<simd_mask<T, Abi>, simd_mask<T, Abi>> 137*4ba319b5SDimitry Andricwhere(const nodeduce_t<simd_mask<T, Abi>>&, simd_mask<T, Abi>&) noexcept; 138*4ba319b5SDimitry Andric 139*4ba319b5SDimitry Andrictemplate <class T, class Abi> 140*4ba319b5SDimitry Andricconst_where_expression<simd_mask<T, Abi>, const simd_mask<T, Abi>> 141*4ba319b5SDimitry Andricwhere(const nodeduce_t<simd_mask<T, Abi>>&, const simd_mask<T, Abi>&) noexcept; 142*4ba319b5SDimitry Andric 143*4ba319b5SDimitry Andrictemplate <class T> where_expression<bool, T> where(see below k, T& d) noexcept; 144*4ba319b5SDimitry Andric 145*4ba319b5SDimitry Andrictemplate <class T> 146*4ba319b5SDimitry Andricconst_where_expression<bool, const T> where(see below k, const T& d) noexcept; 147*4ba319b5SDimitry Andric 148*4ba319b5SDimitry Andric// reductions [simd.reductions] 149*4ba319b5SDimitry Andrictemplate <class T, class Abi, class BinaryOperation = std::plus<>> 150*4ba319b5SDimitry AndricT reduce(const simd<T, Abi>&, BinaryOperation = BinaryOperation()); 151*4ba319b5SDimitry Andric 152*4ba319b5SDimitry Andrictemplate <class M, class V, class BinaryOperation> 153*4ba319b5SDimitry Andrictypename V::value_type reduce(const const_where_expression<M, V>& x, 154*4ba319b5SDimitry Andrictypename V::value_type neutral_element, BinaryOperation binary_op); 155*4ba319b5SDimitry Andric 156*4ba319b5SDimitry Andrictemplate <class M, class V> 157*4ba319b5SDimitry Andrictypename V::value_type reduce(const const_where_expression<M, V>& x, plus<> binary_op = plus<>()); 158*4ba319b5SDimitry Andric 159*4ba319b5SDimitry Andrictemplate <class M, class V> 160*4ba319b5SDimitry Andrictypename V::value_type reduce(const const_where_expression<M, V>& x, multiplies<> binary_op); 161*4ba319b5SDimitry Andric 162*4ba319b5SDimitry Andrictemplate <class M, class V> 163*4ba319b5SDimitry Andrictypename V::value_type reduce(const const_where_expression<M, V>& x, bit_and<> binary_op); 164*4ba319b5SDimitry Andric 165*4ba319b5SDimitry Andrictemplate <class M, class V> 166*4ba319b5SDimitry Andrictypename V::value_type reduce(const const_where_expression<M, V>& x, bit_or<> binary_op); 167*4ba319b5SDimitry Andric 168*4ba319b5SDimitry Andrictemplate <class M, class V> 169*4ba319b5SDimitry Andrictypename V::value_type reduce(const const_where_expression<M, V>& x, bit_xor<> binary_op); 170*4ba319b5SDimitry Andric 171*4ba319b5SDimitry Andrictemplate <class T, class Abi> T hmin(const simd<T, Abi>&); 172*4ba319b5SDimitry Andrictemplate <class M, class V> T hmin(const const_where_expression<M, V>&); 173*4ba319b5SDimitry Andrictemplate <class T, class Abi> T hmax(const simd<T, Abi>&); 174*4ba319b5SDimitry Andrictemplate <class M, class V> T hmax(const const_where_expression<M, V>&); 175*4ba319b5SDimitry Andric 176*4ba319b5SDimitry Andric// algorithms [simd.alg] 177*4ba319b5SDimitry Andrictemplate <class T, class Abi> simd<T, Abi> min(const simd<T, Abi>&, const simd<T, Abi>&) noexcept; 178*4ba319b5SDimitry Andric 179*4ba319b5SDimitry Andrictemplate <class T, class Abi> simd<T, Abi> max(const simd<T, Abi>&, const simd<T, Abi>&) noexcept; 180*4ba319b5SDimitry Andric 181*4ba319b5SDimitry Andrictemplate <class T, class Abi> 182*4ba319b5SDimitry Andricstd::pair<simd<T, Abi>, simd<T, Abi>> minmax(const simd<T, Abi>&, const simd<T, Abi>&) noexcept; 183*4ba319b5SDimitry Andric 184*4ba319b5SDimitry Andrictemplate <class T, class Abi> 185*4ba319b5SDimitry Andricsimd<T, Abi> clamp(const simd<T, Abi>& v, const simd<T, Abi>& lo, const simd<T, Abi>& hi); 186*4ba319b5SDimitry Andric 187*4ba319b5SDimitry Andric// [simd.whereexpr] 188*4ba319b5SDimitry Andrictemplate <class M, class T> 189*4ba319b5SDimitry Andricclass const_where_expression { 190*4ba319b5SDimitry Andric const M& mask; // exposition only 191*4ba319b5SDimitry Andric T& data; // exposition only 192*4ba319b5SDimitry Andricpublic: 193*4ba319b5SDimitry Andric const_where_expression(const const_where_expression&) = delete; 194*4ba319b5SDimitry Andric const_where_expression& operator=(const const_where_expression&) = delete; 195*4ba319b5SDimitry Andric remove_const_t<T> operator-() const &&; 196*4ba319b5SDimitry Andric template <class U, class Flags> void copy_to(U* mem, Flags f) const &&; 197*4ba319b5SDimitry Andric}; 198*4ba319b5SDimitry Andric 199*4ba319b5SDimitry Andrictemplate <class M, class T> 200*4ba319b5SDimitry Andricclass where_expression : public const_where_expression<M, T> { 201*4ba319b5SDimitry Andricpublic: 202*4ba319b5SDimitry Andric where_expression(const where_expression&) = delete; 203*4ba319b5SDimitry Andric where_expression& operator=(const where_expression&) = delete; 204*4ba319b5SDimitry Andric template <class U> void operator=(U&& x); 205*4ba319b5SDimitry Andric template <class U> void operator+=(U&& x); 206*4ba319b5SDimitry Andric template <class U> void operator-=(U&& x); 207*4ba319b5SDimitry Andric template <class U> void operator*=(U&& x); 208*4ba319b5SDimitry Andric template <class U> void operator/=(U&& x); 209*4ba319b5SDimitry Andric template <class U> void operator%=(U&& x); 210*4ba319b5SDimitry Andric template <class U> void operator&=(U&& x); 211*4ba319b5SDimitry Andric template <class U> void operator|=(U&& x); 212*4ba319b5SDimitry Andric template <class U> void operator^=(U&& x); 213*4ba319b5SDimitry Andric template <class U> void operator<<=(U&& x); 214*4ba319b5SDimitry Andric template <class U> void operator>>=(U&& x); 215*4ba319b5SDimitry Andric void operator++(); 216*4ba319b5SDimitry Andric void operator++(int); 217*4ba319b5SDimitry Andric void operator--(); 218*4ba319b5SDimitry Andric void operator--(int); 219*4ba319b5SDimitry Andric template <class U, class Flags> void copy_from(const U* mem, Flags); 220*4ba319b5SDimitry Andric}; 221*4ba319b5SDimitry Andric 222*4ba319b5SDimitry Andric// [simd.class] 223*4ba319b5SDimitry Andrictemplate <class T, class Abi> class simd { 224*4ba319b5SDimitry Andricpublic: 225*4ba319b5SDimitry Andric using value_type = T; 226*4ba319b5SDimitry Andric using reference = see below; 227*4ba319b5SDimitry Andric using mask_type = simd_mask<T, Abi>; 228*4ba319b5SDimitry Andric 229*4ba319b5SDimitry Andric using abi_type = Abi; 230*4ba319b5SDimitry Andric static constexpr size_t size() noexcept; 231*4ba319b5SDimitry Andric simd() = default; 232*4ba319b5SDimitry Andric 233*4ba319b5SDimitry Andric // implicit type conversion constructor 234*4ba319b5SDimitry Andric template <class U> simd(const simd<U, simd_abi::fixed_size<size()>>&); 235*4ba319b5SDimitry Andric 236*4ba319b5SDimitry Andric // implicit broadcast constructor (see below for constraints) 237*4ba319b5SDimitry Andric template <class U> simd(U&& value); 238*4ba319b5SDimitry Andric 239*4ba319b5SDimitry Andric // generator constructor (see below for constraints) 240*4ba319b5SDimitry Andric template <class G> explicit simd(G&& gen); 241*4ba319b5SDimitry Andric 242*4ba319b5SDimitry Andric // load constructor 243*4ba319b5SDimitry Andric template <class U, class Flags> simd(const U* mem, Flags f); 244*4ba319b5SDimitry Andric 245*4ba319b5SDimitry Andric // loads [simd.load] 246*4ba319b5SDimitry Andric template <class U, class Flags> void copy_from(const U* mem, Flags f); 247*4ba319b5SDimitry Andric 248*4ba319b5SDimitry Andric // stores [simd.store] 249*4ba319b5SDimitry Andric template <class U, class Flags> void copy_to(U* mem, Flags f) const; 250*4ba319b5SDimitry Andric 251*4ba319b5SDimitry Andric // scalar access [simd.subscr] 252*4ba319b5SDimitry Andric reference operator[](size_t); 253*4ba319b5SDimitry Andric value_type operator[](size_t) const; 254*4ba319b5SDimitry Andric 255*4ba319b5SDimitry Andric // unary operators [simd.unary] 256*4ba319b5SDimitry Andric simd& operator++(); 257*4ba319b5SDimitry Andric simd operator++(int); 258*4ba319b5SDimitry Andric simd& operator--(); 259*4ba319b5SDimitry Andric simd operator--(int); 260*4ba319b5SDimitry Andric mask_type operator!() const; 261*4ba319b5SDimitry Andric simd operator~() const; // see below 262*4ba319b5SDimitry Andric simd operator+() const; 263*4ba319b5SDimitry Andric simd operator-() const; 264*4ba319b5SDimitry Andric 265*4ba319b5SDimitry Andric // binary operators [simd.binary] 266*4ba319b5SDimitry Andric friend simd operator+ (const simd&, const simd&); 267*4ba319b5SDimitry Andric friend simd operator- (const simd&, const simd&); 268*4ba319b5SDimitry Andric friend simd operator* (const simd&, const simd&); 269*4ba319b5SDimitry Andric friend simd operator/ (const simd&, const simd&); 270*4ba319b5SDimitry Andric friend simd operator% (const simd&, const simd&); 271*4ba319b5SDimitry Andric friend simd operator& (const simd&, const simd&); 272*4ba319b5SDimitry Andric friend simd operator| (const simd&, const simd&); 273*4ba319b5SDimitry Andric friend simd operator^ (const simd&, const simd&); 274*4ba319b5SDimitry Andric friend simd operator<<(const simd&, const simd&); 275*4ba319b5SDimitry Andric friend simd operator>>(const simd&, const simd&); 276*4ba319b5SDimitry Andric friend simd operator<<(const simd&, int); 277*4ba319b5SDimitry Andric friend simd operator>>(const simd&, int); 278*4ba319b5SDimitry Andric 279*4ba319b5SDimitry Andric // compound assignment [simd.cassign] 280*4ba319b5SDimitry Andric friend simd& operator+= (simd&, const simd&); 281*4ba319b5SDimitry Andric friend simd& operator-= (simd&, const simd&); 282*4ba319b5SDimitry Andric friend simd& operator*= (simd&, const simd&); 283*4ba319b5SDimitry Andric friend simd& operator/= (simd&, const simd&); 284*4ba319b5SDimitry Andric friend simd& operator%= (simd&, const simd&); 285*4ba319b5SDimitry Andric 286*4ba319b5SDimitry Andric friend simd& operator&= (simd&, const simd&); 287*4ba319b5SDimitry Andric friend simd& operator|= (simd&, const simd&); 288*4ba319b5SDimitry Andric friend simd& operator^= (simd&, const simd&); 289*4ba319b5SDimitry Andric friend simd& operator<<=(simd&, const simd&); 290*4ba319b5SDimitry Andric friend simd& operator>>=(simd&, const simd&); 291*4ba319b5SDimitry Andric friend simd& operator<<=(simd&, int); 292*4ba319b5SDimitry Andric friend simd& operator>>=(simd&, int); 293*4ba319b5SDimitry Andric 294*4ba319b5SDimitry Andric // compares [simd.comparison] 295*4ba319b5SDimitry Andric friend mask_type operator==(const simd&, const simd&); 296*4ba319b5SDimitry Andric friend mask_type operator!=(const simd&, const simd&); 297*4ba319b5SDimitry Andric friend mask_type operator>=(const simd&, const simd&); 298*4ba319b5SDimitry Andric friend mask_type operator<=(const simd&, const simd&); 299*4ba319b5SDimitry Andric friend mask_type operator> (const simd&, const simd&); 300*4ba319b5SDimitry Andric friend mask_type operator< (const simd&, const simd&); 301*4ba319b5SDimitry Andric}; 302*4ba319b5SDimitry Andric 303*4ba319b5SDimitry Andric// [simd.math] 304*4ba319b5SDimitry Andrictemplate <class Abi> using scharv = simd<signed char, Abi>; // exposition only 305*4ba319b5SDimitry Andrictemplate <class Abi> using shortv = simd<short, Abi>; // exposition only 306*4ba319b5SDimitry Andrictemplate <class Abi> using intv = simd<int, Abi>; // exposition only 307*4ba319b5SDimitry Andrictemplate <class Abi> using longv = simd<long int, Abi>; // exposition only 308*4ba319b5SDimitry Andrictemplate <class Abi> using llongv = simd<long long int, Abi>; // exposition only 309*4ba319b5SDimitry Andrictemplate <class Abi> using floatv = simd<float, Abi>; // exposition only 310*4ba319b5SDimitry Andrictemplate <class Abi> using doublev = simd<double, Abi>; // exposition only 311*4ba319b5SDimitry Andrictemplate <class Abi> using ldoublev = simd<long double, Abi>; // exposition only 312*4ba319b5SDimitry Andrictemplate <class T, class V> using samesize = fixed_size_simd<T, V::size()>; // exposition only 313*4ba319b5SDimitry Andric 314*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> acos(floatv<Abi> x); 315*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> acos(doublev<Abi> x); 316*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> acos(ldoublev<Abi> x); 317*4ba319b5SDimitry Andric 318*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> asin(floatv<Abi> x); 319*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> asin(doublev<Abi> x); 320*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> asin(ldoublev<Abi> x); 321*4ba319b5SDimitry Andric 322*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> atan(floatv<Abi> x); 323*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> atan(doublev<Abi> x); 324*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> atan(ldoublev<Abi> x); 325*4ba319b5SDimitry Andric 326*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> atan2(floatv<Abi> y, floatv<Abi> x); 327*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> atan2(doublev<Abi> y, doublev<Abi> x); 328*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> atan2(ldoublev<Abi> y, ldoublev<Abi> x); 329*4ba319b5SDimitry Andric 330*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> cos(floatv<Abi> x); 331*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> cos(doublev<Abi> x); 332*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> cos(ldoublev<Abi> x); 333*4ba319b5SDimitry Andric 334*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> sin(floatv<Abi> x); 335*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> sin(doublev<Abi> x); 336*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> sin(ldoublev<Abi> x); 337*4ba319b5SDimitry Andric 338*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> tan(floatv<Abi> x); 339*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> tan(doublev<Abi> x); 340*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> tan(ldoublev<Abi> x); 341*4ba319b5SDimitry Andric 342*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> acosh(floatv<Abi> x); 343*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> acosh(doublev<Abi> x); 344*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> acosh(ldoublev<Abi> x); 345*4ba319b5SDimitry Andric 346*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> asinh(floatv<Abi> x); 347*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> asinh(doublev<Abi> x); 348*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> asinh(ldoublev<Abi> x); 349*4ba319b5SDimitry Andric 350*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> atanh(floatv<Abi> x); 351*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> atanh(doublev<Abi> x); 352*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> atanh(ldoublev<Abi> x); 353*4ba319b5SDimitry Andric 354*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> cosh(floatv<Abi> x); 355*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> cosh(doublev<Abi> x); 356*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> cosh(ldoublev<Abi> x); 357*4ba319b5SDimitry Andric 358*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> sinh(floatv<Abi> x); 359*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> sinh(doublev<Abi> x); 360*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> sinh(ldoublev<Abi> x); 361*4ba319b5SDimitry Andric 362*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> tanh(floatv<Abi> x); 363*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> tanh(doublev<Abi> x); 364*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> tanh(ldoublev<Abi> x); 365*4ba319b5SDimitry Andric 366*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> exp(floatv<Abi> x); 367*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> exp(doublev<Abi> x); 368*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> exp(ldoublev<Abi> x); 369*4ba319b5SDimitry Andric 370*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> exp2(floatv<Abi> x); 371*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> exp2(doublev<Abi> x); 372*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> exp2(ldoublev<Abi> x); 373*4ba319b5SDimitry Andric 374*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> expm1(floatv<Abi> x); 375*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> expm1(doublev<Abi> x); 376*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> expm1(ldoublev<Abi> x); 377*4ba319b5SDimitry Andric 378*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> frexp(floatv<Abi> value, samesize<int, floatv<Abi>>* exp); 379*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> frexp(doublev<Abi> value, samesize<int, doublev<Abi>>* exp); 380*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> frexp(ldoublev<Abi> value, samesize<int, ldoublev<Abi>>* exp); 381*4ba319b5SDimitry Andric 382*4ba319b5SDimitry Andrictemplate <class Abi> samesize<int, floatv<Abi>> ilogb(floatv<Abi> x); 383*4ba319b5SDimitry Andrictemplate <class Abi> samesize<int, doublev<Abi>> ilogb(doublev<Abi> x); 384*4ba319b5SDimitry Andrictemplate <class Abi> samesize<int, ldoublev<Abi>> ilogb(ldoublev<Abi> x); 385*4ba319b5SDimitry Andric 386*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> ldexp(floatv<Abi> x, samesize<int, floatv<Abi>> exp); 387*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> ldexp(doublev<Abi> x, samesize<int, doublev<Abi>> exp); 388*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> ldexp(ldoublev<Abi> x, samesize<int, ldoublev<Abi>> exp); 389*4ba319b5SDimitry Andric 390*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> log(floatv<Abi> x); 391*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> log(doublev<Abi> x); 392*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> log(ldoublev<Abi> x); 393*4ba319b5SDimitry Andric 394*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> log10(floatv<Abi> x); 395*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> log10(doublev<Abi> x); 396*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> log10(ldoublev<Abi> x); 397*4ba319b5SDimitry Andric 398*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> log1p(floatv<Abi> x); 399*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> log1p(doublev<Abi> x); 400*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> log1p(ldoublev<Abi> x); 401*4ba319b5SDimitry Andric 402*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> log2(floatv<Abi> x); 403*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> log2(doublev<Abi> x); 404*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> log2(ldoublev<Abi> x); 405*4ba319b5SDimitry Andric 406*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> logb(floatv<Abi> x); 407*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> logb(doublev<Abi> x); 408*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> logb(ldoublev<Abi> x); 409*4ba319b5SDimitry Andric 410*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> modf(floatv<Abi> value, floatv<Abi>* iptr); 411*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> modf(doublev<Abi> value, doublev<Abi>* iptr); 412*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> modf(ldoublev<Abi> value, ldoublev<Abi>* iptr); 413*4ba319b5SDimitry Andric 414*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> scalbn(floatv<Abi> x, samesize<int, floatv<Abi>> n); 415*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> scalbn(doublev<Abi> x, samesize<int, doublev<Abi>> n); 416*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> scalbn(ldoublev<Abi> x, samesize<int, ldoublev<Abi>> n); 417*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> scalbln(floatv<Abi> x, samesize<long int, floatv<Abi>> n); 418*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> scalbln(doublev<Abi> x, samesize<long int, doublev<Abi>> n); 419*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> scalbln(ldoublev<Abi> x, samesize<long int, ldoublev<Abi>> n); 420*4ba319b5SDimitry Andric 421*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> cbrt(floatv<Abi> x); 422*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> cbrt(doublev<Abi> x); 423*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> cbrt(ldoublev<Abi> x); 424*4ba319b5SDimitry Andric 425*4ba319b5SDimitry Andrictemplate <class Abi> scharv<Abi> abs(scharv<Abi> j); 426*4ba319b5SDimitry Andrictemplate <class Abi> shortv<Abi> abs(shortv<Abi> j); 427*4ba319b5SDimitry Andrictemplate <class Abi> intv<Abi> abs(intv<Abi> j); 428*4ba319b5SDimitry Andrictemplate <class Abi> longv<Abi> abs(longv<Abi> j); 429*4ba319b5SDimitry Andrictemplate <class Abi> llongv<Abi> abs(llongv<Abi> j); 430*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> abs(floatv<Abi> j); 431*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> abs(doublev<Abi> j); 432*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> abs(ldoublev<Abi> j); 433*4ba319b5SDimitry Andric 434*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> hypot(floatv<Abi> x, floatv<Abi> y); 435*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> hypot(doublev<Abi> x, doublev<Abi> y); 436*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> hypot(doublev<Abi> x, doublev<Abi> y); 437*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> hypot(floatv<Abi> x, floatv<Abi> y, floatv<Abi> z); 438*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> hypot(doublev<Abi> x, doublev<Abi> y, doublev<Abi> z); 439*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> hypot(ldoublev<Abi> x, ldoublev<Abi> y, ldoublev<Abi> z); 440*4ba319b5SDimitry Andric 441*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> pow(floatv<Abi> x, floatv<Abi> y); 442*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> pow(doublev<Abi> x, doublev<Abi> y); 443*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> pow(ldoublev<Abi> x, ldoublev<Abi> y); 444*4ba319b5SDimitry Andric 445*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> sqrt(floatv<Abi> x); 446*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> sqrt(doublev<Abi> x); 447*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> sqrt(ldoublev<Abi> x); 448*4ba319b5SDimitry Andric 449*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> erf(floatv<Abi> x); 450*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> erf(doublev<Abi> x); 451*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> erf(ldoublev<Abi> x); 452*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> erfc(floatv<Abi> x); 453*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> erfc(doublev<Abi> x); 454*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> erfc(ldoublev<Abi> x); 455*4ba319b5SDimitry Andric 456*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> lgamma(floatv<Abi> x); 457*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> lgamma(doublev<Abi> x); 458*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> lgamma(ldoublev<Abi> x); 459*4ba319b5SDimitry Andric 460*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> tgamma(floatv<Abi> x); 461*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> tgamma(doublev<Abi> x); 462*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> tgamma(ldoublev<Abi> x); 463*4ba319b5SDimitry Andric 464*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> ceil(floatv<Abi> x); 465*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> ceil(doublev<Abi> x); 466*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> ceil(ldoublev<Abi> x); 467*4ba319b5SDimitry Andric 468*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> floor(floatv<Abi> x); 469*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> floor(doublev<Abi> x); 470*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> floor(ldoublev<Abi> x); 471*4ba319b5SDimitry Andric 472*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> nearbyint(floatv<Abi> x); 473*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> nearbyint(doublev<Abi> x); 474*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> nearbyint(ldoublev<Abi> x); 475*4ba319b5SDimitry Andric 476*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> rint(floatv<Abi> x); 477*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> rint(doublev<Abi> x); 478*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> rint(ldoublev<Abi> x); 479*4ba319b5SDimitry Andric 480*4ba319b5SDimitry Andrictemplate <class Abi> samesize<long int, floatv<Abi>> lrint(floatv<Abi> x); 481*4ba319b5SDimitry Andrictemplate <class Abi> samesize<long int, doublev<Abi>> lrint(doublev<Abi> x); 482*4ba319b5SDimitry Andrictemplate <class Abi> samesize<long int, ldoublev<Abi>> lrint(ldoublev<Abi> x); 483*4ba319b5SDimitry Andrictemplate <class Abi> samesize<long long int, floatv<Abi>> llrint(floatv<Abi> x); 484*4ba319b5SDimitry Andrictemplate <class Abi> samesize<long long int, doublev<Abi>> llrint(doublev<Abi> x); 485*4ba319b5SDimitry Andrictemplate <class Abi> samesize<long long int, ldoublev<Abi>> llrint(ldoublev<Abi> x); 486*4ba319b5SDimitry Andric 487*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> round(floatv<Abi> x); 488*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> round(doublev<Abi> x); 489*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> round(ldoublev<Abi> x); 490*4ba319b5SDimitry Andrictemplate <class Abi> samesize<long int, floatv<Abi>> lround(floatv<Abi> x); 491*4ba319b5SDimitry Andrictemplate <class Abi> samesize<long int, doublev<Abi>> lround(doublev<Abi> x); 492*4ba319b5SDimitry Andrictemplate <class Abi> samesize<long int, ldoublev<Abi>> lround(ldoublev<Abi> x); 493*4ba319b5SDimitry Andrictemplate <class Abi> samesize<long long int, floatv<Abi>> llround(floatv<Abi> x); 494*4ba319b5SDimitry Andrictemplate <class Abi> samesize<long long int, doublev<Abi>> llround(doublev<Abi> x); 495*4ba319b5SDimitry Andrictemplate <class Abi> samesize<long long int, ldoublev<Abi>> llround(ldoublev<Abi> x); 496*4ba319b5SDimitry Andric 497*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> trunc(floatv<Abi> x); 498*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> trunc(doublev<Abi> x); 499*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> trunc(ldoublev<Abi> x); 500*4ba319b5SDimitry Andric 501*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> fmod(floatv<Abi> x, floatv<Abi> y); 502*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> fmod(doublev<Abi> x, doublev<Abi> y); 503*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> fmod(ldoublev<Abi> x, ldoublev<Abi> y); 504*4ba319b5SDimitry Andric 505*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> remainder(floatv<Abi> x, floatv<Abi> y); 506*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> remainder(doublev<Abi> x, doublev<Abi> y); 507*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> remainder(ldoublev<Abi> x, ldoublev<Abi> y); 508*4ba319b5SDimitry Andric 509*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> remquo(floatv<Abi> x, floatv<Abi> y, samesize<int, floatv<Abi>>* quo); 510*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> remquo(doublev<Abi> x, doublev<Abi> y, samesize<int, doublev<Abi>>* quo); 511*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> remquo(ldoublev<Abi> x, ldoublev<Abi> y, samesize<int, ldoublev<Abi>>* quo); 512*4ba319b5SDimitry Andric 513*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> copysign(floatv<Abi> x, floatv<Abi> y); 514*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> copysign(doublev<Abi> x, doublev<Abi> y); 515*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> copysign(ldoublev<Abi> x, ldoublev<Abi> y); 516*4ba319b5SDimitry Andric 517*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> nan(const char* tagp); 518*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> nanf(const char* tagp); 519*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> nanl(const char* tagp); 520*4ba319b5SDimitry Andric 521*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> nextafter(floatv<Abi> x, floatv<Abi> y); 522*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> nextafter(doublev<Abi> x, doublev<Abi> y); 523*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> nextafter(ldoublev<Abi> x, ldoublev<Abi> y); 524*4ba319b5SDimitry Andric 525*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> nexttoward(floatv<Abi> x, ldoublev<Abi> y); 526*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> nexttoward(doublev<Abi> x, ldoublev<Abi> y); 527*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> nexttoward(ldoublev<Abi> x, ldoublev<Abi> y); 528*4ba319b5SDimitry Andric 529*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> fdim(floatv<Abi> x, floatv<Abi> y); 530*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> fdim(doublev<Abi> x, doublev<Abi> y); 531*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> fdim(ldoublev<Abi> x, ldoublev<Abi> y); 532*4ba319b5SDimitry Andric 533*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> fmax(floatv<Abi> x, floatv<Abi> y); 534*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> fmax(doublev<Abi> x, doublev<Abi> y); 535*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> fmax(ldoublev<Abi> x, ldoublev<Abi> y); 536*4ba319b5SDimitry Andric 537*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> fmin(floatv<Abi> x, floatv<Abi> y); 538*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> fmin(doublev<Abi> x, doublev<Abi> y); 539*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> fmin(ldoublev<Abi> x, ldoublev<Abi> y); 540*4ba319b5SDimitry Andric 541*4ba319b5SDimitry Andrictemplate <class Abi> floatv<Abi> fma(floatv<Abi> x, floatv<Abi> y, floatv<Abi> z); 542*4ba319b5SDimitry Andrictemplate <class Abi> doublev<Abi> fma(doublev<Abi> x, doublev<Abi> y, doublev<Abi> z); 543*4ba319b5SDimitry Andrictemplate <class Abi> ldoublev<Abi> fma(ldoublev<Abi> x, ldoublev<Abi> y, ldoublev<Abi> z); 544*4ba319b5SDimitry Andric 545*4ba319b5SDimitry Andrictemplate <class Abi> samesize<int, floatv<Abi>> fpclassify(floatv<Abi> x); 546*4ba319b5SDimitry Andrictemplate <class Abi> samesize<int, doublev<Abi>> fpclassify(doublev<Abi> x); 547*4ba319b5SDimitry Andrictemplate <class Abi> samesize<int, ldoublev<Abi>> fpclassify(ldoublev<Abi> x); 548*4ba319b5SDimitry Andric 549*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<float, Abi> isfinite(floatv<Abi> x); 550*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<double, Abi> isfinite(doublev<Abi> x); 551*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<long double, Abi> isfinite(ldoublev<Abi> x); 552*4ba319b5SDimitry Andric 553*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<float, Abi> isinf(floatv<Abi> x); 554*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<double, Abi> isinf(doublev<Abi> x); 555*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<long double, Abi> isinf(ldoublev<Abi> x); 556*4ba319b5SDimitry Andric 557*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<float, Abi> isnan(floatv<Abi> x); 558*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<double, Abi> isnan(doublev<Abi> x); 559*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<long double, Abi> isnan(ldoublev<Abi> x); 560*4ba319b5SDimitry Andric 561*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<float, Abi> isnormal(floatv<Abi> x); 562*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<double, Abi> isnormal(doublev<Abi> x); 563*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<long double, Abi> isnormal(ldoublev<Abi> x); 564*4ba319b5SDimitry Andric 565*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<float, Abi> signbit(floatv<Abi> x); 566*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<double, Abi> signbit(doublev<Abi> x); 567*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<long double, Abi> signbit(ldoublev<Abi> x); 568*4ba319b5SDimitry Andric 569*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<float, Abi> isgreater(floatv<Abi> x, floatv<Abi> y); 570*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<double, Abi> isgreater(doublev<Abi> x, doublev<Abi> y); 571*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<long double, Abi> isgreater(ldoublev<Abi> x, ldoublev<Abi> y); 572*4ba319b5SDimitry Andric 573*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<float, Abi> isgreaterequal(floatv<Abi> x, floatv<Abi> y); 574*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<double, Abi> isgreaterequal(doublev<Abi> x, doublev<Abi> y); 575*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<long double, Abi> isgreaterequal(ldoublev<Abi> x, ldoublev<Abi> y); 576*4ba319b5SDimitry Andric 577*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<float, Abi> isless(floatv<Abi> x, floatv<Abi> y); 578*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<double, Abi> isless(doublev<Abi> x, doublev<Abi> y); 579*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<long double, Abi> isless(ldoublev<Abi> x, ldoublev<Abi> y); 580*4ba319b5SDimitry Andric 581*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<float, Abi> islessequal(floatv<Abi> x, floatv<Abi> y); 582*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<double, Abi> islessequal(doublev<Abi> x, doublev<Abi> y); 583*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<long double, Abi> islessequal(ldoublev<Abi> x, ldoublev<Abi> y); 584*4ba319b5SDimitry Andric 585*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<float, Abi> islessgreater(floatv<Abi> x, floatv<Abi> y); 586*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<double, Abi> islessgreater(doublev<Abi> x, doublev<Abi> y); 587*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<long double, Abi> islessgreater(ldoublev<Abi> x, ldoublev<Abi> y); 588*4ba319b5SDimitry Andric 589*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<float, Abi> isunordered(floatv<Abi> x, floatv<Abi> y); 590*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<double, Abi> isunordered(doublev<Abi> x, doublev<Abi> y); 591*4ba319b5SDimitry Andrictemplate <class Abi> simd_mask<long double, Abi> isunordered(ldoublev<Abi> x, ldoublev<Abi> y); 592*4ba319b5SDimitry Andric 593*4ba319b5SDimitry Andrictemplate <class V> struct simd_div_t { V quot, rem; }; 594*4ba319b5SDimitry Andrictemplate <class Abi> simd_div_t<scharv<Abi>> div(scharv<Abi> numer, scharv<Abi> denom); 595*4ba319b5SDimitry Andrictemplate <class Abi> simd_div_t<shortv<Abi>> div(shortv<Abi> numer, shortv<Abi> denom); 596*4ba319b5SDimitry Andrictemplate <class Abi> simd_div_t<intv<Abi>> div(intv<Abi> numer, intv<Abi> denom); 597*4ba319b5SDimitry Andrictemplate <class Abi> simd_div_t<longv<Abi>> div(longv<Abi> numer, longv<Abi> denom); 598*4ba319b5SDimitry Andrictemplate <class Abi> simd_div_t<llongv<Abi>> div(llongv<Abi> numer, llongv<Abi> denom); 599*4ba319b5SDimitry Andric 600*4ba319b5SDimitry Andric// [simd.mask.class] 601*4ba319b5SDimitry Andrictemplate <class T, class Abi> 602*4ba319b5SDimitry Andricclass simd_mask { 603*4ba319b5SDimitry Andricpublic: 604*4ba319b5SDimitry Andric using value_type = bool; 605*4ba319b5SDimitry Andric using reference = see below; 606*4ba319b5SDimitry Andric using simd_type = simd<T, Abi>; 607*4ba319b5SDimitry Andric using abi_type = Abi; 608*4ba319b5SDimitry Andric static constexpr size_t size() noexcept; 609*4ba319b5SDimitry Andric simd_mask() = default; 610*4ba319b5SDimitry Andric 611*4ba319b5SDimitry Andric // broadcast constructor 612*4ba319b5SDimitry Andric explicit simd_mask(value_type) noexcept; 613*4ba319b5SDimitry Andric 614*4ba319b5SDimitry Andric // implicit type conversion constructor 615*4ba319b5SDimitry Andric template <class U> simd_mask(const simd_mask<U, simd_abi::fixed_size<size()>>&) noexcept; 616*4ba319b5SDimitry Andric 617*4ba319b5SDimitry Andric // load constructor 618*4ba319b5SDimitry Andric template <class Flags> simd_mask(const value_type* mem, Flags); 619*4ba319b5SDimitry Andric 620*4ba319b5SDimitry Andric // loads [simd.mask.copy] 621*4ba319b5SDimitry Andric template <class Flags> void copy_from(const value_type* mem, Flags); 622*4ba319b5SDimitry Andric template <class Flags> void copy_to(value_type* mem, Flags) const; 623*4ba319b5SDimitry Andric 624*4ba319b5SDimitry Andric // scalar access [simd.mask.subscr] 625*4ba319b5SDimitry Andric reference operator[](size_t); 626*4ba319b5SDimitry Andric value_type operator[](size_t) const; 627*4ba319b5SDimitry Andric 628*4ba319b5SDimitry Andric // unary operators [simd.mask.unary] 629*4ba319b5SDimitry Andric simd_mask operator!() const noexcept; 630*4ba319b5SDimitry Andric 631*4ba319b5SDimitry Andric // simd_mask binary operators [simd.mask.binary] 632*4ba319b5SDimitry Andric friend simd_mask operator&&(const simd_mask&, const simd_mask&) noexcept; 633*4ba319b5SDimitry Andric friend simd_mask operator||(const simd_mask&, const simd_mask&) noexcept; 634*4ba319b5SDimitry Andric friend simd_mask operator& (const simd_mask&, const simd_mask&) noexcept; 635*4ba319b5SDimitry Andric friend simd_mask operator| (const simd_mask&, const simd_mask&) noexcept; 636*4ba319b5SDimitry Andric friend simd_mask operator^ (const simd_mask&, const simd_mask&) noexcept; 637*4ba319b5SDimitry Andric 638*4ba319b5SDimitry Andric // simd_mask compound assignment [simd.mask.cassign] 639*4ba319b5SDimitry Andric friend simd_mask& operator&=(simd_mask&, const simd_mask&) noexcept; 640*4ba319b5SDimitry Andric friend simd_mask& operator|=(simd_mask&, const simd_mask&) noexcept; 641*4ba319b5SDimitry Andric friend simd_mask& operator^=(simd_mask&, const simd_mask&) noexcept; 642*4ba319b5SDimitry Andric 643*4ba319b5SDimitry Andric // simd_mask compares [simd.mask.comparison] 644*4ba319b5SDimitry Andric friend simd_mask operator==(const simd_mask&, const simd_mask&) noexcept; 645*4ba319b5SDimitry Andric friend simd_mask operator!=(const simd_mask&, const simd_mask&) noexcept; 646*4ba319b5SDimitry Andric}; 647*4ba319b5SDimitry Andric 648*4ba319b5SDimitry Andric} // parallelism_v2 649*4ba319b5SDimitry Andric} // std::experimental 650*4ba319b5SDimitry Andric 651*4ba319b5SDimitry Andric*/ 652*4ba319b5SDimitry Andric 653*4ba319b5SDimitry Andric#include <experimental/__config> 654*4ba319b5SDimitry Andric#include <algorithm> 655*4ba319b5SDimitry Andric#include <array> 656*4ba319b5SDimitry Andric#include <cstddef> 657*4ba319b5SDimitry Andric#include <functional> 658*4ba319b5SDimitry Andric 659*4ba319b5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 660*4ba319b5SDimitry Andric#pragma GCC system_header 661*4ba319b5SDimitry Andric#endif 662*4ba319b5SDimitry Andric 663*4ba319b5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_SIMD 664*4ba319b5SDimitry Andric 665*4ba319b5SDimitry Andric#if _LIBCPP_STD_VER >= 17 666*4ba319b5SDimitry Andric 667*4ba319b5SDimitry Andricenum class _StorageKind { 668*4ba319b5SDimitry Andric _Scalar, 669*4ba319b5SDimitry Andric _Array, 670*4ba319b5SDimitry Andric _VecExt, 671*4ba319b5SDimitry Andric}; 672*4ba319b5SDimitry Andric 673*4ba319b5SDimitry Andrictemplate <_StorageKind __kind, int _Np> 674*4ba319b5SDimitry Andricstruct __simd_abi {}; 675*4ba319b5SDimitry Andric 676*4ba319b5SDimitry Andrictemplate <class _Tp, class _Abi> 677*4ba319b5SDimitry Andricclass __simd_storage {}; 678*4ba319b5SDimitry Andric 679*4ba319b5SDimitry Andrictemplate <class _Tp, int __num_element> 680*4ba319b5SDimitry Andricclass __simd_storage<_Tp, __simd_abi<_StorageKind::_Array, __num_element>> { 681*4ba319b5SDimitry Andric std::array<_Tp, __num_element> __storage_; 682*4ba319b5SDimitry Andric 683*4ba319b5SDimitry Andric template <class, class> 684*4ba319b5SDimitry Andric friend struct simd; 685*4ba319b5SDimitry Andric 686*4ba319b5SDimitry Andric template <class, class> 687*4ba319b5SDimitry Andric friend struct simd_mask; 688*4ba319b5SDimitry Andric 689*4ba319b5SDimitry Andricpublic: 690*4ba319b5SDimitry Andric _Tp __get(size_t __index) const noexcept { return __storage_[__index]; }; 691*4ba319b5SDimitry Andric void __set(size_t __index, _Tp __val) noexcept { 692*4ba319b5SDimitry Andric __storage_[__index] = __val; 693*4ba319b5SDimitry Andric } 694*4ba319b5SDimitry Andric}; 695*4ba319b5SDimitry Andric 696*4ba319b5SDimitry Andrictemplate <class _Tp> 697*4ba319b5SDimitry Andricclass __simd_storage<_Tp, __simd_abi<_StorageKind::_Scalar, 1>> { 698*4ba319b5SDimitry Andric _Tp __storage_; 699*4ba319b5SDimitry Andric 700*4ba319b5SDimitry Andric template <class, class> 701*4ba319b5SDimitry Andric friend struct simd; 702*4ba319b5SDimitry Andric 703*4ba319b5SDimitry Andric template <class, class> 704*4ba319b5SDimitry Andric friend struct simd_mask; 705*4ba319b5SDimitry Andric 706*4ba319b5SDimitry Andricpublic: 707*4ba319b5SDimitry Andric _Tp __get(size_t __index) const noexcept { return (&__storage_)[__index]; }; 708*4ba319b5SDimitry Andric void __set(size_t __index, _Tp __val) noexcept { 709*4ba319b5SDimitry Andric (&__storage_)[__index] = __val; 710*4ba319b5SDimitry Andric } 711*4ba319b5SDimitry Andric}; 712*4ba319b5SDimitry Andric 713*4ba319b5SDimitry Andric#ifndef _LIBCPP_HAS_NO_VECTOR_EXTENSION 714*4ba319b5SDimitry Andric 715*4ba319b5SDimitry Andricconstexpr size_t __floor_pow_of_2(size_t __val) { 716*4ba319b5SDimitry Andric return ((__val - 1) & __val) == 0 ? __val 717*4ba319b5SDimitry Andric : __floor_pow_of_2((__val - 1) & __val); 718*4ba319b5SDimitry Andric} 719*4ba319b5SDimitry Andric 720*4ba319b5SDimitry Andricconstexpr size_t __ceil_pow_of_2(size_t __val) { 721*4ba319b5SDimitry Andric return __val == 1 ? 1 : __floor_pow_of_2(__val - 1) << 1; 722*4ba319b5SDimitry Andric} 723*4ba319b5SDimitry Andric 724*4ba319b5SDimitry Andrictemplate <class _Tp, size_t __bytes> 725*4ba319b5SDimitry Andricstruct __vec_ext_traits { 726*4ba319b5SDimitry Andric#if !defined(_LIBCPP_COMPILER_CLANG) 727*4ba319b5SDimitry Andric typedef _Tp type __attribute__((vector_size(__ceil_pow_of_2(__bytes)))); 728*4ba319b5SDimitry Andric#endif 729*4ba319b5SDimitry Andric}; 730*4ba319b5SDimitry Andric 731*4ba319b5SDimitry Andric#if defined(_LIBCPP_COMPILER_CLANG) 732*4ba319b5SDimitry Andric#define _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, _NUM_ELEMENT) \ 733*4ba319b5SDimitry Andric template <> \ 734*4ba319b5SDimitry Andric struct __vec_ext_traits<_TYPE, sizeof(_TYPE) * _NUM_ELEMENT> { \ 735*4ba319b5SDimitry Andric using type = \ 736*4ba319b5SDimitry Andric _TYPE __attribute__((vector_size(sizeof(_TYPE) * _NUM_ELEMENT))); \ 737*4ba319b5SDimitry Andric } 738*4ba319b5SDimitry Andric 739*4ba319b5SDimitry Andric#define _LIBCPP_SPECIALIZE_VEC_EXT_32(_TYPE) \ 740*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 1); \ 741*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 2); \ 742*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 3); \ 743*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 4); \ 744*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 5); \ 745*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 6); \ 746*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 7); \ 747*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 8); \ 748*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 9); \ 749*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 10); \ 750*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 11); \ 751*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 12); \ 752*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 13); \ 753*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 14); \ 754*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 15); \ 755*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 16); \ 756*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 17); \ 757*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 18); \ 758*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 19); \ 759*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 20); \ 760*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 21); \ 761*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 22); \ 762*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 23); \ 763*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 24); \ 764*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 25); \ 765*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 26); \ 766*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 27); \ 767*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 28); \ 768*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 29); \ 769*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 30); \ 770*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 31); \ 771*4ba319b5SDimitry Andric _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 32); 772*4ba319b5SDimitry Andric 773*4ba319b5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(char); 774*4ba319b5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(char16_t); 775*4ba319b5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(char32_t); 776*4ba319b5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(wchar_t); 777*4ba319b5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(signed char); 778*4ba319b5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(signed short); 779*4ba319b5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(signed int); 780*4ba319b5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(signed long); 781*4ba319b5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(signed long long); 782*4ba319b5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned char); 783*4ba319b5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned short); 784*4ba319b5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned int); 785*4ba319b5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned long); 786*4ba319b5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned long long); 787*4ba319b5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(float); 788*4ba319b5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(double); 789*4ba319b5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(long double); 790*4ba319b5SDimitry Andric 791*4ba319b5SDimitry Andric#undef _LIBCPP_SPECIALIZE_VEC_EXT_32 792*4ba319b5SDimitry Andric#undef _LIBCPP_SPECIALIZE_VEC_EXT 793*4ba319b5SDimitry Andric#endif 794*4ba319b5SDimitry Andric 795*4ba319b5SDimitry Andrictemplate <class _Tp, int __num_element> 796*4ba319b5SDimitry Andricclass __simd_storage<_Tp, __simd_abi<_StorageKind::_VecExt, __num_element>> { 797*4ba319b5SDimitry Andric using _StorageType = 798*4ba319b5SDimitry Andric typename __vec_ext_traits<_Tp, sizeof(_Tp) * __num_element>::type; 799*4ba319b5SDimitry Andric 800*4ba319b5SDimitry Andric _StorageType __storage_; 801*4ba319b5SDimitry Andric 802*4ba319b5SDimitry Andric template <class, class> 803*4ba319b5SDimitry Andric friend struct simd; 804*4ba319b5SDimitry Andric 805*4ba319b5SDimitry Andric template <class, class> 806*4ba319b5SDimitry Andric friend struct simd_mask; 807*4ba319b5SDimitry Andric 808*4ba319b5SDimitry Andricpublic: 809*4ba319b5SDimitry Andric _Tp __get(size_t __index) const noexcept { return __storage_[__index]; }; 810*4ba319b5SDimitry Andric void __set(size_t __index, _Tp __val) noexcept { 811*4ba319b5SDimitry Andric __storage_[__index] = __val; 812*4ba319b5SDimitry Andric } 813*4ba319b5SDimitry Andric}; 814*4ba319b5SDimitry Andric 815*4ba319b5SDimitry Andric#endif // _LIBCPP_HAS_NO_VECTOR_EXTENSION 816*4ba319b5SDimitry Andric 817*4ba319b5SDimitry Andrictemplate <class _Vp, class _Tp, class _Abi> 818*4ba319b5SDimitry Andricclass __simd_reference { 819*4ba319b5SDimitry Andric static_assert(std::is_same<_Vp, _Tp>::value, ""); 820*4ba319b5SDimitry Andric 821*4ba319b5SDimitry Andric template <class, class> 822*4ba319b5SDimitry Andric friend struct simd; 823*4ba319b5SDimitry Andric 824*4ba319b5SDimitry Andric template <class, class> 825*4ba319b5SDimitry Andric friend struct simd_mask; 826*4ba319b5SDimitry Andric 827*4ba319b5SDimitry Andric __simd_storage<_Tp, _Abi>* __ptr_; 828*4ba319b5SDimitry Andric size_t __index_; 829*4ba319b5SDimitry Andric 830*4ba319b5SDimitry Andric __simd_reference(__simd_storage<_Tp, _Abi>* __ptr, size_t __index) 831*4ba319b5SDimitry Andric : __ptr_(__ptr), __index_(__index) {} 832*4ba319b5SDimitry Andric 833*4ba319b5SDimitry Andric __simd_reference(const __simd_reference&) = default; 834*4ba319b5SDimitry Andric 835*4ba319b5SDimitry Andricpublic: 836*4ba319b5SDimitry Andric __simd_reference() = delete; 837*4ba319b5SDimitry Andric __simd_reference& operator=(const __simd_reference&) = delete; 838*4ba319b5SDimitry Andric 839*4ba319b5SDimitry Andric operator _Vp() const { return __ptr_->__get(__index_); } 840*4ba319b5SDimitry Andric 841*4ba319b5SDimitry Andric __simd_reference operator=(_Vp __value) && { 842*4ba319b5SDimitry Andric __ptr_->__set(__index_, __value); 843*4ba319b5SDimitry Andric return *this; 844*4ba319b5SDimitry Andric } 845*4ba319b5SDimitry Andric 846*4ba319b5SDimitry Andric __simd_reference operator++() && { 847*4ba319b5SDimitry Andric return std::move(*this) = __ptr_->__get(__index_) + 1; 848*4ba319b5SDimitry Andric } 849*4ba319b5SDimitry Andric 850*4ba319b5SDimitry Andric _Vp operator++(int) && { 851*4ba319b5SDimitry Andric auto __val = __ptr_->__get(__index_); 852*4ba319b5SDimitry Andric __ptr_->__set(__index_, __val + 1); 853*4ba319b5SDimitry Andric return __val; 854*4ba319b5SDimitry Andric } 855*4ba319b5SDimitry Andric 856*4ba319b5SDimitry Andric __simd_reference operator--() && { 857*4ba319b5SDimitry Andric return std::move(*this) = __ptr_->__get(__index_) - 1; 858*4ba319b5SDimitry Andric } 859*4ba319b5SDimitry Andric 860*4ba319b5SDimitry Andric _Vp operator--(int) && { 861*4ba319b5SDimitry Andric auto __val = __ptr_->__get(__index_); 862*4ba319b5SDimitry Andric __ptr_->__set(__index_, __val - 1); 863*4ba319b5SDimitry Andric return __val; 864*4ba319b5SDimitry Andric } 865*4ba319b5SDimitry Andric 866*4ba319b5SDimitry Andric __simd_reference operator+=(_Vp __value) && { 867*4ba319b5SDimitry Andric return std::move(*this) = __ptr_->__get(__index_) + __value; 868*4ba319b5SDimitry Andric } 869*4ba319b5SDimitry Andric 870*4ba319b5SDimitry Andric __simd_reference operator-=(_Vp __value) && { 871*4ba319b5SDimitry Andric return std::move(*this) = __ptr_->__get(__index_) - __value; 872*4ba319b5SDimitry Andric } 873*4ba319b5SDimitry Andric 874*4ba319b5SDimitry Andric __simd_reference operator*=(_Vp __value) && { 875*4ba319b5SDimitry Andric return std::move(*this) = __ptr_->__get(__index_) * __value; 876*4ba319b5SDimitry Andric } 877*4ba319b5SDimitry Andric 878*4ba319b5SDimitry Andric __simd_reference operator/=(_Vp __value) && { 879*4ba319b5SDimitry Andric return std::move(*this) = __ptr_->__get(__index_) / __value; 880*4ba319b5SDimitry Andric } 881*4ba319b5SDimitry Andric 882*4ba319b5SDimitry Andric __simd_reference operator%=(_Vp __value) && { 883*4ba319b5SDimitry Andric return std::move(*this) = __ptr_->__get(__index_) % __value; 884*4ba319b5SDimitry Andric } 885*4ba319b5SDimitry Andric 886*4ba319b5SDimitry Andric __simd_reference operator>>=(_Vp __value) && { 887*4ba319b5SDimitry Andric return std::move(*this) = __ptr_->__get(__index_) >> __value; 888*4ba319b5SDimitry Andric } 889*4ba319b5SDimitry Andric 890*4ba319b5SDimitry Andric __simd_reference operator<<=(_Vp __value) && { 891*4ba319b5SDimitry Andric return std::move(*this) = __ptr_->__get(__index_) << __value; 892*4ba319b5SDimitry Andric } 893*4ba319b5SDimitry Andric 894*4ba319b5SDimitry Andric __simd_reference operator&=(_Vp __value) && { 895*4ba319b5SDimitry Andric return std::move(*this) = __ptr_->__get(__index_) & __value; 896*4ba319b5SDimitry Andric } 897*4ba319b5SDimitry Andric 898*4ba319b5SDimitry Andric __simd_reference operator|=(_Vp __value) && { 899*4ba319b5SDimitry Andric return std::move(*this) = __ptr_->__get(__index_) | __value; 900*4ba319b5SDimitry Andric } 901*4ba319b5SDimitry Andric 902*4ba319b5SDimitry Andric __simd_reference operator^=(_Vp __value) && { 903*4ba319b5SDimitry Andric return std::move(*this) = __ptr_->__get(__index_) ^ __value; 904*4ba319b5SDimitry Andric } 905*4ba319b5SDimitry Andric}; 906*4ba319b5SDimitry Andric 907*4ba319b5SDimitry Andrictemplate <class _To, class _From> 908*4ba319b5SDimitry Andricconstexpr decltype(_To{std::declval<_From>()}, true) 909*4ba319b5SDimitry Andric__is_non_narrowing_convertible_impl(_From) { 910*4ba319b5SDimitry Andric return true; 911*4ba319b5SDimitry Andric} 912*4ba319b5SDimitry Andric 913*4ba319b5SDimitry Andrictemplate <class _To> 914*4ba319b5SDimitry Andricconstexpr bool __is_non_narrowing_convertible_impl(...) { 915*4ba319b5SDimitry Andric return false; 916*4ba319b5SDimitry Andric} 917*4ba319b5SDimitry Andric 918*4ba319b5SDimitry Andrictemplate <class _From, class _To> 919*4ba319b5SDimitry Andricconstexpr typename std::enable_if<std::is_arithmetic<_To>::value && 920*4ba319b5SDimitry Andric std::is_arithmetic<_From>::value, 921*4ba319b5SDimitry Andric bool>::type 922*4ba319b5SDimitry Andric__is_non_narrowing_arithmetic_convertible() { 923*4ba319b5SDimitry Andric return __is_non_narrowing_convertible_impl<_To>(_From{}); 924*4ba319b5SDimitry Andric} 925*4ba319b5SDimitry Andric 926*4ba319b5SDimitry Andrictemplate <class _From, class _To> 927*4ba319b5SDimitry Andricconstexpr typename std::enable_if<!(std::is_arithmetic<_To>::value && 928*4ba319b5SDimitry Andric std::is_arithmetic<_From>::value), 929*4ba319b5SDimitry Andric bool>::type 930*4ba319b5SDimitry Andric__is_non_narrowing_arithmetic_convertible() { 931*4ba319b5SDimitry Andric return false; 932*4ba319b5SDimitry Andric} 933*4ba319b5SDimitry Andric 934*4ba319b5SDimitry Andrictemplate <class _Tp> 935*4ba319b5SDimitry Andricconstexpr _Tp __variadic_sum() { 936*4ba319b5SDimitry Andric return _Tp{}; 937*4ba319b5SDimitry Andric} 938*4ba319b5SDimitry Andric 939*4ba319b5SDimitry Andrictemplate <class _Tp, class _Up, class... _Args> 940*4ba319b5SDimitry Andricconstexpr _Tp __variadic_sum(_Up __first, _Args... __rest) { 941*4ba319b5SDimitry Andric return static_cast<_Tp>(__first) + __variadic_sum<_Tp>(__rest...); 942*4ba319b5SDimitry Andric} 943*4ba319b5SDimitry Andric 944*4ba319b5SDimitry Andrictemplate <class _Tp> 945*4ba319b5SDimitry Andricstruct __nodeduce { 946*4ba319b5SDimitry Andric using type = _Tp; 947*4ba319b5SDimitry Andric}; 948*4ba319b5SDimitry Andric 949*4ba319b5SDimitry Andrictemplate <class _Tp> 950*4ba319b5SDimitry Andricconstexpr bool __vectorizable() { 951*4ba319b5SDimitry Andric return std::is_arithmetic<_Tp>::value && !std::is_const<_Tp>::value && 952*4ba319b5SDimitry Andric !std::is_volatile<_Tp>::value && !std::is_same<_Tp, bool>::value; 953*4ba319b5SDimitry Andric} 954*4ba319b5SDimitry Andric 955*4ba319b5SDimitry Andric_LIBCPP_END_NAMESPACE_EXPERIMENTAL_SIMD 956*4ba319b5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_SIMD_ABI 957*4ba319b5SDimitry Andric 958*4ba319b5SDimitry Andricusing scalar = __simd_abi<_StorageKind::_Scalar, 1>; 959*4ba319b5SDimitry Andric 960*4ba319b5SDimitry Andrictemplate <int _Np> 961*4ba319b5SDimitry Andricusing fixed_size = __simd_abi<_StorageKind::_Array, _Np>; 962*4ba319b5SDimitry Andric 963*4ba319b5SDimitry Andrictemplate <class _Tp> 964*4ba319b5SDimitry Andric_LIBCPP_INLINE_VAR constexpr size_t max_fixed_size = 32; 965*4ba319b5SDimitry Andric 966*4ba319b5SDimitry Andrictemplate <class _Tp> 967*4ba319b5SDimitry Andricusing compatible = fixed_size<16 / sizeof(_Tp)>; 968*4ba319b5SDimitry Andric 969*4ba319b5SDimitry Andric#ifndef _LIBCPP_HAS_NO_VECTOR_EXTENSION 970*4ba319b5SDimitry Andrictemplate <class _Tp> 971*4ba319b5SDimitry Andricusing native = __simd_abi<_StorageKind::_VecExt, 972*4ba319b5SDimitry Andric _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES / sizeof(_Tp)>; 973*4ba319b5SDimitry Andric#else 974*4ba319b5SDimitry Andrictemplate <class _Tp> 975*4ba319b5SDimitry Andricusing native = 976*4ba319b5SDimitry Andric fixed_size<_Tp, _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES / sizeof(_Tp)>; 977*4ba319b5SDimitry Andric#endif // _LIBCPP_HAS_NO_VECTOR_EXTENSION 978*4ba319b5SDimitry Andric 979*4ba319b5SDimitry Andric_LIBCPP_END_NAMESPACE_EXPERIMENTAL_SIMD_ABI 980*4ba319b5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_SIMD 981*4ba319b5SDimitry Andric 982*4ba319b5SDimitry Andrictemplate <class _Tp, class _Abi = simd_abi::compatible<_Tp>> 983*4ba319b5SDimitry Andricclass simd; 984*4ba319b5SDimitry Andrictemplate <class _Tp, class _Abi = simd_abi::compatible<_Tp>> 985*4ba319b5SDimitry Andricclass simd_mask; 986*4ba319b5SDimitry Andric 987*4ba319b5SDimitry Andricstruct element_aligned_tag {}; 988*4ba319b5SDimitry Andricstruct vector_aligned_tag {}; 989*4ba319b5SDimitry Andrictemplate <size_t> 990*4ba319b5SDimitry Andricstruct overaligned_tag {}; 991*4ba319b5SDimitry Andric_LIBCPP_INLINE_VAR constexpr element_aligned_tag element_aligned{}; 992*4ba319b5SDimitry Andric_LIBCPP_INLINE_VAR constexpr vector_aligned_tag vector_aligned{}; 993*4ba319b5SDimitry Andrictemplate <size_t _Np> 994*4ba319b5SDimitry Andric_LIBCPP_INLINE_VAR constexpr overaligned_tag<_Np> overaligned{}; 995*4ba319b5SDimitry Andric 996*4ba319b5SDimitry Andric// traits [simd.traits] 997*4ba319b5SDimitry Andrictemplate <class _Tp> 998*4ba319b5SDimitry Andricstruct is_abi_tag : std::integral_constant<bool, false> {}; 999*4ba319b5SDimitry Andric 1000*4ba319b5SDimitry Andrictemplate <_StorageKind __kind, int _Np> 1001*4ba319b5SDimitry Andricstruct is_abi_tag<__simd_abi<__kind, _Np>> 1002*4ba319b5SDimitry Andric : std::integral_constant<bool, true> {}; 1003*4ba319b5SDimitry Andric 1004*4ba319b5SDimitry Andrictemplate <class _Tp> 1005*4ba319b5SDimitry Andricstruct is_simd : std::integral_constant<bool, false> {}; 1006*4ba319b5SDimitry Andric 1007*4ba319b5SDimitry Andrictemplate <class _Tp, class _Abi> 1008*4ba319b5SDimitry Andricstruct is_simd<simd<_Tp, _Abi>> : std::integral_constant<bool, true> {}; 1009*4ba319b5SDimitry Andric 1010*4ba319b5SDimitry Andrictemplate <class _Tp> 1011*4ba319b5SDimitry Andricstruct is_simd_mask : std::integral_constant<bool, false> {}; 1012*4ba319b5SDimitry Andric 1013*4ba319b5SDimitry Andrictemplate <class _Tp, class _Abi> 1014*4ba319b5SDimitry Andricstruct is_simd_mask<simd_mask<_Tp, _Abi>> : std::integral_constant<bool, true> { 1015*4ba319b5SDimitry Andric}; 1016*4ba319b5SDimitry Andric 1017*4ba319b5SDimitry Andrictemplate <class _Tp> 1018*4ba319b5SDimitry Andricstruct is_simd_flag_type : std::integral_constant<bool, false> {}; 1019*4ba319b5SDimitry Andric 1020*4ba319b5SDimitry Andrictemplate <> 1021*4ba319b5SDimitry Andricstruct is_simd_flag_type<element_aligned_tag> 1022*4ba319b5SDimitry Andric : std::integral_constant<bool, true> {}; 1023*4ba319b5SDimitry Andric 1024*4ba319b5SDimitry Andrictemplate <> 1025*4ba319b5SDimitry Andricstruct is_simd_flag_type<vector_aligned_tag> 1026*4ba319b5SDimitry Andric : std::integral_constant<bool, true> {}; 1027*4ba319b5SDimitry Andric 1028*4ba319b5SDimitry Andrictemplate <size_t _Align> 1029*4ba319b5SDimitry Andricstruct is_simd_flag_type<overaligned_tag<_Align>> 1030*4ba319b5SDimitry Andric : std::integral_constant<bool, true> {}; 1031*4ba319b5SDimitry Andric 1032*4ba319b5SDimitry Andrictemplate <class _Tp> 1033*4ba319b5SDimitry Andric_LIBCPP_INLINE_VAR constexpr bool is_abi_tag_v = is_abi_tag<_Tp>::value; 1034*4ba319b5SDimitry Andrictemplate <class _Tp> 1035*4ba319b5SDimitry Andric_LIBCPP_INLINE_VAR constexpr bool is_simd_v = is_simd<_Tp>::value; 1036*4ba319b5SDimitry Andrictemplate <class _Tp> 1037*4ba319b5SDimitry Andric_LIBCPP_INLINE_VAR constexpr bool is_simd_mask_v = is_simd_mask<_Tp>::value; 1038*4ba319b5SDimitry Andrictemplate <class _Tp> 1039*4ba319b5SDimitry Andric_LIBCPP_INLINE_VAR constexpr bool is_simd_flag_type_v = 1040*4ba319b5SDimitry Andric is_simd_flag_type<_Tp>::value; 1041*4ba319b5SDimitry Andrictemplate <class _Tp, size_t _Np> 1042*4ba319b5SDimitry Andricstruct abi_for_size { 1043*4ba319b5SDimitry Andric using type = simd_abi::fixed_size<_Np>; 1044*4ba319b5SDimitry Andric}; 1045*4ba319b5SDimitry Andrictemplate <class _Tp, size_t _Np> 1046*4ba319b5SDimitry Andricusing abi_for_size_t = typename abi_for_size<_Tp, _Np>::type; 1047*4ba319b5SDimitry Andric 1048*4ba319b5SDimitry Andrictemplate <class _Tp, class _Abi = simd_abi::compatible<_Tp>> 1049*4ba319b5SDimitry Andricstruct simd_size; 1050*4ba319b5SDimitry Andric 1051*4ba319b5SDimitry Andrictemplate <class _Tp, _StorageKind __kind, int _Np> 1052*4ba319b5SDimitry Andricstruct simd_size<_Tp, __simd_abi<__kind, _Np>> 1053*4ba319b5SDimitry Andric : std::integral_constant<size_t, _Np> { 1054*4ba319b5SDimitry Andric static_assert( 1055*4ba319b5SDimitry Andric std::is_arithmetic<_Tp>::value && 1056*4ba319b5SDimitry Andric !std::is_same<typename std::remove_const<_Tp>::type, bool>::value, 1057*4ba319b5SDimitry Andric "Element type should be vectorizable"); 1058*4ba319b5SDimitry Andric}; 1059*4ba319b5SDimitry Andric 1060*4ba319b5SDimitry Andric// TODO: implement it. 1061*4ba319b5SDimitry Andrictemplate <class _Tp, class _Up = typename _Tp::value_type> 1062*4ba319b5SDimitry Andricstruct memory_alignment; 1063*4ba319b5SDimitry Andric 1064*4ba319b5SDimitry Andrictemplate <class _Tp, class _Abi = simd_abi::compatible<_Tp>> 1065*4ba319b5SDimitry Andric_LIBCPP_INLINE_VAR constexpr size_t simd_size_v = simd_size<_Tp, _Abi>::value; 1066*4ba319b5SDimitry Andric 1067*4ba319b5SDimitry Andrictemplate <class _Tp, class _Up = typename _Tp::value_type> 1068*4ba319b5SDimitry Andric_LIBCPP_INLINE_VAR constexpr size_t memory_alignment_v = 1069*4ba319b5SDimitry Andric memory_alignment<_Tp, _Up>::value; 1070*4ba319b5SDimitry Andric 1071*4ba319b5SDimitry Andric// class template simd [simd.class] 1072*4ba319b5SDimitry Andrictemplate <class _Tp> 1073*4ba319b5SDimitry Andricusing native_simd = simd<_Tp, simd_abi::native<_Tp>>; 1074*4ba319b5SDimitry Andrictemplate <class _Tp, int _Np> 1075*4ba319b5SDimitry Andricusing fixed_size_simd = simd<_Tp, simd_abi::fixed_size<_Np>>; 1076*4ba319b5SDimitry Andric 1077*4ba319b5SDimitry Andric// class template simd_mask [simd.mask.class] 1078*4ba319b5SDimitry Andrictemplate <class _Tp> 1079*4ba319b5SDimitry Andricusing native_simd_mask = simd_mask<_Tp, simd_abi::native<_Tp>>; 1080*4ba319b5SDimitry Andric 1081*4ba319b5SDimitry Andrictemplate <class _Tp, int _Np> 1082*4ba319b5SDimitry Andricusing fixed_size_simd_mask = simd_mask<_Tp, simd_abi::fixed_size<_Np>>; 1083*4ba319b5SDimitry Andric 1084*4ba319b5SDimitry Andric// casts [simd.casts] 1085*4ba319b5SDimitry Andrictemplate <class _Tp> 1086*4ba319b5SDimitry Andricstruct __static_simd_cast_traits { 1087*4ba319b5SDimitry Andric template <class _Up, class _Abi> 1088*4ba319b5SDimitry Andric static simd<_Tp, _Abi> __apply(const simd<_Up, _Abi>& __v); 1089*4ba319b5SDimitry Andric}; 1090*4ba319b5SDimitry Andric 1091*4ba319b5SDimitry Andrictemplate <class _Tp, class _NewAbi> 1092*4ba319b5SDimitry Andricstruct __static_simd_cast_traits<simd<_Tp, _NewAbi>> { 1093*4ba319b5SDimitry Andric template <class _Up, class _Abi> 1094*4ba319b5SDimitry Andric static typename std::enable_if<simd<_Up, _Abi>::size() == 1095*4ba319b5SDimitry Andric simd<_Tp, _NewAbi>::size(), 1096*4ba319b5SDimitry Andric simd<_Tp, _NewAbi>>::type 1097*4ba319b5SDimitry Andric __apply(const simd<_Up, _Abi>& __v); 1098*4ba319b5SDimitry Andric}; 1099*4ba319b5SDimitry Andric 1100*4ba319b5SDimitry Andrictemplate <class _Tp> 1101*4ba319b5SDimitry Andricstruct __simd_cast_traits { 1102*4ba319b5SDimitry Andric template <class _Up, class _Abi> 1103*4ba319b5SDimitry Andric static typename std::enable_if< 1104*4ba319b5SDimitry Andric __is_non_narrowing_arithmetic_convertible<_Up, _Tp>(), 1105*4ba319b5SDimitry Andric simd<_Tp, _Abi>>::type 1106*4ba319b5SDimitry Andric __apply(const simd<_Up, _Abi>& __v); 1107*4ba319b5SDimitry Andric}; 1108*4ba319b5SDimitry Andric 1109*4ba319b5SDimitry Andrictemplate <class _Tp, class _NewAbi> 1110*4ba319b5SDimitry Andricstruct __simd_cast_traits<simd<_Tp, _NewAbi>> { 1111*4ba319b5SDimitry Andric template <class _Up, class _Abi> 1112*4ba319b5SDimitry Andric static typename std::enable_if< 1113*4ba319b5SDimitry Andric __is_non_narrowing_arithmetic_convertible<_Up, _Tp>() && 1114*4ba319b5SDimitry Andric simd<_Up, _Abi>::size() == simd<_Tp, _NewAbi>::size(), 1115*4ba319b5SDimitry Andric simd<_Tp, _NewAbi>>::type 1116*4ba319b5SDimitry Andric __apply(const simd<_Up, _Abi>& __v); 1117*4ba319b5SDimitry Andric}; 1118*4ba319b5SDimitry Andric 1119*4ba319b5SDimitry Andrictemplate <class _Tp, class _Up, class _Abi> 1120*4ba319b5SDimitry Andricauto simd_cast(const simd<_Up, _Abi>& __v) 1121*4ba319b5SDimitry Andric -> decltype(__simd_cast_traits<_Tp>::__apply(__v)) { 1122*4ba319b5SDimitry Andric return __simd_cast_traits<_Tp>::__apply(__v); 1123*4ba319b5SDimitry Andric} 1124*4ba319b5SDimitry Andric 1125*4ba319b5SDimitry Andrictemplate <class _Tp, class _Up, class _Abi> 1126*4ba319b5SDimitry Andricauto static_simd_cast(const simd<_Up, _Abi>& __v) 1127*4ba319b5SDimitry Andric -> decltype(__static_simd_cast_traits<_Tp>::__apply(__v)) { 1128*4ba319b5SDimitry Andric return __static_simd_cast_traits<_Tp>::__apply(__v); 1129*4ba319b5SDimitry Andric} 1130*4ba319b5SDimitry Andric 1131*4ba319b5SDimitry Andrictemplate <class _Tp, class _Abi> 1132*4ba319b5SDimitry Andricfixed_size_simd<_Tp, simd_size<_Tp, _Abi>::value> 1133*4ba319b5SDimitry Andricto_fixed_size(const simd<_Tp, _Abi>&) noexcept; 1134*4ba319b5SDimitry Andric 1135*4ba319b5SDimitry Andrictemplate <class _Tp, class _Abi> 1136*4ba319b5SDimitry Andricfixed_size_simd_mask<_Tp, simd_size<_Tp, _Abi>::value> 1137*4ba319b5SDimitry Andricto_fixed_size(const simd_mask<_Tp, _Abi>&) noexcept; 1138*4ba319b5SDimitry Andric 1139*4ba319b5SDimitry Andrictemplate <class _Tp, size_t _Np> 1140*4ba319b5SDimitry Andricnative_simd<_Tp> to_native(const fixed_size_simd<_Tp, _Np>&) noexcept; 1141*4ba319b5SDimitry Andric 1142*4ba319b5SDimitry Andrictemplate <class _Tp, size_t _Np> 1143*4ba319b5SDimitry Andricnative_simd_mask<_Tp> to_native(const fixed_size_simd_mask<_Tp, _Np>&) noexcept; 1144*4ba319b5SDimitry Andric 1145*4ba319b5SDimitry Andrictemplate <class _Tp, size_t _Np> 1146*4ba319b5SDimitry Andricsimd<_Tp> to_compatible(const fixed_size_simd<_Tp, _Np>&) noexcept; 1147*4ba319b5SDimitry Andric 1148*4ba319b5SDimitry Andrictemplate <class _Tp, size_t _Np> 1149*4ba319b5SDimitry Andricsimd_mask<_Tp> to_compatible(const fixed_size_simd_mask<_Tp, _Np>&) noexcept; 1150*4ba319b5SDimitry Andric 1151*4ba319b5SDimitry Andrictemplate <size_t... __sizes, class _Tp, class _Abi> 1152*4ba319b5SDimitry Andrictuple<simd<_Tp, abi_for_size_t<_Tp, __sizes>>...> split(const simd<_Tp, _Abi>&); 1153*4ba319b5SDimitry Andric 1154*4ba319b5SDimitry Andrictemplate <size_t... __sizes, class _Tp, class _Abi> 1155*4ba319b5SDimitry Andrictuple<simd_mask<_Tp, abi_for_size_t<_Tp, __sizes>>...> 1156*4ba319b5SDimitry Andricsplit(const simd_mask<_Tp, _Abi>&); 1157*4ba319b5SDimitry Andric 1158*4ba319b5SDimitry Andrictemplate <class _SimdType, class _Abi> 1159*4ba319b5SDimitry Andricarray<_SimdType, simd_size<typename _SimdType::value_type, _Abi>::value / 1160*4ba319b5SDimitry Andric _SimdType::size()> 1161*4ba319b5SDimitry Andricsplit(const simd<typename _SimdType::value_type, _Abi>&); 1162*4ba319b5SDimitry Andric 1163*4ba319b5SDimitry Andrictemplate <class _SimdType, class _Abi> 1164*4ba319b5SDimitry Andricarray<_SimdType, simd_size<typename _SimdType::value_type, _Abi>::value / 1165*4ba319b5SDimitry Andric _SimdType::size()> 1166*4ba319b5SDimitry Andricsplit(const simd_mask<typename _SimdType::value_type, _Abi>&); 1167*4ba319b5SDimitry Andric 1168*4ba319b5SDimitry Andrictemplate <class _Tp, class... _Abis> 1169*4ba319b5SDimitry Andricsimd<_Tp, abi_for_size_t<_Tp, __variadic_sum(simd_size<_Tp, _Abis>::value...)>> 1170*4ba319b5SDimitry Andricconcat(const simd<_Tp, _Abis>&...); 1171*4ba319b5SDimitry Andric 1172*4ba319b5SDimitry Andrictemplate <class _Tp, class... _Abis> 1173*4ba319b5SDimitry Andricsimd_mask<_Tp, 1174*4ba319b5SDimitry Andric abi_for_size_t<_Tp, __variadic_sum(simd_size<_Tp, _Abis>::value...)>> 1175*4ba319b5SDimitry Andricconcat(const simd_mask<_Tp, _Abis>&...); 1176*4ba319b5SDimitry Andric 1177*4ba319b5SDimitry Andric// reductions [simd.mask.reductions] 1178*4ba319b5SDimitry Andrictemplate <class _Tp, class _Abi> 1179*4ba319b5SDimitry Andricbool all_of(const simd_mask<_Tp, _Abi>&) noexcept; 1180*4ba319b5SDimitry Andrictemplate <class _Tp, class _Abi> 1181*4ba319b5SDimitry Andricbool any_of(const simd_mask<_Tp, _Abi>&) noexcept; 1182*4ba319b5SDimitry Andrictemplate <class _Tp, class _Abi> 1183*4ba319b5SDimitry Andricbool none_of(const simd_mask<_Tp, _Abi>&) noexcept; 1184*4ba319b5SDimitry Andrictemplate <class _Tp, class _Abi> 1185*4ba319b5SDimitry Andricbool some_of(const simd_mask<_Tp, _Abi>&) noexcept; 1186*4ba319b5SDimitry Andrictemplate <class _Tp, class _Abi> 1187*4ba319b5SDimitry Andricint popcount(const simd_mask<_Tp, _Abi>&) noexcept; 1188*4ba319b5SDimitry Andrictemplate <class _Tp, class _Abi> 1189*4ba319b5SDimitry Andricint find_first_set(const simd_mask<_Tp, _Abi>&); 1190*4ba319b5SDimitry Andrictemplate <class _Tp, class _Abi> 1191*4ba319b5SDimitry Andricint find_last_set(const simd_mask<_Tp, _Abi>&); 1192*4ba319b5SDimitry Andricbool all_of(bool) noexcept; 1193*4ba319b5SDimitry Andricbool any_of(bool) noexcept; 1194*4ba319b5SDimitry Andricbool none_of(bool) noexcept; 1195*4ba319b5SDimitry Andricbool some_of(bool) noexcept; 1196*4ba319b5SDimitry Andricint popcount(bool) noexcept; 1197*4ba319b5SDimitry Andricint find_first_set(bool) noexcept; 1198*4ba319b5SDimitry Andricint find_last_set(bool) noexcept; 1199*4ba319b5SDimitry Andric 1200*4ba319b5SDimitry Andric// masked assignment [simd.whereexpr] 1201*4ba319b5SDimitry Andrictemplate <class _MaskType, class _Tp> 1202*4ba319b5SDimitry Andricclass const_where_expression; 1203*4ba319b5SDimitry Andrictemplate <class _MaskType, class _Tp> 1204*4ba319b5SDimitry Andricclass where_expression; 1205*4ba319b5SDimitry Andric 1206*4ba319b5SDimitry Andric// masked assignment [simd.mask.where] 1207*4ba319b5SDimitry Andrictemplate <class _Tp, class _Abi> 1208*4ba319b5SDimitry Andricwhere_expression<simd_mask<_Tp, _Abi>, simd<_Tp, _Abi>> 1209*4ba319b5SDimitry Andricwhere(const typename simd<_Tp, _Abi>::mask_type&, simd<_Tp, _Abi>&) noexcept; 1210*4ba319b5SDimitry Andric 1211*4ba319b5SDimitry Andrictemplate <class _Tp, class _Abi> 1212*4ba319b5SDimitry Andricconst_where_expression<simd_mask<_Tp, _Abi>, const simd<_Tp, _Abi>> 1213*4ba319b5SDimitry Andricwhere(const typename simd<_Tp, _Abi>::mask_type&, 1214*4ba319b5SDimitry Andric const simd<_Tp, _Abi>&) noexcept; 1215*4ba319b5SDimitry Andric 1216*4ba319b5SDimitry Andrictemplate <class _Tp, class _Abi> 1217*4ba319b5SDimitry Andricwhere_expression<simd_mask<_Tp, _Abi>, simd_mask<_Tp, _Abi>> 1218*4ba319b5SDimitry Andricwhere(const typename __nodeduce<simd_mask<_Tp, _Abi>>::type&, 1219*4ba319b5SDimitry Andric simd_mask<_Tp, _Abi>&) noexcept; 1220*4ba319b5SDimitry Andric 1221*4ba319b5SDimitry Andrictemplate <class _Tp, class _Abi> 1222*4ba319b5SDimitry Andricconst_where_expression<simd_mask<_Tp, _Abi>, const simd_mask<_Tp, _Abi>> 1223*4ba319b5SDimitry Andricwhere(const typename __nodeduce<simd_mask<_Tp, _Abi>>::type&, 1224*4ba319b5SDimitry Andric const simd_mask<_Tp, _Abi>&) noexcept; 1225*4ba319b5SDimitry Andric 1226*4ba319b5SDimitry Andrictemplate <class _Tp> 1227*4ba319b5SDimitry Andricwhere_expression<bool, _Tp> where(bool, _Tp&) noexcept; 1228*4ba319b5SDimitry Andric 1229*4ba319b5SDimitry Andrictemplate <class _Tp> 1230*4ba319b5SDimitry Andricconst_where_expression<bool, const _Tp> where(bool, const _Tp&) noexcept; 1231*4ba319b5SDimitry Andric 1232*4ba319b5SDimitry Andric// reductions [simd.reductions] 1233*4ba319b5SDimitry Andrictemplate <class _Tp, class _Abi, class _BinaryOp = std::plus<_Tp>> 1234*4ba319b5SDimitry Andric_Tp reduce(const simd<_Tp, _Abi>&, _BinaryOp = _BinaryOp()); 1235*4ba319b5SDimitry Andric 1236*4ba319b5SDimitry Andrictemplate <class _MaskType, class _SimdType, class _BinaryOp> 1237*4ba319b5SDimitry Andrictypename _SimdType::value_type 1238*4ba319b5SDimitry Andricreduce(const const_where_expression<_MaskType, _SimdType>&, 1239*4ba319b5SDimitry Andric typename _SimdType::value_type neutral_element, _BinaryOp binary_op); 1240*4ba319b5SDimitry Andric 1241*4ba319b5SDimitry Andrictemplate <class _MaskType, class _SimdType> 1242*4ba319b5SDimitry Andrictypename _SimdType::value_type 1243*4ba319b5SDimitry Andricreduce(const const_where_expression<_MaskType, _SimdType>&, 1244*4ba319b5SDimitry Andric plus<typename _SimdType::value_type> binary_op = {}); 1245*4ba319b5SDimitry Andric 1246*4ba319b5SDimitry Andrictemplate <class _MaskType, class _SimdType> 1247*4ba319b5SDimitry Andrictypename _SimdType::value_type 1248*4ba319b5SDimitry Andricreduce(const const_where_expression<_MaskType, _SimdType>&, 1249*4ba319b5SDimitry Andric multiplies<typename _SimdType::value_type> binary_op); 1250*4ba319b5SDimitry Andric 1251*4ba319b5SDimitry Andrictemplate <class _MaskType, class _SimdType> 1252*4ba319b5SDimitry Andrictypename _SimdType::value_type 1253*4ba319b5SDimitry Andricreduce(const const_where_expression<_MaskType, _SimdType>&, 1254*4ba319b5SDimitry Andric bit_and<typename _SimdType::value_type> binary_op); 1255*4ba319b5SDimitry Andric 1256*4ba319b5SDimitry Andrictemplate <class _MaskType, class _SimdType> 1257*4ba319b5SDimitry Andrictypename _SimdType::value_type 1258*4ba319b5SDimitry Andricreduce(const const_where_expression<_MaskType, _SimdType>&, 1259*4ba319b5SDimitry Andric bit_or<typename _SimdType::value_type> binary_op); 1260*4ba319b5SDimitry Andric 1261*4ba319b5SDimitry Andrictemplate <class _MaskType, class _SimdType> 1262*4ba319b5SDimitry Andrictypename _SimdType::value_type 1263*4ba319b5SDimitry Andricreduce(const const_where_expression<_MaskType, _SimdType>&, 1264*4ba319b5SDimitry Andric bit_xor<typename _SimdType::value_type> binary_op); 1265*4ba319b5SDimitry Andric 1266*4ba319b5SDimitry Andrictemplate <class _Tp, class _Abi> 1267*4ba319b5SDimitry Andric_Tp hmin(const simd<_Tp, _Abi>&); 1268*4ba319b5SDimitry Andrictemplate <class _MaskType, class _SimdType> 1269*4ba319b5SDimitry Andrictypename _SimdType::value_type 1270*4ba319b5SDimitry Andrichmin(const const_where_expression<_MaskType, _SimdType>&); 1271*4ba319b5SDimitry Andrictemplate <class _Tp, class _Abi> 1272*4ba319b5SDimitry Andric_Tp hmax(const simd<_Tp, _Abi>&); 1273*4ba319b5SDimitry Andrictemplate <class _MaskType, class _SimdType> 1274*4ba319b5SDimitry Andrictypename _SimdType::value_type 1275*4ba319b5SDimitry Andrichmax(const const_where_expression<_MaskType, _SimdType>&); 1276*4ba319b5SDimitry Andric 1277*4ba319b5SDimitry Andric// algorithms [simd.alg] 1278*4ba319b5SDimitry Andrictemplate <class _Tp, class _Abi> 1279*4ba319b5SDimitry Andricsimd<_Tp, _Abi> min(const simd<_Tp, _Abi>&, const simd<_Tp, _Abi>&) noexcept; 1280*4ba319b5SDimitry Andric 1281*4ba319b5SDimitry Andrictemplate <class _Tp, class _Abi> 1282*4ba319b5SDimitry Andricsimd<_Tp, _Abi> max(const simd<_Tp, _Abi>&, const simd<_Tp, _Abi>&) noexcept; 1283*4ba319b5SDimitry Andric 1284*4ba319b5SDimitry Andrictemplate <class _Tp, class _Abi> 1285*4ba319b5SDimitry Andricstd::pair<simd<_Tp, _Abi>, simd<_Tp, _Abi>> 1286*4ba319b5SDimitry Andricminmax(const simd<_Tp, _Abi>&, const simd<_Tp, _Abi>&) noexcept; 1287*4ba319b5SDimitry Andric 1288*4ba319b5SDimitry Andrictemplate <class _Tp, class _Abi> 1289*4ba319b5SDimitry Andricsimd<_Tp, _Abi> clamp(const simd<_Tp, _Abi>&, const simd<_Tp, _Abi>&, 1290*4ba319b5SDimitry Andric const simd<_Tp, _Abi>&); 1291*4ba319b5SDimitry Andric 1292*4ba319b5SDimitry Andric// [simd.whereexpr] 1293*4ba319b5SDimitry Andric// TODO implement where expressions. 1294*4ba319b5SDimitry Andrictemplate <class _MaskType, class _Tp> 1295*4ba319b5SDimitry Andricclass const_where_expression { 1296*4ba319b5SDimitry Andricpublic: 1297*4ba319b5SDimitry Andric const_where_expression(const const_where_expression&) = delete; 1298*4ba319b5SDimitry Andric const_where_expression& operator=(const const_where_expression&) = delete; 1299*4ba319b5SDimitry Andric typename remove_const<_Tp>::type operator-() const&&; 1300*4ba319b5SDimitry Andric template <class _Up, class _Flags> 1301*4ba319b5SDimitry Andric void copy_to(_Up*, _Flags) const&&; 1302*4ba319b5SDimitry Andric}; 1303*4ba319b5SDimitry Andric 1304*4ba319b5SDimitry Andrictemplate <class _MaskType, class _Tp> 1305*4ba319b5SDimitry Andricclass where_expression : public const_where_expression<_MaskType, _Tp> { 1306*4ba319b5SDimitry Andricpublic: 1307*4ba319b5SDimitry Andric where_expression(const where_expression&) = delete; 1308*4ba319b5SDimitry Andric where_expression& operator=(const where_expression&) = delete; 1309*4ba319b5SDimitry Andric template <class _Up> 1310*4ba319b5SDimitry Andric void operator=(_Up&&); 1311*4ba319b5SDimitry Andric template <class _Up> 1312*4ba319b5SDimitry Andric void operator+=(_Up&&); 1313*4ba319b5SDimitry Andric template <class _Up> 1314*4ba319b5SDimitry Andric void operator-=(_Up&&); 1315*4ba319b5SDimitry Andric template <class _Up> 1316*4ba319b5SDimitry Andric void operator*=(_Up&&); 1317*4ba319b5SDimitry Andric template <class _Up> 1318*4ba319b5SDimitry Andric void operator/=(_Up&&); 1319*4ba319b5SDimitry Andric template <class _Up> 1320*4ba319b5SDimitry Andric void operator%=(_Up&&); 1321*4ba319b5SDimitry Andric template <class _Up> 1322*4ba319b5SDimitry Andric void operator&=(_Up&&); 1323*4ba319b5SDimitry Andric template <class _Up> 1324*4ba319b5SDimitry Andric void operator|=(_Up&&); 1325*4ba319b5SDimitry Andric template <class _Up> 1326*4ba319b5SDimitry Andric void operator^=(_Up&&); 1327*4ba319b5SDimitry Andric template <class _Up> 1328*4ba319b5SDimitry Andric void operator<<=(_Up&&); 1329*4ba319b5SDimitry Andric template <class _Up> 1330*4ba319b5SDimitry Andric void operator>>=(_Up&&); 1331*4ba319b5SDimitry Andric void operator++(); 1332*4ba319b5SDimitry Andric void operator++(int); 1333*4ba319b5SDimitry Andric void operator--(); 1334*4ba319b5SDimitry Andric void operator--(int); 1335*4ba319b5SDimitry Andric template <class _Up, class _Flags> 1336*4ba319b5SDimitry Andric void copy_from(const _Up*, _Flags); 1337*4ba319b5SDimitry Andric}; 1338*4ba319b5SDimitry Andric 1339*4ba319b5SDimitry Andric// [simd.class] 1340*4ba319b5SDimitry Andric// TODO: implement simd 1341*4ba319b5SDimitry Andrictemplate <class _Tp, class _Abi> 1342*4ba319b5SDimitry Andricclass simd { 1343*4ba319b5SDimitry Andricpublic: 1344*4ba319b5SDimitry Andric using value_type = _Tp; 1345*4ba319b5SDimitry Andric using reference = __simd_reference<_Tp, _Tp, _Abi>; 1346*4ba319b5SDimitry Andric using mask_type = simd_mask<_Tp, _Abi>; 1347*4ba319b5SDimitry Andric using abi_type = _Abi; 1348*4ba319b5SDimitry Andric 1349*4ba319b5SDimitry Andric simd() = default; 1350*4ba319b5SDimitry Andric simd(const simd&) = default; 1351*4ba319b5SDimitry Andric simd& operator=(const simd&) = default; 1352*4ba319b5SDimitry Andric 1353*4ba319b5SDimitry Andric static constexpr size_t size() noexcept { 1354*4ba319b5SDimitry Andric return simd_size<_Tp, _Abi>::value; 1355*4ba319b5SDimitry Andric } 1356*4ba319b5SDimitry Andric 1357*4ba319b5SDimitry Andricprivate: 1358*4ba319b5SDimitry Andric __simd_storage<_Tp, _Abi> __s_; 1359*4ba319b5SDimitry Andric 1360*4ba319b5SDimitry Andric template <class _Up> 1361*4ba319b5SDimitry Andric static constexpr bool __can_broadcast() { 1362*4ba319b5SDimitry Andric return (std::is_arithmetic<_Up>::value && 1363*4ba319b5SDimitry Andric __is_non_narrowing_arithmetic_convertible<_Up, _Tp>()) || 1364*4ba319b5SDimitry Andric (!std::is_arithmetic<_Up>::value && 1365*4ba319b5SDimitry Andric std::is_convertible<_Up, _Tp>::value) || 1366*4ba319b5SDimitry Andric std::is_same<typename std::remove_const<_Up>::type, int>::value || 1367*4ba319b5SDimitry Andric (std::is_same<typename std::remove_const<_Up>::type, 1368*4ba319b5SDimitry Andric unsigned int>::value && 1369*4ba319b5SDimitry Andric std::is_unsigned<_Tp>::value); 1370*4ba319b5SDimitry Andric } 1371*4ba319b5SDimitry Andric 1372*4ba319b5SDimitry Andric template <class _Generator, size_t... __indicies> 1373*4ba319b5SDimitry Andric static constexpr decltype( 1374*4ba319b5SDimitry Andric std::forward_as_tuple(std::declval<_Generator>()( 1375*4ba319b5SDimitry Andric std::integral_constant<size_t, __indicies>())...), 1376*4ba319b5SDimitry Andric bool()) 1377*4ba319b5SDimitry Andric __can_generate(std::index_sequence<__indicies...>) { 1378*4ba319b5SDimitry Andric return !__variadic_sum<bool>( 1379*4ba319b5SDimitry Andric !__can_broadcast<decltype(std::declval<_Generator>()( 1380*4ba319b5SDimitry Andric std::integral_constant<size_t, __indicies>()))>()...); 1381*4ba319b5SDimitry Andric } 1382*4ba319b5SDimitry Andric 1383*4ba319b5SDimitry Andric template <class _Generator> 1384*4ba319b5SDimitry Andric static bool __can_generate(...) { 1385*4ba319b5SDimitry Andric return false; 1386*4ba319b5SDimitry Andric } 1387*4ba319b5SDimitry Andric 1388*4ba319b5SDimitry Andric template <class _Generator, size_t... __indicies> 1389*4ba319b5SDimitry Andric void __generator_init(_Generator&& __g, std::index_sequence<__indicies...>) { 1390*4ba319b5SDimitry Andric int __not_used[]{((*this)[__indicies] = 1391*4ba319b5SDimitry Andric __g(std::integral_constant<size_t, __indicies>()), 1392*4ba319b5SDimitry Andric 0)...}; 1393*4ba319b5SDimitry Andric (void)__not_used; 1394*4ba319b5SDimitry Andric } 1395*4ba319b5SDimitry Andric 1396*4ba319b5SDimitry Andricpublic: 1397*4ba319b5SDimitry Andric // implicit type conversion constructor 1398*4ba319b5SDimitry Andric template <class _Up, 1399*4ba319b5SDimitry Andric class = typename std::enable_if< 1400*4ba319b5SDimitry Andric std::is_same<_Abi, simd_abi::fixed_size<size()>>::value && 1401*4ba319b5SDimitry Andric __is_non_narrowing_arithmetic_convertible<_Up, _Tp>()>::type> 1402*4ba319b5SDimitry Andric simd(const simd<_Up, simd_abi::fixed_size<size()>>& __v) { 1403*4ba319b5SDimitry Andric for (size_t __i = 0; __i < size(); __i++) { 1404*4ba319b5SDimitry Andric (*this)[__i] = static_cast<_Tp>(__v[__i]); 1405*4ba319b5SDimitry Andric } 1406*4ba319b5SDimitry Andric } 1407*4ba319b5SDimitry Andric 1408*4ba319b5SDimitry Andric // implicit broadcast constructor 1409*4ba319b5SDimitry Andric template <class _Up, 1410*4ba319b5SDimitry Andric class = typename std::enable_if<__can_broadcast<_Up>()>::type> 1411*4ba319b5SDimitry Andric simd(_Up&& __rv) { 1412*4ba319b5SDimitry Andric auto __v = static_cast<_Tp>(__rv); 1413*4ba319b5SDimitry Andric for (size_t __i = 0; __i < size(); __i++) { 1414*4ba319b5SDimitry Andric (*this)[__i] = __v; 1415*4ba319b5SDimitry Andric } 1416*4ba319b5SDimitry Andric } 1417*4ba319b5SDimitry Andric 1418*4ba319b5SDimitry Andric // generator constructor 1419*4ba319b5SDimitry Andric template <class _Generator, 1420*4ba319b5SDimitry Andric int = typename std::enable_if< 1421*4ba319b5SDimitry Andric __can_generate<_Generator>(std::make_index_sequence<size()>()), 1422*4ba319b5SDimitry Andric int>::type()> 1423*4ba319b5SDimitry Andric explicit simd(_Generator&& __g) { 1424*4ba319b5SDimitry Andric __generator_init(std::forward<_Generator>(__g), 1425*4ba319b5SDimitry Andric std::make_index_sequence<size()>()); 1426*4ba319b5SDimitry Andric } 1427*4ba319b5SDimitry Andric 1428*4ba319b5SDimitry Andric // load constructor 1429*4ba319b5SDimitry Andric template < 1430*4ba319b5SDimitry Andric class _Up, class _Flags, 1431*4ba319b5SDimitry Andric class = typename std::enable_if<__vectorizable<_Up>()>::type, 1432*4ba319b5SDimitry Andric class = typename std::enable_if<is_simd_flag_type<_Flags>::value>::type> 1433*4ba319b5SDimitry Andric simd(const _Up* __buffer, _Flags) { 1434*4ba319b5SDimitry Andric // TODO: optimize for overaligned flags 1435*4ba319b5SDimitry Andric for (size_t __i = 0; __i < size(); __i++) { 1436*4ba319b5SDimitry Andric (*this)[__i] = static_cast<_Tp>(__buffer[__i]); 1437*4ba319b5SDimitry Andric } 1438*4ba319b5SDimitry Andric } 1439*4ba319b5SDimitry Andric 1440*4ba319b5SDimitry Andric // loads [simd.load] 1441*4ba319b5SDimitry Andric template <class _Up, class _Flags> 1442*4ba319b5SDimitry Andric typename std::enable_if<__vectorizable<_Up>() && 1443*4ba319b5SDimitry Andric is_simd_flag_type<_Flags>::value>::type 1444*4ba319b5SDimitry Andric copy_from(const _Up* __buffer, _Flags) { 1445*4ba319b5SDimitry Andric *this = simd(__buffer, _Flags()); 1446*4ba319b5SDimitry Andric } 1447*4ba319b5SDimitry Andric 1448*4ba319b5SDimitry Andric // stores [simd.store] 1449*4ba319b5SDimitry Andric template <class _Up, class _Flags> 1450*4ba319b5SDimitry Andric typename std::enable_if<__vectorizable<_Up>() && 1451*4ba319b5SDimitry Andric is_simd_flag_type<_Flags>::value>::type 1452*4ba319b5SDimitry Andric copy_to(_Up* __buffer, _Flags) const { 1453*4ba319b5SDimitry Andric // TODO: optimize for overaligned flags 1454*4ba319b5SDimitry Andric for (size_t __i = 0; __i < size(); __i++) { 1455*4ba319b5SDimitry Andric __buffer[__i] = static_cast<_Up>((*this)[__i]); 1456*4ba319b5SDimitry Andric } 1457*4ba319b5SDimitry Andric } 1458*4ba319b5SDimitry Andric 1459*4ba319b5SDimitry Andric // scalar access [simd.subscr] 1460*4ba319b5SDimitry Andric reference operator[](size_t __i) { return reference(&__s_, __i); } 1461*4ba319b5SDimitry Andric 1462*4ba319b5SDimitry Andric value_type operator[](size_t __i) const { return __s_.__get(__i); } 1463*4ba319b5SDimitry Andric 1464*4ba319b5SDimitry Andric // unary operators [simd.unary] 1465*4ba319b5SDimitry Andric simd& operator++(); 1466*4ba319b5SDimitry Andric simd operator++(int); 1467*4ba319b5SDimitry Andric simd& operator--(); 1468*4ba319b5SDimitry Andric simd operator--(int); 1469*4ba319b5SDimitry Andric mask_type operator!() const; 1470*4ba319b5SDimitry Andric simd operator~() const; 1471*4ba319b5SDimitry Andric simd operator+() const; 1472*4ba319b5SDimitry Andric simd operator-() const; 1473*4ba319b5SDimitry Andric 1474*4ba319b5SDimitry Andric // binary operators [simd.binary] 1475*4ba319b5SDimitry Andric friend simd operator+(const simd&, const simd&); 1476*4ba319b5SDimitry Andric friend simd operator-(const simd&, const simd&); 1477*4ba319b5SDimitry Andric friend simd operator*(const simd&, const simd&); 1478*4ba319b5SDimitry Andric friend simd operator/(const simd&, const simd&); 1479*4ba319b5SDimitry Andric friend simd operator%(const simd&, const simd&); 1480*4ba319b5SDimitry Andric friend simd operator&(const simd&, const simd&); 1481*4ba319b5SDimitry Andric friend simd operator|(const simd&, const simd&); 1482*4ba319b5SDimitry Andric friend simd operator^(const simd&, const simd&); 1483*4ba319b5SDimitry Andric friend simd operator<<(const simd&, const simd&); 1484*4ba319b5SDimitry Andric friend simd operator>>(const simd&, const simd&); 1485*4ba319b5SDimitry Andric friend simd operator<<(const simd&, int); 1486*4ba319b5SDimitry Andric friend simd operator>>(const simd&, int); 1487*4ba319b5SDimitry Andric 1488*4ba319b5SDimitry Andric // compound assignment [simd.cassign] 1489*4ba319b5SDimitry Andric friend simd& operator+=(simd&, const simd&); 1490*4ba319b5SDimitry Andric friend simd& operator-=(simd&, const simd&); 1491*4ba319b5SDimitry Andric friend simd& operator*=(simd&, const simd&); 1492*4ba319b5SDimitry Andric friend simd& operator/=(simd&, const simd&); 1493*4ba319b5SDimitry Andric friend simd& operator%=(simd&, const simd&); 1494*4ba319b5SDimitry Andric 1495*4ba319b5SDimitry Andric friend simd& operator&=(simd&, const simd&); 1496*4ba319b5SDimitry Andric friend simd& operator|=(simd&, const simd&); 1497*4ba319b5SDimitry Andric friend simd& operator^=(simd&, const simd&); 1498*4ba319b5SDimitry Andric friend simd& operator<<=(simd&, const simd&); 1499*4ba319b5SDimitry Andric friend simd& operator>>=(simd&, const simd&); 1500*4ba319b5SDimitry Andric friend simd& operator<<=(simd&, int); 1501*4ba319b5SDimitry Andric friend simd& operator>>=(simd&, int); 1502*4ba319b5SDimitry Andric 1503*4ba319b5SDimitry Andric // compares [simd.comparison] 1504*4ba319b5SDimitry Andric friend mask_type operator==(const simd&, const simd&); 1505*4ba319b5SDimitry Andric friend mask_type operator!=(const simd&, const simd&); 1506*4ba319b5SDimitry Andric friend mask_type operator>=(const simd&, const simd&); 1507*4ba319b5SDimitry Andric friend mask_type operator<=(const simd&, const simd&); 1508*4ba319b5SDimitry Andric friend mask_type operator>(const simd&, const simd&); 1509*4ba319b5SDimitry Andric friend mask_type operator<(const simd&, const simd&); 1510*4ba319b5SDimitry Andric}; 1511*4ba319b5SDimitry Andric 1512*4ba319b5SDimitry Andric// [simd.mask.class] 1513*4ba319b5SDimitry Andrictemplate <class _Tp, class _Abi> 1514*4ba319b5SDimitry Andric// TODO: implement simd_mask 1515*4ba319b5SDimitry Andricclass simd_mask { 1516*4ba319b5SDimitry Andricpublic: 1517*4ba319b5SDimitry Andric using value_type = bool; 1518*4ba319b5SDimitry Andric // TODO: this is strawman implementation. Turn it into a proxy type. 1519*4ba319b5SDimitry Andric using reference = bool&; 1520*4ba319b5SDimitry Andric using simd_type = simd<_Tp, _Abi>; 1521*4ba319b5SDimitry Andric using abi_type = _Abi; 1522*4ba319b5SDimitry Andric static constexpr size_t size() noexcept; 1523*4ba319b5SDimitry Andric simd_mask() = default; 1524*4ba319b5SDimitry Andric 1525*4ba319b5SDimitry Andric // broadcast constructor 1526*4ba319b5SDimitry Andric explicit simd_mask(value_type) noexcept; 1527*4ba319b5SDimitry Andric 1528*4ba319b5SDimitry Andric // implicit type conversion constructor 1529*4ba319b5SDimitry Andric template <class _Up> 1530*4ba319b5SDimitry Andric simd_mask(const simd_mask<_Up, simd_abi::fixed_size<size()>>&) noexcept; 1531*4ba319b5SDimitry Andric 1532*4ba319b5SDimitry Andric // load constructor 1533*4ba319b5SDimitry Andric template <class _Flags> 1534*4ba319b5SDimitry Andric simd_mask(const value_type*, _Flags); 1535*4ba319b5SDimitry Andric 1536*4ba319b5SDimitry Andric // loads [simd.mask.copy] 1537*4ba319b5SDimitry Andric template <class _Flags> 1538*4ba319b5SDimitry Andric void copy_from(const value_type*, _Flags); 1539*4ba319b5SDimitry Andric template <class _Flags> 1540*4ba319b5SDimitry Andric void copy_to(value_type*, _Flags) const; 1541*4ba319b5SDimitry Andric 1542*4ba319b5SDimitry Andric // scalar access [simd.mask.subscr] 1543*4ba319b5SDimitry Andric reference operator[](size_t); 1544*4ba319b5SDimitry Andric value_type operator[](size_t) const; 1545*4ba319b5SDimitry Andric 1546*4ba319b5SDimitry Andric // unary operators [simd.mask.unary] 1547*4ba319b5SDimitry Andric simd_mask operator!() const noexcept; 1548*4ba319b5SDimitry Andric 1549*4ba319b5SDimitry Andric // simd_mask binary operators [simd.mask.binary] 1550*4ba319b5SDimitry Andric friend simd_mask operator&&(const simd_mask&, const simd_mask&) noexcept; 1551*4ba319b5SDimitry Andric friend simd_mask operator||(const simd_mask&, const simd_mask&) noexcept; 1552*4ba319b5SDimitry Andric friend simd_mask operator&(const simd_mask&, const simd_mask&)noexcept; 1553*4ba319b5SDimitry Andric friend simd_mask operator|(const simd_mask&, const simd_mask&) noexcept; 1554*4ba319b5SDimitry Andric friend simd_mask operator^(const simd_mask&, const simd_mask&) noexcept; 1555*4ba319b5SDimitry Andric 1556*4ba319b5SDimitry Andric // simd_mask compound assignment [simd.mask.cassign] 1557*4ba319b5SDimitry Andric friend simd_mask& operator&=(simd_mask&, const simd_mask&) noexcept; 1558*4ba319b5SDimitry Andric friend simd_mask& operator|=(simd_mask&, const simd_mask&) noexcept; 1559*4ba319b5SDimitry Andric friend simd_mask& operator^=(simd_mask&, const simd_mask&) noexcept; 1560*4ba319b5SDimitry Andric 1561*4ba319b5SDimitry Andric // simd_mask compares [simd.mask.comparison] 1562*4ba319b5SDimitry Andric friend simd_mask operator==(const simd_mask&, const simd_mask&) noexcept; 1563*4ba319b5SDimitry Andric friend simd_mask operator!=(const simd_mask&, const simd_mask&) noexcept; 1564*4ba319b5SDimitry Andric}; 1565*4ba319b5SDimitry Andric 1566*4ba319b5SDimitry Andric#endif // _LIBCPP_STD_VER >= 17 1567*4ba319b5SDimitry Andric 1568*4ba319b5SDimitry Andric_LIBCPP_END_NAMESPACE_EXPERIMENTAL_SIMD 1569*4ba319b5SDimitry Andric 1570*4ba319b5SDimitry Andric#endif /* _LIBCPP_EXPERIMENTAL_SIMD */ 1571