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