// -*- C++ -*- //===------------------------------- simd ---------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef _LIBCPP_EXPERIMENTAL_SIMD #define _LIBCPP_EXPERIMENTAL_SIMD /* experimental/simd synopsis namespace std::experimental { inline namespace parallelism_v2 { namespace simd_abi { struct scalar {}; template struct fixed_size {}; template inline constexpr int max_fixed_size = implementation-defined; template using compatible = implementation-defined; template using native = implementation-defined; } // simd_abi struct element_aligned_tag {}; struct vector_aligned_tag {}; template struct overaligned_tag {}; inline constexpr element_aligned_tag element_aligned{}; inline constexpr vector_aligned_tag vector_aligned{}; template inline constexpr overaligned_tag overaligned{}; // traits [simd.traits] template struct is_abi_tag; template inline constexpr bool is_abi_tag_v = is_abi_tag::value; template struct is_simd; template inline constexpr bool is_simd_v = is_simd::value; template struct is_simd_mask; template inline constexpr bool is_simd_mask_v = is_simd_mask::value; template struct is_simd_flag_type; template inline constexpr bool is_simd_flag_type_v = is_simd_flag_type::value; template struct abi_for_size { using type = see below; }; template using abi_for_size_t = typename abi_for_size::type; template > struct simd_size; template > inline constexpr size_t simd_size_v = simd_size::value; template struct memory_alignment; template inline constexpr size_t memory_alignment_v = memory_alignment::value; // class template simd [simd.class] template > class simd; template using native_simd = simd>; template using fixed_size_simd = simd>; // class template simd_mask [simd.mask.class] template > class simd_mask; template using native_simd_mask = simd_mask>; template using fixed_size_simd_mask = simd_mask>; // casts [simd.casts] template see below simd_cast(const simd&); template see below static_simd_cast(const simd&); template fixed_size_simd> to_fixed_size(const simd&) noexcept; template fixed_size_simd_mask> to_fixed_size(const simd_mask&) noexcept; template native_simd to_native(const fixed_size_simd&) noexcept; template native_simd_mask to_native(const fixed_size_simd_mask> &) noexcept; template simd to_compatible(const fixed_size_simd&) noexcept; template simd_mask to_compatible(const fixed_size_simd_mask&) noexcept; template tuple>...> split(const simd&); template tuple>...> split(const simd_mask&); template array / V::size()> split( const simd&); template array / V::size()> split( const simd_mask&); template simd + ...)>> concat(const simd&...); template simd_mask + ...)>> concat(const simd_mask&...); // reductions [simd.mask.reductions] template bool all_of(const simd_mask&) noexcept; template bool any_of(const simd_mask&) noexcept; template bool none_of(const simd_mask&) noexcept; template bool some_of(const simd_mask&) noexcept; template int popcount(const simd_mask&) noexcept; template int find_first_set(const simd_mask&); template int find_last_set(const simd_mask&); bool all_of(see below) noexcept; bool any_of(see below) noexcept; bool none_of(see below) noexcept; bool some_of(see below) noexcept; int popcount(see below) noexcept; int find_first_set(see below) noexcept; int find_last_set(see below) noexcept; // masked assignment [simd.whereexpr] template class const_where_expression; template class where_expression; // masked assignment [simd.mask.where] template struct nodeduce { using type = T; }; // exposition only template using nodeduce_t = typename nodeduce::type; // exposition only template where_expression, simd> where(const typename simd::mask_type&, simd&) noexcept; template const_where_expression, const simd> where(const typename simd::mask_type&, const simd&) noexcept; template where_expression, simd_mask> where(const nodeduce_t>&, simd_mask&) noexcept; template const_where_expression, const simd_mask> where(const nodeduce_t>&, const simd_mask&) noexcept; template where_expression where(see below k, T& d) noexcept; template const_where_expression where(see below k, const T& d) noexcept; // reductions [simd.reductions] template > T reduce(const simd&, BinaryOperation = BinaryOperation()); template typename V::value_type reduce(const const_where_expression& x, typename V::value_type neutral_element, BinaryOperation binary_op); template typename V::value_type reduce(const const_where_expression& x, plus<> binary_op = plus<>()); template typename V::value_type reduce(const const_where_expression& x, multiplies<> binary_op); template typename V::value_type reduce(const const_where_expression& x, bit_and<> binary_op); template typename V::value_type reduce(const const_where_expression& x, bit_or<> binary_op); template typename V::value_type reduce(const const_where_expression& x, bit_xor<> binary_op); template T hmin(const simd&); template T hmin(const const_where_expression&); template T hmax(const simd&); template T hmax(const const_where_expression&); // algorithms [simd.alg] template simd min(const simd&, const simd&) noexcept; template simd max(const simd&, const simd&) noexcept; template std::pair, simd> minmax(const simd&, const simd&) noexcept; template simd clamp(const simd& v, const simd& lo, const simd& hi); // [simd.whereexpr] template class const_where_expression { const M& mask; // exposition only T& data; // exposition only public: const_where_expression(const const_where_expression&) = delete; const_where_expression& operator=(const const_where_expression&) = delete; remove_const_t operator-() const &&; template void copy_to(U* mem, Flags f) const &&; }; template class where_expression : public const_where_expression { public: where_expression(const where_expression&) = delete; where_expression& operator=(const where_expression&) = delete; template void operator=(U&& x); template void operator+=(U&& x); template void operator-=(U&& x); template void operator*=(U&& x); template void operator/=(U&& x); template void operator%=(U&& x); template void operator&=(U&& x); template void operator|=(U&& x); template void operator^=(U&& x); template void operator<<=(U&& x); template void operator>>=(U&& x); void operator++(); void operator++(int); void operator--(); void operator--(int); template void copy_from(const U* mem, Flags); }; // [simd.class] template class simd { public: using value_type = T; using reference = see below; using mask_type = simd_mask; using abi_type = Abi; static constexpr size_t size() noexcept; simd() = default; // implicit type conversion constructor template simd(const simd>&); // implicit broadcast constructor (see below for constraints) template simd(U&& value); // generator constructor (see below for constraints) template explicit simd(G&& gen); // load constructor template simd(const U* mem, Flags f); // loads [simd.load] template void copy_from(const U* mem, Flags f); // stores [simd.store] template void copy_to(U* mem, Flags f) const; // scalar access [simd.subscr] reference operator[](size_t); value_type operator[](size_t) const; // unary operators [simd.unary] simd& operator++(); simd operator++(int); simd& operator--(); simd operator--(int); mask_type operator!() const; simd operator~() const; // see below simd operator+() const; simd operator-() const; // binary operators [simd.binary] friend simd operator+ (const simd&, const simd&); friend simd operator- (const simd&, const simd&); friend simd operator* (const simd&, const simd&); friend simd operator/ (const simd&, const simd&); friend simd operator% (const simd&, const simd&); friend simd operator& (const simd&, const simd&); friend simd operator| (const simd&, const simd&); friend simd operator^ (const simd&, const simd&); friend simd operator<<(const simd&, const simd&); friend simd operator>>(const simd&, const simd&); friend simd operator<<(const simd&, int); friend simd operator>>(const simd&, int); // compound assignment [simd.cassign] friend simd& operator+= (simd&, const simd&); friend simd& operator-= (simd&, const simd&); friend simd& operator*= (simd&, const simd&); friend simd& operator/= (simd&, const simd&); friend simd& operator%= (simd&, const simd&); friend simd& operator&= (simd&, const simd&); friend simd& operator|= (simd&, const simd&); friend simd& operator^= (simd&, const simd&); friend simd& operator<<=(simd&, const simd&); friend simd& operator>>=(simd&, const simd&); friend simd& operator<<=(simd&, int); friend simd& operator>>=(simd&, int); // compares [simd.comparison] friend mask_type operator==(const simd&, const simd&); friend mask_type operator!=(const simd&, const simd&); friend mask_type operator>=(const simd&, const simd&); friend mask_type operator<=(const simd&, const simd&); friend mask_type operator> (const simd&, const simd&); friend mask_type operator< (const simd&, const simd&); }; // [simd.math] template using scharv = simd; // exposition only template using shortv = simd; // exposition only template using intv = simd; // exposition only template using longv = simd; // exposition only template using llongv = simd; // exposition only template using floatv = simd; // exposition only template using doublev = simd; // exposition only template using ldoublev = simd; // exposition only template using samesize = fixed_size_simd; // exposition only template floatv acos(floatv x); template doublev acos(doublev x); template ldoublev acos(ldoublev x); template floatv asin(floatv x); template doublev asin(doublev x); template ldoublev asin(ldoublev x); template floatv atan(floatv x); template doublev atan(doublev x); template ldoublev atan(ldoublev x); template floatv atan2(floatv y, floatv x); template doublev atan2(doublev y, doublev x); template ldoublev atan2(ldoublev y, ldoublev x); template floatv cos(floatv x); template doublev cos(doublev x); template ldoublev cos(ldoublev x); template