[simd.expos]

# 29 Numerics library [[numerics]](./#numerics)

## 29.10 Data-parallel types [[simd]](simd#expos)

### 29.10.2 Exposition-only types, variables, and concepts [simd.expos]

using *simd-size-type* = *see below*; // *exposition only*template<size_t Bytes> using *integer-from* = *see below*; // *exposition only*template<class T, class Abi>constexpr *simd-size-type* *simd-size-v* = *see below*; // *exposition only*template<class T> constexpr size_t *mask-element-size* = *see below*; // *exposition only*template<class T>concept [*constexpr-wrapper-like*](#concept:constexpr-wrapper-like "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") = // *exposition only*[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<T, decltype(T::value)> &&[equality_comparable_with](concept.equalitycomparable#concept:equality_comparable_with "18.5.4 Concept equality_­comparable [concept.equalitycomparable]")<T, decltype(T::value)> && bool_constant<T() == T::value>::value && bool_constant<static_cast<decltype(T::value)>(T()) == T::value>::value;

template<class T> using *deduced-vec-t* = *see below*; // *exposition only*template<class V, class T> using *make-compatible-simd-t* = *see below*; // *exposition only*template<class V>concept [*simd-vec-type*](#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") = // *exposition only*[same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<V, basic_vec<typename V::value_type, typename V::abi_type>> && is_default_constructible_v<V>;

template<class V>concept [*simd-mask-type*](#concept:simd-mask-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") = // *exposition only*[same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<V, basic_mask<*mask-element-size*<V>, typename V::abi_type>> && is_default_constructible_v<V>;

template<class V>concept [*simd-floating-point*](#concept:simd-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") = // *exposition only*[*simd-vec-type*](#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]")<V> && [floating_point](concepts.arithmetic#concept:floating_point "18.4.7 Arithmetic concepts [concepts.arithmetic]")<typename V::value_type>;

template<class V>concept [*simd-integral*](#concept:simd-integral "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") = // *exposition only*[*simd-vec-type*](#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]")<V> && [integral](concepts.arithmetic#concept:integral "18.4.7 Arithmetic concepts [concepts.arithmetic]")<typename V::value_type>;

template<class V>using *simd-complex-value-type* = typename V::value_type::value_type; // *exposition only*template<class V>concept [*simd-complex*](#concept:simd-complex "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") = // *exposition only*[*simd-vec-type*](#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]")<V> && [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<typename V::value_type, complex<*simd-complex-value-type*<V>>>;

template<class... Ts>concept [*math-floating-point*](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") = // *exposition only*([*simd-floating-point*](#concept:simd-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]")<*deduced-vec-t*<Ts>> || ...);

template<class... Ts>requires [*math-floating-point*](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]")<Ts...>using *math-common-simd-t* = *see below*; // *exposition only*template<class BinaryOperation, class T>concept [*reduction-binary-operation*](#concept:reduction-binary-operation "29.10.2.1 Exposition-only helpers [simd.expos.defn]") = *see below*; // *exposition only*// [[simd.expos.abi]](#abi "29.10.2.2 simd ABI tags"), simd ABI tagstemplate<class T> using *native-abi* = *see below*; // *exposition only*template<class T, *simd-size-type* N> using *deduce-abi-t* = *see below*; // *exposition only*// [[simd.flags]](simd.flags "29.10.5 Load and store flags"), Load and store flagsstruct *convert-flag*; // *exposition only*struct *aligned-flag*; // *exposition only*template<size_t N> struct *overaligned-flag*; // *exposition only*

#### [29.10.2.1](#defn) Exposition-only helpers [[simd.expos.defn]](simd.expos.defn)

[ð](#defn-itemdecl:1)

`using simd-size-type = see below;
`

[1](#defn-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16280)

*simd-size-type* is an alias for a signed integer type[.](#defn-1.sentence-1)

[ð](#defn-itemdecl:2)

`template<size_t Bytes> using integer-from = see below;
`

[2](#defn-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16289)

*integer-from*<Bytes> is an alias for a signed integer typeT such that sizeof(T) equals Bytes[.](#defn-2.sentence-1)

[ð](#defn-itemdecl:3)

`template<class T, class Abi>
  constexpr simd-size-type simd-size-v = see below;
`

[3](#defn-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16300)

*simd-size-v*<T, Abi> denotes the width of basic_vec<T,
Abi> if the specialization basic_vec<T, Abi> is enabled, or 0 otherwise[.](#defn-3.sentence-1)

[ð](#defn-itemdecl:4)

`template<class T> constexpr size_t mask-element-size = see below;
`

[4](#defn-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16311)

*mask-element-size*<basic_mask<Bytes, Abi>> has the valueBytes[.](#defn-4.sentence-1)

[ð](#defn-itemdecl:5)

`template<class T> using deduced-vec-t = see below;
`

[5](#defn-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16321)

Let x denote an lvalue of type const T[.](#defn-5.sentence-1)

[6](#defn-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16324)

*deduced-vec-t*<T> is an alias for

- [(6.1)](#defn-6.1)

decltype(x + x), if the type of x + x is an enabled
 specialization of basic_vec; otherwise

- [(6.2)](#defn-6.2)

void[.](#defn-6.sentence-1)

[ð](#defn-itemdecl:6)

`template<class V, class T> using make-compatible-simd-t = see below;
`

[7](#defn-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16340)

Let x denote an lvalue of type const T[.](#defn-7.sentence-1)

[8](#defn-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16343)

*make-compatible-simd-t*<V, T> is an alias for

- [(8.1)](#defn-8.1)

*deduced-vec-t*<T>, if that type is not void,
 otherwise

- [(8.2)](#defn-8.2)

vec<decltype(x + x), V​::​size()>[.](#defn-8.sentence-1)

[ð](#defn-itemdecl:7)

`template<class... Ts>
  requires [math-floating-point](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]")<Ts...>
    using math-common-simd-t = see below;
`

[9](#defn-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16361)

Let T0 denote Ts...[0][.](#defn-9.sentence-1)

Let T1 denote Ts...[1][.](#defn-9.sentence-2)

Let TRest denote a pack such that T0, T1, TRest... is equivalent
to Ts...[.](#defn-9.sentence-3)

[10](#defn-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16367)

Let *math-common-simd-t*<Ts...> be an alias for

- [(10.1)](#defn-10.1)

*deduced-vec-t*<T0>, if sizeof...(Ts) equals 1;
 otherwise

- [(10.2)](#defn-10.2)

common_type_t<*deduced-vec-t*<T0>, *deduced-vec-t*<T1>>, if sizeof...(Ts) equals 2 and [*math-floating-point*](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]")<T0> &&[*math-floating-point*](#concept:math-floating-point "29.10.2 Exposition-only types, variables, and concepts [simd.expos]")<T1> is true; otherwise

- [(10.3)](#defn-10.3)

common_type_t<*deduced-vec-t*<T0>, T1>, if sizeof...(Ts) equals 2 and *math-floating-​point*<​T0> is true; otherwise

- [(10.4)](#defn-10.4)

common_type_t<T0, *deduced-vec-t*<T1>>, if sizeof...(Ts) equals 2; otherwise

- [(10.5)](#defn-10.5)

common_type_t<*math-common-simd-t*<T0, T1>, TRest...>, if *math-common-simd-t*<T0, T1> is valid and denotes a type;
 otherwise

- [(10.6)](#defn-10.6)

common_type_t<*math-common-simd-t*<TRest...>, T0, T1>[.](#defn-10.sentence-1)

[ð](#concept:reduction-binary-operation)

`template<class BinaryOperation, class T>
  concept [reduction-binary-operation](#concept:reduction-binary-operation "29.10.2.1 Exposition-only helpers [simd.expos.defn]") =
    requires (const BinaryOperation binary_op, const vec<T, 1> v) {
      { binary_op(v, v) } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<vec<T, 1>>;
    };
`

[11](#defn-11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16404)

Types BinaryOperation and T model[*reduction-binary-operation*](#concept:reduction-binary-operation "29.10.2.1 Exposition-only helpers [simd.expos.defn]")<BinaryOperation, T> only if:

- [(11.1)](#defn-11.1)

  BinaryOperation is a binary element-wise operation and the
operation is commutative[.](#defn-11.1.sentence-1)

- [(11.2)](#defn-11.2)

  An object of type BinaryOperation can be invoked with two
arguments of type basic_vec<T, Abi>, with unspecified ABI tagAbi, returning a basic_vec<T, Abi>[.](#defn-11.2.sentence-1)

#### [29.10.2.2](#abi) simd ABI tags [[simd.expos.abi]](simd.expos.abi)

[ð](#abi-itemdecl:1)

`template<class T> using native-abi = see below;
template<class T, simd-size-type N> using deduce-abi-t = see below;
`

[1](#abi-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16425)

An [*ABI tag*](#def:ABI_tag "29.10.2.2 simd ABI tags [simd.expos.abi]") is a type that indicates a choice of size and binary
representation for objects of data-parallel type[.](#abi-1.sentence-1)

[*Note [1](#abi-note-1)*:

The intent is for the size and binary representation to depend on the target
architecture and compiler flags[.](#abi-1.sentence-2)

The ABI tag, together with a given element type, implies the width[.](#abi-1.sentence-3)

â *end note*]

[2](#abi-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16434)

[*Note [2](#abi-note-2)*:

The ABI tag is orthogonal to selecting the machine instruction set[.](#abi-2.sentence-1)

The selected machine instruction set limits the usable ABI tag types, though
(see [[simd.overview]](simd.overview "29.10.7.1 Class template basic_­vec overview"))[.](#abi-2.sentence-2)

The ABI tags enable users to safely pass objects of data-parallel type between
translation unit boundaries (e.g., function calls or I/O)[.](#abi-2.sentence-3)

â *end note*]

[3](#abi-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16443)

An implementation defines ABI tag types as necessary for the following aliases[.](#abi-3.sentence-1)

[4](#abi-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16446)

*deduce-abi-t*<T, N> is defined if

- [(4.1)](#abi-4.1)

T is a vectorizable type,

- [(4.2)](#abi-4.2)

N is greater than zero, and

- [(4.3)](#abi-4.3)

N is not larger than an implementation-defined maximum[.](#abi-4.sentence-1)

The implementation-defined maximum forN is not smaller than 64 and can differ depending on T[.](#abi-4.sentence-2)

[5](#abi-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16456)

Where present, *deduce-abi-t*<T, N> names an ABI tag type such
that

- [(5.1)](#abi-5.1)

*simd-size-v*<T, *deduce-abi-t*<T, N>> equals N,

- [(5.2)](#abi-5.2)

basic_vec<T, *deduce-abi-t*<T, N>> is
 enabled ([[simd.overview]](simd.overview "29.10.7.1 Class template basic_­vec overview")), and

- [(5.3)](#abi-5.3)

basic_mask<sizeof(T), *deduce-abi-t*<*integer-from*<sizeof(T)>, N>> is enabled[.](#abi-5.sentence-1)

[6](#abi-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L16469)

*native-abi*<T> is an implementation-defined alias for an ABI tag[.](#abi-6.sentence-1)

basic_vec<T, *native-abi*<T>> is an enabled specialization[.](#abi-6.sentence-2)

[*Note [3](#abi-note-3)*:

The intent is to use the ABI tag producing the most efficient data-parallel
execution for the element type T on the currently targeted system[.](#abi-6.sentence-3)

For target architectures with ISA extensions, compiler flags can change the type
of the *native-abi*<T> alias[.](#abi-6.sentence-4)

â *end note*]

[*Example [1](#abi-example-1)*:

Consider a target architecture supporting the ABI tags __simd128 and__simd256, where hardware support for __simd256 exists only for
floating-point types[.](#abi-6.sentence-5)

The implementation therefore defines *native-abi*<T> as an alias
for

- [(6.1)](#abi-6.1)

__simd256 if T is a floating-point type, and

- [(6.2)](#abi-6.2)

__simd128 otherwise[.](#abi-6.sentence-6)

â *end example*]
