[simd.permute.memory]

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

## 29.10 Data-parallel types [[simd]](simd#permute.memory)

### 29.10.8 basic_vec non-member operations [[simd.nonmembers]](simd.nonmembers#simd.permute.memory)

#### 29.10.8.10 simd memory permute [simd.permute.memory]

[ð](#lib:unchecked_gather_from,simd)

`template<class V = see below, ranges::[contiguous_range](range.refinements#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]") R, [simd-integral](simd.expos#concept:simd-integral "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") I, class... Flags>
  requires ranges::[sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R>
  constexpr V unchecked_gather_from(R&& in, const I& indices, flags<Flags...> f = {});
template<class V = see below, ranges::[contiguous_range](range.refinements#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]") R, [simd-integral](simd.expos#concept:simd-integral "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") I, class... Flags>
  requires ranges::[sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R>
  constexpr V unchecked_gather_from(R&& in, const typename I::mask_type& mask,
                                    const I& indices, flags<Flags...> f = {});
`

[1](#1)

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

Let mask be typename I​::​mask_type(true) for the overload with
no mask parameter[.](#1.sentence-1)

[2](#2)

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

*Preconditions*: All values in select(mask, indices, typename I​::​value_type()) are in
the range [0, ranges​::​size(in))[.](#2.sentence-1)

[3](#3)

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

*Effects*: Equivalent to: return partial_gather_from<V>(in, mask, indices, f);

[4](#4)

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

*Remarks*: The default argument for template parameter V isvec<ranges​::​range_value_t<R>, I​::​​size()>[.](#4.sentence-1)

[ð](#lib:partial_gather_from,simd)

`template<class V = see below, ranges::[contiguous_range](range.refinements#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]") R, [simd-integral](simd.expos#concept:simd-integral "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") I, class... Flags>
  requires ranges::[sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R>
  constexpr V partial_gather_from(R&& in, const I& indices, flags<Flags...> f = {});
template<class V = see below, ranges::[contiguous_range](range.refinements#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]") R, [simd-integral](simd.expos#concept:simd-integral "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") I, class... Flags>
  requires ranges::[sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R>
  constexpr V partial_gather_from(R&& in, const typename I::mask_type& mask,
                                  const I& indices, flags<Flags...> f = {});
`

[5](#5)

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

Let:

- [(5.1)](#5.1)

mask be typename I​::​mask_type(true) for the overload with no mask parameter;

- [(5.2)](#5.2)

T be typename V​::​value_type[.](#5.sentence-1)

[6](#6)

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

*Mandates*: 

- [(6.1)](#6.1)

ranges​::​range_value_t<R> is a vectorizable type,

- [(6.2)](#6.2)

same_as<remove_cvref_t<V>, V> is true,

- [(6.3)](#6.3)

V is an enabled specialization of basic_vec,

- [(6.4)](#6.4)

V​::​size() == I​::​size() is true, and

- [(6.5)](#6.5)

if the template parameter pack Flags does not contain*convert-flag*, then the conversion fromranges​::​range_value_t<R> to T is value-preserving[.](#6.sentence-1)

[7](#7)

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

*Preconditions*: 

- [(7.1)](#7.1)

  If the template parameter pack Flags contains*aligned-flag*, ranges​::​data(in) points to storage aligned byalignment_v<V, ranges​::​range_value_t<R>>[.](#7.1.sentence-1)

- [(7.2)](#7.2)

  If the template parameter pack Flags contains*overaligned-flag*<N>, ranges​::​data(in) points to
storage aligned by N[.](#7.2.sentence-1)

[8](#8)

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

*Returns*: A basic_vec object where the ith element is initialized to the result ofmask[i] && indices[i] < ranges::size(in) ? static_cast<T>(ranges::data(in)[indices[i]]) : T() for all i in the range [0, I​::​size())[.](#8.sentence-1)

[9](#9)

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

*Remarks*: The default argument for template parameter V isvec<ranges​::​range_value_t<R>, I​::​​size()>[.](#9.sentence-1)

[ð](#lib:unchecked_scatter_to,simd)

`template<[simd-vec-type](simd.expos#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V, ranges::[contiguous_range](range.refinements#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]") R, [simd-integral](simd.expos#concept:simd-integral "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") I, class... Flags>
  requires ranges::[sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R>
  constexpr void unchecked_scatter_to(const V& v, R&& out, const I& indices,
                                      flags<Flags...> f = {});
template<[simd-vec-type](simd.expos#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V, ranges::[contiguous_range](range.refinements#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]") R, [simd-integral](simd.expos#concept:simd-integral "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") I, class... Flags>
  requires ranges::[sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R>
  constexpr void unchecked_scatter_to(const V& v, R&& out, const typename I::mask_type& mask,
                                      const I& indices, flags<Flags...> f = {});
`

[10](#10)

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

Let mask be typename I​::​mask_type(true) for the overload with
no mask parameter[.](#10.sentence-1)

[11](#11)

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

*Preconditions*: All values in select(mask, indices, typename I​::​value_type()) are in
the range [0, ranges​::​size(out))[.](#11.sentence-1)

[12](#12)

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

*Effects*: Equivalent to: partial_scatter_to(v, out, mask, indices, f);

[ð](#lib:partial_scatter_to,simd)

`template<[simd-vec-type](simd.expos#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V, ranges::[contiguous_range](range.refinements#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]") R, [simd-integral](simd.expos#concept:simd-integral "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") I, class... Flags>
  requires ranges::[sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R>
  constexpr void
  partial_scatter_to(const V& v, R&& out, const I& indices, flags<Flags...> f = {});
template<[simd-vec-type](simd.expos#concept:simd-vec-type "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") V, ranges::[contiguous_range](range.refinements#concept:contiguous_range "25.4.6 Other range refinements [range.refinements]") R, [simd-integral](simd.expos#concept:simd-integral "29.10.2 Exposition-only types, variables, and concepts [simd.expos]") I, class... Flags>
  requires ranges::[sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<R>
  constexpr void partial_scatter_to(const V& v, R&& out, const typename I::mask_type& mask,
                                    const I& indices, flags<Flags...> f = {});
`

[13](#13)

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

Let mask be typename I​::​mask_type(true) for the overload with
no mask parameter[.](#13.sentence-1)

[14](#14)

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

*Constraints*: V​::​size() == I​::​size() is true[.](#14.sentence-1)

[15](#15)

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

*Mandates*: 

- [(15.1)](#15.1)

ranges​::​range_value_t<R> is a vectorizable type, and

- [(15.2)](#15.2)

if the template parameter pack Flags does not contain *convert-flag*,
then the conversion from typename V​::​value_type to ranges​::​range_value_t<R> is value-preserving[.](#15.sentence-1)

[16](#16)

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

*Preconditions*: 

- [(16.1)](#16.1)

  For all selected indices i the values indices[i] are unique[.](#16.1.sentence-1)

- [(16.2)](#16.2)

  If the template parameter pack Flags contains *aligned-flag*,ranges​::​data(out) points to storage aligned byalignment_v<V, ranges​::​range_value_t<R>>[.](#16.2.sentence-1)

- [(16.3)](#16.3)

  If the template parameter pack Flags contains*overaligned-flag*<N>,ranges​::​data(out) points to storage aligned by N[.](#16.3.sentence-1)

[17](#17)

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

*Effects*: For all i in the range [0, I​::​size()), if mask[i] &&(indices[i] < ranges​::​size(out)) is true, evaluatesranges​::​data(out)[indices[i]] = v[i][.](#17.sentence-1)
