Files
cppdraft_translate/cppdraft/simd/class.md
2025-10-25 03:02:53 +03:00

27 KiB
Raw Blame History

[simd.class]

29 Numerics library [numerics]

29.10 Data-parallel types [simd]

29.10.7 Class template basic_vec [simd.class]

29.10.7.1 Class template basic_vec overview [simd.overview]

🔗

namespace std::simd {template<class T, class Abi> class basic_vec {public:using value_type = T; using mask_type = basic_mask<sizeof(T), Abi>; using abi_type = Abi; using iterator = simd-iterator<basic_vec>; using const_iterator = simd-iterator; constexpr iterator begin() noexcept { return {*this, 0}; }constexpr const_iterator begin() const noexcept { return {this, 0}; }constexpr const_iterator cbegin() const noexcept { return {this, 0}; }constexpr default_sentinel_t end() const noexcept { return {}; }constexpr default_sentinel_t cend() const noexcept { return {}; }static constexpr integral_constant<simd-size-type, simd-size-v<T, Abi>> size {}; constexpr basic_vec() noexcept = default; // [simd.ctor], basic_vec constructorstemplateconstexpr explicit(see below) basic_vec(U&& value) noexcept; template<class U, class UAbi>constexpr explicit(see below) basic_vec(const basic_vec<U, UAbi>&) noexcept; templateconstexpr explicit basic_vec(G&& gen) noexcept; template<class R, class... Flags>constexpr basic_vec(R&& range, flags<Flags...> = {}); template<class R, class... Flags>constexpr basic_vec(R&& range, const mask_type& mask, flags<Flags...> = {}); template<simd-floating-point V>constexpr explicit(see below) basic_vec(const V& reals, const V& imags = {}) noexcept; // [simd.subscr], basic_vec subscript operatorsconstexpr value_type operator const; template<simd-integral I>constexpr resize_t<I::size(), basic_vec> operator[](const I& indices) const; // [simd.complex.access], basic_vec complex accessorsconstexpr auto real() const noexcept; constexpr auto imag() const noexcept; template<simd-floating-point V>constexpr void real(const V& v) noexcept; template<simd-floating-point V>constexpr void imag(const V& v) noexcept; // [simd.unary], basic_vec unary operatorsconstexpr basic_vec& operator++() noexcept; constexpr basic_vec operator++(int) noexcept; constexpr basic_vec& operator--() noexcept; constexpr basic_vec operator--(int) noexcept; constexpr mask_type operator!() const noexcept; constexpr basic_vec operator~() const noexcept; constexpr basic_vec operator+() const noexcept; constexpr basic_vec operator-() const noexcept; // [simd.binary], basic_vec binary operatorsfriend constexpr basic_vec operator+(const basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec operator-(const basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec operator(const basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec operator/(const basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec operator%(const basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec operator&(const basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec operator|(const basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec operator^(const basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec operator<<(const basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec operator>>(const basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec operator<<(const basic_vec&, simd-size-type) noexcept; friend constexpr basic_vec operator>>(const basic_vec&, simd-size-type) noexcept; // [simd.cassign], basic_vec compound assignmentfriend constexpr basic_vec& operator+=(basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec& operator-=(basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec& operator=(basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec& operator/=(basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec& operator%=(basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec& operator&=(basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec& operator|=(basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec& operator^=(basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec& operator<<=(basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec& operator>>=(basic_vec&, const basic_vec&) noexcept; friend constexpr basic_vec& operator<<=(basic_vec&, simd-size-type) noexcept; friend constexpr basic_vec& operator>>=(basic_vec&, simd-size-type) noexcept; // [simd.comparison], basic_vec compare operatorsfriend constexpr mask_type operator==(const basic_vec&, const basic_vec&) noexcept; friend constexpr mask_type operator!=(const basic_vec&, const basic_vec&) noexcept; friend constexpr mask_type operator>=(const basic_vec&, const basic_vec&) noexcept; friend constexpr mask_type operator<=(const basic_vec&, const basic_vec&) noexcept; friend constexpr mask_type operator>(const basic_vec&, const basic_vec&) noexcept; friend constexpr mask_type operator<(const basic_vec&, const basic_vec&) noexcept; // [simd.cond], basic_vec exposition only conditional operatorsfriend constexpr basic_vec simd-select-impl( // exposition onlyconst mask_type&, const basic_vec&, const basic_vec&) noexcept; }; template<class R, class... Ts> basic_vec(R&& r, Ts...) -> see below;}

1

#

Every specialization of basic_vec is a complete type.

The specialization of basic_vec<T, Abi> is

enabled, if T is a vectorizable type, and there exists value N in the range [1, 64], such that Abi is deduce-abi-t<T, N>,

otherwise, disabled, if T is not a vectorizable type,

otherwise, it is implementation-defined if such a specialization is enabled.

If basic_vec<T, Abi> is disabled, then the specialization has a deleted default constructor, deleted destructor, deleted copy constructor, and deleted copy assignment.

In addition only the value_type, abi_type, andmask_type members are present.

If basic_vec<T, Abi> is enabled, then basic_vec<T, Abi> is trivially copyable, default-initialization of an object of such a type default-initializes all elements, and value-initialization value-initializes all elements ([dcl.init.general]).

2

#

Recommended practice: Implementations should support implicit conversions between specializations ofbasic_vec and appropriate implementation-defined types.

[Note 1:

Appropriate types are non-standard vector types which are available in the implementation.

— end note]

29.10.7.2 basic_vec constructors [simd.ctor]

🔗

template<class U> constexpr explicit(see below) basic_vec(U&& value) noexcept;

1

#

Let From denote the type remove_cvref_t.

2

#

Constraints: value_type satisfies constructible_from.

3

#

Effects: Initializes each element to the value of the argument after conversion tovalue_type.

4

#

Remarks: The expression inside explicit evaluates to false if and only ifU satisfies convertible_to<value_type>, and either

From is not an arithmetic type and does not satisfy constexpr-wrapper-like,

From is an arithmetic type and the conversion from From to value_type is value-preserving ([simd.general]), or

From satisfies constexpr-wrapper-like, remove_const_t<decltype(From::value)> is an arithmetic type, and From::value is representable by value_type.

🔗

template<class U, class UAbi> constexpr explicit(see below) basic_vec(const basic_vec<U, UAbi>& x) noexcept;

5

#

Constraints: simd-size-v<U, UAbi> == size() is true.

6

#

Effects: Initializes the ith element with static_cast(x[i]) for all i in the range of [0, size()).

7

#

Remarks: The expression inside explicit evaluates to true if either

the conversion from U to value_type is not value-preserving, or

both U and value_type are integral types and the integer conversion rank ([conv.rank]) of U is greater than the integer conversion rank of value_type, or

both U and value_type are floating-point types and the floating-point conversion rank ([conv.rank]) of U is greater than the floating-point conversion rank of value_type.

🔗

template<class G> constexpr explicit basic_vec(G&& gen);

8

#

Let Fromi denote the typedecltype(gen(integral_constant<simd-size-type, i>())).

9

#

Constraints: Fromi satisfies convertible_to<value_type> for all i in the range of [0, size()).

In addition, for all i in the range of [0, size()), if Fromi is an arithmetic type, conversion from Fromi to value_type is value-preserving.

10

#

Effects: Initializes the ith element withstatic_cast<value_type>(gen(integral_constant<simd-size-type, i>())) for all i in the range of [0, size()).

11

#

Remarks: gen is invoked exactly once for each i, in increasing order of i.

🔗

template<class R, class... Flags> constexpr basic_vec(R&& r, flags<Flags...> = {}); template<class R, class... Flags> constexpr basic_vec(R&& r, const mask_type& mask, flags<Flags...> = {});

12

#

Let mask be mask_type(true) for the overload with nomask parameter.

13

#

Constraints:

R models ranges::contiguous_range and ranges::sized_range,

ranges::size(r) is a constant expression, and

ranges::size(r) is equal to size().

14

#

Mandates:

ranges::range_value_t is a vectorizable type, and

if the template parameter pack Flags does not contain convert-flag, then the conversion from ranges::range_value_t to value_type is value-preserving.

15

#

Preconditions:

  • (15.1)

    If the template parameter pack Flags contains aligned-flag, ranges::data(r) points to storage aligned by alignment_v<basic_vec, ranges::range_value_t>.

  • (15.2)

    If the template parameter pack Flags contains overaligned-flag, ranges::data(r) points to storage aligned by N.

16

#

Effects: Initializes the ith element with mask[i] ?static_cast(ranges::data(r)[i]) : T() for all i in the range of [0, size()).

🔗

template<class R, class... Ts> basic_vec(R&& r, Ts...) -> see below;

17

#

Constraints:

R models ranges::contiguous_range and ranges::sized_range, and

ranges::size(r) is a constant expression.

18

#

Remarks: The deduced type is equivalent to vec<ranges::range_value_t, ranges::size(r)>.

🔗

template<[simd-floating-point](simd.expos#concept:simd-floating-point "29.10.2Exposition-only types, variables, and concepts[simd.expos]") V> constexpr explicit(see below) basic_vec(const V& reals, const V& imags = {}) noexcept;

19

#

Constraints:

simd-complex<basic_vec> is modeled, and

V::size() == size() is true.

20

#

Effects: Initializes the ith element with value_type(reals[i], imags[i]) for all i in the range [0, size()).

21

#

Remarks: The expression inside explicit evaluates to false if and only if the floating-point conversion rank of T::value_type is greater than or equal to the floating-point conversion rank of V::value_type.

29.10.7.3 basic_vec subscript operator [simd.subscr]

🔗

constexpr value_type operator[](simd-size-type i) const;

1

#

Preconditions: i >= 0 && i < size() is true.

2

#

Returns: The value of the ith element.

3

#

Throws: Nothing.

🔗

template<[simd-integral](simd.expos#concept:simd-integral "29.10.2Exposition-only types, variables, and concepts[simd.expos]") I> constexpr resize_t<I::size(), basic_vec> operator[](const I& indices) const;

4

#

Effects: Equivalent to: return permute(*this, indices);

29.10.7.4 basic_vec complex accessors [simd.complex.access]

🔗

constexpr auto real() const noexcept; constexpr auto imag() const noexcept;

1

#

Constraints: simd-complex<basic_vec> is modeled.

2

#

Returns: An object of type rebind_t<typename T::value_type, basic_vec> where the ith element is initialized to the result ofcmplx-func(operator) for all i in the range [0, size()), where cmplx-func is the corresponding function from .

🔗

template<[simd-floating-point](simd.expos#concept:simd-floating-point "29.10.2Exposition-only types, variables, and concepts[simd.expos]") V> constexpr void real(const V& v) noexcept; template<[simd-floating-point](simd.expos#concept:simd-floating-point "29.10.2Exposition-only types, variables, and concepts[simd.expos]") V> constexpr void imag(const V& v) noexcept;

3

#

Constraints:

simd-complex<basic_vec> is modeled,

same_as<typename V::value_type, typename T::value_type> is modeled, and

V::size() == size() is true.

4

#

Effects: Replaces each element of the basic_vec object such that theith element is replaced with value_type(v[i],operator.imag()) or value_type(operator.real(), v[i]) for real and imag respectively, for all i in the range [0, size()).

29.10.7.5 basic_vec unary operators [simd.unary]

1

#

Effects in [simd.unary] are applied as unary element-wise operations.

🔗

constexpr basic_vec& operator++() noexcept;

2

#

Constraints: requires (value_type a) { ++a; } is true.

3

#

Effects: Increments every element by one.

4

#

Returns: *this.

🔗

constexpr basic_vec operator++(int) noexcept;

5

#

Constraints: requires (value_type a) { a++; } is true.

6

#

Effects: Increments every element by one.

7

#

Returns: A copy of *this before incrementing.

🔗

constexpr basic_vec& operator--() noexcept;

8

#

Constraints: requires (value_type a) { --a; } is true.

9

#

Effects: Decrements every element by one.

10

#

Returns: *this.

🔗

constexpr basic_vec operator--(int) noexcept;

11

#

Constraints: requires (value_type a) { a--; } is true.

12

#

Effects: Decrements every element by one.

13

#

Returns: A copy of *this before decrementing.

🔗

constexpr mask_type operator!() const noexcept;

14

#

Constraints: requires (const value_type a) { !a; } is true.

15

#

Returns: A basic_mask object with the ith element set to!operator for all i in the range of [0, size()).

🔗

constexpr basic_vec operator~() const noexcept;

16

#

Constraints: requires (const value_type a) { ~a; } is true.

17

#

Returns: A basic_vec object with the ith element set to~operator for all i in the range of [0, size()).

🔗

constexpr basic_vec operator+() const noexcept;

18

#

Constraints: requires (const value_type a) { +a; } is true.

19

#

Returns: *this.

🔗

constexpr basic_vec operator-() const noexcept;

20

#

Constraints: requires (const value_type a) { -a; } is true.

21

#

Returns: A basic_vec object where the ith element is initialized to-operator for all i in the range of [0, size()).