xref: /freebsd/contrib/llvm-project/libcxx/include/experimental/simd (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
10b57cec5SDimitry Andric// -*- C++ -*-
2349cc55cSDimitry Andric//===----------------------------------------------------------------------===//
30b57cec5SDimitry Andric//
40b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
50b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
60b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
70b57cec5SDimitry Andric//
80b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
9*bdd1243dSDimitry Andric
100b57cec5SDimitry Andric#ifndef _LIBCPP_EXPERIMENTAL_SIMD
110b57cec5SDimitry Andric#define _LIBCPP_EXPERIMENTAL_SIMD
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric/*
140b57cec5SDimitry Andric    experimental/simd synopsis
150b57cec5SDimitry Andric
160b57cec5SDimitry Andricnamespace std::experimental {
170b57cec5SDimitry Andric
180b57cec5SDimitry Andricinline namespace parallelism_v2 {
190b57cec5SDimitry Andric
200b57cec5SDimitry Andricnamespace simd_abi {
210b57cec5SDimitry Andric
220b57cec5SDimitry Andricstruct scalar {};
230b57cec5SDimitry Andrictemplate <int N> struct fixed_size {};
240b57cec5SDimitry Andrictemplate <typename T> inline constexpr int max_fixed_size = implementation-defined;
250b57cec5SDimitry Andrictemplate <typename T> using compatible = implementation-defined;
260b57cec5SDimitry Andrictemplate <typename T> using native = implementation-defined;
270b57cec5SDimitry Andric
280b57cec5SDimitry Andric} // simd_abi
290b57cec5SDimitry Andric
300b57cec5SDimitry Andricstruct element_aligned_tag {};
310b57cec5SDimitry Andricstruct vector_aligned_tag {};
320b57cec5SDimitry Andrictemplate <size_t> struct overaligned_tag {};
330b57cec5SDimitry Andricinline constexpr element_aligned_tag element_aligned{};
340b57cec5SDimitry Andricinline constexpr vector_aligned_tag vector_aligned{};
350b57cec5SDimitry Andrictemplate <size_t N> inline constexpr overaligned_tag<N> overaligned{};
360b57cec5SDimitry Andric
370b57cec5SDimitry Andric// traits [simd.traits]
380b57cec5SDimitry Andrictemplate <class T> struct is_abi_tag;
390b57cec5SDimitry Andrictemplate <class T> inline constexpr bool is_abi_tag_v = is_abi_tag<T>::value;
400b57cec5SDimitry Andric
410b57cec5SDimitry Andrictemplate <class T> struct is_simd;
420b57cec5SDimitry Andrictemplate <class T> inline constexpr bool is_simd_v = is_simd<T>::value;
430b57cec5SDimitry Andric
440b57cec5SDimitry Andrictemplate <class T> struct is_simd_mask;
450b57cec5SDimitry Andrictemplate <class T> inline constexpr bool is_simd_mask_v = is_simd_mask<T>::value;
460b57cec5SDimitry Andric
470b57cec5SDimitry Andrictemplate <class T> struct is_simd_flag_type;
480b57cec5SDimitry Andrictemplate <class T> inline constexpr bool is_simd_flag_type_v = is_simd_flag_type<T>::value;
490b57cec5SDimitry Andric
500b57cec5SDimitry Andrictemplate <class T, size_t N> struct abi_for_size { using type = see below; };
510b57cec5SDimitry Andrictemplate <class T, size_t N> using abi_for_size_t = typename abi_for_size<T, N>::type;
520b57cec5SDimitry Andric
530b57cec5SDimitry Andrictemplate <class T, class Abi = simd_abi::compatible<T>> struct simd_size;
540b57cec5SDimitry Andrictemplate <class T, class Abi = simd_abi::compatible<T>>
550b57cec5SDimitry Andricinline constexpr size_t simd_size_v = simd_size<T, Abi>::value;
560b57cec5SDimitry Andric
570b57cec5SDimitry Andrictemplate <class T, class U = typename T::value_type> struct memory_alignment;
580b57cec5SDimitry Andrictemplate <class T, class U = typename T::value_type>
590b57cec5SDimitry Andricinline constexpr size_t memory_alignment_v = memory_alignment<T, U>::value;
600b57cec5SDimitry Andric
610b57cec5SDimitry Andric// class template simd [simd.class]
620b57cec5SDimitry Andrictemplate <class T, class Abi = simd_abi::compatible<T>> class simd;
630b57cec5SDimitry Andrictemplate <class T> using native_simd = simd<T, simd_abi::native<T>>;
640b57cec5SDimitry Andrictemplate <class T, int N> using fixed_size_simd = simd<T, simd_abi::fixed_size<N>>;
650b57cec5SDimitry Andric
660b57cec5SDimitry Andric// class template simd_mask [simd.mask.class]
670b57cec5SDimitry Andrictemplate <class T, class Abi = simd_abi::compatible<T>> class simd_mask;
680b57cec5SDimitry Andrictemplate <class T> using native_simd_mask = simd_mask<T, simd_abi::native<T>>;
690b57cec5SDimitry Andrictemplate <class T, int N> using fixed_size_simd_mask = simd_mask<T, simd_abi::fixed_size<N>>;
700b57cec5SDimitry Andric
710b57cec5SDimitry Andric// casts [simd.casts]
720b57cec5SDimitry Andrictemplate <class T, class U, class Abi> see below simd_cast(const simd<U, Abi>&);
730b57cec5SDimitry Andrictemplate <class T, class U, class Abi> see below static_simd_cast(const simd<U, Abi>&);
740b57cec5SDimitry Andric
750b57cec5SDimitry Andrictemplate <class T, class Abi>
760b57cec5SDimitry Andricfixed_size_simd<T, simd_size_v<T, Abi>> to_fixed_size(const simd<T, Abi>&) noexcept;
770b57cec5SDimitry Andrictemplate <class T, class Abi>
780b57cec5SDimitry Andricfixed_size_simd_mask<T, simd_size_v<T, Abi>> to_fixed_size(const simd_mask<T, Abi>&) noexcept;
790b57cec5SDimitry Andrictemplate <class T, size_t N> native_simd<T> to_native(const fixed_size_simd<T, N>&) noexcept;
800b57cec5SDimitry Andrictemplate <class T, size_t N>
810b57cec5SDimitry Andricnative_simd_mask<T> to_native(const fixed_size_simd_mask<T, N>> &) noexcept;
820b57cec5SDimitry Andrictemplate <class T, size_t N> simd<T> to_compatible(const fixed_size_simd<T, N>&) noexcept;
830b57cec5SDimitry Andrictemplate <class T, size_t N> simd_mask<T> to_compatible(const fixed_size_simd_mask<T, N>&) noexcept;
840b57cec5SDimitry Andric
850b57cec5SDimitry Andrictemplate <size_t... Sizes, class T, class Abi>
860b57cec5SDimitry Andrictuple<simd<T, abi_for_size_t<Sizes>>...> split(const simd<T, Abi>&);
870b57cec5SDimitry Andrictemplate <size_t... Sizes, class T, class Abi>
880b57cec5SDimitry Andrictuple<simd_mask<T, abi_for_size_t<Sizes>>...> split(const simd_mask<T, Abi>&);
890b57cec5SDimitry Andrictemplate <class V, class Abi>
900b57cec5SDimitry Andricarray<V, simd_size_v<typename V::value_type, Abi> / V::size()> split(
910b57cec5SDimitry Andricconst simd<typename V::value_type, Abi>&);
920b57cec5SDimitry Andrictemplate <class V, class Abi>
930b57cec5SDimitry Andricarray<V, simd_size_v<typename V::value_type, Abi> / V::size()> split(
940b57cec5SDimitry Andricconst simd_mask<typename V::value_type, Abi>&);
950b57cec5SDimitry Andric
960b57cec5SDimitry Andrictemplate <class T, class... Abis>
970b57cec5SDimitry Andricsimd<T, abi_for_size_t<T, (simd_size_v<T, Abis> + ...)>> concat(const simd<T, Abis>&...);
980b57cec5SDimitry Andrictemplate <class T, class... Abis>
990b57cec5SDimitry Andricsimd_mask<T, abi_for_size_t<T, (simd_size_v<T, Abis> + ...)>> concat(const simd_mask<T, Abis>&...);
1000b57cec5SDimitry Andric
1010b57cec5SDimitry Andric// reductions [simd.mask.reductions]
1020b57cec5SDimitry Andrictemplate <class T, class Abi> bool all_of(const simd_mask<T, Abi>&) noexcept;
1030b57cec5SDimitry Andrictemplate <class T, class Abi> bool any_of(const simd_mask<T, Abi>&) noexcept;
1040b57cec5SDimitry Andrictemplate <class T, class Abi> bool none_of(const simd_mask<T, Abi>&) noexcept;
1050b57cec5SDimitry Andrictemplate <class T, class Abi> bool some_of(const simd_mask<T, Abi>&) noexcept;
1060b57cec5SDimitry Andrictemplate <class T, class Abi> int popcount(const simd_mask<T, Abi>&) noexcept;
1070b57cec5SDimitry Andrictemplate <class T, class Abi> int find_first_set(const simd_mask<T, Abi>&);
1080b57cec5SDimitry Andrictemplate <class T, class Abi> int find_last_set(const simd_mask<T, Abi>&);
1090b57cec5SDimitry Andric
1100b57cec5SDimitry Andricbool all_of(see below) noexcept;
1110b57cec5SDimitry Andricbool any_of(see below) noexcept;
1120b57cec5SDimitry Andricbool none_of(see below) noexcept;
1130b57cec5SDimitry Andricbool some_of(see below) noexcept;
1140b57cec5SDimitry Andricint popcount(see below) noexcept;
1150b57cec5SDimitry Andricint find_first_set(see below) noexcept;
1160b57cec5SDimitry Andricint find_last_set(see below) noexcept;
1170b57cec5SDimitry Andric
1180b57cec5SDimitry Andric// masked assignment [simd.whereexpr]
1190b57cec5SDimitry Andrictemplate <class M, class T> class const_where_expression;
1200b57cec5SDimitry Andrictemplate <class M, class T> class where_expression;
1210b57cec5SDimitry Andric
1220b57cec5SDimitry Andric// masked assignment [simd.mask.where]
1230b57cec5SDimitry Andrictemplate <class T> struct nodeduce { using type = T; }; // exposition only
1240b57cec5SDimitry Andric
1250b57cec5SDimitry Andrictemplate <class T> using nodeduce_t = typename nodeduce<T>::type; // exposition only
1260b57cec5SDimitry Andric
1270b57cec5SDimitry Andrictemplate <class T, class Abi>
1280b57cec5SDimitry Andricwhere_expression<simd_mask<T, Abi>, simd<T, Abi>>
1290b57cec5SDimitry Andricwhere(const typename simd<T, Abi>::mask_type&, simd<T, Abi>&) noexcept;
1300b57cec5SDimitry Andric
1310b57cec5SDimitry Andrictemplate <class T, class Abi>
1320b57cec5SDimitry Andricconst_where_expression<simd_mask<T, Abi>, const simd<T, Abi>>
1330b57cec5SDimitry Andricwhere(const typename simd<T, Abi>::mask_type&, const simd<T, Abi>&) noexcept;
1340b57cec5SDimitry Andric
1350b57cec5SDimitry Andrictemplate <class T, class Abi>
1360b57cec5SDimitry Andricwhere_expression<simd_mask<T, Abi>, simd_mask<T, Abi>>
1370b57cec5SDimitry Andricwhere(const nodeduce_t<simd_mask<T, Abi>>&, simd_mask<T, Abi>&) noexcept;
1380b57cec5SDimitry Andric
1390b57cec5SDimitry Andrictemplate <class T, class Abi>
1400b57cec5SDimitry Andricconst_where_expression<simd_mask<T, Abi>, const simd_mask<T, Abi>>
1410b57cec5SDimitry Andricwhere(const nodeduce_t<simd_mask<T, Abi>>&, const simd_mask<T, Abi>&) noexcept;
1420b57cec5SDimitry Andric
1430b57cec5SDimitry Andrictemplate <class T> where_expression<bool, T> where(see below k, T& d) noexcept;
1440b57cec5SDimitry Andric
1450b57cec5SDimitry Andrictemplate <class T>
1460b57cec5SDimitry Andricconst_where_expression<bool, const T> where(see below k, const T& d) noexcept;
1470b57cec5SDimitry Andric
1480b57cec5SDimitry Andric// reductions [simd.reductions]
1490b57cec5SDimitry Andrictemplate <class T, class Abi, class BinaryOperation = std::plus<>>
1500b57cec5SDimitry AndricT reduce(const simd<T, Abi>&, BinaryOperation = BinaryOperation());
1510b57cec5SDimitry Andric
1520b57cec5SDimitry Andrictemplate <class M, class V, class BinaryOperation>
1530b57cec5SDimitry Andrictypename V::value_type reduce(const const_where_expression<M, V>& x,
1540b57cec5SDimitry Andrictypename V::value_type neutral_element, BinaryOperation binary_op);
1550b57cec5SDimitry Andric
1560b57cec5SDimitry Andrictemplate <class M, class V>
1570b57cec5SDimitry Andrictypename V::value_type reduce(const const_where_expression<M, V>& x, plus<> binary_op = plus<>());
1580b57cec5SDimitry Andric
1590b57cec5SDimitry Andrictemplate <class M, class V>
1600b57cec5SDimitry Andrictypename V::value_type reduce(const const_where_expression<M, V>& x, multiplies<> binary_op);
1610b57cec5SDimitry Andric
1620b57cec5SDimitry Andrictemplate <class M, class V>
1630b57cec5SDimitry Andrictypename V::value_type reduce(const const_where_expression<M, V>& x, bit_and<> binary_op);
1640b57cec5SDimitry Andric
1650b57cec5SDimitry Andrictemplate <class M, class V>
1660b57cec5SDimitry Andrictypename V::value_type reduce(const const_where_expression<M, V>& x, bit_or<> binary_op);
1670b57cec5SDimitry Andric
1680b57cec5SDimitry Andrictemplate <class M, class V>
1690b57cec5SDimitry Andrictypename V::value_type reduce(const const_where_expression<M, V>& x, bit_xor<> binary_op);
1700b57cec5SDimitry Andric
1710b57cec5SDimitry Andrictemplate <class T, class Abi> T hmin(const simd<T, Abi>&);
1720b57cec5SDimitry Andrictemplate <class M, class V> T hmin(const const_where_expression<M, V>&);
1730b57cec5SDimitry Andrictemplate <class T, class Abi> T hmax(const simd<T, Abi>&);
1740b57cec5SDimitry Andrictemplate <class M, class V> T hmax(const const_where_expression<M, V>&);
1750b57cec5SDimitry Andric
1760b57cec5SDimitry Andric// algorithms [simd.alg]
1770b57cec5SDimitry Andrictemplate <class T, class Abi> simd<T, Abi> min(const simd<T, Abi>&, const simd<T, Abi>&) noexcept;
1780b57cec5SDimitry Andric
1790b57cec5SDimitry Andrictemplate <class T, class Abi> simd<T, Abi> max(const simd<T, Abi>&, const simd<T, Abi>&) noexcept;
1800b57cec5SDimitry Andric
1810b57cec5SDimitry Andrictemplate <class T, class Abi>
1820b57cec5SDimitry Andricstd::pair<simd<T, Abi>, simd<T, Abi>> minmax(const simd<T, Abi>&, const simd<T, Abi>&) noexcept;
1830b57cec5SDimitry Andric
1840b57cec5SDimitry Andrictemplate <class T, class Abi>
1850b57cec5SDimitry Andricsimd<T, Abi> clamp(const simd<T, Abi>& v, const simd<T, Abi>& lo, const simd<T, Abi>& hi);
1860b57cec5SDimitry Andric
1870b57cec5SDimitry Andric// [simd.whereexpr]
1880b57cec5SDimitry Andrictemplate <class M, class T>
1890b57cec5SDimitry Andricclass const_where_expression {
1900b57cec5SDimitry Andric  const M& mask; // exposition only
1910b57cec5SDimitry Andric  T& data; // exposition only
1920b57cec5SDimitry Andricpublic:
1930b57cec5SDimitry Andric  const_where_expression(const const_where_expression&) = delete;
1940b57cec5SDimitry Andric  const_where_expression& operator=(const const_where_expression&) = delete;
1950b57cec5SDimitry Andric  remove_const_t<T> operator-() const &&;
1960b57cec5SDimitry Andric  template <class U, class Flags> void copy_to(U* mem, Flags f) const &&;
1970b57cec5SDimitry Andric};
1980b57cec5SDimitry Andric
1990b57cec5SDimitry Andrictemplate <class M, class T>
2000b57cec5SDimitry Andricclass where_expression : public const_where_expression<M, T> {
2010b57cec5SDimitry Andricpublic:
2020b57cec5SDimitry Andric  where_expression(const where_expression&) = delete;
2030b57cec5SDimitry Andric  where_expression& operator=(const where_expression&) = delete;
2040b57cec5SDimitry Andric  template <class U> void operator=(U&& x);
2050b57cec5SDimitry Andric  template <class U> void operator+=(U&& x);
2060b57cec5SDimitry Andric  template <class U> void operator-=(U&& x);
2070b57cec5SDimitry Andric  template <class U> void operator*=(U&& x);
2080b57cec5SDimitry Andric  template <class U> void operator/=(U&& x);
2090b57cec5SDimitry Andric  template <class U> void operator%=(U&& x);
2100b57cec5SDimitry Andric  template <class U> void operator&=(U&& x);
2110b57cec5SDimitry Andric  template <class U> void operator|=(U&& x);
2120b57cec5SDimitry Andric  template <class U> void operator^=(U&& x);
2130b57cec5SDimitry Andric  template <class U> void operator<<=(U&& x);
2140b57cec5SDimitry Andric  template <class U> void operator>>=(U&& x);
2150b57cec5SDimitry Andric  void operator++();
2160b57cec5SDimitry Andric  void operator++(int);
2170b57cec5SDimitry Andric  void operator--();
2180b57cec5SDimitry Andric  void operator--(int);
2190b57cec5SDimitry Andric  template <class U, class Flags> void copy_from(const U* mem, Flags);
2200b57cec5SDimitry Andric};
2210b57cec5SDimitry Andric
2220b57cec5SDimitry Andric// [simd.class]
2230b57cec5SDimitry Andrictemplate <class T, class Abi> class simd {
2240b57cec5SDimitry Andricpublic:
2250b57cec5SDimitry Andric  using value_type = T;
2260b57cec5SDimitry Andric  using reference = see below;
2270b57cec5SDimitry Andric  using mask_type = simd_mask<T, Abi>;
2280b57cec5SDimitry Andric
2290b57cec5SDimitry Andric  using abi_type = Abi;
2300b57cec5SDimitry Andric  static constexpr size_t size() noexcept;
2310b57cec5SDimitry Andric  simd() = default;
2320b57cec5SDimitry Andric
2330b57cec5SDimitry Andric  // implicit type conversion constructor
2340b57cec5SDimitry Andric  template <class U> simd(const simd<U, simd_abi::fixed_size<size()>>&);
2350b57cec5SDimitry Andric
2360b57cec5SDimitry Andric  // implicit broadcast constructor (see below for constraints)
2370b57cec5SDimitry Andric  template <class U> simd(U&& value);
2380b57cec5SDimitry Andric
2390b57cec5SDimitry Andric  // generator constructor (see below for constraints)
2400b57cec5SDimitry Andric  template <class G> explicit simd(G&& gen);
2410b57cec5SDimitry Andric
2420b57cec5SDimitry Andric  // load constructor
2430b57cec5SDimitry Andric  template <class U, class Flags> simd(const U* mem, Flags f);
2440b57cec5SDimitry Andric
2450b57cec5SDimitry Andric  // loads [simd.load]
2460b57cec5SDimitry Andric  template <class U, class Flags> void copy_from(const U* mem, Flags f);
2470b57cec5SDimitry Andric
2480b57cec5SDimitry Andric  // stores [simd.store]
2490b57cec5SDimitry Andric  template <class U, class Flags> void copy_to(U* mem, Flags f) const;
2500b57cec5SDimitry Andric
2510b57cec5SDimitry Andric  // scalar access [simd.subscr]
2520b57cec5SDimitry Andric  reference operator[](size_t);
2530b57cec5SDimitry Andric  value_type operator[](size_t) const;
2540b57cec5SDimitry Andric
2550b57cec5SDimitry Andric  // unary operators [simd.unary]
2560b57cec5SDimitry Andric  simd& operator++();
2570b57cec5SDimitry Andric  simd operator++(int);
2580b57cec5SDimitry Andric  simd& operator--();
2590b57cec5SDimitry Andric  simd operator--(int);
2600b57cec5SDimitry Andric  mask_type operator!() const;
2610b57cec5SDimitry Andric  simd operator~() const; // see below
2620b57cec5SDimitry Andric  simd operator+() const;
2630b57cec5SDimitry Andric  simd operator-() const;
2640b57cec5SDimitry Andric
2650b57cec5SDimitry Andric  // binary operators [simd.binary]
2660b57cec5SDimitry Andric  friend simd operator+ (const simd&, const simd&);
2670b57cec5SDimitry Andric  friend simd operator- (const simd&, const simd&);
2680b57cec5SDimitry Andric  friend simd operator* (const simd&, const simd&);
2690b57cec5SDimitry Andric  friend simd operator/ (const simd&, const simd&);
2700b57cec5SDimitry Andric  friend simd operator% (const simd&, const simd&);
2710b57cec5SDimitry Andric  friend simd operator& (const simd&, const simd&);
2720b57cec5SDimitry Andric  friend simd operator| (const simd&, const simd&);
2730b57cec5SDimitry Andric  friend simd operator^ (const simd&, const simd&);
2740b57cec5SDimitry Andric  friend simd operator<<(const simd&, const simd&);
2750b57cec5SDimitry Andric  friend simd operator>>(const simd&, const simd&);
2760b57cec5SDimitry Andric  friend simd operator<<(const simd&, int);
2770b57cec5SDimitry Andric  friend simd operator>>(const simd&, int);
2780b57cec5SDimitry Andric
2790b57cec5SDimitry Andric  // compound assignment [simd.cassign]
2800b57cec5SDimitry Andric  friend simd& operator+= (simd&, const simd&);
2810b57cec5SDimitry Andric  friend simd& operator-= (simd&, const simd&);
2820b57cec5SDimitry Andric  friend simd& operator*= (simd&, const simd&);
2830b57cec5SDimitry Andric  friend simd& operator/= (simd&, const simd&);
2840b57cec5SDimitry Andric  friend simd& operator%= (simd&, const simd&);
2850b57cec5SDimitry Andric
2860b57cec5SDimitry Andric  friend simd& operator&= (simd&, const simd&);
2870b57cec5SDimitry Andric  friend simd& operator|= (simd&, const simd&);
2880b57cec5SDimitry Andric  friend simd& operator^= (simd&, const simd&);
2890b57cec5SDimitry Andric  friend simd& operator<<=(simd&, const simd&);
2900b57cec5SDimitry Andric  friend simd& operator>>=(simd&, const simd&);
2910b57cec5SDimitry Andric  friend simd& operator<<=(simd&, int);
2920b57cec5SDimitry Andric  friend simd& operator>>=(simd&, int);
2930b57cec5SDimitry Andric
2940b57cec5SDimitry Andric  // compares [simd.comparison]
2950b57cec5SDimitry Andric  friend mask_type operator==(const simd&, const simd&);
2960b57cec5SDimitry Andric  friend mask_type operator!=(const simd&, const simd&);
2970b57cec5SDimitry Andric  friend mask_type operator>=(const simd&, const simd&);
2980b57cec5SDimitry Andric  friend mask_type operator<=(const simd&, const simd&);
2990b57cec5SDimitry Andric  friend mask_type operator> (const simd&, const simd&);
3000b57cec5SDimitry Andric  friend mask_type operator< (const simd&, const simd&);
3010b57cec5SDimitry Andric};
3020b57cec5SDimitry Andric
3030b57cec5SDimitry Andric// [simd.math]
3040b57cec5SDimitry Andrictemplate <class Abi> using scharv = simd<signed char, Abi>; // exposition only
3050b57cec5SDimitry Andrictemplate <class Abi> using shortv = simd<short, Abi>; // exposition only
3060b57cec5SDimitry Andrictemplate <class Abi> using intv = simd<int, Abi>; // exposition only
3070b57cec5SDimitry Andrictemplate <class Abi> using longv = simd<long int, Abi>; // exposition only
3080b57cec5SDimitry Andrictemplate <class Abi> using llongv = simd<long long int, Abi>; // exposition only
3090b57cec5SDimitry Andrictemplate <class Abi> using floatv = simd<float, Abi>; // exposition only
3100b57cec5SDimitry Andrictemplate <class Abi> using doublev = simd<double, Abi>; // exposition only
3110b57cec5SDimitry Andrictemplate <class Abi> using ldoublev = simd<long double, Abi>; // exposition only
3120b57cec5SDimitry Andrictemplate <class T, class V> using samesize = fixed_size_simd<T, V::size()>; // exposition only
3130b57cec5SDimitry Andric
3140b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> acos(floatv<Abi> x);
3150b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> acos(doublev<Abi> x);
3160b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> acos(ldoublev<Abi> x);
3170b57cec5SDimitry Andric
3180b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> asin(floatv<Abi> x);
3190b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> asin(doublev<Abi> x);
3200b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> asin(ldoublev<Abi> x);
3210b57cec5SDimitry Andric
3220b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> atan(floatv<Abi> x);
3230b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> atan(doublev<Abi> x);
3240b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> atan(ldoublev<Abi> x);
3250b57cec5SDimitry Andric
3260b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> atan2(floatv<Abi> y, floatv<Abi> x);
3270b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> atan2(doublev<Abi> y, doublev<Abi> x);
3280b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> atan2(ldoublev<Abi> y, ldoublev<Abi> x);
3290b57cec5SDimitry Andric
3300b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> cos(floatv<Abi> x);
3310b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> cos(doublev<Abi> x);
3320b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> cos(ldoublev<Abi> x);
3330b57cec5SDimitry Andric
3340b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> sin(floatv<Abi> x);
3350b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> sin(doublev<Abi> x);
3360b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> sin(ldoublev<Abi> x);
3370b57cec5SDimitry Andric
3380b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> tan(floatv<Abi> x);
3390b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> tan(doublev<Abi> x);
3400b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> tan(ldoublev<Abi> x);
3410b57cec5SDimitry Andric
3420b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> acosh(floatv<Abi> x);
3430b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> acosh(doublev<Abi> x);
3440b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> acosh(ldoublev<Abi> x);
3450b57cec5SDimitry Andric
3460b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> asinh(floatv<Abi> x);
3470b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> asinh(doublev<Abi> x);
3480b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> asinh(ldoublev<Abi> x);
3490b57cec5SDimitry Andric
3500b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> atanh(floatv<Abi> x);
3510b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> atanh(doublev<Abi> x);
3520b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> atanh(ldoublev<Abi> x);
3530b57cec5SDimitry Andric
3540b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> cosh(floatv<Abi> x);
3550b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> cosh(doublev<Abi> x);
3560b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> cosh(ldoublev<Abi> x);
3570b57cec5SDimitry Andric
3580b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> sinh(floatv<Abi> x);
3590b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> sinh(doublev<Abi> x);
3600b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> sinh(ldoublev<Abi> x);
3610b57cec5SDimitry Andric
3620b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> tanh(floatv<Abi> x);
3630b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> tanh(doublev<Abi> x);
3640b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> tanh(ldoublev<Abi> x);
3650b57cec5SDimitry Andric
3660b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> exp(floatv<Abi> x);
3670b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> exp(doublev<Abi> x);
3680b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> exp(ldoublev<Abi> x);
3690b57cec5SDimitry Andric
3700b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> exp2(floatv<Abi> x);
3710b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> exp2(doublev<Abi> x);
3720b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> exp2(ldoublev<Abi> x);
3730b57cec5SDimitry Andric
3740b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> expm1(floatv<Abi> x);
3750b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> expm1(doublev<Abi> x);
3760b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> expm1(ldoublev<Abi> x);
3770b57cec5SDimitry Andric
3780b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> frexp(floatv<Abi> value, samesize<int, floatv<Abi>>* exp);
3790b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> frexp(doublev<Abi> value, samesize<int, doublev<Abi>>* exp);
3800b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> frexp(ldoublev<Abi> value, samesize<int, ldoublev<Abi>>* exp);
3810b57cec5SDimitry Andric
3820b57cec5SDimitry Andrictemplate <class Abi> samesize<int, floatv<Abi>> ilogb(floatv<Abi> x);
3830b57cec5SDimitry Andrictemplate <class Abi> samesize<int, doublev<Abi>> ilogb(doublev<Abi> x);
3840b57cec5SDimitry Andrictemplate <class Abi> samesize<int, ldoublev<Abi>> ilogb(ldoublev<Abi> x);
3850b57cec5SDimitry Andric
3860b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> ldexp(floatv<Abi> x, samesize<int, floatv<Abi>> exp);
3870b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> ldexp(doublev<Abi> x, samesize<int, doublev<Abi>> exp);
3880b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> ldexp(ldoublev<Abi> x, samesize<int, ldoublev<Abi>> exp);
3890b57cec5SDimitry Andric
3900b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> log(floatv<Abi> x);
3910b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> log(doublev<Abi> x);
3920b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> log(ldoublev<Abi> x);
3930b57cec5SDimitry Andric
3940b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> log10(floatv<Abi> x);
3950b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> log10(doublev<Abi> x);
3960b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> log10(ldoublev<Abi> x);
3970b57cec5SDimitry Andric
3980b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> log1p(floatv<Abi> x);
3990b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> log1p(doublev<Abi> x);
4000b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> log1p(ldoublev<Abi> x);
4010b57cec5SDimitry Andric
4020b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> log2(floatv<Abi> x);
4030b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> log2(doublev<Abi> x);
4040b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> log2(ldoublev<Abi> x);
4050b57cec5SDimitry Andric
4060b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> logb(floatv<Abi> x);
4070b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> logb(doublev<Abi> x);
4080b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> logb(ldoublev<Abi> x);
4090b57cec5SDimitry Andric
4100b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> modf(floatv<Abi> value, floatv<Abi>* iptr);
4110b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> modf(doublev<Abi> value, doublev<Abi>* iptr);
4120b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> modf(ldoublev<Abi> value, ldoublev<Abi>* iptr);
4130b57cec5SDimitry Andric
4140b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> scalbn(floatv<Abi> x, samesize<int, floatv<Abi>> n);
4150b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> scalbn(doublev<Abi> x, samesize<int, doublev<Abi>> n);
4160b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> scalbn(ldoublev<Abi> x, samesize<int, ldoublev<Abi>> n);
4170b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> scalbln(floatv<Abi> x, samesize<long int, floatv<Abi>> n);
4180b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> scalbln(doublev<Abi> x, samesize<long int, doublev<Abi>> n);
4190b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> scalbln(ldoublev<Abi> x, samesize<long int, ldoublev<Abi>> n);
4200b57cec5SDimitry Andric
4210b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> cbrt(floatv<Abi> x);
4220b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> cbrt(doublev<Abi> x);
4230b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> cbrt(ldoublev<Abi> x);
4240b57cec5SDimitry Andric
4250b57cec5SDimitry Andrictemplate <class Abi> scharv<Abi> abs(scharv<Abi> j);
4260b57cec5SDimitry Andrictemplate <class Abi> shortv<Abi> abs(shortv<Abi> j);
4270b57cec5SDimitry Andrictemplate <class Abi> intv<Abi> abs(intv<Abi> j);
4280b57cec5SDimitry Andrictemplate <class Abi> longv<Abi> abs(longv<Abi> j);
4290b57cec5SDimitry Andrictemplate <class Abi> llongv<Abi> abs(llongv<Abi> j);
4300b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> abs(floatv<Abi> j);
4310b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> abs(doublev<Abi> j);
4320b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> abs(ldoublev<Abi> j);
4330b57cec5SDimitry Andric
4340b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> hypot(floatv<Abi> x, floatv<Abi> y);
4350b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> hypot(doublev<Abi> x, doublev<Abi> y);
4360b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> hypot(doublev<Abi> x, doublev<Abi> y);
4370b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> hypot(floatv<Abi> x, floatv<Abi> y, floatv<Abi> z);
4380b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> hypot(doublev<Abi> x, doublev<Abi> y, doublev<Abi> z);
4390b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> hypot(ldoublev<Abi> x, ldoublev<Abi> y, ldoublev<Abi> z);
4400b57cec5SDimitry Andric
4410b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> pow(floatv<Abi> x, floatv<Abi> y);
4420b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> pow(doublev<Abi> x, doublev<Abi> y);
4430b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> pow(ldoublev<Abi> x, ldoublev<Abi> y);
4440b57cec5SDimitry Andric
4450b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> sqrt(floatv<Abi> x);
4460b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> sqrt(doublev<Abi> x);
4470b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> sqrt(ldoublev<Abi> x);
4480b57cec5SDimitry Andric
4490b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> erf(floatv<Abi> x);
4500b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> erf(doublev<Abi> x);
4510b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> erf(ldoublev<Abi> x);
4520b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> erfc(floatv<Abi> x);
4530b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> erfc(doublev<Abi> x);
4540b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> erfc(ldoublev<Abi> x);
4550b57cec5SDimitry Andric
4560b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> lgamma(floatv<Abi> x);
4570b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> lgamma(doublev<Abi> x);
4580b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> lgamma(ldoublev<Abi> x);
4590b57cec5SDimitry Andric
4600b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> tgamma(floatv<Abi> x);
4610b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> tgamma(doublev<Abi> x);
4620b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> tgamma(ldoublev<Abi> x);
4630b57cec5SDimitry Andric
4640b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> ceil(floatv<Abi> x);
4650b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> ceil(doublev<Abi> x);
4660b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> ceil(ldoublev<Abi> x);
4670b57cec5SDimitry Andric
4680b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> floor(floatv<Abi> x);
4690b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> floor(doublev<Abi> x);
4700b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> floor(ldoublev<Abi> x);
4710b57cec5SDimitry Andric
4720b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> nearbyint(floatv<Abi> x);
4730b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> nearbyint(doublev<Abi> x);
4740b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> nearbyint(ldoublev<Abi> x);
4750b57cec5SDimitry Andric
4760b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> rint(floatv<Abi> x);
4770b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> rint(doublev<Abi> x);
4780b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> rint(ldoublev<Abi> x);
4790b57cec5SDimitry Andric
4800b57cec5SDimitry Andrictemplate <class Abi> samesize<long int, floatv<Abi>> lrint(floatv<Abi> x);
4810b57cec5SDimitry Andrictemplate <class Abi> samesize<long int, doublev<Abi>> lrint(doublev<Abi> x);
4820b57cec5SDimitry Andrictemplate <class Abi> samesize<long int, ldoublev<Abi>> lrint(ldoublev<Abi> x);
4830b57cec5SDimitry Andrictemplate <class Abi> samesize<long long int, floatv<Abi>> llrint(floatv<Abi> x);
4840b57cec5SDimitry Andrictemplate <class Abi> samesize<long long int, doublev<Abi>> llrint(doublev<Abi> x);
4850b57cec5SDimitry Andrictemplate <class Abi> samesize<long long int, ldoublev<Abi>> llrint(ldoublev<Abi> x);
4860b57cec5SDimitry Andric
4870b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> round(floatv<Abi> x);
4880b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> round(doublev<Abi> x);
4890b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> round(ldoublev<Abi> x);
4900b57cec5SDimitry Andrictemplate <class Abi> samesize<long int, floatv<Abi>> lround(floatv<Abi> x);
4910b57cec5SDimitry Andrictemplate <class Abi> samesize<long int, doublev<Abi>> lround(doublev<Abi> x);
4920b57cec5SDimitry Andrictemplate <class Abi> samesize<long int, ldoublev<Abi>> lround(ldoublev<Abi> x);
4930b57cec5SDimitry Andrictemplate <class Abi> samesize<long long int, floatv<Abi>> llround(floatv<Abi> x);
4940b57cec5SDimitry Andrictemplate <class Abi> samesize<long long int, doublev<Abi>> llround(doublev<Abi> x);
4950b57cec5SDimitry Andrictemplate <class Abi> samesize<long long int, ldoublev<Abi>> llround(ldoublev<Abi> x);
4960b57cec5SDimitry Andric
4970b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> trunc(floatv<Abi> x);
4980b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> trunc(doublev<Abi> x);
4990b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> trunc(ldoublev<Abi> x);
5000b57cec5SDimitry Andric
5010b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> fmod(floatv<Abi> x, floatv<Abi> y);
5020b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> fmod(doublev<Abi> x, doublev<Abi> y);
5030b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> fmod(ldoublev<Abi> x, ldoublev<Abi> y);
5040b57cec5SDimitry Andric
5050b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> remainder(floatv<Abi> x, floatv<Abi> y);
5060b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> remainder(doublev<Abi> x, doublev<Abi> y);
5070b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> remainder(ldoublev<Abi> x, ldoublev<Abi> y);
5080b57cec5SDimitry Andric
5090b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> remquo(floatv<Abi> x, floatv<Abi> y, samesize<int, floatv<Abi>>* quo);
5100b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> remquo(doublev<Abi> x, doublev<Abi> y, samesize<int, doublev<Abi>>* quo);
5110b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> remquo(ldoublev<Abi> x, ldoublev<Abi> y, samesize<int, ldoublev<Abi>>* quo);
5120b57cec5SDimitry Andric
5130b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> copysign(floatv<Abi> x, floatv<Abi> y);
5140b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> copysign(doublev<Abi> x, doublev<Abi> y);
5150b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> copysign(ldoublev<Abi> x, ldoublev<Abi> y);
5160b57cec5SDimitry Andric
5170b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> nan(const char* tagp);
5180b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> nanf(const char* tagp);
5190b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> nanl(const char* tagp);
5200b57cec5SDimitry Andric
5210b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> nextafter(floatv<Abi> x, floatv<Abi> y);
5220b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> nextafter(doublev<Abi> x, doublev<Abi> y);
5230b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> nextafter(ldoublev<Abi> x, ldoublev<Abi> y);
5240b57cec5SDimitry Andric
5250b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> nexttoward(floatv<Abi> x, ldoublev<Abi> y);
5260b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> nexttoward(doublev<Abi> x, ldoublev<Abi> y);
5270b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> nexttoward(ldoublev<Abi> x, ldoublev<Abi> y);
5280b57cec5SDimitry Andric
5290b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> fdim(floatv<Abi> x, floatv<Abi> y);
5300b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> fdim(doublev<Abi> x, doublev<Abi> y);
5310b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> fdim(ldoublev<Abi> x, ldoublev<Abi> y);
5320b57cec5SDimitry Andric
5330b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> fmax(floatv<Abi> x, floatv<Abi> y);
5340b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> fmax(doublev<Abi> x, doublev<Abi> y);
5350b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> fmax(ldoublev<Abi> x, ldoublev<Abi> y);
5360b57cec5SDimitry Andric
5370b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> fmin(floatv<Abi> x, floatv<Abi> y);
5380b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> fmin(doublev<Abi> x, doublev<Abi> y);
5390b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> fmin(ldoublev<Abi> x, ldoublev<Abi> y);
5400b57cec5SDimitry Andric
5410b57cec5SDimitry Andrictemplate <class Abi> floatv<Abi> fma(floatv<Abi> x, floatv<Abi> y, floatv<Abi> z);
5420b57cec5SDimitry Andrictemplate <class Abi> doublev<Abi> fma(doublev<Abi> x, doublev<Abi> y, doublev<Abi> z);
5430b57cec5SDimitry Andrictemplate <class Abi> ldoublev<Abi> fma(ldoublev<Abi> x, ldoublev<Abi> y, ldoublev<Abi> z);
5440b57cec5SDimitry Andric
5450b57cec5SDimitry Andrictemplate <class Abi> samesize<int, floatv<Abi>> fpclassify(floatv<Abi> x);
5460b57cec5SDimitry Andrictemplate <class Abi> samesize<int, doublev<Abi>> fpclassify(doublev<Abi> x);
5470b57cec5SDimitry Andrictemplate <class Abi> samesize<int, ldoublev<Abi>> fpclassify(ldoublev<Abi> x);
5480b57cec5SDimitry Andric
5490b57cec5SDimitry Andrictemplate <class Abi> simd_mask<float, Abi> isfinite(floatv<Abi> x);
5500b57cec5SDimitry Andrictemplate <class Abi> simd_mask<double, Abi> isfinite(doublev<Abi> x);
5510b57cec5SDimitry Andrictemplate <class Abi> simd_mask<long double, Abi> isfinite(ldoublev<Abi> x);
5520b57cec5SDimitry Andric
5530b57cec5SDimitry Andrictemplate <class Abi> simd_mask<float, Abi> isinf(floatv<Abi> x);
5540b57cec5SDimitry Andrictemplate <class Abi> simd_mask<double, Abi> isinf(doublev<Abi> x);
5550b57cec5SDimitry Andrictemplate <class Abi> simd_mask<long double, Abi> isinf(ldoublev<Abi> x);
5560b57cec5SDimitry Andric
5570b57cec5SDimitry Andrictemplate <class Abi> simd_mask<float, Abi> isnan(floatv<Abi> x);
5580b57cec5SDimitry Andrictemplate <class Abi> simd_mask<double, Abi> isnan(doublev<Abi> x);
5590b57cec5SDimitry Andrictemplate <class Abi> simd_mask<long double, Abi> isnan(ldoublev<Abi> x);
5600b57cec5SDimitry Andric
5610b57cec5SDimitry Andrictemplate <class Abi> simd_mask<float, Abi> isnormal(floatv<Abi> x);
5620b57cec5SDimitry Andrictemplate <class Abi> simd_mask<double, Abi> isnormal(doublev<Abi> x);
5630b57cec5SDimitry Andrictemplate <class Abi> simd_mask<long double, Abi> isnormal(ldoublev<Abi> x);
5640b57cec5SDimitry Andric
5650b57cec5SDimitry Andrictemplate <class Abi> simd_mask<float, Abi> signbit(floatv<Abi> x);
5660b57cec5SDimitry Andrictemplate <class Abi> simd_mask<double, Abi> signbit(doublev<Abi> x);
5670b57cec5SDimitry Andrictemplate <class Abi> simd_mask<long double, Abi> signbit(ldoublev<Abi> x);
5680b57cec5SDimitry Andric
5690b57cec5SDimitry Andrictemplate <class Abi> simd_mask<float, Abi> isgreater(floatv<Abi> x, floatv<Abi> y);
5700b57cec5SDimitry Andrictemplate <class Abi> simd_mask<double, Abi> isgreater(doublev<Abi> x, doublev<Abi> y);
5710b57cec5SDimitry Andrictemplate <class Abi> simd_mask<long double, Abi> isgreater(ldoublev<Abi> x, ldoublev<Abi> y);
5720b57cec5SDimitry Andric
5730b57cec5SDimitry Andrictemplate <class Abi> simd_mask<float, Abi> isgreaterequal(floatv<Abi> x, floatv<Abi> y);
5740b57cec5SDimitry Andrictemplate <class Abi> simd_mask<double, Abi> isgreaterequal(doublev<Abi> x, doublev<Abi> y);
5750b57cec5SDimitry Andrictemplate <class Abi> simd_mask<long double, Abi> isgreaterequal(ldoublev<Abi> x, ldoublev<Abi> y);
5760b57cec5SDimitry Andric
5770b57cec5SDimitry Andrictemplate <class Abi> simd_mask<float, Abi> isless(floatv<Abi> x, floatv<Abi> y);
5780b57cec5SDimitry Andrictemplate <class Abi> simd_mask<double, Abi> isless(doublev<Abi> x, doublev<Abi> y);
5790b57cec5SDimitry Andrictemplate <class Abi> simd_mask<long double, Abi> isless(ldoublev<Abi> x, ldoublev<Abi> y);
5800b57cec5SDimitry Andric
5810b57cec5SDimitry Andrictemplate <class Abi> simd_mask<float, Abi> islessequal(floatv<Abi> x, floatv<Abi> y);
5820b57cec5SDimitry Andrictemplate <class Abi> simd_mask<double, Abi> islessequal(doublev<Abi> x, doublev<Abi> y);
5830b57cec5SDimitry Andrictemplate <class Abi> simd_mask<long double, Abi> islessequal(ldoublev<Abi> x, ldoublev<Abi> y);
5840b57cec5SDimitry Andric
5850b57cec5SDimitry Andrictemplate <class Abi> simd_mask<float, Abi> islessgreater(floatv<Abi> x, floatv<Abi> y);
5860b57cec5SDimitry Andrictemplate <class Abi> simd_mask<double, Abi> islessgreater(doublev<Abi> x, doublev<Abi> y);
5870b57cec5SDimitry Andrictemplate <class Abi> simd_mask<long double, Abi> islessgreater(ldoublev<Abi> x, ldoublev<Abi> y);
5880b57cec5SDimitry Andric
5890b57cec5SDimitry Andrictemplate <class Abi> simd_mask<float, Abi> isunordered(floatv<Abi> x, floatv<Abi> y);
5900b57cec5SDimitry Andrictemplate <class Abi> simd_mask<double, Abi> isunordered(doublev<Abi> x, doublev<Abi> y);
5910b57cec5SDimitry Andrictemplate <class Abi> simd_mask<long double, Abi> isunordered(ldoublev<Abi> x, ldoublev<Abi> y);
5920b57cec5SDimitry Andric
5930b57cec5SDimitry Andrictemplate <class V> struct simd_div_t { V quot, rem; };
5940b57cec5SDimitry Andrictemplate <class Abi> simd_div_t<scharv<Abi>> div(scharv<Abi> numer, scharv<Abi> denom);
5950b57cec5SDimitry Andrictemplate <class Abi> simd_div_t<shortv<Abi>> div(shortv<Abi> numer, shortv<Abi> denom);
5960b57cec5SDimitry Andrictemplate <class Abi> simd_div_t<intv<Abi>> div(intv<Abi> numer, intv<Abi> denom);
5970b57cec5SDimitry Andrictemplate <class Abi> simd_div_t<longv<Abi>> div(longv<Abi> numer, longv<Abi> denom);
5980b57cec5SDimitry Andrictemplate <class Abi> simd_div_t<llongv<Abi>> div(llongv<Abi> numer, llongv<Abi> denom);
5990b57cec5SDimitry Andric
6000b57cec5SDimitry Andric// [simd.mask.class]
6010b57cec5SDimitry Andrictemplate <class T, class Abi>
6020b57cec5SDimitry Andricclass simd_mask {
6030b57cec5SDimitry Andricpublic:
6040b57cec5SDimitry Andric  using value_type = bool;
6050b57cec5SDimitry Andric  using reference = see below;
6060b57cec5SDimitry Andric  using simd_type = simd<T, Abi>;
6070b57cec5SDimitry Andric  using abi_type = Abi;
6080b57cec5SDimitry Andric  static constexpr size_t size() noexcept;
6090b57cec5SDimitry Andric  simd_mask() = default;
6100b57cec5SDimitry Andric
6110b57cec5SDimitry Andric  // broadcast constructor
6120b57cec5SDimitry Andric  explicit simd_mask(value_type) noexcept;
6130b57cec5SDimitry Andric
6140b57cec5SDimitry Andric  // implicit type conversion constructor
6150b57cec5SDimitry Andric  template <class U> simd_mask(const simd_mask<U, simd_abi::fixed_size<size()>>&) noexcept;
6160b57cec5SDimitry Andric
6170b57cec5SDimitry Andric  // load constructor
6180b57cec5SDimitry Andric  template <class Flags> simd_mask(const value_type* mem, Flags);
6190b57cec5SDimitry Andric
6200b57cec5SDimitry Andric  // loads [simd.mask.copy]
6210b57cec5SDimitry Andric  template <class Flags> void copy_from(const value_type* mem, Flags);
6220b57cec5SDimitry Andric  template <class Flags> void copy_to(value_type* mem, Flags) const;
6230b57cec5SDimitry Andric
6240b57cec5SDimitry Andric  // scalar access [simd.mask.subscr]
6250b57cec5SDimitry Andric  reference operator[](size_t);
6260b57cec5SDimitry Andric  value_type operator[](size_t) const;
6270b57cec5SDimitry Andric
6280b57cec5SDimitry Andric  // unary operators [simd.mask.unary]
6290b57cec5SDimitry Andric  simd_mask operator!() const noexcept;
6300b57cec5SDimitry Andric
6310b57cec5SDimitry Andric  // simd_mask binary operators [simd.mask.binary]
6320b57cec5SDimitry Andric  friend simd_mask operator&&(const simd_mask&, const simd_mask&) noexcept;
6330b57cec5SDimitry Andric  friend simd_mask operator||(const simd_mask&, const simd_mask&) noexcept;
6340b57cec5SDimitry Andric  friend simd_mask operator& (const simd_mask&, const simd_mask&) noexcept;
6350b57cec5SDimitry Andric  friend simd_mask operator| (const simd_mask&, const simd_mask&) noexcept;
6360b57cec5SDimitry Andric  friend simd_mask operator^ (const simd_mask&, const simd_mask&) noexcept;
6370b57cec5SDimitry Andric
6380b57cec5SDimitry Andric  // simd_mask compound assignment [simd.mask.cassign]
6390b57cec5SDimitry Andric  friend simd_mask& operator&=(simd_mask&, const simd_mask&) noexcept;
6400b57cec5SDimitry Andric  friend simd_mask& operator|=(simd_mask&, const simd_mask&) noexcept;
6410b57cec5SDimitry Andric  friend simd_mask& operator^=(simd_mask&, const simd_mask&) noexcept;
6420b57cec5SDimitry Andric
6430b57cec5SDimitry Andric  // simd_mask compares [simd.mask.comparison]
6440b57cec5SDimitry Andric  friend simd_mask operator==(const simd_mask&, const simd_mask&) noexcept;
6450b57cec5SDimitry Andric  friend simd_mask operator!=(const simd_mask&, const simd_mask&) noexcept;
6460b57cec5SDimitry Andric};
6470b57cec5SDimitry Andric
6480b57cec5SDimitry Andric} // parallelism_v2
6490b57cec5SDimitry Andric} // std::experimental
6500b57cec5SDimitry Andric
6510b57cec5SDimitry Andric*/
6520b57cec5SDimitry Andric
65381ad6265SDimitry Andric#include <__assert> // all public C++ headers provide the assertion handler
65481ad6265SDimitry Andric#include <__functional/operations.h>
6550b57cec5SDimitry Andric#include <array>
6560b57cec5SDimitry Andric#include <cstddef>
65704eeddc0SDimitry Andric#include <experimental/__config>
65881ad6265SDimitry Andric#include <tuple>
65981ad6265SDimitry Andric
6600b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
6610b57cec5SDimitry Andric#  pragma GCC system_header
6620b57cec5SDimitry Andric#endif
6630b57cec5SDimitry Andric
664e8d8bef9SDimitry Andric_LIBCPP_PUSH_MACROS
665e8d8bef9SDimitry Andric#include <__undef_macros>
666e8d8bef9SDimitry Andric
6670b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_SIMD
6680b57cec5SDimitry Andric
6690b57cec5SDimitry Andric#if _LIBCPP_STD_VER >= 17
6700b57cec5SDimitry Andric
6710b57cec5SDimitry Andricenum class _StorageKind {
6720b57cec5SDimitry Andric  _Scalar,
6730b57cec5SDimitry Andric  _Array,
6740b57cec5SDimitry Andric  _VecExt,
6750b57cec5SDimitry Andric};
6760b57cec5SDimitry Andric
6770b57cec5SDimitry Andrictemplate <_StorageKind __kind, int _Np>
6780b57cec5SDimitry Andricstruct __simd_abi {};
6790b57cec5SDimitry Andric
6800b57cec5SDimitry Andrictemplate <class _Tp, class _Abi>
6810b57cec5SDimitry Andricclass __simd_storage {};
6820b57cec5SDimitry Andric
6830b57cec5SDimitry Andrictemplate <class _Tp, int __num_element>
6840b57cec5SDimitry Andricclass __simd_storage<_Tp, __simd_abi<_StorageKind::_Array, __num_element>> {
6850b57cec5SDimitry Andric  std::array<_Tp, __num_element> __storage_;
6860b57cec5SDimitry Andric
6870b57cec5SDimitry Andric  template <class, class>
6880b57cec5SDimitry Andric  friend struct simd;
6890b57cec5SDimitry Andric
6900b57cec5SDimitry Andric  template <class, class>
6910b57cec5SDimitry Andric  friend struct simd_mask;
6920b57cec5SDimitry Andric
6930b57cec5SDimitry Andricpublic:
69404eeddc0SDimitry Andric  _Tp __get(size_t __index) const noexcept { return __storage_[__index]; }
6950b57cec5SDimitry Andric  void __set(size_t __index, _Tp __val) noexcept {
6960b57cec5SDimitry Andric    __storage_[__index] = __val;
6970b57cec5SDimitry Andric  }
6980b57cec5SDimitry Andric};
6990b57cec5SDimitry Andric
7000b57cec5SDimitry Andrictemplate <class _Tp>
7010b57cec5SDimitry Andricclass __simd_storage<_Tp, __simd_abi<_StorageKind::_Scalar, 1>> {
7020b57cec5SDimitry Andric  _Tp __storage_;
7030b57cec5SDimitry Andric
7040b57cec5SDimitry Andric  template <class, class>
7050b57cec5SDimitry Andric  friend struct simd;
7060b57cec5SDimitry Andric
7070b57cec5SDimitry Andric  template <class, class>
7080b57cec5SDimitry Andric  friend struct simd_mask;
7090b57cec5SDimitry Andric
7100b57cec5SDimitry Andricpublic:
71104eeddc0SDimitry Andric  _Tp __get(size_t __index) const noexcept { return (&__storage_)[__index]; }
7120b57cec5SDimitry Andric  void __set(size_t __index, _Tp __val) noexcept {
7130b57cec5SDimitry Andric    (&__storage_)[__index] = __val;
7140b57cec5SDimitry Andric  }
7150b57cec5SDimitry Andric};
7160b57cec5SDimitry Andric
7170b57cec5SDimitry Andric#ifndef _LIBCPP_HAS_NO_VECTOR_EXTENSION
7180b57cec5SDimitry Andric
719*bdd1243dSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr size_t __floor_pow_of_2(size_t __val) {
7200b57cec5SDimitry Andric  return ((__val - 1) & __val) == 0 ? __val
7210b57cec5SDimitry Andric                                    : __floor_pow_of_2((__val - 1) & __val);
7220b57cec5SDimitry Andric}
7230b57cec5SDimitry Andric
724*bdd1243dSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr size_t __ceil_pow_of_2(size_t __val) {
7250b57cec5SDimitry Andric  return __val == 1 ? 1 : __floor_pow_of_2(__val - 1) << 1;
7260b57cec5SDimitry Andric}
7270b57cec5SDimitry Andric
7280b57cec5SDimitry Andrictemplate <class _Tp, size_t __bytes>
7290b57cec5SDimitry Andricstruct __vec_ext_traits {
730fe6060f1SDimitry Andric#if !defined(_LIBCPP_COMPILER_CLANG_BASED)
7310b57cec5SDimitry Andric  typedef _Tp type __attribute__((vector_size(__ceil_pow_of_2(__bytes))));
7320b57cec5SDimitry Andric#endif
7330b57cec5SDimitry Andric};
7340b57cec5SDimitry Andric
735fe6060f1SDimitry Andric#if defined(_LIBCPP_COMPILER_CLANG_BASED)
7360b57cec5SDimitry Andric#define _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, _NUM_ELEMENT)                        \
7370b57cec5SDimitry Andric  template <>                                                                  \
7380b57cec5SDimitry Andric  struct __vec_ext_traits<_TYPE, sizeof(_TYPE) * _NUM_ELEMENT> {               \
7390b57cec5SDimitry Andric    using type =                                                               \
7400b57cec5SDimitry Andric        _TYPE __attribute__((vector_size(sizeof(_TYPE) * _NUM_ELEMENT)));      \
7410b57cec5SDimitry Andric  }
7420b57cec5SDimitry Andric
7430b57cec5SDimitry Andric#define _LIBCPP_SPECIALIZE_VEC_EXT_32(_TYPE)                                   \
7440b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 1);                                        \
7450b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 2);                                        \
7460b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 3);                                        \
7470b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 4);                                        \
7480b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 5);                                        \
7490b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 6);                                        \
7500b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 7);                                        \
7510b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 8);                                        \
7520b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 9);                                        \
7530b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 10);                                       \
7540b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 11);                                       \
7550b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 12);                                       \
7560b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 13);                                       \
7570b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 14);                                       \
7580b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 15);                                       \
7590b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 16);                                       \
7600b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 17);                                       \
7610b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 18);                                       \
7620b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 19);                                       \
7630b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 20);                                       \
7640b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 21);                                       \
7650b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 22);                                       \
7660b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 23);                                       \
7670b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 24);                                       \
7680b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 25);                                       \
7690b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 26);                                       \
7700b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 27);                                       \
7710b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 28);                                       \
7720b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 29);                                       \
7730b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 30);                                       \
7740b57cec5SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 31);                                       \
77504eeddc0SDimitry Andric  _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 32)
7760b57cec5SDimitry Andric
7770b57cec5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(char);
7780b57cec5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(char16_t);
7790b57cec5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(char32_t);
7800b57cec5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(wchar_t);
7810b57cec5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(signed char);
7820b57cec5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(signed short);
7830b57cec5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(signed int);
7840b57cec5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(signed long);
7850b57cec5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(signed long long);
7860b57cec5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned char);
7870b57cec5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned short);
7880b57cec5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned int);
7890b57cec5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned long);
7900b57cec5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned long long);
7910b57cec5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(float);
7920b57cec5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(double);
7930b57cec5SDimitry Andric_LIBCPP_SPECIALIZE_VEC_EXT_32(long double);
7940b57cec5SDimitry Andric
7950b57cec5SDimitry Andric#undef _LIBCPP_SPECIALIZE_VEC_EXT_32
7960b57cec5SDimitry Andric#undef _LIBCPP_SPECIALIZE_VEC_EXT
7970b57cec5SDimitry Andric#endif
7980b57cec5SDimitry Andric
7990b57cec5SDimitry Andrictemplate <class _Tp, int __num_element>
8000b57cec5SDimitry Andricclass __simd_storage<_Tp, __simd_abi<_StorageKind::_VecExt, __num_element>> {
8010b57cec5SDimitry Andric  using _StorageType =
8020b57cec5SDimitry Andric      typename __vec_ext_traits<_Tp, sizeof(_Tp) * __num_element>::type;
8030b57cec5SDimitry Andric
8040b57cec5SDimitry Andric  _StorageType __storage_;
8050b57cec5SDimitry Andric
8060b57cec5SDimitry Andric  template <class, class>
8070b57cec5SDimitry Andric  friend struct simd;
8080b57cec5SDimitry Andric
8090b57cec5SDimitry Andric  template <class, class>
8100b57cec5SDimitry Andric  friend struct simd_mask;
8110b57cec5SDimitry Andric
8120b57cec5SDimitry Andricpublic:
81304eeddc0SDimitry Andric  _Tp __get(size_t __index) const noexcept { return __storage_[__index]; }
8140b57cec5SDimitry Andric  void __set(size_t __index, _Tp __val) noexcept {
8150b57cec5SDimitry Andric    __storage_[__index] = __val;
8160b57cec5SDimitry Andric  }
8170b57cec5SDimitry Andric};
8180b57cec5SDimitry Andric
8190b57cec5SDimitry Andric#endif // _LIBCPP_HAS_NO_VECTOR_EXTENSION
8200b57cec5SDimitry Andric
8210b57cec5SDimitry Andrictemplate <class _Vp, class _Tp, class _Abi>
8220b57cec5SDimitry Andricclass __simd_reference {
8230b57cec5SDimitry Andric  static_assert(std::is_same<_Vp, _Tp>::value, "");
8240b57cec5SDimitry Andric
8250b57cec5SDimitry Andric  template <class, class>
8260b57cec5SDimitry Andric  friend struct simd;
8270b57cec5SDimitry Andric
8280b57cec5SDimitry Andric  template <class, class>
8290b57cec5SDimitry Andric  friend struct simd_mask;
8300b57cec5SDimitry Andric
8310b57cec5SDimitry Andric  __simd_storage<_Tp, _Abi>* __ptr_;
8320b57cec5SDimitry Andric  size_t __index_;
8330b57cec5SDimitry Andric
8340b57cec5SDimitry Andric  __simd_reference(__simd_storage<_Tp, _Abi>* __ptr, size_t __index)
8350b57cec5SDimitry Andric      : __ptr_(__ptr), __index_(__index) {}
8360b57cec5SDimitry Andric
8370b57cec5SDimitry Andric  __simd_reference(const __simd_reference&) = default;
8380b57cec5SDimitry Andric
8390b57cec5SDimitry Andricpublic:
8400b57cec5SDimitry Andric  __simd_reference() = delete;
8410b57cec5SDimitry Andric  __simd_reference& operator=(const __simd_reference&) = delete;
8420b57cec5SDimitry Andric
8430b57cec5SDimitry Andric  operator _Vp() const { return __ptr_->__get(__index_); }
8440b57cec5SDimitry Andric
8450b57cec5SDimitry Andric  __simd_reference operator=(_Vp __value) && {
8460b57cec5SDimitry Andric    __ptr_->__set(__index_, __value);
8470b57cec5SDimitry Andric    return *this;
8480b57cec5SDimitry Andric  }
8490b57cec5SDimitry Andric
8500b57cec5SDimitry Andric  __simd_reference operator++() && {
8510b57cec5SDimitry Andric    return std::move(*this) = __ptr_->__get(__index_) + 1;
8520b57cec5SDimitry Andric  }
8530b57cec5SDimitry Andric
8540b57cec5SDimitry Andric  _Vp operator++(int) && {
8550b57cec5SDimitry Andric    auto __val = __ptr_->__get(__index_);
8560b57cec5SDimitry Andric    __ptr_->__set(__index_, __val + 1);
8570b57cec5SDimitry Andric    return __val;
8580b57cec5SDimitry Andric  }
8590b57cec5SDimitry Andric
8600b57cec5SDimitry Andric  __simd_reference operator--() && {
8610b57cec5SDimitry Andric    return std::move(*this) = __ptr_->__get(__index_) - 1;
8620b57cec5SDimitry Andric  }
8630b57cec5SDimitry Andric
8640b57cec5SDimitry Andric  _Vp operator--(int) && {
8650b57cec5SDimitry Andric    auto __val = __ptr_->__get(__index_);
8660b57cec5SDimitry Andric    __ptr_->__set(__index_, __val - 1);
8670b57cec5SDimitry Andric    return __val;
8680b57cec5SDimitry Andric  }
8690b57cec5SDimitry Andric
8700b57cec5SDimitry Andric  __simd_reference operator+=(_Vp __value) && {
8710b57cec5SDimitry Andric    return std::move(*this) = __ptr_->__get(__index_) + __value;
8720b57cec5SDimitry Andric  }
8730b57cec5SDimitry Andric
8740b57cec5SDimitry Andric  __simd_reference operator-=(_Vp __value) && {
8750b57cec5SDimitry Andric    return std::move(*this) = __ptr_->__get(__index_) - __value;
8760b57cec5SDimitry Andric  }
8770b57cec5SDimitry Andric
8780b57cec5SDimitry Andric  __simd_reference operator*=(_Vp __value) && {
8790b57cec5SDimitry Andric    return std::move(*this) = __ptr_->__get(__index_) * __value;
8800b57cec5SDimitry Andric  }
8810b57cec5SDimitry Andric
8820b57cec5SDimitry Andric  __simd_reference operator/=(_Vp __value) && {
8830b57cec5SDimitry Andric    return std::move(*this) = __ptr_->__get(__index_) / __value;
8840b57cec5SDimitry Andric  }
8850b57cec5SDimitry Andric
8860b57cec5SDimitry Andric  __simd_reference operator%=(_Vp __value) && {
8870b57cec5SDimitry Andric    return std::move(*this) = __ptr_->__get(__index_) % __value;
8880b57cec5SDimitry Andric  }
8890b57cec5SDimitry Andric
8900b57cec5SDimitry Andric  __simd_reference operator>>=(_Vp __value) && {
8910b57cec5SDimitry Andric    return std::move(*this) = __ptr_->__get(__index_) >> __value;
8920b57cec5SDimitry Andric  }
8930b57cec5SDimitry Andric
8940b57cec5SDimitry Andric  __simd_reference operator<<=(_Vp __value) && {
8950b57cec5SDimitry Andric    return std::move(*this) = __ptr_->__get(__index_) << __value;
8960b57cec5SDimitry Andric  }
8970b57cec5SDimitry Andric
8980b57cec5SDimitry Andric  __simd_reference operator&=(_Vp __value) && {
8990b57cec5SDimitry Andric    return std::move(*this) = __ptr_->__get(__index_) & __value;
9000b57cec5SDimitry Andric  }
9010b57cec5SDimitry Andric
9020b57cec5SDimitry Andric  __simd_reference operator|=(_Vp __value) && {
9030b57cec5SDimitry Andric    return std::move(*this) = __ptr_->__get(__index_) | __value;
9040b57cec5SDimitry Andric  }
9050b57cec5SDimitry Andric
9060b57cec5SDimitry Andric  __simd_reference operator^=(_Vp __value) && {
9070b57cec5SDimitry Andric    return std::move(*this) = __ptr_->__get(__index_) ^ __value;
9080b57cec5SDimitry Andric  }
9090b57cec5SDimitry Andric};
9100b57cec5SDimitry Andric
9110b57cec5SDimitry Andrictemplate <class _To, class _From>
912*bdd1243dSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr decltype(_To{std::declval<_From>()}, true)
9130b57cec5SDimitry Andric__is_non_narrowing_convertible_impl(_From) {
9140b57cec5SDimitry Andric  return true;
9150b57cec5SDimitry Andric}
9160b57cec5SDimitry Andric
9170b57cec5SDimitry Andrictemplate <class _To>
918*bdd1243dSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool __is_non_narrowing_convertible_impl(...) {
9190b57cec5SDimitry Andric  return false;
9200b57cec5SDimitry Andric}
9210b57cec5SDimitry Andric
9220b57cec5SDimitry Andrictemplate <class _From, class _To>
923*bdd1243dSDimitry Andric_LIBCPP_HIDE_FROM_ABI
9240b57cec5SDimitry Andricconstexpr typename std::enable_if<std::is_arithmetic<_To>::value &&
9250b57cec5SDimitry Andric                                      std::is_arithmetic<_From>::value,
9260b57cec5SDimitry Andric                                  bool>::type
9270b57cec5SDimitry Andric__is_non_narrowing_arithmetic_convertible() {
928*bdd1243dSDimitry Andric  return experimental::__is_non_narrowing_convertible_impl<_To>(_From{});
9290b57cec5SDimitry Andric}
9300b57cec5SDimitry Andric
9310b57cec5SDimitry Andrictemplate <class _From, class _To>
932*bdd1243dSDimitry Andric_LIBCPP_HIDE_FROM_ABI
9330b57cec5SDimitry Andricconstexpr typename std::enable_if<!(std::is_arithmetic<_To>::value &&
9340b57cec5SDimitry Andric                                    std::is_arithmetic<_From>::value),
9350b57cec5SDimitry Andric                                  bool>::type
9360b57cec5SDimitry Andric__is_non_narrowing_arithmetic_convertible() {
9370b57cec5SDimitry Andric  return false;
9380b57cec5SDimitry Andric}
9390b57cec5SDimitry Andric
9400b57cec5SDimitry Andrictemplate <class _Tp>
941*bdd1243dSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr _Tp __variadic_sum() {
9420b57cec5SDimitry Andric  return _Tp{};
9430b57cec5SDimitry Andric}
9440b57cec5SDimitry Andric
9450b57cec5SDimitry Andrictemplate <class _Tp, class _Up, class... _Args>
946*bdd1243dSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr _Tp __variadic_sum(_Up __first, _Args... __rest) {
947*bdd1243dSDimitry Andric  return static_cast<_Tp>(__first) + experimental::__variadic_sum<_Tp>(__rest...);
9480b57cec5SDimitry Andric}
9490b57cec5SDimitry Andric
9500b57cec5SDimitry Andrictemplate <class _Tp>
9510b57cec5SDimitry Andricstruct __nodeduce {
9520b57cec5SDimitry Andric  using type = _Tp;
9530b57cec5SDimitry Andric};
9540b57cec5SDimitry Andric
9550b57cec5SDimitry Andrictemplate <class _Tp>
956*bdd1243dSDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool __vectorizable() {
9570b57cec5SDimitry Andric  return std::is_arithmetic<_Tp>::value && !std::is_const<_Tp>::value &&
9580b57cec5SDimitry Andric         !std::is_volatile<_Tp>::value && !std::is_same<_Tp, bool>::value;
9590b57cec5SDimitry Andric}
9600b57cec5SDimitry Andric
9610b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_EXPERIMENTAL_SIMD
9620b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_SIMD_ABI
9630b57cec5SDimitry Andric
9640b57cec5SDimitry Andricusing scalar = __simd_abi<_StorageKind::_Scalar, 1>;
9650b57cec5SDimitry Andric
9660b57cec5SDimitry Andrictemplate <int _Np>
9670b57cec5SDimitry Andricusing fixed_size = __simd_abi<_StorageKind::_Array, _Np>;
9680b57cec5SDimitry Andric
9690b57cec5SDimitry Andrictemplate <class _Tp>
970349cc55cSDimitry Andricinline constexpr size_t max_fixed_size = 32;
9710b57cec5SDimitry Andric
9720b57cec5SDimitry Andrictemplate <class _Tp>
9730b57cec5SDimitry Andricusing compatible = fixed_size<16 / sizeof(_Tp)>;
9740b57cec5SDimitry Andric
9750b57cec5SDimitry Andric#ifndef _LIBCPP_HAS_NO_VECTOR_EXTENSION
9760b57cec5SDimitry Andrictemplate <class _Tp>
9770b57cec5SDimitry Andricusing native = __simd_abi<_StorageKind::_VecExt,
9780b57cec5SDimitry Andric                          _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES / sizeof(_Tp)>;
9790b57cec5SDimitry Andric#else
9800b57cec5SDimitry Andrictemplate <class _Tp>
9810b57cec5SDimitry Andricusing native =
9820b57cec5SDimitry Andric    fixed_size<_Tp, _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES / sizeof(_Tp)>;
9830b57cec5SDimitry Andric#endif // _LIBCPP_HAS_NO_VECTOR_EXTENSION
9840b57cec5SDimitry Andric
9850b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_EXPERIMENTAL_SIMD_ABI
9860b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_SIMD
9870b57cec5SDimitry Andric
9880b57cec5SDimitry Andrictemplate <class _Tp, class _Abi = simd_abi::compatible<_Tp>>
9890b57cec5SDimitry Andricclass simd;
9900b57cec5SDimitry Andrictemplate <class _Tp, class _Abi = simd_abi::compatible<_Tp>>
9910b57cec5SDimitry Andricclass simd_mask;
9920b57cec5SDimitry Andric
9930b57cec5SDimitry Andricstruct element_aligned_tag {};
9940b57cec5SDimitry Andricstruct vector_aligned_tag {};
9950b57cec5SDimitry Andrictemplate <size_t>
9960b57cec5SDimitry Andricstruct overaligned_tag {};
997349cc55cSDimitry Andricinline constexpr element_aligned_tag element_aligned{};
998349cc55cSDimitry Andricinline constexpr vector_aligned_tag vector_aligned{};
9990b57cec5SDimitry Andrictemplate <size_t _Np>
1000349cc55cSDimitry Andricinline constexpr overaligned_tag<_Np> overaligned{};
10010b57cec5SDimitry Andric
10020b57cec5SDimitry Andric// traits [simd.traits]
10030b57cec5SDimitry Andrictemplate <class _Tp>
10040b57cec5SDimitry Andricstruct is_abi_tag : std::integral_constant<bool, false> {};
10050b57cec5SDimitry Andric
10060b57cec5SDimitry Andrictemplate <_StorageKind __kind, int _Np>
10070b57cec5SDimitry Andricstruct is_abi_tag<__simd_abi<__kind, _Np>>
10080b57cec5SDimitry Andric    : std::integral_constant<bool, true> {};
10090b57cec5SDimitry Andric
10100b57cec5SDimitry Andrictemplate <class _Tp>
10110b57cec5SDimitry Andricstruct is_simd : std::integral_constant<bool, false> {};
10120b57cec5SDimitry Andric
10130b57cec5SDimitry Andrictemplate <class _Tp, class _Abi>
10140b57cec5SDimitry Andricstruct is_simd<simd<_Tp, _Abi>> : std::integral_constant<bool, true> {};
10150b57cec5SDimitry Andric
10160b57cec5SDimitry Andrictemplate <class _Tp>
10170b57cec5SDimitry Andricstruct is_simd_mask : std::integral_constant<bool, false> {};
10180b57cec5SDimitry Andric
10190b57cec5SDimitry Andrictemplate <class _Tp, class _Abi>
10200b57cec5SDimitry Andricstruct is_simd_mask<simd_mask<_Tp, _Abi>> : std::integral_constant<bool, true> {
10210b57cec5SDimitry Andric};
10220b57cec5SDimitry Andric
10230b57cec5SDimitry Andrictemplate <class _Tp>
10240b57cec5SDimitry Andricstruct is_simd_flag_type : std::integral_constant<bool, false> {};
10250b57cec5SDimitry Andric
10260b57cec5SDimitry Andrictemplate <>
10270b57cec5SDimitry Andricstruct is_simd_flag_type<element_aligned_tag>
10280b57cec5SDimitry Andric    : std::integral_constant<bool, true> {};
10290b57cec5SDimitry Andric
10300b57cec5SDimitry Andrictemplate <>
10310b57cec5SDimitry Andricstruct is_simd_flag_type<vector_aligned_tag>
10320b57cec5SDimitry Andric    : std::integral_constant<bool, true> {};
10330b57cec5SDimitry Andric
10340b57cec5SDimitry Andrictemplate <size_t _Align>
10350b57cec5SDimitry Andricstruct is_simd_flag_type<overaligned_tag<_Align>>
10360b57cec5SDimitry Andric    : std::integral_constant<bool, true> {};
10370b57cec5SDimitry Andric
10380b57cec5SDimitry Andrictemplate <class _Tp>
1039349cc55cSDimitry Andricinline constexpr bool is_abi_tag_v = is_abi_tag<_Tp>::value;
10400b57cec5SDimitry Andrictemplate <class _Tp>
1041349cc55cSDimitry Andricinline constexpr bool is_simd_v = is_simd<_Tp>::value;
10420b57cec5SDimitry Andrictemplate <class _Tp>
1043349cc55cSDimitry Andricinline constexpr bool is_simd_mask_v = is_simd_mask<_Tp>::value;
10440b57cec5SDimitry Andrictemplate <class _Tp>
1045349cc55cSDimitry Andricinline constexpr bool is_simd_flag_type_v = is_simd_flag_type<_Tp>::value;
10460b57cec5SDimitry Andrictemplate <class _Tp, size_t _Np>
10470b57cec5SDimitry Andricstruct abi_for_size {
10480b57cec5SDimitry Andric  using type = simd_abi::fixed_size<_Np>;
10490b57cec5SDimitry Andric};
10500b57cec5SDimitry Andrictemplate <class _Tp, size_t _Np>
10510b57cec5SDimitry Andricusing abi_for_size_t = typename abi_for_size<_Tp, _Np>::type;
10520b57cec5SDimitry Andric
10530b57cec5SDimitry Andrictemplate <class _Tp, class _Abi = simd_abi::compatible<_Tp>>
10540b57cec5SDimitry Andricstruct simd_size;
10550b57cec5SDimitry Andric
10560b57cec5SDimitry Andrictemplate <class _Tp, _StorageKind __kind, int _Np>
10570b57cec5SDimitry Andricstruct simd_size<_Tp, __simd_abi<__kind, _Np>>
10580b57cec5SDimitry Andric    : std::integral_constant<size_t, _Np> {
10590b57cec5SDimitry Andric  static_assert(
10600b57cec5SDimitry Andric      std::is_arithmetic<_Tp>::value &&
1061*bdd1243dSDimitry Andric          !std::is_same<__remove_const_t<_Tp>, bool>::value,
10620b57cec5SDimitry Andric      "Element type should be vectorizable");
10630b57cec5SDimitry Andric};
10640b57cec5SDimitry Andric
10650b57cec5SDimitry Andric// TODO: implement it.
10660b57cec5SDimitry Andrictemplate <class _Tp, class _Up = typename _Tp::value_type>
10670b57cec5SDimitry Andricstruct memory_alignment;
10680b57cec5SDimitry Andric
10690b57cec5SDimitry Andrictemplate <class _Tp, class _Abi = simd_abi::compatible<_Tp>>
1070349cc55cSDimitry Andricinline constexpr size_t simd_size_v = simd_size<_Tp, _Abi>::value;
10710b57cec5SDimitry Andric
10720b57cec5SDimitry Andrictemplate <class _Tp, class _Up = typename _Tp::value_type>
1073349cc55cSDimitry Andricinline constexpr size_t memory_alignment_v = memory_alignment<_Tp, _Up>::value;
10740b57cec5SDimitry Andric
10750b57cec5SDimitry Andric// class template simd [simd.class]
10760b57cec5SDimitry Andrictemplate <class _Tp>
10770b57cec5SDimitry Andricusing native_simd = simd<_Tp, simd_abi::native<_Tp>>;
10780b57cec5SDimitry Andrictemplate <class _Tp, int _Np>
10790b57cec5SDimitry Andricusing fixed_size_simd = simd<_Tp, simd_abi::fixed_size<_Np>>;
10800b57cec5SDimitry Andric
10810b57cec5SDimitry Andric// class template simd_mask [simd.mask.class]
10820b57cec5SDimitry Andrictemplate <class _Tp>
10830b57cec5SDimitry Andricusing native_simd_mask = simd_mask<_Tp, simd_abi::native<_Tp>>;
10840b57cec5SDimitry Andric
10850b57cec5SDimitry Andrictemplate <class _Tp, int _Np>
10860b57cec5SDimitry Andricusing fixed_size_simd_mask = simd_mask<_Tp, simd_abi::fixed_size<_Np>>;
10870b57cec5SDimitry Andric
10880b57cec5SDimitry Andric// casts [simd.casts]
10890b57cec5SDimitry Andrictemplate <class _Tp>
10900b57cec5SDimitry Andricstruct __static_simd_cast_traits {
10910b57cec5SDimitry Andric  template <class _Up, class _Abi>
10920b57cec5SDimitry Andric  static simd<_Tp, _Abi> __apply(const simd<_Up, _Abi>& __v);
10930b57cec5SDimitry Andric};
10940b57cec5SDimitry Andric
10950b57cec5SDimitry Andrictemplate <class _Tp, class _NewAbi>
10960b57cec5SDimitry Andricstruct __static_simd_cast_traits<simd<_Tp, _NewAbi>> {
10970b57cec5SDimitry Andric  template <class _Up, class _Abi>
10980b57cec5SDimitry Andric  static typename std::enable_if<simd<_Up, _Abi>::size() ==
10990b57cec5SDimitry Andric                                     simd<_Tp, _NewAbi>::size(),
11000b57cec5SDimitry Andric                                 simd<_Tp, _NewAbi>>::type
11010b57cec5SDimitry Andric  __apply(const simd<_Up, _Abi>& __v);
11020b57cec5SDimitry Andric};
11030b57cec5SDimitry Andric
11040b57cec5SDimitry Andrictemplate <class _Tp>
11050b57cec5SDimitry Andricstruct __simd_cast_traits {
11060b57cec5SDimitry Andric  template <class _Up, class _Abi>
11070b57cec5SDimitry Andric  static typename std::enable_if<
11080b57cec5SDimitry Andric      __is_non_narrowing_arithmetic_convertible<_Up, _Tp>(),
11090b57cec5SDimitry Andric      simd<_Tp, _Abi>>::type
11100b57cec5SDimitry Andric  __apply(const simd<_Up, _Abi>& __v);
11110b57cec5SDimitry Andric};
11120b57cec5SDimitry Andric
11130b57cec5SDimitry Andrictemplate <class _Tp, class _NewAbi>
11140b57cec5SDimitry Andricstruct __simd_cast_traits<simd<_Tp, _NewAbi>> {
11150b57cec5SDimitry Andric  template <class _Up, class _Abi>
11160b57cec5SDimitry Andric  static typename std::enable_if<
11170b57cec5SDimitry Andric      __is_non_narrowing_arithmetic_convertible<_Up, _Tp>() &&
11180b57cec5SDimitry Andric          simd<_Up, _Abi>::size() == simd<_Tp, _NewAbi>::size(),
11190b57cec5SDimitry Andric      simd<_Tp, _NewAbi>>::type
11200b57cec5SDimitry Andric  __apply(const simd<_Up, _Abi>& __v);
11210b57cec5SDimitry Andric};
11220b57cec5SDimitry Andric
11230b57cec5SDimitry Andrictemplate <class _Tp, class _Up, class _Abi>
1124*bdd1243dSDimitry Andric_LIBCPP_HIDE_FROM_ABI auto simd_cast(const simd<_Up, _Abi>& __v)
11250b57cec5SDimitry Andric    -> decltype(__simd_cast_traits<_Tp>::__apply(__v)) {
11260b57cec5SDimitry Andric  return __simd_cast_traits<_Tp>::__apply(__v);
11270b57cec5SDimitry Andric}
11280b57cec5SDimitry Andric
11290b57cec5SDimitry Andrictemplate <class _Tp, class _Up, class _Abi>
1130*bdd1243dSDimitry Andric_LIBCPP_HIDE_FROM_ABI auto static_simd_cast(const simd<_Up, _Abi>& __v)
11310b57cec5SDimitry Andric    -> decltype(__static_simd_cast_traits<_Tp>::__apply(__v)) {
11320b57cec5SDimitry Andric  return __static_simd_cast_traits<_Tp>::__apply(__v);
11330b57cec5SDimitry Andric}
11340b57cec5SDimitry Andric
11350b57cec5SDimitry Andrictemplate <class _Tp, class _Abi>
11360b57cec5SDimitry Andricfixed_size_simd<_Tp, simd_size<_Tp, _Abi>::value>
11370b57cec5SDimitry Andricto_fixed_size(const simd<_Tp, _Abi>&) noexcept;
11380b57cec5SDimitry Andric
11390b57cec5SDimitry Andrictemplate <class _Tp, class _Abi>
11400b57cec5SDimitry Andricfixed_size_simd_mask<_Tp, simd_size<_Tp, _Abi>::value>
11410b57cec5SDimitry Andricto_fixed_size(const simd_mask<_Tp, _Abi>&) noexcept;
11420b57cec5SDimitry Andric
11430b57cec5SDimitry Andrictemplate <class _Tp, size_t _Np>
11440b57cec5SDimitry Andricnative_simd<_Tp> to_native(const fixed_size_simd<_Tp, _Np>&) noexcept;
11450b57cec5SDimitry Andric
11460b57cec5SDimitry Andrictemplate <class _Tp, size_t _Np>
11470b57cec5SDimitry Andricnative_simd_mask<_Tp> to_native(const fixed_size_simd_mask<_Tp, _Np>&) noexcept;
11480b57cec5SDimitry Andric
11490b57cec5SDimitry Andrictemplate <class _Tp, size_t _Np>
11500b57cec5SDimitry Andricsimd<_Tp> to_compatible(const fixed_size_simd<_Tp, _Np>&) noexcept;
11510b57cec5SDimitry Andric
11520b57cec5SDimitry Andrictemplate <class _Tp, size_t _Np>
11530b57cec5SDimitry Andricsimd_mask<_Tp> to_compatible(const fixed_size_simd_mask<_Tp, _Np>&) noexcept;
11540b57cec5SDimitry Andric
11550b57cec5SDimitry Andrictemplate <size_t... __sizes, class _Tp, class _Abi>
11560b57cec5SDimitry Andrictuple<simd<_Tp, abi_for_size_t<_Tp, __sizes>>...> split(const simd<_Tp, _Abi>&);
11570b57cec5SDimitry Andric
11580b57cec5SDimitry Andrictemplate <size_t... __sizes, class _Tp, class _Abi>
11590b57cec5SDimitry Andrictuple<simd_mask<_Tp, abi_for_size_t<_Tp, __sizes>>...>
11600b57cec5SDimitry Andricsplit(const simd_mask<_Tp, _Abi>&);
11610b57cec5SDimitry Andric
11620b57cec5SDimitry Andrictemplate <class _SimdType, class _Abi>
11630b57cec5SDimitry Andricarray<_SimdType, simd_size<typename _SimdType::value_type, _Abi>::value /
11640b57cec5SDimitry Andric                     _SimdType::size()>
11650b57cec5SDimitry Andricsplit(const simd<typename _SimdType::value_type, _Abi>&);
11660b57cec5SDimitry Andric
11670b57cec5SDimitry Andrictemplate <class _SimdType, class _Abi>
11680b57cec5SDimitry Andricarray<_SimdType, simd_size<typename _SimdType::value_type, _Abi>::value /
11690b57cec5SDimitry Andric                     _SimdType::size()>
11700b57cec5SDimitry Andricsplit(const simd_mask<typename _SimdType::value_type, _Abi>&);
11710b57cec5SDimitry Andric
11720b57cec5SDimitry Andrictemplate <class _Tp, class... _Abis>
1173*bdd1243dSDimitry Andricsimd<_Tp, abi_for_size_t<_Tp, experimental::__variadic_sum(simd_size<_Tp, _Abis>::value...)>>
11740b57cec5SDimitry Andricconcat(const simd<_Tp, _Abis>&...);
11750b57cec5SDimitry Andric
11760b57cec5SDimitry Andrictemplate <class _Tp, class... _Abis>
11770b57cec5SDimitry Andricsimd_mask<_Tp,
1178*bdd1243dSDimitry Andric          abi_for_size_t<_Tp, experimental::__variadic_sum(simd_size<_Tp, _Abis>::value...)>>
11790b57cec5SDimitry Andricconcat(const simd_mask<_Tp, _Abis>&...);
11800b57cec5SDimitry Andric
11810b57cec5SDimitry Andric// reductions [simd.mask.reductions]
11820b57cec5SDimitry Andrictemplate <class _Tp, class _Abi>
11830b57cec5SDimitry Andricbool all_of(const simd_mask<_Tp, _Abi>&) noexcept;
11840b57cec5SDimitry Andrictemplate <class _Tp, class _Abi>
11850b57cec5SDimitry Andricbool any_of(const simd_mask<_Tp, _Abi>&) noexcept;
11860b57cec5SDimitry Andrictemplate <class _Tp, class _Abi>
11870b57cec5SDimitry Andricbool none_of(const simd_mask<_Tp, _Abi>&) noexcept;
11880b57cec5SDimitry Andrictemplate <class _Tp, class _Abi>
11890b57cec5SDimitry Andricbool some_of(const simd_mask<_Tp, _Abi>&) noexcept;
11900b57cec5SDimitry Andrictemplate <class _Tp, class _Abi>
11910b57cec5SDimitry Andricint popcount(const simd_mask<_Tp, _Abi>&) noexcept;
11920b57cec5SDimitry Andrictemplate <class _Tp, class _Abi>
11930b57cec5SDimitry Andricint find_first_set(const simd_mask<_Tp, _Abi>&);
11940b57cec5SDimitry Andrictemplate <class _Tp, class _Abi>
11950b57cec5SDimitry Andricint find_last_set(const simd_mask<_Tp, _Abi>&);
11960b57cec5SDimitry Andricbool all_of(bool) noexcept;
11970b57cec5SDimitry Andricbool any_of(bool) noexcept;
11980b57cec5SDimitry Andricbool none_of(bool) noexcept;
11990b57cec5SDimitry Andricbool some_of(bool) noexcept;
12000b57cec5SDimitry Andricint popcount(bool) noexcept;
12010b57cec5SDimitry Andricint find_first_set(bool) noexcept;
12020b57cec5SDimitry Andricint find_last_set(bool) noexcept;
12030b57cec5SDimitry Andric
12040b57cec5SDimitry Andric// masked assignment [simd.whereexpr]
12050b57cec5SDimitry Andrictemplate <class _MaskType, class _Tp>
12060b57cec5SDimitry Andricclass const_where_expression;
12070b57cec5SDimitry Andrictemplate <class _MaskType, class _Tp>
12080b57cec5SDimitry Andricclass where_expression;
12090b57cec5SDimitry Andric
12100b57cec5SDimitry Andric// masked assignment [simd.mask.where]
12110b57cec5SDimitry Andrictemplate <class _Tp, class _Abi>
12120b57cec5SDimitry Andricwhere_expression<simd_mask<_Tp, _Abi>, simd<_Tp, _Abi>>
12130b57cec5SDimitry Andricwhere(const typename simd<_Tp, _Abi>::mask_type&, simd<_Tp, _Abi>&) noexcept;
12140b57cec5SDimitry Andric
12150b57cec5SDimitry Andrictemplate <class _Tp, class _Abi>
12160b57cec5SDimitry Andricconst_where_expression<simd_mask<_Tp, _Abi>, const simd<_Tp, _Abi>>
12170b57cec5SDimitry Andricwhere(const typename simd<_Tp, _Abi>::mask_type&,
12180b57cec5SDimitry Andric      const simd<_Tp, _Abi>&) noexcept;
12190b57cec5SDimitry Andric
12200b57cec5SDimitry Andrictemplate <class _Tp, class _Abi>
12210b57cec5SDimitry Andricwhere_expression<simd_mask<_Tp, _Abi>, simd_mask<_Tp, _Abi>>
12220b57cec5SDimitry Andricwhere(const typename __nodeduce<simd_mask<_Tp, _Abi>>::type&,
12230b57cec5SDimitry Andric      simd_mask<_Tp, _Abi>&) noexcept;
12240b57cec5SDimitry Andric
12250b57cec5SDimitry Andrictemplate <class _Tp, class _Abi>
12260b57cec5SDimitry Andricconst_where_expression<simd_mask<_Tp, _Abi>, const simd_mask<_Tp, _Abi>>
12270b57cec5SDimitry Andricwhere(const typename __nodeduce<simd_mask<_Tp, _Abi>>::type&,
12280b57cec5SDimitry Andric      const simd_mask<_Tp, _Abi>&) noexcept;
12290b57cec5SDimitry Andric
12300b57cec5SDimitry Andrictemplate <class _Tp>
12310b57cec5SDimitry Andricwhere_expression<bool, _Tp> where(bool, _Tp&) noexcept;
12320b57cec5SDimitry Andric
12330b57cec5SDimitry Andrictemplate <class _Tp>
12340b57cec5SDimitry Andricconst_where_expression<bool, const _Tp> where(bool, const _Tp&) noexcept;
12350b57cec5SDimitry Andric
12360b57cec5SDimitry Andric// reductions [simd.reductions]
12370b57cec5SDimitry Andrictemplate <class _Tp, class _Abi, class _BinaryOp = std::plus<_Tp>>
12380b57cec5SDimitry Andric_Tp reduce(const simd<_Tp, _Abi>&, _BinaryOp = _BinaryOp());
12390b57cec5SDimitry Andric
12400b57cec5SDimitry Andrictemplate <class _MaskType, class _SimdType, class _BinaryOp>
12410b57cec5SDimitry Andrictypename _SimdType::value_type
12420b57cec5SDimitry Andricreduce(const const_where_expression<_MaskType, _SimdType>&,
1243753f127fSDimitry Andric       typename _SimdType::value_type __neutral_element, _BinaryOp);
12440b57cec5SDimitry Andric
12450b57cec5SDimitry Andrictemplate <class _MaskType, class _SimdType>
12460b57cec5SDimitry Andrictypename _SimdType::value_type
12470b57cec5SDimitry Andricreduce(const const_where_expression<_MaskType, _SimdType>&,
1248753f127fSDimitry Andric       plus<typename _SimdType::value_type> = {});
12490b57cec5SDimitry Andric
12500b57cec5SDimitry Andrictemplate <class _MaskType, class _SimdType>
12510b57cec5SDimitry Andrictypename _SimdType::value_type
12520b57cec5SDimitry Andricreduce(const const_where_expression<_MaskType, _SimdType>&,
1253753f127fSDimitry Andric       multiplies<typename _SimdType::value_type>);
12540b57cec5SDimitry Andric
12550b57cec5SDimitry Andrictemplate <class _MaskType, class _SimdType>
12560b57cec5SDimitry Andrictypename _SimdType::value_type
12570b57cec5SDimitry Andricreduce(const const_where_expression<_MaskType, _SimdType>&,
1258753f127fSDimitry Andric       bit_and<typename _SimdType::value_type>);
12590b57cec5SDimitry Andric
12600b57cec5SDimitry Andrictemplate <class _MaskType, class _SimdType>
12610b57cec5SDimitry Andrictypename _SimdType::value_type
12620b57cec5SDimitry Andricreduce(const const_where_expression<_MaskType, _SimdType>&,
1263753f127fSDimitry Andric       bit_or<typename _SimdType::value_type>);
12640b57cec5SDimitry Andric
12650b57cec5SDimitry Andrictemplate <class _MaskType, class _SimdType>
12660b57cec5SDimitry Andrictypename _SimdType::value_type
12670b57cec5SDimitry Andricreduce(const const_where_expression<_MaskType, _SimdType>&,
1268753f127fSDimitry Andric       bit_xor<typename _SimdType::value_type>);
12690b57cec5SDimitry Andric
12700b57cec5SDimitry Andrictemplate <class _Tp, class _Abi>
12710b57cec5SDimitry Andric_Tp hmin(const simd<_Tp, _Abi>&);
12720b57cec5SDimitry Andrictemplate <class _MaskType, class _SimdType>
12730b57cec5SDimitry Andrictypename _SimdType::value_type
12740b57cec5SDimitry Andrichmin(const const_where_expression<_MaskType, _SimdType>&);
12750b57cec5SDimitry Andrictemplate <class _Tp, class _Abi>
12760b57cec5SDimitry Andric_Tp hmax(const simd<_Tp, _Abi>&);
12770b57cec5SDimitry Andrictemplate <class _MaskType, class _SimdType>
12780b57cec5SDimitry Andrictypename _SimdType::value_type
12790b57cec5SDimitry Andrichmax(const const_where_expression<_MaskType, _SimdType>&);
12800b57cec5SDimitry Andric
12810b57cec5SDimitry Andric// algorithms [simd.alg]
12820b57cec5SDimitry Andrictemplate <class _Tp, class _Abi>
12830b57cec5SDimitry Andricsimd<_Tp, _Abi> min(const simd<_Tp, _Abi>&, const simd<_Tp, _Abi>&) noexcept;
12840b57cec5SDimitry Andric
12850b57cec5SDimitry Andrictemplate <class _Tp, class _Abi>
12860b57cec5SDimitry Andricsimd<_Tp, _Abi> max(const simd<_Tp, _Abi>&, const simd<_Tp, _Abi>&) noexcept;
12870b57cec5SDimitry Andric
12880b57cec5SDimitry Andrictemplate <class _Tp, class _Abi>
12890b57cec5SDimitry Andricstd::pair<simd<_Tp, _Abi>, simd<_Tp, _Abi>>
12900b57cec5SDimitry Andricminmax(const simd<_Tp, _Abi>&, const simd<_Tp, _Abi>&) noexcept;
12910b57cec5SDimitry Andric
12920b57cec5SDimitry Andrictemplate <class _Tp, class _Abi>
12930b57cec5SDimitry Andricsimd<_Tp, _Abi> clamp(const simd<_Tp, _Abi>&, const simd<_Tp, _Abi>&,
12940b57cec5SDimitry Andric                      const simd<_Tp, _Abi>&);
12950b57cec5SDimitry Andric
12960b57cec5SDimitry Andric// [simd.whereexpr]
12970b57cec5SDimitry Andric// TODO implement where expressions.
12980b57cec5SDimitry Andrictemplate <class _MaskType, class _Tp>
12990b57cec5SDimitry Andricclass const_where_expression {
13000b57cec5SDimitry Andricpublic:
13010b57cec5SDimitry Andric  const_where_expression(const const_where_expression&) = delete;
13020b57cec5SDimitry Andric  const_where_expression& operator=(const const_where_expression&) = delete;
1303*bdd1243dSDimitry Andric  __remove_const_t<_Tp> operator-() const&&;
13040b57cec5SDimitry Andric  template <class _Up, class _Flags>
13050b57cec5SDimitry Andric  void copy_to(_Up*, _Flags) const&&;
13060b57cec5SDimitry Andric};
13070b57cec5SDimitry Andric
13080b57cec5SDimitry Andrictemplate <class _MaskType, class _Tp>
13090b57cec5SDimitry Andricclass where_expression : public const_where_expression<_MaskType, _Tp> {
13100b57cec5SDimitry Andricpublic:
13110b57cec5SDimitry Andric  where_expression(const where_expression&) = delete;
13120b57cec5SDimitry Andric  where_expression& operator=(const where_expression&) = delete;
13130b57cec5SDimitry Andric  template <class _Up>
13140b57cec5SDimitry Andric  void operator=(_Up&&);
13150b57cec5SDimitry Andric  template <class _Up>
13160b57cec5SDimitry Andric  void operator+=(_Up&&);
13170b57cec5SDimitry Andric  template <class _Up>
13180b57cec5SDimitry Andric  void operator-=(_Up&&);
13190b57cec5SDimitry Andric  template <class _Up>
13200b57cec5SDimitry Andric  void operator*=(_Up&&);
13210b57cec5SDimitry Andric  template <class _Up>
13220b57cec5SDimitry Andric  void operator/=(_Up&&);
13230b57cec5SDimitry Andric  template <class _Up>
13240b57cec5SDimitry Andric  void operator%=(_Up&&);
13250b57cec5SDimitry Andric  template <class _Up>
13260b57cec5SDimitry Andric  void operator&=(_Up&&);
13270b57cec5SDimitry Andric  template <class _Up>
13280b57cec5SDimitry Andric  void operator|=(_Up&&);
13290b57cec5SDimitry Andric  template <class _Up>
13300b57cec5SDimitry Andric  void operator^=(_Up&&);
13310b57cec5SDimitry Andric  template <class _Up>
13320b57cec5SDimitry Andric  void operator<<=(_Up&&);
13330b57cec5SDimitry Andric  template <class _Up>
13340b57cec5SDimitry Andric  void operator>>=(_Up&&);
13350b57cec5SDimitry Andric  void operator++();
13360b57cec5SDimitry Andric  void operator++(int);
13370b57cec5SDimitry Andric  void operator--();
13380b57cec5SDimitry Andric  void operator--(int);
13390b57cec5SDimitry Andric  template <class _Up, class _Flags>
13400b57cec5SDimitry Andric  void copy_from(const _Up*, _Flags);
13410b57cec5SDimitry Andric};
13420b57cec5SDimitry Andric
13430b57cec5SDimitry Andric// [simd.class]
13440b57cec5SDimitry Andric// TODO: implement simd
13450b57cec5SDimitry Andrictemplate <class _Tp, class _Abi>
13460b57cec5SDimitry Andricclass simd {
13470b57cec5SDimitry Andricpublic:
13480b57cec5SDimitry Andric  using value_type = _Tp;
13490b57cec5SDimitry Andric  using reference = __simd_reference<_Tp, _Tp, _Abi>;
13500b57cec5SDimitry Andric  using mask_type = simd_mask<_Tp, _Abi>;
13510b57cec5SDimitry Andric  using abi_type = _Abi;
13520b57cec5SDimitry Andric
13530b57cec5SDimitry Andric  simd() = default;
13540b57cec5SDimitry Andric  simd(const simd&) = default;
13550b57cec5SDimitry Andric  simd& operator=(const simd&) = default;
13560b57cec5SDimitry Andric
13570b57cec5SDimitry Andric  static constexpr size_t size() noexcept {
13580b57cec5SDimitry Andric    return simd_size<_Tp, _Abi>::value;
13590b57cec5SDimitry Andric  }
13600b57cec5SDimitry Andric
13610b57cec5SDimitry Andricprivate:
13620b57cec5SDimitry Andric  __simd_storage<_Tp, _Abi> __s_;
13630b57cec5SDimitry Andric
13640b57cec5SDimitry Andric  template <class _Up>
13650b57cec5SDimitry Andric  static constexpr bool __can_broadcast() {
13660b57cec5SDimitry Andric    return (std::is_arithmetic<_Up>::value &&
13670b57cec5SDimitry Andric            __is_non_narrowing_arithmetic_convertible<_Up, _Tp>()) ||
13680b57cec5SDimitry Andric           (!std::is_arithmetic<_Up>::value &&
13690b57cec5SDimitry Andric            std::is_convertible<_Up, _Tp>::value) ||
1370*bdd1243dSDimitry Andric           std::is_same<__remove_const_t<_Up>, int>::value ||
1371*bdd1243dSDimitry Andric           (std::is_same<__remove_const_t<_Up>,
13720b57cec5SDimitry Andric                         unsigned int>::value &&
13730b57cec5SDimitry Andric            std::is_unsigned<_Tp>::value);
13740b57cec5SDimitry Andric  }
13750b57cec5SDimitry Andric
13760b57cec5SDimitry Andric  template <class _Generator, size_t... __indicies>
13770b57cec5SDimitry Andric  static constexpr decltype(
13780b57cec5SDimitry Andric      std::forward_as_tuple(std::declval<_Generator>()(
13790b57cec5SDimitry Andric          std::integral_constant<size_t, __indicies>())...),
13800b57cec5SDimitry Andric      bool())
13810b57cec5SDimitry Andric  __can_generate(std::index_sequence<__indicies...>) {
1382*bdd1243dSDimitry Andric    return !experimental::__variadic_sum<bool>(
13830b57cec5SDimitry Andric        !__can_broadcast<decltype(std::declval<_Generator>()(
13840b57cec5SDimitry Andric            std::integral_constant<size_t, __indicies>()))>()...);
13850b57cec5SDimitry Andric  }
13860b57cec5SDimitry Andric
13870b57cec5SDimitry Andric  template <class _Generator>
13880b57cec5SDimitry Andric  static bool __can_generate(...) {
13890b57cec5SDimitry Andric    return false;
13900b57cec5SDimitry Andric  }
13910b57cec5SDimitry Andric
13920b57cec5SDimitry Andric  template <class _Generator, size_t... __indicies>
13930b57cec5SDimitry Andric  void __generator_init(_Generator&& __g, std::index_sequence<__indicies...>) {
13940b57cec5SDimitry Andric    int __not_used[]{((*this)[__indicies] =
13950b57cec5SDimitry Andric                          __g(std::integral_constant<size_t, __indicies>()),
13960b57cec5SDimitry Andric                      0)...};
13970b57cec5SDimitry Andric    (void)__not_used;
13980b57cec5SDimitry Andric  }
13990b57cec5SDimitry Andric
14000b57cec5SDimitry Andricpublic:
14010b57cec5SDimitry Andric  // implicit type conversion constructor
14020b57cec5SDimitry Andric  template <class _Up,
14030b57cec5SDimitry Andric            class = typename std::enable_if<
14040b57cec5SDimitry Andric                std::is_same<_Abi, simd_abi::fixed_size<size()>>::value &&
14050b57cec5SDimitry Andric                __is_non_narrowing_arithmetic_convertible<_Up, _Tp>()>::type>
14060b57cec5SDimitry Andric  simd(const simd<_Up, simd_abi::fixed_size<size()>>& __v) {
14070b57cec5SDimitry Andric    for (size_t __i = 0; __i < size(); __i++) {
14080b57cec5SDimitry Andric      (*this)[__i] = static_cast<_Tp>(__v[__i]);
14090b57cec5SDimitry Andric    }
14100b57cec5SDimitry Andric  }
14110b57cec5SDimitry Andric
14120b57cec5SDimitry Andric  // implicit broadcast constructor
14130b57cec5SDimitry Andric  template <class _Up,
14140b57cec5SDimitry Andric            class = typename std::enable_if<__can_broadcast<_Up>()>::type>
14150b57cec5SDimitry Andric  simd(_Up&& __rv) {
14160b57cec5SDimitry Andric    auto __v = static_cast<_Tp>(__rv);
14170b57cec5SDimitry Andric    for (size_t __i = 0; __i < size(); __i++) {
14180b57cec5SDimitry Andric      (*this)[__i] = __v;
14190b57cec5SDimitry Andric    }
14200b57cec5SDimitry Andric  }
14210b57cec5SDimitry Andric
14220b57cec5SDimitry Andric  // generator constructor
14230b57cec5SDimitry Andric  template <class _Generator,
14240b57cec5SDimitry Andric            int = typename std::enable_if<
14250b57cec5SDimitry Andric                __can_generate<_Generator>(std::make_index_sequence<size()>()),
14260b57cec5SDimitry Andric                int>::type()>
14270b57cec5SDimitry Andric  explicit simd(_Generator&& __g) {
14280b57cec5SDimitry Andric    __generator_init(std::forward<_Generator>(__g),
14290b57cec5SDimitry Andric                     std::make_index_sequence<size()>());
14300b57cec5SDimitry Andric  }
14310b57cec5SDimitry Andric
14320b57cec5SDimitry Andric  // load constructor
14330b57cec5SDimitry Andric  template <
14340b57cec5SDimitry Andric      class _Up, class _Flags,
14350b57cec5SDimitry Andric      class = typename std::enable_if<__vectorizable<_Up>()>::type,
14360b57cec5SDimitry Andric      class = typename std::enable_if<is_simd_flag_type<_Flags>::value>::type>
14370b57cec5SDimitry Andric  simd(const _Up* __buffer, _Flags) {
14380b57cec5SDimitry Andric    // TODO: optimize for overaligned flags
14390b57cec5SDimitry Andric    for (size_t __i = 0; __i < size(); __i++) {
14400b57cec5SDimitry Andric      (*this)[__i] = static_cast<_Tp>(__buffer[__i]);
14410b57cec5SDimitry Andric    }
14420b57cec5SDimitry Andric  }
14430b57cec5SDimitry Andric
14440b57cec5SDimitry Andric  // loads [simd.load]
14450b57cec5SDimitry Andric  template <class _Up, class _Flags>
14460b57cec5SDimitry Andric  typename std::enable_if<__vectorizable<_Up>() &&
14470b57cec5SDimitry Andric                          is_simd_flag_type<_Flags>::value>::type
14480b57cec5SDimitry Andric  copy_from(const _Up* __buffer, _Flags) {
14490b57cec5SDimitry Andric    *this = simd(__buffer, _Flags());
14500b57cec5SDimitry Andric  }
14510b57cec5SDimitry Andric
14520b57cec5SDimitry Andric  // stores [simd.store]
14530b57cec5SDimitry Andric  template <class _Up, class _Flags>
14540b57cec5SDimitry Andric  typename std::enable_if<__vectorizable<_Up>() &&
14550b57cec5SDimitry Andric                          is_simd_flag_type<_Flags>::value>::type
14560b57cec5SDimitry Andric  copy_to(_Up* __buffer, _Flags) const {
14570b57cec5SDimitry Andric    // TODO: optimize for overaligned flags
14580b57cec5SDimitry Andric    for (size_t __i = 0; __i < size(); __i++) {
14590b57cec5SDimitry Andric      __buffer[__i] = static_cast<_Up>((*this)[__i]);
14600b57cec5SDimitry Andric    }
14610b57cec5SDimitry Andric  }
14620b57cec5SDimitry Andric
14630b57cec5SDimitry Andric  // scalar access [simd.subscr]
14640b57cec5SDimitry Andric  reference operator[](size_t __i) { return reference(&__s_, __i); }
14650b57cec5SDimitry Andric
14660b57cec5SDimitry Andric  value_type operator[](size_t __i) const { return __s_.__get(__i); }
14670b57cec5SDimitry Andric
14680b57cec5SDimitry Andric  // unary operators [simd.unary]
14690b57cec5SDimitry Andric  simd& operator++();
14700b57cec5SDimitry Andric  simd operator++(int);
14710b57cec5SDimitry Andric  simd& operator--();
14720b57cec5SDimitry Andric  simd operator--(int);
14730b57cec5SDimitry Andric  mask_type operator!() const;
14740b57cec5SDimitry Andric  simd operator~() const;
14750b57cec5SDimitry Andric  simd operator+() const;
14760b57cec5SDimitry Andric  simd operator-() const;
14770b57cec5SDimitry Andric
147881ad6265SDimitry Andric#if 0
14790b57cec5SDimitry Andric  // binary operators [simd.binary]
14800b57cec5SDimitry Andric  friend simd operator+(const simd&, const simd&);
14810b57cec5SDimitry Andric  friend simd operator-(const simd&, const simd&);
14820b57cec5SDimitry Andric  friend simd operator*(const simd&, const simd&);
14830b57cec5SDimitry Andric  friend simd operator/(const simd&, const simd&);
14840b57cec5SDimitry Andric  friend simd operator%(const simd&, const simd&);
14850b57cec5SDimitry Andric  friend simd operator&(const simd&, const simd&);
14860b57cec5SDimitry Andric  friend simd operator|(const simd&, const simd&);
14870b57cec5SDimitry Andric  friend simd operator^(const simd&, const simd&);
14880b57cec5SDimitry Andric  friend simd operator<<(const simd&, const simd&);
14890b57cec5SDimitry Andric  friend simd operator>>(const simd&, const simd&);
14900b57cec5SDimitry Andric  friend simd operator<<(const simd&, int);
14910b57cec5SDimitry Andric  friend simd operator>>(const simd&, int);
14920b57cec5SDimitry Andric
14930b57cec5SDimitry Andric  // compound assignment [simd.cassign]
14940b57cec5SDimitry Andric  friend simd& operator+=(simd&, const simd&);
14950b57cec5SDimitry Andric  friend simd& operator-=(simd&, const simd&);
14960b57cec5SDimitry Andric  friend simd& operator*=(simd&, const simd&);
14970b57cec5SDimitry Andric  friend simd& operator/=(simd&, const simd&);
14980b57cec5SDimitry Andric  friend simd& operator%=(simd&, const simd&);
14990b57cec5SDimitry Andric
15000b57cec5SDimitry Andric  friend simd& operator&=(simd&, const simd&);
15010b57cec5SDimitry Andric  friend simd& operator|=(simd&, const simd&);
15020b57cec5SDimitry Andric  friend simd& operator^=(simd&, const simd&);
15030b57cec5SDimitry Andric  friend simd& operator<<=(simd&, const simd&);
15040b57cec5SDimitry Andric  friend simd& operator>>=(simd&, const simd&);
15050b57cec5SDimitry Andric  friend simd& operator<<=(simd&, int);
15060b57cec5SDimitry Andric  friend simd& operator>>=(simd&, int);
15070b57cec5SDimitry Andric
15080b57cec5SDimitry Andric  // compares [simd.comparison]
15090b57cec5SDimitry Andric  friend mask_type operator==(const simd&, const simd&);
15100b57cec5SDimitry Andric  friend mask_type operator!=(const simd&, const simd&);
15110b57cec5SDimitry Andric  friend mask_type operator>=(const simd&, const simd&);
15120b57cec5SDimitry Andric  friend mask_type operator<=(const simd&, const simd&);
15130b57cec5SDimitry Andric  friend mask_type operator>(const simd&, const simd&);
15140b57cec5SDimitry Andric  friend mask_type operator<(const simd&, const simd&);
151581ad6265SDimitry Andric#endif
15160b57cec5SDimitry Andric};
15170b57cec5SDimitry Andric
15180b57cec5SDimitry Andric// [simd.mask.class]
15190b57cec5SDimitry Andrictemplate <class _Tp, class _Abi>
15200b57cec5SDimitry Andric// TODO: implement simd_mask
15210b57cec5SDimitry Andricclass simd_mask {
15220b57cec5SDimitry Andricpublic:
15230b57cec5SDimitry Andric  using value_type = bool;
15240b57cec5SDimitry Andric  // TODO: this is strawman implementation. Turn it into a proxy type.
15250b57cec5SDimitry Andric  using reference = bool&;
15260b57cec5SDimitry Andric  using simd_type = simd<_Tp, _Abi>;
15270b57cec5SDimitry Andric  using abi_type = _Abi;
15280b57cec5SDimitry Andric  static constexpr size_t size() noexcept;
15290b57cec5SDimitry Andric  simd_mask() = default;
15300b57cec5SDimitry Andric
15310b57cec5SDimitry Andric  // broadcast constructor
15320b57cec5SDimitry Andric  explicit simd_mask(value_type) noexcept;
15330b57cec5SDimitry Andric
15340b57cec5SDimitry Andric  // implicit type conversion constructor
15350b57cec5SDimitry Andric  template <class _Up>
15360b57cec5SDimitry Andric  simd_mask(const simd_mask<_Up, simd_abi::fixed_size<size()>>&) noexcept;
15370b57cec5SDimitry Andric
15380b57cec5SDimitry Andric  // load constructor
15390b57cec5SDimitry Andric  template <class _Flags>
15400b57cec5SDimitry Andric  simd_mask(const value_type*, _Flags);
15410b57cec5SDimitry Andric
15420b57cec5SDimitry Andric  // loads [simd.mask.copy]
15430b57cec5SDimitry Andric  template <class _Flags>
15440b57cec5SDimitry Andric  void copy_from(const value_type*, _Flags);
15450b57cec5SDimitry Andric  template <class _Flags>
15460b57cec5SDimitry Andric  void copy_to(value_type*, _Flags) const;
15470b57cec5SDimitry Andric
15480b57cec5SDimitry Andric  // scalar access [simd.mask.subscr]
15490b57cec5SDimitry Andric  reference operator[](size_t);
15500b57cec5SDimitry Andric  value_type operator[](size_t) const;
15510b57cec5SDimitry Andric
15520b57cec5SDimitry Andric  // unary operators [simd.mask.unary]
15530b57cec5SDimitry Andric  simd_mask operator!() const noexcept;
15540b57cec5SDimitry Andric
155581ad6265SDimitry Andric#if 0
15560b57cec5SDimitry Andric  // simd_mask binary operators [simd.mask.binary]
15570b57cec5SDimitry Andric  friend simd_mask operator&&(const simd_mask&, const simd_mask&) noexcept;
15580b57cec5SDimitry Andric  friend simd_mask operator||(const simd_mask&, const simd_mask&) noexcept;
15590b57cec5SDimitry Andric  friend simd_mask operator&(const simd_mask&, const simd_mask&)noexcept;
15600b57cec5SDimitry Andric  friend simd_mask operator|(const simd_mask&, const simd_mask&) noexcept;
15610b57cec5SDimitry Andric  friend simd_mask operator^(const simd_mask&, const simd_mask&) noexcept;
15620b57cec5SDimitry Andric
15630b57cec5SDimitry Andric  // simd_mask compound assignment [simd.mask.cassign]
15640b57cec5SDimitry Andric  friend simd_mask& operator&=(simd_mask&, const simd_mask&) noexcept;
15650b57cec5SDimitry Andric  friend simd_mask& operator|=(simd_mask&, const simd_mask&) noexcept;
15660b57cec5SDimitry Andric  friend simd_mask& operator^=(simd_mask&, const simd_mask&) noexcept;
15670b57cec5SDimitry Andric
15680b57cec5SDimitry Andric  // simd_mask compares [simd.mask.comparison]
15690b57cec5SDimitry Andric  friend simd_mask operator==(const simd_mask&, const simd_mask&) noexcept;
15700b57cec5SDimitry Andric  friend simd_mask operator!=(const simd_mask&, const simd_mask&) noexcept;
157181ad6265SDimitry Andric#endif
15720b57cec5SDimitry Andric};
15730b57cec5SDimitry Andric
15740b57cec5SDimitry Andric#endif // _LIBCPP_STD_VER >= 17
15750b57cec5SDimitry Andric
15760b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_EXPERIMENTAL_SIMD
15770b57cec5SDimitry Andric
1578e8d8bef9SDimitry Andric_LIBCPP_POP_MACROS
1579e8d8bef9SDimitry Andric
1580*bdd1243dSDimitry Andric#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
1581*bdd1243dSDimitry Andric#  include <algorithm>
1582*bdd1243dSDimitry Andric#  include <functional>
1583*bdd1243dSDimitry Andric#endif
1584*bdd1243dSDimitry Andric
15850b57cec5SDimitry Andric#endif /* _LIBCPP_EXPERIMENTAL_SIMD */
1586