1403c667bSTim Shen// -*- C++ -*- 2eb8650a7SLouis Dionne//===----------------------------------------------------------------------===// 3403c667bSTim Shen// 457b08b09SChandler Carruth// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 557b08b09SChandler Carruth// See https://llvm.org/LICENSE.txt for license information. 657b08b09SChandler Carruth// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7403c667bSTim Shen// 8403c667bSTim Shen//===----------------------------------------------------------------------===// 9403c667bSTim Shen#ifndef _LIBCPP_EXPERIMENTAL_SIMD 10403c667bSTim Shen#define _LIBCPP_EXPERIMENTAL_SIMD 11403c667bSTim Shen 12403c667bSTim Shen/* 13403c667bSTim Shen experimental/simd synopsis 14403c667bSTim Shen 15403c667bSTim Shennamespace std::experimental { 16403c667bSTim Shen 17403c667bSTim Sheninline namespace parallelism_v2 { 18403c667bSTim Shen 19403c667bSTim Shennamespace simd_abi { 20403c667bSTim Shen 21403c667bSTim Shenstruct scalar {}; 22403c667bSTim Shentemplate <int N> struct fixed_size {}; 23403c667bSTim Shentemplate <typename T> inline constexpr int max_fixed_size = implementation-defined; 24403c667bSTim Shentemplate <typename T> using compatible = implementation-defined; 25403c667bSTim Shentemplate <typename T> using native = implementation-defined; 26403c667bSTim Shen 27403c667bSTim Shen} // simd_abi 28403c667bSTim Shen 29403c667bSTim Shenstruct element_aligned_tag {}; 30403c667bSTim Shenstruct vector_aligned_tag {}; 31403c667bSTim Shentemplate <size_t> struct overaligned_tag {}; 32403c667bSTim Sheninline constexpr element_aligned_tag element_aligned{}; 33403c667bSTim Sheninline constexpr vector_aligned_tag vector_aligned{}; 34403c667bSTim Shentemplate <size_t N> inline constexpr overaligned_tag<N> overaligned{}; 35403c667bSTim Shen 36403c667bSTim Shen// traits [simd.traits] 37403c667bSTim Shentemplate <class T> struct is_abi_tag; 38403c667bSTim Shentemplate <class T> inline constexpr bool is_abi_tag_v = is_abi_tag<T>::value; 39403c667bSTim Shen 40403c667bSTim Shentemplate <class T> struct is_simd; 41403c667bSTim Shentemplate <class T> inline constexpr bool is_simd_v = is_simd<T>::value; 42403c667bSTim Shen 43403c667bSTim Shentemplate <class T> struct is_simd_mask; 44403c667bSTim Shentemplate <class T> inline constexpr bool is_simd_mask_v = is_simd_mask<T>::value; 45403c667bSTim Shen 46403c667bSTim Shentemplate <class T> struct is_simd_flag_type; 47403c667bSTim Shentemplate <class T> inline constexpr bool is_simd_flag_type_v = is_simd_flag_type<T>::value; 48403c667bSTim Shen 49403c667bSTim Shentemplate <class T, size_t N> struct abi_for_size { using type = see below; }; 50403c667bSTim Shentemplate <class T, size_t N> using abi_for_size_t = typename abi_for_size<T, N>::type; 51403c667bSTim Shen 52403c667bSTim Shentemplate <class T, class Abi = simd_abi::compatible<T>> struct simd_size; 53403c667bSTim Shentemplate <class T, class Abi = simd_abi::compatible<T>> 54403c667bSTim Sheninline constexpr size_t simd_size_v = simd_size<T, Abi>::value; 55403c667bSTim Shen 56403c667bSTim Shentemplate <class T, class U = typename T::value_type> struct memory_alignment; 57403c667bSTim Shentemplate <class T, class U = typename T::value_type> 58403c667bSTim Sheninline constexpr size_t memory_alignment_v = memory_alignment<T, U>::value; 59403c667bSTim Shen 60403c667bSTim Shen// class template simd [simd.class] 61403c667bSTim Shentemplate <class T, class Abi = simd_abi::compatible<T>> class simd; 62403c667bSTim Shentemplate <class T> using native_simd = simd<T, simd_abi::native<T>>; 63403c667bSTim Shentemplate <class T, int N> using fixed_size_simd = simd<T, simd_abi::fixed_size<N>>; 64403c667bSTim Shen 65403c667bSTim Shen// class template simd_mask [simd.mask.class] 66403c667bSTim Shentemplate <class T, class Abi = simd_abi::compatible<T>> class simd_mask; 67403c667bSTim Shentemplate <class T> using native_simd_mask = simd_mask<T, simd_abi::native<T>>; 68403c667bSTim Shentemplate <class T, int N> using fixed_size_simd_mask = simd_mask<T, simd_abi::fixed_size<N>>; 69403c667bSTim Shen 70403c667bSTim Shen// casts [simd.casts] 71403c667bSTim Shentemplate <class T, class U, class Abi> see below simd_cast(const simd<U, Abi>&); 72403c667bSTim Shentemplate <class T, class U, class Abi> see below static_simd_cast(const simd<U, Abi>&); 73403c667bSTim Shen 74403c667bSTim Shentemplate <class T, class Abi> 75403c667bSTim Shenfixed_size_simd<T, simd_size_v<T, Abi>> to_fixed_size(const simd<T, Abi>&) noexcept; 76403c667bSTim Shentemplate <class T, class Abi> 77403c667bSTim Shenfixed_size_simd_mask<T, simd_size_v<T, Abi>> to_fixed_size(const simd_mask<T, Abi>&) noexcept; 78403c667bSTim Shentemplate <class T, size_t N> native_simd<T> to_native(const fixed_size_simd<T, N>&) noexcept; 79403c667bSTim Shentemplate <class T, size_t N> 80403c667bSTim Shennative_simd_mask<T> to_native(const fixed_size_simd_mask<T, N>> &) noexcept; 81403c667bSTim Shentemplate <class T, size_t N> simd<T> to_compatible(const fixed_size_simd<T, N>&) noexcept; 82403c667bSTim Shentemplate <class T, size_t N> simd_mask<T> to_compatible(const fixed_size_simd_mask<T, N>&) noexcept; 83403c667bSTim Shen 84403c667bSTim Shentemplate <size_t... Sizes, class T, class Abi> 85403c667bSTim Shentuple<simd<T, abi_for_size_t<Sizes>>...> split(const simd<T, Abi>&); 86403c667bSTim Shentemplate <size_t... Sizes, class T, class Abi> 87403c667bSTim Shentuple<simd_mask<T, abi_for_size_t<Sizes>>...> split(const simd_mask<T, Abi>&); 88403c667bSTim Shentemplate <class V, class Abi> 89403c667bSTim Shenarray<V, simd_size_v<typename V::value_type, Abi> / V::size()> split( 90403c667bSTim Shenconst simd<typename V::value_type, Abi>&); 91403c667bSTim Shentemplate <class V, class Abi> 92403c667bSTim Shenarray<V, simd_size_v<typename V::value_type, Abi> / V::size()> split( 93403c667bSTim Shenconst simd_mask<typename V::value_type, Abi>&); 94403c667bSTim Shen 95403c667bSTim Shentemplate <class T, class... Abis> 96403c667bSTim Shensimd<T, abi_for_size_t<T, (simd_size_v<T, Abis> + ...)>> concat(const simd<T, Abis>&...); 97403c667bSTim Shentemplate <class T, class... Abis> 98403c667bSTim Shensimd_mask<T, abi_for_size_t<T, (simd_size_v<T, Abis> + ...)>> concat(const simd_mask<T, Abis>&...); 99403c667bSTim Shen 100403c667bSTim Shen// reductions [simd.mask.reductions] 101403c667bSTim Shentemplate <class T, class Abi> bool all_of(const simd_mask<T, Abi>&) noexcept; 102403c667bSTim Shentemplate <class T, class Abi> bool any_of(const simd_mask<T, Abi>&) noexcept; 103403c667bSTim Shentemplate <class T, class Abi> bool none_of(const simd_mask<T, Abi>&) noexcept; 104403c667bSTim Shentemplate <class T, class Abi> bool some_of(const simd_mask<T, Abi>&) noexcept; 105403c667bSTim Shentemplate <class T, class Abi> int popcount(const simd_mask<T, Abi>&) noexcept; 106403c667bSTim Shentemplate <class T, class Abi> int find_first_set(const simd_mask<T, Abi>&); 107403c667bSTim Shentemplate <class T, class Abi> int find_last_set(const simd_mask<T, Abi>&); 108403c667bSTim Shen 109403c667bSTim Shenbool all_of(see below) noexcept; 110403c667bSTim Shenbool any_of(see below) noexcept; 111403c667bSTim Shenbool none_of(see below) noexcept; 112403c667bSTim Shenbool some_of(see below) noexcept; 113403c667bSTim Shenint popcount(see below) noexcept; 114403c667bSTim Shenint find_first_set(see below) noexcept; 115403c667bSTim Shenint find_last_set(see below) noexcept; 116403c667bSTim Shen 117403c667bSTim Shen// masked assignment [simd.whereexpr] 118403c667bSTim Shentemplate <class M, class T> class const_where_expression; 119403c667bSTim Shentemplate <class M, class T> class where_expression; 120403c667bSTim Shen 121403c667bSTim Shen// masked assignment [simd.mask.where] 122403c667bSTim Shentemplate <class T> struct nodeduce { using type = T; }; // exposition only 123403c667bSTim Shen 124403c667bSTim Shentemplate <class T> using nodeduce_t = typename nodeduce<T>::type; // exposition only 125403c667bSTim Shen 126403c667bSTim Shentemplate <class T, class Abi> 127403c667bSTim Shenwhere_expression<simd_mask<T, Abi>, simd<T, Abi>> 128403c667bSTim Shenwhere(const typename simd<T, Abi>::mask_type&, simd<T, Abi>&) noexcept; 129403c667bSTim Shen 130403c667bSTim Shentemplate <class T, class Abi> 131403c667bSTim Shenconst_where_expression<simd_mask<T, Abi>, const simd<T, Abi>> 132403c667bSTim Shenwhere(const typename simd<T, Abi>::mask_type&, const simd<T, Abi>&) noexcept; 133403c667bSTim Shen 134403c667bSTim Shentemplate <class T, class Abi> 135403c667bSTim Shenwhere_expression<simd_mask<T, Abi>, simd_mask<T, Abi>> 136403c667bSTim Shenwhere(const nodeduce_t<simd_mask<T, Abi>>&, simd_mask<T, Abi>&) noexcept; 137403c667bSTim Shen 138403c667bSTim Shentemplate <class T, class Abi> 139403c667bSTim Shenconst_where_expression<simd_mask<T, Abi>, const simd_mask<T, Abi>> 140403c667bSTim Shenwhere(const nodeduce_t<simd_mask<T, Abi>>&, const simd_mask<T, Abi>&) noexcept; 141403c667bSTim Shen 142403c667bSTim Shentemplate <class T> where_expression<bool, T> where(see below k, T& d) noexcept; 143403c667bSTim Shen 144403c667bSTim Shentemplate <class T> 145403c667bSTim Shenconst_where_expression<bool, const T> where(see below k, const T& d) noexcept; 146403c667bSTim Shen 147403c667bSTim Shen// reductions [simd.reductions] 148403c667bSTim Shentemplate <class T, class Abi, class BinaryOperation = std::plus<>> 149403c667bSTim ShenT reduce(const simd<T, Abi>&, BinaryOperation = BinaryOperation()); 150403c667bSTim Shen 151403c667bSTim Shentemplate <class M, class V, class BinaryOperation> 152403c667bSTim Shentypename V::value_type reduce(const const_where_expression<M, V>& x, 153403c667bSTim Shentypename V::value_type neutral_element, BinaryOperation binary_op); 154403c667bSTim Shen 155403c667bSTim Shentemplate <class M, class V> 156403c667bSTim Shentypename V::value_type reduce(const const_where_expression<M, V>& x, plus<> binary_op = plus<>()); 157403c667bSTim Shen 158403c667bSTim Shentemplate <class M, class V> 159403c667bSTim Shentypename V::value_type reduce(const const_where_expression<M, V>& x, multiplies<> binary_op); 160403c667bSTim Shen 161403c667bSTim Shentemplate <class M, class V> 162403c667bSTim Shentypename V::value_type reduce(const const_where_expression<M, V>& x, bit_and<> binary_op); 163403c667bSTim Shen 164403c667bSTim Shentemplate <class M, class V> 165403c667bSTim Shentypename V::value_type reduce(const const_where_expression<M, V>& x, bit_or<> binary_op); 166403c667bSTim Shen 167403c667bSTim Shentemplate <class M, class V> 168403c667bSTim Shentypename V::value_type reduce(const const_where_expression<M, V>& x, bit_xor<> binary_op); 169403c667bSTim Shen 170403c667bSTim Shentemplate <class T, class Abi> T hmin(const simd<T, Abi>&); 171403c667bSTim Shentemplate <class M, class V> T hmin(const const_where_expression<M, V>&); 172403c667bSTim Shentemplate <class T, class Abi> T hmax(const simd<T, Abi>&); 173403c667bSTim Shentemplate <class M, class V> T hmax(const const_where_expression<M, V>&); 174403c667bSTim Shen 175403c667bSTim Shen// algorithms [simd.alg] 176403c667bSTim Shentemplate <class T, class Abi> simd<T, Abi> min(const simd<T, Abi>&, const simd<T, Abi>&) noexcept; 177403c667bSTim Shen 178403c667bSTim Shentemplate <class T, class Abi> simd<T, Abi> max(const simd<T, Abi>&, const simd<T, Abi>&) noexcept; 179403c667bSTim Shen 180403c667bSTim Shentemplate <class T, class Abi> 181403c667bSTim Shenstd::pair<simd<T, Abi>, simd<T, Abi>> minmax(const simd<T, Abi>&, const simd<T, Abi>&) noexcept; 182403c667bSTim Shen 183403c667bSTim Shentemplate <class T, class Abi> 184403c667bSTim Shensimd<T, Abi> clamp(const simd<T, Abi>& v, const simd<T, Abi>& lo, const simd<T, Abi>& hi); 185403c667bSTim Shen 186403c667bSTim Shen// [simd.whereexpr] 187403c667bSTim Shentemplate <class M, class T> 188403c667bSTim Shenclass const_where_expression { 189403c667bSTim Shen const M& mask; // exposition only 190403c667bSTim Shen T& data; // exposition only 191403c667bSTim Shenpublic: 192403c667bSTim Shen const_where_expression(const const_where_expression&) = delete; 193403c667bSTim Shen const_where_expression& operator=(const const_where_expression&) = delete; 194403c667bSTim Shen remove_const_t<T> operator-() const &&; 195403c667bSTim Shen template <class U, class Flags> void copy_to(U* mem, Flags f) const &&; 196403c667bSTim Shen}; 197403c667bSTim Shen 198403c667bSTim Shentemplate <class M, class T> 199403c667bSTim Shenclass where_expression : public const_where_expression<M, T> { 200403c667bSTim Shenpublic: 201403c667bSTim Shen where_expression(const where_expression&) = delete; 202403c667bSTim Shen where_expression& operator=(const where_expression&) = delete; 203403c667bSTim Shen template <class U> void operator=(U&& x); 204403c667bSTim Shen template <class U> void operator+=(U&& x); 205403c667bSTim Shen template <class U> void operator-=(U&& x); 206403c667bSTim Shen template <class U> void operator*=(U&& x); 207403c667bSTim Shen template <class U> void operator/=(U&& x); 208403c667bSTim Shen template <class U> void operator%=(U&& x); 209403c667bSTim Shen template <class U> void operator&=(U&& x); 210403c667bSTim Shen template <class U> void operator|=(U&& x); 211403c667bSTim Shen template <class U> void operator^=(U&& x); 212403c667bSTim Shen template <class U> void operator<<=(U&& x); 213403c667bSTim Shen template <class U> void operator>>=(U&& x); 214403c667bSTim Shen void operator++(); 215403c667bSTim Shen void operator++(int); 216403c667bSTim Shen void operator--(); 217403c667bSTim Shen void operator--(int); 218403c667bSTim Shen template <class U, class Flags> void copy_from(const U* mem, Flags); 219403c667bSTim Shen}; 220403c667bSTim Shen 221403c667bSTim Shen// [simd.class] 222403c667bSTim Shentemplate <class T, class Abi> class simd { 223403c667bSTim Shenpublic: 224403c667bSTim Shen using value_type = T; 225403c667bSTim Shen using reference = see below; 226403c667bSTim Shen using mask_type = simd_mask<T, Abi>; 227403c667bSTim Shen 228403c667bSTim Shen using abi_type = Abi; 229403c667bSTim Shen static constexpr size_t size() noexcept; 230403c667bSTim Shen simd() = default; 231403c667bSTim Shen 232403c667bSTim Shen // implicit type conversion constructor 233403c667bSTim Shen template <class U> simd(const simd<U, simd_abi::fixed_size<size()>>&); 234403c667bSTim Shen 235403c667bSTim Shen // implicit broadcast constructor (see below for constraints) 236403c667bSTim Shen template <class U> simd(U&& value); 237403c667bSTim Shen 238403c667bSTim Shen // generator constructor (see below for constraints) 239403c667bSTim Shen template <class G> explicit simd(G&& gen); 240403c667bSTim Shen 241403c667bSTim Shen // load constructor 242403c667bSTim Shen template <class U, class Flags> simd(const U* mem, Flags f); 243403c667bSTim Shen 244403c667bSTim Shen // loads [simd.load] 245403c667bSTim Shen template <class U, class Flags> void copy_from(const U* mem, Flags f); 246403c667bSTim Shen 247403c667bSTim Shen // stores [simd.store] 248403c667bSTim Shen template <class U, class Flags> void copy_to(U* mem, Flags f) const; 249403c667bSTim Shen 250403c667bSTim Shen // scalar access [simd.subscr] 251403c667bSTim Shen reference operator[](size_t); 252403c667bSTim Shen value_type operator[](size_t) const; 253403c667bSTim Shen 254403c667bSTim Shen // unary operators [simd.unary] 255403c667bSTim Shen simd& operator++(); 256403c667bSTim Shen simd operator++(int); 257403c667bSTim Shen simd& operator--(); 258403c667bSTim Shen simd operator--(int); 259403c667bSTim Shen mask_type operator!() const; 260403c667bSTim Shen simd operator~() const; // see below 261403c667bSTim Shen simd operator+() const; 262403c667bSTim Shen simd operator-() const; 263403c667bSTim Shen 264403c667bSTim Shen // binary operators [simd.binary] 265403c667bSTim Shen friend simd operator+ (const simd&, const simd&); 266403c667bSTim Shen friend simd operator- (const simd&, const simd&); 267403c667bSTim Shen friend simd operator* (const simd&, const simd&); 268403c667bSTim Shen friend simd operator/ (const simd&, const simd&); 269403c667bSTim Shen friend simd operator% (const simd&, const simd&); 270403c667bSTim Shen friend simd operator& (const simd&, const simd&); 271403c667bSTim Shen friend simd operator| (const simd&, const simd&); 272403c667bSTim Shen friend simd operator^ (const simd&, const simd&); 273403c667bSTim Shen friend simd operator<<(const simd&, const simd&); 274403c667bSTim Shen friend simd operator>>(const simd&, const simd&); 275403c667bSTim Shen friend simd operator<<(const simd&, int); 276403c667bSTim Shen friend simd operator>>(const simd&, int); 277403c667bSTim Shen 278403c667bSTim Shen // compound assignment [simd.cassign] 279403c667bSTim Shen friend simd& operator+= (simd&, const simd&); 280403c667bSTim Shen friend simd& operator-= (simd&, const simd&); 281403c667bSTim Shen friend simd& operator*= (simd&, const simd&); 282403c667bSTim Shen friend simd& operator/= (simd&, const simd&); 283403c667bSTim Shen friend simd& operator%= (simd&, const simd&); 284403c667bSTim Shen 285403c667bSTim Shen friend simd& operator&= (simd&, const simd&); 286403c667bSTim Shen friend simd& operator|= (simd&, const simd&); 287403c667bSTim Shen friend simd& operator^= (simd&, const simd&); 288403c667bSTim Shen friend simd& operator<<=(simd&, const simd&); 289403c667bSTim Shen friend simd& operator>>=(simd&, const simd&); 290403c667bSTim Shen friend simd& operator<<=(simd&, int); 291403c667bSTim Shen friend simd& operator>>=(simd&, int); 292403c667bSTim Shen 293403c667bSTim Shen // compares [simd.comparison] 294403c667bSTim Shen friend mask_type operator==(const simd&, const simd&); 295403c667bSTim Shen friend mask_type operator!=(const simd&, const simd&); 296403c667bSTim Shen friend mask_type operator>=(const simd&, const simd&); 297403c667bSTim Shen friend mask_type operator<=(const simd&, const simd&); 298403c667bSTim Shen friend mask_type operator> (const simd&, const simd&); 299403c667bSTim Shen friend mask_type operator< (const simd&, const simd&); 300403c667bSTim Shen}; 301403c667bSTim Shen 302403c667bSTim Shen// [simd.math] 303403c667bSTim Shentemplate <class Abi> using scharv = simd<signed char, Abi>; // exposition only 304403c667bSTim Shentemplate <class Abi> using shortv = simd<short, Abi>; // exposition only 305403c667bSTim Shentemplate <class Abi> using intv = simd<int, Abi>; // exposition only 306403c667bSTim Shentemplate <class Abi> using longv = simd<long int, Abi>; // exposition only 307403c667bSTim Shentemplate <class Abi> using llongv = simd<long long int, Abi>; // exposition only 308403c667bSTim Shentemplate <class Abi> using floatv = simd<float, Abi>; // exposition only 309403c667bSTim Shentemplate <class Abi> using doublev = simd<double, Abi>; // exposition only 310403c667bSTim Shentemplate <class Abi> using ldoublev = simd<long double, Abi>; // exposition only 311403c667bSTim Shentemplate <class T, class V> using samesize = fixed_size_simd<T, V::size()>; // exposition only 312403c667bSTim Shen 313403c667bSTim Shentemplate <class Abi> floatv<Abi> acos(floatv<Abi> x); 314403c667bSTim Shentemplate <class Abi> doublev<Abi> acos(doublev<Abi> x); 315403c667bSTim Shentemplate <class Abi> ldoublev<Abi> acos(ldoublev<Abi> x); 316403c667bSTim Shen 317403c667bSTim Shentemplate <class Abi> floatv<Abi> asin(floatv<Abi> x); 318403c667bSTim Shentemplate <class Abi> doublev<Abi> asin(doublev<Abi> x); 319403c667bSTim Shentemplate <class Abi> ldoublev<Abi> asin(ldoublev<Abi> x); 320403c667bSTim Shen 321403c667bSTim Shentemplate <class Abi> floatv<Abi> atan(floatv<Abi> x); 322403c667bSTim Shentemplate <class Abi> doublev<Abi> atan(doublev<Abi> x); 323403c667bSTim Shentemplate <class Abi> ldoublev<Abi> atan(ldoublev<Abi> x); 324403c667bSTim Shen 325403c667bSTim Shentemplate <class Abi> floatv<Abi> atan2(floatv<Abi> y, floatv<Abi> x); 326403c667bSTim Shentemplate <class Abi> doublev<Abi> atan2(doublev<Abi> y, doublev<Abi> x); 327403c667bSTim Shentemplate <class Abi> ldoublev<Abi> atan2(ldoublev<Abi> y, ldoublev<Abi> x); 328403c667bSTim Shen 329403c667bSTim Shentemplate <class Abi> floatv<Abi> cos(floatv<Abi> x); 330403c667bSTim Shentemplate <class Abi> doublev<Abi> cos(doublev<Abi> x); 331403c667bSTim Shentemplate <class Abi> ldoublev<Abi> cos(ldoublev<Abi> x); 332403c667bSTim Shen 333403c667bSTim Shentemplate <class Abi> floatv<Abi> sin(floatv<Abi> x); 334403c667bSTim Shentemplate <class Abi> doublev<Abi> sin(doublev<Abi> x); 335403c667bSTim Shentemplate <class Abi> ldoublev<Abi> sin(ldoublev<Abi> x); 336403c667bSTim Shen 337403c667bSTim Shentemplate <class Abi> floatv<Abi> tan(floatv<Abi> x); 338403c667bSTim Shentemplate <class Abi> doublev<Abi> tan(doublev<Abi> x); 339403c667bSTim Shentemplate <class Abi> ldoublev<Abi> tan(ldoublev<Abi> x); 340403c667bSTim Shen 341403c667bSTim Shentemplate <class Abi> floatv<Abi> acosh(floatv<Abi> x); 342403c667bSTim Shentemplate <class Abi> doublev<Abi> acosh(doublev<Abi> x); 343403c667bSTim Shentemplate <class Abi> ldoublev<Abi> acosh(ldoublev<Abi> x); 344403c667bSTim Shen 345403c667bSTim Shentemplate <class Abi> floatv<Abi> asinh(floatv<Abi> x); 346403c667bSTim Shentemplate <class Abi> doublev<Abi> asinh(doublev<Abi> x); 347403c667bSTim Shentemplate <class Abi> ldoublev<Abi> asinh(ldoublev<Abi> x); 348403c667bSTim Shen 349403c667bSTim Shentemplate <class Abi> floatv<Abi> atanh(floatv<Abi> x); 350403c667bSTim Shentemplate <class Abi> doublev<Abi> atanh(doublev<Abi> x); 351403c667bSTim Shentemplate <class Abi> ldoublev<Abi> atanh(ldoublev<Abi> x); 352403c667bSTim Shen 353403c667bSTim Shentemplate <class Abi> floatv<Abi> cosh(floatv<Abi> x); 354403c667bSTim Shentemplate <class Abi> doublev<Abi> cosh(doublev<Abi> x); 355403c667bSTim Shentemplate <class Abi> ldoublev<Abi> cosh(ldoublev<Abi> x); 356403c667bSTim Shen 357403c667bSTim Shentemplate <class Abi> floatv<Abi> sinh(floatv<Abi> x); 358403c667bSTim Shentemplate <class Abi> doublev<Abi> sinh(doublev<Abi> x); 359403c667bSTim Shentemplate <class Abi> ldoublev<Abi> sinh(ldoublev<Abi> x); 360403c667bSTim Shen 361403c667bSTim Shentemplate <class Abi> floatv<Abi> tanh(floatv<Abi> x); 362403c667bSTim Shentemplate <class Abi> doublev<Abi> tanh(doublev<Abi> x); 363403c667bSTim Shentemplate <class Abi> ldoublev<Abi> tanh(ldoublev<Abi> x); 364403c667bSTim Shen 365403c667bSTim Shentemplate <class Abi> floatv<Abi> exp(floatv<Abi> x); 366403c667bSTim Shentemplate <class Abi> doublev<Abi> exp(doublev<Abi> x); 367403c667bSTim Shentemplate <class Abi> ldoublev<Abi> exp(ldoublev<Abi> x); 368403c667bSTim Shen 369403c667bSTim Shentemplate <class Abi> floatv<Abi> exp2(floatv<Abi> x); 370403c667bSTim Shentemplate <class Abi> doublev<Abi> exp2(doublev<Abi> x); 371403c667bSTim Shentemplate <class Abi> ldoublev<Abi> exp2(ldoublev<Abi> x); 372403c667bSTim Shen 373403c667bSTim Shentemplate <class Abi> floatv<Abi> expm1(floatv<Abi> x); 374403c667bSTim Shentemplate <class Abi> doublev<Abi> expm1(doublev<Abi> x); 375403c667bSTim Shentemplate <class Abi> ldoublev<Abi> expm1(ldoublev<Abi> x); 376403c667bSTim Shen 377403c667bSTim Shentemplate <class Abi> floatv<Abi> frexp(floatv<Abi> value, samesize<int, floatv<Abi>>* exp); 378403c667bSTim Shentemplate <class Abi> doublev<Abi> frexp(doublev<Abi> value, samesize<int, doublev<Abi>>* exp); 379403c667bSTim Shentemplate <class Abi> ldoublev<Abi> frexp(ldoublev<Abi> value, samesize<int, ldoublev<Abi>>* exp); 380403c667bSTim Shen 381403c667bSTim Shentemplate <class Abi> samesize<int, floatv<Abi>> ilogb(floatv<Abi> x); 382403c667bSTim Shentemplate <class Abi> samesize<int, doublev<Abi>> ilogb(doublev<Abi> x); 383403c667bSTim Shentemplate <class Abi> samesize<int, ldoublev<Abi>> ilogb(ldoublev<Abi> x); 384403c667bSTim Shen 385403c667bSTim Shentemplate <class Abi> floatv<Abi> ldexp(floatv<Abi> x, samesize<int, floatv<Abi>> exp); 386403c667bSTim Shentemplate <class Abi> doublev<Abi> ldexp(doublev<Abi> x, samesize<int, doublev<Abi>> exp); 387403c667bSTim Shentemplate <class Abi> ldoublev<Abi> ldexp(ldoublev<Abi> x, samesize<int, ldoublev<Abi>> exp); 388403c667bSTim Shen 389403c667bSTim Shentemplate <class Abi> floatv<Abi> log(floatv<Abi> x); 390403c667bSTim Shentemplate <class Abi> doublev<Abi> log(doublev<Abi> x); 391403c667bSTim Shentemplate <class Abi> ldoublev<Abi> log(ldoublev<Abi> x); 392403c667bSTim Shen 393403c667bSTim Shentemplate <class Abi> floatv<Abi> log10(floatv<Abi> x); 394403c667bSTim Shentemplate <class Abi> doublev<Abi> log10(doublev<Abi> x); 395403c667bSTim Shentemplate <class Abi> ldoublev<Abi> log10(ldoublev<Abi> x); 396403c667bSTim Shen 397403c667bSTim Shentemplate <class Abi> floatv<Abi> log1p(floatv<Abi> x); 398403c667bSTim Shentemplate <class Abi> doublev<Abi> log1p(doublev<Abi> x); 399403c667bSTim Shentemplate <class Abi> ldoublev<Abi> log1p(ldoublev<Abi> x); 400403c667bSTim Shen 401403c667bSTim Shentemplate <class Abi> floatv<Abi> log2(floatv<Abi> x); 402403c667bSTim Shentemplate <class Abi> doublev<Abi> log2(doublev<Abi> x); 403403c667bSTim Shentemplate <class Abi> ldoublev<Abi> log2(ldoublev<Abi> x); 404403c667bSTim Shen 405403c667bSTim Shentemplate <class Abi> floatv<Abi> logb(floatv<Abi> x); 406403c667bSTim Shentemplate <class Abi> doublev<Abi> logb(doublev<Abi> x); 407403c667bSTim Shentemplate <class Abi> ldoublev<Abi> logb(ldoublev<Abi> x); 408403c667bSTim Shen 409403c667bSTim Shentemplate <class Abi> floatv<Abi> modf(floatv<Abi> value, floatv<Abi>* iptr); 410403c667bSTim Shentemplate <class Abi> doublev<Abi> modf(doublev<Abi> value, doublev<Abi>* iptr); 411403c667bSTim Shentemplate <class Abi> ldoublev<Abi> modf(ldoublev<Abi> value, ldoublev<Abi>* iptr); 412403c667bSTim Shen 413403c667bSTim Shentemplate <class Abi> floatv<Abi> scalbn(floatv<Abi> x, samesize<int, floatv<Abi>> n); 414403c667bSTim Shentemplate <class Abi> doublev<Abi> scalbn(doublev<Abi> x, samesize<int, doublev<Abi>> n); 415403c667bSTim Shentemplate <class Abi> ldoublev<Abi> scalbn(ldoublev<Abi> x, samesize<int, ldoublev<Abi>> n); 416403c667bSTim Shentemplate <class Abi> floatv<Abi> scalbln(floatv<Abi> x, samesize<long int, floatv<Abi>> n); 417403c667bSTim Shentemplate <class Abi> doublev<Abi> scalbln(doublev<Abi> x, samesize<long int, doublev<Abi>> n); 418403c667bSTim Shentemplate <class Abi> ldoublev<Abi> scalbln(ldoublev<Abi> x, samesize<long int, ldoublev<Abi>> n); 419403c667bSTim Shen 420403c667bSTim Shentemplate <class Abi> floatv<Abi> cbrt(floatv<Abi> x); 421403c667bSTim Shentemplate <class Abi> doublev<Abi> cbrt(doublev<Abi> x); 422403c667bSTim Shentemplate <class Abi> ldoublev<Abi> cbrt(ldoublev<Abi> x); 423403c667bSTim Shen 424403c667bSTim Shentemplate <class Abi> scharv<Abi> abs(scharv<Abi> j); 425403c667bSTim Shentemplate <class Abi> shortv<Abi> abs(shortv<Abi> j); 426403c667bSTim Shentemplate <class Abi> intv<Abi> abs(intv<Abi> j); 427403c667bSTim Shentemplate <class Abi> longv<Abi> abs(longv<Abi> j); 428403c667bSTim Shentemplate <class Abi> llongv<Abi> abs(llongv<Abi> j); 429403c667bSTim Shentemplate <class Abi> floatv<Abi> abs(floatv<Abi> j); 430403c667bSTim Shentemplate <class Abi> doublev<Abi> abs(doublev<Abi> j); 431403c667bSTim Shentemplate <class Abi> ldoublev<Abi> abs(ldoublev<Abi> j); 432403c667bSTim Shen 433403c667bSTim Shentemplate <class Abi> floatv<Abi> hypot(floatv<Abi> x, floatv<Abi> y); 434403c667bSTim Shentemplate <class Abi> doublev<Abi> hypot(doublev<Abi> x, doublev<Abi> y); 435403c667bSTim Shentemplate <class Abi> ldoublev<Abi> hypot(doublev<Abi> x, doublev<Abi> y); 436403c667bSTim Shentemplate <class Abi> floatv<Abi> hypot(floatv<Abi> x, floatv<Abi> y, floatv<Abi> z); 437403c667bSTim Shentemplate <class Abi> doublev<Abi> hypot(doublev<Abi> x, doublev<Abi> y, doublev<Abi> z); 438403c667bSTim Shentemplate <class Abi> ldoublev<Abi> hypot(ldoublev<Abi> x, ldoublev<Abi> y, ldoublev<Abi> z); 439403c667bSTim Shen 440403c667bSTim Shentemplate <class Abi> floatv<Abi> pow(floatv<Abi> x, floatv<Abi> y); 441403c667bSTim Shentemplate <class Abi> doublev<Abi> pow(doublev<Abi> x, doublev<Abi> y); 442403c667bSTim Shentemplate <class Abi> ldoublev<Abi> pow(ldoublev<Abi> x, ldoublev<Abi> y); 443403c667bSTim Shen 444403c667bSTim Shentemplate <class Abi> floatv<Abi> sqrt(floatv<Abi> x); 445403c667bSTim Shentemplate <class Abi> doublev<Abi> sqrt(doublev<Abi> x); 446403c667bSTim Shentemplate <class Abi> ldoublev<Abi> sqrt(ldoublev<Abi> x); 447403c667bSTim Shen 448403c667bSTim Shentemplate <class Abi> floatv<Abi> erf(floatv<Abi> x); 449403c667bSTim Shentemplate <class Abi> doublev<Abi> erf(doublev<Abi> x); 450403c667bSTim Shentemplate <class Abi> ldoublev<Abi> erf(ldoublev<Abi> x); 451403c667bSTim Shentemplate <class Abi> floatv<Abi> erfc(floatv<Abi> x); 452403c667bSTim Shentemplate <class Abi> doublev<Abi> erfc(doublev<Abi> x); 453403c667bSTim Shentemplate <class Abi> ldoublev<Abi> erfc(ldoublev<Abi> x); 454403c667bSTim Shen 455403c667bSTim Shentemplate <class Abi> floatv<Abi> lgamma(floatv<Abi> x); 456403c667bSTim Shentemplate <class Abi> doublev<Abi> lgamma(doublev<Abi> x); 457403c667bSTim Shentemplate <class Abi> ldoublev<Abi> lgamma(ldoublev<Abi> x); 458403c667bSTim Shen 459403c667bSTim Shentemplate <class Abi> floatv<Abi> tgamma(floatv<Abi> x); 460403c667bSTim Shentemplate <class Abi> doublev<Abi> tgamma(doublev<Abi> x); 461403c667bSTim Shentemplate <class Abi> ldoublev<Abi> tgamma(ldoublev<Abi> x); 462403c667bSTim Shen 463403c667bSTim Shentemplate <class Abi> floatv<Abi> ceil(floatv<Abi> x); 464403c667bSTim Shentemplate <class Abi> doublev<Abi> ceil(doublev<Abi> x); 465403c667bSTim Shentemplate <class Abi> ldoublev<Abi> ceil(ldoublev<Abi> x); 466403c667bSTim Shen 467403c667bSTim Shentemplate <class Abi> floatv<Abi> floor(floatv<Abi> x); 468403c667bSTim Shentemplate <class Abi> doublev<Abi> floor(doublev<Abi> x); 469403c667bSTim Shentemplate <class Abi> ldoublev<Abi> floor(ldoublev<Abi> x); 470403c667bSTim Shen 471403c667bSTim Shentemplate <class Abi> floatv<Abi> nearbyint(floatv<Abi> x); 472403c667bSTim Shentemplate <class Abi> doublev<Abi> nearbyint(doublev<Abi> x); 473403c667bSTim Shentemplate <class Abi> ldoublev<Abi> nearbyint(ldoublev<Abi> x); 474403c667bSTim Shen 475403c667bSTim Shentemplate <class Abi> floatv<Abi> rint(floatv<Abi> x); 476403c667bSTim Shentemplate <class Abi> doublev<Abi> rint(doublev<Abi> x); 477403c667bSTim Shentemplate <class Abi> ldoublev<Abi> rint(ldoublev<Abi> x); 478403c667bSTim Shen 479403c667bSTim Shentemplate <class Abi> samesize<long int, floatv<Abi>> lrint(floatv<Abi> x); 480403c667bSTim Shentemplate <class Abi> samesize<long int, doublev<Abi>> lrint(doublev<Abi> x); 481403c667bSTim Shentemplate <class Abi> samesize<long int, ldoublev<Abi>> lrint(ldoublev<Abi> x); 482403c667bSTim Shentemplate <class Abi> samesize<long long int, floatv<Abi>> llrint(floatv<Abi> x); 483403c667bSTim Shentemplate <class Abi> samesize<long long int, doublev<Abi>> llrint(doublev<Abi> x); 484403c667bSTim Shentemplate <class Abi> samesize<long long int, ldoublev<Abi>> llrint(ldoublev<Abi> x); 485403c667bSTim Shen 486403c667bSTim Shentemplate <class Abi> floatv<Abi> round(floatv<Abi> x); 487403c667bSTim Shentemplate <class Abi> doublev<Abi> round(doublev<Abi> x); 488403c667bSTim Shentemplate <class Abi> ldoublev<Abi> round(ldoublev<Abi> x); 489403c667bSTim Shentemplate <class Abi> samesize<long int, floatv<Abi>> lround(floatv<Abi> x); 490403c667bSTim Shentemplate <class Abi> samesize<long int, doublev<Abi>> lround(doublev<Abi> x); 491403c667bSTim Shentemplate <class Abi> samesize<long int, ldoublev<Abi>> lround(ldoublev<Abi> x); 492403c667bSTim Shentemplate <class Abi> samesize<long long int, floatv<Abi>> llround(floatv<Abi> x); 493403c667bSTim Shentemplate <class Abi> samesize<long long int, doublev<Abi>> llround(doublev<Abi> x); 494403c667bSTim Shentemplate <class Abi> samesize<long long int, ldoublev<Abi>> llround(ldoublev<Abi> x); 495403c667bSTim Shen 496403c667bSTim Shentemplate <class Abi> floatv<Abi> trunc(floatv<Abi> x); 497403c667bSTim Shentemplate <class Abi> doublev<Abi> trunc(doublev<Abi> x); 498403c667bSTim Shentemplate <class Abi> ldoublev<Abi> trunc(ldoublev<Abi> x); 499403c667bSTim Shen 500403c667bSTim Shentemplate <class Abi> floatv<Abi> fmod(floatv<Abi> x, floatv<Abi> y); 501403c667bSTim Shentemplate <class Abi> doublev<Abi> fmod(doublev<Abi> x, doublev<Abi> y); 502403c667bSTim Shentemplate <class Abi> ldoublev<Abi> fmod(ldoublev<Abi> x, ldoublev<Abi> y); 503403c667bSTim Shen 504403c667bSTim Shentemplate <class Abi> floatv<Abi> remainder(floatv<Abi> x, floatv<Abi> y); 505403c667bSTim Shentemplate <class Abi> doublev<Abi> remainder(doublev<Abi> x, doublev<Abi> y); 506403c667bSTim Shentemplate <class Abi> ldoublev<Abi> remainder(ldoublev<Abi> x, ldoublev<Abi> y); 507403c667bSTim Shen 508403c667bSTim Shentemplate <class Abi> floatv<Abi> remquo(floatv<Abi> x, floatv<Abi> y, samesize<int, floatv<Abi>>* quo); 509403c667bSTim Shentemplate <class Abi> doublev<Abi> remquo(doublev<Abi> x, doublev<Abi> y, samesize<int, doublev<Abi>>* quo); 510403c667bSTim Shentemplate <class Abi> ldoublev<Abi> remquo(ldoublev<Abi> x, ldoublev<Abi> y, samesize<int, ldoublev<Abi>>* quo); 511403c667bSTim Shen 512403c667bSTim Shentemplate <class Abi> floatv<Abi> copysign(floatv<Abi> x, floatv<Abi> y); 513403c667bSTim Shentemplate <class Abi> doublev<Abi> copysign(doublev<Abi> x, doublev<Abi> y); 514403c667bSTim Shentemplate <class Abi> ldoublev<Abi> copysign(ldoublev<Abi> x, ldoublev<Abi> y); 515403c667bSTim Shen 516403c667bSTim Shentemplate <class Abi> doublev<Abi> nan(const char* tagp); 517403c667bSTim Shentemplate <class Abi> floatv<Abi> nanf(const char* tagp); 518403c667bSTim Shentemplate <class Abi> ldoublev<Abi> nanl(const char* tagp); 519403c667bSTim Shen 520403c667bSTim Shentemplate <class Abi> floatv<Abi> nextafter(floatv<Abi> x, floatv<Abi> y); 521403c667bSTim Shentemplate <class Abi> doublev<Abi> nextafter(doublev<Abi> x, doublev<Abi> y); 522403c667bSTim Shentemplate <class Abi> ldoublev<Abi> nextafter(ldoublev<Abi> x, ldoublev<Abi> y); 523403c667bSTim Shen 524403c667bSTim Shentemplate <class Abi> floatv<Abi> nexttoward(floatv<Abi> x, ldoublev<Abi> y); 525403c667bSTim Shentemplate <class Abi> doublev<Abi> nexttoward(doublev<Abi> x, ldoublev<Abi> y); 526403c667bSTim Shentemplate <class Abi> ldoublev<Abi> nexttoward(ldoublev<Abi> x, ldoublev<Abi> y); 527403c667bSTim Shen 528403c667bSTim Shentemplate <class Abi> floatv<Abi> fdim(floatv<Abi> x, floatv<Abi> y); 529403c667bSTim Shentemplate <class Abi> doublev<Abi> fdim(doublev<Abi> x, doublev<Abi> y); 530403c667bSTim Shentemplate <class Abi> ldoublev<Abi> fdim(ldoublev<Abi> x, ldoublev<Abi> y); 531403c667bSTim Shen 532403c667bSTim Shentemplate <class Abi> floatv<Abi> fmax(floatv<Abi> x, floatv<Abi> y); 533403c667bSTim Shentemplate <class Abi> doublev<Abi> fmax(doublev<Abi> x, doublev<Abi> y); 534403c667bSTim Shentemplate <class Abi> ldoublev<Abi> fmax(ldoublev<Abi> x, ldoublev<Abi> y); 535403c667bSTim Shen 536403c667bSTim Shentemplate <class Abi> floatv<Abi> fmin(floatv<Abi> x, floatv<Abi> y); 537403c667bSTim Shentemplate <class Abi> doublev<Abi> fmin(doublev<Abi> x, doublev<Abi> y); 538403c667bSTim Shentemplate <class Abi> ldoublev<Abi> fmin(ldoublev<Abi> x, ldoublev<Abi> y); 539403c667bSTim Shen 540403c667bSTim Shentemplate <class Abi> floatv<Abi> fma(floatv<Abi> x, floatv<Abi> y, floatv<Abi> z); 541403c667bSTim Shentemplate <class Abi> doublev<Abi> fma(doublev<Abi> x, doublev<Abi> y, doublev<Abi> z); 542403c667bSTim Shentemplate <class Abi> ldoublev<Abi> fma(ldoublev<Abi> x, ldoublev<Abi> y, ldoublev<Abi> z); 543403c667bSTim Shen 544403c667bSTim Shentemplate <class Abi> samesize<int, floatv<Abi>> fpclassify(floatv<Abi> x); 545403c667bSTim Shentemplate <class Abi> samesize<int, doublev<Abi>> fpclassify(doublev<Abi> x); 546403c667bSTim Shentemplate <class Abi> samesize<int, ldoublev<Abi>> fpclassify(ldoublev<Abi> x); 547403c667bSTim Shen 548403c667bSTim Shentemplate <class Abi> simd_mask<float, Abi> isfinite(floatv<Abi> x); 549403c667bSTim Shentemplate <class Abi> simd_mask<double, Abi> isfinite(doublev<Abi> x); 550403c667bSTim Shentemplate <class Abi> simd_mask<long double, Abi> isfinite(ldoublev<Abi> x); 551403c667bSTim Shen 552403c667bSTim Shentemplate <class Abi> simd_mask<float, Abi> isinf(floatv<Abi> x); 553403c667bSTim Shentemplate <class Abi> simd_mask<double, Abi> isinf(doublev<Abi> x); 554403c667bSTim Shentemplate <class Abi> simd_mask<long double, Abi> isinf(ldoublev<Abi> x); 555403c667bSTim Shen 556403c667bSTim Shentemplate <class Abi> simd_mask<float, Abi> isnan(floatv<Abi> x); 557403c667bSTim Shentemplate <class Abi> simd_mask<double, Abi> isnan(doublev<Abi> x); 558403c667bSTim Shentemplate <class Abi> simd_mask<long double, Abi> isnan(ldoublev<Abi> x); 559403c667bSTim Shen 560403c667bSTim Shentemplate <class Abi> simd_mask<float, Abi> isnormal(floatv<Abi> x); 561403c667bSTim Shentemplate <class Abi> simd_mask<double, Abi> isnormal(doublev<Abi> x); 562403c667bSTim Shentemplate <class Abi> simd_mask<long double, Abi> isnormal(ldoublev<Abi> x); 563403c667bSTim Shen 564403c667bSTim Shentemplate <class Abi> simd_mask<float, Abi> signbit(floatv<Abi> x); 565403c667bSTim Shentemplate <class Abi> simd_mask<double, Abi> signbit(doublev<Abi> x); 566403c667bSTim Shentemplate <class Abi> simd_mask<long double, Abi> signbit(ldoublev<Abi> x); 567403c667bSTim Shen 568403c667bSTim Shentemplate <class Abi> simd_mask<float, Abi> isgreater(floatv<Abi> x, floatv<Abi> y); 569403c667bSTim Shentemplate <class Abi> simd_mask<double, Abi> isgreater(doublev<Abi> x, doublev<Abi> y); 570403c667bSTim Shentemplate <class Abi> simd_mask<long double, Abi> isgreater(ldoublev<Abi> x, ldoublev<Abi> y); 571403c667bSTim Shen 572403c667bSTim Shentemplate <class Abi> simd_mask<float, Abi> isgreaterequal(floatv<Abi> x, floatv<Abi> y); 573403c667bSTim Shentemplate <class Abi> simd_mask<double, Abi> isgreaterequal(doublev<Abi> x, doublev<Abi> y); 574403c667bSTim Shentemplate <class Abi> simd_mask<long double, Abi> isgreaterequal(ldoublev<Abi> x, ldoublev<Abi> y); 575403c667bSTim Shen 576403c667bSTim Shentemplate <class Abi> simd_mask<float, Abi> isless(floatv<Abi> x, floatv<Abi> y); 577403c667bSTim Shentemplate <class Abi> simd_mask<double, Abi> isless(doublev<Abi> x, doublev<Abi> y); 578403c667bSTim Shentemplate <class Abi> simd_mask<long double, Abi> isless(ldoublev<Abi> x, ldoublev<Abi> y); 579403c667bSTim Shen 580403c667bSTim Shentemplate <class Abi> simd_mask<float, Abi> islessequal(floatv<Abi> x, floatv<Abi> y); 581403c667bSTim Shentemplate <class Abi> simd_mask<double, Abi> islessequal(doublev<Abi> x, doublev<Abi> y); 582403c667bSTim Shentemplate <class Abi> simd_mask<long double, Abi> islessequal(ldoublev<Abi> x, ldoublev<Abi> y); 583403c667bSTim Shen 584403c667bSTim Shentemplate <class Abi> simd_mask<float, Abi> islessgreater(floatv<Abi> x, floatv<Abi> y); 585403c667bSTim Shentemplate <class Abi> simd_mask<double, Abi> islessgreater(doublev<Abi> x, doublev<Abi> y); 586403c667bSTim Shentemplate <class Abi> simd_mask<long double, Abi> islessgreater(ldoublev<Abi> x, ldoublev<Abi> y); 587403c667bSTim Shen 588403c667bSTim Shentemplate <class Abi> simd_mask<float, Abi> isunordered(floatv<Abi> x, floatv<Abi> y); 589403c667bSTim Shentemplate <class Abi> simd_mask<double, Abi> isunordered(doublev<Abi> x, doublev<Abi> y); 590403c667bSTim Shentemplate <class Abi> simd_mask<long double, Abi> isunordered(ldoublev<Abi> x, ldoublev<Abi> y); 591403c667bSTim Shen 592403c667bSTim Shentemplate <class V> struct simd_div_t { V quot, rem; }; 593403c667bSTim Shentemplate <class Abi> simd_div_t<scharv<Abi>> div(scharv<Abi> numer, scharv<Abi> denom); 594403c667bSTim Shentemplate <class Abi> simd_div_t<shortv<Abi>> div(shortv<Abi> numer, shortv<Abi> denom); 595403c667bSTim Shentemplate <class Abi> simd_div_t<intv<Abi>> div(intv<Abi> numer, intv<Abi> denom); 596403c667bSTim Shentemplate <class Abi> simd_div_t<longv<Abi>> div(longv<Abi> numer, longv<Abi> denom); 597403c667bSTim Shentemplate <class Abi> simd_div_t<llongv<Abi>> div(llongv<Abi> numer, llongv<Abi> denom); 598403c667bSTim Shen 599403c667bSTim Shen// [simd.mask.class] 600403c667bSTim Shentemplate <class T, class Abi> 601403c667bSTim Shenclass simd_mask { 602403c667bSTim Shenpublic: 603403c667bSTim Shen using value_type = bool; 604403c667bSTim Shen using reference = see below; 605403c667bSTim Shen using simd_type = simd<T, Abi>; 606403c667bSTim Shen using abi_type = Abi; 607403c667bSTim Shen static constexpr size_t size() noexcept; 608403c667bSTim Shen simd_mask() = default; 609403c667bSTim Shen 610403c667bSTim Shen // broadcast constructor 611403c667bSTim Shen explicit simd_mask(value_type) noexcept; 612403c667bSTim Shen 613403c667bSTim Shen // implicit type conversion constructor 614403c667bSTim Shen template <class U> simd_mask(const simd_mask<U, simd_abi::fixed_size<size()>>&) noexcept; 615403c667bSTim Shen 616403c667bSTim Shen // load constructor 617403c667bSTim Shen template <class Flags> simd_mask(const value_type* mem, Flags); 618403c667bSTim Shen 619403c667bSTim Shen // loads [simd.mask.copy] 620403c667bSTim Shen template <class Flags> void copy_from(const value_type* mem, Flags); 621403c667bSTim Shen template <class Flags> void copy_to(value_type* mem, Flags) const; 622403c667bSTim Shen 623403c667bSTim Shen // scalar access [simd.mask.subscr] 624403c667bSTim Shen reference operator[](size_t); 625403c667bSTim Shen value_type operator[](size_t) const; 626403c667bSTim Shen 627403c667bSTim Shen // unary operators [simd.mask.unary] 628403c667bSTim Shen simd_mask operator!() const noexcept; 629403c667bSTim Shen 630403c667bSTim Shen // simd_mask binary operators [simd.mask.binary] 631403c667bSTim Shen friend simd_mask operator&&(const simd_mask&, const simd_mask&) noexcept; 632403c667bSTim Shen friend simd_mask operator||(const simd_mask&, const simd_mask&) noexcept; 633403c667bSTim Shen friend simd_mask operator& (const simd_mask&, const simd_mask&) noexcept; 634403c667bSTim Shen friend simd_mask operator| (const simd_mask&, const simd_mask&) noexcept; 635403c667bSTim Shen friend simd_mask operator^ (const simd_mask&, const simd_mask&) noexcept; 636403c667bSTim Shen 637403c667bSTim Shen // simd_mask compound assignment [simd.mask.cassign] 638403c667bSTim Shen friend simd_mask& operator&=(simd_mask&, const simd_mask&) noexcept; 639403c667bSTim Shen friend simd_mask& operator|=(simd_mask&, const simd_mask&) noexcept; 640403c667bSTim Shen friend simd_mask& operator^=(simd_mask&, const simd_mask&) noexcept; 641403c667bSTim Shen 642403c667bSTim Shen // simd_mask compares [simd.mask.comparison] 643403c667bSTim Shen friend simd_mask operator==(const simd_mask&, const simd_mask&) noexcept; 644403c667bSTim Shen friend simd_mask operator!=(const simd_mask&, const simd_mask&) noexcept; 645403c667bSTim Shen}; 646403c667bSTim Shen 647403c667bSTim Shen} // parallelism_v2 648403c667bSTim Shen} // std::experimental 649403c667bSTim Shen 650403c667bSTim Shen*/ 651403c667bSTim Shen 652385cc25aSLouis Dionne#include <__assert> // all public C++ headers provide the assertion handler 653faef447eSNikolas Klauser#include <__functional/operations.h> 654403c667bSTim Shen#include <array> 655403c667bSTim Shen#include <cstddef> 6564d81a46fSArthur O'Dwyer#include <experimental/__config> 657faef447eSNikolas Klauser#include <tuple> 658403c667bSTim Shen 659de4a57cbSLouis Dionne#ifndef _LIBCPP_REMOVE_TRANSITIVE_INCLUDES 660de4a57cbSLouis Dionne# include <algorithm> 661de4a57cbSLouis Dionne# include <functional> 662de4a57cbSLouis Dionne#endif 663de4a57cbSLouis Dionne 664403c667bSTim Shen#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 665403c667bSTim Shen# pragma GCC system_header 666403c667bSTim Shen#endif 667403c667bSTim Shen 668d4303307SArthur O'Dwyer_LIBCPP_PUSH_MACROS 669d4303307SArthur O'Dwyer#include <__undef_macros> 670d4303307SArthur O'Dwyer 671403c667bSTim Shen_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_SIMD 672403c667bSTim Shen 67338cd7de5STim Shen#if _LIBCPP_STD_VER >= 17 67438cd7de5STim Shen 675403c667bSTim Shenenum class _StorageKind { 676403c667bSTim Shen _Scalar, 677403c667bSTim Shen _Array, 67838cd7de5STim Shen _VecExt, 679403c667bSTim Shen}; 680403c667bSTim Shen 681403c667bSTim Shentemplate <_StorageKind __kind, int _Np> 682403c667bSTim Shenstruct __simd_abi {}; 683403c667bSTim Shen 684403c667bSTim Shentemplate <class _Tp, class _Abi> 68538cd7de5STim Shenclass __simd_storage {}; 686403c667bSTim Shen 687403c667bSTim Shentemplate <class _Tp, int __num_element> 68838cd7de5STim Shenclass __simd_storage<_Tp, __simd_abi<_StorageKind::_Array, __num_element>> { 68938cd7de5STim Shen std::array<_Tp, __num_element> __storage_; 69038cd7de5STim Shen 69138cd7de5STim Shen template <class, class> 69238cd7de5STim Shen friend struct simd; 69338cd7de5STim Shen 69438cd7de5STim Shen template <class, class> 69538cd7de5STim Shen friend struct simd_mask; 69638cd7de5STim Shen 69738cd7de5STim Shenpublic: 698bdd5b948SNikolas Klauser _Tp __get(size_t __index) const noexcept { return __storage_[__index]; } 69938cd7de5STim Shen void __set(size_t __index, _Tp __val) noexcept { 70038cd7de5STim Shen __storage_[__index] = __val; 70138cd7de5STim Shen } 702403c667bSTim Shen}; 703403c667bSTim Shen 704403c667bSTim Shentemplate <class _Tp> 70538cd7de5STim Shenclass __simd_storage<_Tp, __simd_abi<_StorageKind::_Scalar, 1>> { 70638cd7de5STim Shen _Tp __storage_; 70738cd7de5STim Shen 70838cd7de5STim Shen template <class, class> 70938cd7de5STim Shen friend struct simd; 71038cd7de5STim Shen 71138cd7de5STim Shen template <class, class> 71238cd7de5STim Shen friend struct simd_mask; 71338cd7de5STim Shen 71438cd7de5STim Shenpublic: 715bdd5b948SNikolas Klauser _Tp __get(size_t __index) const noexcept { return (&__storage_)[__index]; } 71638cd7de5STim Shen void __set(size_t __index, _Tp __val) noexcept { 71738cd7de5STim Shen (&__storage_)[__index] = __val; 71838cd7de5STim Shen } 71938cd7de5STim Shen}; 72038cd7de5STim Shen 72138cd7de5STim Shen#ifndef _LIBCPP_HAS_NO_VECTOR_EXTENSION 72238cd7de5STim Shen 72338cd7de5STim Shenconstexpr size_t __floor_pow_of_2(size_t __val) { 72438cd7de5STim Shen return ((__val - 1) & __val) == 0 ? __val 72538cd7de5STim Shen : __floor_pow_of_2((__val - 1) & __val); 72638cd7de5STim Shen} 72738cd7de5STim Shen 72838cd7de5STim Shenconstexpr size_t __ceil_pow_of_2(size_t __val) { 72938cd7de5STim Shen return __val == 1 ? 1 : __floor_pow_of_2(__val - 1) << 1; 73038cd7de5STim Shen} 73138cd7de5STim Shen 73238cd7de5STim Shentemplate <class _Tp, size_t __bytes> 73338cd7de5STim Shenstruct __vec_ext_traits { 7345c703f0fSMarek Kurdej#if !defined(_LIBCPP_COMPILER_CLANG_BASED) 73538cd7de5STim Shen typedef _Tp type __attribute__((vector_size(__ceil_pow_of_2(__bytes)))); 73638cd7de5STim Shen#endif 73738cd7de5STim Shen}; 73838cd7de5STim Shen 7395c703f0fSMarek Kurdej#if defined(_LIBCPP_COMPILER_CLANG_BASED) 74038cd7de5STim Shen#define _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, _NUM_ELEMENT) \ 74138cd7de5STim Shen template <> \ 74238cd7de5STim Shen struct __vec_ext_traits<_TYPE, sizeof(_TYPE) * _NUM_ELEMENT> { \ 74338cd7de5STim Shen using type = \ 74438cd7de5STim Shen _TYPE __attribute__((vector_size(sizeof(_TYPE) * _NUM_ELEMENT))); \ 74538cd7de5STim Shen } 74638cd7de5STim Shen 74738cd7de5STim Shen#define _LIBCPP_SPECIALIZE_VEC_EXT_32(_TYPE) \ 74838cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 1); \ 74938cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 2); \ 75038cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 3); \ 75138cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 4); \ 75238cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 5); \ 75338cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 6); \ 75438cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 7); \ 75538cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 8); \ 75638cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 9); \ 75738cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 10); \ 75838cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 11); \ 75938cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 12); \ 76038cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 13); \ 76138cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 14); \ 76238cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 15); \ 76338cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 16); \ 76438cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 17); \ 76538cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 18); \ 76638cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 19); \ 76738cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 20); \ 76838cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 21); \ 76938cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 22); \ 77038cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 23); \ 77138cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 24); \ 77238cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 25); \ 77338cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 26); \ 77438cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 27); \ 77538cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 28); \ 77638cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 29); \ 77738cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 30); \ 77838cd7de5STim Shen _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 31); \ 779bdd5b948SNikolas Klauser _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 32) 78038cd7de5STim Shen 78138cd7de5STim Shen_LIBCPP_SPECIALIZE_VEC_EXT_32(char); 78238cd7de5STim Shen_LIBCPP_SPECIALIZE_VEC_EXT_32(char16_t); 78338cd7de5STim Shen_LIBCPP_SPECIALIZE_VEC_EXT_32(char32_t); 78438cd7de5STim Shen_LIBCPP_SPECIALIZE_VEC_EXT_32(wchar_t); 78538cd7de5STim Shen_LIBCPP_SPECIALIZE_VEC_EXT_32(signed char); 78638cd7de5STim Shen_LIBCPP_SPECIALIZE_VEC_EXT_32(signed short); 78738cd7de5STim Shen_LIBCPP_SPECIALIZE_VEC_EXT_32(signed int); 78838cd7de5STim Shen_LIBCPP_SPECIALIZE_VEC_EXT_32(signed long); 78938cd7de5STim Shen_LIBCPP_SPECIALIZE_VEC_EXT_32(signed long long); 79038cd7de5STim Shen_LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned char); 79138cd7de5STim Shen_LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned short); 79238cd7de5STim Shen_LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned int); 79338cd7de5STim Shen_LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned long); 79438cd7de5STim Shen_LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned long long); 79538cd7de5STim Shen_LIBCPP_SPECIALIZE_VEC_EXT_32(float); 79638cd7de5STim Shen_LIBCPP_SPECIALIZE_VEC_EXT_32(double); 79738cd7de5STim Shen_LIBCPP_SPECIALIZE_VEC_EXT_32(long double); 79838cd7de5STim Shen 79938cd7de5STim Shen#undef _LIBCPP_SPECIALIZE_VEC_EXT_32 80038cd7de5STim Shen#undef _LIBCPP_SPECIALIZE_VEC_EXT 80138cd7de5STim Shen#endif 80238cd7de5STim Shen 80338cd7de5STim Shentemplate <class _Tp, int __num_element> 80438cd7de5STim Shenclass __simd_storage<_Tp, __simd_abi<_StorageKind::_VecExt, __num_element>> { 80538cd7de5STim Shen using _StorageType = 80638cd7de5STim Shen typename __vec_ext_traits<_Tp, sizeof(_Tp) * __num_element>::type; 80738cd7de5STim Shen 80838cd7de5STim Shen _StorageType __storage_; 80938cd7de5STim Shen 81038cd7de5STim Shen template <class, class> 81138cd7de5STim Shen friend struct simd; 81238cd7de5STim Shen 81338cd7de5STim Shen template <class, class> 81438cd7de5STim Shen friend struct simd_mask; 81538cd7de5STim Shen 81638cd7de5STim Shenpublic: 817bdd5b948SNikolas Klauser _Tp __get(size_t __index) const noexcept { return __storage_[__index]; } 81838cd7de5STim Shen void __set(size_t __index, _Tp __val) noexcept { 81938cd7de5STim Shen __storage_[__index] = __val; 82038cd7de5STim Shen } 82138cd7de5STim Shen}; 82238cd7de5STim Shen 82338cd7de5STim Shen#endif // _LIBCPP_HAS_NO_VECTOR_EXTENSION 82438cd7de5STim Shen 82538cd7de5STim Shentemplate <class _Vp, class _Tp, class _Abi> 82638cd7de5STim Shenclass __simd_reference { 82738cd7de5STim Shen static_assert(std::is_same<_Vp, _Tp>::value, ""); 82838cd7de5STim Shen 82938cd7de5STim Shen template <class, class> 83038cd7de5STim Shen friend struct simd; 83138cd7de5STim Shen 83238cd7de5STim Shen template <class, class> 83338cd7de5STim Shen friend struct simd_mask; 83438cd7de5STim Shen 83538cd7de5STim Shen __simd_storage<_Tp, _Abi>* __ptr_; 83638cd7de5STim Shen size_t __index_; 83738cd7de5STim Shen 83838cd7de5STim Shen __simd_reference(__simd_storage<_Tp, _Abi>* __ptr, size_t __index) 83938cd7de5STim Shen : __ptr_(__ptr), __index_(__index) {} 84038cd7de5STim Shen 84138cd7de5STim Shen __simd_reference(const __simd_reference&) = default; 84238cd7de5STim Shen 84338cd7de5STim Shenpublic: 84438cd7de5STim Shen __simd_reference() = delete; 84538cd7de5STim Shen __simd_reference& operator=(const __simd_reference&) = delete; 84638cd7de5STim Shen 84738cd7de5STim Shen operator _Vp() const { return __ptr_->__get(__index_); } 84838cd7de5STim Shen 84938cd7de5STim Shen __simd_reference operator=(_Vp __value) && { 85038cd7de5STim Shen __ptr_->__set(__index_, __value); 85138cd7de5STim Shen return *this; 85238cd7de5STim Shen } 85338cd7de5STim Shen 85438cd7de5STim Shen __simd_reference operator++() && { 85538cd7de5STim Shen return std::move(*this) = __ptr_->__get(__index_) + 1; 85638cd7de5STim Shen } 85738cd7de5STim Shen 85838cd7de5STim Shen _Vp operator++(int) && { 85938cd7de5STim Shen auto __val = __ptr_->__get(__index_); 86038cd7de5STim Shen __ptr_->__set(__index_, __val + 1); 86138cd7de5STim Shen return __val; 86238cd7de5STim Shen } 86338cd7de5STim Shen 86438cd7de5STim Shen __simd_reference operator--() && { 86538cd7de5STim Shen return std::move(*this) = __ptr_->__get(__index_) - 1; 86638cd7de5STim Shen } 86738cd7de5STim Shen 86838cd7de5STim Shen _Vp operator--(int) && { 86938cd7de5STim Shen auto __val = __ptr_->__get(__index_); 87038cd7de5STim Shen __ptr_->__set(__index_, __val - 1); 87138cd7de5STim Shen return __val; 87238cd7de5STim Shen } 87338cd7de5STim Shen 87438cd7de5STim Shen __simd_reference operator+=(_Vp __value) && { 87538cd7de5STim Shen return std::move(*this) = __ptr_->__get(__index_) + __value; 87638cd7de5STim Shen } 87738cd7de5STim Shen 87838cd7de5STim Shen __simd_reference operator-=(_Vp __value) && { 87938cd7de5STim Shen return std::move(*this) = __ptr_->__get(__index_) - __value; 88038cd7de5STim Shen } 88138cd7de5STim Shen 88238cd7de5STim Shen __simd_reference operator*=(_Vp __value) && { 88338cd7de5STim Shen return std::move(*this) = __ptr_->__get(__index_) * __value; 88438cd7de5STim Shen } 88538cd7de5STim Shen 88638cd7de5STim Shen __simd_reference operator/=(_Vp __value) && { 88738cd7de5STim Shen return std::move(*this) = __ptr_->__get(__index_) / __value; 88838cd7de5STim Shen } 88938cd7de5STim Shen 89038cd7de5STim Shen __simd_reference operator%=(_Vp __value) && { 89138cd7de5STim Shen return std::move(*this) = __ptr_->__get(__index_) % __value; 89238cd7de5STim Shen } 89338cd7de5STim Shen 89438cd7de5STim Shen __simd_reference operator>>=(_Vp __value) && { 89538cd7de5STim Shen return std::move(*this) = __ptr_->__get(__index_) >> __value; 89638cd7de5STim Shen } 89738cd7de5STim Shen 89838cd7de5STim Shen __simd_reference operator<<=(_Vp __value) && { 89938cd7de5STim Shen return std::move(*this) = __ptr_->__get(__index_) << __value; 90038cd7de5STim Shen } 90138cd7de5STim Shen 90238cd7de5STim Shen __simd_reference operator&=(_Vp __value) && { 90338cd7de5STim Shen return std::move(*this) = __ptr_->__get(__index_) & __value; 90438cd7de5STim Shen } 90538cd7de5STim Shen 90638cd7de5STim Shen __simd_reference operator|=(_Vp __value) && { 90738cd7de5STim Shen return std::move(*this) = __ptr_->__get(__index_) | __value; 90838cd7de5STim Shen } 90938cd7de5STim Shen 91038cd7de5STim Shen __simd_reference operator^=(_Vp __value) && { 91138cd7de5STim Shen return std::move(*this) = __ptr_->__get(__index_) ^ __value; 91238cd7de5STim Shen } 913403c667bSTim Shen}; 914403c667bSTim Shen 915403c667bSTim Shentemplate <class _To, class _From> 916403c667bSTim Shenconstexpr decltype(_To{std::declval<_From>()}, true) 917403c667bSTim Shen__is_non_narrowing_convertible_impl(_From) { 918403c667bSTim Shen return true; 919403c667bSTim Shen} 920403c667bSTim Shen 921403c667bSTim Shentemplate <class _To> 922403c667bSTim Shenconstexpr bool __is_non_narrowing_convertible_impl(...) { 923403c667bSTim Shen return false; 924403c667bSTim Shen} 925403c667bSTim Shen 926403c667bSTim Shentemplate <class _From, class _To> 927403c667bSTim Shenconstexpr typename std::enable_if<std::is_arithmetic<_To>::value && 928403c667bSTim Shen std::is_arithmetic<_From>::value, 929403c667bSTim Shen bool>::type 930403c667bSTim Shen__is_non_narrowing_arithmetic_convertible() { 931403c667bSTim Shen return __is_non_narrowing_convertible_impl<_To>(_From{}); 932403c667bSTim Shen} 933403c667bSTim Shen 934403c667bSTim Shentemplate <class _From, class _To> 935403c667bSTim Shenconstexpr typename std::enable_if<!(std::is_arithmetic<_To>::value && 936403c667bSTim Shen std::is_arithmetic<_From>::value), 937403c667bSTim Shen bool>::type 938403c667bSTim Shen__is_non_narrowing_arithmetic_convertible() { 939403c667bSTim Shen return false; 940403c667bSTim Shen} 941403c667bSTim Shen 942403c667bSTim Shentemplate <class _Tp> 943403c667bSTim Shenconstexpr _Tp __variadic_sum() { 944403c667bSTim Shen return _Tp{}; 945403c667bSTim Shen} 946403c667bSTim Shen 947403c667bSTim Shentemplate <class _Tp, class _Up, class... _Args> 948403c667bSTim Shenconstexpr _Tp __variadic_sum(_Up __first, _Args... __rest) { 949403c667bSTim Shen return static_cast<_Tp>(__first) + __variadic_sum<_Tp>(__rest...); 950403c667bSTim Shen} 951403c667bSTim Shen 95238cd7de5STim Shentemplate <class _Tp> 95338cd7de5STim Shenstruct __nodeduce { 95438cd7de5STim Shen using type = _Tp; 95538cd7de5STim Shen}; 95638cd7de5STim Shen 95738cd7de5STim Shentemplate <class _Tp> 95838cd7de5STim Shenconstexpr bool __vectorizable() { 95938cd7de5STim Shen return std::is_arithmetic<_Tp>::value && !std::is_const<_Tp>::value && 96038cd7de5STim Shen !std::is_volatile<_Tp>::value && !std::is_same<_Tp, bool>::value; 96138cd7de5STim Shen} 96238cd7de5STim Shen 963403c667bSTim Shen_LIBCPP_END_NAMESPACE_EXPERIMENTAL_SIMD 964403c667bSTim Shen_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_SIMD_ABI 965403c667bSTim Shen 966403c667bSTim Shenusing scalar = __simd_abi<_StorageKind::_Scalar, 1>; 967403c667bSTim Shen 968403c667bSTim Shentemplate <int _Np> 969403c667bSTim Shenusing fixed_size = __simd_abi<_StorageKind::_Array, _Np>; 970403c667bSTim Shen 971403c667bSTim Shentemplate <class _Tp> 972cb793e1aSLouis Dionneinline constexpr size_t max_fixed_size = 32; 97338cd7de5STim Shen 974403c667bSTim Shentemplate <class _Tp> 975403c667bSTim Shenusing compatible = fixed_size<16 / sizeof(_Tp)>; 97638cd7de5STim Shen 97738cd7de5STim Shen#ifndef _LIBCPP_HAS_NO_VECTOR_EXTENSION 978403c667bSTim Shentemplate <class _Tp> 97938cd7de5STim Shenusing native = __simd_abi<_StorageKind::_VecExt, 98038cd7de5STim Shen _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES / sizeof(_Tp)>; 98138cd7de5STim Shen#else 98238cd7de5STim Shentemplate <class _Tp> 98338cd7de5STim Shenusing native = 98438cd7de5STim Shen fixed_size<_Tp, _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES / sizeof(_Tp)>; 98538cd7de5STim Shen#endif // _LIBCPP_HAS_NO_VECTOR_EXTENSION 986403c667bSTim Shen 987403c667bSTim Shen_LIBCPP_END_NAMESPACE_EXPERIMENTAL_SIMD_ABI 988403c667bSTim Shen_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_SIMD 989403c667bSTim Shen 990403c667bSTim Shentemplate <class _Tp, class _Abi = simd_abi::compatible<_Tp>> 991403c667bSTim Shenclass simd; 992403c667bSTim Shentemplate <class _Tp, class _Abi = simd_abi::compatible<_Tp>> 993403c667bSTim Shenclass simd_mask; 994403c667bSTim Shen 995403c667bSTim Shenstruct element_aligned_tag {}; 996403c667bSTim Shenstruct vector_aligned_tag {}; 997403c667bSTim Shentemplate <size_t> 998403c667bSTim Shenstruct overaligned_tag {}; 999cb793e1aSLouis Dionneinline constexpr element_aligned_tag element_aligned{}; 1000cb793e1aSLouis Dionneinline constexpr vector_aligned_tag vector_aligned{}; 1001403c667bSTim Shentemplate <size_t _Np> 1002cb793e1aSLouis Dionneinline constexpr overaligned_tag<_Np> overaligned{}; 1003403c667bSTim Shen 1004403c667bSTim Shen// traits [simd.traits] 1005403c667bSTim Shentemplate <class _Tp> 1006403c667bSTim Shenstruct is_abi_tag : std::integral_constant<bool, false> {}; 1007403c667bSTim Shen 1008403c667bSTim Shentemplate <_StorageKind __kind, int _Np> 1009403c667bSTim Shenstruct is_abi_tag<__simd_abi<__kind, _Np>> 1010403c667bSTim Shen : std::integral_constant<bool, true> {}; 1011403c667bSTim Shen 1012403c667bSTim Shentemplate <class _Tp> 1013403c667bSTim Shenstruct is_simd : std::integral_constant<bool, false> {}; 1014403c667bSTim Shen 1015403c667bSTim Shentemplate <class _Tp, class _Abi> 1016403c667bSTim Shenstruct is_simd<simd<_Tp, _Abi>> : std::integral_constant<bool, true> {}; 1017403c667bSTim Shen 1018403c667bSTim Shentemplate <class _Tp> 1019403c667bSTim Shenstruct is_simd_mask : std::integral_constant<bool, false> {}; 1020403c667bSTim Shen 1021403c667bSTim Shentemplate <class _Tp, class _Abi> 1022403c667bSTim Shenstruct is_simd_mask<simd_mask<_Tp, _Abi>> : std::integral_constant<bool, true> { 1023403c667bSTim Shen}; 1024403c667bSTim Shen 1025403c667bSTim Shentemplate <class _Tp> 1026403c667bSTim Shenstruct is_simd_flag_type : std::integral_constant<bool, false> {}; 1027403c667bSTim Shen 1028403c667bSTim Shentemplate <> 1029403c667bSTim Shenstruct is_simd_flag_type<element_aligned_tag> 1030403c667bSTim Shen : std::integral_constant<bool, true> {}; 1031403c667bSTim Shen 1032403c667bSTim Shentemplate <> 1033403c667bSTim Shenstruct is_simd_flag_type<vector_aligned_tag> 1034403c667bSTim Shen : std::integral_constant<bool, true> {}; 1035403c667bSTim Shen 1036403c667bSTim Shentemplate <size_t _Align> 1037403c667bSTim Shenstruct is_simd_flag_type<overaligned_tag<_Align>> 1038403c667bSTim Shen : std::integral_constant<bool, true> {}; 1039403c667bSTim Shen 1040403c667bSTim Shentemplate <class _Tp> 1041cb793e1aSLouis Dionneinline constexpr bool is_abi_tag_v = is_abi_tag<_Tp>::value; 1042403c667bSTim Shentemplate <class _Tp> 1043cb793e1aSLouis Dionneinline constexpr bool is_simd_v = is_simd<_Tp>::value; 1044403c667bSTim Shentemplate <class _Tp> 1045cb793e1aSLouis Dionneinline constexpr bool is_simd_mask_v = is_simd_mask<_Tp>::value; 1046403c667bSTim Shentemplate <class _Tp> 1047cb793e1aSLouis Dionneinline constexpr bool is_simd_flag_type_v = is_simd_flag_type<_Tp>::value; 1048403c667bSTim Shentemplate <class _Tp, size_t _Np> 1049403c667bSTim Shenstruct abi_for_size { 1050403c667bSTim Shen using type = simd_abi::fixed_size<_Np>; 1051403c667bSTim Shen}; 1052403c667bSTim Shentemplate <class _Tp, size_t _Np> 1053403c667bSTim Shenusing abi_for_size_t = typename abi_for_size<_Tp, _Np>::type; 1054403c667bSTim Shen 1055403c667bSTim Shentemplate <class _Tp, class _Abi = simd_abi::compatible<_Tp>> 1056403c667bSTim Shenstruct simd_size; 1057403c667bSTim Shen 1058403c667bSTim Shentemplate <class _Tp, _StorageKind __kind, int _Np> 1059403c667bSTim Shenstruct simd_size<_Tp, __simd_abi<__kind, _Np>> 1060403c667bSTim Shen : std::integral_constant<size_t, _Np> { 1061403c667bSTim Shen static_assert( 1062403c667bSTim Shen std::is_arithmetic<_Tp>::value && 1063403c667bSTim Shen !std::is_same<typename std::remove_const<_Tp>::type, bool>::value, 1064403c667bSTim Shen "Element type should be vectorizable"); 1065403c667bSTim Shen}; 1066403c667bSTim Shen 106738cd7de5STim Shen// TODO: implement it. 1068403c667bSTim Shentemplate <class _Tp, class _Up = typename _Tp::value_type> 1069403c667bSTim Shenstruct memory_alignment; 1070403c667bSTim Shen 1071403c667bSTim Shentemplate <class _Tp, class _Abi = simd_abi::compatible<_Tp>> 1072cb793e1aSLouis Dionneinline constexpr size_t simd_size_v = simd_size<_Tp, _Abi>::value; 1073403c667bSTim Shen 1074403c667bSTim Shentemplate <class _Tp, class _Up = typename _Tp::value_type> 1075cb793e1aSLouis Dionneinline constexpr size_t memory_alignment_v = memory_alignment<_Tp, _Up>::value; 1076403c667bSTim Shen 1077403c667bSTim Shen// class template simd [simd.class] 1078403c667bSTim Shentemplate <class _Tp> 1079403c667bSTim Shenusing native_simd = simd<_Tp, simd_abi::native<_Tp>>; 1080403c667bSTim Shentemplate <class _Tp, int _Np> 1081403c667bSTim Shenusing fixed_size_simd = simd<_Tp, simd_abi::fixed_size<_Np>>; 1082403c667bSTim Shen 1083403c667bSTim Shen// class template simd_mask [simd.mask.class] 1084403c667bSTim Shentemplate <class _Tp> 1085403c667bSTim Shenusing native_simd_mask = simd_mask<_Tp, simd_abi::native<_Tp>>; 1086403c667bSTim Shen 1087403c667bSTim Shentemplate <class _Tp, int _Np> 1088403c667bSTim Shenusing fixed_size_simd_mask = simd_mask<_Tp, simd_abi::fixed_size<_Np>>; 1089403c667bSTim Shen 1090403c667bSTim Shen// casts [simd.casts] 1091403c667bSTim Shentemplate <class _Tp> 1092403c667bSTim Shenstruct __static_simd_cast_traits { 1093403c667bSTim Shen template <class _Up, class _Abi> 1094403c667bSTim Shen static simd<_Tp, _Abi> __apply(const simd<_Up, _Abi>& __v); 1095403c667bSTim Shen}; 1096403c667bSTim Shen 1097403c667bSTim Shentemplate <class _Tp, class _NewAbi> 1098403c667bSTim Shenstruct __static_simd_cast_traits<simd<_Tp, _NewAbi>> { 1099403c667bSTim Shen template <class _Up, class _Abi> 1100403c667bSTim Shen static typename std::enable_if<simd<_Up, _Abi>::size() == 1101403c667bSTim Shen simd<_Tp, _NewAbi>::size(), 1102403c667bSTim Shen simd<_Tp, _NewAbi>>::type 1103403c667bSTim Shen __apply(const simd<_Up, _Abi>& __v); 1104403c667bSTim Shen}; 1105403c667bSTim Shen 1106403c667bSTim Shentemplate <class _Tp> 1107403c667bSTim Shenstruct __simd_cast_traits { 1108403c667bSTim Shen template <class _Up, class _Abi> 1109403c667bSTim Shen static typename std::enable_if< 1110403c667bSTim Shen __is_non_narrowing_arithmetic_convertible<_Up, _Tp>(), 1111403c667bSTim Shen simd<_Tp, _Abi>>::type 1112403c667bSTim Shen __apply(const simd<_Up, _Abi>& __v); 1113403c667bSTim Shen}; 1114403c667bSTim Shen 1115403c667bSTim Shentemplate <class _Tp, class _NewAbi> 1116403c667bSTim Shenstruct __simd_cast_traits<simd<_Tp, _NewAbi>> { 1117403c667bSTim Shen template <class _Up, class _Abi> 1118403c667bSTim Shen static typename std::enable_if< 1119403c667bSTim Shen __is_non_narrowing_arithmetic_convertible<_Up, _Tp>() && 1120403c667bSTim Shen simd<_Up, _Abi>::size() == simd<_Tp, _NewAbi>::size(), 1121403c667bSTim Shen simd<_Tp, _NewAbi>>::type 1122403c667bSTim Shen __apply(const simd<_Up, _Abi>& __v); 1123403c667bSTim Shen}; 1124403c667bSTim Shen 1125403c667bSTim Shentemplate <class _Tp, class _Up, class _Abi> 1126403c667bSTim Shenauto simd_cast(const simd<_Up, _Abi>& __v) 1127403c667bSTim Shen -> decltype(__simd_cast_traits<_Tp>::__apply(__v)) { 1128403c667bSTim Shen return __simd_cast_traits<_Tp>::__apply(__v); 1129403c667bSTim Shen} 1130403c667bSTim Shen 1131403c667bSTim Shentemplate <class _Tp, class _Up, class _Abi> 1132403c667bSTim Shenauto static_simd_cast(const simd<_Up, _Abi>& __v) 1133403c667bSTim Shen -> decltype(__static_simd_cast_traits<_Tp>::__apply(__v)) { 1134403c667bSTim Shen return __static_simd_cast_traits<_Tp>::__apply(__v); 1135403c667bSTim Shen} 1136403c667bSTim Shen 1137403c667bSTim Shentemplate <class _Tp, class _Abi> 1138403c667bSTim Shenfixed_size_simd<_Tp, simd_size<_Tp, _Abi>::value> 1139403c667bSTim Shento_fixed_size(const simd<_Tp, _Abi>&) noexcept; 1140403c667bSTim Shen 1141403c667bSTim Shentemplate <class _Tp, class _Abi> 1142403c667bSTim Shenfixed_size_simd_mask<_Tp, simd_size<_Tp, _Abi>::value> 1143403c667bSTim Shento_fixed_size(const simd_mask<_Tp, _Abi>&) noexcept; 1144403c667bSTim Shen 1145403c667bSTim Shentemplate <class _Tp, size_t _Np> 1146403c667bSTim Shennative_simd<_Tp> to_native(const fixed_size_simd<_Tp, _Np>&) noexcept; 1147403c667bSTim Shen 1148403c667bSTim Shentemplate <class _Tp, size_t _Np> 1149403c667bSTim Shennative_simd_mask<_Tp> to_native(const fixed_size_simd_mask<_Tp, _Np>&) noexcept; 1150403c667bSTim Shen 1151403c667bSTim Shentemplate <class _Tp, size_t _Np> 1152403c667bSTim Shensimd<_Tp> to_compatible(const fixed_size_simd<_Tp, _Np>&) noexcept; 1153403c667bSTim Shen 1154403c667bSTim Shentemplate <class _Tp, size_t _Np> 1155403c667bSTim Shensimd_mask<_Tp> to_compatible(const fixed_size_simd_mask<_Tp, _Np>&) noexcept; 1156403c667bSTim Shen 1157403c667bSTim Shentemplate <size_t... __sizes, class _Tp, class _Abi> 1158403c667bSTim Shentuple<simd<_Tp, abi_for_size_t<_Tp, __sizes>>...> split(const simd<_Tp, _Abi>&); 1159403c667bSTim Shen 1160403c667bSTim Shentemplate <size_t... __sizes, class _Tp, class _Abi> 1161403c667bSTim Shentuple<simd_mask<_Tp, abi_for_size_t<_Tp, __sizes>>...> 1162403c667bSTim Shensplit(const simd_mask<_Tp, _Abi>&); 1163403c667bSTim Shen 1164403c667bSTim Shentemplate <class _SimdType, class _Abi> 1165403c667bSTim Shenarray<_SimdType, simd_size<typename _SimdType::value_type, _Abi>::value / 1166403c667bSTim Shen _SimdType::size()> 1167403c667bSTim Shensplit(const simd<typename _SimdType::value_type, _Abi>&); 1168403c667bSTim Shen 1169403c667bSTim Shentemplate <class _SimdType, class _Abi> 1170403c667bSTim Shenarray<_SimdType, simd_size<typename _SimdType::value_type, _Abi>::value / 1171403c667bSTim Shen _SimdType::size()> 1172403c667bSTim Shensplit(const simd_mask<typename _SimdType::value_type, _Abi>&); 1173403c667bSTim Shen 1174403c667bSTim Shentemplate <class _Tp, class... _Abis> 1175403c667bSTim Shensimd<_Tp, abi_for_size_t<_Tp, __variadic_sum(simd_size<_Tp, _Abis>::value...)>> 1176403c667bSTim Shenconcat(const simd<_Tp, _Abis>&...); 1177403c667bSTim Shen 1178403c667bSTim Shentemplate <class _Tp, class... _Abis> 1179403c667bSTim Shensimd_mask<_Tp, 1180403c667bSTim Shen abi_for_size_t<_Tp, __variadic_sum(simd_size<_Tp, _Abis>::value...)>> 1181403c667bSTim Shenconcat(const simd_mask<_Tp, _Abis>&...); 1182403c667bSTim Shen 1183403c667bSTim Shen// reductions [simd.mask.reductions] 1184403c667bSTim Shentemplate <class _Tp, class _Abi> 1185403c667bSTim Shenbool all_of(const simd_mask<_Tp, _Abi>&) noexcept; 1186403c667bSTim Shentemplate <class _Tp, class _Abi> 1187403c667bSTim Shenbool any_of(const simd_mask<_Tp, _Abi>&) noexcept; 1188403c667bSTim Shentemplate <class _Tp, class _Abi> 1189403c667bSTim Shenbool none_of(const simd_mask<_Tp, _Abi>&) noexcept; 1190403c667bSTim Shentemplate <class _Tp, class _Abi> 1191403c667bSTim Shenbool some_of(const simd_mask<_Tp, _Abi>&) noexcept; 1192403c667bSTim Shentemplate <class _Tp, class _Abi> 1193403c667bSTim Shenint popcount(const simd_mask<_Tp, _Abi>&) noexcept; 1194403c667bSTim Shentemplate <class _Tp, class _Abi> 1195403c667bSTim Shenint find_first_set(const simd_mask<_Tp, _Abi>&); 1196403c667bSTim Shentemplate <class _Tp, class _Abi> 1197403c667bSTim Shenint find_last_set(const simd_mask<_Tp, _Abi>&); 1198403c667bSTim Shenbool all_of(bool) noexcept; 1199403c667bSTim Shenbool any_of(bool) noexcept; 1200403c667bSTim Shenbool none_of(bool) noexcept; 1201403c667bSTim Shenbool some_of(bool) noexcept; 1202403c667bSTim Shenint popcount(bool) noexcept; 1203403c667bSTim Shenint find_first_set(bool) noexcept; 1204403c667bSTim Shenint find_last_set(bool) noexcept; 1205403c667bSTim Shen 1206403c667bSTim Shen// masked assignment [simd.whereexpr] 1207403c667bSTim Shentemplate <class _MaskType, class _Tp> 1208403c667bSTim Shenclass const_where_expression; 1209403c667bSTim Shentemplate <class _MaskType, class _Tp> 1210403c667bSTim Shenclass where_expression; 1211403c667bSTim Shen 1212403c667bSTim Shen// masked assignment [simd.mask.where] 1213403c667bSTim Shentemplate <class _Tp, class _Abi> 1214403c667bSTim Shenwhere_expression<simd_mask<_Tp, _Abi>, simd<_Tp, _Abi>> 1215403c667bSTim Shenwhere(const typename simd<_Tp, _Abi>::mask_type&, simd<_Tp, _Abi>&) noexcept; 1216403c667bSTim Shen 1217403c667bSTim Shentemplate <class _Tp, class _Abi> 1218403c667bSTim Shenconst_where_expression<simd_mask<_Tp, _Abi>, const simd<_Tp, _Abi>> 1219403c667bSTim Shenwhere(const typename simd<_Tp, _Abi>::mask_type&, 1220403c667bSTim Shen const simd<_Tp, _Abi>&) noexcept; 1221403c667bSTim Shen 1222403c667bSTim Shentemplate <class _Tp, class _Abi> 1223403c667bSTim Shenwhere_expression<simd_mask<_Tp, _Abi>, simd_mask<_Tp, _Abi>> 1224403c667bSTim Shenwhere(const typename __nodeduce<simd_mask<_Tp, _Abi>>::type&, 1225403c667bSTim Shen simd_mask<_Tp, _Abi>&) noexcept; 1226403c667bSTim Shen 1227403c667bSTim Shentemplate <class _Tp, class _Abi> 1228403c667bSTim Shenconst_where_expression<simd_mask<_Tp, _Abi>, const simd_mask<_Tp, _Abi>> 1229403c667bSTim Shenwhere(const typename __nodeduce<simd_mask<_Tp, _Abi>>::type&, 1230403c667bSTim Shen const simd_mask<_Tp, _Abi>&) noexcept; 1231403c667bSTim Shen 1232403c667bSTim Shentemplate <class _Tp> 1233403c667bSTim Shenwhere_expression<bool, _Tp> where(bool, _Tp&) noexcept; 1234403c667bSTim Shen 1235403c667bSTim Shentemplate <class _Tp> 1236403c667bSTim Shenconst_where_expression<bool, const _Tp> where(bool, const _Tp&) noexcept; 1237403c667bSTim Shen 1238403c667bSTim Shen// reductions [simd.reductions] 1239403c667bSTim Shentemplate <class _Tp, class _Abi, class _BinaryOp = std::plus<_Tp>> 1240403c667bSTim Shen_Tp reduce(const simd<_Tp, _Abi>&, _BinaryOp = _BinaryOp()); 1241403c667bSTim Shen 1242403c667bSTim Shentemplate <class _MaskType, class _SimdType, class _BinaryOp> 1243403c667bSTim Shentypename _SimdType::value_type 1244403c667bSTim Shenreduce(const const_where_expression<_MaskType, _SimdType>&, 1245*b48c5010SNikolas Klauser typename _SimdType::value_type __neutral_element, _BinaryOp); 1246403c667bSTim Shen 1247403c667bSTim Shentemplate <class _MaskType, class _SimdType> 1248403c667bSTim Shentypename _SimdType::value_type 1249403c667bSTim Shenreduce(const const_where_expression<_MaskType, _SimdType>&, 1250*b48c5010SNikolas Klauser plus<typename _SimdType::value_type> = {}); 1251403c667bSTim Shen 1252403c667bSTim Shentemplate <class _MaskType, class _SimdType> 1253403c667bSTim Shentypename _SimdType::value_type 1254403c667bSTim Shenreduce(const const_where_expression<_MaskType, _SimdType>&, 1255*b48c5010SNikolas Klauser multiplies<typename _SimdType::value_type>); 1256403c667bSTim Shen 1257403c667bSTim Shentemplate <class _MaskType, class _SimdType> 1258403c667bSTim Shentypename _SimdType::value_type 1259403c667bSTim Shenreduce(const const_where_expression<_MaskType, _SimdType>&, 1260*b48c5010SNikolas Klauser bit_and<typename _SimdType::value_type>); 1261403c667bSTim Shen 1262403c667bSTim Shentemplate <class _MaskType, class _SimdType> 1263403c667bSTim Shentypename _SimdType::value_type 1264403c667bSTim Shenreduce(const const_where_expression<_MaskType, _SimdType>&, 1265*b48c5010SNikolas Klauser bit_or<typename _SimdType::value_type>); 1266403c667bSTim Shen 1267403c667bSTim Shentemplate <class _MaskType, class _SimdType> 1268403c667bSTim Shentypename _SimdType::value_type 1269403c667bSTim Shenreduce(const const_where_expression<_MaskType, _SimdType>&, 1270*b48c5010SNikolas Klauser bit_xor<typename _SimdType::value_type>); 1271403c667bSTim Shen 1272403c667bSTim Shentemplate <class _Tp, class _Abi> 1273403c667bSTim Shen_Tp hmin(const simd<_Tp, _Abi>&); 1274403c667bSTim Shentemplate <class _MaskType, class _SimdType> 1275403c667bSTim Shentypename _SimdType::value_type 1276403c667bSTim Shenhmin(const const_where_expression<_MaskType, _SimdType>&); 1277403c667bSTim Shentemplate <class _Tp, class _Abi> 1278403c667bSTim Shen_Tp hmax(const simd<_Tp, _Abi>&); 1279403c667bSTim Shentemplate <class _MaskType, class _SimdType> 1280403c667bSTim Shentypename _SimdType::value_type 1281403c667bSTim Shenhmax(const const_where_expression<_MaskType, _SimdType>&); 1282403c667bSTim Shen 1283403c667bSTim Shen// algorithms [simd.alg] 1284403c667bSTim Shentemplate <class _Tp, class _Abi> 1285403c667bSTim Shensimd<_Tp, _Abi> min(const simd<_Tp, _Abi>&, const simd<_Tp, _Abi>&) noexcept; 1286403c667bSTim Shen 1287403c667bSTim Shentemplate <class _Tp, class _Abi> 1288403c667bSTim Shensimd<_Tp, _Abi> max(const simd<_Tp, _Abi>&, const simd<_Tp, _Abi>&) noexcept; 1289403c667bSTim Shen 1290403c667bSTim Shentemplate <class _Tp, class _Abi> 1291403c667bSTim Shenstd::pair<simd<_Tp, _Abi>, simd<_Tp, _Abi>> 1292403c667bSTim Shenminmax(const simd<_Tp, _Abi>&, const simd<_Tp, _Abi>&) noexcept; 1293403c667bSTim Shen 1294403c667bSTim Shentemplate <class _Tp, class _Abi> 1295403c667bSTim Shensimd<_Tp, _Abi> clamp(const simd<_Tp, _Abi>&, const simd<_Tp, _Abi>&, 1296403c667bSTim Shen const simd<_Tp, _Abi>&); 1297403c667bSTim Shen 1298403c667bSTim Shen// [simd.whereexpr] 1299403c667bSTim Shen// TODO implement where expressions. 1300403c667bSTim Shentemplate <class _MaskType, class _Tp> 1301403c667bSTim Shenclass const_where_expression { 1302403c667bSTim Shenpublic: 1303403c667bSTim Shen const_where_expression(const const_where_expression&) = delete; 1304403c667bSTim Shen const_where_expression& operator=(const const_where_expression&) = delete; 1305403c667bSTim Shen typename remove_const<_Tp>::type operator-() const&&; 1306403c667bSTim Shen template <class _Up, class _Flags> 1307403c667bSTim Shen void copy_to(_Up*, _Flags) const&&; 1308403c667bSTim Shen}; 1309403c667bSTim Shen 1310403c667bSTim Shentemplate <class _MaskType, class _Tp> 1311403c667bSTim Shenclass where_expression : public const_where_expression<_MaskType, _Tp> { 1312403c667bSTim Shenpublic: 1313403c667bSTim Shen where_expression(const where_expression&) = delete; 1314403c667bSTim Shen where_expression& operator=(const where_expression&) = delete; 1315403c667bSTim Shen template <class _Up> 1316403c667bSTim Shen void operator=(_Up&&); 1317403c667bSTim Shen template <class _Up> 1318403c667bSTim Shen void operator+=(_Up&&); 1319403c667bSTim Shen template <class _Up> 1320403c667bSTim Shen void operator-=(_Up&&); 1321403c667bSTim Shen template <class _Up> 1322403c667bSTim Shen void operator*=(_Up&&); 1323403c667bSTim Shen template <class _Up> 1324403c667bSTim Shen void operator/=(_Up&&); 1325403c667bSTim Shen template <class _Up> 1326403c667bSTim Shen void operator%=(_Up&&); 1327403c667bSTim Shen template <class _Up> 1328403c667bSTim Shen void operator&=(_Up&&); 1329403c667bSTim Shen template <class _Up> 1330403c667bSTim Shen void operator|=(_Up&&); 1331403c667bSTim Shen template <class _Up> 1332403c667bSTim Shen void operator^=(_Up&&); 1333403c667bSTim Shen template <class _Up> 1334403c667bSTim Shen void operator<<=(_Up&&); 1335403c667bSTim Shen template <class _Up> 1336403c667bSTim Shen void operator>>=(_Up&&); 1337403c667bSTim Shen void operator++(); 1338403c667bSTim Shen void operator++(int); 1339403c667bSTim Shen void operator--(); 1340403c667bSTim Shen void operator--(int); 1341403c667bSTim Shen template <class _Up, class _Flags> 1342403c667bSTim Shen void copy_from(const _Up*, _Flags); 1343403c667bSTim Shen}; 1344403c667bSTim Shen 1345403c667bSTim Shen// [simd.class] 1346403c667bSTim Shen// TODO: implement simd 1347403c667bSTim Shentemplate <class _Tp, class _Abi> 1348403c667bSTim Shenclass simd { 134938cd7de5STim Shenpublic: 135038cd7de5STim Shen using value_type = _Tp; 135138cd7de5STim Shen using reference = __simd_reference<_Tp, _Tp, _Abi>; 135238cd7de5STim Shen using mask_type = simd_mask<_Tp, _Abi>; 135338cd7de5STim Shen using abi_type = _Abi; 135438cd7de5STim Shen 135538cd7de5STim Shen simd() = default; 135638cd7de5STim Shen simd(const simd&) = default; 135738cd7de5STim Shen simd& operator=(const simd&) = default; 135838cd7de5STim Shen 135938cd7de5STim Shen static constexpr size_t size() noexcept { 136038cd7de5STim Shen return simd_size<_Tp, _Abi>::value; 136138cd7de5STim Shen } 136238cd7de5STim Shen 1363403c667bSTim Shenprivate: 136438cd7de5STim Shen __simd_storage<_Tp, _Abi> __s_; 136538cd7de5STim Shen 1366403c667bSTim Shen template <class _Up> 1367403c667bSTim Shen static constexpr bool __can_broadcast() { 1368403c667bSTim Shen return (std::is_arithmetic<_Up>::value && 1369403c667bSTim Shen __is_non_narrowing_arithmetic_convertible<_Up, _Tp>()) || 1370403c667bSTim Shen (!std::is_arithmetic<_Up>::value && 1371403c667bSTim Shen std::is_convertible<_Up, _Tp>::value) || 1372403c667bSTim Shen std::is_same<typename std::remove_const<_Up>::type, int>::value || 1373403c667bSTim Shen (std::is_same<typename std::remove_const<_Up>::type, 1374403c667bSTim Shen unsigned int>::value && 1375403c667bSTim Shen std::is_unsigned<_Tp>::value); 1376403c667bSTim Shen } 1377403c667bSTim Shen 137838cd7de5STim Shen template <class _Generator, size_t... __indicies> 137938cd7de5STim Shen static constexpr decltype( 138038cd7de5STim Shen std::forward_as_tuple(std::declval<_Generator>()( 138138cd7de5STim Shen std::integral_constant<size_t, __indicies>())...), 138238cd7de5STim Shen bool()) 138338cd7de5STim Shen __can_generate(std::index_sequence<__indicies...>) { 138438cd7de5STim Shen return !__variadic_sum<bool>( 138538cd7de5STim Shen !__can_broadcast<decltype(std::declval<_Generator>()( 138638cd7de5STim Shen std::integral_constant<size_t, __indicies>()))>()...); 13876f33ea4eSTim Shen } 13886f33ea4eSTim Shen 138938cd7de5STim Shen template <class _Generator> 139038cd7de5STim Shen static bool __can_generate(...) { 139138cd7de5STim Shen return false; 139238cd7de5STim Shen } 13936f33ea4eSTim Shen 139438cd7de5STim Shen template <class _Generator, size_t... __indicies> 139538cd7de5STim Shen void __generator_init(_Generator&& __g, std::index_sequence<__indicies...>) { 139638cd7de5STim Shen int __not_used[]{((*this)[__indicies] = 139738cd7de5STim Shen __g(std::integral_constant<size_t, __indicies>()), 139838cd7de5STim Shen 0)...}; 139938cd7de5STim Shen (void)__not_used; 140038cd7de5STim Shen } 140138cd7de5STim Shen 140238cd7de5STim Shenpublic: 1403403c667bSTim Shen // implicit type conversion constructor 1404403c667bSTim Shen template <class _Up, 1405403c667bSTim Shen class = typename std::enable_if< 1406403c667bSTim Shen std::is_same<_Abi, simd_abi::fixed_size<size()>>::value && 1407403c667bSTim Shen __is_non_narrowing_arithmetic_convertible<_Up, _Tp>()>::type> 140838cd7de5STim Shen simd(const simd<_Up, simd_abi::fixed_size<size()>>& __v) { 140938cd7de5STim Shen for (size_t __i = 0; __i < size(); __i++) { 141038cd7de5STim Shen (*this)[__i] = static_cast<_Tp>(__v[__i]); 141138cd7de5STim Shen } 141238cd7de5STim Shen } 1413403c667bSTim Shen 1414403c667bSTim Shen // implicit broadcast constructor 1415403c667bSTim Shen template <class _Up, 1416403c667bSTim Shen class = typename std::enable_if<__can_broadcast<_Up>()>::type> 141738cd7de5STim Shen simd(_Up&& __rv) { 141838cd7de5STim Shen auto __v = static_cast<_Tp>(__rv); 141938cd7de5STim Shen for (size_t __i = 0; __i < size(); __i++) { 142038cd7de5STim Shen (*this)[__i] = __v; 142138cd7de5STim Shen } 142238cd7de5STim Shen } 1423403c667bSTim Shen 1424403c667bSTim Shen // generator constructor 1425403c667bSTim Shen template <class _Generator, 142638cd7de5STim Shen int = typename std::enable_if< 142738cd7de5STim Shen __can_generate<_Generator>(std::make_index_sequence<size()>()), 142838cd7de5STim Shen int>::type()> 142938cd7de5STim Shen explicit simd(_Generator&& __g) { 143038cd7de5STim Shen __generator_init(std::forward<_Generator>(__g), 143138cd7de5STim Shen std::make_index_sequence<size()>()); 143238cd7de5STim Shen } 1433403c667bSTim Shen 1434403c667bSTim Shen // load constructor 143538cd7de5STim Shen template < 143638cd7de5STim Shen class _Up, class _Flags, 143738cd7de5STim Shen class = typename std::enable_if<__vectorizable<_Up>()>::type, 143838cd7de5STim Shen class = typename std::enable_if<is_simd_flag_type<_Flags>::value>::type> 143938cd7de5STim Shen simd(const _Up* __buffer, _Flags) { 144038cd7de5STim Shen // TODO: optimize for overaligned flags 144138cd7de5STim Shen for (size_t __i = 0; __i < size(); __i++) { 144238cd7de5STim Shen (*this)[__i] = static_cast<_Tp>(__buffer[__i]); 144338cd7de5STim Shen } 144438cd7de5STim Shen } 1445403c667bSTim Shen 1446403c667bSTim Shen // loads [simd.load] 1447403c667bSTim Shen template <class _Up, class _Flags> 144838cd7de5STim Shen typename std::enable_if<__vectorizable<_Up>() && 144938cd7de5STim Shen is_simd_flag_type<_Flags>::value>::type 145038cd7de5STim Shen copy_from(const _Up* __buffer, _Flags) { 145138cd7de5STim Shen *this = simd(__buffer, _Flags()); 145238cd7de5STim Shen } 1453403c667bSTim Shen 1454403c667bSTim Shen // stores [simd.store] 1455403c667bSTim Shen template <class _Up, class _Flags> 145638cd7de5STim Shen typename std::enable_if<__vectorizable<_Up>() && 145738cd7de5STim Shen is_simd_flag_type<_Flags>::value>::type 145838cd7de5STim Shen copy_to(_Up* __buffer, _Flags) const { 145938cd7de5STim Shen // TODO: optimize for overaligned flags 146038cd7de5STim Shen for (size_t __i = 0; __i < size(); __i++) { 146138cd7de5STim Shen __buffer[__i] = static_cast<_Up>((*this)[__i]); 146238cd7de5STim Shen } 146338cd7de5STim Shen } 1464403c667bSTim Shen 1465403c667bSTim Shen // scalar access [simd.subscr] 146638cd7de5STim Shen reference operator[](size_t __i) { return reference(&__s_, __i); } 146738cd7de5STim Shen 146838cd7de5STim Shen value_type operator[](size_t __i) const { return __s_.__get(__i); } 1469403c667bSTim Shen 1470403c667bSTim Shen // unary operators [simd.unary] 1471403c667bSTim Shen simd& operator++(); 1472403c667bSTim Shen simd operator++(int); 1473403c667bSTim Shen simd& operator--(); 1474403c667bSTim Shen simd operator--(int); 1475403c667bSTim Shen mask_type operator!() const; 1476403c667bSTim Shen simd operator~() const; 1477403c667bSTim Shen simd operator+() const; 1478403c667bSTim Shen simd operator-() const; 1479403c667bSTim Shen 1480e39095a3SLouis Dionne#if 0 1481403c667bSTim Shen // binary operators [simd.binary] 1482403c667bSTim Shen friend simd operator+(const simd&, const simd&); 1483403c667bSTim Shen friend simd operator-(const simd&, const simd&); 1484403c667bSTim Shen friend simd operator*(const simd&, const simd&); 1485403c667bSTim Shen friend simd operator/(const simd&, const simd&); 1486403c667bSTim Shen friend simd operator%(const simd&, const simd&); 1487403c667bSTim Shen friend simd operator&(const simd&, const simd&); 1488403c667bSTim Shen friend simd operator|(const simd&, const simd&); 1489403c667bSTim Shen friend simd operator^(const simd&, const simd&); 1490403c667bSTim Shen friend simd operator<<(const simd&, const simd&); 1491403c667bSTim Shen friend simd operator>>(const simd&, const simd&); 1492403c667bSTim Shen friend simd operator<<(const simd&, int); 1493403c667bSTim Shen friend simd operator>>(const simd&, int); 1494403c667bSTim Shen 1495403c667bSTim Shen // compound assignment [simd.cassign] 1496403c667bSTim Shen friend simd& operator+=(simd&, const simd&); 1497403c667bSTim Shen friend simd& operator-=(simd&, const simd&); 1498403c667bSTim Shen friend simd& operator*=(simd&, const simd&); 1499403c667bSTim Shen friend simd& operator/=(simd&, const simd&); 1500403c667bSTim Shen friend simd& operator%=(simd&, const simd&); 1501403c667bSTim Shen 1502403c667bSTim Shen friend simd& operator&=(simd&, const simd&); 1503403c667bSTim Shen friend simd& operator|=(simd&, const simd&); 1504403c667bSTim Shen friend simd& operator^=(simd&, const simd&); 1505403c667bSTim Shen friend simd& operator<<=(simd&, const simd&); 1506403c667bSTim Shen friend simd& operator>>=(simd&, const simd&); 1507403c667bSTim Shen friend simd& operator<<=(simd&, int); 1508403c667bSTim Shen friend simd& operator>>=(simd&, int); 1509403c667bSTim Shen 1510403c667bSTim Shen // compares [simd.comparison] 1511403c667bSTim Shen friend mask_type operator==(const simd&, const simd&); 1512403c667bSTim Shen friend mask_type operator!=(const simd&, const simd&); 1513403c667bSTim Shen friend mask_type operator>=(const simd&, const simd&); 1514403c667bSTim Shen friend mask_type operator<=(const simd&, const simd&); 1515403c667bSTim Shen friend mask_type operator>(const simd&, const simd&); 1516403c667bSTim Shen friend mask_type operator<(const simd&, const simd&); 1517e39095a3SLouis Dionne#endif 1518403c667bSTim Shen}; 1519403c667bSTim Shen 1520403c667bSTim Shen// [simd.mask.class] 1521403c667bSTim Shentemplate <class _Tp, class _Abi> 1522403c667bSTim Shen// TODO: implement simd_mask 1523403c667bSTim Shenclass simd_mask { 1524403c667bSTim Shenpublic: 1525403c667bSTim Shen using value_type = bool; 1526403c667bSTim Shen // TODO: this is strawman implementation. Turn it into a proxy type. 1527403c667bSTim Shen using reference = bool&; 1528403c667bSTim Shen using simd_type = simd<_Tp, _Abi>; 1529403c667bSTim Shen using abi_type = _Abi; 1530403c667bSTim Shen static constexpr size_t size() noexcept; 1531403c667bSTim Shen simd_mask() = default; 1532403c667bSTim Shen 1533403c667bSTim Shen // broadcast constructor 1534403c667bSTim Shen explicit simd_mask(value_type) noexcept; 1535403c667bSTim Shen 1536403c667bSTim Shen // implicit type conversion constructor 1537403c667bSTim Shen template <class _Up> 1538403c667bSTim Shen simd_mask(const simd_mask<_Up, simd_abi::fixed_size<size()>>&) noexcept; 1539403c667bSTim Shen 1540403c667bSTim Shen // load constructor 1541403c667bSTim Shen template <class _Flags> 1542403c667bSTim Shen simd_mask(const value_type*, _Flags); 1543403c667bSTim Shen 1544403c667bSTim Shen // loads [simd.mask.copy] 1545403c667bSTim Shen template <class _Flags> 1546403c667bSTim Shen void copy_from(const value_type*, _Flags); 1547403c667bSTim Shen template <class _Flags> 1548403c667bSTim Shen void copy_to(value_type*, _Flags) const; 1549403c667bSTim Shen 1550403c667bSTim Shen // scalar access [simd.mask.subscr] 1551403c667bSTim Shen reference operator[](size_t); 1552403c667bSTim Shen value_type operator[](size_t) const; 1553403c667bSTim Shen 1554403c667bSTim Shen // unary operators [simd.mask.unary] 1555403c667bSTim Shen simd_mask operator!() const noexcept; 1556403c667bSTim Shen 1557e39095a3SLouis Dionne#if 0 1558403c667bSTim Shen // simd_mask binary operators [simd.mask.binary] 1559403c667bSTim Shen friend simd_mask operator&&(const simd_mask&, const simd_mask&) noexcept; 1560403c667bSTim Shen friend simd_mask operator||(const simd_mask&, const simd_mask&) noexcept; 1561403c667bSTim Shen friend simd_mask operator&(const simd_mask&, const simd_mask&)noexcept; 1562403c667bSTim Shen friend simd_mask operator|(const simd_mask&, const simd_mask&) noexcept; 1563403c667bSTim Shen friend simd_mask operator^(const simd_mask&, const simd_mask&) noexcept; 1564403c667bSTim Shen 1565403c667bSTim Shen // simd_mask compound assignment [simd.mask.cassign] 1566403c667bSTim Shen friend simd_mask& operator&=(simd_mask&, const simd_mask&) noexcept; 1567403c667bSTim Shen friend simd_mask& operator|=(simd_mask&, const simd_mask&) noexcept; 1568403c667bSTim Shen friend simd_mask& operator^=(simd_mask&, const simd_mask&) noexcept; 1569403c667bSTim Shen 1570403c667bSTim Shen // simd_mask compares [simd.mask.comparison] 1571403c667bSTim Shen friend simd_mask operator==(const simd_mask&, const simd_mask&) noexcept; 1572403c667bSTim Shen friend simd_mask operator!=(const simd_mask&, const simd_mask&) noexcept; 1573e39095a3SLouis Dionne#endif 1574403c667bSTim Shen}; 1575403c667bSTim Shen 157638cd7de5STim Shen#endif // _LIBCPP_STD_VER >= 17 157738cd7de5STim Shen 1578403c667bSTim Shen_LIBCPP_END_NAMESPACE_EXPERIMENTAL_SIMD 1579403c667bSTim Shen 1580d4303307SArthur O'Dwyer_LIBCPP_POP_MACROS 1581d4303307SArthur O'Dwyer 1582403c667bSTim Shen#endif /* _LIBCPP_EXPERIMENTAL_SIMD */ 1583