From Jason Turner

[numerics]

Large diff (399.9 KB) - rendering may be slow on some devices

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp33xvo_sw/{from.md → to.md} +8197 -465
tmp/tmp33xvo_sw/{from.md → to.md} RENAMED
@@ -19,10 +19,12 @@ floating-point types, as summarized in [[numerics.summary]].
19
  | [[complex.numbers]] | Complex numbers | `<complex>` |
20
  | [[rand]] | Random number generation | `<random>` |
21
  | [[numarray]] | Numeric arrays | `<valarray>` |
22
  | [[c.math]] | Mathematical functions for floating-point types | `<cmath>`, `<cstdlib>` |
23
  | [[numbers]] | Numbers | `<numbers>` |
 
 
24
 
25
 
26
  ## Numeric type requirements <a id="numeric.requirements">[[numeric.requirements]]</a>
27
 
28
  The `complex` and `valarray` components are parameterized by the type of
@@ -65,11 +67,11 @@ operators. — *end example*]
65
  #define FE_DFL_ENV see below
66
 
67
  namespace std {
68
  // types
69
  using fenv_t = object type;
70
- using fexcept_t = integer type;
71
 
72
  // functions
73
  int feclearexcept(int except);
74
  int fegetexceptflag(fexcept_t* pflag, int except);
75
  int feraiseexcept(int except);
@@ -84,12 +86,13 @@ namespace std {
84
  int fesetenv(const fenv_t* penv);
85
  int feupdateenv(const fenv_t* penv);
86
  }
87
  ```
88
 
89
- The contents and meaning of the header `<cfenv>` are the same as the C
90
- standard library header `<fenv.h>`.
 
91
 
92
  [*Note 1*: This document does not require an implementation to support
93
  the `FENV_ACCESS` pragma; it is *implementation-defined* [[cpp.pragma]]
94
  whether the pragma is supported. As a consequence, it is
95
  *implementation-defined* whether these functions can be used to test
@@ -122,14 +125,14 @@ thread.
122
  ### General <a id="complex.numbers.general">[[complex.numbers.general]]</a>
123
 
124
  The header `<complex>` defines a class template, and numerous functions
125
  for representing and manipulating complex numbers.
126
 
127
- The effect of instantiating the template `complex` for any type that is
128
- not a cv-unqualified floating-point type [[basic.fundamental]] is
129
- unspecified. Specializations of `complex` for cv-unqualified
130
- floating-point types are trivially-copyable literal types
131
  [[term.literal.type]].
132
 
133
  If the result of a function is not mathematically defined or not in the
134
  range of representable values for its type, the behavior is undefined.
135
 
@@ -142,14 +145,14 @@ If `z` is an lvalue of type cv `complex<T>` then:
142
  `z`.
143
 
144
  Moreover, if `a` is an expression of type cv `complex<T>*` and the
145
  expression `a[i]` is well-defined for an integer expression `i`, then:
146
 
147
- - `reinterpret_cast<cv T*>(a)[2*i]` designates the real part of `a[i]`,
148
- and
149
- - `reinterpret_cast<cv T*>(a)[2*i + 1]` designates the imaginary part of
150
- `a[i]`.
151
 
152
  ### Header `<complex>` synopsis <a id="complex.syn">[[complex.syn]]</a>
153
 
154
  ``` cpp
155
  namespace std {
@@ -187,42 +190,56 @@ namespace std {
187
 
188
  // [complex.value.ops], values
189
  template<class T> constexpr T real(const complex<T>&);
190
  template<class T> constexpr T imag(const complex<T>&);
191
 
192
- template<class T> T abs(const complex<T>&);
193
- template<class T> T arg(const complex<T>&);
194
  template<class T> constexpr T norm(const complex<T>&);
195
 
196
  template<class T> constexpr complex<T> conj(const complex<T>&);
197
- template<class T> complex<T> proj(const complex<T>&);
198
- template<class T> complex<T> polar(const T&, const T& = T());
199
 
200
  // [complex.transcendentals], transcendentals
201
- template<class T> complex<T> acos(const complex<T>&);
202
- template<class T> complex<T> asin(const complex<T>&);
203
- template<class T> complex<T> atan(const complex<T>&);
204
 
205
- template<class T> complex<T> acosh(const complex<T>&);
206
- template<class T> complex<T> asinh(const complex<T>&);
207
- template<class T> complex<T> atanh(const complex<T>&);
208
 
209
- template<class T> complex<T> cos (const complex<T>&);
210
- template<class T> complex<T> cosh (const complex<T>&);
211
- template<class T> complex<T> exp (const complex<T>&);
212
- template<class T> complex<T> log (const complex<T>&);
213
- template<class T> complex<T> log10(const complex<T>&);
214
 
215
- template<class T> complex<T> pow (const complex<T>&, const T&);
216
- template<class T> complex<T> pow (const complex<T>&, const complex<T>&);
217
- template<class T> complex<T> pow (const T&, const complex<T>&);
218
 
219
- template<class T> complex<T> sin (const complex<T>&);
220
- template<class T> complex<T> sinh (const complex<T>&);
221
- template<class T> complex<T> sqrt (const complex<T>&);
222
- template<class T> complex<T> tan (const complex<T>&);
223
- template<class T> complex<T> tanh (const complex<T>&);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
 
225
  // [complex.literals], complex literals
226
  inline namespace literals {
227
  inline namespace complex_literals {
228
  constexpr complex<long double> operator""il(long double);
@@ -353,10 +370,19 @@ constexpr complex& operator/=(const T& rhs);
353
  *Effects:* Divides the scalar value `rhs` into the complex value `*this`
354
  and stores the result in `*this`.
355
 
356
  *Returns:* `*this`.
357
 
 
 
 
 
 
 
 
 
 
358
  ``` cpp
359
  template<class X> constexpr complex& operator+=(const complex<X>& rhs);
360
  ```
361
 
362
  *Effects:* Adds the complex value `rhs` to the complex value `*this` and
@@ -503,17 +529,17 @@ template<class T> constexpr T imag(const complex<T>& x);
503
  ```
504
 
505
  *Returns:* `x.imag()`.
506
 
507
  ``` cpp
508
- template<class T> T abs(const complex<T>& x);
509
  ```
510
 
511
  *Returns:* The magnitude of `x`.
512
 
513
  ``` cpp
514
- template<class T> T arg(const complex<T>& x);
515
  ```
516
 
517
  *Returns:* The phase angle of `x`, or `atan2(imag(x), real(x))`.
518
 
519
  ``` cpp
@@ -527,103 +553,103 @@ template<class T> constexpr complex<T> conj(const complex<T>& x);
527
  ```
528
 
529
  *Returns:* The complex conjugate of `x`.
530
 
531
  ``` cpp
532
- template<class T> complex<T> proj(const complex<T>& x);
533
  ```
534
 
535
  *Returns:* The projection of `x` onto the Riemann sphere.
536
 
537
  *Remarks:* Behaves the same as the C function `cproj`. See also: ISO C
538
  7.3.9.5
539
 
540
  ``` cpp
541
- template<class T> complex<T> polar(const T& rho, const T& theta = T());
542
  ```
543
 
544
  *Preconditions:* `rho` is non-negative and non-NaN. `theta` is finite.
545
 
546
  *Returns:* The `complex` value corresponding to a complex number whose
547
  magnitude is `rho` and whose phase angle is `theta`.
548
 
549
  ### Transcendentals <a id="complex.transcendentals">[[complex.transcendentals]]</a>
550
 
551
  ``` cpp
552
- template<class T> complex<T> acos(const complex<T>& x);
553
  ```
554
 
555
  *Returns:* The complex arc cosine of `x`.
556
 
557
  *Remarks:* Behaves the same as the C function `cacos`. See also: ISO C
558
  7.3.5.1
559
 
560
  ``` cpp
561
- template<class T> complex<T> asin(const complex<T>& x);
562
  ```
563
 
564
  *Returns:* The complex arc sine of `x`.
565
 
566
  *Remarks:* Behaves the same as the C function `casin`. See also: ISO C
567
  7.3.5.2
568
 
569
  ``` cpp
570
- template<class T> complex<T> atan(const complex<T>& x);
571
  ```
572
 
573
  *Returns:* The complex arc tangent of `x`.
574
 
575
  *Remarks:* Behaves the same as the C function `catan`. See also: ISO C
576
  7.3.5.3
577
 
578
  ``` cpp
579
- template<class T> complex<T> acosh(const complex<T>& x);
580
  ```
581
 
582
  *Returns:* The complex arc hyperbolic cosine of `x`.
583
 
584
  *Remarks:* Behaves the same as the C function `cacosh`. See also: ISO C
585
  7.3.6.1
586
 
587
  ``` cpp
588
- template<class T> complex<T> asinh(const complex<T>& x);
589
  ```
590
 
591
  *Returns:* The complex arc hyperbolic sine of `x`.
592
 
593
  *Remarks:* Behaves the same as the C function `casinh`. See also: ISO C
594
  7.3.6.2
595
 
596
  ``` cpp
597
- template<class T> complex<T> atanh(const complex<T>& x);
598
  ```
599
 
600
  *Returns:* The complex arc hyperbolic tangent of `x`.
601
 
602
  *Remarks:* Behaves the same as the C function `catanh`. See also: ISO C
603
  7.3.6.3
604
 
605
  ``` cpp
606
- template<class T> complex<T> cos(const complex<T>& x);
607
  ```
608
 
609
  *Returns:* The complex cosine of `x`.
610
 
611
  ``` cpp
612
- template<class T> complex<T> cosh(const complex<T>& x);
613
  ```
614
 
615
  *Returns:* The complex hyperbolic cosine of `x`.
616
 
617
  ``` cpp
618
- template<class T> complex<T> exp(const complex<T>& x);
619
  ```
620
 
621
  *Returns:* The complex base-e exponential of `x`.
622
 
623
  ``` cpp
624
- template<class T> complex<T> log(const complex<T>& x);
625
  ```
626
 
627
  *Returns:* The complex natural (base-e) logarithm of `x`. For all `x`,
628
  `imag(log(x))` lies in the interval \[-π, π\].
629
 
@@ -631,44 +657,44 @@ template<class T> complex<T> log(const complex<T>& x);
631
  in C++ as they are for `clog` in C. — *end note*]
632
 
633
  *Remarks:* The branch cuts are along the negative real axis.
634
 
635
  ``` cpp
636
- template<class T> complex<T> log10(const complex<T>& x);
637
  ```
638
 
639
  *Returns:* The complex common (base-10) logarithm of `x`, defined as
640
  `log(x) / log(10)`.
641
 
642
  *Remarks:* The branch cuts are along the negative real axis.
643
 
644
  ``` cpp
645
- template<class T> complex<T> pow(const complex<T>& x, const complex<T>& y);
646
- template<class T> complex<T> pow(const complex<T>& x, const T& y);
647
- template<class T> complex<T> pow(const T& x, const complex<T>& y);
648
  ```
649
 
650
  *Returns:* The complex power of base `x` raised to the `y`ᵗʰ power,
651
  defined as `exp(y * log(x))`. The value returned for `pow(0, 0)` is
652
  *implementation-defined*.
653
 
654
  *Remarks:* The branch cuts are along the negative real axis.
655
 
656
  ``` cpp
657
- template<class T> complex<T> sin(const complex<T>& x);
658
  ```
659
 
660
  *Returns:* The complex sine of `x`.
661
 
662
  ``` cpp
663
- template<class T> complex<T> sinh(const complex<T>& x);
664
  ```
665
 
666
  *Returns:* The complex hyperbolic sine of `x`.
667
 
668
  ``` cpp
669
- template<class T> complex<T> sqrt(const complex<T>& x);
670
  ```
671
 
672
  *Returns:* The complex square root of `x`, in the range of the right
673
  half-plane.
674
 
@@ -676,45 +702,74 @@ half-plane.
676
  in C++ as they are for `csqrt` in C. — *end note*]
677
 
678
  *Remarks:* The branch cuts are along the negative real axis.
679
 
680
  ``` cpp
681
- template<class T> complex<T> tan(const complex<T>& x);
682
  ```
683
 
684
  *Returns:* The complex tangent of `x`.
685
 
686
  ``` cpp
687
- template<class T> complex<T> tanh(const complex<T>& x);
688
  ```
689
 
690
  *Returns:* The complex hyperbolic tangent of `x`.
691
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
692
  ### Additional overloads <a id="cmplx.over">[[cmplx.over]]</a>
693
 
694
- The following function templates shall have additional overloads:
695
 
696
  ``` cpp
697
  arg norm
698
  conj proj
699
  imag real
700
  ```
701
 
702
- where `norm`, `conj`, `imag`, and `real` are `constexpr` overloads.
703
-
704
- The additional overloads shall be sufficient to ensure:
705
 
706
  - If the argument has a floating-point type `T`, then it is effectively
707
  cast to `complex<T>`.
708
  - Otherwise, if the argument has integer type, then it is effectively
709
  cast to `complex<double>`.
710
 
711
- Function template `pow` has additional overloads sufficient to ensure,
712
- for a call with one argument of type `complex<T1>` and the other
713
  argument of type `T2` or `complex<T2>`, both arguments are effectively
714
- cast to `complex<common_type_t<T1, T2>>`. If `common_type_t<T1, T2>` is
715
- not well-formed, then the program is ill-formed.
 
716
 
717
  ### Suffixes for complex number literals <a id="complex.literals">[[complex.literals]]</a>
718
 
719
  This subclause describes literal suffixes for constructing complex
720
  number literals. The suffixes `i`, `il`, and `if` create complex numbers
@@ -794,65 +849,94 @@ conventional bitwise operations. Further:
794
  #include <initializer_list> // see [initializer.list.syn]
795
 
796
  namespace std {
797
  // [rand.req.urng], uniform random bit generator requirements
798
  template<class G>
799
- concept uniform_random_bit_generator = see below;
800
 
801
  // [rand.eng.lcong], class template linear_congruential_engine
802
  template<class UIntType, UIntType a, UIntType c, UIntType m>
803
- class linear_congruential_engine;
804
 
805
  // [rand.eng.mers], class template mersenne_twister_engine
806
  template<class UIntType, size_t w, size_t n, size_t m, size_t r,
807
  UIntType a, size_t u, UIntType d, size_t s,
808
  UIntType b, size_t t,
809
  UIntType c, size_t l, UIntType f>
810
  class mersenne_twister_engine;
811
 
812
  // [rand.eng.sub], class template subtract_with_carry_engine
813
  template<class UIntType, size_t w, size_t s, size_t r>
814
- class subtract_with_carry_engine;
815
 
816
  // [rand.adapt.disc], class template discard_block_engine
817
  template<class Engine, size_t p, size_t r>
818
- class discard_block_engine;
819
 
820
  // [rand.adapt.ibits], class template independent_bits_engine
821
  template<class Engine, size_t w, class UIntType>
822
- class independent_bits_engine;
823
 
824
  // [rand.adapt.shuf], class template shuffle_order_engine
825
  template<class Engine, size_t k>
826
  class shuffle_order_engine;
827
 
 
 
 
 
828
  // [rand.predef], engines and engine adaptors with predefined parameters
829
- using minstd_rand0 = see below;
830
- using minstd_rand = see below;
831
- using mt19937 = see below;
832
- using mt19937_64 = see below;
833
- using ranlux24_base = see below;
834
- using ranlux48_base = see below;
835
- using ranlux24 = see below;
836
- using ranlux48 = see below;
837
  using knuth_b = see below;
 
 
838
 
839
  using default_random_engine = see below;
840
 
841
  // [rand.device], class random_device
842
  class random_device;
843
 
844
  // [rand.util.seedseq], class seed_seq
845
  class seed_seq;
846
 
847
  // [rand.util.canonical], function template generate_canonical
848
- template<class RealType, size_t bits, class URBG>
849
  RealType generate_canonical(URBG& g);
850
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
851
  // [rand.dist.uni.int], class template uniform_int_distribution
852
  template<class IntType = int>
853
- class uniform_int_distribution;
854
 
855
  // [rand.dist.uni.real], class template uniform_real_distribution
856
  template<class RealType = double>
857
  class uniform_real_distribution;
858
 
@@ -931,12 +1015,11 @@ namespace std {
931
 
932
  ### Requirements <a id="rand.req">[[rand.req]]</a>
933
 
934
  #### General requirements <a id="rand.req.genl">[[rand.req.genl]]</a>
935
 
936
- Throughout this subclause [[rand]], the effect of instantiating a
937
- template:
938
 
939
  - that has a template type parameter named `Sseq` is undefined unless
940
  the corresponding template argument is cv-unqualified and meets the
941
  requirements of seed sequence [[rand.req.seedseq]].
942
  - that has a template type parameter named `URBG` is undefined unless
@@ -955,18 +1038,18 @@ template:
955
  - that has a template type parameter named `UIntType` is undefined
956
  unless the corresponding template argument is cv-unqualified and is
957
  one of `unsigned short`, `unsigned int`, `unsigned long`, or
958
  `unsigned long long`.
959
 
960
- Throughout this subclause [[rand]], phrases of the form “`x` is an
961
- iterator of a specific kind” shall be interpreted as equivalent to the
962
- more formal requirement that “`x` is a value of a type meeting the
963
- requirements of the specified iterator type”.
964
 
965
- Throughout this subclause [[rand]], any constructor that can be called
966
- with a single argument and that meets a requirement specified in this
967
- subclause shall be declared `explicit`.
968
 
969
  #### Seed sequence requirements <a id="rand.req.seedseq">[[rand.req.seedseq]]</a>
970
 
971
  A *seed sequence* is an object that consumes a sequence of
972
  integer-valued data and produces a requested number of unsigned integer
@@ -977,12 +1060,12 @@ streams of random variates. This can be useful, for example, in
977
  applications requiring large numbers of random number
978
  engines. — *end note*]
979
 
980
  A class `S` meets the requirements of a seed sequence if the expressions
981
  shown in [[rand.req.seedseq]] are valid and have the indicated
982
- semantics, and if `S` also meets all other requirements of this
983
- subclause [[rand.req.seedseq]]. In that Table and throughout this
984
  subclause:
985
 
986
  - `T` is the type named by `S`’s associated `result_type`;
987
  - `q` is a value of type `S` and `r` is a value of type `S` or
988
  `const S`;
@@ -1049,12 +1132,12 @@ suitable `operator>>`.
1049
 
1050
  A class `E` that meets the requirements of a uniform random bit
1051
  generator [[rand.req.urng]] also meets the requirements of a *random
1052
  number engine* if the expressions shown in [[rand.req.eng]] are valid
1053
  and have the indicated semantics, and if `E` also meets all other
1054
- requirements of this subclause [[rand.req.eng]]. In that Table and
1055
- throughout this subclause:
1056
 
1057
  - `T` is the type named by `E`’s associated `result_type`;
1058
  - `e` is a value of `E`, `v` is an lvalue of `E`, `x` and `y` are
1059
  (possibly const) values of `E`;
1060
  - `s` is a value of `T`;
@@ -1072,10 +1155,56 @@ where `charT` and `traits` are constrained according to [[strings]] and
1072
  `E` shall meet the *Cpp17CopyConstructible* (
1073
  [[cpp17.copyconstructible]]) and *Cpp17CopyAssignable* (
1074
  [[cpp17.copyassignable]]) requirements. These operations shall each be
1075
  of complexity no worse than 𝑂(\text{size of state}).
1076
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1077
  #### Random number engine adaptor requirements <a id="rand.req.adapt">[[rand.req.adapt]]</a>
1078
 
1079
  A *random number engine adaptor* (commonly shortened to *adaptor*) `a`
1080
  of type `A` is a random number engine that takes values produced by some
1081
  other random number engine, and applies an algorithm to those values in
@@ -1160,12 +1289,12 @@ P(zᵢ |{`p`}), to denote a distribution’s parameters `p` taken as a
1160
  whole.
1161
 
1162
  A class `D` meets the requirements of a *random number distribution* if
1163
  the expressions shown in [[rand.req.dist]] are valid and have the
1164
  indicated semantics, and if `D` and its associated types also meet all
1165
- other requirements of this subclause [[rand.req.dist]]. In that Table
1166
- and throughout this subclause,
1167
 
1168
  - `T` is the type named by `D`’s associated `result_type`;
1169
  - `P` is the type named by `D`’s associated `param_type`;
1170
  - `d` is a value of `D`, and `x` and `y` are (possibly const) values of
1171
  `D`;
@@ -1197,13 +1326,12 @@ representation is restored into the same or a different object `y` of
1197
  the same type using `is >> y`, repeated invocations of `y(g)` shall
1198
  produce the same sequence of numbers as would repeated invocations of
1199
  `x(g)`.
1200
 
1201
  It is unspecified whether `D::param_type` is declared as a (nested)
1202
- `class` or via a `typedef`. In this subclause [[rand]], declarations of
1203
- `D::param_type` are in the form of `typedef`s for convenience of
1204
- exposition only.
1205
 
1206
  `P` shall meet the *Cpp17CopyConstructible* (
1207
  [[cpp17.copyconstructible]]), *Cpp17CopyAssignable* (
1208
  [[cpp17.copyassignable]]), and *Cpp17EqualityComparable* (
1209
  [[cpp17.equalitycomparable]]) requirements.
@@ -1220,10 +1348,46 @@ the identical name, type, and semantics.
1220
 
1221
  ``` cpp
1222
  using distribution_type = D;
1223
  ```
1224
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1225
  ### Random number engine class templates <a id="rand.eng">[[rand.eng]]</a>
1226
 
1227
  #### General <a id="rand.eng.general">[[rand.eng.general]]</a>
1228
 
1229
  Each type instantiated from a class template specified in [[rand.eng]]
@@ -1245,11 +1409,11 @@ that are not described in [[rand.req.eng]] or for operations where there
1245
  is additional semantic information. In particular, declarations for copy
1246
  constructors, for copy assignment operators, for streaming operators,
1247
  and for equality and inequality operators are not shown in the synopses.
1248
 
1249
  Each template specified in [[rand.eng]] requires one or more
1250
- relationships, involving the value(s) of its non-type template
1251
  parameter(s), to hold. A program instantiating any of these templates is
1252
  ill-formed if any such required relationship fails to hold.
1253
 
1254
  For every random number engine and for every random number engine
1255
  adaptor `X` defined in [[rand.eng]] and in [[rand.adapt]]:
@@ -1315,21 +1479,22 @@ namespace std {
1315
  void discard(unsigned long long z);
1316
 
1317
  // inserters and extractors
1318
  template<class charT, class traits>
1319
  friend basic_ostream<charT, traits>&
1320
- operator<<(basic_ostream<charT, traits>& os, const linear_congruential_engine& x);
 
1321
  template<class charT, class traits>
1322
  friend basic_istream<charT, traits>&
1323
- operator>>(basic_istream<charT, traits>& is, linear_congruential_engine& x);
 
1324
  };
1325
  }
1326
  ```
1327
 
1328
- If the template parameter `m` is 0, the modulus m used throughout this
1329
- subclause  [[rand.eng.lcong]] is `numeric_limits<result_type>::max()`
1330
- plus 1.
1331
 
1332
  [*Note 1*: m need not be representable as a value of type
1333
  `result_type`. — *end note*]
1334
 
1335
  If the template parameter `m` is not 0, the following relations shall
@@ -1433,14 +1598,16 @@ namespace std {
1433
  void discard(unsigned long long z);
1434
 
1435
  // inserters and extractors
1436
  template<class charT, class traits>
1437
  friend basic_ostream<charT, traits>&
1438
- operator<<(basic_ostream<charT, traits>& os, const mersenne_twister_engine& x);
 
1439
  template<class charT, class traits>
1440
  friend basic_istream<charT, traits>&
1441
- operator>>(basic_istream<charT, traits>& is, mersenne_twister_engine& x);
 
1442
  };
1443
  }
1444
  ```
1445
 
1446
  The following relations shall hold: `0 < m`, `m <= n`, `2u < w`,
@@ -1513,17 +1680,17 @@ namespace std {
1513
  static constexpr size_t word_size = w;
1514
  static constexpr size_t short_lag = s;
1515
  static constexpr size_t long_lag = r;
1516
  static constexpr result_type min() { return 0; }
1517
  static constexpr result_type max() { return m - 1; }
1518
- static constexpr result_type default_seed = 19780503u;
1519
 
1520
  // constructors and seeding functions
1521
- subtract_with_carry_engine() : subtract_with_carry_engine(default_seed) {}
1522
  explicit subtract_with_carry_engine(result_type value);
1523
  template<class Sseq> explicit subtract_with_carry_engine(Sseq& q);
1524
- void seed(result_type value = default_seed);
1525
  template<class Sseq> void seed(Sseq& q);
1526
 
1527
  // equality operators
1528
  friend bool operator==(const subtract_with_carry_engine& x,
1529
  const subtract_with_carry_engine& y);
@@ -1533,14 +1700,16 @@ namespace std {
1533
  void discard(unsigned long long z);
1534
 
1535
  // inserters and extractors
1536
  template<class charT, class traits>
1537
  friend basic_ostream<charT, traits>&
1538
- operator<<(basic_ostream<charT, traits>& os, const subtract_with_carry_engine& x);
 
1539
  template<class charT, class traits>
1540
  friend basic_istream<charT, traits>&
1541
- operator>>(basic_istream<charT, traits>& is, subtract_with_carry_engine& x);
 
1542
  };
1543
  }
1544
  ```
1545
 
1546
  The following relations shall hold: `0u < s`, `s < r`, `0 < w`, and
@@ -1558,12 +1727,12 @@ below. If X₋₁ is then 0, sets c to 1; otherwise sets c to 0.
1558
 
1559
  To set the values Xₖ, first construct `e`, a
1560
  `linear_congruential_engine` object, as if by the following definition:
1561
 
1562
  ``` cpp
1563
- linear_congruential_engine<result_type,
1564
- 40014u,0u,2147483563u> e(value == 0u ? default_seed : value);
1565
  ```
1566
 
1567
  Then, to set each Xₖ, obtain new values z₀, …, zₙ₋₁ from n = ⌈ w/32 ⌉
1568
  successive invocations of `e`. Set Xₖ to
1569
  $\left( \sum_{j=0}^{n-1} z_j \cdot 2^{32j}\right) \bmod m$.
@@ -1578,38 +1747,207 @@ template<class Sseq> explicit subtract_with_carry_engine(Sseq& q);
1578
  r ⋅ k, invokes `q.generate(`a + 0`, `a + r ⋅ k`)` and then, iteratively
1579
  for i = -r, …, -1, sets Xᵢ to
1580
  $\left(\sum_{j=0}^{k-1}a_{k(i+r)+j} \cdot 2^{32j} \right) \bmod m$. If
1581
  X₋₁ is then 0, sets c to 1; otherwise sets c to 0.
1582
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1583
  ### Random number engine adaptor class templates <a id="rand.adapt">[[rand.adapt]]</a>
1584
 
1585
- #### In general <a id="rand.adapt.general">[[rand.adapt.general]]</a>
1586
 
1587
- Each type instantiated from a class template specified in this
1588
- subclause  [[rand.adapt]] meets the requirements of a random number
1589
- engine adaptor [[rand.req.adapt]] type.
1590
 
1591
  Except where specified otherwise, the complexity of each function
1592
- specified in this subclause  [[rand.adapt]] is constant.
1593
 
1594
- Except where specified otherwise, no function described in this
1595
- subclause  [[rand.adapt]] throws an exception.
1596
 
1597
- Every function described in this subclause  [[rand.adapt]] that has a
1598
- function parameter `q` of type `Sseq&` for a template type parameter
1599
- named `Sseq` that is different from type `seed_seq` throws what and when
1600
- the invocation of `q.generate` throws.
1601
 
1602
- Descriptions are provided in this subclause  [[rand.adapt]] only for
1603
- adaptor operations that are not described in subclause 
1604
- [[rand.req.adapt]] or for operations where there is additional semantic
1605
- information. In particular, declarations for copy constructors, for copy
1606
- assignment operators, for streaming operators, and for equality and
1607
- inequality operators are not shown in the synopses.
1608
 
1609
- Each template specified in this subclause  [[rand.adapt]] requires one
1610
- or more relationships, involving the value(s) of its non-type template
1611
  parameter(s), to hold. A program instantiating any of these templates is
1612
  ill-formed if any such required relationship fails to hold.
1613
 
1614
  #### Class template `discard_block_engine` <a id="rand.adapt.disc">[[rand.adapt.disc]]</a>
1615
 
@@ -1632,11 +1970,11 @@ invocation of `e()` while advancing `e`’s state as described above.
1632
  namespace std {
1633
  template<class Engine, size_t p, size_t r>
1634
  class discard_block_engine {
1635
  public:
1636
  // types
1637
- using result_type = typename Engine::result_type;
1638
 
1639
  // engine characteristics
1640
  static constexpr size_t block_size = p;
1641
  static constexpr size_t used_block = r;
1642
  static constexpr result_type min() { return Engine::min(); }
@@ -1663,14 +2001,14 @@ namespace std {
1663
  const Engine& base() const noexcept { return e; }
1664
 
1665
  // inserters and extractors
1666
  template<class charT, class traits>
1667
  friend basic_ostream<charT, traits>&
1668
- operator<<(basic_ostream<charT, traits>& os, const discard_block_engine& x);
1669
  template<class charT, class traits>
1670
  friend basic_istream<charT, traits>&
1671
- operator>>(basic_istream<charT, traits>& is, discard_block_engine& x);
1672
 
1673
  private:
1674
  Engine e; // exposition only
1675
  size_t n; // exposition only
1676
  };
@@ -1726,10 +2064,11 @@ for (k = n₀; k \neq n; k += 1) {
1726
  S = 2^{w₀ + 1} \cdot S + u \bmod 2^{w₀ + 1};
1727
  }
1728
  ```
1729
 
1730
  ``` cpp
 
1731
  template<class Engine, size_t w, class UIntType>
1732
  class independent_bits_engine {
1733
  public:
1734
  // types
1735
  using result_type = UIntType;
@@ -1759,18 +2098,19 @@ template<class Engine, size_t w, class UIntType>
1759
  const Engine& base() const noexcept { return e; }
1760
 
1761
  // inserters and extractors
1762
  template<class charT, class traits>
1763
  friend basic_ostream<charT, traits>&
1764
- operator<<(basic_ostream<charT, traits>& os, const independent_bits_engine& x);
1765
  template<class charT, class traits>
1766
  friend basic_istream<charT, traits>&
1767
- operator>>(basic_istream<charT, traits>& is, independent_bits_engine& x);
1768
 
1769
  private:
1770
  Engine e; // exposition only
1771
  };
 
1772
  ```
1773
 
1774
  The following relations shall hold: `0 < w` and
1775
  `w <= numeric_limits<result_type>::digits`.
1776
 
@@ -1802,11 +2142,11 @@ advancing `e`’s state as described above.
1802
  namespace std {
1803
  template<class Engine, size_t k>
1804
  class shuffle_order_engine {
1805
  public:
1806
  // types
1807
- using result_type = typename Engine::result_type;
1808
 
1809
  // engine characteristics
1810
  static constexpr size_t table_size = k;
1811
  static constexpr result_type min() { return Engine::min(); }
1812
  static constexpr result_type max() { return Engine::max(); }
@@ -1953,10 +2293,30 @@ provide at least acceptable engine behavior for relatively casual,
1953
  inexpert, and/or lightweight use. Because different implementations can
1954
  select different underlying engine types, code that uses this `typedef`
1955
  need not generate identical sequences across
1956
  implementations. — *end note*]
1957
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1958
  ### Class `random_device` <a id="rand.device">[[rand.device]]</a>
1959
 
1960
  A `random_device` uniform random bit generator produces nondeterministic
1961
  random numbers.
1962
 
@@ -2184,52 +2544,64 @@ copy(v.begin(), v.end(), dest);
2184
  *Throws:* What and when `OutputIterator` operations of `dest` throw.
2185
 
2186
  #### Function template `generate_canonical` <a id="rand.util.canonical">[[rand.util.canonical]]</a>
2187
 
2188
  ``` cpp
2189
- template<class RealType, size_t bits, class URBG>
2190
  RealType generate_canonical(URBG& g);
2191
  ```
2192
 
2193
- *Effects:* Invokes `g()` k times to obtain values g₀, …, gₖ₋₁,
2194
- respectively. Calculates a quantity
2195
- $$S = \sum_{i=0}^{k-1} (g_i - \texttt{g.min()})
2196
- \cdot R^i$$ using arithmetic of type `RealType`.
2197
 
2198
- *Returns:* S / Rᵏ.
 
 
 
 
 
2199
 
2200
- [*Note 1*: 0 S / Rᵏ < 1. *end note*]
 
 
 
 
 
 
 
 
 
 
2201
 
2202
  *Throws:* What and when `g` throws.
2203
 
2204
- *Complexity:* Exactly k = max(1, ⌈ b / log₂ R ⌉) invocations of `g`,
2205
- where b[^6]
2206
 
2207
- is the lesser of `numeric_limits<RealType>::digits` and `bits`, and R is
2208
- the value of `g.max()` - `g.min()` + 1.
2209
-
2210
- [*Note 2*: If the values gᵢ produced by `g` are uniformly distributed,
2211
  the instantiation’s results are distributed as uniformly as possible.
2212
  Obtaining a value in this way can be a useful step in the process of
2213
  transforming a value generated by a uniform random bit generator into a
2214
  value that can be delivered by a random number
2215
  distribution. — *end note*]
2216
 
 
 
 
 
2217
  ### Random number distribution class templates <a id="rand.dist">[[rand.dist]]</a>
2218
 
2219
- #### In general <a id="rand.dist.general">[[rand.dist.general]]</a>
2220
 
2221
- Each type instantiated from a class template specified in this
2222
- subclause  [[rand.dist]] meets the requirements of a random number
2223
- distribution [[rand.req.dist]] type.
2224
 
2225
- Descriptions are provided in this subclause  [[rand.dist]] only for
2226
- distribution operations that are not described in [[rand.req.dist]] or
2227
- for operations where there is additional semantic information. In
2228
- particular, declarations for copy constructors, for copy assignment
2229
- operators, for streaming operators, and for equality and inequality
2230
- operators are not shown in the synopses.
2231
 
2232
  The algorithms for producing each of the specified distributions are
2233
  *implementation-defined*.
2234
 
2235
  The value of each probability density function p(z) and of each discrete
@@ -2240,11 +2612,11 @@ outside its stated domain.
2240
 
2241
  ##### Class template `uniform_int_distribution` <a id="rand.dist.uni.int">[[rand.dist.uni.int]]</a>
2242
 
2243
  A `uniform_int_distribution` random number distribution produces random
2244
  integers i, a ≤ i ≤ b, distributed according to the constant discrete
2245
- probability function $$P(i\,|\,a,b) = 1 / (b - a + 1) \text{ .}$$
2246
 
2247
  ``` cpp
2248
  namespace std {
2249
  template<class IntType = int>
2250
  class uniform_int_distribution {
@@ -2277,14 +2649,16 @@ namespace std {
2277
  result_type max() const;
2278
 
2279
  // inserters and extractors
2280
  template<class charT, class traits>
2281
  friend basic_ostream<charT, traits>&
2282
- operator<<(basic_ostream<charT, traits>& os, const uniform_int_distribution& x);
 
2283
  template<class charT, class traits>
2284
  friend basic_istream<charT, traits>&
2285
- operator>>(basic_istream<charT, traits>& is, uniform_int_distribution& x);
 
2286
  };
2287
  }
2288
  ```
2289
 
2290
  ``` cpp
@@ -2312,11 +2686,11 @@ constructed.
2312
 
2313
  ##### Class template `uniform_real_distribution` <a id="rand.dist.uni.real">[[rand.dist.uni.real]]</a>
2314
 
2315
  A `uniform_real_distribution` random number distribution produces random
2316
  numbers x, a ≤ x < b, distributed according to the constant probability
2317
- density function $$p(x\,|\,a,b) = 1 / (b - a) \text{ .}$$
2318
 
2319
  [*Note 1*: This implies that p(x | a,b) is undefined when
2320
  `a == b`. — *end note*]
2321
 
2322
  ``` cpp
@@ -2390,15 +2764,11 @@ constructed.
2390
  #### Bernoulli distributions <a id="rand.dist.bern">[[rand.dist.bern]]</a>
2391
 
2392
  ##### Class `bernoulli_distribution` <a id="rand.dist.bern.bernoulli">[[rand.dist.bern.bernoulli]]</a>
2393
 
2394
  A `bernoulli_distribution` random number distribution produces `bool`
2395
- values b distributed according to the discrete probability function
2396
- $$P(b\,|\,p) = \left\{ \begin{array}{ll}
2397
- p & \text{ if $b = \tcode{true}$, or} \\
2398
- 1 - p & \text{ if $b = \tcode{false}$.}
2399
- \end{array}\right.$$
2400
 
2401
  ``` cpp
2402
  namespace std {
2403
  class bernoulli_distribution {
2404
  public:
@@ -2456,11 +2826,11 @@ constructed.
2456
 
2457
  ##### Class template `binomial_distribution` <a id="rand.dist.bern.bin">[[rand.dist.bern.bin]]</a>
2458
 
2459
  A `binomial_distribution` random number distribution produces integer
2460
  values i ≥ 0 distributed according to the discrete probability function
2461
- $$P(i\,|\,t,p) = \binom{t}{i} \cdot p^i \cdot (1-p)^{t-i} \text{ .}$$
2462
 
2463
  ``` cpp
2464
  namespace std {
2465
  template<class IntType = int>
2466
  class binomial_distribution {
@@ -2528,11 +2898,11 @@ constructed.
2528
 
2529
  ##### Class template `geometric_distribution` <a id="rand.dist.bern.geo">[[rand.dist.bern.geo]]</a>
2530
 
2531
  A `geometric_distribution` random number distribution produces integer
2532
  values i ≥ 0 distributed according to the discrete probability function
2533
- $$P(i\,|\,p) = p \cdot (1-p)^{i} \text{ .}$$
2534
 
2535
  ``` cpp
2536
  namespace std {
2537
  template<class IntType = int>
2538
  class geometric_distribution {
@@ -2591,12 +2961,11 @@ constructed.
2591
 
2592
  ##### Class template `negative_binomial_distribution` <a id="rand.dist.bern.negbin">[[rand.dist.bern.negbin]]</a>
2593
 
2594
  A `negative_binomial_distribution` random number distribution produces
2595
  random integers i ≥ 0 distributed according to the discrete probability
2596
- function
2597
- $$P(i\,|\,k,p) = \binom{k+i-1}{i} \cdot p^k \cdot (1-p)^i \text{ .}$$
2598
 
2599
  [*Note 1*: This implies that P(i | k,p) is undefined when
2600
  `p == 1`. — *end note*]
2601
 
2602
  ``` cpp
@@ -2670,17 +3039,19 @@ constructed.
2670
 
2671
  ##### Class template `poisson_distribution` <a id="rand.dist.pois.poisson">[[rand.dist.pois.poisson]]</a>
2672
 
2673
  A `poisson_distribution` random number distribution produces integer
2674
  values i ≥ 0 distributed according to the discrete probability function
2675
- $$P(i\,|\,\mu) = \frac{e^{-\mu} \mu^{i}}{i\,!} \text{ .}$$ The
2676
- distribution parameter μ is also known as this distribution’s *mean* .
 
 
2677
 
2678
  ``` cpp
 
2679
  template<class IntType = int>
2680
- class poisson_distribution
2681
- {
2682
  public:
2683
  // types
2684
  using result_type = IntType;
2685
  using param_type = unspecified;
2686
 
@@ -2712,10 +3083,11 @@ template<class IntType = int>
2712
  operator<<(basic_ostream<charT, traits>& os, const poisson_distribution& x);
2713
  template<class charT, class traits>
2714
  friend basic_istream<charT, traits>&
2715
  operator>>(basic_istream<charT, traits>& is, poisson_distribution& x);
2716
  };
 
2717
  ```
2718
 
2719
  ``` cpp
2720
  explicit poisson_distribution(double mean);
2721
  ```
@@ -2733,11 +3105,11 @@ constructed.
2733
 
2734
  ##### Class template `exponential_distribution` <a id="rand.dist.pois.exp">[[rand.dist.pois.exp]]</a>
2735
 
2736
  An `exponential_distribution` random number distribution produces random
2737
  numbers x > 0 distributed according to the probability density function
2738
- $$p(x\,|\,\lambda) = \lambda e^{-\lambda x} \text{ .}$$
2739
 
2740
  ``` cpp
2741
  namespace std {
2742
  template<class RealType = double>
2743
  class exponential_distribution {
@@ -2796,13 +3168,11 @@ constructed.
2796
 
2797
  ##### Class template `gamma_distribution` <a id="rand.dist.pois.gamma">[[rand.dist.pois.gamma]]</a>
2798
 
2799
  A `gamma_distribution` random number distribution produces random
2800
  numbers x > 0 distributed according to the probability density function
2801
- $$p(x\,|\,\alpha,\beta) =
2802
- \frac{e^{-x/\beta}}{\beta^{\alpha} \cdot \Gamma(\alpha)} \, \cdot \, x^{\, \alpha-1}
2803
- \text{ .}$$
2804
 
2805
  ``` cpp
2806
  namespace std {
2807
  template<class RealType = double>
2808
  class gamma_distribution {
@@ -2870,14 +3240,11 @@ constructed.
2870
 
2871
  ##### Class template `weibull_distribution` <a id="rand.dist.pois.weibull">[[rand.dist.pois.weibull]]</a>
2872
 
2873
  A `weibull_distribution` random number distribution produces random
2874
  numbers x ≥ 0 distributed according to the probability density function
2875
- $$p(x\,|\,a,b) = \frac{a}{b}
2876
- \cdot \left(\frac{x}{b}\right)^{a-1}
2877
- \cdot \, \exp\left( -\left(\frac{x}{b}\right)^a\right)
2878
- \text{ .}$$
2879
 
2880
  ``` cpp
2881
  namespace std {
2882
  template<class RealType = double>
2883
  class weibull_distribution {
@@ -2945,15 +3312,11 @@ constructed.
2945
 
2946
  ##### Class template `extreme_value_distribution` <a id="rand.dist.pois.extreme">[[rand.dist.pois.extreme]]</a>
2947
 
2948
  An `extreme_value_distribution` random number distribution produces
2949
  random numbers x distributed according to the probability density
2950
- function[^7]
2951
-
2952
- $$p(x\,|\,a,b) = \frac{1}{b}
2953
- \cdot \exp\left(\frac{a-x}{b} - \exp\left(\frac{a-x}{b}\right)\right)
2954
- \text{ .}$$
2955
 
2956
  ``` cpp
2957
  namespace std {
2958
  template<class RealType = double>
2959
  class extreme_value_distribution {
@@ -3023,20 +3386,13 @@ constructed.
3023
  #### Normal distributions <a id="rand.dist.norm">[[rand.dist.norm]]</a>
3024
 
3025
  ##### Class template `normal_distribution` <a id="rand.dist.norm.normal">[[rand.dist.norm.normal]]</a>
3026
 
3027
  A `normal_distribution` random number distribution produces random
3028
- numbers x distributed according to the probability density function $$%
3029
- p(x\,|\,\mu,\sigma)
3030
- = \frac{1}{\sigma \sqrt{2\pi}}
3031
- \cdot
3032
- % e^{-(x-\mu)^2 / (2\sigma^2)}
3033
- \exp{\left(- \, \frac{(x - \mu)^2}
3034
- {2 \sigma^2}
3035
- \right)
3036
- }
3037
- \text{ .}$$ The distribution parameters μ and σ are also known as this
3038
  distribution’s *mean* and *standard deviation*.
3039
 
3040
  ``` cpp
3041
  namespace std {
3042
  template<class RealType = double>
@@ -3105,13 +3461,11 @@ constructed.
3105
 
3106
  ##### Class template `lognormal_distribution` <a id="rand.dist.norm.lognormal">[[rand.dist.norm.lognormal]]</a>
3107
 
3108
  A `lognormal_distribution` random number distribution produces random
3109
  numbers x > 0 distributed according to the probability density function
3110
- $$p(x\,|\,m,s) = \frac{1}{s x \sqrt{2 \pi}}
3111
- \cdot \exp{\left(-\frac{(\ln{x} - m)^2}{2 s^2}\right)}
3112
- \text{ .}$$
3113
 
3114
  ``` cpp
3115
  namespace std {
3116
  template<class RealType = double>
3117
  class lognormal_distribution {
@@ -3179,11 +3533,11 @@ constructed.
3179
 
3180
  ##### Class template `chi_squared_distribution` <a id="rand.dist.norm.chisq">[[rand.dist.norm.chisq]]</a>
3181
 
3182
  A `chi_squared_distribution` random number distribution produces random
3183
  numbers x > 0 distributed according to the probability density function
3184
- $$p(x\,|\,n) = \frac{x^{(n/2)-1} \cdot e^{-x/2}}{\Gamma(n/2) \cdot 2^{n/2}} \text{ .}$$
3185
 
3186
  ``` cpp
3187
  namespace std {
3188
  template<class RealType = double>
3189
  class chi_squared_distribution {
@@ -3241,12 +3595,11 @@ RealType n() const;
3241
  constructed.
3242
 
3243
  ##### Class template `cauchy_distribution` <a id="rand.dist.norm.cauchy">[[rand.dist.norm.cauchy]]</a>
3244
 
3245
  A `cauchy_distribution` random number distribution produces random
3246
- numbers x distributed according to the probability density function
3247
- $$p(x\,|\,a,b) = \left(\pi b \left(1 + \left(\frac{x-a}{b} \right)^2 \, \right)\right)^{-1} \text{ .}$$
3248
 
3249
  ``` cpp
3250
  namespace std {
3251
  template<class RealType = double>
3252
  class cauchy_distribution {
@@ -3314,15 +3667,11 @@ constructed.
3314
 
3315
  ##### Class template `fisher_f_distribution` <a id="rand.dist.norm.f">[[rand.dist.norm.f]]</a>
3316
 
3317
  A `fisher_f_distribution` random number distribution produces random
3318
  numbers x ≥ 0 distributed according to the probability density function
3319
- $$p(x\,|\,m,n) = \frac{\Gamma\big((m+n)/2\big)}{\Gamma(m/2) \; \Gamma(n/2)}
3320
- \cdot \left(\frac{m}{n}\right)^{m/2}
3321
- \cdot x^{(m/2)-1}
3322
- \cdot \left(1 + \frac{m x}{n}\right)^{-(m + n)/2}
3323
- \text{ .}$$
3324
 
3325
  ``` cpp
3326
  namespace std {
3327
  template<class RealType = double>
3328
  class fisher_f_distribution {
@@ -3389,15 +3738,11 @@ RealType n() const;
3389
  constructed.
3390
 
3391
  ##### Class template `student_t_distribution` <a id="rand.dist.norm.t">[[rand.dist.norm.t]]</a>
3392
 
3393
  A `student_t_distribution` random number distribution produces random
3394
- numbers x distributed according to the probability density function
3395
- $$p(x\,|\,n) = \frac{1}{\sqrt{n \pi}}
3396
- \cdot \frac{\Gamma\big((n+1)/2\big)}{\Gamma(n/2)}
3397
- \cdot \left(1 + \frac{x^2}{n} \right)^{-(n+1)/2}
3398
- \text{ .}$$
3399
 
3400
  ``` cpp
3401
  namespace std {
3402
  template<class RealType = double>
3403
  class student_t_distribution {
@@ -3458,11 +3803,11 @@ constructed.
3458
 
3459
  ##### Class template `discrete_distribution` <a id="rand.dist.samp.discrete">[[rand.dist.samp.discrete]]</a>
3460
 
3461
  A `discrete_distribution` random number distribution produces random
3462
  integers i, 0 ≤ i < n, distributed according to the discrete probability
3463
- function $$P(i \,|\, p_0, \dotsc, p_{n-1}) = p_i \text{ .}$$
3464
 
3465
  Unless specified otherwise, the distribution parameters are calculated
3466
  as: pₖ = {wₖ / S} for k = 0, …, n - 1, in which the values wₖ, commonly
3467
  known as the *weights* , shall be non-negative, non-NaN, and
3468
  non-infinity. Moreover, the following relation shall hold:
@@ -3537,11 +3882,11 @@ is `true`.
3537
  requirements [[input.iterators]]. If `firstW == lastW`, let n = 1 and
3538
  w₀ = 1. Otherwise, [`firstW`, `lastW`) forms a sequence w of length
3539
  n > 0.
3540
 
3541
  *Effects:* Constructs a `discrete_distribution` object with
3542
- probabilities given by the formula above.
3543
 
3544
  ``` cpp
3545
  discrete_distribution(initializer_list<double> wl);
3546
  ```
3547
 
@@ -3576,12 +3921,11 @@ k = 0, …, n - 1.
3576
  ##### Class template `piecewise_constant_distribution` <a id="rand.dist.samp.pconst">[[rand.dist.samp.pconst]]</a>
3577
 
3578
  A `piecewise_constant_distribution` random number distribution produces
3579
  random numbers x, b₀ ≤ x < bₙ, uniformly distributed over each
3580
  subinterval [ bᵢ, bᵢ₊₁ ) according to the probability density function
3581
- $$p(x \,|\, b_0, \dotsc, b_n, \; \rho_0, \dotsc, \rho_{n-1}) = \rho_i
3582
- \text{ , for $b_i \le x < b_{i+1}$.}$$
3583
 
3584
  The n + 1 distribution parameters bᵢ, also known as this distribution’s
3585
  *interval boundaries* , shall satisfy the relation $b_i < b_{i + 1}$ for
3586
  i = 0, …, n - 1. Unless specified otherwise, the remaining n
3587
  distribution parameters are calculated as:
@@ -3723,15 +4067,11 @@ k = 0, …, n - 1.
3723
 
3724
  ##### Class template `piecewise_linear_distribution` <a id="rand.dist.samp.plinear">[[rand.dist.samp.plinear]]</a>
3725
 
3726
  A `piecewise_linear_distribution` random number distribution produces
3727
  random numbers x, b₀ ≤ x < bₙ, distributed over each subinterval
3728
- [bᵢ, bᵢ₊₁) according to the probability density function
3729
- $$p(x \,|\, b_0, \dotsc, b_n, \; \rho_0, \dotsc, \rho_n)
3730
- = \rho_{i} \cdot {\frac{b_{i+1} - x}{b_{i+1} - b_i}}
3731
- + \rho_{i+1} \cdot {\frac{x - b_i}{b_{i+1} - b_i}}
3732
- \text{ , for $b_i \le x < b_{i+1}$.}$$
3733
 
3734
  The n + 1 distribution parameters bᵢ, also known as this distribution’s
3735
  *interval boundaries* , shall satisfy the relation bᵢ < bᵢ₊₁ for
3736
  i = 0, …, n - 1. Unless specified otherwise, the remaining n + 1
3737
  distribution parameters are calculated as ρₖ = {wₖ / S} for k = 0, …, n,
@@ -3801,12 +4141,16 @@ n = 1, ρ₀ = ρ₁ = 1, b₀ = 0, and b₁ = 1.
3801
  template<class InputIteratorB, class InputIteratorW>
3802
  piecewise_linear_distribution(InputIteratorB firstB, InputIteratorB lastB,
3803
  InputIteratorW firstW);
3804
  ```
3805
 
3806
- *Mandates:* `is_invocable_r_v<double, UnaryOperation&, double>` is
3807
- `true`.
 
 
 
 
3808
 
3809
  *Preconditions:* `InputIteratorB` and `InputIteratorW` each meet the
3810
  *Cpp17InputIterator* requirements [[input.iterators]]. If
3811
  `firstB == lastB` or `++firstB == lastB`, let n = 1, ρ₀ = ρ₁ = 1,
3812
  b₀ = 0, and b₁ = 1. Otherwise, [`firstB`, `lastB`) forms a sequence b of
@@ -3886,11 +4230,11 @@ functions may call `rand`. It is *implementation-defined* whether the
3886
  document [[rand]] are often preferable to `rand`, because `rand`’s
3887
  underlying algorithm is unspecified. Use of `rand` therefore continues
3888
  to be non-portable, with unpredictable and oft-questionable quality and
3889
  performance. — *end note*]
3890
 
3891
- See also: ISO C 7.22.2
3892
 
3893
  ## Numeric arrays <a id="numarray">[[numarray]]</a>
3894
 
3895
  ### Header `<valarray>` synopsis <a id="valarray.syn">[[valarray.syn]]</a>
3896
 
@@ -4319,11 +4663,11 @@ operation to be assigned directly to a `valarray`.
4319
  ``` cpp
4320
  const T& operator[](size_t n) const;
4321
  T& operator[](size_t n);
4322
  ```
4323
 
4324
- *Preconditions:* `n < size()` is `true`.
4325
 
4326
  *Returns:* A reference to the corresponding element of the array.
4327
 
4328
  [*Note 1*: The expression `(a[i] = q, a[i]) == q` evaluates to `true`
4329
  for any non-constant `valarray<T> a`, any `T q`, and for any `size_t i`
@@ -4577,11 +4921,11 @@ valarray& operator>>=(const T& v);
4577
  type `T`.
4578
 
4579
  *Effects:* Each of these operators applies the indicated operation to
4580
  each element of `*this` and `v`.
4581
 
4582
- *Returns:* `*this`
4583
 
4584
  *Remarks:* The appearance of an array on the left-hand side of a
4585
  compound assignment does not invalidate references or pointers to the
4586
  elements of the array.
4587
 
@@ -5412,15 +5756,10 @@ template<class T> unspecified{2} end(const valarray<T>& v);
5412
  ## Mathematical functions for floating-point types <a id="c.math">[[c.math]]</a>
5413
 
5414
  ### Header `<cmath>` synopsis <a id="cmath.syn">[[cmath.syn]]</a>
5415
 
5416
  ``` cpp
5417
- namespace std {
5418
- using float_t = see below;
5419
- using double_t = see below;
5420
- }
5421
-
5422
  #define HUGE_VAL see below
5423
  #define HUGE_VALF see below
5424
  #define HUGE_VALL see below
5425
  #define INFINITY see below
5426
  #define NAN see below
@@ -5438,73 +5777,76 @@ namespace std {
5438
  #define MATH_ERREXCEPT see below
5439
 
5440
  #define math_errhandling see below
5441
 
5442
  namespace std {
5443
- floating-point-type acos(floating-point-type x);
5444
- float acosf(float x);
5445
- long double acosl(long double x);
5446
 
5447
- floating-point-type asin(floating-point-type x);
5448
- float asinf(float x);
5449
- long double asinl(long double x);
5450
 
5451
- floating-point-type atan(floating-point-type x);
5452
- float atanf(float x);
5453
- long double atanl(long double x);
5454
 
5455
- floating-point-type atan2(floating-point-type y, floating-point-type x);
5456
- float atan2f(float y, float x);
5457
- long double atan2l(long double y, long double x);
5458
 
5459
- floating-point-type cos(floating-point-type x);
5460
- float cosf(float x);
5461
- long double cosl(long double x);
5462
 
5463
- floating-point-type sin(floating-point-type x);
5464
- float sinf(float x);
5465
- long double sinl(long double x);
5466
 
5467
- floating-point-type tan(floating-point-type x);
5468
- float tanf(float x);
5469
- long double tanl(long double x);
5470
 
5471
- floating-point-type acosh(floating-point-type x);
5472
- float acoshf(float x);
5473
- long double acoshl(long double x);
5474
 
5475
- floating-point-type asinh(floating-point-type x);
5476
- float asinhf(float x);
5477
- long double asinhl(long double x);
5478
 
5479
- floating-point-type atanh(floating-point-type x);
5480
- float atanhf(float x);
5481
- long double atanhl(long double x);
5482
 
5483
- floating-point-type cosh(floating-point-type x);
5484
- float coshf(float x);
5485
- long double coshl(long double x);
5486
 
5487
- floating-point-type sinh(floating-point-type x);
5488
- float sinhf(float x);
5489
- long double sinhl(long double x);
5490
 
5491
- floating-point-type tanh(floating-point-type x);
5492
- float tanhf(float x);
5493
- long double tanhl(long double x);
5494
 
5495
- floating-point-type exp(floating-point-type x);
5496
- float expf(float x);
5497
- long double expl(long double x);
5498
 
5499
- floating-point-type exp2(floating-point-type x);
5500
- float exp2f(float x);
5501
- long double exp2l(long double x);
5502
 
5503
- floating-point-type expm1(floating-point-type x);
5504
- float expm1f(float x);
5505
- long double expm1l(long double x);
 
 
 
 
5506
 
5507
  constexpr floating-point-type frexp(floating-point-type value, int* exp);
5508
  constexpr float frexpf(float value, int* exp);
5509
  constexpr long double frexpl(long double value, int* exp);
5510
 
@@ -5514,25 +5856,25 @@ namespace std {
5514
 
5515
  constexpr floating-point-type ldexp(floating-point-type x, int exp);
5516
  constexpr float ldexpf(float x, int exp);
5517
  constexpr long double ldexpl(long double x, int exp);
5518
 
5519
- floating-point-type log(floating-point-type x);
5520
- float logf(float x);
5521
- long double logl(long double x);
5522
 
5523
- floating-point-type log10(floating-point-type x);
5524
- float log10f(float x);
5525
- long double log10l(long double x);
5526
 
5527
- floating-point-type log1p(floating-point-type x);
5528
- float log1pf(float x);
5529
- long double log1pl(long double x);
5530
 
5531
- floating-point-type log2(floating-point-type x);
5532
- float log2f(float x);
5533
- long double log2l(long double x);
5534
 
5535
  constexpr floating-point-type logb(floating-point-type x);
5536
  constexpr float logbf(float x);
5537
  constexpr long double logbl(long double x);
5538
 
@@ -5546,55 +5888,55 @@ namespace std {
5546
 
5547
  constexpr floating-point-type scalbln(floating-point-type x, long int n);
5548
  constexpr float scalblnf(float x, long int n);
5549
  constexpr long double scalblnl(long double x, long int n);
5550
 
5551
- floating-point-type cbrt(floating-point-type x);
5552
- float cbrtf(float x);
5553
- long double cbrtl(long double x);
5554
 
5555
  // [c.math.abs], absolute values
5556
- constexpr int abs(int j);
5557
- constexpr long int abs(long int j);
5558
- constexpr long long int abs(long long int j);
5559
- constexpr floating-point-type abs(floating-point-type j);
5560
 
5561
  constexpr floating-point-type fabs(floating-point-type x);
5562
  constexpr float fabsf(float x);
5563
  constexpr long double fabsl(long double x);
5564
 
5565
- floating-point-type hypot(floating-point-type x, floating-point-type y);
5566
- float hypotf(float x, float y);
5567
- long double hypotl(long double x, long double y);
5568
 
5569
  // [c.math.hypot3], three-dimensional hypotenuse
5570
- floating-point-type hypot(floating-point-type x, floating-point-type y,
5571
  floating-point-type z);
5572
 
5573
- floating-point-type pow(floating-point-type x, floating-point-type y);
5574
- float powf(float x, float y);
5575
- long double powl(long double x, long double y);
5576
 
5577
- floating-point-type sqrt(floating-point-type x);
5578
- float sqrtf(float x);
5579
- long double sqrtl(long double x);
5580
 
5581
- floating-point-type erf(floating-point-type x);
5582
- float erff(float x);
5583
- long double erfl(long double x);
5584
 
5585
- floating-point-type erfc(floating-point-type x);
5586
- float erfcf(float x);
5587
- long double erfcl(long double x);
5588
 
5589
- floating-point-type lgamma(floating-point-type x);
5590
- float lgammaf(float x);
5591
- long double lgammal(long double x);
5592
 
5593
- floating-point-type tgamma(floating-point-type x);
5594
- float tgammaf(float x);
5595
- long double tgammal(long double x);
5596
 
5597
  constexpr floating-point-type ceil(floating-point-type x);
5598
  constexpr float ceilf(float x);
5599
  constexpr long double ceill(long double x);
5600
 
@@ -5660,10 +6002,18 @@ namespace std {
5660
 
5661
  constexpr floating-point-type nexttoward(floating-point-type x, long double y);
5662
  constexpr float nexttowardf(float x, long double y);
5663
  constexpr long double nexttowardl(long double x, long double y);
5664
 
 
 
 
 
 
 
 
 
5665
  constexpr floating-point-type fdim(floating-point-type x, floating-point-type y);
5666
  constexpr float fdimf(float x, float y);
5667
  constexpr long double fdiml(long double x, long double y);
5668
 
5669
  constexpr floating-point-type fmax(floating-point-type x, floating-point-type y);
@@ -5672,10 +6022,15 @@ namespace std {
5672
 
5673
  constexpr floating-point-type fmin(floating-point-type x, floating-point-type y);
5674
  constexpr float fminf(float x, float y);
5675
  constexpr long double fminl(long double x, long double y);
5676
 
 
 
 
 
 
5677
  constexpr floating-point-type fma(floating-point-type x, floating-point-type y,
5678
  floating-point-type z);
5679
  constexpr float fmaf(float x, float y, float z);
5680
  constexpr long double fmal(long double x, long double y, long double z);
5681
 
@@ -5807,41 +6162,42 @@ namespace std {
5807
  float sph_neumannf(unsigned n, float x);
5808
  long double sph_neumannl(unsigned n, long double x);
5809
  }
5810
  ```
5811
 
5812
- The contents and meaning of the header `<cmath>` are the same as the C
5813
- standard library header `<math.h>`, with the addition of a
5814
- three-dimensional hypotenuse function [[c.math.hypot3]], a linear
5815
- interpolation function [[c.math.lerp]], and the mathematical special
5816
- functions described in [[sf.cmath]].
 
5817
 
5818
  [*Note 1*: Several functions have additional overloads in this
5819
  document, but they have the same behavior as in the C standard library
5820
  [[library.c]]. — *end note*]
5821
 
5822
  For each function with at least one parameter of type
5823
- *floating-point-type*, the implementation provides an overload for each
5824
  cv-unqualified floating-point type [[basic.fundamental]] where all uses
5825
- of *floating-point-type* in the function signature are replaced with
5826
  that floating-point type.
5827
 
5828
  For each function with at least one parameter of type
5829
- *floating-point-type* other than `abs`, the implementation also provides
5830
  additional overloads sufficient to ensure that, if every argument
5831
- corresponding to a *floating-point-type* parameter has arithmetic type,
5832
  then every such argument is effectively cast to the floating-point type
5833
  with the greatest floating-point conversion rank and greatest
5834
  floating-point conversion subrank among the types of all such arguments,
5835
  where arguments of integer type are considered to have the same
5836
  floating-point conversion rank as `double`. If no such floating-point
5837
  type with the greatest rank and subrank exists, then overload resolution
5838
  does not result in a usable candidate [[over.match.general]] from the
5839
  overloads provided by the implementation.
5840
 
5841
  An invocation of `nexttoward` is ill-formed if the argument
5842
- corresponding to the *floating-point-type* parameter has extended
5843
  floating-point type.
5844
 
5845
  See also: ISO C 7.12
5846
 
5847
  ### Absolute values <a id="c.math.abs">[[c.math.abs]]</a>
@@ -5861,25 +6217,26 @@ respectively.
5861
 
5862
  *Remarks:* If `abs` is called with an argument of type `X` for which
5863
  `is_unsigned_v<X>` is `true` and if `X` cannot be converted to `int` by
5864
  integral promotion [[conv.prom]], the program is ill-formed.
5865
 
5866
- [*Note 1*: Arguments that can be promoted to `int` are permitted for
5867
  compatibility with C. — *end note*]
5868
 
5869
  ``` cpp
5870
  constexpr floating-point-type abs(floating-point-type x);
5871
  ```
5872
 
5873
  *Returns:* The absolute value of `x`.
5874
 
5875
- See also: ISO C 7.12.7.2, 7.22.6.1
5876
 
5877
  ### Three-dimensional hypotenuse <a id="c.math.hypot3">[[c.math.hypot3]]</a>
5878
 
5879
  ``` cpp
5880
- floating-point-type hypot(floating-point-type x, floating-point-type y, floating-point-type z);
 
5881
  ```
5882
 
5883
  *Returns:* $\sqrt{x^2+y^2+z^2}$.
5884
 
5885
  ### Linear interpolation <a id="c.math.lerp">[[c.math.lerp]]</a>
@@ -5908,11 +6265,11 @@ otherwise. For any `t1` and `t2`, the product of
5908
  ### Classification / comparison functions <a id="c.math.fpclass">[[c.math.fpclass]]</a>
5909
 
5910
  The classification / comparison functions behave the same as the C
5911
  macros with the corresponding names defined in the C standard library.
5912
 
5913
- See also: ISO C 7.12.3, 7.12.4
5914
 
5915
  ### Mathematical special functions <a id="sf.cmath">[[sf.cmath]]</a>
5916
 
5917
  #### General <a id="sf.cmath.general">[[sf.cmath.general]]</a>
5918
 
@@ -5940,14 +6297,12 @@ long double assoc_laguerrel(unsigned n, unsigned m, long double x);
5940
  ```
5941
 
5942
  *Effects:* These functions compute the associated Laguerre polynomials
5943
  of their respective arguments `n`, `m`, and `x`.
5944
 
5945
- *Returns:* $$\mathsf{L}_n^m(x) =
5946
- (-1)^m \frac{\mathsf{d} ^ m}{\mathsf{d}x ^ m} \, \mathsf{L}_{n+m}(x)
5947
- \text{ ,\quad for $x \ge 0$,}$$ where n is `n`, m is `m`, and x is
5948
- `x`.
5949
 
5950
  *Remarks:* The effect of calling each of these functions is
5951
  *implementation-defined* if `n >= 128` or if `m >= 128`.
5952
 
5953
  #### Associated Legendre functions <a id="sf.cmath.assoc.legendre">[[sf.cmath.assoc.legendre]]</a>
@@ -5959,14 +6314,12 @@ long double assoc_legendrel(unsigned l, unsigned m, long double x);
5959
  ```
5960
 
5961
  *Effects:* These functions compute the associated Legendre functions of
5962
  their respective arguments `l`, `m`, and `x`.
5963
 
5964
- *Returns:* $$\mathsf{P}_\ell^m(x) = (1 - x^2) ^ {m/2} \:
5965
- \frac{\mathsf{d} ^ m}{\mathsf{d}x ^ m} \, \mathsf{P}_\ell(x)
5966
- \text{ ,\quad for $|x| \le 1$,}$$ where l is `l`, m is `m`, and x is
5967
- `x`.
5968
 
5969
  *Remarks:* The effect of calling each of these functions is
5970
  *implementation-defined* if `l >= 128`.
5971
 
5972
  #### Beta function <a id="sf.cmath.beta">[[sf.cmath.beta]]</a>
@@ -5978,13 +6331,11 @@ long double betal(long double x, long double y);
5978
  ```
5979
 
5980
  *Effects:* These functions compute the beta function of their respective
5981
  arguments `x` and `y`.
5982
 
5983
- *Returns:*
5984
- $$\mathsf{B}(x, y) = \frac{\Gamma(x) \, \Gamma(y)}{\Gamma(x + y)}
5985
- \text{ ,\quad for $x > 0$,\, $y > 0$,}$$ where x is `x` and y is `y`.
5986
 
5987
  #### Complete elliptic integral of the first kind <a id="sf.cmath.comp.ellint.1">[[sf.cmath.comp.ellint.1]]</a>
5988
 
5989
  ``` cpp
5990
  floating-point-type comp_ellint_1(floating-point-type k);
@@ -5993,13 +6344,11 @@ long double comp_ellint_1l(long double k);
5993
  ```
5994
 
5995
  *Effects:* These functions compute the complete elliptic integral of the
5996
  first kind of their respective arguments `k`.
5997
 
5998
- *Returns:*
5999
- $$\mathsf{K}(k) = \mathsf{F}(k, \pi / 2) \text{ ,\quad for $|k| \le 1$,}$$
6000
- where k is `k`.
6001
 
6002
  See also [[sf.cmath.ellint.1]].
6003
 
6004
  #### Complete elliptic integral of the second kind <a id="sf.cmath.comp.ellint.2">[[sf.cmath.comp.ellint.2]]</a>
6005
 
@@ -6010,13 +6359,11 @@ long double comp_ellint_2l(long double k);
6010
  ```
6011
 
6012
  *Effects:* These functions compute the complete elliptic integral of the
6013
  second kind of their respective arguments `k`.
6014
 
6015
- *Returns:*
6016
- $$\mathsf{E}(k) = \mathsf{E}(k, \pi / 2) \text{ ,\quad for $|k| \le 1$,}$$
6017
- where k is `k`.
6018
 
6019
  See also [[sf.cmath.ellint.2]].
6020
 
6021
  #### Complete elliptic integral of the third kind <a id="sf.cmath.comp.ellint.3">[[sf.cmath.comp.ellint.3]]</a>
6022
 
@@ -6027,13 +6374,12 @@ long double comp_ellint_3l(long double k, long double nu);
6027
  ```
6028
 
6029
  *Effects:* These functions compute the complete elliptic integral of the
6030
  third kind of their respective arguments `k` and `nu`.
6031
 
6032
- *Returns:*
6033
- $$\mathsf{\Pi}(\nu, k) = \mathsf{\Pi}(\nu, k, \pi / 2) \text{ ,\quad for $|k| \le 1$,}$$
6034
- where k is `k` and $\nu$ is `nu`.
6035
 
6036
  See also [[sf.cmath.ellint.3]].
6037
 
6038
  #### Regular modified cylindrical Bessel functions <a id="sf.cmath.cyl.bessel.i">[[sf.cmath.cyl.bessel.i]]</a>
6039
 
@@ -6044,14 +6390,12 @@ long double cyl_bessel_il(long double nu, long double x);
6044
  ```
6045
 
6046
  *Effects:* These functions compute the regular modified cylindrical
6047
  Bessel functions of their respective arguments `nu` and `x`.
6048
 
6049
- *Returns:* $$\mathsf{I}_\nu(x) =
6050
- i^{-\nu} \mathsf{J}_\nu(ix) =
6051
- \sum_{k=0}^\infty \frac{(x/2)^{\nu+2k}}{k! \: \Gamma(\nu+k+1)}
6052
- \text{ ,\quad for $x \ge 0$,}$$ where $\nu$ is `nu` and x is `x`.
6053
 
6054
  *Remarks:* The effect of calling each of these functions is
6055
  *implementation-defined* if `nu >= 128`.
6056
 
6057
  See also [[sf.cmath.cyl.bessel.j]].
@@ -6065,13 +6409,12 @@ long double cyl_bessel_jl(long double nu, long double x);
6065
  ```
6066
 
6067
  *Effects:* These functions compute the cylindrical Bessel functions of
6068
  the first kind of their respective arguments `nu` and `x`.
6069
 
6070
- *Returns:* $$\mathsf{J}_\nu(x) =
6071
- \sum_{k=0}^\infty \frac{(-1)^k (x/2)^{\nu+2k}}{k! \: \Gamma(\nu+k+1)}
6072
- \text{ ,\quad for $x \ge 0$,}$$ where $\nu$ is `nu` and x is `x`.
6073
 
6074
  *Remarks:* The effect of calling each of these functions is
6075
  *implementation-defined* if `nu >= 128`.
6076
 
6077
  #### Irregular modified cylindrical Bessel functions <a id="sf.cmath.cyl.bessel.k">[[sf.cmath.cyl.bessel.k]]</a>
@@ -6083,32 +6426,12 @@ long double cyl_bessel_kl(long double nu, long double x);
6083
  ```
6084
 
6085
  *Effects:* These functions compute the irregular modified cylindrical
6086
  Bessel functions of their respective arguments `nu` and `x`.
6087
 
6088
- *Returns:* $$%
6089
- \mathsf{K}_\nu(x) =
6090
- (\pi/2)i^{\nu+1} ( \mathsf{J}_\nu(ix)
6091
- + i \mathsf{N}_\nu(ix)
6092
- )
6093
- =
6094
- \left\{
6095
- \begin{array}{cl}
6096
- \displaystyle
6097
- \frac{\pi}{2}
6098
- \frac{\mathsf{I}_{-\nu}(x) - \mathsf{I}_{\nu}(x)}
6099
- {\sin \nu\pi },
6100
- & \mbox{for $x \ge 0$ and non-integral $\nu$}
6101
- \\
6102
- \\
6103
- \displaystyle
6104
- \frac{\pi}{2}
6105
- \lim_{\mu \rightarrow \nu} \frac{\mathsf{I}_{-\mu}(x) - \mathsf{I}_{\mu}(x)}
6106
- {\sin \mu\pi },
6107
- & \mbox{for $x \ge 0$ and integral $\nu$}
6108
- \end{array}
6109
- \right.$$ where $\nu$ is `nu` and x is `x`.
6110
 
6111
  *Remarks:* The effect of calling each of these functions is
6112
  *implementation-defined* if `nu >= 128`.
6113
 
6114
  See also [[sf.cmath.cyl.bessel.i]], [[sf.cmath.cyl.bessel.j]],
@@ -6124,26 +6447,12 @@ long double cyl_neumannl(long double nu, long double x);
6124
 
6125
  *Effects:* These functions compute the cylindrical Neumann functions,
6126
  also known as the cylindrical Bessel functions of the second kind, of
6127
  their respective arguments `nu` and `x`.
6128
 
6129
- *Returns:* $$%
6130
- \mathsf{N}_\nu(x) =
6131
- \left\{
6132
- \begin{array}{cl}
6133
- \displaystyle
6134
- \frac{\mathsf{J}_\nu(x) \cos \nu\pi - \mathsf{J}_{-\nu}(x)}
6135
- {\sin \nu\pi },
6136
- & \mbox{for $x \ge 0$ and non-integral $\nu$}
6137
- \\
6138
- \\
6139
- \displaystyle
6140
- \lim_{\mu \rightarrow \nu} \frac{\mathsf{J}_\mu(x) \cos \mu\pi - \mathsf{J}_{-\mu}(x)}
6141
- {\sin \mu\pi },
6142
- & \mbox{for $x \ge 0$ and integral $\nu$}
6143
- \end{array}
6144
- \right.$$ where $\nu$ is `nu` and x is `x`.
6145
 
6146
  *Remarks:* The effect of calling each of these functions is
6147
  *implementation-defined* if `nu >= 128`.
6148
 
6149
  See also [[sf.cmath.cyl.bessel.j]].
@@ -6158,13 +6467,11 @@ long double ellint_1l(long double k, long double phi);
6158
 
6159
  *Effects:* These functions compute the incomplete elliptic integral of
6160
  the first kind of their respective arguments `k` and `phi` (`phi`
6161
  measured in radians).
6162
 
6163
- *Returns:* $$\mathsf{F}(k, \phi) =
6164
- \int_0^\phi \! \frac{\mathsf{d}\theta}{\sqrt{1 - k^2 \sin^2 \theta}}
6165
- \text{ ,\quad for $|k| \le 1$,}$$ where k is `k` and φ is `phi`.
6166
 
6167
  #### Incomplete elliptic integral of the second kind <a id="sf.cmath.ellint.2">[[sf.cmath.ellint.2]]</a>
6168
 
6169
  ``` cpp
6170
  floating-point-type ellint_2(floating-point-type k, floating-point-type phi);
@@ -6174,13 +6481,11 @@ long double ellint_2l(long double k, long double phi);
6174
 
6175
  *Effects:* These functions compute the incomplete elliptic integral of
6176
  the second kind of their respective arguments `k` and `phi` (`phi`
6177
  measured in radians).
6178
 
6179
- *Returns:*
6180
- $$\mathsf{E}(k, \phi) = \int_0^\phi \! \sqrt{1 - k^2 \sin^2 \theta} \, \mathsf{d}\theta
6181
- \text{ ,\quad for $|k| \le 1$,}$$ where k is `k` and φ is `phi`.
6182
 
6183
  #### Incomplete elliptic integral of the third kind <a id="sf.cmath.ellint.3">[[sf.cmath.ellint.3]]</a>
6184
 
6185
  ``` cpp
6186
  floating-point-type ellint_3(floating-point-type k, floating-point-type nu,
@@ -6191,13 +6496,12 @@ long double ellint_3l(long double k, long double nu, long double phi);
6191
 
6192
  *Effects:* These functions compute the incomplete elliptic integral of
6193
  the third kind of their respective arguments `k`, `nu`, and `phi` (`phi`
6194
  measured in radians).
6195
 
6196
- *Returns:* $$\mathsf{\Pi}(\nu, k, \phi) = \int_0^\phi \!
6197
- \frac{ \mathsf{d}\theta }{ (1 - \nu \, \sin^2 \theta) \sqrt{1 - k^2 \sin^2 \theta} } \text{ ,\quad for $|k| \le 1$,}$$
6198
- where $\nu$ is `nu`, k is `k`, and φ is `phi`.
6199
 
6200
  #### Exponential integral <a id="sf.cmath.expint">[[sf.cmath.expint]]</a>
6201
 
6202
  ``` cpp
6203
  floating-point-type expint(floating-point-type x);
@@ -6206,15 +6510,11 @@ long double expintl(long double x);
6206
  ```
6207
 
6208
  *Effects:* These functions compute the exponential integral of their
6209
  respective arguments `x`.
6210
 
6211
- *Returns:* $$%
6212
- \mathsf{Ei}(x) =
6213
- - \int_{-x}^\infty \frac{e^{-t}}
6214
- {t } \, \mathsf{d}t
6215
- \;$$ where x is `x`.
6216
 
6217
  #### Hermite polynomials <a id="sf.cmath.hermite">[[sf.cmath.hermite]]</a>
6218
 
6219
  ``` cpp
6220
  floating-point-type hermite(unsigned n, floating-point-type x);
@@ -6223,15 +6523,11 @@ long double hermitel(unsigned n, long double x);
6223
  ```
6224
 
6225
  *Effects:* These functions compute the Hermite polynomials of their
6226
  respective arguments `n` and `x`.
6227
 
6228
- *Returns:* $$%
6229
- \mathsf{H}_n(x) =
6230
- (-1)^n e^{x^2} \frac{ \mathsf{d} ^n}
6231
- { \mathsf{d}x^n} \, e^{-x^2}
6232
- \;$$ where n is `n` and x is `x`.
6233
 
6234
  *Remarks:* The effect of calling each of these functions is
6235
  *implementation-defined* if `n >= 128`.
6236
 
6237
  #### Laguerre polynomials <a id="sf.cmath.laguerre">[[sf.cmath.laguerre]]</a>
@@ -6243,13 +6539,11 @@ long double laguerrel(unsigned n, long double x);
6243
  ```
6244
 
6245
  *Effects:* These functions compute the Laguerre polynomials of their
6246
  respective arguments `n` and `x`.
6247
 
6248
- *Returns:* $$\mathsf{L}_n(x) =
6249
- \frac{e^x}{n!} \frac{\mathsf{d}^n}{\mathsf{d}x^n} \, (x^n e^{-x})
6250
- \text{ ,\quad for $x \ge 0$,}$$ where n is `n` and x is `x`.
6251
 
6252
  *Remarks:* The effect of calling each of these functions is
6253
  *implementation-defined* if `n >= 128`.
6254
 
6255
  #### Legendre polynomials <a id="sf.cmath.legendre">[[sf.cmath.legendre]]</a>
@@ -6261,14 +6555,11 @@ long double legendrel(unsigned l, long double x);
6261
  ```
6262
 
6263
  *Effects:* These functions compute the Legendre polynomials of their
6264
  respective arguments `l` and `x`.
6265
 
6266
- *Returns:* $$\mathsf{P}_\ell(x) =
6267
- \frac{1}{2^\ell \, \ell!}
6268
- \frac{\mathsf{d}^\ell}{\mathsf{d}x^\ell} \, (x^2 - 1) ^ \ell
6269
- \text{ ,\quad for $|x| \le 1$,}$$ where l is `l` and x is `x`.
6270
 
6271
  *Remarks:* The effect of calling each of these functions is
6272
  *implementation-defined* if `l >= 128`.
6273
 
6274
  #### Riemann zeta function <a id="sf.cmath.riemann.zeta">[[sf.cmath.riemann.zeta]]</a>
@@ -6280,32 +6571,11 @@ long double riemann_zetal(long double x);
6280
  ```
6281
 
6282
  *Effects:* These functions compute the Riemann zeta function of their
6283
  respective arguments `x`.
6284
 
6285
- *Returns:* $$%
6286
- \mathsf{\zeta}(x) =
6287
- \left\{
6288
- \begin{array}{cl}
6289
- \displaystyle
6290
- \sum_{k=1}^\infty k^{-x},
6291
- & \mbox{for $x > 1$}
6292
- \\
6293
- \\
6294
- \displaystyle
6295
- \frac{1}
6296
- {1 - 2^{1-x}}
6297
- \sum_{k=1}^\infty (-1)^{k-1} k^{-x},
6298
- & \mbox{for $0 \le x \le 1$}
6299
- \\
6300
- \\
6301
- \displaystyle
6302
- 2^x \pi^{x-1} \sin(\frac{\pi x}{2}) \, \Gamma(1-x) \, \zeta(1-x),
6303
- & \mbox{for $x < 0$}
6304
- \end{array}
6305
- \right.
6306
- \;$$ where x is `x`.
6307
 
6308
  #### Spherical Bessel functions of the first kind <a id="sf.cmath.sph.bessel">[[sf.cmath.sph.bessel]]</a>
6309
 
6310
  ``` cpp
6311
  floating-point-type sph_bessel(unsigned n, floating-point-type x);
@@ -6314,13 +6584,11 @@ long double sph_bessell(unsigned n, long double x);
6314
  ```
6315
 
6316
  *Effects:* These functions compute the spherical Bessel functions of the
6317
  first kind of their respective arguments `n` and `x`.
6318
 
6319
- *Returns:*
6320
- $$\mathsf{j}_n(x) = (\pi/2x)^{1\!/\!2} \mathsf{J}_{n + 1\!/\!2}(x) \text{ ,\quad for $x \ge 0$,}$$
6321
- where n is `n` and x is `x`.
6322
 
6323
  *Remarks:* The effect of calling each of these functions is
6324
  *implementation-defined* if `n >= 128`.
6325
 
6326
  See also [[sf.cmath.cyl.bessel.j]].
@@ -6335,16 +6603,12 @@ long double sph_legendrel(unsigned l, unsigned m, long double theta);
6335
 
6336
  *Effects:* These functions compute the spherical associated Legendre
6337
  functions of their respective arguments `l`, `m`, and `theta` (`theta`
6338
  measured in radians).
6339
 
6340
- *Returns:* $$\mathsf{Y}_\ell^m(\theta, 0)$$ where
6341
- $$\mathsf{Y}_\ell^m(\theta, \phi) =
6342
- (-1)^m \left[\frac{(2 \ell + 1)}{4 \pi} \frac{(\ell - m)!}{(\ell + m)!}\right]^{1/2}
6343
- \mathsf{P}_\ell^m (\cos\theta) e^{i m \phi}
6344
- \text{ ,\quad for $|m| \le \ell$,}$$ and l is `l`, m is `m`, and θ
6345
- is `theta`.
6346
 
6347
  *Remarks:* The effect of calling each of these functions is
6348
  *implementation-defined* if `l >= 128`.
6349
 
6350
  See also [[sf.cmath.assoc.legendre]].
@@ -6359,13 +6623,11 @@ long double sph_neumannl(unsigned n, long double x);
6359
 
6360
  *Effects:* These functions compute the spherical Neumann functions, also
6361
  known as the spherical Bessel functions of the second kind, of their
6362
  respective arguments `n` and `x`.
6363
 
6364
- *Returns:*
6365
- $$\mathsf{n}_n(x) = (\pi/2x)^{1\!/\!2} \mathsf{N}_{n + 1\!/\!2}(x)
6366
- \text{ ,\quad for $x \ge 0$,}$$ where n is `n` and x is `x`.
6367
 
6368
  *Remarks:* The effect of calling each of these functions is
6369
  *implementation-defined* if `n >= 128`.
6370
 
6371
  See also [[sf.cmath.cyl.neumann]].
@@ -6434,14 +6696,7350 @@ specialize a mathematical constant variable template provided that the
6434
  specialization depends on a program-defined type.
6435
 
6436
  A program that instantiates a primary template of a mathematical
6437
  constant variable template is ill-formed.
6438
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6439
  <!-- Link reference definitions -->
 
6440
  [bad.alloc]: support.md#bad.alloc
 
6441
  [basic.fundamental]: basic.md#basic.fundamental
 
6442
  [basic.stc.thread]: basic.md#basic.stc.thread
 
6443
  [c.math]: #c.math
6444
  [c.math.abs]: #c.math.abs
6445
  [c.math.fpclass]: #c.math.fpclass
6446
  [c.math.hypot3]: #c.math.hypot3
6447
  [c.math.lerp]: #c.math.lerp
@@ -6462,18 +14060,25 @@ constant variable template is ill-formed.
6462
  [complex.numbers]: #complex.numbers
6463
  [complex.numbers.general]: #complex.numbers.general
6464
  [complex.ops]: #complex.ops
6465
  [complex.syn]: #complex.syn
6466
  [complex.transcendentals]: #complex.transcendentals
 
6467
  [complex.value.ops]: #complex.value.ops
6468
  [cons.slice]: #cons.slice
 
6469
  [conv.prom]: expr.md#conv.prom
 
6470
  [cpp.pragma]: cpp.md#cpp.pragma
6471
  [cpp17.copyassignable]: #cpp17.copyassignable
6472
  [cpp17.copyconstructible]: #cpp17.copyconstructible
6473
  [cpp17.equalitycomparable]: #cpp17.equalitycomparable
6474
  [dcl.init]: dcl.md#dcl.init
 
 
 
 
6475
  [gslice.access]: #gslice.access
6476
  [gslice.array.assign]: #gslice.array.assign
6477
  [gslice.array.comp.assign]: #gslice.array.comp.assign
6478
  [gslice.array.fill]: #gslice.array.fill
6479
  [gslice.cons]: #gslice.cons
@@ -6486,20 +14091,98 @@ constant variable template is ill-formed.
6486
  [iostate.flags]: input.md#iostate.flags
6487
  [istream.formatted]: input.md#istream.formatted
6488
  [iterator.concept.contiguous]: iterators.md#iterator.concept.contiguous
6489
  [iterator.requirements.general]: iterators.md#iterator.requirements.general
6490
  [library.c]: library.md#library.c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6491
  [mask.array.assign]: #mask.array.assign
6492
  [mask.array.comp.assign]: #mask.array.comp.assign
6493
  [mask.array.fill]: #mask.array.fill
6494
  [math.constants]: #math.constants
 
 
 
6495
  [namespace.std]: library.md#namespace.std
6496
  [numarray]: #numarray
6497
  [numbers]: #numbers
6498
  [numbers.syn]: #numbers.syn
6499
  [numeric.requirements]: #numeric.requirements
6500
  [numerics]: #numerics
 
 
 
6501
  [numerics.general]: #numerics.general
6502
  [numerics.summary]: #numerics.summary
6503
  [output.iterators]: iterators.md#output.iterators
6504
  [over.match.general]: over.md#over.match.general
6505
  [rand]: #rand
@@ -6538,10 +14221,12 @@ constant variable template is ill-formed.
6538
  [rand.dist.uni.real]: #rand.dist.uni.real
6539
  [rand.eng]: #rand.eng
6540
  [rand.eng.general]: #rand.eng.general
6541
  [rand.eng.lcong]: #rand.eng.lcong
6542
  [rand.eng.mers]: #rand.eng.mers
 
 
6543
  [rand.eng.sub]: #rand.eng.sub
6544
  [rand.general]: #rand.general
6545
  [rand.predef]: #rand.predef
6546
  [rand.req]: #rand.req
6547
  [rand.req.adapt]: #rand.req.adapt
@@ -6577,15 +14262,61 @@ constant variable template is ill-formed.
6577
  [sf.cmath.legendre]: #sf.cmath.legendre
6578
  [sf.cmath.riemann.zeta]: #sf.cmath.riemann.zeta
6579
  [sf.cmath.sph.bessel]: #sf.cmath.sph.bessel
6580
  [sf.cmath.sph.legendre]: #sf.cmath.sph.legendre
6581
  [sf.cmath.sph.neumann]: #sf.cmath.sph.neumann
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6582
  [slice.access]: #slice.access
6583
  [slice.arr.assign]: #slice.arr.assign
6584
  [slice.arr.comp.assign]: #slice.arr.comp.assign
6585
  [slice.arr.fill]: #slice.arr.fill
6586
  [slice.ops]: #slice.ops
 
6587
  [strings]: strings.md#strings
6588
  [template.gslice.array]: #template.gslice.array
6589
  [template.gslice.array.overview]: #template.gslice.array.overview
6590
  [template.indirect.array]: #template.indirect.array
6591
  [template.indirect.array.overview]: #template.indirect.array.overview
@@ -6611,10 +14342,11 @@ constant variable template is ill-formed.
6611
  [valarray.special]: #valarray.special
6612
  [valarray.sub]: #valarray.sub
6613
  [valarray.syn]: #valarray.syn
6614
  [valarray.transcend]: #valarray.transcend
6615
  [valarray.unary]: #valarray.unary
 
6616
 
6617
  [^1]: In other words, value types. These include arithmetic types,
6618
  pointers, the library class `complex`, and instantiations of
6619
  `valarray` for value types.
6620
 
@@ -6631,11 +14363,11 @@ constant variable template is ill-formed.
6631
 
6632
  [^5]: If a device has n states whose respective probabilities are
6633
  P₀, …, Pₙ₋₁, the device entropy S is defined as
6634
  $S = - \sum_{i=0}^{n-1} P_i \cdot \log P_i$.
6635
 
6636
- [^6]: b is introduced to avoid any attempt to produce more bits of
6637
  randomness than can be held in `RealType`.
6638
 
6639
  [^7]: The distribution corresponding to this probability density
6640
  function is also known (with a possible change of variable) as the
6641
  Gumbel Type I, the log-Weibull, or the Fisher-Tippett Type I
 
19
  | [[complex.numbers]] | Complex numbers | `<complex>` |
20
  | [[rand]] | Random number generation | `<random>` |
21
  | [[numarray]] | Numeric arrays | `<valarray>` |
22
  | [[c.math]] | Mathematical functions for floating-point types | `<cmath>`, `<cstdlib>` |
23
  | [[numbers]] | Numbers | `<numbers>` |
24
+ | [[linalg]] | Linear algebra | `<linalg>` |
25
+ | [[simd]] | Data-parallel types | `<simd>` |
26
 
27
 
28
  ## Numeric type requirements <a id="numeric.requirements">[[numeric.requirements]]</a>
29
 
30
  The `complex` and `valarray` components are parameterized by the type of
 
67
  #define FE_DFL_ENV see below
68
 
69
  namespace std {
70
  // types
71
  using fenv_t = object type;
72
+ using fexcept_t = object type;
73
 
74
  // functions
75
  int feclearexcept(int except);
76
  int fegetexceptflag(fexcept_t* pflag, int except);
77
  int feraiseexcept(int except);
 
86
  int fesetenv(const fenv_t* penv);
87
  int feupdateenv(const fenv_t* penv);
88
  }
89
  ```
90
 
91
+ The contents and meaning of the header `<cfenv>` are a subset of the C
92
+ standard library header `<fenv.h>` and only the declarations shown in
93
+ the synopsis above are present.
94
 
95
  [*Note 1*: This document does not require an implementation to support
96
  the `FENV_ACCESS` pragma; it is *implementation-defined* [[cpp.pragma]]
97
  whether the pragma is supported. As a consequence, it is
98
  *implementation-defined* whether these functions can be used to test
 
125
  ### General <a id="complex.numbers.general">[[complex.numbers.general]]</a>
126
 
127
  The header `<complex>` defines a class template, and numerous functions
128
  for representing and manipulating complex numbers.
129
 
130
+ The effect of instantiating the primary template of `complex` for any
131
+ type that is not a cv-unqualified floating-point type
132
+ [[basic.fundamental]] is unspecified. Specializations of `complex` for
133
+ cv-unqualified floating-point types are trivially copyable literal types
134
  [[term.literal.type]].
135
 
136
  If the result of a function is not mathematically defined or not in the
137
  range of representable values for its type, the behavior is undefined.
138
 
 
145
  `z`.
146
 
147
  Moreover, if `a` is an expression of type cv `complex<T>*` and the
148
  expression `a[i]` is well-defined for an integer expression `i`, then:
149
 
150
+ - `reinterpret_cast<cv T*>(a)[2 * i]` designates the real part of
151
+ `a[i]`, and
152
+ - `reinterpret_cast<cv T*>(a)[2 * i + 1]` designates the imaginary part
153
+ of `a[i]`.
154
 
155
  ### Header `<complex>` synopsis <a id="complex.syn">[[complex.syn]]</a>
156
 
157
  ``` cpp
158
  namespace std {
 
190
 
191
  // [complex.value.ops], values
192
  template<class T> constexpr T real(const complex<T>&);
193
  template<class T> constexpr T imag(const complex<T>&);
194
 
195
+ template<class T> constexpr T abs(const complex<T>&);
196
+ template<class T> constexpr T arg(const complex<T>&);
197
  template<class T> constexpr T norm(const complex<T>&);
198
 
199
  template<class T> constexpr complex<T> conj(const complex<T>&);
200
+ template<class T> constexpr complex<T> proj(const complex<T>&);
201
+ template<class T> constexpr complex<T> polar(const T&, const T& = T());
202
 
203
  // [complex.transcendentals], transcendentals
204
+ template<class T> constexpr complex<T> acos(const complex<T>&);
205
+ template<class T> constexpr complex<T> asin(const complex<T>&);
206
+ template<class T> constexpr complex<T> atan(const complex<T>&);
207
 
208
+ template<class T> constexpr complex<T> acosh(const complex<T>&);
209
+ template<class T> constexpr complex<T> asinh(const complex<T>&);
210
+ template<class T> constexpr complex<T> atanh(const complex<T>&);
211
 
212
+ template<class T> constexpr complex<T> cos (const complex<T>&);
213
+ template<class T> constexpr complex<T> cosh (const complex<T>&);
214
+ template<class T> constexpr complex<T> exp (const complex<T>&);
215
+ template<class T> constexpr complex<T> log (const complex<T>&);
216
+ template<class T> constexpr complex<T> log10(const complex<T>&);
217
 
218
+ template<class T> constexpr complex<T> pow (const complex<T>&, const T&);
219
+ template<class T> constexpr complex<T> pow (const complex<T>&, const complex<T>&);
220
+ template<class T> constexpr complex<T> pow (const T&, const complex<T>&);
221
 
222
+ template<class T> constexpr complex<T> sin (const complex<T>&);
223
+ template<class T> constexpr complex<T> sinh (const complex<T>&);
224
+ template<class T> constexpr complex<T> sqrt (const complex<T>&);
225
+ template<class T> constexpr complex<T> tan (const complex<T>&);
226
+ template<class T> constexpr complex<T> tanh (const complex<T>&);
227
+
228
+ // [complex.tuple], tuple interface
229
+ template<class T> struct tuple_size;
230
+ template<size_t I, class T> struct tuple_element;
231
+ template<class T> struct tuple_size<complex<T>>;
232
+ template<size_t I, class T> struct tuple_element<I, complex<T>>;
233
+ template<size_t I, class T>
234
+ constexpr T& get(complex<T>&) noexcept;
235
+ template<size_t I, class T>
236
+ constexpr T&& get(complex<T>&&) noexcept;
237
+ template<size_t I, class T>
238
+ constexpr const T& get(const complex<T>&) noexcept;
239
+ template<size_t I, class T>
240
+ constexpr const T&& get(const complex<T>&&) noexcept;
241
 
242
  // [complex.literals], complex literals
243
  inline namespace literals {
244
  inline namespace complex_literals {
245
  constexpr complex<long double> operator""il(long double);
 
370
  *Effects:* Divides the scalar value `rhs` into the complex value `*this`
371
  and stores the result in `*this`.
372
 
373
  *Returns:* `*this`.
374
 
375
+ ``` cpp
376
+ template<class X> constexpr complex& operator=(const complex<X>& rhs);
377
+ ```
378
+
379
+ *Effects:* Assigns the value `rhs.real()` to the real part and the value
380
+ `rhs.imag()` to the imaginary part of the complex value `*this`.
381
+
382
+ *Returns:* `*this`.
383
+
384
  ``` cpp
385
  template<class X> constexpr complex& operator+=(const complex<X>& rhs);
386
  ```
387
 
388
  *Effects:* Adds the complex value `rhs` to the complex value `*this` and
 
529
  ```
530
 
531
  *Returns:* `x.imag()`.
532
 
533
  ``` cpp
534
+ template<class T> constexpr T abs(const complex<T>& x);
535
  ```
536
 
537
  *Returns:* The magnitude of `x`.
538
 
539
  ``` cpp
540
+ template<class T> constexpr T arg(const complex<T>& x);
541
  ```
542
 
543
  *Returns:* The phase angle of `x`, or `atan2(imag(x), real(x))`.
544
 
545
  ``` cpp
 
553
  ```
554
 
555
  *Returns:* The complex conjugate of `x`.
556
 
557
  ``` cpp
558
+ template<class T> constexpr complex<T> proj(const complex<T>& x);
559
  ```
560
 
561
  *Returns:* The projection of `x` onto the Riemann sphere.
562
 
563
  *Remarks:* Behaves the same as the C function `cproj`. See also: ISO C
564
  7.3.9.5
565
 
566
  ``` cpp
567
+ template<class T> constexpr complex<T> polar(const T& rho, const T& theta = T());
568
  ```
569
 
570
  *Preconditions:* `rho` is non-negative and non-NaN. `theta` is finite.
571
 
572
  *Returns:* The `complex` value corresponding to a complex number whose
573
  magnitude is `rho` and whose phase angle is `theta`.
574
 
575
  ### Transcendentals <a id="complex.transcendentals">[[complex.transcendentals]]</a>
576
 
577
  ``` cpp
578
+ template<class T> constexpr complex<T> acos(const complex<T>& x);
579
  ```
580
 
581
  *Returns:* The complex arc cosine of `x`.
582
 
583
  *Remarks:* Behaves the same as the C function `cacos`. See also: ISO C
584
  7.3.5.1
585
 
586
  ``` cpp
587
+ template<class T> constexpr complex<T> asin(const complex<T>& x);
588
  ```
589
 
590
  *Returns:* The complex arc sine of `x`.
591
 
592
  *Remarks:* Behaves the same as the C function `casin`. See also: ISO C
593
  7.3.5.2
594
 
595
  ``` cpp
596
+ template<class T> constexpr complex<T> atan(const complex<T>& x);
597
  ```
598
 
599
  *Returns:* The complex arc tangent of `x`.
600
 
601
  *Remarks:* Behaves the same as the C function `catan`. See also: ISO C
602
  7.3.5.3
603
 
604
  ``` cpp
605
+ template<class T> constexpr complex<T> acosh(const complex<T>& x);
606
  ```
607
 
608
  *Returns:* The complex arc hyperbolic cosine of `x`.
609
 
610
  *Remarks:* Behaves the same as the C function `cacosh`. See also: ISO C
611
  7.3.6.1
612
 
613
  ``` cpp
614
+ template<class T> constexpr complex<T> asinh(const complex<T>& x);
615
  ```
616
 
617
  *Returns:* The complex arc hyperbolic sine of `x`.
618
 
619
  *Remarks:* Behaves the same as the C function `casinh`. See also: ISO C
620
  7.3.6.2
621
 
622
  ``` cpp
623
+ template<class T> constexpr complex<T> atanh(const complex<T>& x);
624
  ```
625
 
626
  *Returns:* The complex arc hyperbolic tangent of `x`.
627
 
628
  *Remarks:* Behaves the same as the C function `catanh`. See also: ISO C
629
  7.3.6.3
630
 
631
  ``` cpp
632
+ template<class T> constexpr complex<T> cos(const complex<T>& x);
633
  ```
634
 
635
  *Returns:* The complex cosine of `x`.
636
 
637
  ``` cpp
638
+ template<class T> constexpr complex<T> cosh(const complex<T>& x);
639
  ```
640
 
641
  *Returns:* The complex hyperbolic cosine of `x`.
642
 
643
  ``` cpp
644
+ template<class T> constexpr complex<T> exp(const complex<T>& x);
645
  ```
646
 
647
  *Returns:* The complex base-e exponential of `x`.
648
 
649
  ``` cpp
650
+ template<class T> constexpr complex<T> log(const complex<T>& x);
651
  ```
652
 
653
  *Returns:* The complex natural (base-e) logarithm of `x`. For all `x`,
654
  `imag(log(x))` lies in the interval \[-π, π\].
655
 
 
657
  in C++ as they are for `clog` in C. — *end note*]
658
 
659
  *Remarks:* The branch cuts are along the negative real axis.
660
 
661
  ``` cpp
662
+ template<class T> constexpr complex<T> log10(const complex<T>& x);
663
  ```
664
 
665
  *Returns:* The complex common (base-10) logarithm of `x`, defined as
666
  `log(x) / log(10)`.
667
 
668
  *Remarks:* The branch cuts are along the negative real axis.
669
 
670
  ``` cpp
671
+ template<class T> constexpr complex<T> pow(const complex<T>& x, const complex<T>& y);
672
+ template<class T> constexpr complex<T> pow(const complex<T>& x, const T& y);
673
+ template<class T> constexpr complex<T> pow(const T& x, const complex<T>& y);
674
  ```
675
 
676
  *Returns:* The complex power of base `x` raised to the `y`ᵗʰ power,
677
  defined as `exp(y * log(x))`. The value returned for `pow(0, 0)` is
678
  *implementation-defined*.
679
 
680
  *Remarks:* The branch cuts are along the negative real axis.
681
 
682
  ``` cpp
683
+ template<class T> constexpr complex<T> sin(const complex<T>& x);
684
  ```
685
 
686
  *Returns:* The complex sine of `x`.
687
 
688
  ``` cpp
689
+ template<class T> constexpr complex<T> sinh(const complex<T>& x);
690
  ```
691
 
692
  *Returns:* The complex hyperbolic sine of `x`.
693
 
694
  ``` cpp
695
+ template<class T> constexpr complex<T> sqrt(const complex<T>& x);
696
  ```
697
 
698
  *Returns:* The complex square root of `x`, in the range of the right
699
  half-plane.
700
 
 
702
  in C++ as they are for `csqrt` in C. — *end note*]
703
 
704
  *Remarks:* The branch cuts are along the negative real axis.
705
 
706
  ``` cpp
707
+ template<class T> constexpr complex<T> tan(const complex<T>& x);
708
  ```
709
 
710
  *Returns:* The complex tangent of `x`.
711
 
712
  ``` cpp
713
+ template<class T> constexpr complex<T> tanh(const complex<T>& x);
714
  ```
715
 
716
  *Returns:* The complex hyperbolic tangent of `x`.
717
 
718
+ ### Tuple interface <a id="complex.tuple">[[complex.tuple]]</a>
719
+
720
+ ``` cpp
721
+ template<class T>
722
+ struct tuple_size<complex<T>> : integral_constant<size_t, 2> {};
723
+
724
+ template<size_t I, class T>
725
+ struct tuple_element<I, complex<T>> {
726
+ using type = T;
727
+ };
728
+ ```
729
+
730
+ *Mandates:* `I < 2` is `true`.
731
+
732
+ ``` cpp
733
+ template<size_t I, class T>
734
+ constexpr T& get(complex<T>& z) noexcept;
735
+ template<size_t I, class T>
736
+ constexpr T&& get(complex<T>&& z) noexcept;
737
+ template<size_t I, class T>
738
+ constexpr const T& get(const complex<T>& z) noexcept;
739
+ template<size_t I, class T>
740
+ constexpr const T&& get(const complex<T>&& z) noexcept;
741
+ ```
742
+
743
+ *Mandates:* `I < 2` is `true`.
744
+
745
+ *Returns:* A reference to the real part of `z` if `I == 0` is `true`,
746
+ otherwise a reference to the imaginary part of `z`.
747
+
748
  ### Additional overloads <a id="cmplx.over">[[cmplx.over]]</a>
749
 
750
+ The following function templates have additional constexpr overloads:
751
 
752
  ``` cpp
753
  arg norm
754
  conj proj
755
  imag real
756
  ```
757
 
758
+ The additional constexpr overloads are sufficient to ensure:
 
 
759
 
760
  - If the argument has a floating-point type `T`, then it is effectively
761
  cast to `complex<T>`.
762
  - Otherwise, if the argument has integer type, then it is effectively
763
  cast to `complex<double>`.
764
 
765
+ Function template `pow` has additional constexpr overloads sufficient to
766
+ ensure, for a call with one argument of type `complex<T1>` and the other
767
  argument of type `T2` or `complex<T2>`, both arguments are effectively
768
+ cast to `complex<common_type_t<T1, T3>>`, where `T3` is `double` if `T2`
769
+ is an integer type and `T2` otherwise. If `common_type_t<T1, T3>` is not
770
+ well-formed, then the program is ill-formed.
771
 
772
  ### Suffixes for complex number literals <a id="complex.literals">[[complex.literals]]</a>
773
 
774
  This subclause describes literal suffixes for constructing complex
775
  number literals. The suffixes `i`, `il`, and `if` create complex numbers
 
849
  #include <initializer_list> // see [initializer.list.syn]
850
 
851
  namespace std {
852
  // [rand.req.urng], uniform random bit generator requirements
853
  template<class G>
854
+ concept uniform_random_bit_generator = see below; // freestanding
855
 
856
  // [rand.eng.lcong], class template linear_congruential_engine
857
  template<class UIntType, UIntType a, UIntType c, UIntType m>
858
+ class linear_congruential_engine; // partially freestanding
859
 
860
  // [rand.eng.mers], class template mersenne_twister_engine
861
  template<class UIntType, size_t w, size_t n, size_t m, size_t r,
862
  UIntType a, size_t u, UIntType d, size_t s,
863
  UIntType b, size_t t,
864
  UIntType c, size_t l, UIntType f>
865
  class mersenne_twister_engine;
866
 
867
  // [rand.eng.sub], class template subtract_with_carry_engine
868
  template<class UIntType, size_t w, size_t s, size_t r>
869
+ class subtract_with_carry_engine; // partially freestanding
870
 
871
  // [rand.adapt.disc], class template discard_block_engine
872
  template<class Engine, size_t p, size_t r>
873
+ class discard_block_engine; // partially freestanding
874
 
875
  // [rand.adapt.ibits], class template independent_bits_engine
876
  template<class Engine, size_t w, class UIntType>
877
+ class independent_bits_engine; // partially freestanding
878
 
879
  // [rand.adapt.shuf], class template shuffle_order_engine
880
  template<class Engine, size_t k>
881
  class shuffle_order_engine;
882
 
883
+ // [rand.eng.philox], class template philox_engine
884
+ template<class UIntType, size_t w, size_t n, size_t r, UIntType... consts>
885
+ class philox_engine; // partially freestanding
886
+
887
  // [rand.predef], engines and engine adaptors with predefined parameters
888
+ using minstd_rand0 = see below; // freestanding
889
+ using minstd_rand = see below; // freestanding
890
+ using mt19937 = see below; // freestanding
891
+ using mt19937_64 = see below; // freestanding
892
+ using ranlux24_base = see below; // freestanding
893
+ using ranlux48_base = see below; // freestanding
894
+ using ranlux24 = see below; // freestanding
895
+ using ranlux48 = see below; // freestanding
896
  using knuth_b = see below;
897
+ using philox4x32 = see below; // freestanding
898
+ using philox4x64 = see below; // freestanding
899
 
900
  using default_random_engine = see below;
901
 
902
  // [rand.device], class random_device
903
  class random_device;
904
 
905
  // [rand.util.seedseq], class seed_seq
906
  class seed_seq;
907
 
908
  // [rand.util.canonical], function template generate_canonical
909
+ template<class RealType, size_t digits, class URBG>
910
  RealType generate_canonical(URBG& g);
911
 
912
+ namespace ranges {
913
+ // [alg.rand.generate], generate_random
914
+ template<class R, class G>
915
+ requires output_range<R, invoke_result_t<G&>> &&
916
+ uniform_random_bit_generator<remove_cvref_t<G>>
917
+ constexpr borrowed_iterator_t<R> generate_random(R&& r, G&& g);
918
+
919
+ template<class G, output_iterator<invoke_result_t<G&>> O, sentinel_for<O> S>
920
+ requires uniform_random_bit_generator<remove_cvref_t<G>>
921
+ constexpr O generate_random(O first, S last, G&& g);
922
+
923
+ template<class R, class G, class D>
924
+ requires output_range<R, invoke_result_t<D&, G&>> && invocable<D&, G&> &&
925
+ uniform_random_bit_generator<remove_cvref_t<G>> &&
926
+ is_arithmetic_v<invoke_result_t<D&, G&>>
927
+ constexpr borrowed_iterator_t<R> generate_random(R&& r, G&& g, D&& d);
928
+
929
+ template<class G, class D, output_iterator<invoke_result_t<D&, G&>> O, sentinel_for<O> S>
930
+ requires invocable<D&, G&> && uniform_random_bit_generator<remove_cvref_t<G>> &&
931
+ is_arithmetic_v<invoke_result_t<D&, G&>>
932
+ constexpr O generate_random(O first, S last, G&& g, D&& d);
933
+ }
934
+
935
  // [rand.dist.uni.int], class template uniform_int_distribution
936
  template<class IntType = int>
937
+ class uniform_int_distribution; // partially freestanding
938
 
939
  // [rand.dist.uni.real], class template uniform_real_distribution
940
  template<class RealType = double>
941
  class uniform_real_distribution;
942
 
 
1015
 
1016
  ### Requirements <a id="rand.req">[[rand.req]]</a>
1017
 
1018
  #### General requirements <a id="rand.req.genl">[[rand.req.genl]]</a>
1019
 
1020
+ Throughout [[rand]], the effect of instantiating a template:
 
1021
 
1022
  - that has a template type parameter named `Sseq` is undefined unless
1023
  the corresponding template argument is cv-unqualified and meets the
1024
  requirements of seed sequence [[rand.req.seedseq]].
1025
  - that has a template type parameter named `URBG` is undefined unless
 
1038
  - that has a template type parameter named `UIntType` is undefined
1039
  unless the corresponding template argument is cv-unqualified and is
1040
  one of `unsigned short`, `unsigned int`, `unsigned long`, or
1041
  `unsigned long long`.
1042
 
1043
+ Throughout [[rand]], phrases of the form “`x` is an iterator of a
1044
+ specific kind” shall be interpreted as equivalent to the more formal
1045
+ requirement that “`x` is a value of a type meeting the requirements of
1046
+ the specified iterator type”.
1047
 
1048
+ Throughout [[rand]], any constructor that can be called with a single
1049
+ argument and that meets a requirement specified in this subclause shall
1050
+ be declared `explicit`.
1051
 
1052
  #### Seed sequence requirements <a id="rand.req.seedseq">[[rand.req.seedseq]]</a>
1053
 
1054
  A *seed sequence* is an object that consumes a sequence of
1055
  integer-valued data and produces a requested number of unsigned integer
 
1060
  applications requiring large numbers of random number
1061
  engines. — *end note*]
1062
 
1063
  A class `S` meets the requirements of a seed sequence if the expressions
1064
  shown in [[rand.req.seedseq]] are valid and have the indicated
1065
+ semantics, and if `S` also meets all other requirements of
1066
+ [[rand.req.seedseq]]. In [[rand.req.seedseq]] and throughout this
1067
  subclause:
1068
 
1069
  - `T` is the type named by `S`’s associated `result_type`;
1070
  - `q` is a value of type `S` and `r` is a value of type `S` or
1071
  `const S`;
 
1132
 
1133
  A class `E` that meets the requirements of a uniform random bit
1134
  generator [[rand.req.urng]] also meets the requirements of a *random
1135
  number engine* if the expressions shown in [[rand.req.eng]] are valid
1136
  and have the indicated semantics, and if `E` also meets all other
1137
+ requirements of [[rand.req.eng]]. In [[rand.req.eng]] and throughout
1138
+ this subclause:
1139
 
1140
  - `T` is the type named by `E`’s associated `result_type`;
1141
  - `e` is a value of `E`, `v` is an lvalue of `E`, `x` and `y` are
1142
  (possibly const) values of `E`;
1143
  - `s` is a value of `T`;
 
1155
  `E` shall meet the *Cpp17CopyConstructible* (
1156
  [[cpp17.copyconstructible]]) and *Cpp17CopyAssignable* (
1157
  [[cpp17.copyassignable]]) requirements. These operations shall each be
1158
  of complexity no worse than 𝑂(\text{size of state}).
1159
 
1160
+ On hosted implementations, the following expressions are well-formed and
1161
+ have the specified semantics.
1162
+
1163
+ ``` cpp
1164
+ os << x
1165
+ ```
1166
+
1167
+ *Effects:* With `os.`*`fmtflags`* set to `ios_base::dec|ios_base::left`
1168
+ and the fill character set to the space character, writes to `os` the
1169
+ textual representation of `x`’s current state. In the output, adjacent
1170
+ numbers are separated by one or more space characters.
1171
+
1172
+ *Ensures:* The `os.`*`fmtflags`* and fill character are unchanged.
1173
+
1174
+ *Result:* reference to the type of `os`.
1175
+
1176
+ *Returns:* `os`.
1177
+
1178
+ *Complexity:* 𝑂(size of state)
1179
+
1180
+ ``` cpp
1181
+ is >> v
1182
+ ```
1183
+
1184
+ *Preconditions:* `is` provides a textual representation that was
1185
+ previously written using an output stream whose imbued locale was the
1186
+ same as that of `is`, and whose type’s template specialization arguments
1187
+ `charT` and `traits` were respectively the same as those of `is`.
1188
+
1189
+ *Effects:* With `is.`*`fmtflags`* set to `ios_base::dec`, sets `v`’s
1190
+ state as determined by reading its textual representation from `is`. If
1191
+ bad input is encountered, ensures that `v`’s state is unchanged by the
1192
+ operation and calls `is.setstate(ios_base::failbit)` (which may throw
1193
+ `ios_base::failure` [[iostate.flags]]). If a textual representation
1194
+ written via `os << x` was subsequently read via `is >> v`, then `x == v`
1195
+ provided that there have been no intervening invocations of `x` or of
1196
+ `v`.
1197
+
1198
+ *Ensures:* The `is.`*`fmtflags`* are unchanged.
1199
+
1200
+ *Result:* reference to the type of `is`.
1201
+
1202
+ *Returns:* `is`.
1203
+
1204
+ *Complexity:* 𝑂(size of state)
1205
+
1206
  #### Random number engine adaptor requirements <a id="rand.req.adapt">[[rand.req.adapt]]</a>
1207
 
1208
  A *random number engine adaptor* (commonly shortened to *adaptor*) `a`
1209
  of type `A` is a random number engine that takes values produced by some
1210
  other random number engine, and applies an algorithm to those values in
 
1289
  whole.
1290
 
1291
  A class `D` meets the requirements of a *random number distribution* if
1292
  the expressions shown in [[rand.req.dist]] are valid and have the
1293
  indicated semantics, and if `D` and its associated types also meet all
1294
+ other requirements of [[rand.req.dist]]. In [[rand.req.dist]] and
1295
+ throughout this subclause,
1296
 
1297
  - `T` is the type named by `D`’s associated `result_type`;
1298
  - `P` is the type named by `D`’s associated `param_type`;
1299
  - `d` is a value of `D`, and `x` and `y` are (possibly const) values of
1300
  `D`;
 
1326
  the same type using `is >> y`, repeated invocations of `y(g)` shall
1327
  produce the same sequence of numbers as would repeated invocations of
1328
  `x(g)`.
1329
 
1330
  It is unspecified whether `D::param_type` is declared as a (nested)
1331
+ `class` or via a `typedef`. In [[rand]], declarations of `D::param_type`
1332
+ are in the form of `typedef`s for convenience of exposition only.
 
1333
 
1334
  `P` shall meet the *Cpp17CopyConstructible* (
1335
  [[cpp17.copyconstructible]]), *Cpp17CopyAssignable* (
1336
  [[cpp17.copyassignable]]), and *Cpp17EqualityComparable* (
1337
  [[cpp17.equalitycomparable]]) requirements.
 
1348
 
1349
  ``` cpp
1350
  using distribution_type = D;
1351
  ```
1352
 
1353
+ On hosted implementations, the following expressions are well-formed and
1354
+ have the specified semantics.
1355
+
1356
+ ``` cpp
1357
+ os << x
1358
+ ```
1359
+
1360
+ *Effects:* Writes to `os` a textual representation for the parameters
1361
+ and the additional internal data of `x`.
1362
+
1363
+ *Ensures:* The `os.`*`fmtflags`* and fill character are unchanged.
1364
+
1365
+ *Result:* reference to the type of `os`.
1366
+
1367
+ *Returns:* `os`.
1368
+
1369
+ ``` cpp
1370
+ is >> d
1371
+ ```
1372
+
1373
+ *Preconditions:* `is` provides a textual representation that was
1374
+ previously written using an `os` whose imbued locale and whose type’s
1375
+ template specialization arguments `charT` and `traits` were the same as
1376
+ those of `is`.
1377
+
1378
+ *Effects:* Restores from `is` the parameters and additional internal
1379
+ data of the lvalue `d`. If bad input is encountered, ensures that `d` is
1380
+ unchanged by the operation and calls `is.setstate(ios_base::failbit)`
1381
+ (which may throw `ios_base::failure` [[iostate.flags]]).
1382
+
1383
+ *Ensures:* The `is.`*`fmtflags`* are unchanged.
1384
+
1385
+ *Result:* reference to the type of `is`.
1386
+
1387
+ *Returns:* `is`.
1388
+
1389
  ### Random number engine class templates <a id="rand.eng">[[rand.eng]]</a>
1390
 
1391
  #### General <a id="rand.eng.general">[[rand.eng.general]]</a>
1392
 
1393
  Each type instantiated from a class template specified in [[rand.eng]]
 
1409
  is additional semantic information. In particular, declarations for copy
1410
  constructors, for copy assignment operators, for streaming operators,
1411
  and for equality and inequality operators are not shown in the synopses.
1412
 
1413
  Each template specified in [[rand.eng]] requires one or more
1414
+ relationships, involving the value(s) of its constant template
1415
  parameter(s), to hold. A program instantiating any of these templates is
1416
  ill-formed if any such required relationship fails to hold.
1417
 
1418
  For every random number engine and for every random number engine
1419
  adaptor `X` defined in [[rand.eng]] and in [[rand.adapt]]:
 
1479
  void discard(unsigned long long z);
1480
 
1481
  // inserters and extractors
1482
  template<class charT, class traits>
1483
  friend basic_ostream<charT, traits>&
1484
+ operator<<(basic_ostream<charT, traits>& os, // hosted
1485
+ const linear_congruential_engine& x);
1486
  template<class charT, class traits>
1487
  friend basic_istream<charT, traits>&
1488
+ operator>>(basic_istream<charT, traits>& is, // hosted
1489
+ linear_congruential_engine& x);
1490
  };
1491
  }
1492
  ```
1493
 
1494
+ If the template parameter `m` is 0, the modulus m used throughout
1495
+ [[rand.eng.lcong]] is `numeric_limits<result_type>::max()` plus 1.
 
1496
 
1497
  [*Note 1*: m need not be representable as a value of type
1498
  `result_type`. — *end note*]
1499
 
1500
  If the template parameter `m` is not 0, the following relations shall
 
1598
  void discard(unsigned long long z);
1599
 
1600
  // inserters and extractors
1601
  template<class charT, class traits>
1602
  friend basic_ostream<charT, traits>&
1603
+ operator<<(basic_ostream<charT, traits>& os, // hosted
1604
+ const mersenne_twister_engine& x);
1605
  template<class charT, class traits>
1606
  friend basic_istream<charT, traits>&
1607
+ operator>>(basic_istream<charT, traits>& is, // hosted
1608
+ mersenne_twister_engine& x);
1609
  };
1610
  }
1611
  ```
1612
 
1613
  The following relations shall hold: `0 < m`, `m <= n`, `2u < w`,
 
1680
  static constexpr size_t word_size = w;
1681
  static constexpr size_t short_lag = s;
1682
  static constexpr size_t long_lag = r;
1683
  static constexpr result_type min() { return 0; }
1684
  static constexpr result_type max() { return m - 1; }
1685
+ static constexpr uint_least32_t default_seed = 19780503u;
1686
 
1687
  // constructors and seeding functions
1688
+ subtract_with_carry_engine() : subtract_with_carry_engine(0u) {}
1689
  explicit subtract_with_carry_engine(result_type value);
1690
  template<class Sseq> explicit subtract_with_carry_engine(Sseq& q);
1691
+ void seed(result_type value = 0u);
1692
  template<class Sseq> void seed(Sseq& q);
1693
 
1694
  // equality operators
1695
  friend bool operator==(const subtract_with_carry_engine& x,
1696
  const subtract_with_carry_engine& y);
 
1700
  void discard(unsigned long long z);
1701
 
1702
  // inserters and extractors
1703
  template<class charT, class traits>
1704
  friend basic_ostream<charT, traits>&
1705
+ operator<<(basic_ostream<charT, traits>& os, // hosted
1706
+ const subtract_with_carry_engine& x);
1707
  template<class charT, class traits>
1708
  friend basic_istream<charT, traits>&
1709
+ operator>>(basic_istream<charT, traits>& is, // hosted
1710
+ subtract_with_carry_engine& x);
1711
  };
1712
  }
1713
  ```
1714
 
1715
  The following relations shall hold: `0u < s`, `s < r`, `0 < w`, and
 
1727
 
1728
  To set the values Xₖ, first construct `e`, a
1729
  `linear_congruential_engine` object, as if by the following definition:
1730
 
1731
  ``` cpp
1732
+ linear_congruential_engine<uint_least32_t, 40014u, 0u, 2147483563u> e(
1733
+ value == 0u ? default_seed : static_cast<uint_least32_t>(value % 2147483563u));
1734
  ```
1735
 
1736
  Then, to set each Xₖ, obtain new values z₀, …, zₙ₋₁ from n = ⌈ w/32 ⌉
1737
  successive invocations of `e`. Set Xₖ to
1738
  $\left( \sum_{j=0}^{n-1} z_j \cdot 2^{32j}\right) \bmod m$.
 
1747
  r ⋅ k, invokes `q.generate(`a + 0`, `a + r ⋅ k`)` and then, iteratively
1748
  for i = -r, …, -1, sets Xᵢ to
1749
  $\left(\sum_{j=0}^{k-1}a_{k(i+r)+j} \cdot 2^{32j} \right) \bmod m$. If
1750
  X₋₁ is then 0, sets c to 1; otherwise sets c to 0.
1751
 
1752
+ #### Class template `philox_engine` <a id="rand.eng.philox">[[rand.eng.philox]]</a>
1753
+
1754
+ A `philox_engine` random number engine produces unsigned integer random
1755
+ numbers in the interval \[`0`, m), where m = 2ʷ and the template
1756
+ parameter w defines the range of the produced numbers. The state of a
1757
+ `philox_engine` object consists of a sequence X of n unsigned integer
1758
+ values of width w, a sequence K of n/2 values of `result_type`, a
1759
+ sequence Y of n values of `result_type`, and a scalar i, where
1760
+
1761
+ - X is the interpretation of the unsigned integer *counter* value
1762
+ $Z \cedef \sum_{j = 0}^{n - 1} X_j \cdot 2^{wj}$ of n ⋅ w bits,
1763
+ - K are keys, which are generated once from the seed (see constructors
1764
+ below) and remain constant unless the `seed` function [[rand.req.eng]]
1765
+ is invoked,
1766
+ - Y stores a batch of output values, and
1767
+ - i is an index for an element of the sequence Y.
1768
+
1769
+ The generation algorithm returns Yᵢ, the value stored in the iᵗʰ element
1770
+ of Y after applying the transition algorithm.
1771
+
1772
+ The state transition is performed as if by the following algorithm:
1773
+
1774
+ ``` cpp
1775
+ i = i + 1
1776
+ if (i == n) {
1777
+ Y = Philox(K, X) // see below
1778
+ Z = Z + 1
1779
+ i = 0
1780
+ }
1781
+ ```
1782
+
1783
+ The `Philox` function maps the length-n/2 sequence K and the length-n
1784
+ sequence X into a length-n output sequence Y. Philox applies an r-round
1785
+ substitution-permutation network to the values in X. A single round of
1786
+ the generation algorithm performs the following steps:
1787
+
1788
+ - The output sequence X' of the previous round (X in case of the first
1789
+ round) is permuted to obtain the intermediate state V:
1790
+ ``` cpp
1791
+ Vⱼ = X'_{fₙ(j)}
1792
+ ```
1793
+
1794
+ where j = 0, …, n - 1 and fₙ(j) is defined in [[rand.eng.philox.f]].
1795
+ **Table: Values for the word permutation $\bm{f}_{\bm{n}}\bm{(j)}$** <a id="rand.eng.philox.f">[rand.eng.philox.f]</a>
1796
+
1797
+ | | |
1798
+ | --------------------------------------------- | ---------------------------- |
1799
+ | *[spans 2 columns]* $\bm{f}_{\bm{n}}\bm{(j)}$ | *[spans 4 columns]* $\bm{j}$ |
1800
+ | \multicolumn{2}{|c|} | 0 | 1 | 2 | 3 |
1801
+ | $\bm{n} $ | 2 | 0 | 1 | \multicolumn{2}{c|} |
1802
+ | | 4 | 2 | 1 | 0 | 3 |
1803
+
1804
+
1805
+ \[*Note 1*: For n = 2 the sequence is not permuted. — *end note*]
1806
+ - The following computations are applied to the elements of the V
1807
+ sequence:
1808
+ ``` cpp
1809
+ X_2k + 0} = \mulhi(V_2k, Mₖ, w) \xor key^qₖ \xor V_2k + 1}
1810
+ X_2k + 1} = \mullo(V_2k, Mₖ, w)
1811
+ ```
1812
+
1813
+ where:
1814
+ - μllo(`a`, `b`, `w`) is the low half of the modular multiplication of
1815
+ `a` and `b`: $(\tcode{a} \cdot \tcode{b}) \mod 2^w$,
1816
+ - μlhi(`a`, `b`, `w`) is the high half of the modular multiplication
1817
+ of `a` and `b`: (⌊ (`a` ⋅ `b`) / 2ʷ ⌋),
1818
+ - k = 0, …, n/2 - 1 is the index in the sequences,
1819
+ - q = 0, …, r - 1 is the index of the round,
1820
+ - $\mathit{key}^q_k$ is the kᵗʰ round key for round q,
1821
+ $\mathit{key}^q_k \cedef (K_k + q \cdot C_k) \mod 2^w$,
1822
+ - Kₖ are the elements of the key sequence K,
1823
+ - Mₖ is `multipliers[k]`, and
1824
+ - Cₖ is `round_consts[k]`.
1825
+
1826
+ After r applications of the single-round function, `Philox` returns the
1827
+ sequence Y = X'.
1828
+
1829
+ ``` cpp
1830
+ namespace std {
1831
+ template<class UIntType, size_t w, size_t n, size_t r, UIntType... consts>
1832
+ class philox_engine {
1833
+ static constexpr size_t array-size = n / 2; // exposition only
1834
+ public:
1835
+ // types
1836
+ using result_type = UIntType;
1837
+
1838
+ // engine characteristics
1839
+ static constexpr size_t word_size = w;
1840
+ static constexpr size_t word_count = n;
1841
+ static constexpr size_t round_count = r;
1842
+ static constexpr array<result_type, array-size> multipliers;
1843
+ static constexpr array<result_type, array-size> round_consts;
1844
+ static constexpr result_type min() { return 0; }
1845
+ static constexpr result_type max() { return m - 1; }
1846
+ static constexpr result_type default_seed = 20111115u;
1847
+
1848
+ // constructors and seeding functions
1849
+ philox_engine() : philox_engine(default_seed) {}
1850
+ explicit philox_engine(result_type value);
1851
+ template<class Sseq> explicit philox_engine(Sseq& q);
1852
+ void seed(result_type value = default_seed);
1853
+ template<class Sseq> void seed(Sseq& q);
1854
+
1855
+ void set_counter(const array<result_type, n>& counter);
1856
+
1857
+ // equality operators
1858
+ friend bool operator==(const philox_engine& x, const philox_engine& y);
1859
+
1860
+ // generating functions
1861
+ result_type operator()();
1862
+ void discard(unsigned long long z);
1863
+
1864
+ // inserters and extractors
1865
+ template<class charT, class traits>
1866
+ friend basic_ostream<charT, traits>&
1867
+ operator<<(basic_ostream<charT, traits>& os, const philox_engine& x); // hosted
1868
+ template<class charT, class traits>
1869
+ friend basic_istream<charT, traits>&
1870
+ operator>>(basic_istream<charT, traits>& is, philox_engine& x); // hosted
1871
+ };
1872
+ }
1873
+ ```
1874
+
1875
+ *Mandates:*
1876
+
1877
+ - `sizeof...(consts) == n` is `true`, and
1878
+ - `n == 2 || n == 4` is `true`, and
1879
+ - `0 < r` is `true`, and
1880
+ - `0 < w && w <= numeric_limits<UIntType>::digits` is `true`.
1881
+
1882
+ The template parameter pack `consts` represents the Mₖ and Cₖ constants
1883
+ which are grouped as follows:
1884
+ $[ M_0, C_0, M_1, C_1, M_2, C_2, \dotsc, M_{n/2 - 1}, C_{n/2 - 1} ]$.
1885
+
1886
+ The textual representation consists of the values of
1887
+ $K_0, \dotsc, K_{n/2 - 1}, X_{0}, \dotsc, X_{n - 1}, i$, in that order.
1888
+
1889
+ [*Note 2*: The stream extraction operator can reconstruct Y from K and
1890
+ X, as needed. — *end note*]
1891
+
1892
+ ``` cpp
1893
+ explicit philox_engine(result_type value);
1894
+ ```
1895
+
1896
+ *Effects:* Sets the K₀ element of sequence K to
1897
+ $\texttt{value} \mod 2^w$. All elements of sequences X and K (except K₀)
1898
+ are set to `0`. The value of i is set to n - 1.
1899
+
1900
+ ``` cpp
1901
+ template<class Sseq> explicit philox_engine(Sseq& q);
1902
+ ```
1903
+
1904
+ *Effects:* With p = ⌈ w / 32 ⌉ and an array (or equivalent) `a` of
1905
+ length (n/2) ⋅ p, invokes `q.generate(a + 0, a + n / 2 * `p`)` and then
1906
+ iteratively for k = 0, …, n/2 - 1, sets Kₖ to
1907
+ $\left(\sum_{j = 0}^{p - 1} a_{k p + j} \cdot 2^{32j} \right) \mod 2^w$.
1908
+ All elements of sequence X are set to `0`. The value of i is set to
1909
+ n - 1.
1910
+
1911
+ ``` cpp
1912
+ void set_counter(const array<result_type, n>& c);
1913
+ ```
1914
+
1915
+ *Effects:* For j = 0, …, n - 1 sets Xⱼ to $C_{n - 1 - j} \mod 2^w$. The
1916
+ value of i is set to n - 1.
1917
+
1918
+ [*Note 1*: The counter is the value Z introduced at the beginning of
1919
+ this subclause. — *end note*]
1920
+
1921
  ### Random number engine adaptor class templates <a id="rand.adapt">[[rand.adapt]]</a>
1922
 
1923
+ #### General <a id="rand.adapt.general">[[rand.adapt.general]]</a>
1924
 
1925
+ Each type instantiated from a class template specified in [[rand.adapt]]
1926
+ meets the requirements of a random number engine adaptor
1927
+ [[rand.req.adapt]] type.
1928
 
1929
  Except where specified otherwise, the complexity of each function
1930
+ specified in [[rand.adapt]] is constant.
1931
 
1932
+ Except where specified otherwise, no function described in
1933
+ [[rand.adapt]] throws an exception.
1934
 
1935
+ Every function described in [[rand.adapt]] that has a function parameter
1936
+ `q` of type `Sseq&` for a template type parameter named `Sseq` that is
1937
+ different from type `seed_seq` throws what and when the invocation of
1938
+ `q.generate` throws.
1939
 
1940
+ Descriptions are provided in [[rand.adapt]] only for adaptor operations
1941
+ that are not described in subclause  [[rand.req.adapt]] or for
1942
+ operations where there is additional semantic information. In
1943
+ particular, declarations for copy constructors, for copy assignment
1944
+ operators, for streaming operators, and for equality and inequality
1945
+ operators are not shown in the synopses.
1946
 
1947
+ Each template specified in [[rand.adapt]] requires one or more
1948
+ relationships, involving the value(s) of its constant template
1949
  parameter(s), to hold. A program instantiating any of these templates is
1950
  ill-formed if any such required relationship fails to hold.
1951
 
1952
  #### Class template `discard_block_engine` <a id="rand.adapt.disc">[[rand.adapt.disc]]</a>
1953
 
 
1970
  namespace std {
1971
  template<class Engine, size_t p, size_t r>
1972
  class discard_block_engine {
1973
  public:
1974
  // types
1975
+ using result_type = Engine::result_type;
1976
 
1977
  // engine characteristics
1978
  static constexpr size_t block_size = p;
1979
  static constexpr size_t used_block = r;
1980
  static constexpr result_type min() { return Engine::min(); }
 
2001
  const Engine& base() const noexcept { return e; }
2002
 
2003
  // inserters and extractors
2004
  template<class charT, class traits>
2005
  friend basic_ostream<charT, traits>&
2006
+ operator<<(basic_ostream<charT, traits>& os, const discard_block_engine& x); // hosted
2007
  template<class charT, class traits>
2008
  friend basic_istream<charT, traits>&
2009
+ operator>>(basic_istream<charT, traits>& is, discard_block_engine& x); // hosted
2010
 
2011
  private:
2012
  Engine e; // exposition only
2013
  size_t n; // exposition only
2014
  };
 
2064
  S = 2^{w₀ + 1} \cdot S + u \bmod 2^{w₀ + 1};
2065
  }
2066
  ```
2067
 
2068
  ``` cpp
2069
+ namespace std {
2070
  template<class Engine, size_t w, class UIntType>
2071
  class independent_bits_engine {
2072
  public:
2073
  // types
2074
  using result_type = UIntType;
 
2098
  const Engine& base() const noexcept { return e; }
2099
 
2100
  // inserters and extractors
2101
  template<class charT, class traits>
2102
  friend basic_ostream<charT, traits>&
2103
+ operator<<(basic_ostream<charT, traits>& os, const independent_bits_engine& x); // hosted
2104
  template<class charT, class traits>
2105
  friend basic_istream<charT, traits>&
2106
+ operator>>(basic_istream<charT, traits>& is, independent_bits_engine& x); // hosted
2107
 
2108
  private:
2109
  Engine e; // exposition only
2110
  };
2111
+ }
2112
  ```
2113
 
2114
  The following relations shall hold: `0 < w` and
2115
  `w <= numeric_limits<result_type>::digits`.
2116
 
 
2142
  namespace std {
2143
  template<class Engine, size_t k>
2144
  class shuffle_order_engine {
2145
  public:
2146
  // types
2147
+ using result_type = Engine::result_type;
2148
 
2149
  // engine characteristics
2150
  static constexpr size_t table_size = k;
2151
  static constexpr result_type min() { return Engine::min(); }
2152
  static constexpr result_type max() { return Engine::max(); }
 
2293
  inexpert, and/or lightweight use. Because different implementations can
2294
  select different underlying engine types, code that uses this `typedef`
2295
  need not generate identical sequences across
2296
  implementations. — *end note*]
2297
 
2298
+ ``` cpp
2299
+ using philox4x32 =
2300
+ philox_engine<uint_fast32_t, 32, 4, 10,
2301
+ 0xCD9E8D57, 0x9E3779B9, 0xD2511F53, 0xBB67AE85>;
2302
+ ```
2303
+
2304
+ *Required behavior:* The 10000ᵗʰ consecutive invocation a
2305
+ default-constructed object of type `philox4x32` produces the value
2306
+ 1955073260.
2307
+
2308
+ ``` cpp
2309
+ using philox4x64 =
2310
+ philox_engine<uint_fast64_t, 64, 4, 10,
2311
+ 0xCA5A826395121157, 0x9E3779B97F4A7C15, 0xD2E7470EE14C6C93, 0xBB67AE8584CAA73B>;
2312
+ ```
2313
+
2314
+ *Required behavior:* The 10000ᵗʰ consecutive invocation a
2315
+ default-constructed object of type `philox4x64` produces the value
2316
+ 3409172418970261260.
2317
+
2318
  ### Class `random_device` <a id="rand.device">[[rand.device]]</a>
2319
 
2320
  A `random_device` uniform random bit generator produces nondeterministic
2321
  random numbers.
2322
 
 
2544
  *Throws:* What and when `OutputIterator` operations of `dest` throw.
2545
 
2546
  #### Function template `generate_canonical` <a id="rand.util.canonical">[[rand.util.canonical]]</a>
2547
 
2548
  ``` cpp
2549
+ template<class RealType, size_t digits, class URBG>
2550
  RealType generate_canonical(URBG& g);
2551
  ```
2552
 
2553
+ Let
 
 
 
2554
 
2555
+ - r be `numeric_limits<RealType>::radix`,
2556
+ - R be `g.max()` - `g.min()` + 1,
2557
+ - d be the smaller of `digits` and
2558
+ `numeric_limits<RealType>::digits`,[^6]
2559
+ - k be the smallest integer such that Rᵏ ≥ rᵈ, and
2560
+ - x be ⌊ Rᵏ / rᵈ ⌋.
2561
 
2562
+ An *attempt* is k invocations of `g()` to obtain values g₀, …, gₖ₋₁,
2563
+ respectively, and the calculation of a quantity S given by :
2564
+
2565
+ *Effects:* Attempts are made until S < xrᵈ.
2566
+
2567
+ [*Note 1*: When R is a power of r, precisely one attempt is
2568
+ made. — *end note*]
2569
+
2570
+ *Returns:* ⌊ S / x ⌋ / rᵈ.
2571
+
2572
+ [*Note 2*: The return value c satisfies 0 ≤ c < 1. — *end note*]
2573
 
2574
  *Throws:* What and when `g` throws.
2575
 
2576
+ *Complexity:* Exactly k invocations of `g` per attempt.
 
2577
 
2578
+ [*Note 3*: If the values gᵢ produced by `g` are uniformly distributed,
 
 
 
2579
  the instantiation’s results are distributed as uniformly as possible.
2580
  Obtaining a value in this way can be a useful step in the process of
2581
  transforming a value generated by a uniform random bit generator into a
2582
  value that can be delivered by a random number
2583
  distribution. — *end note*]
2584
 
2585
+ [*Note 4*: When R is a power of r, an implementation can avoid using an
2586
+ arithmetic type that is wider than the output when computing
2587
+ S. — *end note*]
2588
+
2589
  ### Random number distribution class templates <a id="rand.dist">[[rand.dist]]</a>
2590
 
2591
+ #### General <a id="rand.dist.general">[[rand.dist.general]]</a>
2592
 
2593
+ Each type instantiated from a class template specified in [[rand.dist]]
2594
+ meets the requirements of a random number distribution [[rand.req.dist]]
2595
+ type.
2596
 
2597
+ Descriptions are provided in [[rand.dist]] only for distribution
2598
+ operations that are not described in [[rand.req.dist]] or for operations
2599
+ where there is additional semantic information. In particular,
2600
+ declarations for copy constructors, for copy assignment operators, for
2601
+ streaming operators, and for equality and inequality operators are not
2602
+ shown in the synopses.
2603
 
2604
  The algorithms for producing each of the specified distributions are
2605
  *implementation-defined*.
2606
 
2607
  The value of each probability density function p(z) and of each discrete
 
2612
 
2613
  ##### Class template `uniform_int_distribution` <a id="rand.dist.uni.int">[[rand.dist.uni.int]]</a>
2614
 
2615
  A `uniform_int_distribution` random number distribution produces random
2616
  integers i, a ≤ i ≤ b, distributed according to the constant discrete
2617
+ probability function in .
2618
 
2619
  ``` cpp
2620
  namespace std {
2621
  template<class IntType = int>
2622
  class uniform_int_distribution {
 
2649
  result_type max() const;
2650
 
2651
  // inserters and extractors
2652
  template<class charT, class traits>
2653
  friend basic_ostream<charT, traits>&
2654
+ operator<<(basic_ostream<charT, traits>& os, // hosted
2655
+ const uniform_int_distribution& x);
2656
  template<class charT, class traits>
2657
  friend basic_istream<charT, traits>&
2658
+ operator>>(basic_istream<charT, traits>& is, // hosted
2659
+ uniform_int_distribution& x);
2660
  };
2661
  }
2662
  ```
2663
 
2664
  ``` cpp
 
2686
 
2687
  ##### Class template `uniform_real_distribution` <a id="rand.dist.uni.real">[[rand.dist.uni.real]]</a>
2688
 
2689
  A `uniform_real_distribution` random number distribution produces random
2690
  numbers x, a ≤ x < b, distributed according to the constant probability
2691
+ density function in .
2692
 
2693
  [*Note 1*: This implies that p(x | a,b) is undefined when
2694
  `a == b`. — *end note*]
2695
 
2696
  ``` cpp
 
2764
  #### Bernoulli distributions <a id="rand.dist.bern">[[rand.dist.bern]]</a>
2765
 
2766
  ##### Class `bernoulli_distribution` <a id="rand.dist.bern.bernoulli">[[rand.dist.bern.bernoulli]]</a>
2767
 
2768
  A `bernoulli_distribution` random number distribution produces `bool`
2769
+ values b distributed according to the discrete probability function in .
 
 
 
 
2770
 
2771
  ``` cpp
2772
  namespace std {
2773
  class bernoulli_distribution {
2774
  public:
 
2826
 
2827
  ##### Class template `binomial_distribution` <a id="rand.dist.bern.bin">[[rand.dist.bern.bin]]</a>
2828
 
2829
  A `binomial_distribution` random number distribution produces integer
2830
  values i ≥ 0 distributed according to the discrete probability function
2831
+ in .
2832
 
2833
  ``` cpp
2834
  namespace std {
2835
  template<class IntType = int>
2836
  class binomial_distribution {
 
2898
 
2899
  ##### Class template `geometric_distribution` <a id="rand.dist.bern.geo">[[rand.dist.bern.geo]]</a>
2900
 
2901
  A `geometric_distribution` random number distribution produces integer
2902
  values i ≥ 0 distributed according to the discrete probability function
2903
+ in .
2904
 
2905
  ``` cpp
2906
  namespace std {
2907
  template<class IntType = int>
2908
  class geometric_distribution {
 
2961
 
2962
  ##### Class template `negative_binomial_distribution` <a id="rand.dist.bern.negbin">[[rand.dist.bern.negbin]]</a>
2963
 
2964
  A `negative_binomial_distribution` random number distribution produces
2965
  random integers i ≥ 0 distributed according to the discrete probability
2966
+ function in .
 
2967
 
2968
  [*Note 1*: This implies that P(i | k,p) is undefined when
2969
  `p == 1`. — *end note*]
2970
 
2971
  ``` cpp
 
3039
 
3040
  ##### Class template `poisson_distribution` <a id="rand.dist.pois.poisson">[[rand.dist.pois.poisson]]</a>
3041
 
3042
  A `poisson_distribution` random number distribution produces integer
3043
  values i ≥ 0 distributed according to the discrete probability function
3044
+ in .
3045
+
3046
+ The distribution parameter μ is also known as this distribution’s
3047
+ *mean*.
3048
 
3049
  ``` cpp
3050
+ namespace std {
3051
  template<class IntType = int>
3052
+ class poisson_distribution {
 
3053
  public:
3054
  // types
3055
  using result_type = IntType;
3056
  using param_type = unspecified;
3057
 
 
3083
  operator<<(basic_ostream<charT, traits>& os, const poisson_distribution& x);
3084
  template<class charT, class traits>
3085
  friend basic_istream<charT, traits>&
3086
  operator>>(basic_istream<charT, traits>& is, poisson_distribution& x);
3087
  };
3088
+ }
3089
  ```
3090
 
3091
  ``` cpp
3092
  explicit poisson_distribution(double mean);
3093
  ```
 
3105
 
3106
  ##### Class template `exponential_distribution` <a id="rand.dist.pois.exp">[[rand.dist.pois.exp]]</a>
3107
 
3108
  An `exponential_distribution` random number distribution produces random
3109
  numbers x > 0 distributed according to the probability density function
3110
+ in .
3111
 
3112
  ``` cpp
3113
  namespace std {
3114
  template<class RealType = double>
3115
  class exponential_distribution {
 
3168
 
3169
  ##### Class template `gamma_distribution` <a id="rand.dist.pois.gamma">[[rand.dist.pois.gamma]]</a>
3170
 
3171
  A `gamma_distribution` random number distribution produces random
3172
  numbers x > 0 distributed according to the probability density function
3173
+ in .
 
 
3174
 
3175
  ``` cpp
3176
  namespace std {
3177
  template<class RealType = double>
3178
  class gamma_distribution {
 
3240
 
3241
  ##### Class template `weibull_distribution` <a id="rand.dist.pois.weibull">[[rand.dist.pois.weibull]]</a>
3242
 
3243
  A `weibull_distribution` random number distribution produces random
3244
  numbers x ≥ 0 distributed according to the probability density function
3245
+ in .
 
 
 
3246
 
3247
  ``` cpp
3248
  namespace std {
3249
  template<class RealType = double>
3250
  class weibull_distribution {
 
3312
 
3313
  ##### Class template `extreme_value_distribution` <a id="rand.dist.pois.extreme">[[rand.dist.pois.extreme]]</a>
3314
 
3315
  An `extreme_value_distribution` random number distribution produces
3316
  random numbers x distributed according to the probability density
3317
+ function in .[^7]
 
 
 
 
3318
 
3319
  ``` cpp
3320
  namespace std {
3321
  template<class RealType = double>
3322
  class extreme_value_distribution {
 
3386
  #### Normal distributions <a id="rand.dist.norm">[[rand.dist.norm]]</a>
3387
 
3388
  ##### Class template `normal_distribution` <a id="rand.dist.norm.normal">[[rand.dist.norm.normal]]</a>
3389
 
3390
  A `normal_distribution` random number distribution produces random
3391
+ numbers x distributed according to the probability density function in .
3392
+
3393
+ The distribution parameters μ and σ are also known as this
 
 
 
 
 
 
 
3394
  distribution’s *mean* and *standard deviation*.
3395
 
3396
  ``` cpp
3397
  namespace std {
3398
  template<class RealType = double>
 
3461
 
3462
  ##### Class template `lognormal_distribution` <a id="rand.dist.norm.lognormal">[[rand.dist.norm.lognormal]]</a>
3463
 
3464
  A `lognormal_distribution` random number distribution produces random
3465
  numbers x > 0 distributed according to the probability density function
3466
+ in .
 
 
3467
 
3468
  ``` cpp
3469
  namespace std {
3470
  template<class RealType = double>
3471
  class lognormal_distribution {
 
3533
 
3534
  ##### Class template `chi_squared_distribution` <a id="rand.dist.norm.chisq">[[rand.dist.norm.chisq]]</a>
3535
 
3536
  A `chi_squared_distribution` random number distribution produces random
3537
  numbers x > 0 distributed according to the probability density function
3538
+ in .
3539
 
3540
  ``` cpp
3541
  namespace std {
3542
  template<class RealType = double>
3543
  class chi_squared_distribution {
 
3595
  constructed.
3596
 
3597
  ##### Class template `cauchy_distribution` <a id="rand.dist.norm.cauchy">[[rand.dist.norm.cauchy]]</a>
3598
 
3599
  A `cauchy_distribution` random number distribution produces random
3600
+ numbers x distributed according to the probability density function in .
 
3601
 
3602
  ``` cpp
3603
  namespace std {
3604
  template<class RealType = double>
3605
  class cauchy_distribution {
 
3667
 
3668
  ##### Class template `fisher_f_distribution` <a id="rand.dist.norm.f">[[rand.dist.norm.f]]</a>
3669
 
3670
  A `fisher_f_distribution` random number distribution produces random
3671
  numbers x ≥ 0 distributed according to the probability density function
3672
+ in .
 
 
 
 
3673
 
3674
  ``` cpp
3675
  namespace std {
3676
  template<class RealType = double>
3677
  class fisher_f_distribution {
 
3738
  constructed.
3739
 
3740
  ##### Class template `student_t_distribution` <a id="rand.dist.norm.t">[[rand.dist.norm.t]]</a>
3741
 
3742
  A `student_t_distribution` random number distribution produces random
3743
+ numbers x distributed according to the probability density function in .
 
 
 
 
3744
 
3745
  ``` cpp
3746
  namespace std {
3747
  template<class RealType = double>
3748
  class student_t_distribution {
 
3803
 
3804
  ##### Class template `discrete_distribution` <a id="rand.dist.samp.discrete">[[rand.dist.samp.discrete]]</a>
3805
 
3806
  A `discrete_distribution` random number distribution produces random
3807
  integers i, 0 ≤ i < n, distributed according to the discrete probability
3808
+ function in .
3809
 
3810
  Unless specified otherwise, the distribution parameters are calculated
3811
  as: pₖ = {wₖ / S} for k = 0, …, n - 1, in which the values wₖ, commonly
3812
  known as the *weights* , shall be non-negative, non-NaN, and
3813
  non-infinity. Moreover, the following relation shall hold:
 
3882
  requirements [[input.iterators]]. If `firstW == lastW`, let n = 1 and
3883
  w₀ = 1. Otherwise, [`firstW`, `lastW`) forms a sequence w of length
3884
  n > 0.
3885
 
3886
  *Effects:* Constructs a `discrete_distribution` object with
3887
+ probabilities given by the .
3888
 
3889
  ``` cpp
3890
  discrete_distribution(initializer_list<double> wl);
3891
  ```
3892
 
 
3921
  ##### Class template `piecewise_constant_distribution` <a id="rand.dist.samp.pconst">[[rand.dist.samp.pconst]]</a>
3922
 
3923
  A `piecewise_constant_distribution` random number distribution produces
3924
  random numbers x, b₀ ≤ x < bₙ, uniformly distributed over each
3925
  subinterval [ bᵢ, bᵢ₊₁ ) according to the probability density function
3926
+ in .
 
3927
 
3928
  The n + 1 distribution parameters bᵢ, also known as this distribution’s
3929
  *interval boundaries* , shall satisfy the relation $b_i < b_{i + 1}$ for
3930
  i = 0, …, n - 1. Unless specified otherwise, the remaining n
3931
  distribution parameters are calculated as:
 
4067
 
4068
  ##### Class template `piecewise_linear_distribution` <a id="rand.dist.samp.plinear">[[rand.dist.samp.plinear]]</a>
4069
 
4070
  A `piecewise_linear_distribution` random number distribution produces
4071
  random numbers x, b₀ ≤ x < bₙ, distributed over each subinterval
4072
+ [bᵢ, bᵢ₊₁) according to the probability density function in .
 
 
 
 
4073
 
4074
  The n + 1 distribution parameters bᵢ, also known as this distribution’s
4075
  *interval boundaries* , shall satisfy the relation bᵢ < bᵢ₊₁ for
4076
  i = 0, …, n - 1. Unless specified otherwise, the remaining n + 1
4077
  distribution parameters are calculated as ρₖ = {wₖ / S} for k = 0, …, n,
 
4141
  template<class InputIteratorB, class InputIteratorW>
4142
  piecewise_linear_distribution(InputIteratorB firstB, InputIteratorB lastB,
4143
  InputIteratorW firstW);
4144
  ```
4145
 
4146
+ *Mandates:* Both of
4147
+
4148
+ - `is_convertible_v<iterator_traits<InputIteratorB>::value_type, double>`
4149
+ - `is_convertible_v<iterator_traits<InputIteratorW>::value_type, double>`
4150
+
4151
+ are `true`.
4152
 
4153
  *Preconditions:* `InputIteratorB` and `InputIteratorW` each meet the
4154
  *Cpp17InputIterator* requirements [[input.iterators]]. If
4155
  `firstB == lastB` or `++firstB == lastB`, let n = 1, ρ₀ = ρ₁ = 1,
4156
  b₀ = 0, and b₁ = 1. Otherwise, [`firstB`, `lastB`) forms a sequence b of
 
4230
  document [[rand]] are often preferable to `rand`, because `rand`’s
4231
  underlying algorithm is unspecified. Use of `rand` therefore continues
4232
  to be non-portable, with unpredictable and oft-questionable quality and
4233
  performance. — *end note*]
4234
 
4235
+ See also: ISO C 7.24.3
4236
 
4237
  ## Numeric arrays <a id="numarray">[[numarray]]</a>
4238
 
4239
  ### Header `<valarray>` synopsis <a id="valarray.syn">[[valarray.syn]]</a>
4240
 
 
4663
  ``` cpp
4664
  const T& operator[](size_t n) const;
4665
  T& operator[](size_t n);
4666
  ```
4667
 
4668
+ `n < size()` is `true`.
4669
 
4670
  *Returns:* A reference to the corresponding element of the array.
4671
 
4672
  [*Note 1*: The expression `(a[i] = q, a[i]) == q` evaluates to `true`
4673
  for any non-constant `valarray<T> a`, any `T q`, and for any `size_t i`
 
4921
  type `T`.
4922
 
4923
  *Effects:* Each of these operators applies the indicated operation to
4924
  each element of `*this` and `v`.
4925
 
4926
+ *Returns:* `*this`.
4927
 
4928
  *Remarks:* The appearance of an array on the left-hand side of a
4929
  compound assignment does not invalidate references or pointers to the
4930
  elements of the array.
4931
 
 
5756
  ## Mathematical functions for floating-point types <a id="c.math">[[c.math]]</a>
5757
 
5758
  ### Header `<cmath>` synopsis <a id="cmath.syn">[[cmath.syn]]</a>
5759
 
5760
  ``` cpp
 
 
 
 
 
5761
  #define HUGE_VAL see below
5762
  #define HUGE_VALF see below
5763
  #define HUGE_VALL see below
5764
  #define INFINITY see below
5765
  #define NAN see below
 
5777
  #define MATH_ERREXCEPT see below
5778
 
5779
  #define math_errhandling see below
5780
 
5781
  namespace std {
5782
+ using float_t = see below;
5783
+ using double_t = see below;
 
5784
 
5785
+ constexpr floating-point-type acos(floating-point-type x);
5786
+ constexpr float acosf(float x);
5787
+ constexpr long double acosl(long double x);
5788
 
5789
+ constexpr floating-point-type asin(floating-point-type x);
5790
+ constexpr float asinf(float x);
5791
+ constexpr long double asinl(long double x);
5792
 
5793
+ constexpr floating-point-type atan(floating-point-type x);
5794
+ constexpr float atanf(float x);
5795
+ constexpr long double atanl(long double x);
5796
 
5797
+ constexpr floating-point-type atan2(floating-point-type y, floating-point-type x);
5798
+ constexpr float atan2f(float y, float x);
5799
+ constexpr long double atan2l(long double y, long double x);
5800
 
5801
+ constexpr floating-point-type cos(floating-point-type x);
5802
+ constexpr float cosf(float x);
5803
+ constexpr long double cosl(long double x);
5804
 
5805
+ constexpr floating-point-type sin(floating-point-type x);
5806
+ constexpr float sinf(float x);
5807
+ constexpr long double sinl(long double x);
5808
 
5809
+ constexpr floating-point-type tan(floating-point-type x);
5810
+ constexpr float tanf(float x);
5811
+ constexpr long double tanl(long double x);
5812
 
5813
+ constexpr floating-point-type acosh(floating-point-type x);
5814
+ constexpr float acoshf(float x);
5815
+ constexpr long double acoshl(long double x);
5816
 
5817
+ constexpr floating-point-type asinh(floating-point-type x);
5818
+ constexpr float asinhf(float x);
5819
+ constexpr long double asinhl(long double x);
5820
 
5821
+ constexpr floating-point-type atanh(floating-point-type x);
5822
+ constexpr float atanhf(float x);
5823
+ constexpr long double atanhl(long double x);
5824
 
5825
+ constexpr floating-point-type cosh(floating-point-type x);
5826
+ constexpr float coshf(float x);
5827
+ constexpr long double coshl(long double x);
5828
 
5829
+ constexpr floating-point-type sinh(floating-point-type x);
5830
+ constexpr float sinhf(float x);
5831
+ constexpr long double sinhl(long double x);
5832
 
5833
+ constexpr floating-point-type tanh(floating-point-type x);
5834
+ constexpr float tanhf(float x);
5835
+ constexpr long double tanhl(long double x);
5836
 
5837
+ constexpr floating-point-type exp(floating-point-type x);
5838
+ constexpr float expf(float x);
5839
+ constexpr long double expl(long double x);
5840
 
5841
+ constexpr floating-point-type exp2(floating-point-type x);
5842
+ constexpr float exp2f(float x);
5843
+ constexpr long double exp2l(long double x);
5844
+
5845
+ constexpr floating-point-type expm1(floating-point-type x);
5846
+ constexpr float expm1f(float x);
5847
+ constexpr long double expm1l(long double x);
5848
 
5849
  constexpr floating-point-type frexp(floating-point-type value, int* exp);
5850
  constexpr float frexpf(float value, int* exp);
5851
  constexpr long double frexpl(long double value, int* exp);
5852
 
 
5856
 
5857
  constexpr floating-point-type ldexp(floating-point-type x, int exp);
5858
  constexpr float ldexpf(float x, int exp);
5859
  constexpr long double ldexpl(long double x, int exp);
5860
 
5861
+ constexpr floating-point-type log(floating-point-type x);
5862
+ constexpr float logf(float x);
5863
+ constexpr long double logl(long double x);
5864
 
5865
+ constexpr floating-point-type log10(floating-point-type x);
5866
+ constexpr float log10f(float x);
5867
+ constexpr long double log10l(long double x);
5868
 
5869
+ constexpr floating-point-type log1p(floating-point-type x);
5870
+ constexpr float log1pf(float x);
5871
+ constexpr long double log1pl(long double x);
5872
 
5873
+ constexpr floating-point-type log2(floating-point-type x);
5874
+ constexpr float log2f(float x);
5875
+ constexpr long double log2l(long double x);
5876
 
5877
  constexpr floating-point-type logb(floating-point-type x);
5878
  constexpr float logbf(float x);
5879
  constexpr long double logbl(long double x);
5880
 
 
5888
 
5889
  constexpr floating-point-type scalbln(floating-point-type x, long int n);
5890
  constexpr float scalblnf(float x, long int n);
5891
  constexpr long double scalblnl(long double x, long int n);
5892
 
5893
+ constexpr floating-point-type cbrt(floating-point-type x);
5894
+ constexpr float cbrtf(float x);
5895
+ constexpr long double cbrtl(long double x);
5896
 
5897
  // [c.math.abs], absolute values
5898
+ constexpr int abs(int j); // freestanding
5899
+ constexpr long int abs(long int j); // freestanding
5900
+ constexpr long long int abs(long long int j); // freestanding
5901
+ constexpr floating-point-type abs(floating-point-type j); // freestanding-deleted
5902
 
5903
  constexpr floating-point-type fabs(floating-point-type x);
5904
  constexpr float fabsf(float x);
5905
  constexpr long double fabsl(long double x);
5906
 
5907
+ constexpr floating-point-type hypot(floating-point-type x, floating-point-type y);
5908
+ constexpr float hypotf(float x, float y);
5909
+ constexpr long double hypotl(long double x, long double y);
5910
 
5911
  // [c.math.hypot3], three-dimensional hypotenuse
5912
+ constexpr floating-point-type hypot(floating-point-type x, floating-point-type y,
5913
  floating-point-type z);
5914
 
5915
+ constexpr floating-point-type pow(floating-point-type x, floating-point-type y);
5916
+ constexpr float powf(float x, float y);
5917
+ constexpr long double powl(long double x, long double y);
5918
 
5919
+ constexpr floating-point-type sqrt(floating-point-type x);
5920
+ constexpr float sqrtf(float x);
5921
+ constexpr long double sqrtl(long double x);
5922
 
5923
+ constexpr floating-point-type erf(floating-point-type x);
5924
+ constexpr float erff(float x);
5925
+ constexpr long double erfl(long double x);
5926
 
5927
+ constexpr floating-point-type erfc(floating-point-type x);
5928
+ constexpr float erfcf(float x);
5929
+ constexpr long double erfcl(long double x);
5930
 
5931
+ constexpr floating-point-type lgamma(floating-point-type x);
5932
+ constexpr float lgammaf(float x);
5933
+ constexpr long double lgammal(long double x);
5934
 
5935
+ constexpr floating-point-type tgamma(floating-point-type x);
5936
+ constexpr float tgammaf(float x);
5937
+ constexpr long double tgammal(long double x);
5938
 
5939
  constexpr floating-point-type ceil(floating-point-type x);
5940
  constexpr float ceilf(float x);
5941
  constexpr long double ceill(long double x);
5942
 
 
6002
 
6003
  constexpr floating-point-type nexttoward(floating-point-type x, long double y);
6004
  constexpr float nexttowardf(float x, long double y);
6005
  constexpr long double nexttowardl(long double x, long double y);
6006
 
6007
+ constexpr floating-point-type nextup(floating-point-type x);
6008
+ constexpr float nextupf(float x);
6009
+ constexpr long double nextupl(long double x);
6010
+
6011
+ constexpr floating-point-type nextdown(floating-point-type x);
6012
+ constexpr float nextdownf(float x);
6013
+ constexpr long double nextdownl(long double x);
6014
+
6015
  constexpr floating-point-type fdim(floating-point-type x, floating-point-type y);
6016
  constexpr float fdimf(float x, float y);
6017
  constexpr long double fdiml(long double x, long double y);
6018
 
6019
  constexpr floating-point-type fmax(floating-point-type x, floating-point-type y);
 
6022
 
6023
  constexpr floating-point-type fmin(floating-point-type x, floating-point-type y);
6024
  constexpr float fminf(float x, float y);
6025
  constexpr long double fminl(long double x, long double y);
6026
 
6027
+ constexpr floating-point-type fmaximum(floating-point-type x, floating-point-type y);
6028
+ constexpr floating-point-type fmaximum_num(floating-point-type x, floating-point-type y);
6029
+ constexpr floating-point-type fminimum(floating-point-type x, floating-point-type y);
6030
+ constexpr floating-point-type fminimum_num(floating-point-type x, floating-point-type y);
6031
+
6032
  constexpr floating-point-type fma(floating-point-type x, floating-point-type y,
6033
  floating-point-type z);
6034
  constexpr float fmaf(float x, float y, float z);
6035
  constexpr long double fmal(long double x, long double y, long double z);
6036
 
 
6162
  float sph_neumannf(unsigned n, float x);
6163
  long double sph_neumannl(unsigned n, long double x);
6164
  }
6165
  ```
6166
 
6167
+ The contents and meaning of the header `<cmath>` are a subset of the C
6168
+ standard library header `<math.h>` and only the declarations shown in
6169
+ the synopsis above are present, with the addition of a three-dimensional
6170
+ hypotenuse function [[c.math.hypot3]], a linear interpolation function
6171
+ [[c.math.lerp]], and the mathematical special functions described in
6172
+ [[sf.cmath]].
6173
 
6174
  [*Note 1*: Several functions have additional overloads in this
6175
  document, but they have the same behavior as in the C standard library
6176
  [[library.c]]. — *end note*]
6177
 
6178
  For each function with at least one parameter of type
6179
+ `floating-point-type`, the implementation provides an overload for each
6180
  cv-unqualified floating-point type [[basic.fundamental]] where all uses
6181
+ of `floating-point-type` in the function signature are replaced with
6182
  that floating-point type.
6183
 
6184
  For each function with at least one parameter of type
6185
+ `floating-point-type` other than `abs`, the implementation also provides
6186
  additional overloads sufficient to ensure that, if every argument
6187
+ corresponding to a `floating-point-type` parameter has arithmetic type,
6188
  then every such argument is effectively cast to the floating-point type
6189
  with the greatest floating-point conversion rank and greatest
6190
  floating-point conversion subrank among the types of all such arguments,
6191
  where arguments of integer type are considered to have the same
6192
  floating-point conversion rank as `double`. If no such floating-point
6193
  type with the greatest rank and subrank exists, then overload resolution
6194
  does not result in a usable candidate [[over.match.general]] from the
6195
  overloads provided by the implementation.
6196
 
6197
  An invocation of `nexttoward` is ill-formed if the argument
6198
+ corresponding to the `floating-point-type` parameter has extended
6199
  floating-point type.
6200
 
6201
  See also: ISO C 7.12
6202
 
6203
  ### Absolute values <a id="c.math.abs">[[c.math.abs]]</a>
 
6217
 
6218
  *Remarks:* If `abs` is called with an argument of type `X` for which
6219
  `is_unsigned_v<X>` is `true` and if `X` cannot be converted to `int` by
6220
  integral promotion [[conv.prom]], the program is ill-formed.
6221
 
6222
+ [*Note 1*: Allowing arguments that can be promoted to `int` provides
6223
  compatibility with C. — *end note*]
6224
 
6225
  ``` cpp
6226
  constexpr floating-point-type abs(floating-point-type x);
6227
  ```
6228
 
6229
  *Returns:* The absolute value of `x`.
6230
 
6231
+ See also: ISO C 7.12.8.3, 7.24.7.1
6232
 
6233
  ### Three-dimensional hypotenuse <a id="c.math.hypot3">[[c.math.hypot3]]</a>
6234
 
6235
  ``` cpp
6236
+ constexpr floating-point-type hypot(floating-point-type x, floating-point-type y,
6237
+ floating-point-type z);
6238
  ```
6239
 
6240
  *Returns:* $\sqrt{x^2+y^2+z^2}$.
6241
 
6242
  ### Linear interpolation <a id="c.math.lerp">[[c.math.lerp]]</a>
 
6265
  ### Classification / comparison functions <a id="c.math.fpclass">[[c.math.fpclass]]</a>
6266
 
6267
  The classification / comparison functions behave the same as the C
6268
  macros with the corresponding names defined in the C standard library.
6269
 
6270
+ See also: ISO C 7.12.4, 7.12.18
6271
 
6272
  ### Mathematical special functions <a id="sf.cmath">[[sf.cmath]]</a>
6273
 
6274
  #### General <a id="sf.cmath.general">[[sf.cmath.general]]</a>
6275
 
 
6297
  ```
6298
 
6299
  *Effects:* These functions compute the associated Laguerre polynomials
6300
  of their respective arguments `n`, `m`, and `x`.
6301
 
6302
+ *Returns:* Lₙᵐ(x), where Lₙᵐ is given by , Lₙ₊ₘ is given by , n is `n`,
6303
+ m is `m`, and x is `x`.
 
 
6304
 
6305
  *Remarks:* The effect of calling each of these functions is
6306
  *implementation-defined* if `n >= 128` or if `m >= 128`.
6307
 
6308
  #### Associated Legendre functions <a id="sf.cmath.assoc.legendre">[[sf.cmath.assoc.legendre]]</a>
 
6314
  ```
6315
 
6316
  *Effects:* These functions compute the associated Legendre functions of
6317
  their respective arguments `l`, `m`, and `x`.
6318
 
6319
+ *Returns:* P_ℓ^m(x), where P_ℓ^m is given by , P_ℓ is given by , ℓ is
6320
+ `l`, m is `m`, and x is `x`.
 
 
6321
 
6322
  *Remarks:* The effect of calling each of these functions is
6323
  *implementation-defined* if `l >= 128`.
6324
 
6325
  #### Beta function <a id="sf.cmath.beta">[[sf.cmath.beta]]</a>
 
6331
  ```
6332
 
6333
  *Effects:* These functions compute the beta function of their respective
6334
  arguments `x` and `y`.
6335
 
6336
+ *Returns:* B(x, y), where B is given by , x is `x` and y is `y`.
 
 
6337
 
6338
  #### Complete elliptic integral of the first kind <a id="sf.cmath.comp.ellint.1">[[sf.cmath.comp.ellint.1]]</a>
6339
 
6340
  ``` cpp
6341
  floating-point-type comp_ellint_1(floating-point-type k);
 
6344
  ```
6345
 
6346
  *Effects:* These functions compute the complete elliptic integral of the
6347
  first kind of their respective arguments `k`.
6348
 
6349
+ *Returns:* K(k), where K is given by and k is `k`.
 
 
6350
 
6351
  See also [[sf.cmath.ellint.1]].
6352
 
6353
  #### Complete elliptic integral of the second kind <a id="sf.cmath.comp.ellint.2">[[sf.cmath.comp.ellint.2]]</a>
6354
 
 
6359
  ```
6360
 
6361
  *Effects:* These functions compute the complete elliptic integral of the
6362
  second kind of their respective arguments `k`.
6363
 
6364
+ *Returns:* E(k), where E is given by and k is `k`.
 
 
6365
 
6366
  See also [[sf.cmath.ellint.2]].
6367
 
6368
  #### Complete elliptic integral of the third kind <a id="sf.cmath.comp.ellint.3">[[sf.cmath.comp.ellint.3]]</a>
6369
 
 
6374
  ```
6375
 
6376
  *Effects:* These functions compute the complete elliptic integral of the
6377
  third kind of their respective arguments `k` and `nu`.
6378
 
6379
+ *Returns:* $\mathsf{\Pi}(\nu, k)$, where $\mathsf{\Pi}$ is given by , k
6380
+ is `k`, and $\nu$ is `nu`.
 
6381
 
6382
  See also [[sf.cmath.ellint.3]].
6383
 
6384
  #### Regular modified cylindrical Bessel functions <a id="sf.cmath.cyl.bessel.i">[[sf.cmath.cyl.bessel.i]]</a>
6385
 
 
6390
  ```
6391
 
6392
  *Effects:* These functions compute the regular modified cylindrical
6393
  Bessel functions of their respective arguments `nu` and `x`.
6394
 
6395
+ *Returns:* $\mathsf{I}_\nu(x)$, where $\mathsf{I}_\nu$ is given by ,
6396
+ $\nu$ is `nu`, and x is `x`.
 
 
6397
 
6398
  *Remarks:* The effect of calling each of these functions is
6399
  *implementation-defined* if `nu >= 128`.
6400
 
6401
  See also [[sf.cmath.cyl.bessel.j]].
 
6409
  ```
6410
 
6411
  *Effects:* These functions compute the cylindrical Bessel functions of
6412
  the first kind of their respective arguments `nu` and `x`.
6413
 
6414
+ *Returns:* $\mathsf{J}_\nu(x)$, where $\mathsf{J}_\nu$ is given by ,
6415
+ $\nu$ is `nu`, and x is `x`.
 
6416
 
6417
  *Remarks:* The effect of calling each of these functions is
6418
  *implementation-defined* if `nu >= 128`.
6419
 
6420
  #### Irregular modified cylindrical Bessel functions <a id="sf.cmath.cyl.bessel.k">[[sf.cmath.cyl.bessel.k]]</a>
 
6426
  ```
6427
 
6428
  *Effects:* These functions compute the irregular modified cylindrical
6429
  Bessel functions of their respective arguments `nu` and `x`.
6430
 
6431
+ *Returns:* $\mathsf{K}_\nu(x)$, where $\mathsf{K}_\nu$ is given by ,
6432
+ $\nu$ is `nu`, and x is `x`.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6433
 
6434
  *Remarks:* The effect of calling each of these functions is
6435
  *implementation-defined* if `nu >= 128`.
6436
 
6437
  See also [[sf.cmath.cyl.bessel.i]], [[sf.cmath.cyl.bessel.j]],
 
6447
 
6448
  *Effects:* These functions compute the cylindrical Neumann functions,
6449
  also known as the cylindrical Bessel functions of the second kind, of
6450
  their respective arguments `nu` and `x`.
6451
 
6452
+ *Returns:* $\mathsf{N}_\nu(x)$, where $\mathsf{N}_\nu$ is given by ,
6453
+ $\nu$ is `nu`, and x is `x`.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6454
 
6455
  *Remarks:* The effect of calling each of these functions is
6456
  *implementation-defined* if `nu >= 128`.
6457
 
6458
  See also [[sf.cmath.cyl.bessel.j]].
 
6467
 
6468
  *Effects:* These functions compute the incomplete elliptic integral of
6469
  the first kind of their respective arguments `k` and `phi` (`phi`
6470
  measured in radians).
6471
 
6472
+ *Returns:* F(k, φ), where F is given by , k is `k`, and φ is `phi`.
 
 
6473
 
6474
  #### Incomplete elliptic integral of the second kind <a id="sf.cmath.ellint.2">[[sf.cmath.ellint.2]]</a>
6475
 
6476
  ``` cpp
6477
  floating-point-type ellint_2(floating-point-type k, floating-point-type phi);
 
6481
 
6482
  *Effects:* These functions compute the incomplete elliptic integral of
6483
  the second kind of their respective arguments `k` and `phi` (`phi`
6484
  measured in radians).
6485
 
6486
+ *Returns:* E(k, φ), where E is given by , k is `k`, and φ is `phi`.
 
 
6487
 
6488
  #### Incomplete elliptic integral of the third kind <a id="sf.cmath.ellint.3">[[sf.cmath.ellint.3]]</a>
6489
 
6490
  ``` cpp
6491
  floating-point-type ellint_3(floating-point-type k, floating-point-type nu,
 
6496
 
6497
  *Effects:* These functions compute the incomplete elliptic integral of
6498
  the third kind of their respective arguments `k`, `nu`, and `phi` (`phi`
6499
  measured in radians).
6500
 
6501
+ *Returns:* $\mathsf{\Pi}(\nu, k, \phi)$, where $\mathsf{\Pi}$ is given
6502
+ by , $\nu$ is `nu`, k is `k`, and φ is `phi`.
 
6503
 
6504
  #### Exponential integral <a id="sf.cmath.expint">[[sf.cmath.expint]]</a>
6505
 
6506
  ``` cpp
6507
  floating-point-type expint(floating-point-type x);
 
6510
  ```
6511
 
6512
  *Effects:* These functions compute the exponential integral of their
6513
  respective arguments `x`.
6514
 
6515
+ *Returns:* Ei(x), where Ei is given by and x is `x`.
 
 
 
 
6516
 
6517
  #### Hermite polynomials <a id="sf.cmath.hermite">[[sf.cmath.hermite]]</a>
6518
 
6519
  ``` cpp
6520
  floating-point-type hermite(unsigned n, floating-point-type x);
 
6523
  ```
6524
 
6525
  *Effects:* These functions compute the Hermite polynomials of their
6526
  respective arguments `n` and `x`.
6527
 
6528
+ *Returns:* Hₙ(x), where Hₙ is given by , n is `n`, and x is `x`.
 
 
 
 
6529
 
6530
  *Remarks:* The effect of calling each of these functions is
6531
  *implementation-defined* if `n >= 128`.
6532
 
6533
  #### Laguerre polynomials <a id="sf.cmath.laguerre">[[sf.cmath.laguerre]]</a>
 
6539
  ```
6540
 
6541
  *Effects:* These functions compute the Laguerre polynomials of their
6542
  respective arguments `n` and `x`.
6543
 
6544
+ *Returns:* L(x), where Lₙ is given by , n is `n`, and x is `x`.
 
 
6545
 
6546
  *Remarks:* The effect of calling each of these functions is
6547
  *implementation-defined* if `n >= 128`.
6548
 
6549
  #### Legendre polynomials <a id="sf.cmath.legendre">[[sf.cmath.legendre]]</a>
 
6555
  ```
6556
 
6557
  *Effects:* These functions compute the Legendre polynomials of their
6558
  respective arguments `l` and `x`.
6559
 
6560
+ *Returns:* P_ℓ(x), where P_ℓ is given by , l is `l`, and x is `x`.
 
 
 
6561
 
6562
  *Remarks:* The effect of calling each of these functions is
6563
  *implementation-defined* if `l >= 128`.
6564
 
6565
  #### Riemann zeta function <a id="sf.cmath.riemann.zeta">[[sf.cmath.riemann.zeta]]</a>
 
6571
  ```
6572
 
6573
  *Effects:* These functions compute the Riemann zeta function of their
6574
  respective arguments `x`.
6575
 
6576
+ *Returns:* ζ(x), where ζ is given by and x is `x`.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6577
 
6578
  #### Spherical Bessel functions of the first kind <a id="sf.cmath.sph.bessel">[[sf.cmath.sph.bessel]]</a>
6579
 
6580
  ``` cpp
6581
  floating-point-type sph_bessel(unsigned n, floating-point-type x);
 
6584
  ```
6585
 
6586
  *Effects:* These functions compute the spherical Bessel functions of the
6587
  first kind of their respective arguments `n` and `x`.
6588
 
6589
+ *Returns:* jₙ(x), where jₙ is given by , n is `n`, and x is `x`.
 
 
6590
 
6591
  *Remarks:* The effect of calling each of these functions is
6592
  *implementation-defined* if `n >= 128`.
6593
 
6594
  See also [[sf.cmath.cyl.bessel.j]].
 
6603
 
6604
  *Effects:* These functions compute the spherical associated Legendre
6605
  functions of their respective arguments `l`, `m`, and `theta` (`theta`
6606
  measured in radians).
6607
 
6608
+ *Returns:* Y_ℓ^m(θ, 0), where Y_ℓ^m is given by , l is `l`, m is `m`,
6609
+ and θ is `theta`.
 
 
 
 
6610
 
6611
  *Remarks:* The effect of calling each of these functions is
6612
  *implementation-defined* if `l >= 128`.
6613
 
6614
  See also [[sf.cmath.assoc.legendre]].
 
6623
 
6624
  *Effects:* These functions compute the spherical Neumann functions, also
6625
  known as the spherical Bessel functions of the second kind, of their
6626
  respective arguments `n` and `x`.
6627
 
6628
+ *Returns:* nₙ(x), where nₙ is given by , n is `n`, and x is `x`.
 
 
6629
 
6630
  *Remarks:* The effect of calling each of these functions is
6631
  *implementation-defined* if `n >= 128`.
6632
 
6633
  See also [[sf.cmath.cyl.neumann]].
 
6696
  specialization depends on a program-defined type.
6697
 
6698
  A program that instantiates a primary template of a mathematical
6699
  constant variable template is ill-formed.
6700
 
6701
+ ## Basic linear algebra algorithms <a id="linalg">[[linalg]]</a>
6702
+
6703
+ ### Overview <a id="linalg.overview">[[linalg.overview]]</a>
6704
+
6705
+ Subclause [[linalg]] defines basic linear algebra algorithms. The
6706
+ algorithms that access the elements of arrays view those elements
6707
+ through `mdspan` [[views.multidim]].
6708
+
6709
+ ### Header `<linalg>` synopsis <a id="linalg.syn">[[linalg.syn]]</a>
6710
+
6711
+ ``` cpp
6712
+ namespace std::linalg {
6713
+ // [linalg.tags.order], storage order tags
6714
+ struct column_major_t;
6715
+ inline constexpr column_major_t column_major;
6716
+ struct row_major_t;
6717
+ inline constexpr row_major_t row_major;
6718
+
6719
+ // [linalg.tags.triangle], triangle tags
6720
+ struct upper_triangle_t;
6721
+ inline constexpr upper_triangle_t upper_triangle;
6722
+ struct lower_triangle_t;
6723
+ inline constexpr lower_triangle_t lower_triangle;
6724
+
6725
+ // [linalg.tags.diagonal], diagonal tags
6726
+ struct implicit_unit_diagonal_t;
6727
+ inline constexpr implicit_unit_diagonal_t implicit_unit_diagonal;
6728
+ struct explicit_diagonal_t;
6729
+ inline constexpr explicit_diagonal_t explicit_diagonal;
6730
+
6731
+ // [linalg.layout.packed], class template layout_blas_packed
6732
+ template<class Triangle, class StorageOrder>
6733
+ class layout_blas_packed;
6734
+
6735
+ // [linalg.helpers], exposition-only helpers
6736
+
6737
+ // [linalg.helpers.concepts], linear algebra argument concepts
6738
+ template<class T>
6739
+ constexpr bool is-mdspan = see below; // exposition only
6740
+
6741
+ template<class T>
6742
+ concept in-vector = see below; // exposition only
6743
+
6744
+ template<class T>
6745
+ concept out-vector = see below; // exposition only
6746
+
6747
+ template<class T>
6748
+ concept inout-vector = see below; // exposition only
6749
+
6750
+ template<class T>
6751
+ concept in-matrix = see below; // exposition only
6752
+
6753
+ template<class T>
6754
+ concept out-matrix = see below; // exposition only
6755
+
6756
+ template<class T>
6757
+ concept inout-matrix = see below; // exposition only
6758
+
6759
+ template<class T>
6760
+ concept possibly-packed-inout-matrix = see below; // exposition only
6761
+
6762
+ template<class T>
6763
+ concept in-object = see below; // exposition only
6764
+
6765
+ template<class T>
6766
+ concept out-object = see below; // exposition only
6767
+
6768
+ template<class T>
6769
+ concept inout-object = see below; // exposition only
6770
+
6771
+ // [linalg.scaled], scaled in-place transformation
6772
+
6773
+ // [linalg.scaled.scaledaccessor], class template scaled_accessor
6774
+ template<class ScalingFactor, class NestedAccessor>
6775
+ class scaled_accessor;
6776
+
6777
+ // [linalg.scaled.scaled], function template scaled
6778
+ template<class ScalingFactor,
6779
+ class ElementType, class Extents, class Layout, class Accessor>
6780
+ constexpr auto scaled(ScalingFactor alpha, mdspan<ElementType, Extents, Layout, Accessor> x);
6781
+
6782
+ // [linalg.conj], conjugated in-place transformation
6783
+
6784
+ // [linalg.conj.conjugatedaccessor], class template conjugated_accessor
6785
+ template<class NestedAccessor>
6786
+ class conjugated_accessor;
6787
+
6788
+ // [linalg.conj.conjugated], function template conjugated
6789
+ template<class ElementType, class Extents, class Layout, class Accessor>
6790
+ constexpr auto conjugated(mdspan<ElementType, Extents, Layout, Accessor> a);
6791
+
6792
+ // [linalg.transp], transpose in-place transformation
6793
+
6794
+ // [linalg.transp.layout.transpose], class template layout_transpose
6795
+ template<class Layout>
6796
+ class layout_transpose;
6797
+
6798
+ // [linalg.transp.transposed], function template transposed
6799
+ template<class ElementType, class Extents, class Layout, class Accessor>
6800
+ constexpr auto transposed(mdspan<ElementType, Extents, Layout, Accessor> a);
6801
+
6802
+ // [linalg.conjtransposed], conjugated transpose in-place transformation
6803
+ template<class ElementType, class Extents, class Layout, class Accessor>
6804
+ constexpr auto conjugate_transposed(mdspan<ElementType, Extents, Layout, Accessor> a);
6805
+
6806
+ // [linalg.algs.blas1], BLAS 1 algorithms
6807
+
6808
+ // [linalg.algs.blas1.givens], Givens rotations
6809
+
6810
+ // [linalg.algs.blas1.givens.lartg], compute Givens rotation
6811
+
6812
+ template<class Real>
6813
+ struct setup_givens_rotation_result {
6814
+ Real c;
6815
+ Real s;
6816
+ Real r;
6817
+ };
6818
+ template<class Real>
6819
+ struct setup_givens_rotation_result<complex<Real>> {
6820
+ Real c;
6821
+ complex<Real> s;
6822
+ complex<Real> r;
6823
+ };
6824
+
6825
+ template<class Real>
6826
+ setup_givens_rotation_result<Real> setup_givens_rotation(Real a, Real b) noexcept;
6827
+
6828
+ template<class Real>
6829
+ setup_givens_rotation_result<complex<Real>>
6830
+ setup_givens_rotation(complex<Real> a, complex<Real> b) noexcept;
6831
+
6832
+ // [linalg.algs.blas1.givens.rot], apply computed Givens rotation
6833
+ template<inout-vector InOutVec1, inout-vector InOutVec2, class Real>
6834
+ void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, Real s);
6835
+ template<class ExecutionPolicy, inout-vector InOutVec1, inout-vector InOutVec2, class Real>
6836
+ void apply_givens_rotation(ExecutionPolicy&& exec,
6837
+ InOutVec1 x, InOutVec2 y, Real c, Real s);
6838
+ template<inout-vector InOutVec1, inout-vector InOutVec2, class Real>
6839
+ void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, complex<Real> s);
6840
+ template<class ExecutionPolicy, inout-vector InOutVec1, inout-vector InOutVec2, class Real>
6841
+ void apply_givens_rotation(ExecutionPolicy&& exec,
6842
+ InOutVec1 x, InOutVec2 y, Real c, complex<Real> s);
6843
+
6844
+ // [linalg.algs.blas1.swap], swap elements
6845
+ template<inout-object InOutObj1, inout-object InOutObj2>
6846
+ void swap_elements(InOutObj1 x, InOutObj2 y);
6847
+ template<class ExecutionPolicy, inout-object InOutObj1, inout-object InOutObj2>
6848
+ void swap_elements(ExecutionPolicy&& exec, InOutObj1 x, InOutObj2 y);
6849
+
6850
+ // [linalg.algs.blas1.scal], multiply elements by scalar
6851
+ template<class Scalar, inout-object InOutObj>
6852
+ void scale(Scalar alpha, InOutObj x);
6853
+ template<class ExecutionPolicy, class Scalar, inout-object InOutObj>
6854
+ void scale(ExecutionPolicy&& exec, Scalar alpha, InOutObj x);
6855
+
6856
+ // [linalg.algs.blas1.copy], copy elements
6857
+ template<in-object InObj, out-object OutObj>
6858
+ void copy(InObj x, OutObj y);
6859
+ template<class ExecutionPolicy, in-object InObj, out-object OutObj>
6860
+ void copy(ExecutionPolicy&& exec, InObj x, OutObj y);
6861
+
6862
+ // [linalg.algs.blas1.add], add elementwise
6863
+ template<in-object InObj1, in-object InObj2, out-object OutObj>
6864
+ void add(InObj1 x, InObj2 y, OutObj z);
6865
+ template<class ExecutionPolicy, in-object InObj1, in-object InObj2, out-object OutObj>
6866
+ void add(ExecutionPolicy&& exec, InObj1 x, InObj2 y, OutObj z);
6867
+
6868
+ // [linalg.algs.blas1.dot], dot product of two vectors
6869
+ template<in-vector InVec1, in-vector InVec2, class Scalar>
6870
+ Scalar dot(InVec1 v1, InVec2 v2, Scalar init);
6871
+ template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2, class Scalar>
6872
+ Scalar dot(ExecutionPolicy&& exec, InVec1 v1, InVec2 v2, Scalar init);
6873
+ template<in-vector InVec1, in-vector InVec2>
6874
+ auto dot(InVec1 v1, InVec2 v2);
6875
+ template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2>
6876
+ auto dot(ExecutionPolicy&& exec, InVec1 v1, InVec2 v2);
6877
+
6878
+ template<in-vector InVec1, in-vector InVec2, class Scalar>
6879
+ Scalar dotc(InVec1 v1, InVec2 v2, Scalar init);
6880
+ template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2, class Scalar>
6881
+ Scalar dotc(ExecutionPolicy&& exec, InVec1 v1, InVec2 v2, Scalar init);
6882
+ template<in-vector InVec1, in-vector InVec2>
6883
+ auto dotc(InVec1 v1, InVec2 v2);
6884
+ template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2>
6885
+ auto dotc(ExecutionPolicy&& exec, InVec1 v1, InVec2 v2);
6886
+
6887
+ // [linalg.algs.blas1.ssq], scaled sum of squares of a vector's elements
6888
+ template<class Scalar>
6889
+ struct sum_of_squares_result {
6890
+ Scalar scaling_factor;
6891
+ Scalar scaled_sum_of_squares;
6892
+ };
6893
+ template<in-vector InVec, class Scalar>
6894
+ sum_of_squares_result<Scalar>
6895
+ vector_sum_of_squares(InVec v, sum_of_squares_result<Scalar> init);
6896
+ template<class ExecutionPolicy, in-vector InVec, class Scalar>
6897
+ sum_of_squares_result<Scalar>
6898
+ vector_sum_of_squares(ExecutionPolicy&& exec,
6899
+ InVec v, sum_of_squares_result<Scalar> init);
6900
+
6901
+ // [linalg.algs.blas1.nrm2], Euclidean norm of a vector
6902
+ template<in-vector InVec, class Scalar>
6903
+ Scalar vector_two_norm(InVec v, Scalar init);
6904
+ template<class ExecutionPolicy, in-vector InVec, class Scalar>
6905
+ Scalar vector_two_norm(ExecutionPolicy&& exec, InVec v, Scalar init);
6906
+ template<in-vector InVec>
6907
+ auto vector_two_norm(InVec v);
6908
+ template<class ExecutionPolicy, in-vector InVec>
6909
+ auto vector_two_norm(ExecutionPolicy&& exec, InVec v);
6910
+
6911
+ // [linalg.algs.blas1.asum], sum of absolute values of vector elements
6912
+ template<in-vector InVec, class Scalar>
6913
+ Scalar vector_abs_sum(InVec v, Scalar init);
6914
+ template<class ExecutionPolicy, in-vector InVec, class Scalar>
6915
+ Scalar vector_abs_sum(ExecutionPolicy&& exec, InVec v, Scalar init);
6916
+ template<in-vector InVec>
6917
+ auto vector_abs_sum(InVec v);
6918
+ template<class ExecutionPolicy, in-vector InVec>
6919
+ auto vector_abs_sum(ExecutionPolicy&& exec, InVec v);
6920
+
6921
+ // [linalg.algs.blas1.iamax], index of maximum absolute value of vector elements
6922
+ template<in-vector InVec>
6923
+ typename InVec::extents_type vector_idx_abs_max(InVec v);
6924
+ template<class ExecutionPolicy, in-vector InVec>
6925
+ typename InVec::extents_type vector_idx_abs_max(ExecutionPolicy&& exec, InVec v);
6926
+
6927
+ // [linalg.algs.blas1.matfrobnorm], Frobenius norm of a matrix
6928
+ template<in-matrix InMat, class Scalar>
6929
+ Scalar matrix_frob_norm(InMat A, Scalar init);
6930
+ template<class ExecutionPolicy, in-matrix InMat, class Scalar>
6931
+ Scalar matrix_frob_norm(ExecutionPolicy&& exec, InMat A, Scalar init);
6932
+ template<in-matrix InMat>
6933
+ auto matrix_frob_norm(InMat A);
6934
+ template<class ExecutionPolicy, in-matrix InMat>
6935
+ auto matrix_frob_norm(ExecutionPolicy&& exec, InMat A);
6936
+
6937
+ // [linalg.algs.blas1.matonenorm], one norm of a matrix
6938
+ template<in-matrix InMat, class Scalar>
6939
+ Scalar matrix_one_norm(InMat A, Scalar init);
6940
+ template<class ExecutionPolicy, in-matrix InMat, class Scalar>
6941
+ Scalar matrix_one_norm(ExecutionPolicy&& exec, InMat A, Scalar init);
6942
+ template<in-matrix InMat>
6943
+ auto matrix_one_norm(InMat A);
6944
+ template<class ExecutionPolicy, in-matrix InMat>
6945
+ auto matrix_one_norm(ExecutionPolicy&& exec, InMat A);
6946
+
6947
+ // [linalg.algs.blas1.matinfnorm], infinity norm of a matrix
6948
+ template<in-matrix InMat, class Scalar>
6949
+ Scalar matrix_inf_norm(InMat A, Scalar init);
6950
+ template<class ExecutionPolicy, in-matrix InMat, class Scalar>
6951
+ Scalar matrix_inf_norm(ExecutionPolicy&& exec, InMat A, Scalar init);
6952
+ template<in-matrix InMat>
6953
+ auto matrix_inf_norm(InMat A);
6954
+ template<class ExecutionPolicy, in-matrix InMat>
6955
+ auto matrix_inf_norm(ExecutionPolicy&& exec, InMat A);
6956
+
6957
+ // [linalg.algs.blas2], BLAS 2 algorithms
6958
+
6959
+ // [linalg.algs.blas2.gemv], general matrix-vector product
6960
+ template<in-matrix InMat, in-vector InVec, out-vector OutVec>
6961
+ void matrix_vector_product(InMat A, InVec x, OutVec y);
6962
+ template<class ExecutionPolicy, in-matrix InMat, in-vector InVec, out-vector OutVec>
6963
+ void matrix_vector_product(ExecutionPolicy&& exec, InMat A, InVec x, OutVec y);
6964
+ template<in-matrix InMat, in-vector InVec1, in-vector InVec2, out-vector OutVec>
6965
+ void matrix_vector_product(InMat A, InVec1 x, InVec2 y, OutVec z);
6966
+ template<class ExecutionPolicy,
6967
+ in-matrix InMat, in-vector InVec1, in-vector InVec2, out-vector OutVec>
6968
+ void matrix_vector_product(ExecutionPolicy&& exec, InMat A, InVec1 x, InVec2 y, OutVec z);
6969
+
6970
+ // [linalg.algs.blas2.symv], symmetric matrix-vector product
6971
+ template<in-matrix InMat, class Triangle, in-vector InVec, out-vector OutVec>
6972
+ void symmetric_matrix_vector_product(InMat A, Triangle t, InVec x, OutVec y);
6973
+ template<class ExecutionPolicy,
6974
+ in-matrix InMat, class Triangle, in-vector InVec, out-vector OutVec>
6975
+ void symmetric_matrix_vector_product(ExecutionPolicy&& exec,
6976
+ InMat A, Triangle t, InVec x, OutVec y);
6977
+ template<in-matrix InMat, class Triangle, in-vector InVec1, in-vector InVec2,
6978
+ out-vector OutVec>
6979
+ void symmetric_matrix_vector_product(InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z);
6980
+ template<class ExecutionPolicy,
6981
+ in-matrix InMat, class Triangle, in-vector InVec1, in-vector InVec2,
6982
+ out-vector OutVec>
6983
+ void symmetric_matrix_vector_product(ExecutionPolicy&& exec,
6984
+ InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z);
6985
+
6986
+ // [linalg.algs.blas2.hemv], Hermitian matrix-vector product
6987
+ template<in-matrix InMat, class Triangle, in-vector InVec, out-vector OutVec>
6988
+ void hermitian_matrix_vector_product(InMat A, Triangle t, InVec x, OutVec y);
6989
+ template<class ExecutionPolicy,
6990
+ in-matrix InMat, class Triangle, in-vector InVec, out-vector OutVec>
6991
+ void hermitian_matrix_vector_product(ExecutionPolicy&& exec,
6992
+ InMat A, Triangle t, InVec x, OutVec y);
6993
+ template<in-matrix InMat, class Triangle, in-vector InVec1, in-vector InVec2,
6994
+ out-vector OutVec>
6995
+ void hermitian_matrix_vector_product(InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z);
6996
+ template<class ExecutionPolicy,
6997
+ in-matrix InMat, class Triangle, in-vector InVec1, in-vector InVec2,
6998
+ out-vector OutVec>
6999
+ void hermitian_matrix_vector_product(ExecutionPolicy&& exec,
7000
+ InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z);
7001
+
7002
+ // [linalg.algs.blas2.trmv], triangular matrix-vector product
7003
+
7004
+ // Overwriting triangular matrix-vector product
7005
+ template<in-matrix InMat, class Triangle, class DiagonalStorage, in-vector InVec,
7006
+ out-vector OutVec>
7007
+ void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d,
7008
+ InVec x, OutVec y);
7009
+ template<class ExecutionPolicy,
7010
+ in-matrix InMat, class Triangle, class DiagonalStorage, in-vector InVec,
7011
+ out-vector OutVec>
7012
+ void triangular_matrix_vector_product(ExecutionPolicy&& exec,
7013
+ InMat A, Triangle t, DiagonalStorage d,
7014
+ InVec x, OutVec y);
7015
+
7016
+ // In-place triangular matrix-vector product
7017
+ template<in-matrix InMat, class Triangle, class DiagonalStorage, inout-vector InOutVec>
7018
+ void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, InOutVec y);
7019
+ template<class ExecutionPolicy,
7020
+ in-matrix InMat, class Triangle, class DiagonalStorage, inout-vector InOutVec>
7021
+ void triangular_matrix_vector_product(ExecutionPolicy&& exec,
7022
+ InMat A, Triangle t, DiagonalStorage d, InOutVec y);
7023
+
7024
+ // Updating triangular matrix-vector product
7025
+ template<in-matrix InMat, class Triangle, class DiagonalStorage,
7026
+ in-vector InVec1, in-vector InVec2, out-vector OutVec>
7027
+ void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d,
7028
+ InVec1 x, InVec2 y, OutVec z);
7029
+ template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage,
7030
+ in-vector InVec1, in-vector InVec2, out-vector OutVec>
7031
+ void triangular_matrix_vector_product(ExecutionPolicy&& exec,
7032
+ InMat A, Triangle t, DiagonalStorage d,
7033
+ InVec1 x, InVec2 y, OutVec z);
7034
+
7035
+ // [linalg.algs.blas2.trsv], solve a triangular linear system
7036
+
7037
+ // Solve a triangular linear system, not in place
7038
+ template<in-matrix InMat, class Triangle, class DiagonalStorage,
7039
+ in-vector InVec, out-vector OutVec, class BinaryDivideOp>
7040
+ void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d,
7041
+ InVec b, OutVec x, BinaryDivideOp divide);
7042
+ template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage,
7043
+ in-vector InVec, out-vector OutVec, class BinaryDivideOp>
7044
+ void triangular_matrix_vector_solve(ExecutionPolicy&& exec,
7045
+ InMat A, Triangle t, DiagonalStorage d,
7046
+ InVec b, OutVec x, BinaryDivideOp divide);
7047
+ template<in-matrix InMat, class Triangle, class DiagonalStorage,
7048
+ in-vector InVec, out-vector OutVec>
7049
+ void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d,
7050
+ InVec b, OutVec x);
7051
+ template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage,
7052
+ in-vector InVec, out-vector OutVec>
7053
+ void triangular_matrix_vector_solve(ExecutionPolicy&& exec,
7054
+ InMat A, Triangle t, DiagonalStorage d,
7055
+ InVec b, OutVec x);
7056
+
7057
+ // Solve a triangular linear system, in place
7058
+ template<in-matrix InMat, class Triangle, class DiagonalStorage,
7059
+ inout-vector InOutVec, class BinaryDivideOp>
7060
+ void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d,
7061
+ InOutVec b, BinaryDivideOp divide);
7062
+ template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage,
7063
+ inout-vector InOutVec, class BinaryDivideOp>
7064
+ void triangular_matrix_vector_solve(ExecutionPolicy&& exec,
7065
+ InMat A, Triangle t, DiagonalStorage d,
7066
+ InOutVec b, BinaryDivideOp divide);
7067
+ template<in-matrix InMat, class Triangle, class DiagonalStorage, inout-vector InOutVec>
7068
+ void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, InOutVec b);
7069
+ template<class ExecutionPolicy,
7070
+ in-matrix InMat, class Triangle, class DiagonalStorage, inout-vector InOutVec>
7071
+ void triangular_matrix_vector_solve(ExecutionPolicy&& exec,
7072
+ InMat A, Triangle t, DiagonalStorage d, InOutVec b);
7073
+
7074
+ // [linalg.algs.blas2.rank1], nonsymmetric rank-1 matrix update
7075
+ template<in-vector InVec1, in-vector InVec2, inout-matrix InOutMat>
7076
+ void matrix_rank_1_update(InVec1 x, InVec2 y, InOutMat A);
7077
+ template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2, inout-matrix InOutMat>
7078
+ void matrix_rank_1_update(ExecutionPolicy&& exec, InVec1 x, InVec2 y, InOutMat A);
7079
+
7080
+ template<in-vector InVec1, in-vector InVec2, inout-matrix InOutMat>
7081
+ void matrix_rank_1_update_c(InVec1 x, InVec2 y, InOutMat A);
7082
+ template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2, inout-matrix InOutMat>
7083
+ void matrix_rank_1_update_c(ExecutionPolicy&& exec, InVec1 x, InVec2 y, InOutMat A);
7084
+
7085
+ // [linalg.algs.blas2.symherrank1], symmetric or Hermitian rank-1 matrix update
7086
+ template<class Scalar, in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle>
7087
+ void symmetric_matrix_rank_1_update(Scalar alpha, InVec x, InOutMat A, Triangle t);
7088
+ template<class ExecutionPolicy,
7089
+ class Scalar, in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle>
7090
+ void symmetric_matrix_rank_1_update(ExecutionPolicy&& exec,
7091
+ Scalar alpha, InVec x, InOutMat A, Triangle t);
7092
+ template<in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle>
7093
+ void symmetric_matrix_rank_1_update(InVec x, InOutMat A, Triangle t);
7094
+ template<class ExecutionPolicy,
7095
+ in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle>
7096
+ void symmetric_matrix_rank_1_update(ExecutionPolicy&& exec, InVec x, InOutMat A, Triangle t);
7097
+
7098
+ template<class Scalar, in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle>
7099
+ void hermitian_matrix_rank_1_update(Scalar alpha, InVec x, InOutMat A, Triangle t);
7100
+ template<class ExecutionPolicy,
7101
+ class Scalar, in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle>
7102
+ void hermitian_matrix_rank_1_update(ExecutionPolicy&& exec,
7103
+ Scalar alpha, InVec x, InOutMat A, Triangle t);
7104
+ template<in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle>
7105
+ void hermitian_matrix_rank_1_update(InVec x, InOutMat A, Triangle t);
7106
+ template<class ExecutionPolicy,
7107
+ in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle>
7108
+ void hermitian_matrix_rank_1_update(ExecutionPolicy&& exec, InVec x, InOutMat A, Triangle t);
7109
+
7110
+ // [linalg.algs.blas2.rank2], symmetric and Hermitian rank-2 matrix updates
7111
+
7112
+ // symmetric rank-2 matrix update
7113
+ template<in-vector InVec1, in-vector InVec2,
7114
+ possibly-packed-inout-matrix InOutMat, class Triangle>
7115
+ void symmetric_matrix_rank_2_update(InVec1 x, InVec2 y, InOutMat A, Triangle t);
7116
+ template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2,
7117
+ possibly-packed-inout-matrix InOutMat, class Triangle>
7118
+ void symmetric_matrix_rank_2_update(ExecutionPolicy&& exec,
7119
+ InVec1 x, InVec2 y, InOutMat A, Triangle t);
7120
+
7121
+ // Hermitian rank-2 matrix update
7122
+ template<in-vector InVec1, in-vector InVec2,
7123
+ possibly-packed-inout-matrix InOutMat, class Triangle>
7124
+ void hermitian_matrix_rank_2_update(InVec1 x, InVec2 y, InOutMat A, Triangle t);
7125
+ template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2,
7126
+ possibly-packed-inout-matrix InOutMat, class Triangle>
7127
+ void hermitian_matrix_rank_2_update(ExecutionPolicy&& exec,
7128
+ InVec1 x, InVec2 y, InOutMat A, Triangle t);
7129
+
7130
+ // [linalg.algs.blas3], BLAS 3 algorithms
7131
+
7132
+ // [linalg.algs.blas3.gemm], general matrix-matrix product
7133
+ template<in-matrix InMat1, in-matrix InMat2, out-matrix OutMat>
7134
+ void matrix_product(InMat1 A, InMat2 B, OutMat C);
7135
+ template<class ExecutionPolicy, in-matrix InMat1, in-matrix InMat2, out-matrix OutMat>
7136
+ void matrix_product(ExecutionPolicy&& exec,
7137
+ InMat1 A, InMat2 B, OutMat C);
7138
+ template<in-matrix InMat1, in-matrix InMat2, in-matrix InMat3, out-matrix OutMat>
7139
+ void matrix_product(InMat1 A, InMat2 B, InMat3 E, OutMat C);
7140
+ template<class ExecutionPolicy,
7141
+ in-matrix InMat1, in-matrix InMat2, in-matrix InMat3, out-matrix OutMat>
7142
+ void matrix_product(ExecutionPolicy&& exec,
7143
+ InMat1 A, InMat2 B, InMat3 E, OutMat C);
7144
+
7145
+ // [linalg.algs.blas3.xxmm], symmetric, Hermitian, and triangular matrix-matrix product
7146
+
7147
+ template<in-matrix InMat1, class Triangle, in-matrix InMat2, out-matrix OutMat>
7148
+ void symmetric_matrix_product(InMat1 A, Triangle t, InMat2 B, OutMat C);
7149
+ template<class ExecutionPolicy,
7150
+ in-matrix InMat1, class Triangle, in-matrix InMat2, out-matrix OutMat>
7151
+ void symmetric_matrix_product(ExecutionPolicy&& exec,
7152
+ InMat1 A, Triangle t, InMat2 B, OutMat C);
7153
+
7154
+ template<in-matrix InMat1, class Triangle, in-matrix InMat2, out-matrix OutMat>
7155
+ void hermitian_matrix_product(InMat1 A, Triangle t, InMat2 B, OutMat C);
7156
+ template<class ExecutionPolicy,
7157
+ in-matrix InMat1, class Triangle, in-matrix InMat2, out-matrix OutMat>
7158
+ void hermitian_matrix_product(ExecutionPolicy&& exec,
7159
+ InMat1 A, Triangle t, InMat2 B, OutMat C);
7160
+
7161
+ template<in-matrix InMat1, class Triangle, class DiagonalStorage,
7162
+ in-matrix InMat2, out-matrix OutMat>
7163
+ void triangular_matrix_product(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat C);
7164
+ template<class ExecutionPolicy,
7165
+ in-matrix InMat1, class Triangle, class DiagonalStorage,
7166
+ in-matrix InMat2, out-matrix OutMat>
7167
+ void triangular_matrix_product(ExecutionPolicy&& exec,
7168
+ InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat C);
7169
+
7170
+ template<in-matrix InMat1, in-matrix InMat2, class Triangle, out-matrix OutMat>
7171
+ void symmetric_matrix_product(InMat1 A, InMat2 B, Triangle t, OutMat C);
7172
+ template<class ExecutionPolicy,
7173
+ in-matrix InMat1, in-matrix InMat2, class Triangle, out-matrix OutMat>
7174
+ void symmetric_matrix_product(ExecutionPolicy&& exec,
7175
+ InMat1 A, InMat2 B, Triangle t, OutMat C);
7176
+
7177
+ template<in-matrix InMat1, in-matrix InMat2, class Triangle, out-matrix OutMat>
7178
+ void hermitian_matrix_product(InMat1 A, InMat2 B, Triangle t, OutMat C);
7179
+ template<class ExecutionPolicy,
7180
+ in-matrix InMat1, in-matrix InMat2, class Triangle, out-matrix OutMat>
7181
+ void hermitian_matrix_product(ExecutionPolicy&& exec,
7182
+ InMat1 A, InMat2 B, Triangle t, OutMat C);
7183
+
7184
+ template<in-matrix InMat1, in-matrix InMat2, class Triangle, class DiagonalStorage,
7185
+ out-matrix OutMat>
7186
+ void triangular_matrix_product(InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, OutMat C);
7187
+ template<class ExecutionPolicy,
7188
+ in-matrix InMat1, in-matrix InMat2, class Triangle, class DiagonalStorage,
7189
+ out-matrix OutMat>
7190
+ void triangular_matrix_product(ExecutionPolicy&& exec,
7191
+ InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, OutMat C);
7192
+
7193
+ template<in-matrix InMat1, class Triangle, in-matrix InMat2, in-matrix InMat3,
7194
+ out-matrix OutMat>
7195
+ void symmetric_matrix_product(InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C);
7196
+ template<class ExecutionPolicy,
7197
+ in-matrix InMat1, class Triangle, in-matrix InMat2, in-matrix InMat3,
7198
+ out-matrix OutMat>
7199
+ void symmetric_matrix_product(ExecutionPolicy&& exec,
7200
+ InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C);
7201
+
7202
+ template<in-matrix InMat1, class Triangle, in-matrix InMat2, in-matrix InMat3,
7203
+ out-matrix OutMat>
7204
+ void hermitian_matrix_product(InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C);
7205
+ template<class ExecutionPolicy,
7206
+ in-matrix InMat1, class Triangle, in-matrix InMat2, in-matrix InMat3,
7207
+ out-matrix OutMat>
7208
+ void hermitian_matrix_product(ExecutionPolicy&& exec,
7209
+ InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C);
7210
+
7211
+ template<in-matrix InMat1, class Triangle, class DiagonalStorage,
7212
+ in-matrix InMat2, in-matrix InMat3, out-matrix OutMat>
7213
+ void triangular_matrix_product(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, InMat3 E,
7214
+ OutMat C);
7215
+ template<class ExecutionPolicy,
7216
+ in-matrix InMat1, class Triangle, class DiagonalStorage,
7217
+ in-matrix InMat2, in-matrix InMat3, out-matrix OutMat>
7218
+ void triangular_matrix_product(ExecutionPolicy&& exec,
7219
+ InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, InMat3 E,
7220
+ OutMat C);
7221
+
7222
+ template<in-matrix InMat1, in-matrix InMat2, class Triangle, in-matrix InMat3,
7223
+ out-matrix OutMat>
7224
+ void symmetric_matrix_product(InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C);
7225
+ template<class ExecutionPolicy,
7226
+ in-matrix InMat1, in-matrix InMat2, class Triangle, in-matrix InMat3,
7227
+ out-matrix OutMat>
7228
+ void symmetric_matrix_product(ExecutionPolicy&& exec,
7229
+ InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C);
7230
+
7231
+ template<in-matrix InMat1, in-matrix InMat2, class Triangle, in-matrix InMat3,
7232
+ out-matrix OutMat>
7233
+ void hermitian_matrix_product(InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C);
7234
+ template<class ExecutionPolicy,
7235
+ in-matrix InMat1, in-matrix InMat2, class Triangle, in-matrix InMat3,
7236
+ out-matrix OutMat>
7237
+ void hermitian_matrix_product(ExecutionPolicy&& exec,
7238
+ InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C);
7239
+
7240
+ template<in-matrix InMat1, in-matrix InMat2, class Triangle, class DiagonalStorage,
7241
+ in-matrix InMat3, out-matrix OutMat>
7242
+ void triangular_matrix_product(InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, InMat3 E,
7243
+ OutMat C);
7244
+ template<class ExecutionPolicy,
7245
+ in-matrix InMat1, in-matrix InMat2, class Triangle, class DiagonalStorage,
7246
+ in-matrix InMat3, out-matrix OutMat>
7247
+ void triangular_matrix_product(ExecutionPolicy&& exec,
7248
+ InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, InMat3 E,
7249
+ OutMat C);
7250
+
7251
+ // [linalg.algs.blas3.trmm], in-place triangular matrix-matrix product
7252
+
7253
+ template<in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat>
7254
+ void triangular_matrix_left_product(InMat A, Triangle t, DiagonalStorage d, InOutMat C);
7255
+ template<class ExecutionPolicy,
7256
+ in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat>
7257
+ void triangular_matrix_left_product(ExecutionPolicy&& exec,
7258
+ InMat A, Triangle t, DiagonalStorage d, InOutMat C);
7259
+
7260
+ template<in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat>
7261
+ void triangular_matrix_right_product(InMat A, Triangle t, DiagonalStorage d, InOutMat C);
7262
+ template<class ExecutionPolicy,
7263
+ in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat>
7264
+ void triangular_matrix_right_product(ExecutionPolicy&& exec,
7265
+ InMat A, Triangle t, DiagonalStorage d, InOutMat C);
7266
+
7267
+ // [linalg.algs.blas3.rankk], rank-k update of a symmetric or Hermitian matrix
7268
+
7269
+ // rank-k symmetric matrix update
7270
+ template<class Scalar, in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle>
7271
+ void symmetric_matrix_rank_k_update(Scalar alpha, InMat A, InOutMat C, Triangle t);
7272
+ template<class ExecutionPolicy, class Scalar,
7273
+ in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle>
7274
+ void symmetric_matrix_rank_k_update(ExecutionPolicy&& exec,
7275
+ Scalar alpha, InMat A, InOutMat C, Triangle t);
7276
+
7277
+ template<in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle>
7278
+ void symmetric_matrix_rank_k_update(InMat A, InOutMat C, Triangle t);
7279
+ template<class ExecutionPolicy,
7280
+ in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle>
7281
+ void symmetric_matrix_rank_k_update(ExecutionPolicy&& exec,
7282
+ InMat A, InOutMat C, Triangle t);
7283
+
7284
+ // rank-k Hermitian matrix update
7285
+ template<class Scalar, in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle>
7286
+ void hermitian_matrix_rank_k_update(Scalar alpha, InMat A, InOutMat C, Triangle t);
7287
+ template<class ExecutionPolicy,
7288
+ class Scalar, in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle>
7289
+ void hermitian_matrix_rank_k_update(ExecutionPolicy&& exec,
7290
+ Scalar alpha, InMat A, InOutMat C, Triangle t);
7291
+
7292
+ template<in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle>
7293
+ void hermitian_matrix_rank_k_update(InMat A, InOutMat C, Triangle t);
7294
+ template<class ExecutionPolicy,
7295
+ in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle>
7296
+ void hermitian_matrix_rank_k_update(ExecutionPolicy&& exec,
7297
+ InMat A, InOutMat C, Triangle t);
7298
+
7299
+ // [linalg.algs.blas3.rank2k], rank-2k update of a symmetric or Hermitian matrix
7300
+
7301
+ // rank-2k symmetric matrix update
7302
+ template<in-matrix InMat1, in-matrix InMat2,
7303
+ possibly-packed-inout-matrix InOutMat, class Triangle>
7304
+ void symmetric_matrix_rank_2k_update(InMat1 A, InMat2 B, InOutMat C, Triangle t);
7305
+ template<class ExecutionPolicy,
7306
+ in-matrix InMat1, in-matrix InMat2,
7307
+ possibly-packed-inout-matrix InOutMat, class Triangle>
7308
+ void symmetric_matrix_rank_2k_update(ExecutionPolicy&& exec,
7309
+ InMat1 A, InMat2 B, InOutMat C, Triangle t);
7310
+
7311
+ // rank-2k Hermitian matrix update
7312
+ template<in-matrix InMat1, in-matrix InMat2,
7313
+ possibly-packed-inout-matrix InOutMat, class Triangle>
7314
+ void hermitian_matrix_rank_2k_update(InMat1 A, InMat2 B, InOutMat C, Triangle t);
7315
+ template<class ExecutionPolicy,
7316
+ in-matrix InMat1, in-matrix InMat2,
7317
+ possibly-packed-inout-matrix InOutMat, class Triangle>
7318
+ void hermitian_matrix_rank_2k_update(ExecutionPolicy&& exec,
7319
+ InMat1 A, InMat2 B, InOutMat C, Triangle t);
7320
+
7321
+ // [linalg.algs.blas3.trsm], solve multiple triangular linear systems
7322
+
7323
+ // solve multiple triangular systems on the left, not-in-place
7324
+ template<in-matrix InMat1, class Triangle, class DiagonalStorage,
7325
+ in-matrix InMat2, out-matrix OutMat, class BinaryDivideOp>
7326
+ void triangular_matrix_matrix_left_solve(InMat1 A, Triangle t, DiagonalStorage d,
7327
+ InMat2 B, OutMat X, BinaryDivideOp divide);
7328
+ template<class ExecutionPolicy,
7329
+ in-matrix InMat1, class Triangle, class DiagonalStorage,
7330
+ in-matrix InMat2, out-matrix OutMat, class BinaryDivideOp>
7331
+ void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec,
7332
+ InMat1 A, Triangle t, DiagonalStorage d,
7333
+ InMat2 B, OutMat X, BinaryDivideOp divide);
7334
+ template<in-matrix InMat1, class Triangle, class DiagonalStorage,
7335
+ in-matrix InMat2, out-matrix OutMat>
7336
+ void triangular_matrix_matrix_left_solve(InMat1 A, Triangle t, DiagonalStorage d,
7337
+ InMat2 B, OutMat X);
7338
+ template<class ExecutionPolicy,
7339
+ in-matrix InMat1, class Triangle, class DiagonalStorage,
7340
+ in-matrix InMat2, out-matrix OutMat>
7341
+ void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec,
7342
+ InMat1 A, Triangle t, DiagonalStorage d,
7343
+ InMat2 B, OutMat X);
7344
+
7345
+ // solve multiple triangular systems on the right, not-in-place
7346
+ template<in-matrix InMat1, class Triangle, class DiagonalStorage,
7347
+ in-matrix InMat2, out-matrix OutMat, class BinaryDivideOp>
7348
+ void triangular_matrix_matrix_right_solve(InMat1 A, Triangle t, DiagonalStorage d,
7349
+ InMat2 B, OutMat X, BinaryDivideOp divide);
7350
+ template<class ExecutionPolicy,
7351
+ in-matrix InMat1, class Triangle, class DiagonalStorage,
7352
+ in-matrix InMat2, out-matrix OutMat, class BinaryDivideOp>
7353
+ void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec,
7354
+ InMat1 A, Triangle t, DiagonalStorage d,
7355
+ InMat2 B, OutMat X, BinaryDivideOp divide);
7356
+ template<in-matrix InMat1, class Triangle, class DiagonalStorage,
7357
+ in-matrix InMat2, out-matrix OutMat>
7358
+ void triangular_matrix_matrix_right_solve(InMat1 A, Triangle t, DiagonalStorage d,
7359
+ InMat2 B, OutMat X);
7360
+ template<class ExecutionPolicy,
7361
+ in-matrix InMat1, class Triangle, class DiagonalStorage,
7362
+ in-matrix InMat2, out-matrix OutMat>
7363
+ void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec,
7364
+ InMat1 A, Triangle t, DiagonalStorage d,
7365
+ InMat2 B, OutMat X);
7366
+
7367
+ // solve multiple triangular systems on the left, in-place
7368
+ template<in-matrix InMat, class Triangle, class DiagonalStorage,
7369
+ inout-matrix InOutMat, class BinaryDivideOp>
7370
+ void triangular_matrix_matrix_left_solve(InMat A, Triangle t, DiagonalStorage d,
7371
+ InOutMat B, BinaryDivideOp divide);
7372
+ template<class ExecutionPolicy,
7373
+ in-matrix InMat, class Triangle, class DiagonalStorage,
7374
+ inout-matrix InOutMat, class BinaryDivideOp>
7375
+ void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec,
7376
+ InMat A, Triangle t, DiagonalStorage d,
7377
+ InOutMat B, BinaryDivideOp divide);
7378
+ template<in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat>
7379
+ void triangular_matrix_matrix_left_solve(InMat A, Triangle t, DiagonalStorage d,
7380
+ InOutMat B);
7381
+ template<class ExecutionPolicy,
7382
+ in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat>
7383
+ void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec,
7384
+ InMat A, Triangle t, DiagonalStorage d,
7385
+ InOutMat B);
7386
+
7387
+ // solve multiple triangular systems on the right, in-place
7388
+ template<in-matrix InMat, class Triangle, class DiagonalStorage,
7389
+ inout-matrix InOutMat, class BinaryDivideOp>
7390
+ void triangular_matrix_matrix_right_solve(InMat A, Triangle t, DiagonalStorage d,
7391
+ InOutMat B, BinaryDivideOp divide);
7392
+ template<class ExecutionPolicy,
7393
+ in-matrix InMat, class Triangle, class DiagonalStorage,
7394
+ inout-matrix InOutMat, class BinaryDivideOp>
7395
+ void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec,
7396
+ InMat A, Triangle t, DiagonalStorage d,
7397
+ InOutMat B, BinaryDivideOp divide);
7398
+ template<in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat>
7399
+ void triangular_matrix_matrix_right_solve(InMat A, Triangle t, DiagonalStorage d,
7400
+ InOutMat B);
7401
+ template<class ExecutionPolicy,
7402
+ in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat>
7403
+ void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec,
7404
+ InMat A, Triangle t, DiagonalStorage d,
7405
+ InOutMat B);
7406
+ }
7407
+ ```
7408
+
7409
+ ### General <a id="linalg.general">[[linalg.general]]</a>
7410
+
7411
+ For the effects of all functions in [[linalg]], when the effects are
7412
+ described as “computes R = E” or “compute R = E” (for some R and
7413
+ mathematical expression E), the following apply:
7414
+
7415
+ - E has the conventional mathematical meaning as written.
7416
+ - The pattern $x^T$ should be read as “the transpose of x.”
7417
+ - The pattern $x^H$ should be read as “the conjugate transpose of x.”
7418
+ - When R is the same name as a function parameter whose type is a
7419
+ template parameter with `Out` in its name, the intent is that the
7420
+ result of the computation is written to the elements of the function
7421
+ parameter `R`.
7422
+
7423
+ Some of the functions and types in [[linalg]] distinguish between the
7424
+ “rows” and the “columns” of a matrix. For a matrix `A` and a
7425
+ multidimensional index `i, j` in `A.extents()`,
7426
+
7427
+ - *row* `i` of `A` is the set of elements `A[i, k1]` for all `k1` such
7428
+ that `i, k1` is in `A.extents()`; and
7429
+ - *column* `j` of `A` is the set of elements `A[k0, j]` for all `k0`
7430
+ such that `k0, j` is in `A.extents()`.
7431
+
7432
+ Some of the functions in [[linalg]] distinguish between the “upper
7433
+ triangle,” “lower triangle,” and “diagonal” of a matrix.
7434
+
7435
+ - The *diagonal* is the set of all elements of `A` accessed by `A[i,i]`
7436
+ for 0 ≤ `i` \< min(`A.extent(0)`, `A.extent(1)`).
7437
+ - The *upper triangle* of a matrix `A` is the set of all elements of `A`
7438
+ accessed by `A[i,j]` with `i` ≤ `j`. It includes the diagonal.
7439
+ - The *lower triangle* of `A` is the set of all elements of `A` accessed
7440
+ by `A[i,j]` with `i` ≥ `j`. It includes the diagonal.
7441
+
7442
+ For any function `F` that takes a parameter named `t`, `t` applies to
7443
+ accesses done through the parameter preceding `t` in the parameter list
7444
+ of `F`. Let `m` be such an access-modified function parameter. `F` will
7445
+ only access the triangle of `m` specified by `t`. For accesses `m[i, j]`
7446
+ outside the triangle specified by `t`, `F` will use the value
7447
+
7448
+ - `conj-if-needed(m[j, i])` if the name of `F` starts with `hermitian`,
7449
+ - `m[j, i]` if the name of `F` starts with `symmetric`, or
7450
+ - the additive identity if the name of `F` starts with `triangular`.
7451
+
7452
+ [*Example 1*:
7453
+
7454
+ Small vector product accessing only specified triangle. It would not be
7455
+ a precondition violation for the non-accessed matrix element to be
7456
+ non-zero.
7457
+
7458
+ ``` cpp
7459
+ template<class Triangle>
7460
+ void triangular_matrix_vector_2x2_product(
7461
+ mdspan<const float, extents<int, 2, 2>> m,
7462
+ Triangle t,
7463
+ mdspan<const float, extents<int, 2>> x,
7464
+ mdspan<float, extents<int, 2>> y) {
7465
+
7466
+ static_assert(is_same_v<Triangle, lower_triangle_t> ||
7467
+ is_same_v<Triangle, upper_triangle_t>);
7468
+
7469
+ if constexpr (is_same_v<Triangle, lower_triangle_t>) {
7470
+ y[0] = m[0,0] * x[0]; // + 0 * x[1]
7471
+ y[1] = m[1,0] * x[0] + m[1,1] * x[1];
7472
+ } else { // upper_triangle_t
7473
+ y[0] = m[0,0] * x[0] + m[0,1] * x[1];
7474
+ y[1] = /* 0 * x[0] + */ m[1,1] * x[1];
7475
+ }
7476
+ }
7477
+ ```
7478
+
7479
+ — *end example*]
7480
+
7481
+ For any function `F` that takes a parameter named `d`, `d` applies to
7482
+ accesses done through the previous-of-the-previous parameter of `d` in
7483
+ the parameter list of `F`. Let `m` be such an access-modified function
7484
+ parameter. If `d` specifies that an implicit unit diagonal is to be
7485
+ assumed, then
7486
+
7487
+ - `F` will not access the diagonal of `m`; and
7488
+ - the algorithm will interpret `m` as if it has a unit diagonal, that
7489
+ is, a diagonal each of whose elements behaves as a two-sided
7490
+ multiplicative identity (even if `m`’s value type does not have a
7491
+ two-sided multiplicative identity).
7492
+
7493
+ Otherwise, if `d` specifies that an explicit diagonal is to be assumed,
7494
+ then `F` will access the diagonal of `m`.
7495
+
7496
+ Within all the functions in [[linalg]], any calls to `abs`, `conj`,
7497
+ `imag`, and `real` are unqualified.
7498
+
7499
+ Two `mdspan` objects `x` and `y` *alias* each other, if they have the
7500
+ same extents `e`, and for every pack of integers `i` which is a
7501
+ multidimensional index in `e`, `x[i...]` and `y[i...]` refer to the same
7502
+ element.
7503
+
7504
+ [*Note 1*: This means that `x` and `y` view the same elements in the
7505
+ same order. — *end note*]
7506
+
7507
+ Two `mdspan` objects `x` and `y` *overlap* each other, if for some pack
7508
+ of integers `i` that is a multidimensional index in `x.extents()`, there
7509
+ exists a pack of integers `j` that is a multidimensional index in
7510
+ `y.extents()`, such that `x[i...]` and `y[j...]` refer to the same
7511
+ element.
7512
+
7513
+ [*Note 2*: Aliasing is a special case of overlapping. If `x` and `y` do
7514
+ not overlap, then they also do not alias each other. — *end note*]
7515
+
7516
+ ### Requirements <a id="linalg.reqs">[[linalg.reqs]]</a>
7517
+
7518
+ #### Linear algebra value types <a id="linalg.reqs.val">[[linalg.reqs.val]]</a>
7519
+
7520
+ Throughout [[linalg]], the following types are *linear algebra value
7521
+ types*:
7522
+
7523
+ - the `value_type` type alias of any input or output `mdspan`
7524
+ parameter(s) of any function in [[linalg]]; and
7525
+ - the `Scalar` template parameter (if any) of any function or class in
7526
+ [[linalg]].
7527
+
7528
+ Linear algebra value types shall model `semiregular`.
7529
+
7530
+ A value-initialized object of linear algebra value type shall act as the
7531
+ additive identity.
7532
+
7533
+ #### Algorithm and class requirements <a id="linalg.reqs.alg">[[linalg.reqs.alg]]</a>
7534
+
7535
+ [[linalg.reqs.alg]] lists common requirements for all algorithms and
7536
+ classes in [[linalg]].
7537
+
7538
+ All of the following statements presume that the algorithm’s asymptotic
7539
+ complexity requirements, if any, are satisfied.
7540
+
7541
+ - The function may make arbitrarily many objects of any linear algebra
7542
+ value type, value-initializing or direct-initializing them with any
7543
+ existing object of that type.
7544
+ - The *triangular solve algorithms* in [[linalg.algs.blas2.trsv]],
7545
+ [[linalg.algs.blas3.trmm]], [[linalg.algs.blas3.trsm]], and
7546
+ [[linalg.algs.blas3.inplacetrsm]] either have a `BinaryDivideOp`
7547
+ template parameter (see [[linalg.algs.reqs]]) and a binary function
7548
+ object parameter `divide` of that type, or they have effects
7549
+ equivalent to invoking such an algorithm. Triangular solve algorithms
7550
+ interpret `divide(a, b)` as `a` times the multiplicative inverse of
7551
+ `b`. Each triangular solve algorithm uses a sequence of evaluations of
7552
+ `*`, `*=`, `divide`, unary `+`, binary `+`, `+=`, unary `-`, binary
7553
+ `-`, `-=`, and `=` operators that would produce the result specified
7554
+ by the algorithm’s *Effects* and *Remarks* when operating on elements
7555
+ of a field with noncommutative multiplication. It is a precondition of
7556
+ the algorithm that any addend, any subtrahend, any partial sum of
7557
+ addends in any order (treating any difference as a sum with the second
7558
+ term negated), any factor, any partial product of factors respecting
7559
+ their order, any numerator (first argument of `divide`), any
7560
+ denominator (second argument of `divide`), and any assignment is a
7561
+ well-formed expression.
7562
+ - Each function in [[linalg.algs.blas1]], [[linalg.algs.blas2]], and
7563
+ [[linalg.algs.blas3]] that is not a triangular solve algorithm will
7564
+ use a sequence of evaluations of `*`, `*=`, `+`, `+=`, and `=`
7565
+ operators that would produce the result specified by the algorithm’s
7566
+ *Effects* and *Remarks* when operating on elements of a semiring with
7567
+ noncommutative multiplication. It is a precondition of the algorithm
7568
+ that any addend, any partial sum of addends in any order, any factor,
7569
+ any partial product of factors respecting their order, and any
7570
+ assignment is a well-formed expression.
7571
+ - If the function has an output `mdspan`, then all addends, subtrahends
7572
+ (for the triangular solve algorithms), or results of the `divide`
7573
+ parameter on intermediate terms (if the function takes a `divide`
7574
+ parameter) are assignable and convertible to the output `mdspan`’s
7575
+ `value_type`.
7576
+ - The function may reorder addends and partial sums arbitrarily.
7577
+ \[*Note 1*: Factors in each product are not reordered; multiplication
7578
+ is not necessarily commutative. — *end note*]
7579
+
7580
+ [*Note 2*: The above requirements do not prohibit implementation
7581
+ approaches and optimization techniques which are not user-observable. In
7582
+ particular, if for all input and output arguments the `value_type` is a
7583
+ floating-point type, implementers are free to leverage approximations,
7584
+ use arithmetic operations not explicitly listed above, and compute
7585
+ floating-point sums in any way that improves their
7586
+ accuracy. — *end note*]
7587
+
7588
+ [*Note 3*:
7589
+
7590
+ For all functions in [[linalg]], suppose that all input and output
7591
+ `mdspan` have as `value_type` a floating-point type, and any `Scalar`
7592
+ template argument has a floating-point type. Then, functions can do all
7593
+ of the following:
7594
+
7595
+ - compute floating-point sums in any way that improves their accuracy
7596
+ for arbitrary input;
7597
+ - perform additional arithmetic operations (other than those specified
7598
+ by the function’s wording and [[linalg.reqs.alg]]) in order to improve
7599
+ performance or accuracy; and
7600
+ - use approximations (that might not be exact even if computing with
7601
+ real numbers), instead of computations that would be exact if it were
7602
+ possible to compute without rounding error;
7603
+
7604
+ as long as
7605
+
7606
+ - the function satisfies the complexity requirements; and
7607
+ - the function is logarithmically stable, as defined in Demmel 2007.
7608
+ Strassen’s algorithm for matrix-matrix multiply is an example of a
7609
+ logarithmically stable algorithm.
7610
+
7611
+ — *end note*]
7612
+
7613
+ ### Tag classes <a id="linalg.tags">[[linalg.tags]]</a>
7614
+
7615
+ #### Storage order tags <a id="linalg.tags.order">[[linalg.tags.order]]</a>
7616
+
7617
+ The storage order tags describe the order of elements in an `mdspan`
7618
+ with `layout_blas_packed` [[linalg.layout.packed]] layout.
7619
+
7620
+ ``` cpp
7621
+ struct column_major_t {
7622
+ explicit column_major_t() = default;
7623
+ };
7624
+ inline constexpr column_major_t column_major{};
7625
+
7626
+ struct row_major_t {
7627
+ explicit row_major_t() = default;
7628
+ };
7629
+ inline constexpr row_major_t row_major{};
7630
+ ```
7631
+
7632
+ `column_major_t` indicates a column-major order, and `row_major_t`
7633
+ indicates a row-major order.
7634
+
7635
+ #### Triangle tags <a id="linalg.tags.triangle">[[linalg.tags.triangle]]</a>
7636
+
7637
+ ``` cpp
7638
+ struct upper_triangle_t {
7639
+ explicit upper_triangle_t() = default;
7640
+ };
7641
+ inline constexpr upper_triangle_t upper_triangle{};
7642
+
7643
+ struct lower_triangle_t {
7644
+ explicit lower_triangle_t() = default;
7645
+ };
7646
+ inline constexpr lower_triangle_t lower_triangle{};
7647
+ ```
7648
+
7649
+ These tag classes specify whether algorithms and other users of a matrix
7650
+ (represented as an `mdspan`) access the upper triangle
7651
+ (`upper_triangle_t`) or lower triangle (`lower_triangle_t`) of the
7652
+ matrix (see also [[linalg.general]]). This is also subject to the
7653
+ restrictions of `implicit_unit_diagonal_t` if that tag is also used as a
7654
+ function argument; see below.
7655
+
7656
+ #### Diagonal tags <a id="linalg.tags.diagonal">[[linalg.tags.diagonal]]</a>
7657
+
7658
+ ``` cpp
7659
+ struct implicit_unit_diagonal_t {
7660
+ explicit implicit_unit_diagonal_t() = default;
7661
+ };
7662
+ inline constexpr implicit_unit_diagonal_t implicit_unit_diagonal{};
7663
+
7664
+ struct explicit_diagonal_t {
7665
+ explicit explicit_diagonal_t() = default;
7666
+ };
7667
+ inline constexpr explicit_diagonal_t explicit_diagonal{};
7668
+ ```
7669
+
7670
+ These tag classes specify whether algorithms access the matrix’s
7671
+ diagonal entries, and if not, then how algorithms interpret the matrix’s
7672
+ implicitly represented diagonal values.
7673
+
7674
+ The `implicit_unit_diagonal_t` tag indicates that an implicit unit
7675
+ diagonal is to be assumed [[linalg.general]].
7676
+
7677
+ The `explicit_diagonal_t` tag indicates that an explicit diagonal is
7678
+ used [[linalg.general]].
7679
+
7680
+ ### Layouts for packed matrix types <a id="linalg.layout.packed">[[linalg.layout.packed]]</a>
7681
+
7682
+ #### Overview <a id="linalg.layout.packed.overview">[[linalg.layout.packed.overview]]</a>
7683
+
7684
+ `layout_blas_packed` is an `mdspan` layout mapping policy that
7685
+ represents a square matrix that stores only the entries in one triangle,
7686
+ in a packed contiguous format. Its `Triangle` template parameter
7687
+ determines whether an `mdspan` with this layout stores the upper or
7688
+ lower triangle of the matrix. Its `StorageOrder` template parameter
7689
+ determines whether the layout packs the matrix’s elements in
7690
+ column-major or row-major order.
7691
+
7692
+ A `StorageOrder` of `column_major_t` indicates column-major ordering.
7693
+ This packs matrix elements starting with the leftmost (least column
7694
+ index) column, and proceeding column by column, from the top entry
7695
+ (least row index).
7696
+
7697
+ A `StorageOrder` of `row_major_t` indicates row-major ordering. This
7698
+ packs matrix elements starting with the topmost (least row index) row,
7699
+ and proceeding row by row, from the leftmost (least column index) entry.
7700
+
7701
+ [*Note 1*: `layout_blas_packed` describes the data layout used by the
7702
+ BLAS’ Symmetric Packed (SP), Hermitian Packed (HP), and Triangular
7703
+ Packed (TP) matrix types. — *end note*]
7704
+
7705
+ ``` cpp
7706
+ namespace std::linalg {
7707
+ template<class Triangle, class StorageOrder>
7708
+ class layout_blas_packed {
7709
+ public:
7710
+ using triangle_type = Triangle;
7711
+ using storage_order_type = StorageOrder;
7712
+
7713
+ template<class Extents>
7714
+ struct mapping {
7715
+ public:
7716
+ using extents_type = Extents;
7717
+ using index_type = extents_type::index_type;
7718
+ using size_type = extents_type::size_type;
7719
+ using rank_type = extents_type::rank_type;
7720
+ using layout_type = layout_blas_packed;
7721
+
7722
+ // [linalg.layout.packed.cons], constructors
7723
+ constexpr mapping() noexcept = default;
7724
+ constexpr mapping(const mapping&) noexcept = default;
7725
+ constexpr mapping(const extents_type&) noexcept;
7726
+ template<class OtherExtents>
7727
+ constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
7728
+ mapping(const mapping<OtherExtents>& other) noexcept;
7729
+
7730
+ constexpr mapping& operator=(const mapping&) noexcept = default;
7731
+
7732
+ // [linalg.layout.packed.obs], observers
7733
+ constexpr const extents_type& extents() const noexcept { return extents_; }
7734
+
7735
+ constexpr index_type required_span_size() const noexcept;
7736
+
7737
+ template<class Index0, class Index1>
7738
+ constexpr index_type operator() (Index0 ind0, Index1 ind1) const noexcept;
7739
+
7740
+ static constexpr bool is_always_unique() noexcept {
7741
+ return (extents_type::static_extent(0) != dynamic_extent &&
7742
+ extents_type::static_extent(0) < 2) ||
7743
+ (extents_type::static_extent(1) != dynamic_extent &&
7744
+ extents_type::static_extent(1) < 2);
7745
+ }
7746
+ static constexpr bool is_always_exhaustive() noexcept { return true; }
7747
+ static constexpr bool is_always_strided() noexcept
7748
+ { return is_always_unique(); }
7749
+
7750
+ constexpr bool is_unique() const noexcept {
7751
+ return extents_.extent(0) < 2;
7752
+ }
7753
+ constexpr bool is_exhaustive() const noexcept { return true; }
7754
+ constexpr bool is_strided() const noexcept {
7755
+ return extents_.extent(0) < 2;
7756
+ }
7757
+
7758
+ constexpr index_type stride(rank_type) const noexcept;
7759
+
7760
+ template<class OtherExtents>
7761
+ friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept;
7762
+
7763
+ private:
7764
+ extents_type extents_{}; // exposition only
7765
+ };
7766
+ };
7767
+ }
7768
+ ```
7769
+
7770
+ *Mandates:*
7771
+
7772
+ - `Triangle` is either `upper_triangle_t` or `lower_triangle_t`,
7773
+ - `StorageOrder` is either `column_major_t` or `row_major_t`,
7774
+ - `Extents` is a specialization of `std::extents`,
7775
+ - `Extents::rank()` equals 2,
7776
+ - one of
7777
+ ``` cpp
7778
+ extents_type::static_extent(0) == dynamic_extent,
7779
+ extents_type::static_extent(1) == dynamic_extent, or
7780
+ extents_type::static_extent(0) == extents_type::static_extent(1)
7781
+ ```
7782
+
7783
+ is `true`, and
7784
+ - if `Extents::rank_dynamic() == 0` is `true`, let Nₛ be equal to
7785
+ `Extents::static_extent(0)`; then, Nₛ × (Nₛ + 1) is representable as a
7786
+ value of type `index_type`.
7787
+
7788
+ `layout_blas_packed<T, SO>::mapping<E>` is a trivially copyable type
7789
+ that models `regular` for each `T`, `SO`, and `E`.
7790
+
7791
+ #### Constructors <a id="linalg.layout.packed.cons">[[linalg.layout.packed.cons]]</a>
7792
+
7793
+ ``` cpp
7794
+ constexpr mapping(const extents_type& e) noexcept;
7795
+ ```
7796
+
7797
+ *Preconditions:*
7798
+
7799
+ - Let N be equal to `e.extent(0)`. Then, N × (N+1) is representable as a
7800
+ value of type `index_type` [[basic.fundamental]].
7801
+ - `e.extent(0)` equals `e.extent(1)`.
7802
+
7803
+ *Effects:* Direct-non-list-initializes *extents\_* with `e`.
7804
+
7805
+ ``` cpp
7806
+ template<class OtherExtents>
7807
+ explicit(!is_convertible_v<OtherExtents, extents_type>)
7808
+ constexpr mapping(const mapping<OtherExtents>& other) noexcept;
7809
+ ```
7810
+
7811
+ *Constraints:* `is_constructible_v<extents_type, OtherExtents>` is
7812
+ `true`.
7813
+
7814
+ *Preconditions:* Let N be `other.extents().extent(0)`. Then, N × (N+1)
7815
+ is representable as a value of type `index_type` [[basic.fundamental]].
7816
+
7817
+ *Effects:* Direct-non-list-initializes *extents\_* with
7818
+ `other.extents()`.
7819
+
7820
+ #### Observers <a id="linalg.layout.packed.obs">[[linalg.layout.packed.obs]]</a>
7821
+
7822
+ ``` cpp
7823
+ constexpr index_type required_span_size() const noexcept;
7824
+ ```
7825
+
7826
+ *Returns:* *`extents_`*`.extent(0) * (`*`extents_`*`.extent(0) + 1)/2`.
7827
+
7828
+ [*Note 1*: For example, a 5 x 5 packed matrix only stores 15 matrix
7829
+ elements. — *end note*]
7830
+
7831
+ ``` cpp
7832
+ template<class Index0, class Index1>
7833
+ constexpr index_type operator() (Index0 ind0, Index1 ind1) const noexcept;
7834
+ ```
7835
+
7836
+ *Constraints:*
7837
+
7838
+ - `is_convertible_v<Index0, index_type>` is `true`,
7839
+ - `is_convertible_v<Index1, index_type>` is `true`,
7840
+ - `is_nothrow_constructible_v<index_type, Index0>` is `true`, and
7841
+ - `is_nothrow_constructible_v<index_type, Index1>` is `true`.
7842
+
7843
+ Let `i` be `extents_type::`*`index-cast`*`(ind0)`, and let `j` be
7844
+ `extents_type::`*`index-cast`*`(ind1)`.
7845
+
7846
+ *Preconditions:* `i, j` is a multidimensional index in
7847
+ *extents\_*[[mdspan.overview]].
7848
+
7849
+ *Returns:* Let `N` be *`extents_`*`.extent(0)`. Then
7850
+
7851
+ - `(*this)(j, i)` if `i > j` is `true`; otherwise
7852
+ - `i + j * (j + 1)/2` if
7853
+ ``` cpp
7854
+ is_same_v<StorageOrder, column_major_t> && is_same_v<Triangle, upper_triangle_t>
7855
+ ```
7856
+
7857
+ is `true` or
7858
+ ``` cpp
7859
+ is_same_v<StorageOrder, row_major_t> && is_same_v<Triangle, lower_triangle_t>
7860
+ ```
7861
+
7862
+ is `true`; otherwise
7863
+ - `j + N * i - i * (i + 1)/2`.
7864
+
7865
+ ``` cpp
7866
+ constexpr index_type stride(rank_type r) const noexcept;
7867
+ ```
7868
+
7869
+ *Preconditions:*
7870
+
7871
+ - `is_strided()` is `true`, and
7872
+ - `r < extents_type::rank()` is `true`.
7873
+
7874
+ *Returns:* `1`.
7875
+
7876
+ ``` cpp
7877
+ template<class OtherExtents>
7878
+ friend constexpr bool operator==(const mapping& x, const mapping<OtherExtents>& y) noexcept;
7879
+ ```
7880
+
7881
+ *Effects:* Equivalent to: `return x.extents() == y.extents();`
7882
+
7883
+ ### Exposition-only helpers <a id="linalg.helpers">[[linalg.helpers]]</a>
7884
+
7885
+ #### *`abs-if-needed`* <a id="linalg.helpers.abs">[[linalg.helpers.abs]]</a>
7886
+
7887
+ The name *`abs-if-needed`* denotes an exposition-only function object.
7888
+ The expression `abs-if-needed(E)` for a subexpression `E` whose type is
7889
+ `T` is expression-equivalent to:
7890
+
7891
+ - `E` if `T` is an unsigned integer;
7892
+ - otherwise, `std::abs(E)` if `T` is an arithmetic type,
7893
+ - otherwise, `abs(E)`, if that expression is valid, with overload
7894
+ resolution performed in a context that includes the declaration
7895
+ ``` cpp
7896
+ template<class U> U abs(U) = delete;
7897
+ ```
7898
+
7899
+ If the function selected by overload resolution does not return the
7900
+ absolute value of its input, the program is ill-formed, no diagnostic
7901
+ required.
7902
+
7903
+ #### *`conj-if-needed`* <a id="linalg.helpers.conj">[[linalg.helpers.conj]]</a>
7904
+
7905
+ The name *`conj-if-needed`* denotes an exposition-only function object.
7906
+ The expression `conj-if-needed(E)` for a subexpression `E` whose type is
7907
+ `T` is expression-equivalent to:
7908
+
7909
+ - `conj(E)`, if `T` is not an arithmetic type and the expression
7910
+ `conj(E)` is valid, with overload resolution performed in a context
7911
+ that includes the declaration
7912
+ ``` cpp
7913
+ template<class U> U conj(const U&) = delete;
7914
+ ```
7915
+
7916
+ If the function selected by overload resolution does not return the
7917
+ complex conjugate of its input, the program is ill-formed, no
7918
+ diagnostic required;
7919
+ - otherwise, `E`.
7920
+
7921
+ #### *`real-if-needed`* <a id="linalg.helpers.real">[[linalg.helpers.real]]</a>
7922
+
7923
+ The name *`real-if-needed`* denotes an exposition-only function object.
7924
+ The expression `real-if-needed(E)` for a subexpression `E` whose type is
7925
+ `T` is expression-equivalent to:
7926
+
7927
+ - `real(E)`, if `T` is not an arithmetic type and the expression
7928
+ `real(E)` is valid, with overload resolution performed in a context
7929
+ that includes the declaration
7930
+ ``` cpp
7931
+ template<class U> U real(const U&) = delete;
7932
+ ```
7933
+
7934
+ If the function selected by overload resolution does not return the
7935
+ real part of its input, the program is ill-formed, no diagnostic
7936
+ required;
7937
+ - otherwise, `E`.
7938
+
7939
+ #### *`imag-if-needed`* <a id="linalg.helpers.imag">[[linalg.helpers.imag]]</a>
7940
+
7941
+ The name *`imag-if-needed`* denotes an exposition-only function object.
7942
+ The expression `imag-if-needed(E)` for a subexpression `E` whose type is
7943
+ `T` is expression-equivalent to:
7944
+
7945
+ - `imag(E)`, if `T` is not an arithmetic type and the expression
7946
+ `imag(E)` is valid, with overload resolution performed in a context
7947
+ that includes the declaration
7948
+ ``` cpp
7949
+ template<class U> U imag(const U&) = delete;
7950
+ ```
7951
+
7952
+ If the function selected by overload resolution does not return the
7953
+ imaginary part of its input, the program is ill-formed, no diagnostic
7954
+ required;
7955
+ - otherwise, `((void)E, T{})`.
7956
+
7957
+ #### Argument concepts <a id="linalg.helpers.concepts">[[linalg.helpers.concepts]]</a>
7958
+
7959
+ The exposition-only concepts defined in this section constrain the
7960
+ algorithms in [[linalg]].
7961
+
7962
+ ``` cpp
7963
+ template<class T>
7964
+ constexpr bool is-mdspan = false;
7965
+
7966
+ template<class ElementType, class Extents, class Layout, class Accessor>
7967
+ constexpr bool is-mdspan<mdspan<ElementType, Extents, Layout, Accessor>> = true;
7968
+
7969
+ template<class T>
7970
+ concept in-vector =
7971
+ is-mdspan<T> && T::rank() == 1;
7972
+
7973
+ template<class T>
7974
+ concept out-vector =
7975
+ is-mdspan<T> && T::rank() == 1 &&
7976
+ is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();
7977
+
7978
+ template<class T>
7979
+ concept inout-vector =
7980
+ is-mdspan<T> && T::rank() == 1 &&
7981
+ is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();
7982
+
7983
+ template<class T>
7984
+ concept in-matrix =
7985
+ is-mdspan<T> && T::rank() == 2;
7986
+
7987
+ template<class T>
7988
+ concept out-matrix =
7989
+ is-mdspan<T> && T::rank() == 2 &&
7990
+ is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();
7991
+
7992
+ template<class T>
7993
+ concept inout-matrix =
7994
+ is-mdspan<T> && T::rank() == 2 &&
7995
+ is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();
7996
+
7997
+ template<class T>
7998
+ constexpr bool is-layout-blas-packed = false; // exposition only
7999
+
8000
+ template<class Triangle, class StorageOrder>
8001
+ constexpr bool is-layout-blas-packed<layout_blas_packed<Triangle, StorageOrder>> = true;
8002
+
8003
+ template<class T>
8004
+ concept possibly-packed-inout-matrix =
8005
+ is-mdspan<T> && T::rank() == 2 &&
8006
+ is_assignable_v<typename T::reference, typename T::element_type> &&
8007
+ (T::is_always_unique() || is-layout-blas-packed<typename T::layout_type>);
8008
+
8009
+ template<class T>
8010
+ concept in-object =
8011
+ is-mdspan<T> && (T::rank() == 1 || T::rank() == 2);
8012
+
8013
+ template<class T>
8014
+ concept out-object =
8015
+ is-mdspan<T> && (T::rank() == 1 || T::rank() == 2) &&
8016
+ is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();
8017
+
8018
+ template<class T>
8019
+ concept inout-object =
8020
+ is-mdspan<T> && (T::rank() == 1 || T::rank() == 2) &&
8021
+ is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();
8022
+ ```
8023
+
8024
+ If a function in [[linalg]] accesses the elements of a parameter
8025
+ constrained by `in-vector`, `in-matrix`, or `in-object`, those accesses
8026
+ will not modify the elements.
8027
+
8028
+ Unless explicitly permitted, any `inout-vector`, `inout-matrix`,
8029
+ `inout-object`, `out-vector`, `out-matrix`, `out-object`, or
8030
+ `possibly-packed-inout-matrix` parameter of a function in [[linalg]]
8031
+ shall not overlap any other `mdspan` parameter of the function.
8032
+
8033
+ #### Mandates <a id="linalg.helpers.mandates">[[linalg.helpers.mandates]]</a>
8034
+
8035
+ [*Note 1*: These exposition-only helper functions use the less
8036
+ constraining input concepts even for the output arguments, because the
8037
+ additional constraint for assignability of elements is not necessary,
8038
+ and they are sometimes used in a context where the third argument is an
8039
+ input type too. — *end note*]
8040
+
8041
+ ``` cpp
8042
+ template<class MDS1, class MDS2>
8043
+ requires(is-mdspan<MDS1> && is-mdspan<MDS2>)
8044
+ constexpr
8045
+ bool compatible-static-extents(size_t r1, size_t r2) { // exposition only
8046
+ return MDS1::static_extent(r1) == dynamic_extent ||
8047
+ MDS2::static_extent(r2) == dynamic_extent ||
8048
+ MDS1::static_extent(r1) == MDS2::static_extent(r2);
8049
+ }
8050
+
8051
+ template<in-vector In1, in-vector In2, in-vector Out>
8052
+ constexpr bool possibly-addable() { // exposition only
8053
+ return compatible-static-extents<Out, In1>(0, 0) &&
8054
+ compatible-static-extents<Out, In2>(0, 0) &&
8055
+ compatible-static-extents<In1, In2>(0, 0);
8056
+ }
8057
+
8058
+ template<in-matrix In1, in-matrix In2, in-matrix Out>
8059
+ constexpr bool possibly-addable() { // exposition only
8060
+ return compatible-static-extents<Out, In1>(0, 0) &&
8061
+ compatible-static-extents<Out, In1>(1, 1) &&
8062
+ compatible-static-extents<Out, In2>(0, 0) &&
8063
+ compatible-static-extents<Out, In2>(1, 1) &&
8064
+ compatible-static-extents<In1, In2>(0, 0) &&
8065
+ compatible-static-extents<In1, In2>(1, 1);
8066
+ }
8067
+
8068
+ template<in-matrix InMat, in-vector InVec, in-vector OutVec>
8069
+ constexpr bool possibly-multipliable() { // exposition only
8070
+ return compatible-static-extents<OutVec, InMat>(0, 0) &&
8071
+ compatible-static-extents<InMat, InVec>(1, 0);
8072
+ }
8073
+
8074
+ template<in-vector InVec, in-matrix InMat, in-vector OutVec>
8075
+ constexpr bool possibly-multipliable() { // exposition only
8076
+ return compatible-static-extents<OutVec, InMat>(0, 1) &&
8077
+ compatible-static-extents<InMat, InVec>(0, 0);
8078
+ }
8079
+
8080
+ template<in-matrix InMat1, in-matrix InMat2, in-matrix OutMat>
8081
+ constexpr bool possibly-multipliable() { // exposition only
8082
+ return compatible-static-extents<OutMat, InMat1>(0, 0) &&
8083
+ compatible-static-extents<OutMat, InMat2>(1, 1) &&
8084
+ compatible-static-extents<InMat1, InMat2>(1, 0);
8085
+ }
8086
+ ```
8087
+
8088
+ #### Preconditions <a id="linalg.helpers.precond">[[linalg.helpers.precond]]</a>
8089
+
8090
+ [*Note 1*: These exposition-only helper functions use the less
8091
+ constraining input concepts even for the output arguments, because the
8092
+ additional constraint for assignability of elements is not necessary,
8093
+ and they are sometimes used in a context where the third argument is an
8094
+ input type too. — *end note*]
8095
+
8096
+ ``` cpp
8097
+ constexpr bool addable( // exposition only
8098
+ const in-vector auto& in1, const in-vector auto& in2, const in-vector auto& out) {
8099
+ return out.extent(0) == in1.extent(0) && out.extent(0) == in2.extent(0);
8100
+ }
8101
+
8102
+ constexpr bool addable( // exposition only
8103
+ const in-matrix auto& in1, const in-matrix auto& in2, const in-matrix auto& out) {
8104
+ return out.extent(0) == in1.extent(0) && out.extent(1) == in1.extent(1) &&
8105
+ out.extent(0) == in2.extent(0) && out.extent(1) == in2.extent(1);
8106
+ }
8107
+
8108
+ constexpr bool multipliable( // exposition only
8109
+ const in-matrix auto& in_mat, const in-vector auto& in_vec, const in-vector auto& out_vec) {
8110
+ return out_vec.extent(0) == in_mat.extent(0) && in_mat.extent(1) == in_vec.extent(0);
8111
+ }
8112
+
8113
+ constexpr bool multipliable( // exposition only
8114
+ const in-vector auto& in_vec, const in-matrix auto& in_mat, const in-vector auto& out_vec) {
8115
+ return out_vec.extent(0) == in_mat.extent(1) && in_mat.extent(0) == in_vec.extent(0);
8116
+ }
8117
+
8118
+ constexpr bool multipliable( // exposition only
8119
+ const in-matrix auto& in_mat1, const in-matrix auto& in_mat2, const in-matrix auto& out_mat) {
8120
+ return out_mat.extent(0) == in_mat1.extent(0) && out_mat.extent(1) == in_mat2.extent(1) &&
8121
+ in_mat1.extent(1) == in_mat2.extent(0);
8122
+ }
8123
+ ```
8124
+
8125
+ ### Scaled in-place transformation <a id="linalg.scaled">[[linalg.scaled]]</a>
8126
+
8127
+ #### Introduction <a id="linalg.scaled.intro">[[linalg.scaled.intro]]</a>
8128
+
8129
+ The `scaled` function takes a value `alpha` and an `mdspan` `x`, and
8130
+ returns a new read-only `mdspan` that represents the elementwise product
8131
+ of `alpha` with each element of `x`.
8132
+
8133
+ [*Example 1*:
8134
+
8135
+ ``` cpp
8136
+ using Vec = mdspan<double, dextents<size_t, 1>>;
8137
+
8138
+ // z = alpha * x + y
8139
+ void z_equals_alpha_times_x_plus_y(double alpha, Vec x, Vec y, Vec z) {
8140
+ add(scaled(alpha, x), y, z);
8141
+ }
8142
+
8143
+ // z = alpha * x + beta * y
8144
+ void z_equals_alpha_times_x_plus_beta_times_y(double alpha, Vec x, double beta, Vec y, Vec z) {
8145
+ add(scaled(alpha, x), scaled(beta, y), z);
8146
+ }
8147
+ ```
8148
+
8149
+ — *end example*]
8150
+
8151
+ #### Class template `scaled_accessor` <a id="linalg.scaled.scaledaccessor">[[linalg.scaled.scaledaccessor]]</a>
8152
+
8153
+ The class template `scaled_accessor` is an `mdspan` accessor policy
8154
+ which upon access produces scaled elements. It is part of the
8155
+ implementation of `scaled` [[linalg.scaled.scaled]].
8156
+
8157
+ ``` cpp
8158
+ namespace std::linalg {
8159
+ template<class ScalingFactor, class NestedAccessor>
8160
+ class scaled_accessor {
8161
+ public:
8162
+ using element_type =
8163
+ const decltype(declval<ScalingFactor>() * declval<NestedAccessor::element_type>());
8164
+ using reference = remove_const_t<element_type>;
8165
+ using data_handle_type = NestedAccessor::data_handle_type;
8166
+ using offset_policy = scaled_accessor<ScalingFactor, NestedAccessor::offset_policy>;
8167
+
8168
+ constexpr scaled_accessor() = default;
8169
+ template<class OtherNestedAccessor>
8170
+ explicit(!is_convertible_v<OtherNestedAccessor, NestedAccessor>)
8171
+ constexpr scaled_accessor(const scaled_accessor<ScalingFactor,
8172
+ OtherNestedAccessor>& other);
8173
+ constexpr scaled_accessor(const ScalingFactor& s, const NestedAccessor& a);
8174
+
8175
+ constexpr reference access(data_handle_type p, size_t i) const;
8176
+ constexpr offset_policy::data_handle_type offset(data_handle_type p, size_t i) const;
8177
+
8178
+ constexpr const ScalingFactor& scaling_factor() const noexcept { return scaling-factor; }
8179
+ constexpr const NestedAccessor& nested_accessor() const noexcept { return nested-accessor; }
8180
+
8181
+ private:
8182
+ ScalingFactor scaling-factor{}; // exposition only
8183
+ NestedAccessor nested-accessor{}; // exposition only
8184
+ };
8185
+ }
8186
+ ```
8187
+
8188
+ *Mandates:*
8189
+
8190
+ - `element_type` is valid and denotes a type,
8191
+ - `is_copy_constructible_v<reference>` is `true`,
8192
+ - `is_reference_v<element_type>` is `false`,
8193
+ - `ScalingFactor` models `semiregular`, and
8194
+ - `NestedAccessor` meets the accessor policy requirements
8195
+ [[mdspan.accessor.reqmts]].
8196
+
8197
+ ``` cpp
8198
+ template<class OtherNestedAccessor>
8199
+ explicit(!is_convertible_v<OtherNestedAccessor, NestedAccessor>)
8200
+ constexpr scaled_accessor(const scaled_accessor<ScalingFactor, OtherNestedAccessor>& other);
8201
+ ```
8202
+
8203
+ *Constraints:*
8204
+ `is_constructible_v<NestedAccessor, const OtherNestedAccessor&>` is
8205
+ `true`.
8206
+
8207
+ *Effects:*
8208
+
8209
+ - Direct-non-list-initializes *scaling-factor* with
8210
+ `other.scaling_factor()`, and
8211
+ - direct-non-list-initializes *nested-accessor* with
8212
+ `other.nested_accessor()`.
8213
+
8214
+ ``` cpp
8215
+ constexpr scaled_accessor(const ScalingFactor& s, const NestedAccessor& a);
8216
+ ```
8217
+
8218
+ *Effects:*
8219
+
8220
+ - Direct-non-list-initializes *scaling-factor* with `s`, and
8221
+ - direct-non-list-initializes *nested-accessor* with `a`.
8222
+
8223
+ ``` cpp
8224
+ constexpr reference access(data_handle_type p, size_t i) const;
8225
+ ```
8226
+
8227
+ *Returns:*
8228
+
8229
+ ``` cpp
8230
+ scaling_factor() * NestedAccessor::element_type(nested-accessor.access(p, i))
8231
+ ```
8232
+
8233
+ ``` cpp
8234
+ constexpr offset_policy::data_handle_type offset(data_handle_type p, size_t i) const;
8235
+ ```
8236
+
8237
+ *Returns:* *`nested-accessor`*`.offset(p, i)`
8238
+
8239
+ #### Function template `scaled` <a id="linalg.scaled.scaled">[[linalg.scaled.scaled]]</a>
8240
+
8241
+ The `scaled` function template takes a scaling factor `alpha` and an
8242
+ `mdspan` `x`, and returns a new read-only `mdspan` with the same domain
8243
+ as `x`, that represents the elementwise product of `alpha` with each
8244
+ element of `x`.
8245
+
8246
+ ``` cpp
8247
+ template<class ScalingFactor,
8248
+ class ElementType, class Extents, class Layout, class Accessor>
8249
+ constexpr auto scaled(ScalingFactor alpha, mdspan<ElementType, Extents, Layout, Accessor> x);
8250
+ ```
8251
+
8252
+ Let `SA` be `scaled_accessor<ScalingFactor, Accessor>`.
8253
+
8254
+ *Returns:*
8255
+
8256
+ ``` cpp
8257
+ mdspan<typename SA::element_type, Extents, Layout, SA>(x.data_handle(), x.mapping(),
8258
+ SA(alpha, x.accessor()))
8259
+ ```
8260
+
8261
+ [*Example 1*:
8262
+
8263
+ ``` cpp
8264
+ void test_scaled(mdspan<double, extents<int, 10>> x)
8265
+ {
8266
+ auto x_scaled = scaled(5.0, x);
8267
+ for (int i = 0; i < x.extent(0); ++i) {
8268
+ assert(x_scaled[i] == 5.0 * x[i]);
8269
+ }
8270
+ }
8271
+ ```
8272
+
8273
+ — *end example*]
8274
+
8275
+ ### Conjugated in-place transformation <a id="linalg.conj">[[linalg.conj]]</a>
8276
+
8277
+ #### Introduction <a id="linalg.conj.intro">[[linalg.conj.intro]]</a>
8278
+
8279
+ The `conjugated` function takes an `mdspan` `x`, and returns a new
8280
+ read-only `mdspan` `y` with the same domain as `x`, whose elements are
8281
+ the complex conjugates of the corresponding elements of `x`.
8282
+
8283
+ #### Class template `conjugated_accessor` <a id="linalg.conj.conjugatedaccessor">[[linalg.conj.conjugatedaccessor]]</a>
8284
+
8285
+ The class template `conjugated_accessor` is an `mdspan` accessor policy
8286
+ which upon access produces conjugate elements. It is part of the
8287
+ implementation of `conjugated` [[linalg.conj.conjugated]].
8288
+
8289
+ ``` cpp
8290
+ namespace std::linalg {
8291
+ template<class NestedAccessor>
8292
+ class conjugated_accessor {
8293
+ public:
8294
+ using element_type =
8295
+ const decltype(conj-if-needed(declval<NestedAccessor::element_type>()));
8296
+ using reference = remove_const_t<element_type>;
8297
+ using data_handle_type = NestedAccessor::data_handle_type;
8298
+ using offset_policy = conjugated_accessor<NestedAccessor::offset_policy>;
8299
+
8300
+ constexpr conjugated_accessor() = default;
8301
+ constexpr conjugated_accessor(const NestedAccessor& acc);
8302
+ template<class OtherNestedAccessor>
8303
+ explicit(!is_convertible_v<OtherNestedAccessor, NestedAccessor>)
8304
+ constexpr conjugated_accessor(const conjugated_accessor<OtherNestedAccessor>& other);
8305
+
8306
+ constexpr reference access(data_handle_type p, size_t i) const;
8307
+
8308
+ constexpr typename offset_policy::data_handle_type
8309
+ offset(data_handle_type p, size_t i) const;
8310
+
8311
+ constexpr const NestedAccessor& nested_accessor() const noexcept { return nested-accessor_; }
8312
+
8313
+ private:
8314
+ NestedAccessor nested-accessor_{}; // exposition only
8315
+ };
8316
+ }
8317
+ ```
8318
+
8319
+ *Mandates:*
8320
+
8321
+ - `element_type` is valid and denotes a type,
8322
+ - `is_copy_constructible_v<reference>` is `true`,
8323
+ - `is_reference_v<element_type>` is `false`, and
8324
+ - `NestedAccessor` meets the accessor policy requirements
8325
+ [[mdspan.accessor.reqmts]].
8326
+
8327
+ ``` cpp
8328
+ constexpr conjugated_accessor(const NestedAccessor& acc);
8329
+ ```
8330
+
8331
+ *Effects:* Direct-non-list-initializes *nested-accessor\_* with `acc`.
8332
+
8333
+ ``` cpp
8334
+ template<class OtherNestedAccessor>
8335
+ explicit(!is_convertible_v<OtherNestedAccessor, NestedAccessor>)
8336
+ constexpr conjugated_accessor(const conjugated_accessor<OtherNestedAccessor>& other);
8337
+ ```
8338
+
8339
+ *Constraints:*
8340
+ `is_constructible_v<NestedAccessor, const OtherNestedAccessor&>` is
8341
+ `true`.
8342
+
8343
+ *Effects:* Direct-non-list-initializes *nested-accessor\_* with
8344
+ `other.nested_accessor()`.
8345
+
8346
+ ``` cpp
8347
+ constexpr reference access(data_handle_type p, size_t i) const;
8348
+ ```
8349
+
8350
+ *Returns:*
8351
+ *`conj-if-needed`*`(NestedAccessor::element_type(`*`nested-accessor_`*`.access(p, i)))`
8352
+
8353
+ ``` cpp
8354
+ constexpr typename offset_policy::data_handle_type offset(data_handle_type p, size_t i) const;
8355
+ ```
8356
+
8357
+ *Returns:* *`nested-accessor_`*`.offset(p, i)`
8358
+
8359
+ #### Function template `conjugated` <a id="linalg.conj.conjugated">[[linalg.conj.conjugated]]</a>
8360
+
8361
+ ``` cpp
8362
+ template<class ElementType, class Extents, class Layout, class Accessor>
8363
+ constexpr auto conjugated(mdspan<ElementType, Extents, Layout, Accessor> a);
8364
+ ```
8365
+
8366
+ Let `A` be
8367
+
8368
+ - `remove_cvref_t<decltype(a.accessor().nested_accessor())>` if
8369
+ `Accessor` is a specialization of `conjugated_accessor`;
8370
+ - otherwise, `Accessor` if `remove_cvref_t<ElementType>` is an
8371
+ arithmetic type;
8372
+ - otherwise, `conjugated_accessor<Accessor>` if the expression `conj(E)`
8373
+ is valid for any subexpression `E` whose type is
8374
+ `remove_cvref_t<ElementType>` with overload resolution performed in a
8375
+ context that includes the declaration
8376
+ `template<class U> U conj(const U&) = delete;`;
8377
+ - otherwise, `Accessor`.
8378
+
8379
+ *Returns:* Let `MD` be
8380
+ `mdspan<typename A::element_type, Extents, Layout, A>`.
8381
+
8382
+ - `MD(a.data_handle(), a.mapping(), a.accessor().nested_accessor())` if
8383
+ `Accessor` is a specialization of `conjugated_accessor`;
8384
+ - otherwise, `a`, if `is_same_v<A, Accessor>` is `true`;
8385
+ - otherwise,
8386
+ `MD(a.data_handle(), a.mapping(), conjugated_accessor(a.accessor()))`.
8387
+
8388
+ [*Example 1*:
8389
+
8390
+ ``` cpp
8391
+ void test_conjugated_complex(mdspan<complex<double>, extents<int, 10>> a) {
8392
+ auto a_conj = conjugated(a);
8393
+ for (int i = 0; i < a.extent(0); ++i) {
8394
+ assert(a_conj[i] == conj(a[i]);
8395
+ }
8396
+ auto a_conj_conj = conjugated(a_conj);
8397
+ for (int i = 0; i < a.extent(0); ++i) {
8398
+ assert(a_conj_conj[i] == a[i]);
8399
+ }
8400
+ }
8401
+
8402
+ void test_conjugated_real(mdspan<double, extents<int, 10>> a) {
8403
+ auto a_conj = conjugated(a);
8404
+ for (int i = 0; i < a.extent(0); ++i) {
8405
+ assert(a_conj[i] == a[i]);
8406
+ }
8407
+ auto a_conj_conj = conjugated(a_conj);
8408
+ for (int i = 0; i < a.extent(0); ++i) {
8409
+ assert(a_conj_conj[i] == a[i]);
8410
+ }
8411
+ }
8412
+ ```
8413
+
8414
+ — *end example*]
8415
+
8416
+ ### Transpose in-place transformation <a id="linalg.transp">[[linalg.transp]]</a>
8417
+
8418
+ #### Introduction <a id="linalg.transp.intro">[[linalg.transp.intro]]</a>
8419
+
8420
+ `layout_transpose` is an `mdspan` layout mapping policy that swaps the
8421
+ two indices, extents, and strides of any unique `mdspan` layout mapping
8422
+ policy.
8423
+
8424
+ The `transposed` function takes an `mdspan` representing a matrix, and
8425
+ returns a new `mdspan` representing the transpose of the input matrix.
8426
+
8427
+ #### Exposition-only helpers for `layout_transpose` and `transposed` <a id="linalg.transp.helpers">[[linalg.transp.helpers]]</a>
8428
+
8429
+ The exposition-only *`transpose-extents`* function takes an `extents`
8430
+ object representing the extents of a matrix, and returns a new `extents`
8431
+ object representing the extents of the transpose of the matrix.
8432
+
8433
+ The exposition-only alias template `transpose-extents-t<InputExtents>`
8434
+ gives the type of `transpose-extents(e)` for a given `extents` object
8435
+ `e` of type `InputExtents`.
8436
+
8437
+ ``` cpp
8438
+ template<class IndexType, size_t InputExtent0, size_t InputExtent1>
8439
+ constexpr extents<IndexType, InputExtent1, InputExtent0>
8440
+ transpose-extents(const extents<IndexType, InputExtent0, InputExtent1>& in); // exposition only
8441
+ ```
8442
+
8443
+ *Returns:*
8444
+ `extents<IndexType, InputExtent1, InputExtent0>(in.extent(1), in.extent(0))`
8445
+
8446
+ ``` cpp
8447
+ template<class InputExtents>
8448
+ using transpose-extents-t =
8449
+ decltype(transpose-extents(declval<InputExtents>())); // exposition only
8450
+ ```
8451
+
8452
+ #### Class template `layout_transpose` <a id="linalg.transp.layout.transpose">[[linalg.transp.layout.transpose]]</a>
8453
+
8454
+ `layout_transpose` is an `mdspan` layout mapping policy that swaps the
8455
+ two indices, extents, and strides of any `mdspan` layout mapping policy.
8456
+
8457
+ ``` cpp
8458
+ namespace std::linalg {
8459
+ template<class Layout>
8460
+ class layout_transpose {
8461
+ public:
8462
+ using nested_layout_type = Layout;
8463
+
8464
+ template<class Extents>
8465
+ struct mapping {
8466
+ private:
8467
+ using nested-mapping-type =
8468
+ Layout::template mapping<transpose-extents-t<Extents>>; // exposition only
8469
+
8470
+ public:
8471
+ using extents_type = Extents;
8472
+ using index_type = extents_type::index_type;
8473
+ using size_type = extents_type::size_type;
8474
+ using rank_type = extents_type::rank_type;
8475
+ using layout_type = layout_transpose;
8476
+
8477
+ constexpr explicit mapping(const nested-mapping-type&);
8478
+
8479
+ constexpr const extents_type& extents() const noexcept { return extents_; }
8480
+
8481
+ constexpr index_type required_span_size() const
8482
+ { return nested-mapping_.required_span_size(); }
8483
+
8484
+ template<class Index0, class Index1>
8485
+ constexpr index_type operator()(Index0 ind0, Index1 ind1) const
8486
+ { return nested-mapping_(ind1, ind0); }
8487
+
8488
+ constexpr const nested-mapping-type& nested_mapping() const noexcept
8489
+ { return nested-mapping_; }
8490
+
8491
+ static constexpr bool is_always_unique() noexcept
8492
+ { return nested-mapping-type::is_always_unique(); }
8493
+ static constexpr bool is_always_exhaustive() noexcept
8494
+ { return nested-mapping-type::is_always_exhaustive(); }
8495
+ static constexpr bool is_always_strided() noexcept
8496
+ { return nested-mapping-type::is_always_strided(); }
8497
+
8498
+ constexpr bool is_unique() const { return nested-mapping_.is_unique(); }
8499
+ constexpr bool is_exhaustive() const { return nested-mapping_.is_exhaustive(); }
8500
+ constexpr bool is_strided() const { return nested-mapping_.is_strided(); }
8501
+
8502
+ constexpr index_type stride(size_t r) const;
8503
+
8504
+ template<class OtherExtents>
8505
+ friend constexpr bool operator==(const mapping& x, const mapping<OtherExtents>& y);
8506
+
8507
+ private:
8508
+ nested-mapping-type nested-mapping_; // exposition only
8509
+ extents_type extents_; // exposition only
8510
+ };
8511
+ };
8512
+ }
8513
+ ```
8514
+
8515
+ `Layout` shall meet the layout mapping policy requirements
8516
+ [[mdspan.layout.policy.reqmts]].
8517
+
8518
+ *Mandates:*
8519
+
8520
+ - `Extents` is a specialization of `std::extents`, and
8521
+ - `Extents::rank()` equals 2.
8522
+
8523
+ ``` cpp
8524
+ constexpr explicit mapping(const nested-mapping-type& map);
8525
+ ```
8526
+
8527
+ *Effects:*
8528
+
8529
+ - Initializes *nested-mapping\_* with `map`, and
8530
+ - initializes *extents\_* with *`transpose-extents`*`(map.extents())`.
8531
+
8532
+ ``` cpp
8533
+ constexpr index_type stride(size_t r) const;
8534
+ ```
8535
+
8536
+ *Preconditions:*
8537
+
8538
+ - `is_strided()` is `true`, and
8539
+ - `r < 2` is `true`.
8540
+
8541
+ *Returns:* *`nested-mapping_`*`.stride(r == 0 ? 1 : 0)`
8542
+
8543
+ ``` cpp
8544
+ template<class OtherExtents>
8545
+ friend constexpr bool operator==(const mapping& x, const mapping<OtherExtents>& y);
8546
+ ```
8547
+
8548
+ *Constraints:* The expression
8549
+ `x.`*`nested-mapping_`*` == y.`*`nested-mapping_`* is well-formed and
8550
+ its result is convertible to `bool`.
8551
+
8552
+ *Returns:* `x.`*`nested-mapping_`*` == y.`*`nested-mapping_`*.
8553
+
8554
+ #### Function template `transposed` <a id="linalg.transp.transposed">[[linalg.transp.transposed]]</a>
8555
+
8556
+ The `transposed` function takes a rank-2 `mdspan` representing a matrix,
8557
+ and returns a new `mdspan` representing the input matrix’s transpose.
8558
+ The input matrix’s data are not modified, and the returned `mdspan`
8559
+ accesses the input matrix’s data in place.
8560
+
8561
+ ``` cpp
8562
+ template<class ElementType, class Extents, class Layout, class Accessor>
8563
+ constexpr auto transposed(mdspan<ElementType, Extents, Layout, Accessor> a);
8564
+ ```
8565
+
8566
+ *Mandates:* `Extents::rank() == 2` is `true`.
8567
+
8568
+ Let `ReturnExtents` be *`transpose-extents-t`*`<Extents>`. Let `R` be
8569
+ `mdspan<ElementType, ReturnExtents, ReturnLayout, Accessor>`, where
8570
+ `ReturnLayout` is:
8571
+
8572
+ - `layout_right` if `Layout` is `layout_left`;
8573
+ - otherwise, `layout_left` if `Layout` is `layout_right`;
8574
+ - otherwise, `layout_right_padded<PaddingValue>` if `Layout` is
8575
+ `layout_left_padded<PaddingValue>` for some `size_t` value
8576
+ `PaddingValue`;
8577
+ - otherwise, `layout_left_padded<PaddingValue>` if `Layout` is
8578
+ `layout_right_padded<PaddingValue>` for some `size_t` value
8579
+ `PaddingValue`;
8580
+ - otherwise, `layout_stride` if `Layout` is `layout_stride`;
8581
+ - otherwise,
8582
+ `layout_blas_packed<OppositeTriangle, OppositeStorageOrder>`, if
8583
+ `Layout` is `layout_blas_packed<Triangle, StorageOrder>` for some
8584
+ `Triangle` and `StorageOrder`, where
8585
+ - `OppositeTriangle` is
8586
+ ``` cpp
8587
+ conditional_t<is_same_v<Triangle, upper_triangle_t>,
8588
+ lower_triangle_t, upper_triangle_t>
8589
+ ```
8590
+
8591
+ and
8592
+ - `OppositeStorageOrder` is
8593
+ ``` cpp
8594
+ conditional_t<is_same_v<StorageOrder, column_major_t>, row_major_t, column_major_t>
8595
+ ```
8596
+ - otherwise, `NestedLayout` if `Layout` is
8597
+ `layout_transpose<NestedLayout>` for some `NestedLayout`;
8598
+ - otherwise, `layout_transpose<Layout>`.
8599
+
8600
+ *Returns:* With `ReturnMapping` being the type
8601
+ `typename ReturnLayout::template mapping<ReturnExtents>`:
8602
+
8603
+ - if `Layout` is `layout_left`, `layout_right`, or a specialization of
8604
+ `layout_blas_packed`,
8605
+ ``` cpp
8606
+ R(a.data_handle(), ReturnMapping(transpose-extents(a.mapping().extents())),
8607
+ a.accessor())
8608
+ ```
8609
+ - otherwise,
8610
+ ``` cpp
8611
+ R(a.data_handle(), ReturnMapping(transpose-extents(a.mapping().extents()),
8612
+ a.mapping().stride(1)), a.accessor())
8613
+ ```
8614
+
8615
+ if `Layout` is `layout_left_padded<PaddingValue>` for some `size_t`
8616
+ value `PaddingValue`;
8617
+ - otherwise,
8618
+ ``` cpp
8619
+ R(a.data_handle(), ReturnMapping(transpose-extents(a.mapping().extents()),
8620
+ a.mapping().stride(0)), a.accessor())
8621
+ ```
8622
+
8623
+ if `Layout` is `layout_right_padded<PaddingValue>` for some `size_t`
8624
+ value `PaddingValue`;
8625
+ - otherwise, if `Layout` is `layout_stride`,
8626
+ ``` cpp
8627
+ R(a.data_handle(), ReturnMapping(transpose-extents(a.mapping().extents()),
8628
+ array{a.mapping().stride(1), a.mapping().stride(0)}), a.accessor())
8629
+ ```
8630
+ - otherwise, if `Layout` is a specialization of `layout_transpose`,
8631
+ ``` cpp
8632
+ R(a.data_handle(), a.mapping().nested_mapping(), a.accessor())
8633
+ ```
8634
+ - otherwise,
8635
+ ``` cpp
8636
+ R(a.data_handle(), ReturnMapping(a.mapping()), a.accessor())
8637
+ ```
8638
+
8639
+ [*Example 1*:
8640
+
8641
+ ``` cpp
8642
+ void test_transposed(mdspan<double, extents<size_t, 3, 4>> a) {
8643
+ const auto num_rows = a.extent(0);
8644
+ const auto num_cols = a.extent(1);
8645
+
8646
+ auto a_t = transposed(a);
8647
+ assert(num_rows == a_t.extent(1));
8648
+ assert(num_cols == a_t.extent(0));
8649
+ assert(a.stride(0) == a_t.stride(1));
8650
+ assert(a.stride(1) == a_t.stride(0));
8651
+
8652
+ for (size_t row = 0; row < num_rows; ++row) {
8653
+ for (size_t col = 0; col < num_rows; ++col) {
8654
+ assert(a[row, col] == a_t[col, row]);
8655
+ }
8656
+ }
8657
+
8658
+ auto a_t_t = transposed(a_t);
8659
+ assert(num_rows == a_t_t.extent(0));
8660
+ assert(num_cols == a_t_t.extent(1));
8661
+ assert(a.stride(0) == a_t_t.stride(0));
8662
+ assert(a.stride(1) == a_t_t.stride(1));
8663
+
8664
+ for (size_t row = 0; row < num_rows; ++row) {
8665
+ for (size_t col = 0; col < num_rows; ++col) {
8666
+ assert(a[row, col] == a_t_t[row, col]);
8667
+ }
8668
+ }
8669
+ }
8670
+ ```
8671
+
8672
+ — *end example*]
8673
+
8674
+ ### Conjugate transpose in-place transform <a id="linalg.conjtransposed">[[linalg.conjtransposed]]</a>
8675
+
8676
+ The `conjugate_transposed` function returns a conjugate transpose view
8677
+ of an object. This combines the effects of `transposed` and
8678
+ `conjugated`.
8679
+
8680
+ ``` cpp
8681
+ template<class ElementType, class Extents, class Layout, class Accessor>
8682
+ constexpr auto conjugate_transposed(mdspan<ElementType, Extents, Layout, Accessor> a);
8683
+ ```
8684
+
8685
+ *Effects:* Equivalent to: `return conjugated(transposed(a));`
8686
+
8687
+ [*Example 1*:
8688
+
8689
+ ``` cpp
8690
+ void test_conjugate_transposed(mdspan<complex<double>, extents<size_t, 3, 4>> a) {
8691
+ const auto num_rows = a.extent(0);
8692
+ const auto num_cols = a.extent(1);
8693
+
8694
+ auto a_ct = conjugate_transposed(a);
8695
+ assert(num_rows == a_ct.extent(1));
8696
+ assert(num_cols == a_ct.extent(0));
8697
+ assert(a.stride(0) == a_ct.stride(1));
8698
+ assert(a.stride(1) == a_ct.stride(0));
8699
+
8700
+ for (size_t row = 0; row < num_rows; ++row) {
8701
+ for (size_t col = 0; col < num_rows; ++col) {
8702
+ assert(a[row, col] == conj(a_ct[col, row]));
8703
+ }
8704
+ }
8705
+
8706
+ auto a_ct_ct = conjugate_transposed(a_ct);
8707
+ assert(num_rows == a_ct_ct.extent(0));
8708
+ assert(num_cols == a_ct_ct.extent(1));
8709
+ assert(a.stride(0) == a_ct_ct.stride(0));
8710
+ assert(a.stride(1) == a_ct_ct.stride(1));
8711
+
8712
+ for (size_t row = 0; row < num_rows; ++row) {
8713
+ for (size_t col = 0; col < num_rows; ++col) {
8714
+ assert(a[row, col] == a_ct_ct[row, col]);
8715
+ assert(conj(a_ct[col, row]) == a_ct_ct[row, col]);
8716
+ }
8717
+ }
8718
+ }
8719
+ ```
8720
+
8721
+ — *end example*]
8722
+
8723
+ ### Algorithm requirements based on template parameter name <a id="linalg.algs.reqs">[[linalg.algs.reqs]]</a>
8724
+
8725
+ Throughout [[linalg.algs.blas1]], [[linalg.algs.blas2]], and
8726
+ [[linalg.algs.blas3]], where the template parameters are not
8727
+ constrained, the names of template parameters are used to express the
8728
+ following constraints.
8729
+
8730
+ - `is_execution_policy<ExecutionPolicy>::value` is `true`
8731
+ [[execpol.type]].
8732
+ - `Real` is any type such that `complex<Real>` is specified
8733
+ [[complex.numbers.general]].
8734
+ - `Triangle` is either `upper_triangle_t` or `lower_triangle_t`.
8735
+ - `DiagonalStorage` is either `implicit_unit_diagonal_t` or
8736
+ `explicit_diagonal_t`.
8737
+
8738
+ [*Note 1*: Function templates that have a template parameter named
8739
+ `ExecutionPolicy` are parallel algorithms
8740
+ [[algorithms.parallel.defns]]. — *end note*]
8741
+
8742
+ ### BLAS 1 algorithms <a id="linalg.algs.blas1">[[linalg.algs.blas1]]</a>
8743
+
8744
+ #### Complexity <a id="linalg.algs.blas1.complexity">[[linalg.algs.blas1.complexity]]</a>
8745
+
8746
+ *Complexity:* All algorithms in [[linalg.algs.blas1]] with `mdspan`
8747
+ parameters perform a count of `mdspan` array accesses and arithmetic
8748
+ operations that is linear in the maximum product of extents of any
8749
+ `mdspan` parameter.
8750
+
8751
+ #### Givens rotations <a id="linalg.algs.blas1.givens">[[linalg.algs.blas1.givens]]</a>
8752
+
8753
+ ##### Compute Givens rotation <a id="linalg.algs.blas1.givens.lartg">[[linalg.algs.blas1.givens.lartg]]</a>
8754
+
8755
+ ``` cpp
8756
+ template<class Real>
8757
+ setup_givens_rotation_result<Real> setup_givens_rotation(Real a, Real b) noexcept;
8758
+
8759
+ template<class Real>
8760
+ setup_givens_rotation_result<complex<Real>>
8761
+ setup_givens_rotation(complex<Real> a, complex<Real> b) noexcept;
8762
+ ```
8763
+
8764
+ These functions compute the Givens plane rotation represented by the two
8765
+ values c and s such that the 2 x 2 system of equations
8766
+ $$\left[ \begin{matrix}
8767
+ c & s \\
8768
+ -\overline{s} & c \\
8769
+ \end{matrix} \right]
8770
+ \cdot
8771
+ \left[ \begin{matrix}
8772
+ a \\
8773
+ b \\
8774
+ \end{matrix} \right]
8775
+ =
8776
+ \left[ \begin{matrix}
8777
+ r \\
8778
+ 0 \\
8779
+ \end{matrix} \right]$$
8780
+
8781
+ holds, where c is always a real scalar, and c² + |s|^2 = 1. That is, c
8782
+ and s represent a 2 x 2 matrix, that when multiplied by the right by the
8783
+ input vector whose components are a and b, produces a result vector
8784
+ whose first component r is the Euclidean norm of the input vector, and
8785
+ whose second component is zero.
8786
+
8787
+ [*Note 1*: These functions correspond to the LAPACK function
8788
+ `xLARTG`. — *end note*]
8789
+
8790
+ *Returns:* `c, s, r`, where `c` and `s` form the Givens plane rotation
8791
+ corresponding to the input `a` and `b`, and `r` is the Euclidean norm of
8792
+ the two-component vector formed by `a` and `b`.
8793
+
8794
+ ##### Apply a computed Givens rotation to vectors <a id="linalg.algs.blas1.givens.rot">[[linalg.algs.blas1.givens.rot]]</a>
8795
+
8796
+ ``` cpp
8797
+ template<inout-vector InOutVec1, inout-vector InOutVec2, class Real>
8798
+ void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, Real s);
8799
+ template<class ExecutionPolicy, inout-vector InOutVec1, inout-vector InOutVec2, class Real>
8800
+ void apply_givens_rotation(ExecutionPolicy&& exec,
8801
+ InOutVec1 x, InOutVec2 y, Real c, Real s);
8802
+ template<inout-vector InOutVec1, inout-vector InOutVec2, class Real>
8803
+ void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, complex<Real> s);
8804
+ template<class ExecutionPolicy, inout-vector InOutVec1, inout-vector InOutVec2, class Real>
8805
+ void apply_givens_rotation(ExecutionPolicy&& exec,
8806
+ InOutVec1 x, InOutVec2 y, Real c, complex<Real> s);
8807
+ ```
8808
+
8809
+ [*Note 2*: These functions correspond to the BLAS function
8810
+ `xROT`. — *end note*]
8811
+
8812
+ *Mandates:* *`compatible-static-extents`*`<InOutVec1, InOutVec2>(0, 0)`
8813
+ is `true`.
8814
+
8815
+ *Preconditions:* `x.extent(0)` equals `y.extent(0)`.
8816
+
8817
+ *Effects:* Applies the plane rotation specified by `c` and `s` to the
8818
+ input vectors `x` and `y`, as if the rotation were a 2 x 2 matrix and
8819
+ the input vectors were successive rows of a matrix with two rows.
8820
+
8821
+ #### Swap matrix or vector elements <a id="linalg.algs.blas1.swap">[[linalg.algs.blas1.swap]]</a>
8822
+
8823
+ ``` cpp
8824
+ template<inout-object InOutObj1, inout-object InOutObj2>
8825
+ void swap_elements(InOutObj1 x, InOutObj2 y);
8826
+ template<class ExecutionPolicy, inout-object InOutObj1, inout-object InOutObj2>
8827
+ void swap_elements(ExecutionPolicy&& exec, InOutObj1 x, InOutObj2 y);
8828
+ ```
8829
+
8830
+ [*Note 1*: These functions correspond to the BLAS function
8831
+ `xSWAP`. — *end note*]
8832
+
8833
+ *Constraints:* `x.rank()` equals `y.rank()`.
8834
+
8835
+ *Mandates:* For all `r` in the range [0, `x.rank()`),
8836
+
8837
+ ``` cpp
8838
+ compatible-static-extents<InOutObj1, InOutObj2>(r, r)
8839
+ ```
8840
+
8841
+ is `true`.
8842
+
8843
+ *Preconditions:* `x.extents()` equals `y.extents()`.
8844
+
8845
+ *Effects:* Swaps all corresponding elements of `x` and `y`.
8846
+
8847
+ #### Multiply the elements of an object in place by a scalar <a id="linalg.algs.blas1.scal">[[linalg.algs.blas1.scal]]</a>
8848
+
8849
+ ``` cpp
8850
+ template<class Scalar, inout-object InOutObj>
8851
+ void scale(Scalar alpha, InOutObj x);
8852
+ template<class ExecutionPolicy, class Scalar, inout-object InOutObj>
8853
+ void scale(ExecutionPolicy&& exec, Scalar alpha, InOutObj x);
8854
+ ```
8855
+
8856
+ [*Note 1*: These functions correspond to the BLAS function
8857
+ `xSCAL`. — *end note*]
8858
+
8859
+ *Effects:* Overwrites x with the result of computing the elementwise
8860
+ multiplication α x, where the scalar α is `alpha`.
8861
+
8862
+ #### Copy elements of one matrix or vector into another <a id="linalg.algs.blas1.copy">[[linalg.algs.blas1.copy]]</a>
8863
+
8864
+ ``` cpp
8865
+ template<in-object InObj, out-object OutObj>
8866
+ void copy(InObj x, OutObj y);
8867
+ template<class ExecutionPolicy, in-object InObj, out-object OutObj>
8868
+ void copy(ExecutionPolicy&& exec, InObj x, OutObj y);
8869
+ ```
8870
+
8871
+ [*Note 1*: These functions correspond to the BLAS function
8872
+ `xCOPY`. — *end note*]
8873
+
8874
+ *Constraints:* `x.rank()` equals `y.rank()`.
8875
+
8876
+ *Mandates:* For all `r` in the range [ 0, `x.rank()`),
8877
+
8878
+ ``` cpp
8879
+ compatible-static-extents<InObj, OutObj>(r, r)
8880
+ ```
8881
+
8882
+ is `true`.
8883
+
8884
+ *Preconditions:* `x.extents()` equals `y.extents()`.
8885
+
8886
+ *Effects:* Assigns each element of x to the corresponding element of y.
8887
+
8888
+ #### Add vectors or matrices elementwise <a id="linalg.algs.blas1.add">[[linalg.algs.blas1.add]]</a>
8889
+
8890
+ ``` cpp
8891
+ template<in-object InObj1, in-object InObj2, out-object OutObj>
8892
+ void add(InObj1 x, InObj2 y, OutObj z);
8893
+ template<class ExecutionPolicy, in-object InObj1, in-object InObj2, out-object OutObj>
8894
+ void add(ExecutionPolicy&& exec,
8895
+ InObj1 x, InObj2 y, OutObj z);
8896
+ ```
8897
+
8898
+ [*Note 1*: These functions correspond to the BLAS function
8899
+ `xAXPY`. — *end note*]
8900
+
8901
+ *Constraints:* `x.rank()`, `y.rank()`, and `z.rank()` are all equal.
8902
+
8903
+ *Mandates:* *`possibly-addable`*`<InObj1, InObj2, OutObj>()` is `true`.
8904
+
8905
+ *Preconditions:* *`addable`*`(x,y,z)` is `true`.
8906
+
8907
+ *Effects:* Computes z = x + y.
8908
+
8909
+ *Remarks:* `z` may alias `x` or `y`.
8910
+
8911
+ #### Dot product of two vectors <a id="linalg.algs.blas1.dot">[[linalg.algs.blas1.dot]]</a>
8912
+
8913
+ [*Note 1*: The functions in this section correspond to the BLAS
8914
+ functions `xDOT`, `xDOTU`, and `xDOTC`. — *end note*]
8915
+
8916
+ The following elements apply to all functions in
8917
+ [[linalg.algs.blas1.dot]].
8918
+
8919
+ *Mandates:* `compatible-static-extents<InVec1, InVec2>(0, 0)` is `true`.
8920
+
8921
+ *Preconditions:* `v1.extent(0)` equals `v2.extent(0)`.
8922
+
8923
+ ``` cpp
8924
+ template<in-vector InVec1, in-vector InVec2, class Scalar>
8925
+ Scalar dot(InVec1 v1, InVec2 v2, Scalar init);
8926
+ template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2, class Scalar>
8927
+ Scalar dot(ExecutionPolicy&& exec,
8928
+ InVec1 v1, InVec2 v2, Scalar init);
8929
+ ```
8930
+
8931
+ These functions compute a non-conjugated dot product with an explicitly
8932
+ specified result type.
8933
+
8934
+ *Returns:* Let `N` be `v1.extent(0)`.
8935
+
8936
+ - `init` if `N` is zero;
8937
+ - otherwise, *GENERALIZED_SUM*(plus\<\>(), init, v1\[0\]\*v2\[0\], …,
8938
+ v1\[N-1\]\*v2\[N-1\]).
8939
+
8940
+ *Remarks:* If `InVec1::value_type`, `InVec2::value_type`, and `Scalar`
8941
+ are all floating-point types or specializations of `complex`, and if
8942
+ `Scalar` has higher precision than `InVec1::value_type` or
8943
+ `InVec2::value_type`, then intermediate terms in the sum use `Scalar`’s
8944
+ precision or greater.
8945
+
8946
+ ``` cpp
8947
+ template<in-vector InVec1, in-vector InVec2>
8948
+ auto dot(InVec1 v1, InVec2 v2);
8949
+ template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2>
8950
+ auto dot(ExecutionPolicy&& exec,
8951
+ InVec1 v1, InVec2 v2);
8952
+ ```
8953
+
8954
+ These functions compute a non-conjugated dot product with a default
8955
+ result type.
8956
+
8957
+ *Effects:* Let `T` be
8958
+ `decltype(declval<typename InVec1::value_type>() * declval<typename InVec2::value_type>())`.
8959
+ Then,
8960
+
8961
+ - the two-parameter overload is equivalent to:
8962
+ ``` cpp
8963
+ return dot(v1, v2, T{});
8964
+ ```
8965
+
8966
+ and
8967
+ - the three-parameter overload is equivalent to:
8968
+ ``` cpp
8969
+ return dot(std::forward<ExecutionPolicy>(exec), v1, v2, T{});
8970
+ ```
8971
+
8972
+ ``` cpp
8973
+ template<in-vector InVec1, in-vector InVec2, class Scalar>
8974
+ Scalar dotc(InVec1 v1, InVec2 v2, Scalar init);
8975
+ template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2, class Scalar>
8976
+ Scalar dotc(ExecutionPolicy&& exec,
8977
+ InVec1 v1, InVec2 v2, Scalar init);
8978
+ ```
8979
+
8980
+ These functions compute a conjugated dot product with an explicitly
8981
+ specified result type.
8982
+
8983
+ *Effects:*
8984
+
8985
+ - The three-parameter overload is equivalent to:
8986
+ ``` cpp
8987
+ return dot(conjugated(v1), v2, init);
8988
+ ```
8989
+
8990
+ and
8991
+ - the four-parameter overload is equivalent to:
8992
+ ``` cpp
8993
+ return dot(std::forward<ExecutionPolicy>(exec), conjugated(v1), v2, init);
8994
+ ```
8995
+
8996
+ ``` cpp
8997
+ template<in-vector InVec1, in-vector InVec2>
8998
+ auto dotc(InVec1 v1, InVec2 v2);
8999
+ template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2>
9000
+ auto dotc(ExecutionPolicy&& exec,
9001
+ InVec1 v1, InVec2 v2);
9002
+ ```
9003
+
9004
+ These functions compute a conjugated dot product with a default result
9005
+ type.
9006
+
9007
+ *Effects:* Let `T` be
9008
+ `decltype(`*`conj-if-needed`*`(declval<typename InVec1::value_type>()) * declval<typename InVec2::value_type>())`.
9009
+ Then,
9010
+
9011
+ - the two-parameter overload is equivalent to:
9012
+ ``` cpp
9013
+ return dotc(v1, v2, T{});
9014
+ ```
9015
+
9016
+ and
9017
+ - the three-parameter overload is equivalent to
9018
+ ``` cpp
9019
+ return dotc(std::forward<ExecutionPolicy>(exec), v1, v2, T{});
9020
+ ```
9021
+
9022
+ #### Scaled sum of squares of a vector’s elements <a id="linalg.algs.blas1.ssq">[[linalg.algs.blas1.ssq]]</a>
9023
+
9024
+ ``` cpp
9025
+ template<in-vector InVec, class Scalar>
9026
+ sum_of_squares_result<Scalar> vector_sum_of_squares(InVec v, sum_of_squares_result<Scalar> init);
9027
+ template<class ExecutionPolicy, in-vector InVec, class Scalar>
9028
+ sum_of_squares_result<Scalar> vector_sum_of_squares(ExecutionPolicy&& exec,
9029
+ InVec v, sum_of_squares_result<Scalar> init);
9030
+ ```
9031
+
9032
+ [*Note 1*: These functions correspond to the LAPACK function
9033
+ `xLASSQ`. — *end note*]
9034
+
9035
+ *Mandates:*
9036
+ `decltype(`*`abs-if-needed`*`(declval<typename InVec::value_type>()))`
9037
+ is convertible to `Scalar`.
9038
+
9039
+ *Effects:* Returns a value `result` such that
9040
+
9041
+ - `result.scaling_factor` is the maximum of `init.scaling_factor` and
9042
+ *`abs-if-needed`*`(x[i])` for all `i` in the domain of `v`; and
9043
+ - let `s2init` be
9044
+ ``` cpp
9045
+ init.scaling_factor * init.scaling_factor * init.scaled_sum_of_squares
9046
+ ```
9047
+
9048
+ then
9049
+ `result.scaling_factor * result.scaling_factor * result.scaled_sum_of_squares`
9050
+ equals the sum of `s2init` and the squares of
9051
+ *`abs-if-needed`*`(x[i])` for all `i` in the domain of `v`.
9052
+
9053
+ *Remarks:* If `InVec::value_type`, and `Scalar` are all floating-point
9054
+ types or specializations of `complex`, and if `Scalar` has higher
9055
+ precision than `InVec::value_type`, then intermediate terms in the sum
9056
+ use `Scalar`’s precision or greater.
9057
+
9058
+ #### Euclidean norm of a vector <a id="linalg.algs.blas1.nrm2">[[linalg.algs.blas1.nrm2]]</a>
9059
+
9060
+ ``` cpp
9061
+ template<in-vector InVec, class Scalar>
9062
+ Scalar vector_two_norm(InVec v, Scalar init);
9063
+ template<class ExecutionPolicy, in-vector InVec, class Scalar>
9064
+ Scalar vector_two_norm(ExecutionPolicy&& exec, InVec v, Scalar init);
9065
+ ```
9066
+
9067
+ [*Note 1*: These functions correspond to the BLAS function
9068
+ `xNRM2`. — *end note*]
9069
+
9070
+ *Mandates:* Let `a` be
9071
+ *`abs-if-needed`*`(declval<typename InVec::value_type>())`. Then,
9072
+ `decltype(init + a * a` is convertible to `Scalar`.
9073
+
9074
+ *Returns:* The square root of the sum of the square of `init` and the
9075
+ squares of the absolute values of the elements of `v`.
9076
+
9077
+ [*Note 2*: For `init` equal to zero, this is the Euclidean norm (also
9078
+ called 2-norm) of the vector `v`. — *end note*]
9079
+
9080
+ *Remarks:* If `InVec::value_type`, and `Scalar` are all floating-point
9081
+ types or specializations of `complex`, and if `Scalar` has higher
9082
+ precision than `InVec::value_type`, then intermediate terms in the sum
9083
+ use `Scalar`’s precision or greater.
9084
+
9085
+ [*Note 3*: An implementation of this function for floating-point types
9086
+ `T` can use the `scaled_sum_of_squares` result from
9087
+ `vector_sum_of_squares(x, {.scaling_factor=1.0, .scaled_sum_of_squares=init})`. — *end note*]
9088
+
9089
+ ``` cpp
9090
+ template<in-vector InVec>
9091
+ auto vector_two_norm(InVec v);
9092
+ template<class ExecutionPolicy, in-vector InVec>
9093
+ auto vector_two_norm(ExecutionPolicy&& exec, InVec v);
9094
+ ```
9095
+
9096
+ *Effects:* Let `a` be
9097
+ *`abs-if-needed`*`(declval<typename InVec::value_type>())`. Let `T` be
9098
+ `decltype(a * a)`. Then,
9099
+
9100
+ - the one-parameter overload is equivalent to:
9101
+ ``` cpp
9102
+ return vector_two_norm(v, T{});
9103
+ ```
9104
+
9105
+ and
9106
+ - the two-parameter overload is equivalent to:
9107
+ ``` cpp
9108
+ return vector_two_norm(std::forward<ExecutionPolicy>(exec), v, T{});
9109
+ ```
9110
+
9111
+ #### Sum of absolute values of vector elements <a id="linalg.algs.blas1.asum">[[linalg.algs.blas1.asum]]</a>
9112
+
9113
+ ``` cpp
9114
+ template<in-vector InVec, class Scalar>
9115
+ Scalar vector_abs_sum(InVec v, Scalar init);
9116
+ template<class ExecutionPolicy, in-vector InVec, class Scalar>
9117
+ Scalar vector_abs_sum(ExecutionPolicy&& exec, InVec v, Scalar init);
9118
+ ```
9119
+
9120
+ [*Note 1*: These functions correspond to the BLAS functions `SASUM`,
9121
+ `DASUM`, `SCASUM`, and `DZASUM`. — *end note*]
9122
+
9123
+ *Mandates:*
9124
+
9125
+ ``` cpp
9126
+ decltype(init + abs-if-needed(real-if-needed(declval<typename InVec::value_type>())) +
9127
+ abs-if-needed(imag-if-needed(declval<typename InVec::value_type>())))
9128
+ ```
9129
+
9130
+ is convertible to `Scalar`.
9131
+
9132
+ *Returns:* Let `N` be `v.extent(0)`.
9133
+
9134
+ - `init` if `N` is zero;
9135
+ - otherwise, if `InVec::value_type` is an arithmetic type,
9136
+ ``` cpp
9137
+ GENERALIZED_SUM(plus<>(), init, abs-if-needed(v[0]), …, abs-if-needed(v[N-1]))
9138
+ ```
9139
+ - otherwise,
9140
+ ``` cpp
9141
+ GENERALIZED_SUM(plus<>(), init,
9142
+ abs-if-needed(real-if-needed(v[0])) + abs-if-needed(imag-if-needed(v[0])),
9143
+ …,
9144
+ abs-if-needed(real-if-needed(v[N-1])) + abs-if-needed(imag-if-needed(v[N-1])))
9145
+ ```
9146
+
9147
+ *Remarks:* If `InVec::value_type` and `Scalar` are all floating-point
9148
+ types or specializations of `complex`, and if `Scalar` has higher
9149
+ precision than `InVec::value_type`, then intermediate terms in the sum
9150
+ use `Scalar`’s precision or greater.
9151
+
9152
+ ``` cpp
9153
+ template<in-vector InVec>
9154
+ auto vector_abs_sum(InVec v);
9155
+ template<class ExecutionPolicy, in-vector InVec>
9156
+ auto vector_abs_sum(ExecutionPolicy&& exec, InVec v);
9157
+ ```
9158
+
9159
+ *Effects:* Let `T` be `typename InVec::value_type`. Then,
9160
+
9161
+ - the one-parameter overload is equivalent to:
9162
+ ``` cpp
9163
+ return vector_abs_sum(v, T{});
9164
+ ```
9165
+
9166
+ and
9167
+ - the two-parameter overload is equivalent to:
9168
+ ``` cpp
9169
+ return vector_abs_sum(std::forward<ExecutionPolicy>(exec), v, T{});
9170
+ ```
9171
+
9172
+ #### Index of maximum absolute value of vector elements <a id="linalg.algs.blas1.iamax">[[linalg.algs.blas1.iamax]]</a>
9173
+
9174
+ ``` cpp
9175
+ template<in-vector InVec>
9176
+ typename InVec::extents_type vector_idx_abs_max(InVec v);
9177
+ template<class ExecutionPolicy, in-vector InVec>
9178
+ typename InVec::extents_type vector_idx_abs_max(ExecutionPolicy&& exec, InVec v);
9179
+ ```
9180
+
9181
+ [*Note 1*: These functions correspond to the BLAS function
9182
+ `IxAMAX`. — *end note*]
9183
+
9184
+ Let `T` be
9185
+
9186
+ ``` cpp
9187
+ decltype(abs-if-needed(real-if-needed(declval<typename InVec::value_type>())) +
9188
+ abs-if-needed(imag-if-needed(declval<typename InVec::value_type>())))
9189
+ ```
9190
+
9191
+ *Mandates:* `declval<T>() < declval<T>()` is a valid expression.
9192
+
9193
+ *Returns:*
9194
+
9195
+ - `numeric_limits<typename InVec::size_type>::max()` if `v` has zero
9196
+ elements;
9197
+ - otherwise, the index of the first element of `v` having largest
9198
+ absolute value, if `InVec::value_type` is an arithmetic type;
9199
+ - otherwise, the index of the first element `vₑ` of `v` for which
9200
+ ``` cpp
9201
+ abs-if-needed(real-if-needed($v_e$)) + abs-if-needed(imag-if-needed($v_e$))
9202
+ ```
9203
+
9204
+ has the largest value.
9205
+
9206
+ #### Frobenius norm of a matrix <a id="linalg.algs.blas1.matfrobnorm">[[linalg.algs.blas1.matfrobnorm]]</a>
9207
+
9208
+ [*Note 1*: These functions exist in the BLAS standard but are not part
9209
+ of the reference implementation. — *end note*]
9210
+
9211
+ ``` cpp
9212
+ template<in-matrix InMat, class Scalar>
9213
+ Scalar matrix_frob_norm(InMat A, Scalar init);
9214
+ template<class ExecutionPolicy, in-matrix InMat, class Scalar>
9215
+ Scalar matrix_frob_norm(ExecutionPolicy&& exec, InMat A, Scalar init);
9216
+ ```
9217
+
9218
+ *Mandates:* Let `a` be
9219
+ *`abs-if-needed`*`(declval<typename InMat::value_type>())`. Then,
9220
+ `decltype(init + a * a)` is convertible to `Scalar`.
9221
+
9222
+ *Returns:* The square root of the sum of squares of `init` and the
9223
+ absolute values of the elements of `A`.
9224
+
9225
+ [*Note 1*: For `init` equal to zero, this is the Frobenius norm of the
9226
+ matrix `A`. — *end note*]
9227
+
9228
+ *Remarks:* If `InMat::value_type` and `Scalar` are all floating-point
9229
+ types or specializations of `complex`, and if `Scalar` has higher
9230
+ precision than `InMat::value_type`, then intermediate terms in the sum
9231
+ use `Scalar`’s precision or greater.
9232
+
9233
+ ``` cpp
9234
+ template<in-matrix InMat>
9235
+ auto matrix_frob_norm(InMat A);
9236
+ template<class ExecutionPolicy, in-matrix InMat>
9237
+ auto matrix_frob_norm(ExecutionPolicy&& exec, InMat A);
9238
+ ```
9239
+
9240
+ *Effects:* Let `a` be
9241
+ *`abs-if-needed`*`(declval<typename InMat::value_type>())`. Let `T` be
9242
+ `decltype(a * a)`. Then,
9243
+
9244
+ - the one-parameter overload is equivalent to:
9245
+ ``` cpp
9246
+ return matrix_frob_norm(A, T{});
9247
+ ```
9248
+
9249
+ and
9250
+ - the two-parameter overload is equivalent to:
9251
+ ``` cpp
9252
+ return matrix_frob_norm(std::forward<ExecutionPolicy>(exec), A, T{});
9253
+ ```
9254
+
9255
+ #### One norm of a matrix <a id="linalg.algs.blas1.matonenorm">[[linalg.algs.blas1.matonenorm]]</a>
9256
+
9257
+ [*Note 1*: These functions exist in the BLAS standard but are not part
9258
+ of the reference implementation. — *end note*]
9259
+
9260
+ ``` cpp
9261
+ template<in-matrix InMat, class Scalar>
9262
+ Scalar matrix_one_norm(InMat A, Scalar init);
9263
+ template<class ExecutionPolicy, in-matrix InMat, class Scalar>
9264
+ Scalar matrix_one_norm(ExecutionPolicy&& exec, InMat A, Scalar init);
9265
+ ```
9266
+
9267
+ *Mandates:*
9268
+ `decltype(`*`abs-if-needed`*`(declval<typename InMat::value_type>()))`
9269
+ is convertible to `Scalar`.
9270
+
9271
+ *Returns:*
9272
+
9273
+ - `init` if `A.extent(1)` is zero;
9274
+ - otherwise, the sum of `init` and the one norm of the matrix A.
9275
+
9276
+ [*Note 1*: The one norm of the matrix `A` is the maximum over all
9277
+ columns of `A`, of the sum of the absolute values of the elements of the
9278
+ column. — *end note*]
9279
+
9280
+ *Remarks:* If `InMat::value_type` and `Scalar` are all floating-point
9281
+ types or specializations of `complex`, and if `Scalar` has higher
9282
+ precision than `InMat::value_type`, then intermediate terms in the sum
9283
+ use `Scalar`’s precision or greater.
9284
+
9285
+ ``` cpp
9286
+ template<in-matrix InMat>
9287
+ auto matrix_one_norm(InMat A);
9288
+ template<class ExecutionPolicy, in-matrix InMat>
9289
+ auto matrix_one_norm(ExecutionPolicy&& exec, InMat A);
9290
+ ```
9291
+
9292
+ *Effects:* Let `T` be
9293
+ `decltype(`*`abs-if-needed`*`(declval<typename InMat::value_type>())`.
9294
+ Then,
9295
+
9296
+ - the one-parameter overload is equivalent to:
9297
+ ``` cpp
9298
+ return matrix_one_norm(A, T{});
9299
+ ```
9300
+
9301
+ and
9302
+ - the two-parameter overload is equivalent to:
9303
+ ``` cpp
9304
+ return matrix_one_norm(std::forward<ExecutionPolicy>(exec), A, T{});
9305
+ ```
9306
+
9307
+ #### Infinity norm of a matrix <a id="linalg.algs.blas1.matinfnorm">[[linalg.algs.blas1.matinfnorm]]</a>
9308
+
9309
+ [*Note 1*: These functions exist in the BLAS standard but are not part
9310
+ of the reference implementation. — *end note*]
9311
+
9312
+ ``` cpp
9313
+ template<in-matrix InMat, class Scalar>
9314
+ Scalar matrix_inf_norm(InMat A, Scalar init);
9315
+ template<class ExecutionPolicy, in-matrix InMat, class Scalar>
9316
+ Scalar matrix_inf_norm(ExecutionPolicy&& exec, InMat A, Scalar init);
9317
+ ```
9318
+
9319
+ *Mandates:*
9320
+ `decltype(`*`abs-if-needed`*`(declval<typename InMat::value_type>()))`
9321
+ is convertible to `Scalar`.
9322
+
9323
+ *Returns:*
9324
+
9325
+ - `init` if `A.extent(0)` is zero;
9326
+ - otherwise, the sum of `init` and the infinity norm of the matrix `A`.
9327
+
9328
+ [*Note 1*: The infinity norm of the matrix `A` is the maximum over all
9329
+ rows of `A`, of the sum of the absolute values of the elements of the
9330
+ row. — *end note*]
9331
+
9332
+ *Remarks:* If `InMat::value_type` and `Scalar` are all floating-point
9333
+ types or specializations of `complex`, and if `Scalar` has higher
9334
+ precision than `InMat::value_type`, then intermediate terms in the sum
9335
+ use `Scalar`’s precision or greater.
9336
+
9337
+ ``` cpp
9338
+ template<in-matrix InMat>
9339
+ auto matrix_inf_norm(InMat A);
9340
+ template<class ExecutionPolicy, in-matrix InMat>
9341
+ auto matrix_inf_norm(ExecutionPolicy&& exec, InMat A);
9342
+ ```
9343
+
9344
+ *Effects:* Let `T` be
9345
+ `decltype(`*`abs-if-needed`*`(declval<typename InMat::value_type>())`.
9346
+ Then,
9347
+
9348
+ - the one-parameter overload is equivalent to:
9349
+ ``` cpp
9350
+ return matrix_inf_norm(A, T{});
9351
+ ```
9352
+
9353
+ and
9354
+ - the two-parameter overload is equivalent to:
9355
+ ``` cpp
9356
+ return matrix_inf_norm(std::forward<ExecutionPolicy>(exec), A, T{});
9357
+ ```
9358
+
9359
+ ### BLAS 2 algorithms <a id="linalg.algs.blas2">[[linalg.algs.blas2]]</a>
9360
+
9361
+ #### General matrix-vector product <a id="linalg.algs.blas2.gemv">[[linalg.algs.blas2.gemv]]</a>
9362
+
9363
+ [*Note 1*: These functions correspond to the BLAS function
9364
+ `xGEMV`. — *end note*]
9365
+
9366
+ The following elements apply to all functions in
9367
+ [[linalg.algs.blas2.gemv]].
9368
+
9369
+ *Mandates:*
9370
+
9371
+ - `possibly-multipliable<decltype(A), decltype(x), decltype(y)>()` is
9372
+ `true`, and
9373
+ - `possibly-addable<decltype(x), decltype(y), decltype(z)>()` is `true`
9374
+ for those overloads that take a `z` parameter.
9375
+
9376
+ *Preconditions:*
9377
+
9378
+ - `multipliable(A,x,y)` is `true`, and
9379
+ - `addable(x,y,z)` is `true` for those overloads that take a `z`
9380
+ parameter.
9381
+
9382
+ *Complexity:* 𝑂(`x.extent(0)` × `A.extent(1)`).
9383
+
9384
+ ``` cpp
9385
+ template<in-matrix InMat, in-vector InVec, out-vector OutVec>
9386
+ void matrix_vector_product(InMat A, InVec x, OutVec y);
9387
+ template<class ExecutionPolicy, in-matrix InMat, in-vector InVec, out-vector OutVec>
9388
+ void matrix_vector_product(ExecutionPolicy&& exec, InMat A, InVec x, OutVec y);
9389
+ ```
9390
+
9391
+ These functions perform an overwriting matrix-vector product.
9392
+
9393
+ *Effects:* Computes y = A x.
9394
+
9395
+ [*Example 1*:
9396
+
9397
+ ``` cpp
9398
+ constexpr size_t num_rows = 5;
9399
+ constexpr size_t num_cols = 6;
9400
+
9401
+ // y = 3.0 * A * x
9402
+ void scaled_matvec_1(mdspan<double, extents<size_t, num_rows, num_cols>> A,
9403
+ mdspan<double, extents<size_t, num_cols>> x, mdspan<double, extents<size_t, num_rows>> y) {
9404
+ matrix_vector_product(scaled(3.0, A), x, y);
9405
+ }
9406
+
9407
+ // z = 7.0 times the transpose of A, times y
9408
+ void scaled_transposed_matvec(mdspan<double, extents<size_t, num_rows, num_cols>> A,
9409
+ mdspan<double, extents<size_t, num_rows>> y, mdspan<double, extents<size_t, num_cols>> z) {
9410
+ matrix_vector_product(scaled(7.0, transposed(A)), y, z);
9411
+ }
9412
+ ```
9413
+
9414
+ — *end example*]
9415
+
9416
+ ``` cpp
9417
+ template<in-matrix InMat, in-vector InVec1, in-vector InVec2, out-vector OutVec>
9418
+ void matrix_vector_product(InMat A, InVec1 x, InVec2 y, OutVec z);
9419
+ template<class ExecutionPolicy,
9420
+ in-matrix InMat, in-vector InVec1, in-vector InVec2, out-vector OutVec>
9421
+ void matrix_vector_product(ExecutionPolicy&& exec,
9422
+ InMat A, InVec1 x, InVec2 y, OutVec z);
9423
+ ```
9424
+
9425
+ These functions perform an updating matrix-vector product.
9426
+
9427
+ *Effects:* Computes z = y + A x.
9428
+
9429
+ *Remarks:* `z` may alias `y`.
9430
+
9431
+ [*Example 2*:
9432
+
9433
+ ``` cpp
9434
+ // y = 3.0 * A * x + 2.0 * y
9435
+ void scaled_matvec_2(mdspan<double, extents<size_t, num_rows, num_cols>> A,
9436
+ mdspan<double, extents<size_t, num_cols>> x, mdspan<double, extents<size_t, num_rows>> y) {
9437
+ matrix_vector_product(scaled(3.0, A), x, scaled(2.0, y), y);
9438
+ }
9439
+ ```
9440
+
9441
+ — *end example*]
9442
+
9443
+ #### Symmetric matrix-vector product <a id="linalg.algs.blas2.symv">[[linalg.algs.blas2.symv]]</a>
9444
+
9445
+ [*Note 1*: These functions correspond to the BLAS functions `xSYMV` and
9446
+ `xSPMV`. — *end note*]
9447
+
9448
+ The following elements apply to all functions in
9449
+ [[linalg.algs.blas2.symv]].
9450
+
9451
+ *Mandates:*
9452
+
9453
+ - If `InMat` has `layout_blas_packed` layout, then the layout’s
9454
+ `Triangle` template argument has the same type as the function’s
9455
+ `Triangle` template argument;
9456
+ - `compatible-static-extents<decltype(A), decltype(A)>(0, 1)` is `true`;
9457
+ - `possibly-multipliable<decltype(A), decltype(x), decltype(y)>()` is
9458
+ `true`; and
9459
+ - `possibly-addable<decltype(x), decltype(y), decltype(z)>()` is `true`
9460
+ for those overloads that take a `z` parameter.
9461
+
9462
+ *Preconditions:*
9463
+
9464
+ - `A.extent(0)` equals `A.extent(1)`,
9465
+ - `multipliable(A,x,y)` is `true`, and
9466
+ - `addable(x,y,z)` is `true` for those overloads that take a `z`
9467
+ parameter.
9468
+
9469
+ *Complexity:* 𝑂(`x.extent(0)` × `A.extent(1)`).
9470
+
9471
+ ``` cpp
9472
+ template<in-matrix InMat, class Triangle, in-vector InVec, out-vector OutVec>
9473
+ void symmetric_matrix_vector_product(InMat A, Triangle t, InVec x, OutVec y);
9474
+ template<class ExecutionPolicy,
9475
+ in-matrix InMat, class Triangle, in-vector InVec, out-vector OutVec>
9476
+ void symmetric_matrix_vector_product(ExecutionPolicy&& exec,
9477
+ InMat A, Triangle t, InVec x, OutVec y);
9478
+ ```
9479
+
9480
+ These functions perform an overwriting symmetric matrix-vector product,
9481
+ taking into account the `Triangle` parameter that applies to the
9482
+ symmetric matrix `A` [[linalg.general]].
9483
+
9484
+ *Effects:* Computes y = A x.
9485
+
9486
+ ``` cpp
9487
+ template<in-matrix InMat, class Triangle, in-vector InVec1, in-vector InVec2, out-vector OutVec>
9488
+ void symmetric_matrix_vector_product(InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z);
9489
+ template<class ExecutionPolicy,
9490
+ in-matrix InMat, class Triangle, in-vector InVec1, in-vector InVec2, out-vector OutVec>
9491
+ void symmetric_matrix_vector_product(ExecutionPolicy&& exec,
9492
+ InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z);
9493
+ ```
9494
+
9495
+ These functions perform an updating symmetric matrix-vector product,
9496
+ taking into account the `Triangle` parameter that applies to the
9497
+ symmetric matrix `A` [[linalg.general]].
9498
+
9499
+ *Effects:* Computes z = y + A x.
9500
+
9501
+ *Remarks:* `z` may alias `y`.
9502
+
9503
+ #### Hermitian matrix-vector product <a id="linalg.algs.blas2.hemv">[[linalg.algs.blas2.hemv]]</a>
9504
+
9505
+ [*Note 1*: These functions correspond to the BLAS functions `xHEMV` and
9506
+ `xHPMV`. — *end note*]
9507
+
9508
+ The following elements apply to all functions in
9509
+ [[linalg.algs.blas2.hemv]].
9510
+
9511
+ *Mandates:*
9512
+
9513
+ - If `InMat` has `layout_blas_packed` layout, then the layout’s
9514
+ `Triangle` template argument has the same type as the function’s
9515
+ `Triangle` template argument;
9516
+ - `compatible-static-extents<decltype(A), decltype(A)>(0, 1)` is `true`;
9517
+ - `possibly-multipliable<decltype(A), decltype(x), decltype(y)>()` is
9518
+ `true`; and
9519
+ - `possibly-addable<decltype(x), decltype(y), decltype(z)>()` is `true`
9520
+ for those overloads that take a `z` parameter.
9521
+
9522
+ *Preconditions:*
9523
+
9524
+ - `A.extent(0)` equals `A.extent(1)`,
9525
+ - `multipliable(A, x, y)` is `true`, and
9526
+ - `addable(x, y, z)` is `true` for those overloads that take a `z`
9527
+ parameter.
9528
+
9529
+ *Complexity:* 𝑂(`x.extent(0)` × `A.extent(1)`).
9530
+
9531
+ ``` cpp
9532
+ template<in-matrix InMat, class Triangle, in-vector InVec, out-vector OutVec>
9533
+ void hermitian_matrix_vector_product(InMat A, Triangle t, InVec x, OutVec y);
9534
+ template<class ExecutionPolicy,
9535
+ in-matrix InMat, class Triangle, in-vector InVec, out-vector OutVec>
9536
+ void hermitian_matrix_vector_product(ExecutionPolicy&& exec,
9537
+ InMat A, Triangle t, InVec x, OutVec y);
9538
+ ```
9539
+
9540
+ These functions perform an overwriting Hermitian matrix-vector product,
9541
+ taking into account the `Triangle` parameter that applies to the
9542
+ Hermitian matrix `A` [[linalg.general]].
9543
+
9544
+ *Effects:* Computes y = A x.
9545
+
9546
+ ``` cpp
9547
+ template<in-matrix InMat, class Triangle, in-vector InVec1, in-vector InVec2, out-vector OutVec>
9548
+ void hermitian_matrix_vector_product(InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z);
9549
+ template<class ExecutionPolicy,
9550
+ in-matrix InMat, class Triangle, in-vector InVec1, in-vector InVec2, out-vector OutVec>
9551
+ void hermitian_matrix_vector_product(ExecutionPolicy&& exec,
9552
+ InMat A, Triangle t, InVec1 x, InVec2 y, OutVec z);
9553
+ ```
9554
+
9555
+ These functions perform an updating Hermitian matrix-vector product,
9556
+ taking into account the `Triangle` parameter that applies to the
9557
+ Hermitian matrix `A` [[linalg.general]].
9558
+
9559
+ *Effects:* Computes z = y + A x.
9560
+
9561
+ *Remarks:* `z` may alias `y`.
9562
+
9563
+ #### Triangular matrix-vector product <a id="linalg.algs.blas2.trmv">[[linalg.algs.blas2.trmv]]</a>
9564
+
9565
+ [*Note 1*: These functions correspond to the BLAS functions `xTRMV` and
9566
+ `xTPMV`. — *end note*]
9567
+
9568
+ The following elements apply to all functions in
9569
+ [[linalg.algs.blas2.trmv]].
9570
+
9571
+ *Mandates:*
9572
+
9573
+ - If `InMat` has `layout_blas_packed` layout, then the layout’s
9574
+ `Triangle` template argument has the same type as the function’s
9575
+ `Triangle` template argument;
9576
+ - `compatible-static-extents<decltype(A), decltype(A)>(0, 1)` is `true`;
9577
+ - `compatible-static-extents<decltype(A), decltype(y)>(0, 0)` is `true`;
9578
+ - `compatible-static-extents<decltype(A), decltype(x)>(0, 0)` is `true`
9579
+ for those overloads that take an `x` parameter; and
9580
+ - `compatible-static-extents<decltype(A), decltype(z)>(0, 0)` is `true`
9581
+ for those overloads that take a `z` parameter.
9582
+
9583
+ *Preconditions:*
9584
+
9585
+ - `A.extent(0)` equals `A.extent(1)`,
9586
+ - `A.extent(0)` equals `y.extent(0)`,
9587
+ - `A.extent(0)` equals `x.extent(0)` for those overloads that take an
9588
+ `x` parameter, and
9589
+ - `A.extent(0)` equals `z.extent(0)` for those overloads that take a `z`
9590
+ parameter.
9591
+
9592
+ ``` cpp
9593
+ template<in-matrix InMat, class Triangle, class DiagonalStorage, in-vector InVec,
9594
+ out-vector OutVec>
9595
+ void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, InVec x, OutVec y);
9596
+ template<class ExecutionPolicy,
9597
+ in-matrix InMat, class Triangle, class DiagonalStorage, in-vector InVec,
9598
+ out-vector OutVec>
9599
+ void triangular_matrix_vector_product(ExecutionPolicy&& exec,
9600
+ InMat A, Triangle t, DiagonalStorage d, InVec x, OutVec y);
9601
+ ```
9602
+
9603
+ These functions perform an overwriting triangular matrix-vector product,
9604
+ taking into account the `Triangle` and `DiagonalStorage` parameters that
9605
+ apply to the triangular matrix `A` [[linalg.general]].
9606
+
9607
+ *Effects:* Computes y = A x.
9608
+
9609
+ *Complexity:* 𝑂(`x.extent(0)` × `A.extent(1)`).
9610
+
9611
+ ``` cpp
9612
+ template<in-matrix InMat, class Triangle, class DiagonalStorage, inout-vector InOutVec>
9613
+ void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d, InOutVec y);
9614
+ template<class ExecutionPolicy,
9615
+ in-matrix InMat, class Triangle, class DiagonalStorage, inout-vector InOutVec>
9616
+ void triangular_matrix_vector_product(ExecutionPolicy&& exec,
9617
+ InMat A, Triangle t, DiagonalStorage d, InOutVec y);
9618
+ ```
9619
+
9620
+ These functions perform an in-place triangular matrix-vector product,
9621
+ taking into account the `Triangle` and `DiagonalStorage` parameters that
9622
+ apply to the triangular matrix `A` [[linalg.general]].
9623
+
9624
+ [*Note 1*: Performing this operation in place hinders parallelization.
9625
+ However, other `ExecutionPolicy` specific optimizations, such as
9626
+ vectorization, are still possible. — *end note*]
9627
+
9628
+ *Effects:* Computes a vector y' such that y' = A y, and assigns each
9629
+ element of y' to the corresponding element of y.
9630
+
9631
+ *Complexity:* 𝑂(`y.extent(0)` × `A.extent(1)`).
9632
+
9633
+ ``` cpp
9634
+ template<in-matrix InMat, class Triangle, class DiagonalStorage,
9635
+ in-vector InVec1, in-vector InVec2, out-vector OutVec>
9636
+ void triangular_matrix_vector_product(InMat A, Triangle t, DiagonalStorage d,
9637
+ InVec1 x, InVec2 y, OutVec z);
9638
+ template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage,
9639
+ in-vector InVec1, in-vector InVec2, out-vector OutVec>
9640
+ void triangular_matrix_vector_product(ExecutionPolicy&& exec,
9641
+ InMat A, Triangle t, DiagonalStorage d,
9642
+ InVec1 x, InVec2 y, OutVec z);
9643
+ ```
9644
+
9645
+ These functions perform an updating triangular matrix-vector product,
9646
+ taking into account the `Triangle` and `DiagonalStorage` parameters that
9647
+ apply to the triangular matrix `A` [[linalg.general]].
9648
+
9649
+ *Effects:* Computes z = y + A x.
9650
+
9651
+ *Complexity:* 𝑂(`x.extent(0)` × `A.extent(1)`).
9652
+
9653
+ *Remarks:* `z` may alias `y`.
9654
+
9655
+ #### Solve a triangular linear system <a id="linalg.algs.blas2.trsv">[[linalg.algs.blas2.trsv]]</a>
9656
+
9657
+ [*Note 1*: These functions correspond to the BLAS functions `xTRSV` and
9658
+ `xTPSV`. — *end note*]
9659
+
9660
+ The following elements apply to all functions in
9661
+ [[linalg.algs.blas2.trsv]].
9662
+
9663
+ *Mandates:*
9664
+
9665
+ - If `InMat` has `layout_blas_packed` layout, then the layout’s
9666
+ `Triangle` template argument has the same type as the function’s
9667
+ `Triangle` template argument;
9668
+ - `compatible-static-extents<decltype(A), decltype(A)>(0, 1)` is `true`;
9669
+ - `compatible-static-extents<decltype(A), decltype(b)>(0, 0)` is `true`;
9670
+ and
9671
+ - `compatible-static-extents<decltype(A), decltype(x)>(0, 0)` is `true`
9672
+ for those overloads that take an `x` parameter.
9673
+
9674
+ *Preconditions:*
9675
+
9676
+ - `A.extent(0)` equals `A.extent(1)`,
9677
+ - `A.extent(0)` equals `b.extent(0)`, and
9678
+ - `A.extent(0)` equals `x.extent(0)` for those overloads that take an
9679
+ `x` parameter.
9680
+
9681
+ ``` cpp
9682
+ template<in-matrix InMat, class Triangle, class DiagonalStorage,
9683
+ in-vector InVec, out-vector OutVec, class BinaryDivideOp>
9684
+ void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d,
9685
+ InVec b, OutVec x, BinaryDivideOp divide);
9686
+ template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage,
9687
+ in-vector InVec, out-vector OutVec, class BinaryDivideOp>
9688
+ void triangular_matrix_vector_solve(ExecutionPolicy&& exec,
9689
+ InMat A, Triangle t, DiagonalStorage d,
9690
+ InVec b, OutVec x, BinaryDivideOp divide);
9691
+ ```
9692
+
9693
+ These functions perform a triangular solve, taking into account the
9694
+ `Triangle` and `DiagonalStorage` parameters that apply to the triangular
9695
+ matrix `A` [[linalg.general]].
9696
+
9697
+ *Effects:* Computes a vector x' such that b = A x', and assigns each
9698
+ element of x' to the corresponding element of x. If no such x' exists,
9699
+ then the elements of `x` are valid but unspecified.
9700
+
9701
+ *Complexity:* 𝑂(`A.extent(1)` × `b.extent(0)`).
9702
+
9703
+ ``` cpp
9704
+ template<in-matrix InMat, class Triangle, class DiagonalStorage,
9705
+ in-vector InVec, out-vector OutVec>
9706
+ void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, InVec b, OutVec x);
9707
+ ```
9708
+
9709
+ *Effects:* Equivalent to:
9710
+
9711
+ ``` cpp
9712
+ triangular_matrix_vector_solve(A, t, d, b, x, divides<void>{});
9713
+ ```
9714
+
9715
+ ``` cpp
9716
+ template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage,
9717
+ in-vector InVec, out-vector OutVec>
9718
+ void triangular_matrix_vector_solve(ExecutionPolicy&& exec,
9719
+ InMat A, Triangle t, DiagonalStorage d, InVec b, OutVec x);
9720
+ ```
9721
+
9722
+ *Effects:* Equivalent to:
9723
+
9724
+ ``` cpp
9725
+ triangular_matrix_vector_solve(std::forward<ExecutionPolicy>(exec),
9726
+ A, t, d, b, x, divides<void>{});
9727
+ ```
9728
+
9729
+ ``` cpp
9730
+ template<in-matrix InMat, class Triangle, class DiagonalStorage,
9731
+ inout-vector InOutVec, class BinaryDivideOp>
9732
+ void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d,
9733
+ InOutVec b, BinaryDivideOp divide);
9734
+ template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage,
9735
+ inout-vector InOutVec, class BinaryDivideOp>
9736
+ void triangular_matrix_vector_solve(ExecutionPolicy&& exec,
9737
+ InMat A, Triangle t, DiagonalStorage d,
9738
+ InOutVec b, BinaryDivideOp divide);
9739
+ ```
9740
+
9741
+ These functions perform an in-place triangular solve, taking into
9742
+ account the `Triangle` and `DiagonalStorage` parameters that apply to
9743
+ the triangular matrix `A` [[linalg.general]].
9744
+
9745
+ [*Note 1*: Performing triangular solve in place hinders
9746
+ parallelization. However, other `ExecutionPolicy` specific
9747
+ optimizations, such as vectorization, are still possible. — *end note*]
9748
+
9749
+ *Effects:* Computes a vector x' such that b = A x', and assigns each
9750
+ element of x' to the corresponding element of b. If no such x' exists,
9751
+ then the elements of `b` are valid but unspecified.
9752
+
9753
+ *Complexity:* 𝑂(`A.extent(1)` × `b.extent(0)`).
9754
+
9755
+ ``` cpp
9756
+ template<in-matrix InMat, class Triangle, class DiagonalStorage, inout-vector InOutVec>
9757
+ void triangular_matrix_vector_solve(InMat A, Triangle t, DiagonalStorage d, InOutVec b);
9758
+ ```
9759
+
9760
+ *Effects:* Equivalent to:
9761
+
9762
+ ``` cpp
9763
+ triangular_matrix_vector_solve(A, t, d, b, divides<void>{});
9764
+ ```
9765
+
9766
+ ``` cpp
9767
+ template<class ExecutionPolicy,
9768
+ in-matrix InMat, class Triangle, class DiagonalStorage, inout-vector InOutVec>
9769
+ void triangular_matrix_vector_solve(ExecutionPolicy&& exec,
9770
+ InMat A, Triangle t, DiagonalStorage d, InOutVec b);
9771
+ ```
9772
+
9773
+ *Effects:* Equivalent to:
9774
+
9775
+ ``` cpp
9776
+ triangular_matrix_vector_solve(std::forward<ExecutionPolicy>(exec),
9777
+ A, t, d, b, divides<void>{});
9778
+ ```
9779
+
9780
+ #### Rank-1 (outer product) update of a matrix <a id="linalg.algs.blas2.rank1">[[linalg.algs.blas2.rank1]]</a>
9781
+
9782
+ ``` cpp
9783
+ template<in-vector InVec1, in-vector InVec2, inout-matrix InOutMat>
9784
+ void matrix_rank_1_update(InVec1 x, InVec2 y, InOutMat A);
9785
+ template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2, inout-matrix InOutMat>
9786
+ void matrix_rank_1_update(ExecutionPolicy&& exec, InVec1 x, InVec2 y, InOutMat A);
9787
+ ```
9788
+
9789
+ These functions perform a nonsymmetric nonconjugated rank-1 update.
9790
+
9791
+ [*Note 1*: These functions correspond to the BLAS functions `xGER` (for
9792
+ real element types) and `xGERU` (for complex element
9793
+ types). — *end note*]
9794
+
9795
+ *Mandates:* *`possibly-multipliable`*`<InOutMat, InVec2, InVec1>()` is
9796
+ `true`.
9797
+
9798
+ *Preconditions:* *`multipliable`*`(A, y, x)` is `true`.
9799
+
9800
+ *Effects:* Computes a matrix A' such that $A' = A + x y^T$, and assigns
9801
+ each element of A' to the corresponding element of A.
9802
+
9803
+ *Complexity:* 𝑂(`x.extent(0)` × `y.extent(0)`).
9804
+
9805
+ ``` cpp
9806
+ template<in-vector InVec1, in-vector InVec2, inout-matrix InOutMat>
9807
+ void matrix_rank_1_update_c(InVec1 x, InVec2 y, InOutMat A);
9808
+ template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2, inout-matrix InOutMat>
9809
+ void matrix_rank_1_update_c(ExecutionPolicy&& exec, InVec1 x, InVec2 y, InOutMat A);
9810
+ ```
9811
+
9812
+ These functions perform a nonsymmetric conjugated rank-1 update.
9813
+
9814
+ [*Note 2*: These functions correspond to the BLAS functions `xGER` (for
9815
+ real element types) and `xGERC` (for complex element
9816
+ types). — *end note*]
9817
+
9818
+ *Effects:*
9819
+
9820
+ - For the overloads without an `ExecutionPolicy` argument, equivalent
9821
+ to:
9822
+ ``` cpp
9823
+ matrix_rank_1_update(x, conjugated(y), A);
9824
+ ```
9825
+ - otherwise, equivalent to:
9826
+ ``` cpp
9827
+ matrix_rank_1_update(std::forward<ExecutionPolicy>(exec), x, conjugated(y), A);
9828
+ ```
9829
+
9830
+ #### Symmetric or Hermitian Rank-1 (outer product) update of a matrix <a id="linalg.algs.blas2.symherrank1">[[linalg.algs.blas2.symherrank1]]</a>
9831
+
9832
+ [*Note 1*: These functions correspond to the BLAS functions `xSYR`,
9833
+ `xSPR`, `xHER`, and `xHPR`. They have overloads taking a scaling factor
9834
+ `alpha`, because it would be impossible to express the update
9835
+ $A = A - x x^T$ otherwise. — *end note*]
9836
+
9837
+ The following elements apply to all functions in
9838
+ [[linalg.algs.blas2.symherrank1]].
9839
+
9840
+ *Mandates:*
9841
+
9842
+ - If `InOutMat` has `layout_blas_packed` layout, then the layout’s
9843
+ `Triangle` template argument has the same type as the function’s
9844
+ `Triangle` template argument;
9845
+ - `compatible-static-extents<decltype(A), decltype(A)>(0, 1)` is `true`;
9846
+ and
9847
+ - `compatible-static-extents<decltype(A), decltype(x)>(0, 0)` is `true`.
9848
+
9849
+ *Preconditions:*
9850
+
9851
+ - `A.extent(0)` equals `A.extent(1)`, and
9852
+ - `A.extent(0)` equals `x.extent(0)`.
9853
+
9854
+ *Complexity:* 𝑂(`x.extent(0)` × `x.extent(0)`).
9855
+
9856
+ ``` cpp
9857
+ template<class Scalar, in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle>
9858
+ void symmetric_matrix_rank_1_update(Scalar alpha, InVec x, InOutMat A, Triangle t);
9859
+ template<class ExecutionPolicy,
9860
+ class Scalar, in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle>
9861
+ void symmetric_matrix_rank_1_update(ExecutionPolicy&& exec,
9862
+ Scalar alpha, InVec x, InOutMat A, Triangle t);
9863
+ ```
9864
+
9865
+ These functions perform a symmetric rank-1 update of the symmetric
9866
+ matrix `A`, taking into account the `Triangle` parameter that applies to
9867
+ `A` [[linalg.general]].
9868
+
9869
+ *Effects:* Computes a matrix A' such that $A' = A + \alpha x x^T$, where
9870
+ the scalar α is `alpha`, and assigns each element of A' to the
9871
+ corresponding element of A.
9872
+
9873
+ ``` cpp
9874
+ template<in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle>
9875
+ void symmetric_matrix_rank_1_update(InVec x, InOutMat A, Triangle t);
9876
+ template<class ExecutionPolicy,
9877
+ in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle>
9878
+ void symmetric_matrix_rank_1_update(ExecutionPolicy&& exec, InVec x, InOutMat A, Triangle t);
9879
+ ```
9880
+
9881
+ These functions perform a symmetric rank-1 update of the symmetric
9882
+ matrix `A`, taking into account the `Triangle` parameter that applies to
9883
+ `A` [[linalg.general]].
9884
+
9885
+ *Effects:* Computes a matrix A' such that $A' = A + x x^T$ and assigns
9886
+ each element of A' to the corresponding element of A.
9887
+
9888
+ ``` cpp
9889
+ template<class Scalar, in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle>
9890
+ void hermitian_matrix_rank_1_update(Scalar alpha, InVec x, InOutMat A, Triangle t);
9891
+ template<class ExecutionPolicy,
9892
+ class Scalar, in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle>
9893
+ void hermitian_matrix_rank_1_update(ExecutionPolicy&& exec,
9894
+ Scalar alpha, InVec x, InOutMat A, Triangle t);
9895
+ ```
9896
+
9897
+ These functions perform a Hermitian rank-1 update of the Hermitian
9898
+ matrix `A`, taking into account the `Triangle` parameter that applies to
9899
+ `A` [[linalg.general]].
9900
+
9901
+ *Effects:* Computes A' such that $A' = A + \alpha x x^H$, where the
9902
+ scalar α is `alpha`, and assigns each element of A' to the corresponding
9903
+ element of A.
9904
+
9905
+ ``` cpp
9906
+ template<in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle>
9907
+ void hermitian_matrix_rank_1_update(InVec x, InOutMat A, Triangle t);
9908
+ template<class ExecutionPolicy,
9909
+ in-vector InVec, possibly-packed-inout-matrix InOutMat, class Triangle>
9910
+ void hermitian_matrix_rank_1_update(ExecutionPolicy&& exec, InVec x, InOutMat A, Triangle t);
9911
+ ```
9912
+
9913
+ These functions perform a Hermitian rank-1 update of the Hermitian
9914
+ matrix `A`, taking into account the `Triangle` parameter that applies to
9915
+ `A` [[linalg.general]].
9916
+
9917
+ *Effects:* Computes a matrix A' such that $A' = A + x x^H$ and assigns
9918
+ each element of A' to the corresponding element of A.
9919
+
9920
+ #### Symmetric and Hermitian rank-2 matrix updates <a id="linalg.algs.blas2.rank2">[[linalg.algs.blas2.rank2]]</a>
9921
+
9922
+ [*Note 1*: These functions correspond to the BLAS functions
9923
+ `xSYR2`,`xSPR2`, `xHER2` and `xHPR2`. — *end note*]
9924
+
9925
+ The following elements apply to all functions in
9926
+ [[linalg.algs.blas2.rank2]].
9927
+
9928
+ *Mandates:*
9929
+
9930
+ - If `InOutMat` has `layout_blas_packed` layout, then the layout’s
9931
+ `Triangle` template argument has the same type as the function’s
9932
+ `Triangle` template argument;
9933
+ - `compatible-static-extents<decltype(A), decltype(A)>(0, 1)` is `true`;
9934
+ and
9935
+ - `possibly-multipliable<decltype(A), decltype(x), decltype(y)>()` is
9936
+ `true`.
9937
+
9938
+ *Preconditions:*
9939
+
9940
+ - `A.extent(0)` equals `A.extent(1)`, and
9941
+ - `multipliable(A, x, y)` is `true`.
9942
+
9943
+ *Complexity:* 𝑂(`x.extent(0)` × `y.extent(0)`).
9944
+
9945
+ ``` cpp
9946
+ template<in-vector InVec1, in-vector InVec2,
9947
+ possibly-packed-inout-matrix InOutMat, class Triangle>
9948
+ void symmetric_matrix_rank_2_update(InVec1 x, InVec2 y, InOutMat A, Triangle t);
9949
+ template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2,
9950
+ possibly-packed-inout-matrix InOutMat, class Triangle>
9951
+ void symmetric_matrix_rank_2_update(ExecutionPolicy&& exec,
9952
+ InVec1 x, InVec2 y, InOutMat A, Triangle t);
9953
+ ```
9954
+
9955
+ These functions perform a symmetric rank-2 update of the symmetric
9956
+ matrix `A`, taking into account the `Triangle` parameter that applies to
9957
+ `A` [[linalg.general]].
9958
+
9959
+ *Effects:* Computes A' such that $A' = A + x y^T + y x^T$ and assigns
9960
+ each element of A' to the corresponding element of A.
9961
+
9962
+ ``` cpp
9963
+ template<in-vector InVec1, in-vector InVec2,
9964
+ possibly-packed-inout-matrix InOutMat, class Triangle>
9965
+ void hermitian_matrix_rank_2_update(InVec1 x, InVec2 y, InOutMat A, Triangle t);
9966
+ template<class ExecutionPolicy, in-vector InVec1, in-vector InVec2,
9967
+ possibly-packed-inout-matrix InOutMat, class Triangle>
9968
+ void hermitian_matrix_rank_2_update(ExecutionPolicy&& exec,
9969
+ InVec1 x, InVec2 y, InOutMat A, Triangle t);
9970
+ ```
9971
+
9972
+ These functions perform a Hermitian rank-2 update of the Hermitian
9973
+ matrix `A`, taking into account the `Triangle` parameter that applies to
9974
+ `A` [[linalg.general]].
9975
+
9976
+ *Effects:* Computes A' such that $A' = A + x y^H + y x^H$ and assigns
9977
+ each element of A' to the corresponding element of A.
9978
+
9979
+ ### BLAS 3 algorithms <a id="linalg.algs.blas3">[[linalg.algs.blas3]]</a>
9980
+
9981
+ #### General matrix-matrix product <a id="linalg.algs.blas3.gemm">[[linalg.algs.blas3.gemm]]</a>
9982
+
9983
+ [*Note 1*: These functions correspond to the BLAS function
9984
+ `xGEMM`. — *end note*]
9985
+
9986
+ The following elements apply to all functions in
9987
+ [[linalg.algs.blas3.gemm]] in addition to function-specific elements.
9988
+
9989
+ *Mandates:*
9990
+ `possibly-multipliable<decltype(A), decltype(B), decltype(C)>()` is
9991
+ `true`.
9992
+
9993
+ *Preconditions:* `multipliable(A, B, C)` is `true`.
9994
+
9995
+ *Complexity:* 𝑂(`A.extent(0)` × `A.extent(1)` × `B.extent(1)`).
9996
+
9997
+ ``` cpp
9998
+ template<in-matrix InMat1, in-matrix InMat2, out-matrix OutMat>
9999
+ void matrix_product(InMat1 A, InMat2 B, OutMat C);
10000
+ template<class ExecutionPolicy, in-matrix InMat1, in-matrix InMat2, out-matrix OutMat>
10001
+ void matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, OutMat C);
10002
+ ```
10003
+
10004
+ *Effects:* Computes C = A B.
10005
+
10006
+ ``` cpp
10007
+ template<in-matrix InMat1, in-matrix InMat2, in-matrix InMat3, out-matrix OutMat>
10008
+ void matrix_product(InMat1 A, InMat2 B, InMat3 E, OutMat C);
10009
+ template<class ExecutionPolicy,
10010
+ in-matrix InMat1, in-matrix InMat2, in-matrix InMat3, out-matrix OutMat>
10011
+ void matrix_product(ExecutionPolicy&& exec, InMat1 A, InMat2 B, InMat3 E, OutMat C);
10012
+ ```
10013
+
10014
+ *Mandates:* *`possibly-addable`*`<InMat3, InMat3, OutMat>()` is `true`.
10015
+
10016
+ *Preconditions:* *`addable`*`(E, E, C)` is `true`.
10017
+
10018
+ *Effects:* Computes C = E + A B.
10019
+
10020
+ *Remarks:* `C` may alias `E`.
10021
+
10022
+ #### Symmetric, Hermitian, and triangular matrix-matrix product <a id="linalg.algs.blas3.xxmm">[[linalg.algs.blas3.xxmm]]</a>
10023
+
10024
+ [*Note 1*: These functions correspond to the BLAS functions `xSYMM`,
10025
+ `xHEMM`, and `xTRMM`. — *end note*]
10026
+
10027
+ The following elements apply to all functions in
10028
+ [[linalg.algs.blas3.xxmm]] in addition to function-specific elements.
10029
+
10030
+ *Mandates:*
10031
+
10032
+ - `possibly-multipliable<decltype(A), decltype(B), decltype(C)>()` is
10033
+ `true`, and
10034
+ - `possibly-addable<decltype(E), decltype(E), decltype(C)>()` is `true`
10035
+ for those overloads that take an `E` parameter.
10036
+
10037
+ *Preconditions:*
10038
+
10039
+ - `multipliable(A, B, C)` is `true`, and
10040
+ - `addable(E, E, C)` is `true` for those overloads that take an `E`
10041
+ parameter.
10042
+
10043
+ *Complexity:* 𝑂(`A.extent(0)` × `A.extent(1)` × `B.extent(1)`).
10044
+
10045
+ ``` cpp
10046
+ template<in-matrix InMat1, class Triangle, in-matrix InMat2, out-matrix OutMat>
10047
+ void symmetric_matrix_product(InMat1 A, Triangle t, InMat2 B, OutMat C);
10048
+ template<class ExecutionPolicy,
10049
+ in-matrix InMat1, class Triangle, in-matrix InMat2, out-matrix OutMat>
10050
+ void symmetric_matrix_product(ExecutionPolicy&& exec, InMat1 A, Triangle t, InMat2 B, OutMat C);
10051
+
10052
+ template<in-matrix InMat1, class Triangle, in-matrix InMat2, out-matrix OutMat>
10053
+ void hermitian_matrix_product(InMat1 A, Triangle t, InMat2 B, OutMat C);
10054
+ template<class ExecutionPolicy,
10055
+ in-matrix InMat1, class Triangle, in-matrix InMat2, out-matrix OutMat>
10056
+ void hermitian_matrix_product(ExecutionPolicy&& exec, InMat1 A, Triangle t, InMat2 B, OutMat C);
10057
+
10058
+ template<in-matrix InMat1, class Triangle, class DiagonalStorage,
10059
+ in-matrix InMat2, out-matrix OutMat>
10060
+ void triangular_matrix_product(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat C);
10061
+ template<class ExecutionPolicy, in-matrix InMat1, class Triangle, class DiagonalStorage,
10062
+ in-matrix InMat2, out-matrix OutMat>
10063
+ void triangular_matrix_product(ExecutionPolicy&& exec,
10064
+ InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, OutMat C);
10065
+ ```
10066
+
10067
+ These functions perform a matrix-matrix multiply, taking into account
10068
+ the `Triangle` and `DiagonalStorage` (if applicable) parameters that
10069
+ apply to the symmetric, Hermitian, or triangular (respectively) matrix
10070
+ `A` [[linalg.general]].
10071
+
10072
+ *Mandates:*
10073
+
10074
+ - If `InMat1` has `layout_blas_packed` layout, then the layout’s
10075
+ `Triangle` template argument has the same type as the function’s
10076
+ `Triangle` template argument; and
10077
+ - *`compatible-static-extents`*`<InMat1, InMat1>(0, 1)` is `true`.
10078
+
10079
+ *Preconditions:* `A.extent(0) == A.extent(1)` is `true`.
10080
+
10081
+ *Effects:* Computes C = A B.
10082
+
10083
+ ``` cpp
10084
+ template<in-matrix InMat1, in-matrix InMat2, class Triangle, out-matrix OutMat>
10085
+ void symmetric_matrix_product(InMat1 A, InMat2 B, Triangle t, OutMat C);
10086
+ template<class ExecutionPolicy,
10087
+ in-matrix InMat1, in-matrix InMat2, class Triangle, out-matrix OutMat>
10088
+ void symmetric_matrix_product(ExecutionPolicy&& exec,
10089
+ InMat1 A, InMat2 B, Triangle t, OutMat C);
10090
+
10091
+ template<in-matrix InMat1, in-matrix InMat2, class Triangle, out-matrix OutMat>
10092
+ void hermitian_matrix_product(InMat1 A, InMat2 B, Triangle t, OutMat C);
10093
+ template<class ExecutionPolicy,
10094
+ in-matrix InMat1, in-matrix InMat2, class Triangle, out-matrix OutMat>
10095
+ void hermitian_matrix_product(ExecutionPolicy&& exec,
10096
+ InMat1 A, InMat2 B, Triangle t, OutMat C);
10097
+
10098
+ template<in-matrix InMat1, in-matrix InMat2, class Triangle, class DiagonalStorage,
10099
+ out-matrix OutMat>
10100
+ void triangular_matrix_product(InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, OutMat C);
10101
+ template<class ExecutionPolicy,
10102
+ in-matrix InMat1, in-matrix InMat2, class Triangle, class DiagonalStorage,
10103
+ out-matrix OutMat>
10104
+ void triangular_matrix_product(ExecutionPolicy&& exec,
10105
+ InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, OutMat C);
10106
+ ```
10107
+
10108
+ These functions perform a matrix-matrix multiply, taking into account
10109
+ the `Triangle` and `DiagonalStorage` (if applicable) parameters that
10110
+ apply to the symmetric, Hermitian, or triangular (respectively) matrix
10111
+ `B` [[linalg.general]].
10112
+
10113
+ *Mandates:*
10114
+
10115
+ - If `InMat2` has `layout_blas_packed` layout, then the layout’s
10116
+ `Triangle` template argument has the same type as the function’s
10117
+ `Triangle` template argument; and
10118
+ - *`compatible-static-extents`*`<InMat2, InMat2>(0, 1)` is `true`.
10119
+
10120
+ *Preconditions:* `B.extent(0) == B.extent(1)` is `true`.
10121
+
10122
+ *Effects:* Computes C = A B.
10123
+
10124
+ ``` cpp
10125
+ template<in-matrix InMat1, class Triangle, in-matrix InMat2, in-matrix InMat3,
10126
+ out-matrix OutMat>
10127
+ void symmetric_matrix_product(InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C);
10128
+ template<class ExecutionPolicy,
10129
+ in-matrix InMat1, class Triangle, in-matrix InMat2, in-matrix InMat3,
10130
+ out-matrix OutMat>
10131
+ void symmetric_matrix_product(ExecutionPolicy&& exec,
10132
+ InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C);
10133
+
10134
+ template<in-matrix InMat1, class Triangle, in-matrix InMat2, in-matrix InMat3,
10135
+ out-matrix OutMat>
10136
+ void hermitian_matrix_product(InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C);
10137
+ template<class ExecutionPolicy,
10138
+ in-matrix InMat1, class Triangle, in-matrix InMat2, in-matrix InMat3,
10139
+ out-matrix OutMat>
10140
+ void hermitian_matrix_product(ExecutionPolicy&& exec,
10141
+ InMat1 A, Triangle t, InMat2 B, InMat3 E, OutMat C);
10142
+
10143
+ template<in-matrix InMat1, class Triangle, class DiagonalStorage,
10144
+ in-matrix InMat2, in-matrix InMat3, out-matrix OutMat>
10145
+ void triangular_matrix_product(InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, InMat3 E,
10146
+ OutMat C);
10147
+ template<class ExecutionPolicy,
10148
+ in-matrix InMat1, class Triangle, class DiagonalStorage,
10149
+ in-matrix InMat2, in-matrix InMat3, out-matrix OutMat>
10150
+ void triangular_matrix_product(ExecutionPolicy&& exec,
10151
+ InMat1 A, Triangle t, DiagonalStorage d, InMat2 B, InMat3 E,
10152
+ OutMat C);
10153
+ ```
10154
+
10155
+ These functions perform a potentially overwriting matrix-matrix
10156
+ multiply-add, taking into account the `Triangle` and `DiagonalStorage`
10157
+ (if applicable) parameters that apply to the symmetric, Hermitian, or
10158
+ triangular (respectively) matrix `A` [[linalg.general]].
10159
+
10160
+ *Mandates:*
10161
+
10162
+ - If `InMat1` has `layout_blas_packed` layout, then the layout’s
10163
+ `Triangle` template argument has the same type as the function’s
10164
+ `Triangle` template argument; and
10165
+ - *`compatible-static-extents`*`<InMat1, InMat1>(0, 1)` is `true`.
10166
+
10167
+ *Preconditions:* `A.extent(0) == A.extent(1)` is `true`.
10168
+
10169
+ *Effects:* Computes C = E + A B.
10170
+
10171
+ *Remarks:* `C` may alias `E`.
10172
+
10173
+ ``` cpp
10174
+ template<in-matrix InMat1, in-matrix InMat2, class Triangle, in-matrix InMat3,
10175
+ out-matrix OutMat>
10176
+ void symmetric_matrix_product(InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C);
10177
+ template<class ExecutionPolicy,
10178
+ in-matrix InMat1, in-matrix InMat2, class Triangle, in-matrix InMat3,
10179
+ out-matrix OutMat>
10180
+ void symmetric_matrix_product(ExecutionPolicy&& exec,
10181
+ InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C);
10182
+
10183
+ template<in-matrix InMat1, in-matrix InMat2, class Triangle, in-matrix InMat3,
10184
+ out-matrix OutMat>
10185
+ void hermitian_matrix_product(InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C);
10186
+ template<class ExecutionPolicy,
10187
+ in-matrix InMat1, in-matrix InMat2, class Triangle, in-matrix InMat3,
10188
+ out-matrix OutMat>
10189
+ void hermitian_matrix_product(ExecutionPolicy&& exec,
10190
+ InMat1 A, InMat2 B, Triangle t, InMat3 E, OutMat C);
10191
+
10192
+ template<in-matrix InMat1, in-matrix InMat2, class Triangle, class DiagonalStorage,
10193
+ in-matrix InMat3, out-matrix OutMat>
10194
+ void triangular_matrix_product(InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, InMat3 E,
10195
+ OutMat C);
10196
+ template<class ExecutionPolicy,
10197
+ in-matrix InMat1, in-matrix InMat2, class Triangle, class DiagonalStorage,
10198
+ in-matrix InMat3, out-matrix OutMat>
10199
+ void triangular_matrix_product(ExecutionPolicy&& exec,
10200
+ InMat1 A, InMat2 B, Triangle t, DiagonalStorage d, InMat3 E,
10201
+ OutMat C);
10202
+ ```
10203
+
10204
+ These functions perform a potentially overwriting matrix-matrix
10205
+ multiply-add, taking into account the `Triangle` and `DiagonalStorage`
10206
+ (if applicable) parameters that apply to the symmetric, Hermitian, or
10207
+ triangular (respectively) matrix `B` [[linalg.general]].
10208
+
10209
+ *Mandates:*
10210
+
10211
+ - If `InMat2` has `layout_blas_packed` layout, then the layout’s
10212
+ `Triangle` template argument has the same type as the function’s
10213
+ `Triangle` template argument; and
10214
+ - *`compatible-static-extents`*`<InMat2, InMat2>(0, 1)` is `true`.
10215
+
10216
+ *Preconditions:* `B.extent(0) == B.extent(1)` is `true`.
10217
+
10218
+ *Effects:* Computes C = E + A B.
10219
+
10220
+ *Remarks:* `C` may alias `E`.
10221
+
10222
+ #### In-place triangular matrix-matrix product <a id="linalg.algs.blas3.trmm">[[linalg.algs.blas3.trmm]]</a>
10223
+
10224
+ These functions perform an in-place matrix-matrix multiply, taking into
10225
+ account the `Triangle` and `DiagonalStorage` parameters that apply to
10226
+ the triangular matrix `A` [[linalg.general]].
10227
+
10228
+ [*Note 1*: These functions correspond to the BLAS function
10229
+ `xTRMM`. — *end note*]
10230
+
10231
+ ``` cpp
10232
+ template<in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat>
10233
+ void triangular_matrix_left_product(InMat A, Triangle t, DiagonalStorage d, InOutMat C);
10234
+ template<class ExecutionPolicy,
10235
+ in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat>
10236
+ void triangular_matrix_left_product(ExecutionPolicy&& exec,
10237
+ InMat A, Triangle t, DiagonalStorage d, InOutMat C);
10238
+ ```
10239
+
10240
+ *Mandates:*
10241
+
10242
+ - If `InMat` has `layout_blas_packed` layout, then the layout’s
10243
+ `Triangle` template argument has the same type as the function’s
10244
+ `Triangle` template argument;
10245
+ - *`possibly-multipliable`*`<InMat, InOutMat, InOutMat>()` is `true`;
10246
+ and
10247
+ - *`compatible-static-extents`*`<InMat, InMat>(0, 1)` is `true`.
10248
+
10249
+ *Preconditions:*
10250
+
10251
+ - *`multipliable`*`(A, C, C)` is `true`, and
10252
+ - `A.extent(0) == A.extent(1)` is `true`.
10253
+
10254
+ *Effects:* Computes a matrix C' such that C' = A C and assigns each
10255
+ element of C' to the corresponding element of C.
10256
+
10257
+ *Complexity:* 𝑂(`A.extent(0)` × `A.extent(1)` × `C.extent(0)`).
10258
+
10259
+ ``` cpp
10260
+ template<in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat>
10261
+ void triangular_matrix_right_product(InMat A, Triangle t, DiagonalStorage d, InOutMat C);
10262
+ template<class ExecutionPolicy,
10263
+ in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat>
10264
+ void triangular_matrix_right_product(ExecutionPolicy&& exec,
10265
+ InMat A, Triangle t, DiagonalStorage d, InOutMat C);
10266
+ ```
10267
+
10268
+ *Mandates:*
10269
+
10270
+ - If `InMat` has `layout_blas_packed` layout, then the layout’s
10271
+ `Triangle` template argument has the same type as the function’s
10272
+ `Triangle` template argument;
10273
+ - *`possibly-multipliable`*`<InOutMat, InMat, InOutMat>()` is `true`;
10274
+ and
10275
+ - *`compatible-static-extents`*`<InMat, InMat>(0, 1)` is `true`.
10276
+
10277
+ *Preconditions:*
10278
+
10279
+ - *`multipliable`*`(C, A, C)` is `true`, and
10280
+ - `A.extent(0) == A.extent(1)` is `true`.
10281
+
10282
+ *Effects:* Computes a matrix C' such that C' = C A and assigns each
10283
+ element of C' to the corresponding element of C.
10284
+
10285
+ *Complexity:* 𝑂(`A.extent(0)` × `A.extent(1)` × `C.extent(0)`).
10286
+
10287
+ #### Rank-k update of a symmetric or Hermitian matrix <a id="linalg.algs.blas3.rankk">[[linalg.algs.blas3.rankk]]</a>
10288
+
10289
+ [*Note 1*: These functions correspond to the BLAS functions `xSYRK` and
10290
+ `xHERK`. — *end note*]
10291
+
10292
+ The following elements apply to all functions in
10293
+ [[linalg.algs.blas3.rankk]].
10294
+
10295
+ *Mandates:*
10296
+
10297
+ - If `InOutMat` has `layout_blas_packed` layout, then the layout’s
10298
+ `Triangle` template argument has the same type as the function’s
10299
+ `Triangle` template argument;
10300
+ - `compatible-static-extents<decltype(A), decltype(A)>(0, 1)` is `true`;
10301
+ - `compatible-static-extents<decltype(C), decltype(C)>(0, 1)` is `true`;
10302
+ and
10303
+ - `compatible-static-extents<decltype(A), decltype(C)>(0, 0)` is `true`.
10304
+
10305
+ *Preconditions:*
10306
+
10307
+ - `A.extent(0)` equals `A.extent(1)`,
10308
+ - `C.extent(0)` equals `C.extent(1)`, and
10309
+ - `A.extent(0)` equals `C.extent(0)`.
10310
+
10311
+ *Complexity:* 𝑂(`A.extent(0)` × `A.extent(1)` × `C.extent(0)`).
10312
+
10313
+ ``` cpp
10314
+ template<class Scalar, in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle>
10315
+ void symmetric_matrix_rank_k_update(Scalar alpha, InMat A, InOutMat C, Triangle t);
10316
+ template<class ExecutionPolicy, class Scalar,
10317
+ in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle>
10318
+ void symmetric_matrix_rank_k_update(ExecutionPolicy&& exec,
10319
+ Scalar alpha, InMat A, InOutMat C, Triangle t);
10320
+ ```
10321
+
10322
+ *Effects:* Computes a matrix C' such that $C' = C + \alpha A A^T$, where
10323
+ the scalar α is `alpha`, and assigns each element of C' to the
10324
+ corresponding element of C.
10325
+
10326
+ ``` cpp
10327
+ template<in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle>
10328
+ void symmetric_matrix_rank_k_update(InMat A, InOutMat C, Triangle t);
10329
+ template<class ExecutionPolicy,
10330
+ in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle>
10331
+ void symmetric_matrix_rank_k_update(ExecutionPolicy&& exec,
10332
+ InMat A, InOutMat C, Triangle t);
10333
+ ```
10334
+
10335
+ *Effects:* Computes a matrix C' such that $C' = C + A A^T$, and assigns
10336
+ each element of C' to the corresponding element of C.
10337
+
10338
+ ``` cpp
10339
+ template<class Scalar, in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle>
10340
+ void hermitian_matrix_rank_k_update(Scalar alpha, InMat A, InOutMat C, Triangle t);
10341
+ template<class ExecutionPolicy,
10342
+ class Scalar, in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle>
10343
+ void hermitian_matrix_rank_k_update(ExecutionPolicy&& exec,
10344
+ Scalar alpha, InMat A, InOutMat C, Triangle t);
10345
+ ```
10346
+
10347
+ *Effects:* Computes a matrix C' such that $C' = C + \alpha A A^H$, where
10348
+ the scalar α is `alpha`, and assigns each element of C' to the
10349
+ corresponding element of C.
10350
+
10351
+ ``` cpp
10352
+ template<in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle>
10353
+ void hermitian_matrix_rank_k_update(InMat A, InOutMat C, Triangle t);
10354
+ template<class ExecutionPolicy,
10355
+ in-matrix InMat, possibly-packed-inout-matrix InOutMat, class Triangle>
10356
+ void hermitian_matrix_rank_k_update(ExecutionPolicy&& exec,
10357
+ InMat A, InOutMat C, Triangle t);
10358
+ ```
10359
+
10360
+ *Effects:* Computes a matrix C' such that $C' = C + A A^H$, and assigns
10361
+ each element of C' to the corresponding element of C.
10362
+
10363
+ #### Rank-2k update of a symmetric or Hermitian matrix <a id="linalg.algs.blas3.rank2k">[[linalg.algs.blas3.rank2k]]</a>
10364
+
10365
+ [*Note 1*: These functions correspond to the BLAS functions `xSYR2K`
10366
+ and `xHER2K`. — *end note*]
10367
+
10368
+ The following elements apply to all functions in
10369
+ [[linalg.algs.blas3.rank2k]].
10370
+
10371
+ *Mandates:*
10372
+
10373
+ - If `InOutMat` has `layout_blas_packed` layout, then the layout’s
10374
+ `Triangle` template argument has the same type as the function’s
10375
+ `Triangle` template argument;
10376
+ - `possibly-addable<decltype(A), decltype(B), decltype(C)>()` is `true`;
10377
+ and
10378
+ - `compatible-static-extents<decltype(A), decltype(A)>(0, 1)` is `true`.
10379
+
10380
+ *Preconditions:*
10381
+
10382
+ - `addable(A, B, C)` is `true`, and
10383
+ - `A.extent(0)` equals `A.extent(1)`.
10384
+
10385
+ *Complexity:* 𝑂(`A.extent(0)` × `A.extent(1)` × `C.extent(0)`).
10386
+
10387
+ ``` cpp
10388
+ template<in-matrix InMat1, in-matrix InMat2,
10389
+ possibly-packed-inout-matrix InOutMat, class Triangle>
10390
+ void symmetric_matrix_rank_2k_update(InMat1 A, InMat2 B, InOutMat C, Triangle t);
10391
+ template<class ExecutionPolicy, in-matrix InMat1, in-matrix InMat2,
10392
+ possibly-packed-inout-matrix InOutMat, class Triangle>
10393
+ void symmetric_matrix_rank_2k_update(ExecutionPolicy&& exec,
10394
+ InMat1 A, InMat2 B, InOutMat C, Triangle t);
10395
+ ```
10396
+
10397
+ *Effects:* Computes a matrix C' such that $C' = C + A B^T + B A^T$, and
10398
+ assigns each element of C' to the corresponding element of C.
10399
+
10400
+ ``` cpp
10401
+ template<in-matrix InMat1, in-matrix InMat2,
10402
+ possibly-packed-inout-matrix InOutMat, class Triangle>
10403
+ void hermitian_matrix_rank_2k_update(InMat1 A, InMat2 B, InOutMat C, Triangle t);
10404
+ template<class ExecutionPolicy,
10405
+ in-matrix InMat1, in-matrix InMat2,
10406
+ possibly-packed-inout-matrix InOutMat, class Triangle>
10407
+ void hermitian_matrix_rank_2k_update(ExecutionPolicy&& exec,
10408
+ InMat1 A, InMat2 B, InOutMat C, Triangle t);
10409
+ ```
10410
+
10411
+ *Effects:* Computes a matrix C' such that $C' = C + A B^H + B A^H$, and
10412
+ assigns each element of C' to the corresponding element of C.
10413
+
10414
+ #### Solve multiple triangular linear systems <a id="linalg.algs.blas3.trsm">[[linalg.algs.blas3.trsm]]</a>
10415
+
10416
+ [*Note 1*: These functions correspond to the BLAS function
10417
+ `xTRSM`. — *end note*]
10418
+
10419
+ ``` cpp
10420
+ template<in-matrix InMat1, class Triangle, class DiagonalStorage,
10421
+ in-matrix InMat2, out-matrix OutMat, class BinaryDivideOp>
10422
+ void triangular_matrix_matrix_left_solve(InMat1 A, Triangle t, DiagonalStorage d,
10423
+ InMat2 B, OutMat X, BinaryDivideOp divide);
10424
+ template<class ExecutionPolicy,
10425
+ in-matrix InMat1, class Triangle, class DiagonalStorage,
10426
+ in-matrix InMat2, out-matrix OutMat, class BinaryDivideOp>
10427
+ void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec,
10428
+ InMat1 A, Triangle t, DiagonalStorage d,
10429
+ InMat2 B, OutMat X, BinaryDivideOp divide);
10430
+ ```
10431
+
10432
+ These functions perform multiple matrix solves, taking into account the
10433
+ `Triangle` and `DiagonalStorage` parameters that apply to the triangular
10434
+ matrix `A` [[linalg.general]].
10435
+
10436
+ *Mandates:*
10437
+
10438
+ - If `InMat1` has `layout_blas_packed` layout, then the layout’s
10439
+ `Triangle` template argument has the same type as the function’s
10440
+ `Triangle` template argument;
10441
+ - *`possibly-multipliable`*`<InMat1, OutMat, InMat2>()` is `true`; and
10442
+ - *`compatible-static-extents`*`<InMat1, InMat1>(0, 1)` is `true`.
10443
+
10444
+ *Preconditions:*
10445
+
10446
+ - *`multipliable`*`(A, X, B)` is `true`, and
10447
+ - `A.extent(0) == A.extent(1)` is `true`.
10448
+
10449
+ *Effects:* Computes X' such that AX' = B, and assigns each element of X'
10450
+ to the corresponding element of X. If no such X' exists, then the
10451
+ elements of `X` are valid but unspecified.
10452
+
10453
+ *Complexity:* 𝑂(`A.extent(0)` × `X.extent(1)` × `X.extent(1)`).
10454
+
10455
+ [*Note 2*: Since the triangular matrix is on the left, the desired
10456
+ `divide` implementation in the case of noncommutative multiplication is
10457
+ mathematically equivalent to $y^{-1} x$, where x is the first argument
10458
+ and y is the second argument, and $y^{-1}$ denotes the multiplicative
10459
+ inverse of y. — *end note*]
10460
+
10461
+ ``` cpp
10462
+ template<in-matrix InMat1, class Triangle, class DiagonalStorage,
10463
+ in-matrix InMat2, out-matrix OutMat>
10464
+ void triangular_matrix_matrix_left_solve(InMat1 A, Triangle t, DiagonalStorage d,
10465
+ InMat2 B, OutMat X);
10466
+ ```
10467
+
10468
+ *Effects:* Equivalent to:
10469
+
10470
+ ``` cpp
10471
+ triangular_matrix_matrix_left_solve(A, t, d, B, X, divides<void>{});
10472
+ ```
10473
+
10474
+ ``` cpp
10475
+ template<class ExecutionPolicy, in-matrix InMat1, class Triangle, class DiagonalStorage,
10476
+ in-matrix InMat2, out-matrix OutMat>
10477
+ void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec,
10478
+ InMat1 A, Triangle t, DiagonalStorage d,
10479
+ InMat2 B, OutMat X);
10480
+ ```
10481
+
10482
+ *Effects:* Equivalent to:
10483
+
10484
+ ``` cpp
10485
+ triangular_matrix_matrix_left_solve(std::forward<ExecutionPolicy>(exec),
10486
+ A, t, d, B, X, divides<void>{});
10487
+ ```
10488
+
10489
+ ``` cpp
10490
+ template<in-matrix InMat1, class Triangle, class DiagonalStorage,
10491
+ in-matrix InMat2, out-matrix OutMat, class BinaryDivideOp>
10492
+ void triangular_matrix_matrix_right_solve(InMat1 A, Triangle t, DiagonalStorage d,
10493
+ InMat2 B, OutMat X, BinaryDivideOp divide);
10494
+ template<class ExecutionPolicy,
10495
+ in-matrix InMat1, class Triangle, class DiagonalStorage,
10496
+ in-matrix InMat2, out-matrix OutMat, class BinaryDivideOp>
10497
+ void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec,
10498
+ InMat1 A, Triangle t, DiagonalStorage d,
10499
+ InMat2 B, OutMat X, BinaryDivideOp divide);
10500
+ ```
10501
+
10502
+ These functions perform multiple matrix solves, taking into account the
10503
+ `Triangle` and `DiagonalStorage` parameters that apply to the triangular
10504
+ matrix `A` [[linalg.general]].
10505
+
10506
+ *Mandates:*
10507
+
10508
+ - If `InMat1` has `layout_blas_packed` layout, then the layout’s
10509
+ `Triangle` template argument has the same type as the function’s
10510
+ `Triangle` template argument;
10511
+ - *`possibly-multipliable`*`<OutMat, InMat1, InMat2>()` is `true`; and
10512
+ - *`compatible-static-extents`*`<InMat1, InMat1>(0,1)` is `true`.
10513
+
10514
+ *Preconditions:*
10515
+
10516
+ - *`multipliable`*`(X, A, B)` is `true`, and
10517
+ - `A.extent(0) == A.extent(1)` is `true`.
10518
+
10519
+ *Effects:* Computes X' such that X'A = B, and assigns each element of X'
10520
+ to the corresponding element of X. If no such X' exists, then the
10521
+ elements of `X` are valid but unspecified.
10522
+
10523
+ *Complexity:* O( `B.extent(0)` ⋅ `B.extent(1)` ⋅ `A.extent(1)` )
10524
+
10525
+ [*Note 1*: Since the triangular matrix is on the right, the desired
10526
+ `divide` implementation in the case of noncommutative multiplication is
10527
+ mathematically equivalent to $x y^{-1}$, where x is the first argument
10528
+ and y is the second argument, and $y^{-1}$ denotes the multiplicative
10529
+ inverse of y. — *end note*]
10530
+
10531
+ ``` cpp
10532
+ template<in-matrix InMat1, class Triangle, class DiagonalStorage,
10533
+ in-matrix InMat2, out-matrix OutMat>
10534
+ void triangular_matrix_matrix_right_solve(InMat1 A, Triangle t, DiagonalStorage d,
10535
+ InMat2 B, OutMat X);
10536
+ ```
10537
+
10538
+ *Effects:* Equivalent to:
10539
+
10540
+ ``` cpp
10541
+ triangular_matrix_matrix_right_solve(A, t, d, B, X, divides<void>{});
10542
+ ```
10543
+
10544
+ ``` cpp
10545
+ template<class ExecutionPolicy, in-matrix InMat1, class Triangle, class DiagonalStorage,
10546
+ in-matrix InMat2, out-matrix OutMat>
10547
+ void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec,
10548
+ InMat1 A, Triangle t, DiagonalStorage d,
10549
+ InMat2 B, OutMat X);
10550
+ ```
10551
+
10552
+ *Effects:* Equivalent to:
10553
+
10554
+ ``` cpp
10555
+ triangular_matrix_matrix_right_solve(std::forward<ExecutionPolicy>(exec),
10556
+ A, t, d, B, X, divides<void>{});
10557
+ ```
10558
+
10559
+ #### Solve multiple triangular linear systems in-place <a id="linalg.algs.blas3.inplacetrsm">[[linalg.algs.blas3.inplacetrsm]]</a>
10560
+
10561
+ [*Note 1*: These functions correspond to the BLAS function
10562
+ `xTRSM`. — *end note*]
10563
+
10564
+ ``` cpp
10565
+ template<in-matrix InMat, class Triangle, class DiagonalStorage,
10566
+ inout-matrix InOutMat, class BinaryDivideOp>
10567
+ void triangular_matrix_matrix_left_solve(InMat A, Triangle t, DiagonalStorage d,
10568
+ InOutMat B, BinaryDivideOp divide);
10569
+ template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage,
10570
+ inout-matrix InOutMat, class BinaryDivideOp>
10571
+ void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec,
10572
+ InMat A, Triangle t, DiagonalStorage d,
10573
+ InOutMat B, BinaryDivideOp divide);
10574
+ ```
10575
+
10576
+ These functions perform multiple in-place matrix solves, taking into
10577
+ account the `Triangle` and `DiagonalStorage` parameters that apply to
10578
+ the triangular matrix `A` [[linalg.general]].
10579
+
10580
+ [*Note 1*: This algorithm makes it possible to compute factorizations
10581
+ like Cholesky and LU in place. Performing triangular solve in place
10582
+ hinders parallelization. However, other `ExecutionPolicy` specific
10583
+ optimizations, such as vectorization, are still possible. — *end note*]
10584
+
10585
+ *Mandates:*
10586
+
10587
+ - If `InMat` has `layout_blas_packed` layout, then the layout’s
10588
+ `Triangle` template argument has the same type as the function’s
10589
+ `Triangle` template argument;
10590
+ - *`possibly-multipliable`*`<InMat, InOutMat, InOutMat>()` is `true`;
10591
+ and
10592
+ - *`compatible-static-extents`*`<InMat, InMat>(0, 1)` is `true`.
10593
+
10594
+ *Preconditions:*
10595
+
10596
+ - *`multipliable`*`(A, B, B)` is `true`, and
10597
+ - `A.extent(0) == A.extent(1)` is `true`.
10598
+
10599
+ *Effects:* Computes X' such that AX' = B, and assigns each element of X'
10600
+ to the corresponding element of B. If so such X' exists, then the
10601
+ elements of `B` are valid but unspecified.
10602
+
10603
+ *Complexity:* 𝑂(`A.extent(0)` × `A.extent(1)` × `B.extent(1)`).
10604
+
10605
+ ``` cpp
10606
+ template<in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat>
10607
+ void triangular_matrix_matrix_left_solve(InMat A, Triangle t, DiagonalStorage d,
10608
+ InOutMat B);
10609
+ ```
10610
+
10611
+ *Effects:* Equivalent to:
10612
+
10613
+ ``` cpp
10614
+ triangular_matrix_matrix_left_solve(A, t, d, B, divides<void>{});
10615
+ ```
10616
+
10617
+ ``` cpp
10618
+ template<class ExecutionPolicy,
10619
+ in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat>
10620
+ void triangular_matrix_matrix_left_solve(ExecutionPolicy&& exec,
10621
+ InMat A, Triangle t, DiagonalStorage d,
10622
+ InOutMat B);
10623
+ ```
10624
+
10625
+ *Effects:* Equivalent to:
10626
+
10627
+ ``` cpp
10628
+ triangular_matrix_matrix_left_solve(std::forward<ExecutionPolicy>(exec),
10629
+ A, t, d, B, divides<void>{});
10630
+ ```
10631
+
10632
+ ``` cpp
10633
+ template<in-matrix InMat, class Triangle, class DiagonalStorage,
10634
+ inout-matrix InOutMat, class BinaryDivideOp>
10635
+ void triangular_matrix_matrix_right_solve(InMat A, Triangle t, DiagonalStorage d,
10636
+ InOutMat B, BinaryDivideOp divide);
10637
+ template<class ExecutionPolicy, in-matrix InMat, class Triangle, class DiagonalStorage,
10638
+ inout-matrix InOutMat, class BinaryDivideOp>
10639
+ void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec,
10640
+ InMat A, Triangle t, DiagonalStorage d,
10641
+ InOutMat B, BinaryDivideOp divide);
10642
+ ```
10643
+
10644
+ These functions perform multiple in-place matrix solves, taking into
10645
+ account the `Triangle` and `DiagonalStorage` parameters that apply to
10646
+ the triangular matrix `A` [[linalg.general]].
10647
+
10648
+ [*Note 2*: This algorithm makes it possible to compute factorizations
10649
+ like Cholesky and LU in place. Performing triangular solve in place
10650
+ hinders parallelization. However, other `ExecutionPolicy` specific
10651
+ optimizations, such as vectorization, are still possible. — *end note*]
10652
+
10653
+ *Mandates:*
10654
+
10655
+ - If `InMat` has `layout_blas_packed` layout, then the layout’s
10656
+ `Triangle` template argument has the same type as the function’s
10657
+ `Triangle` template argument;
10658
+ - *`possibly-multipliable`*`<InOutMat, InMat, InOutMat>()` is `true`;
10659
+ and
10660
+ - *`compatible-static-extents`*`<InMat, InMat>(0, 1)` is `true`.
10661
+
10662
+ *Preconditions:*
10663
+
10664
+ - *`multipliable`*`(B, A, B)` is `true`, and
10665
+ - `A.extent(0) == A.extent(1)` is `true`.
10666
+
10667
+ *Effects:* Computes X' such that X'A = B, and assigns each element of X'
10668
+ to the corresponding element of B. If so such X' exists, then the
10669
+ elements of `B` are valid but unspecified.
10670
+
10671
+ *Complexity:* 𝑂(`A.extent(0)` × `A.extent(1)` × `B.extent(1)`).
10672
+
10673
+ ``` cpp
10674
+ template<in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat>
10675
+ void triangular_matrix_matrix_right_solve(InMat A, Triangle t, DiagonalStorage d, InOutMat B);
10676
+ ```
10677
+
10678
+ *Effects:* Equivalent to:
10679
+
10680
+ ``` cpp
10681
+ triangular_matrix_matrix_right_solve(A, t, d, B, divides<void>{});
10682
+ ```
10683
+
10684
+ ``` cpp
10685
+ template<class ExecutionPolicy,
10686
+ in-matrix InMat, class Triangle, class DiagonalStorage, inout-matrix InOutMat>
10687
+ void triangular_matrix_matrix_right_solve(ExecutionPolicy&& exec,
10688
+ InMat A, Triangle t, DiagonalStorage d,
10689
+ InOutMat B);
10690
+ ```
10691
+
10692
+ *Effects:* Equivalent to:
10693
+
10694
+ ``` cpp
10695
+ triangular_matrix_matrix_right_solve(std::forward<ExecutionPolicy>(exec),
10696
+ A, t, d, B, divides<void>{});
10697
+ ```
10698
+
10699
+ ## Data-parallel types <a id="simd">[[simd]]</a>
10700
+
10701
+ ### General <a id="simd.general">[[simd.general]]</a>
10702
+
10703
+ Subclause [[simd]] defines data-parallel types and operations on these
10704
+ types.
10705
+
10706
+ [*Note 1*: The intent is to support acceleration through data-parallel
10707
+ execution resources where available, such as SIMD registers and
10708
+ instructions or execution units driven by a common instruction decoder.
10709
+ SIMD stands for “Single Instruction Stream – Multiple Data Stream”; it
10710
+ is defined in Flynn 1966. — *end note*]
10711
+
10712
+ The set of *vectorizable types* comprises
10713
+
10714
+ - all standard integer types, character types, and the types `float` and
10715
+ `double` [[basic.fundamental]];
10716
+ - `std::float16_t`, `std::float32_t`, and `std::float64_t` if defined
10717
+ [[basic.extended.fp]]; and
10718
+ - `complex<T>` where `T` is a vectorizable floating-point type.
10719
+
10720
+ The term *data-parallel type* refers to all enabled specializations of
10721
+ the `basic_vec` and `basic_mask` class templates. A
10722
+ *data-parallel object* is an object of data-parallel type.
10723
+
10724
+ Each specialization of `basic_vec` or `basic_mask` is either enabled or
10725
+ disabled, as described in [[simd.overview]] and [[simd.mask.overview]].
10726
+
10727
+ A data-parallel type consists of one or more elements of an underlying
10728
+ vectorizable type, called the *element type*. The number of elements is
10729
+ a constant for each data-parallel type and called the *width* of that
10730
+ type. The elements in a data-parallel type are indexed from 0 to
10731
+ $\textrm{width} - 1$.
10732
+
10733
+ An *element-wise operation* applies a specified operation to the
10734
+ elements of one or more data-parallel objects. Each such application is
10735
+ unsequenced with respect to the others. A *unary element-wise operation*
10736
+ is an element-wise operation that applies a unary operation to each
10737
+ element of a data-parallel object. A *binary element-wise operation* is
10738
+ an element-wise operation that applies a binary operation to
10739
+ corresponding elements of two data-parallel objects.
10740
+
10741
+ Given a `basic_mask<Bytes, Abi>` object `mask`, the *selected indices*
10742
+ signify the integers i in the range \[`0`, `mask.size()`) for which
10743
+ `mask[i]` is `true`. Given a data-parallel object `data`, the
10744
+ *selected elements* signify the elements `data[i]` for all selected
10745
+ indices i.
10746
+
10747
+ The conversion from an arithmetic type `U` to a vectorizable type `T` is
10748
+ *value-preserving* if all possible values of `U` can be represented with
10749
+ type `T`.
10750
+
10751
+ ### Exposition-only types, variables, and concepts <a id="simd.expos">[[simd.expos]]</a>
10752
+
10753
+ ``` cpp
10754
+ using simd-size-type = see belownc; // exposition only
10755
+ template<size_t Bytes> using integer-from = see belownc; // exposition only
10756
+
10757
+ template<class T, class Abi>
10758
+ constexpr simd-size-type simd-size-v = see belownc; // exposition only
10759
+ template<class T> constexpr size_t mask-element-size = see belownc; // exposition only
10760
+
10761
+ template<class T>
10762
+ concept constexpr-wrapper-like = // exposition only
10763
+ convertible_to<T, decltype(T::value)> &&
10764
+ equality_comparable_with<T, decltype(T::value)> &&
10765
+ bool_constant<T() == T::value>::value &&
10766
+ bool_constant<static_cast<decltype(T::value)>(T()) == T::value>::value;
10767
+
10768
+ template<class T> using deduced-vec-t = see belownc; // exposition only
10769
+
10770
+ template<class V, class T> using make-compatible-simd-t = see belownc; // exposition only
10771
+
10772
+ template<class V>
10773
+ concept simd-vec-type = // exposition only
10774
+ same_as<V, basic_vec<typename V::value_type, typename V::abi_type>> &&
10775
+ is_default_constructible_v<V>;
10776
+
10777
+ template<class V>
10778
+ concept simd-mask-type = // exposition only
10779
+ same_as<V, basic_mask<mask-element-size<V>, typename V::abi_type>> &&
10780
+ is_default_constructible_v<V>;
10781
+
10782
+ template<class V>
10783
+ concept simd-floating-point = // exposition only
10784
+ simd-vec-type<V> && floating_point<typename V::value_type>;
10785
+
10786
+ template<class V>
10787
+ concept simd-integral = // exposition only
10788
+ simd-vec-type<V> && integral<typename V::value_type>;
10789
+
10790
+ template<class V>
10791
+ using simd-complex-value-type = V::value_type::value_type; // exposition only
10792
+
10793
+ template<class V>
10794
+ concept simd-complex = // exposition only
10795
+ simd-vec-type<V> && same_as<typename V::value_type, complex<simd-complex-value-type<V>>>;
10796
+
10797
+ template<class... Ts>
10798
+ concept math-floating-point = // exposition only
10799
+ (exposition onlyconceptnc{simd-floating-point}<deduced-vec-t<Ts>> || ...);
10800
+
10801
+ template<class... Ts>
10802
+ requires exposition onlyconceptnc{math-floating-point}<Ts...>
10803
+ using math-common-simd-t = see belownc; // exposition only
10804
+
10805
+ template<class BinaryOperation, class T>
10806
+ concept exposition onlyconceptnc{reduction-binary-operation} = see belownc; // exposition only
10807
+
10808
+ // [simd.expos.abi], simd ABI tags
10809
+ template<class T> using native-abi = see belownc; // exposition only
10810
+ template<class T, simd-size-type N> using deduce-abi-t = see belownc@; // exposition only
10811
+
10812
+ // [simd.flags], load and store flags
10813
+ struct convert-flag; // exposition only
10814
+ struct aligned-flag; // exposition only
10815
+ template<size_t N> struct overaligned-flag; // exposition only
10816
+ ```
10817
+
10818
+ #### Exposition-only helpers <a id="simd.expos.defn">[[simd.expos.defn]]</a>
10819
+
10820
+ ``` cpp
10821
+ using simd-size-type = see below;
10822
+ ```
10823
+
10824
+ *simd-size-type* is an alias for a signed integer type.
10825
+
10826
+ ``` cpp
10827
+ template<size_t Bytes> using integer-from = see below;
10828
+ ```
10829
+
10830
+ *`integer-from`*`<Bytes>` is an alias for a signed integer type `T` such
10831
+ that `sizeof(T)` equals `Bytes`.
10832
+
10833
+ ``` cpp
10834
+ template<class T, class Abi>
10835
+ constexpr simd-size-type simd-size-v = see below;
10836
+ ```
10837
+
10838
+ *`simd-size-v`*`<T, Abi>` denotes the width of `basic_vec<T, Abi>` if
10839
+ the specialization `basic_vec<T, Abi>` is enabled, or `0` otherwise.
10840
+
10841
+ ``` cpp
10842
+ template<class T> constexpr size_t mask-element-size = see below;
10843
+ ```
10844
+
10845
+ *`mask-element-size`*`<basic_mask<Bytes, Abi>>` has the value `Bytes`.
10846
+
10847
+ ``` cpp
10848
+ template<class T> using deduced-vec-t = see below;
10849
+ ```
10850
+
10851
+ Let `x` denote an lvalue of type `const T`.
10852
+
10853
+ *`deduced-vec-t`*`<T>` is an alias for
10854
+
10855
+ - `decltype(x + x)`, if the type of `x + x` is an enabled specialization
10856
+ of `basic_vec`; otherwise
10857
+ - `void`.
10858
+
10859
+ ``` cpp
10860
+ template<class V, class T> using make-compatible-simd-t = see below;
10861
+ ```
10862
+
10863
+ Let `x` denote an lvalue of type `const T`.
10864
+
10865
+ *`make-compatible-simd-t`*`<V, T>` is an alias for
10866
+
10867
+ - *`deduced-vec-t`*`<T>`, if that type is not `void`, otherwise
10868
+ - `vec<decltype(x + x), V::size()>`.
10869
+
10870
+ ``` cpp
10871
+ template<class... Ts>
10872
+ requires math-floating-point<Ts...>
10873
+ using math-common-simd-t = see below;
10874
+ ```
10875
+
10876
+ Let `T0` denote `Ts...[0]`. Let `T1` denote `Ts...[1]`. Let `TRest`
10877
+ denote a pack such that `T0, T1, TRest...` is equivalent to `Ts...`.
10878
+
10879
+ Let *`math-common-simd-t`*`<Ts...>` be an alias for
10880
+
10881
+ - *`deduced-vec-t`*`<T0>`, if `sizeof...(Ts)` equals 1; otherwise
10882
+ - `common_type_t<`*`deduced-vec-t`*`<T0>, `*`deduced-vec-t`*`<T1>>`, if
10883
+ `sizeof...(Ts)` equals 2 and
10884
+ `math-floating-point<T0> && math-floating-point<T1>` is `true`;
10885
+ otherwise
10886
+ - `common_type_t<`*`deduced-vec-t`*`<T0>, T1>`, if `sizeof...(Ts)`
10887
+ equals 2 and *`math-floating-point`*`<T0>` is `true`; otherwise
10888
+ - `common_type_t<T0, `*`deduced-vec-t`*`<T1>>`, if `sizeof...(Ts)`
10889
+ equals 2; otherwise
10890
+ - `common_type_t<`*`math-common-simd-t`*`<T0, T1>, TRest...>`, if
10891
+ *`math-common-simd-t`*`<T0, T1>` is valid and denotes a type;
10892
+ otherwise
10893
+ - `common_type_t<`*`math-common-simd-t`*`<TRest...>, T0, T1>`.
10894
+
10895
+ ``` cpp
10896
+ template<class BinaryOperation, class T>
10897
+ concept reduction-binary-operation =
10898
+ requires (const BinaryOperation binary_op, const vec<T, 1> v) {
10899
+ { binary_op(v, v) } -> same_as<vec<T, 1>>;
10900
+ };
10901
+ ```
10902
+
10903
+ Types `BinaryOperation` and `T` model
10904
+ `reduction-binary-operation<BinaryOperation, T>` only if:
10905
+
10906
+ - `BinaryOperation` is a binary element-wise operation and the operation
10907
+ is commutative.
10908
+ - An object of type `BinaryOperation` can be invoked with two arguments
10909
+ of type `basic_vec<T, Abi>`, with unspecified ABI tag `Abi`, returning
10910
+ a `basic_vec<T, Abi>`.
10911
+
10912
+ #### `simd` ABI tags <a id="simd.expos.abi">[[simd.expos.abi]]</a>
10913
+
10914
+ ``` cpp
10915
+ template<class T> using native-abi = see below;
10916
+ template<class T, simd-size-type N> using deduce-abi-t = see below;
10917
+ ```
10918
+
10919
+ An *ABI tag* is a type that indicates a choice of size and binary
10920
+ representation for objects of data-parallel type.
10921
+
10922
+ [*Note 1*: The intent is for the size and binary representation to
10923
+ depend on the target architecture and compiler flags. The ABI tag,
10924
+ together with a given element type, implies the width. — *end note*]
10925
+
10926
+ [*Note 2*: The ABI tag is orthogonal to selecting the machine
10927
+ instruction set. The selected machine instruction set limits the usable
10928
+ ABI tag types, though (see [[simd.overview]]). The ABI tags enable users
10929
+ to safely pass objects of data-parallel type between translation unit
10930
+ boundaries (e.g., function calls or I/O). — *end note*]
10931
+
10932
+ An implementation defines ABI tag types as necessary for the following
10933
+ aliases.
10934
+
10935
+ *`deduce-abi-t`*`<T, N>` is defined if
10936
+
10937
+ - `T` is a vectorizable type,
10938
+ - `N` is greater than zero, and
10939
+ - `N` is not larger than an implementation-defined maximum.
10940
+
10941
+ The *implementation-defined* maximum for `N` is not smaller than 64 and
10942
+ can differ depending on `T`.
10943
+
10944
+ Where present, *`deduce-abi-t`*`<T, N>` names an ABI tag type such that
10945
+
10946
+ - *`simd-size-v`*`<T, `*`deduce-abi-t`*`<T, N>>` equals `N`,
10947
+ - `basic_vec<T, `*`deduce-abi-t`*`<T, N>>` is enabled [[simd.overview]],
10948
+ and
10949
+ - `basic_mask<sizeof(T), `*`deduce-abi-t`*`<`*`integer-from`*`<sizeof(T)>, N>>`
10950
+ is enabled.
10951
+
10952
+ *`native-abi`*`<T>` is an *implementation-defined* alias for an ABI tag.
10953
+ `basic_vec<T, `*`native-abi`*`<T>>` is an enabled specialization.
10954
+
10955
+ [*Note 3*: The intent is to use the ABI tag producing the most
10956
+ efficient data-parallel execution for the element type `T` on the
10957
+ currently targeted system. For target architectures with ISA extensions,
10958
+ compiler flags can change the type of the *`native-abi`*`<T>`
10959
+ alias. — *end note*]
10960
+
10961
+ [*Example 1*:
10962
+
10963
+ Consider a target architecture supporting the ABI tags `__simd128` and
10964
+ `__simd256`, where hardware support for `__simd256` exists only for
10965
+ floating-point types. The implementation therefore defines
10966
+ *`native-abi`*`<T>` as an alias for
10967
+
10968
+ - `__simd256` if `T` is a floating-point type, and
10969
+ - `__simd128` otherwise.
10970
+
10971
+ — *end example*]
10972
+
10973
+ ### Header `<simd>` synopsis <a id="simd.syn">[[simd.syn]]</a>
10974
+
10975
+ ``` cpp
10976
+ namespace std::simd {
10977
+ // [simd.traits], type traits
10978
+ template<class T, class U = typename T::value_type> struct alignment;
10979
+ template<class T, class U = typename T::value_type>
10980
+ constexpr size_t alignment_v = alignment<T, U>::value;
10981
+
10982
+ template<class T, class V> struct rebind { using type = see below; };
10983
+ template<class T, class V> using rebind_t = rebind<T, V>::type;
10984
+ template<simd-size-type N, class V> struct resize { using type = see below; };
10985
+ template<simd-size-type N, class V> using resize_t = resize<N, V>::type;
10986
+
10987
+ // [simd.flags], load and store flags
10988
+ template<class... Flags> struct flags;
10989
+ inline constexpr flags<> flag_default{};
10990
+ inline constexpr flags<convert-flag> flag_convert{};
10991
+ inline constexpr flags<aligned-flag> flag_aligned{};
10992
+ template<size_t N> requires (has_single_bit(N))
10993
+ constexpr flags<overaligned-flag<N>> flag_overaligned{};
10994
+
10995
+ // [simd.iterator], class template simd-iterator
10996
+ template<class V>
10997
+ class simd-iterator; // exposition only
10998
+
10999
+ // [simd.class], class template basic_vec
11000
+ template<class T, class Abi = native-abi<T>> class basic_vec;
11001
+ template<class T, simd-size-type N = simd-size-v<T, native-abi<T>>>
11002
+ using vec = basic_vec<T, deduce-abi-t<T, N>>;
11003
+
11004
+ // [simd.reductions], reductions
11005
+ template<class T, class Abi, class BinaryOperation = plus<>>
11006
+ constexpr T reduce(const basic_vec<T, Abi>&, BinaryOperation = {});
11007
+ template<class T, class Abi, class BinaryOperation = plus<>>
11008
+ constexpr T reduce(
11009
+ const basic_vec<T, Abi>& x, const typename basic_vec<T, Abi>::mask_type& mask,
11010
+ BinaryOperation binary_op = {}, type_identity_t<T> identity_element = see below);
11011
+
11012
+ template<class T, class Abi>
11013
+ constexpr T reduce_min(const basic_vec<T, Abi>&) noexcept;
11014
+ template<class T, class Abi>
11015
+ constexpr T reduce_min(const basic_vec<T, Abi>&,
11016
+ const typename basic_vec<T, Abi>::mask_type&) noexcept;
11017
+ template<class T, class Abi>
11018
+ constexpr T reduce_max(const basic_vec<T, Abi>&) noexcept;
11019
+ template<class T, class Abi>
11020
+ constexpr T reduce_max(const basic_vec<T, Abi>&,
11021
+ const typename basic_vec<T, Abi>::mask_type&) noexcept;
11022
+
11023
+ // [simd.loadstore], load and store functions
11024
+ template<class V = see below, ranges::contiguous_range R, class... Flags>
11025
+ requires ranges::sized_range<R>
11026
+ constexpr V unchecked_load(R&& r, flags<Flags...> f = {});
11027
+ template<class V = see below, ranges::contiguous_range R, class... Flags>
11028
+ requires ranges::sized_range<R>
11029
+ constexpr V unchecked_load(R&& r, const typename V::mask_type& k,
11030
+ flags<Flags...> f = {});
11031
+ template<class V = see below, contiguous_iterator I, class... Flags>
11032
+ constexpr V unchecked_load(I first, iter_difference_t<I> n,
11033
+ flags<Flags...> f = {});
11034
+ template<class V = see below, contiguous_iterator I, class... Flags>
11035
+ constexpr V unchecked_load(I first, iter_difference_t<I> n,
11036
+ const typename V::mask_type& k, flags<Flags...> f = {});
11037
+ template<class V = see below, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags>
11038
+ constexpr V unchecked_load(I first, S last, flags<Flags...> f = {});
11039
+ template<class V = see below, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags>
11040
+ constexpr V unchecked_load(I first, S last, const typename V::mask_type& k,
11041
+ flags<Flags...> f = {});
11042
+
11043
+ template<class V = see below, ranges::contiguous_range R, class... Flags>
11044
+ requires ranges::sized_range<R>
11045
+ constexpr V partial_load(R&& r, flags<Flags...> f = {});
11046
+ template<class V = see below, ranges::contiguous_range R, class... Flags>
11047
+ requires ranges::sized_range<R>
11048
+ constexpr V partial_load(R&& r, const typename V::mask_type& k,
11049
+ flags<Flags...> f = {});
11050
+ template<class V = see below, contiguous_iterator I, class... Flags>
11051
+ constexpr V partial_load(I first, iter_difference_t<I> n, flags<Flags...> f = {});
11052
+ template<class V = see below, contiguous_iterator I, class... Flags>
11053
+ constexpr V partial_load(I first, iter_difference_t<I> n,
11054
+ const typename V::mask_type& k, flags<Flags...> f = {});
11055
+ template<class V = see below, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags>
11056
+ constexpr V partial_load(I first, S last, flags<Flags...> f = {});
11057
+ template<class V = see below, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags>
11058
+ constexpr V partial_load(I first, S last, const typename V::mask_type& k,
11059
+ flags<Flags...> f = {});
11060
+
11061
+ template<class T, class Abi, ranges::contiguous_range R, class... Flags>
11062
+ requires ranges::sized_range<R> && indirectly_writable<ranges::iterator_t<R>, T>
11063
+ constexpr void unchecked_store(const basic_vec<T, Abi>& v, R&& r,
11064
+ flags<Flags...> f = {});
11065
+ template<class T, class Abi, ranges::contiguous_range R, class... Flags>
11066
+ requires ranges::sized_range<R> && indirectly_writable<ranges::iterator_t<R>, T>
11067
+ constexpr void unchecked_store(const basic_vec<T, Abi>& v, R&& r,
11068
+ const typename basic_vec<T, Abi>::mask_type& mask, flags<Flags...> f = {});
11069
+ template<class T, class Abi, contiguous_iterator I, class... Flags>
11070
+ requires indirectly_writable<I, T>
11071
+ constexpr void unchecked_store(const basic_vec<T, Abi>& v, I first,
11072
+ iter_difference_t<I> n, flags<Flags...> f = {});
11073
+ template<class T, class Abi, contiguous_iterator I, class... Flags>
11074
+ requires indirectly_writable<I, T>
11075
+ constexpr void unchecked_store(const basic_vec<T, Abi>& v, I first,
11076
+ iter_difference_t<I> n, const typename basic_vec<T, Abi>::mask_type& mask,
11077
+ flags<Flags...> f = {});
11078
+ template<class T, class Abi, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags>
11079
+ requires indirectly_writable<I, T>
11080
+ constexpr void unchecked_store(const basic_vec<T, Abi>& v, I first, S last,
11081
+ flags<Flags...> f = {});
11082
+ template<class T, class Abi, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags>
11083
+ requires indirectly_writable<I, T>
11084
+ constexpr void unchecked_store(const basic_vec<T, Abi>& v, I first, S last,
11085
+ const typename basic_vec<T, Abi>::mask_type& mask, flags<Flags...> f = {});
11086
+
11087
+ template<class T, class Abi, ranges::contiguous_range R, class... Flags>
11088
+ requires ranges::sized_range<R> && indirectly_writable<ranges::iterator_t<R>, T>
11089
+ constexpr void partial_store(const basic_vec<T, Abi>& v, R&& r,
11090
+ flags<Flags...> f = {});
11091
+ template<class T, class Abi, ranges::contiguous_range R, class... Flags>
11092
+ requires ranges::sized_range<R> && indirectly_writable<ranges::iterator_t<R>, T>
11093
+ constexpr void partial_store(const basic_vec<T, Abi>& v, R&& r,
11094
+ const typename basic_vec<T, Abi>::mask_type& mask, flags<Flags...> f = {});
11095
+ template<class T, class Abi, contiguous_iterator I, class... Flags>
11096
+ requires indirectly_writable<I, T>
11097
+ constexpr void partial_store(
11098
+ const basic_vec<T, Abi>& v, I first, iter_difference_t<I> n, flags<Flags...> f = {});
11099
+ template<class T, class Abi, contiguous_iterator I, class... Flags>
11100
+ requires indirectly_writable<I, T>
11101
+ constexpr void partial_store(
11102
+ const basic_vec<T, Abi>& v, I first, iter_difference_t<I> n,
11103
+ const typename basic_vec<T, Abi>::mask_type& mask, flags<Flags...> f = {});
11104
+ template<class T, class Abi, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags>
11105
+ requires indirectly_writable<I, T>
11106
+ constexpr void partial_store(const basic_vec<T, Abi>& v, I first, S last,
11107
+ flags<Flags...> f = {});
11108
+ template<class T, class Abi, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags>
11109
+ requires indirectly_writable<I, T>
11110
+ constexpr void partial_store(const basic_vec<T, Abi>& v, I first, S last,
11111
+ const typename basic_vec<T, Abi>::mask_type& mask, flags<Flags...> f = {});
11112
+
11113
+ // [simd.permute.static], static permute
11114
+ static constexpr simd-size-type zero_element = implementation-defined // value of simd::zero_element;
11115
+ static constexpr simd-size-type uninit_element = implementation-defined // value of simd::uninit_element;
11116
+
11117
+ template<simd-size-type N = see below, simd-vec-type V, class IdxMap>
11118
+ constexpr resize_t<N, V> permute(const V& v, IdxMap&& idxmap);
11119
+ template<simd-size-type N = see below, simd-mask-type M, class IdxMap>
11120
+ constexpr resize_t<N, M> permute(const M& v, IdxMap&& idxmap);
11121
+
11122
+ // [simd.permute.dynamic], dynamic permute
11123
+ template<simd-vec-type V, simd-integral I>
11124
+ constexpr resize_t<I::size(), V> permute(const V& v, const I& indices);
11125
+ template<simd-mask-type M, simd-integral I>
11126
+ constexpr resize_t<I::size(), M> permute(const M& v, const I& indices);
11127
+
11128
+ // [simd.permute.mask], mask permute
11129
+ template<simd-vec-type V>
11130
+ constexpr V compress(const V& v, const typename V::mask_type& selector);
11131
+ template<simd-mask-type M>
11132
+ constexpr M compress(const M& v, const type_identity_t<M>& selector);
11133
+ template<simd-vec-type V>
11134
+ constexpr V compress(const V& v, const typename V::mask_type& selector,
11135
+ const typename V::value_type& fill_value);
11136
+ template<simd-mask-type M>
11137
+ constexpr M compress(const M& v, const type_identity_t<M>& selector,
11138
+ const typename M::value_type& fill_value);
11139
+
11140
+ template<simd-vec-type V>
11141
+ constexpr V expand(const V& v, const typename V::mask_type& selector,
11142
+ const V& original = {});
11143
+ template<simd-mask-type M>
11144
+ constexpr M expand(const M& v, const type_identity_t<M>& selector,
11145
+ const M& original = {});
11146
+
11147
+ // [simd.permute.memory], memory permute
11148
+ template<class V = see below, ranges::contiguous_range R, simd-integral I, class... Flags>
11149
+ requires ranges::sized_range<R>
11150
+ constexpr V unchecked_gather_from(R&& in, const I& indices, flags<Flags...> f = {});
11151
+ template<class V = see below, ranges::contiguous_range R, simd-integral I, class... Flags>
11152
+ requires ranges::sized_range<R>
11153
+ constexpr V unchecked_gather_from(R&& in, const typename I::mask_type& mask,
11154
+ const I& indices, flags<Flags...> f = {});
11155
+
11156
+ template<class V = see below, ranges::contiguous_range R, simd-integral I, class... Flags>
11157
+ requires ranges::sized_range<R>
11158
+ constexpr V partial_gather_from(R&& in, const I& indices, flags<Flags...> f = {});
11159
+ template<class V = see below, ranges::contiguous_range R, simd-integral I, class... Flags>
11160
+ requires ranges::sized_range<R>
11161
+ constexpr V partial_gather_from(R&& in, const typename I::mask_type& mask,
11162
+ const I& indices, flags<Flags...> f = {});
11163
+
11164
+ template<simd-vec-type V, ranges::contiguous_range R, simd-integral I, class... Flags>
11165
+ requires ranges::sized_range<R>
11166
+ constexpr void unchecked_scatter_to(const V& v, R&& out,
11167
+ const I& indices, flags<Flags...> f = {});
11168
+ template<simd-vec-type V, ranges::contiguous_range R, simd-integral I, class... Flags>
11169
+ requires ranges::sized_range<R>
11170
+ constexpr void unchecked_scatter_to(const V& v, R&& out, const typename I::mask_type& mask,
11171
+ const I& indices, flags<Flags...> f = {});
11172
+
11173
+ template<simd-vec-type V, ranges::contiguous_range R, simd-integral I, class... Flags>
11174
+ requires ranges::sized_range<R>
11175
+ constexpr void partial_scatter_to(const V& v, R&& out,
11176
+ const I& indices, flags<Flags...> f = {});
11177
+ template<simd-vec-type V, ranges::contiguous_range R, simd-integral I, class... Flags>
11178
+ requires ranges::sized_range<R>
11179
+ constexpr void partial_scatter_to(const V& v, R&& out, const typename I::mask_type& mask,
11180
+ const I& indices, flags<Flags...> f = {});
11181
+
11182
+ // [simd.creation], creation
11183
+ template<class T, class Abi>
11184
+ constexpr auto chunk(const basic_vec<typename T::value_type, Abi>& x) noexcept;
11185
+ template<class T, class Abi>
11186
+ constexpr auto chunk(const basic_mask<mask-element-size<T>, Abi>& x) noexcept;
11187
+
11188
+ template<simd-size-type N, class T, class Abi>
11189
+ constexpr auto chunk(const basic_vec<T, Abi>& x) noexcept;
11190
+ template<simd-size-type N, size_t Bytes, class Abi>
11191
+ constexpr auto chunk(const basic_mask<Bytes, Abi>& x) noexcept;
11192
+
11193
+ template<class T, class... Abis>
11194
+ constexpr basic_vec<T, deduce-abi-t<T, (basic_vec<T, Abis>::size() + ...)>>
11195
+ cat(const basic_vec<T, Abis>&...) noexcept;
11196
+ template<size_t Bytes, class... Abis>
11197
+ constexpr basic_mask<Bytes, deduce-abi-t<integer-from<Bytes>,
11198
+ (basic_mask<Bytes, Abis>::size() + ...)>>
11199
+ cat(const basic_mask<Bytes, Abis>&...) noexcept;
11200
+
11201
+ // [simd.alg], algorithms
11202
+ template<class T, class Abi>
11203
+ constexpr basic_vec<T, Abi>
11204
+ min(const basic_vec<T, Abi>& a, const basic_vec<T, Abi>& b) noexcept;
11205
+ template<class T, class Abi>
11206
+ constexpr basic_vec<T, Abi>
11207
+ max(const basic_vec<T, Abi>& a, const basic_vec<T, Abi>& b) noexcept;
11208
+ template<class T, class Abi>
11209
+ constexpr pair<basic_vec<T, Abi>, basic_vec<T, Abi>>
11210
+ minmax(const basic_vec<T, Abi>& a, const basic_vec<T, Abi>& b) noexcept;
11211
+ template<class T, class Abi>
11212
+ constexpr basic_vec<T, Abi>
11213
+ clamp(const basic_vec<T, Abi>& v, const basic_vec<T, Abi>& lo,
11214
+ const basic_vec<T, Abi>& hi);
11215
+
11216
+ template<class T, class U>
11217
+ constexpr auto select(bool c, const T& a, const U& b)
11218
+ -> remove_cvref_t<decltype(c ? a : b)>;
11219
+ template<size_t Bytes, class Abi, class T, class U>
11220
+ constexpr auto select(const basic_mask<Bytes, Abi>& c, const T& a, const U& b)
11221
+ noexcept -> decltype(simd-select-impl(c, a, b));
11222
+
11223
+ // [simd.math], mathematical functions
11224
+ template<math-floating-point V> constexpr deduced-vec-t<V> acos(const V& x);
11225
+ template<math-floating-point V> constexpr deduced-vec-t<V> asin(const V& x);
11226
+ template<math-floating-point V> constexpr deduced-vec-t<V> atan(const V& x);
11227
+ template<class V0, class V1>
11228
+ constexpr math-common-simd-t<V0, V1> atan2(const V0& y, const V1& x);
11229
+ template<math-floating-point V> constexpr deduced-vec-t<V> cos(const V& x);
11230
+ template<math-floating-point V> constexpr deduced-vec-t<V> sin(const V& x);
11231
+ template<math-floating-point V> constexpr deduced-vec-t<V> tan(const V& x);
11232
+ template<math-floating-point V> constexpr deduced-vec-t<V> acosh(const V& x);
11233
+ template<math-floating-point V> constexpr deduced-vec-t<V> asinh(const V& x);
11234
+ template<math-floating-point V> constexpr deduced-vec-t<V> atanh(const V& x);
11235
+ template<math-floating-point V> constexpr deduced-vec-t<V> cosh(const V& x);
11236
+ template<math-floating-point V> constexpr deduced-vec-t<V> sinh(const V& x);
11237
+ template<math-floating-point V> constexpr deduced-vec-t<V> tanh(const V& x);
11238
+ template<math-floating-point V> constexpr deduced-vec-t<V> exp(const V& x);
11239
+ template<math-floating-point V> constexpr deduced-vec-t<V> exp2(const V& x);
11240
+ template<math-floating-point V> constexpr deduced-vec-t<V> expm1(const V& x);
11241
+ template<math-floating-point V>
11242
+ constexpr deduced-vec-t<V>
11243
+ frexp(const V& value, rebind_t<int, deduced-vec-t<V>>* exp);
11244
+ template<math-floating-point V>
11245
+ constexpr rebind_t<int, deduced-vec-t<V>> ilogb(const V& x);
11246
+ template<math-floating-point V>
11247
+ constexpr deduced-vec-t<V> ldexp(const V& x, const rebind_t<int, deduced-vec-t<V>>& exp);
11248
+ template<math-floating-point V> constexpr deduced-vec-t<V> log(const V& x);
11249
+ template<math-floating-point V> constexpr deduced-vec-t<V> log10(const V& x);
11250
+ template<math-floating-point V> constexpr deduced-vec-t<V> log1p(const V& x);
11251
+ template<math-floating-point V> constexpr deduced-vec-t<V> log2(const V& x);
11252
+ template<math-floating-point V> constexpr deduced-vec-t<V> logb(const V& x);
11253
+ template<class T, class Abi>
11254
+ constexpr basic_vec<T, Abi>
11255
+ modf(const type_identity_t<basic_vec<T, Abi>>& value, basic_vec<T, Abi>* iptr);
11256
+ template<math-floating-point V>
11257
+ constexpr deduced-vec-t<V> scalbn(const V& x, const rebind_t<int, deduced-vec-t<V>>& n);
11258
+ template<math-floating-point V>
11259
+ constexpr deduced-vec-t<V> scalbln(
11260
+ const V& x, const rebind_t<long int, deduced-vec-t<V>>& n);
11261
+ template<math-floating-point V> constexpr deduced-vec-t<V> cbrt(const V& x);
11262
+ template<signed_integral T, class Abi>
11263
+ constexpr basic_vec<T, Abi> abs(const basic_vec<T, Abi>& j);
11264
+ template<math-floating-point V> constexpr deduced-vec-t<V> abs(const V& j);
11265
+ template<math-floating-point V> constexpr deduced-vec-t<V> fabs(const V& x);
11266
+ template<class V0, class V1>
11267
+ constexpr math-common-simd-t<V0, V1> hypot(const V0& x, const V1& y);
11268
+ template<class V0, class V1, class V2>
11269
+ constexpr math-common-simd-t<V0, V1, V2> hypot(const V0& x, const V1& y, const V2& z);
11270
+ template<class V0, class V1>
11271
+ constexpr math-common-simd-t<V0, V1> pow(const V0& x, const V1& y);
11272
+ template<math-floating-point V> constexpr deduced-vec-t<V> sqrt(const V& x);
11273
+ template<math-floating-point V> constexpr deduced-vec-t<V> erf(const V& x);
11274
+ template<math-floating-point V> constexpr deduced-vec-t<V> erfc(const V& x);
11275
+ template<math-floating-point V> constexpr deduced-vec-t<V> lgamma(const V& x);
11276
+ template<math-floating-point V> constexpr deduced-vec-t<V> tgamma(const V& x);
11277
+ template<math-floating-point V> constexpr deduced-vec-t<V> ceil(const V& x);
11278
+ template<math-floating-point V> constexpr deduced-vec-t<V> floor(const V& x);
11279
+ template<math-floating-point V> deduced-vec-t<V> nearbyint(const V& x);
11280
+ template<math-floating-point V> deduced-vec-t<V> rint(const V& x);
11281
+ template<math-floating-point V>
11282
+ rebind_t<long int, deduced-vec-t<V>> lrint(const V& x);
11283
+ template<math-floating-point V>
11284
+ rebind_t<long long int, V> llrint(const deduced-vec-t<V>& x);
11285
+ template<math-floating-point V>
11286
+ constexpr deduced-vec-t<V> round(const V& x);
11287
+ template<math-floating-point V>
11288
+ constexpr rebind_t<long int, deduced-vec-t<V>> lround(const V& x);
11289
+ template<math-floating-point V>
11290
+ constexpr rebind_t<long long int, deduced-vec-t<V>> llround(const V& x);
11291
+ template<math-floating-point V>
11292
+ constexpr deduced-vec-t<V> trunc(const V& x);
11293
+ template<class V0, class V1>
11294
+ constexpr math-common-simd-t<V0, V1> fmod(const V0& x, const V1& y);
11295
+ template<class V0, class V1>
11296
+ constexpr math-common-simd-t<V0, V1> remainder(const V0& x, const V1& y);
11297
+ template<class V0, class V1>
11298
+ constexpr math-common-simd-t<V0, V1>
11299
+ remquo(const V0& x, const V1& y, rebind_t<int, math-common-simd-t<V0, V1>>* quo);
11300
+ template<class V0, class V1>
11301
+ constexpr math-common-simd-t<V0, V1> copysign(const V0& x, const V1& y);
11302
+ template<class V0, class V1>
11303
+ constexpr math-common-simd-t<V0, V1> nextafter(const V0& x, const V1& y);
11304
+ template<class V0, class V1>
11305
+ constexpr math-common-simd-t<V0, V1> fdim(const V0& x, const V1& y);
11306
+ template<class V0, class V1>
11307
+ constexpr math-common-simd-t<V0, V1> fmax(const V0& x, const V1& y);
11308
+ template<class V0, class V1>
11309
+ constexpr math-common-simd-t<V0, V1> fmin(const V0& x, const V1& y);
11310
+ template<class V0, class V1, class V2>
11311
+ constexpr math-common-simd-t<V0, V1, V2> fma(const V0& x, const V1& y, const V2& z);
11312
+ template<class V0, class V1, class V2>
11313
+ constexpr math-common-simd-t<V0, V1, V2>
11314
+ lerp(const V0& a, const V1& b, const V2& t) noexcept;
11315
+ template<math-floating-point V>
11316
+ constexpr rebind_t<int, deduced-vec-t<V>> fpclassify(const V& x);
11317
+ template<math-floating-point V>
11318
+ constexpr typename deduced-vec-t<V>::mask_type isfinite(const V& x);
11319
+ template<math-floating-point V>
11320
+ constexpr typename deduced-vec-t<V>::mask_type isinf(const V& x);
11321
+ template<math-floating-point V>
11322
+ constexpr typename deduced-vec-t<V>::mask_type isnan(const V& x);
11323
+ template<math-floating-point V>
11324
+ constexpr typename deduced-vec-t<V>::mask_type isnormal(const V& x);
11325
+ template<math-floating-point V>
11326
+ constexpr typename deduced-vec-t<V>::mask_type signbit(const V& x);
11327
+ template<class V0, class V1>
11328
+ constexpr typename math-common-simd-t<V0, V1>::mask_type
11329
+ isgreater(const V0& x, const V1& y);
11330
+ template<class V0, class V1>
11331
+ constexpr typename math-common-simd-t<V0, V1>::mask_type
11332
+ isgreaterequal(const V0& x, const V1& y);
11333
+ template<class V0, class V1>
11334
+ constexpr typename math-common-simd-t<V0, V1>::mask_type
11335
+ isless(const V0& x, const V1& y);
11336
+ template<class V0, class V1>
11337
+ constexpr typename math-common-simd-t<V0, V1>::mask_type
11338
+ islessequal(const V0& x, const V1& y);
11339
+ template<class V0, class V1>
11340
+ constexpr typename math-common-simd-t<V0, V1>::mask_type
11341
+ islessgreater(const V0& x, const V1& y);
11342
+ template<class V0, class V1>
11343
+ constexpr typename math-common-simd-t<V0, V1>::mask_type
11344
+ isunordered(const V0& x, const V1& y);
11345
+ template<math-floating-point V>
11346
+ deduced-vec-t<V> assoc_laguerre(const rebind_t<unsigned, deduced-vec-t<V>>& n,
11347
+ const rebind_t<unsigned, deduced-vec-t<V>>& m, const V& x);
11348
+ template<math-floating-point V>
11349
+ deduced-vec-t<V> assoc_legendre(const rebind_t<unsigned, deduced-vec-t<V>>& l,
11350
+ const rebind_t<unsigned, deduced-vec-t<V>>& m, const V& x);
11351
+ template<class V0, class V1>
11352
+ math-common-simd-t<V0, V1> beta(const V0& x, const V1& y);
11353
+ template<math-floating-point V> deduced-vec-t<V> comp_ellint_1(const V& k);
11354
+ template<math-floating-point V> deduced-vec-t<V> comp_ellint_2(const V& k);
11355
+ template<class V0, class V1>
11356
+ math-common-simd-t<V0, V1> comp_ellint_3(const V0& k, const V1& nu);
11357
+ template<class V0, class V1>
11358
+ math-common-simd-t<V0, V1> cyl_bessel_i(const V0& nu, const V1& x);
11359
+ template<class V0, class V1>
11360
+ math-common-simd-t<V0, V1> cyl_bessel_j(const V0& nu, const V1& x);
11361
+ template<class V0, class V1>
11362
+ math-common-simd-t<V0, V1> cyl_bessel_k(const V0& nu, const V1& x);
11363
+ template<class V0, class V1>
11364
+ math-common-simd-t<V0, V1> cyl_neumann(const V0& nu, const V1& x);
11365
+ template<class V0, class V1>
11366
+ math-common-simd-t<V0, V1> ellint_1(const V0& k, const V1& phi);
11367
+ template<class V0, class V1>
11368
+ math-common-simd-t<V0, V1> ellint_2(const V0& k, const V1& phi);
11369
+ template<class V0, class V1, class V2>
11370
+ math-common-simd-t<V0, V1, V2> ellint_3(const V0& k, const V1& nu, const V2& phi);
11371
+ template<math-floating-point V> deduced-vec-t<V> expint(const V& x);
11372
+ template<math-floating-point V>
11373
+ deduced-vec-t<V> hermite(const rebind_t<unsigned, deduced-vec-t<V>>& n, const V& x);
11374
+ template<math-floating-point V>
11375
+ deduced-vec-t<V> laguerre(const rebind_t<unsigned, deduced-vec-t<V>>& n, const V& x);
11376
+ template<math-floating-point V>
11377
+ deduced-vec-t<V> legendre(const rebind_t<unsigned, deduced-vec-t<V>>& l, const V& x);
11378
+ template<math-floating-point V>
11379
+ deduced-vec-t<V> riemann_zeta(const V& x);
11380
+ template<math-floating-point V>
11381
+ deduced-vec-t<V> sph_bessel(
11382
+ const rebind_t<unsigned, deduced-vec-t<V>>& n, const V& x);
11383
+ template<math-floating-point V>
11384
+ deduced-vec-t<V> sph_legendre(const rebind_t<unsigned, deduced-vec-t<V>>& l,
11385
+ const rebind_t<unsigned, deduced-vec-t<V>>& m, const V& theta);
11386
+ template<math-floating-point V>
11387
+ deduced-vec-t<V>
11388
+ sph_neumann(const rebind_t<unsigned, deduced-vec-t<V>>& n, const V& x);
11389
+
11390
+ // [simd.bit], bit manipulation
11391
+ template<simd-vec-type V> constexpr V byteswap(const V& v) noexcept;
11392
+ template<simd-vec-type V> constexpr V bit_ceil(const V& v) noexcept;
11393
+ template<simd-vec-type V> constexpr V bit_floor(const V& v) noexcept;
11394
+
11395
+ template<simd-vec-type V>
11396
+ constexpr typename V::mask_type has_single_bit(const V& v) noexcept;
11397
+
11398
+ template<simd-vec-type V0, simd-vec-type V1>
11399
+ constexpr V0 rotl(const V0& v, const V1& s) noexcept;
11400
+ template<simd-vec-type V>
11401
+ constexpr V rotl(const V& v, int s) noexcept;
11402
+
11403
+ template<simd-vec-type V0, simd-vec-type V1>
11404
+ constexpr V0 rotr(const V0& v, const V1& s) noexcept;
11405
+ template<simd-vec-type V>
11406
+ constexpr V rotr(const V& v, int s) noexcept;
11407
+
11408
+ template<simd-vec-type V>
11409
+ constexpr rebind_t<make_signed_t<typename V::value_type>, V>
11410
+ bit_width(const V& v) noexcept;
11411
+ template<simd-vec-type V>
11412
+ constexpr rebind_t<make_signed_t<typename V::value_type>, V>
11413
+ countl_zero(const V& v) noexcept;
11414
+ template<simd-vec-type V>
11415
+ constexpr rebind_t<make_signed_t<typename V::value_type>, V>
11416
+ countl_one(const V& v) noexcept;
11417
+ template<simd-vec-type V>
11418
+ constexpr rebind_t<make_signed_t<typename V::value_type>, V>
11419
+ countr_zero(const V& v) noexcept;
11420
+ template<simd-vec-type V>
11421
+ constexpr rebind_t<make_signed_t<typename V::value_type>, V>
11422
+ countr_one(const V& v) noexcept;
11423
+ template<simd-vec-type V>
11424
+ constexpr rebind_t<make_signed_t<typename V::value_type>, V>
11425
+ popcount(const V& v) noexcept;
11426
+
11427
+ // [simd.complex.math], complex math
11428
+ template<simd-complex V>
11429
+ constexpr rebind_t<simd-complex-value-type<V>, V> real(const V&) noexcept;
11430
+
11431
+ template<simd-complex V>
11432
+ constexpr rebind_t<simd-complex-value-type<V>, V> imag(const V&) noexcept;
11433
+
11434
+ template<simd-complex V>
11435
+ constexpr rebind_t<simd-complex-value-type<V>, V> abs(const V&);
11436
+
11437
+ template<simd-complex V>
11438
+ constexpr rebind_t<simd-complex-value-type<V>, V> arg(const V&);
11439
+
11440
+ template<simd-complex V>
11441
+ constexpr rebind_t<simd-complex-value-type<V>, V> norm(const V&);
11442
+
11443
+ template<simd-complex V> constexpr V conj(const V&);
11444
+ template<simd-complex V> constexpr V proj(const V&);
11445
+ template<simd-complex V> constexpr V exp(const V& v);
11446
+ template<simd-complex V> constexpr V log(const V& v);
11447
+ template<simd-complex V> constexpr V log10(const V& v);
11448
+
11449
+ template<simd-complex V> constexpr V sqrt(const V& v);
11450
+ template<simd-complex V> constexpr V sin(const V& v);
11451
+ template<simd-complex V> constexpr V asin(const V& v);
11452
+ template<simd-complex V> constexpr V cos(const V& v);
11453
+ template<simd-complex V> constexpr V acos(const V& v);
11454
+ template<simd-complex V> constexpr V tan(const V& v);
11455
+ template<simd-complex V> constexpr V atan(const V& v);
11456
+ template<simd-complex V> constexpr V sinh(const V& v);
11457
+ template<simd-complex V> constexpr V asinh(const V& v);
11458
+ template<simd-complex V> constexpr V cosh(const V& v);
11459
+ template<simd-complex V> constexpr V acosh(const V& v);
11460
+ template<simd-complex V> constexpr V tanh(const V& v);
11461
+ template<simd-complex V> constexpr V atanh(const V& v);
11462
+
11463
+ template<simd-floating-point V>
11464
+ rebind_t<complex<typename V::value_type>, V> polar(const V& x, const V& y = {});
11465
+
11466
+ template<simd-complex V> constexpr V pow(const V& x, const V& y);
11467
+
11468
+ // [simd.mask.class], class template basic_mask
11469
+ template<size_t Bytes, class Abi = native-abi<integer-from<Bytes>>> class basic_mask;
11470
+ template<class T, simd-size-type N = simd-size-v<T, native-abi<T>>>
11471
+ using mask = basic_mask<sizeof(T), deduce-abi-t<T, N>>;
11472
+
11473
+ // [simd.mask.reductions], reductions
11474
+ template<size_t Bytes, class Abi>
11475
+ constexpr bool all_of(const basic_mask<Bytes, Abi>&) noexcept;
11476
+ template<size_t Bytes, class Abi>
11477
+ constexpr bool any_of(const basic_mask<Bytes, Abi>&) noexcept;
11478
+ template<size_t Bytes, class Abi>
11479
+ constexpr bool none_of(const basic_mask<Bytes, Abi>&) noexcept;
11480
+ template<size_t Bytes, class Abi>
11481
+ constexpr simd-size-type reduce_count(const basic_mask<Bytes, Abi>&) noexcept;
11482
+ template<size_t Bytes, class Abi>
11483
+ constexpr simd-size-type reduce_min_index(const basic_mask<Bytes, Abi>&);
11484
+ template<size_t Bytes, class Abi>
11485
+ constexpr simd-size-type reduce_max_index(const basic_mask<Bytes, Abi>&);
11486
+
11487
+ constexpr bool all_of(same_as<bool> auto) noexcept;
11488
+ constexpr bool any_of(same_as<bool> auto) noexcept;
11489
+ constexpr bool none_of(same_as<bool> auto) noexcept;
11490
+ constexpr simd-size-type reduce_count(same_as<bool> auto) noexcept;
11491
+ constexpr simd-size-type reduce_min_index(same_as<bool> auto);
11492
+ constexpr simd-size-type reduce_max_index(same_as<bool> auto);
11493
+ }
11494
+
11495
+ namespace std {
11496
+ // See [simd.alg], algorithms
11497
+ using simd::min;
11498
+ using simd::max;
11499
+ using simd::minmax;
11500
+ using simd::clamp;
11501
+
11502
+ // See [simd.math], mathematical functions
11503
+ using simd::acos;
11504
+ using simd::asin;
11505
+ using simd::atan;
11506
+ using simd::atan2;
11507
+ using simd::cos;
11508
+ using simd::sin;
11509
+ using simd::tan;
11510
+ using simd::acosh;
11511
+ using simd::asinh;
11512
+ using simd::atanh;
11513
+ using simd::cosh;
11514
+ using simd::sinh;
11515
+ using simd::tanh;
11516
+ using simd::exp;
11517
+ using simd::exp2;
11518
+ using simd::expm1;
11519
+ using simd::frexp;
11520
+ using simd::ilogb;
11521
+ using simd::ldexp;
11522
+ using simd::log;
11523
+ using simd::log10;
11524
+ using simd::log1p;
11525
+ using simd::log2;
11526
+ using simd::logb;
11527
+ using simd::modf;
11528
+ using simd::scalbn;
11529
+ using simd::scalbln;
11530
+ using simd::cbrt;
11531
+ using simd::abs;
11532
+ using simd::fabs;
11533
+ using simd::hypot;
11534
+ using simd::pow;
11535
+ using simd::sqrt;
11536
+ using simd::erf;
11537
+ using simd::erfc;
11538
+ using simd::lgamma;
11539
+ using simd::tgamma;
11540
+ using simd::ceil;
11541
+ using simd::floor;
11542
+ using simd::nearbyint;
11543
+ using simd::rint;
11544
+ using simd::lrint;
11545
+ using simd::llrint;
11546
+ using simd::round;
11547
+ using simd::lround;
11548
+ using simd::llround;
11549
+ using simd::trunc;
11550
+ using simd::fmod;
11551
+ using simd::remainder;
11552
+ using simd::remquo;
11553
+ using simd::copysign;
11554
+ using simd::nextafter;
11555
+ using simd::fdim;
11556
+ using simd::fmax;
11557
+ using simd::fmin;
11558
+ using simd::fma;
11559
+ using simd::lerp;
11560
+ using simd::fpclassify;
11561
+ using simd::isfinite;
11562
+ using simd::isinf;
11563
+ using simd::isnan;
11564
+ using simd::isnormal;
11565
+ using simd::signbit;
11566
+ using simd::isgreater;
11567
+ using simd::isgreaterequal;
11568
+ using simd::isless;
11569
+ using simd::islessequal;
11570
+ using simd::islessgreater;
11571
+ using simd::isunordered;
11572
+ using simd::assoc_laguerre;
11573
+ using simd::assoc_legendre;
11574
+ using simd::beta;
11575
+ using simd::comp_ellint_1;
11576
+ using simd::comp_ellint_2;
11577
+ using simd::comp_ellint_3;
11578
+ using simd::cyl_bessel_i;
11579
+ using simd::cyl_bessel_j;
11580
+ using simd::cyl_bessel_k;
11581
+ using simd::cyl_neumann;
11582
+ using simd::ellint_1;
11583
+ using simd::ellint_2;
11584
+ using simd::ellint_3;
11585
+ using simd::expint;
11586
+ using simd::hermite;
11587
+ using simd::laguerre;
11588
+ using simd::legendre;
11589
+ using simd::riemann_zeta;
11590
+ using simd::sph_bessel;
11591
+ using simd::sph_legendre;
11592
+ using simd::sph_neumann;
11593
+
11594
+ // See [simd.bit], bit manipulation
11595
+ using simd::byteswap;
11596
+ using simd::bit_ceil;
11597
+ using simd::bit_floor;
11598
+ using simd::has_single_bit;
11599
+ using simd::rotl;
11600
+ using simd::rotr;
11601
+ using simd::bit_width;
11602
+ using simd::countl_zero;
11603
+ using simd::countl_one;
11604
+ using simd::countr_zero;
11605
+ using simd::countr_one;
11606
+ using simd::popcount;
11607
+
11608
+ // See [simd.complex.math], vec complex math
11609
+ using simd::real;
11610
+ using simd::imag;
11611
+ using simd::arg;
11612
+ using simd::norm;
11613
+ using simd::conj;
11614
+ using simd::proj;
11615
+ using simd::polar;
11616
+ }
11617
+ ```
11618
+
11619
+ ### Type traits <a id="simd.traits">[[simd.traits]]</a>
11620
+
11621
+ ``` cpp
11622
+ template<class T, class U = typename T::value_type> struct alignment { see below };
11623
+ ```
11624
+
11625
+ `alignment<T, U>` has a member `value` if and only if
11626
+
11627
+ - `T` is a specialization of `basic_mask` and `U` is `bool`, or
11628
+ - `T` is a specialization of `basic_vec` and `U` is a vectorizable type.
11629
+
11630
+ If `value` is present, the type `alignment<T, U>` is a `BinaryTypeTrait`
11631
+ with a base characteristic of `integral_constant<size_t, N>` for some
11632
+ unspecified `N` [[simd.ctor]], [[simd.loadstore]].
11633
+
11634
+ [*Note 1*: `value` identifies the alignment restrictions on pointers
11635
+ used for (converting) loads and stores for the given type `T` on arrays
11636
+ of type `U`. — *end note*]
11637
+
11638
+ The behavior of a program that adds specializations for `alignment` is
11639
+ undefined.
11640
+
11641
+ ``` cpp
11642
+ template<class T, class V> struct rebind { using type = see below; };
11643
+ ```
11644
+
11645
+ The member `type` is present if and only if
11646
+
11647
+ - `V` is a data-parallel type,
11648
+ - `T` is a vectorizable type, and
11649
+ - *`deduce-abi-t`*`<T, V::size()>` has a member type `type`.
11650
+
11651
+ If V is a specialization of `basic_vec`, let `Abi1` denote an ABI tag
11652
+ such that `basic_vec<T, Abi1>::size()` equals `V::size()`. If V is a
11653
+ specialization of `basic_mask`, let `Abi1` denote an ABI tag such that
11654
+ `basic_mask<sizeof(T), Abi1>::size()` equals `V::size()`.
11655
+
11656
+ Where present, the member typedef `type` names `basic_vec<T, Abi1>` if V
11657
+ is a specialization of `basic_vec` or `basic_mask<sizeof(T), Abi1>` if V
11658
+ is a specialization of `basic_mask`.
11659
+
11660
+ ``` cpp
11661
+ template<simd-size-type N, class V> struct resize { using type = see below; };
11662
+ ```
11663
+
11664
+ Let `T` denote
11665
+
11666
+ - `typename V::value_type` if `V` is a specialization of `basic_vec`,
11667
+ - otherwise *`integer-from`*`<`*`mask-element-size`*`<V>>` if `V` is a
11668
+ specialization of `basic_mask`.
11669
+
11670
+ The member `type` is present if and only if
11671
+
11672
+ - `V` is a data-parallel type, and
11673
+ - *`deduce-abi-t`*`<T, N>` has a member type `type`.
11674
+
11675
+ If V is a specialization of `basic_vec`, let `Abi1` denote an ABI tag
11676
+ such that `basic_vec<T, Abi1>::size()` equals `N`. If V is a
11677
+ specialization of `basic_mask`, let `Abi1` denote an ABI tag such that
11678
+ `basic_mask<sizeof(T), Abi1>::size()` equals `N`.
11679
+
11680
+ Where present, the member typedef `type` names `basic_vec<T, Abi1>` if V
11681
+ is a specialization of `basic_vec` or `basic_mask<sizeof(T), Abi1>` if V
11682
+ is a specialization of `basic_mask`.
11683
+
11684
+ ### Load and store flags <a id="simd.flags">[[simd.flags]]</a>
11685
+
11686
+ #### Class template `flags` overview <a id="simd.flags.overview">[[simd.flags.overview]]</a>
11687
+
11688
+ ``` cpp
11689
+ namespace std::simd {
11690
+ template<class... Flags> struct flags {
11691
+ // [simd.flags.oper], flags operators
11692
+ template<class... Other>
11693
+ friend consteval auto operator|(flags, flags<Other...>);
11694
+ };
11695
+ }
11696
+ ```
11697
+
11698
+ [*Note 1*: The class template `flags` acts like an integer bit-flag for
11699
+ types. — *end note*]
11700
+
11701
+ *Constraints:* Every type in the parameter pack `Flags` is one of
11702
+ `convert-flag`, `aligned-flag`, or `overaligned-{flag}<N>`.
11703
+
11704
+ #### `flags` operators <a id="simd.flags.oper">[[simd.flags.oper]]</a>
11705
+
11706
+ ``` cpp
11707
+ template<class... Other>
11708
+ friend consteval auto operator|(flags a, flags<Other...> b);
11709
+ ```
11710
+
11711
+ *Returns:* A default-initialized object of type `flags<Flags2...>` for
11712
+ some `Flags2` where every type in `Flags2` is present either in template
11713
+ parameter pack `Flags` or in template parameter pack `Other`, and every
11714
+ type in template parameter packs `Flags` and `Other` is present in
11715
+ `Flags2`. If the packs `Flags` and `Other` contain two different
11716
+ specializations *`overaligned-flag`*`<N1>` and
11717
+ *`overaligned-flag`*`<N2>`, `Flags2` is not required to contain the
11718
+ specialization *`overaligned-flag`*`<std::min(N1, N2)>`.
11719
+
11720
+ ### Class template *`simd-iterator`* <a id="simd.iterator">[[simd.iterator]]</a>
11721
+
11722
+ ``` cpp
11723
+ namespace std::simd {
11724
+ template<class V>
11725
+ class simd-iterator { // exposition only
11726
+ V* data_ = nullptr; // exposition only
11727
+ simd-size-type offset_ = 0; // exposition only
11728
+
11729
+ constexpr simd-iterator(V& d, simd-size-type off) noexcept; // exposition only
11730
+
11731
+ public:
11732
+ using value_type = V::value_type;
11733
+ using iterator_category = input_iterator_tag;
11734
+ using iterator_concept = random_access_iterator_tag;
11735
+ using difference_type = simd-size-type;
11736
+
11737
+ constexpr simd-iterator() = default;
11738
+
11739
+ constexpr simd-iterator(const simd-iterator&) = default;
11740
+ constexpr simd-iterator& operator=(const simd-iterator&) = default;
11741
+
11742
+ constexpr simd-iterator(const simd-iterator<remove_const_t<V>>&) requires is_const_v<V>;
11743
+
11744
+ constexpr value_type operator*() const;
11745
+
11746
+ constexpr simd-iterator& operator++();
11747
+ constexpr simd-iterator operator++(int);
11748
+ constexpr simd-iterator& operator--();
11749
+ constexpr simd-iterator operator--(int);
11750
+
11751
+ constexpr simd-iterator& operator+=(difference_type n);
11752
+ constexpr simd-iterator& operator-=(difference_type n);
11753
+
11754
+ constexpr value_type operator[](difference_type n) const;
11755
+
11756
+ friend constexpr bool operator==(simd-iterator a, simd-iterator b) = default;
11757
+ friend constexpr bool operator==(simd-iterator a, default_sentinel_t) noexcept;
11758
+ friend constexpr auto operator<=>(simd-iterator a, simd-iterator b);
11759
+
11760
+ friend constexpr simd-iterator operator+(simd-iterator i, difference_type n);
11761
+ friend constexpr simd-iterator operator+(difference_type n, simd-iterator i);
11762
+ friend constexpr simd-iterator operator-(simd-iterator i, difference_type n);
11763
+
11764
+ friend constexpr difference_type operator-(simd-iterator a, simd-iterator b);
11765
+ friend constexpr difference_type operator-(simd-iterator i, default_sentinel_t) noexcept;
11766
+ friend constexpr difference_type operator-(default_sentinel_t, simd-iterator i) noexcept;
11767
+ };
11768
+ }
11769
+ ```
11770
+
11771
+ ``` cpp
11772
+ constexpr simd-iterator(V& d, simd-size-type off) noexcept;
11773
+ ```
11774
+
11775
+ *Effects:* Initializes *data\_* with `addressof(d)` and *offset\_* with
11776
+ `off`.
11777
+
11778
+ ``` cpp
11779
+ constexpr simd-iterator(const simd-iterator<remove_const_t<V>>& i) requires is_const_v<V>;
11780
+ ```
11781
+
11782
+ *Effects:* Initializes *data\_* with `i.`*`data_`* and *offset\_* with
11783
+ `i.`*`offset_`*.
11784
+
11785
+ ``` cpp
11786
+ constexpr value_type operator*() const;
11787
+ ```
11788
+
11789
+ *Effects:* Equivalent to: `return (*`*`data_`*`)[`*`offset_`*`];`
11790
+
11791
+ ``` cpp
11792
+ constexpr simd-iterator& operator++();
11793
+ ```
11794
+
11795
+ *Effects:* Equivalent to: `return *this += 1;`
11796
+
11797
+ ``` cpp
11798
+ constexpr simd-iterator operator++(int);
11799
+ ```
11800
+
11801
+ *Effects:* Equivalent to:
11802
+
11803
+ ``` cpp
11804
+ simd-iterator tmp = *this;
11805
+ *this += 1;
11806
+ return tmp;
11807
+ ```
11808
+
11809
+ ``` cpp
11810
+ constexpr simd-iterator& operator--();
11811
+ ```
11812
+
11813
+ *Effects:* Equivalent to: `return *this -= 1;`
11814
+
11815
+ ``` cpp
11816
+ constexpr simd-iterator operator--(int);
11817
+ ```
11818
+
11819
+ *Effects:* Equivalent to:
11820
+
11821
+ ``` cpp
11822
+ simd-iterator tmp = *this;
11823
+ *this -= 1;
11824
+ return tmp;
11825
+ ```
11826
+
11827
+ ``` cpp
11828
+ constexpr simd-iterator& operator+=(difference_type n);
11829
+ ```
11830
+
11831
+ *Preconditions:* *`offset_`*` + n` is in the range \[`0`, `V::size()`\].
11832
+
11833
+ *Effects:* Equivalent to:
11834
+
11835
+ ``` cpp
11836
+ offset_ += n;
11837
+ return *this;
11838
+ ```
11839
+
11840
+ ``` cpp
11841
+ constexpr simd-iterator& operator-=(difference_type n);
11842
+ ```
11843
+
11844
+ *Preconditions:* *`offset_`*` - n` is in the range \[`0`, `V::size()`\].
11845
+
11846
+ *Effects:* Equivalent to:
11847
+
11848
+ ``` cpp
11849
+ offset_ -= n;
11850
+ return *this;
11851
+ ```
11852
+
11853
+ ``` cpp
11854
+ constexpr value_type operator[](difference_type n) const;
11855
+ ```
11856
+
11857
+ *Effects:* Equivalent to: `return (*`*`data_`*`)[`*`offset_`*` + n];`
11858
+
11859
+ ``` cpp
11860
+ friend constexpr bool operator==(simd-iterator i, default_sentinel_t) noexcept;
11861
+ ```
11862
+
11863
+ *Effects:* Equivalent to: `return i.`*`offset_`*` == V::size();`
11864
+
11865
+ ``` cpp
11866
+ friend constexpr auto operator<=>(simd-iterator a, simd-iterator b);
11867
+ ```
11868
+
11869
+ *Preconditions:* `a.`*`data_`*` == b.`*`data_`* is `true`.
11870
+
11871
+ *Effects:* Equivalent to: `return a.`*`offset_`*` <=> b.`*`offset_`*`;`
11872
+
11873
+ ``` cpp
11874
+ friend constexpr simd-iterator operator+(simd-iterator i, difference_type n);
11875
+ friend constexpr simd-iterator operator+(difference_type n, simd-iterator i);
11876
+ ```
11877
+
11878
+ *Effects:* Equivalent to: `return i += n;`
11879
+
11880
+ ``` cpp
11881
+ friend constexpr simd-iterator operator-(simd-iterator i, difference_type n);
11882
+ ```
11883
+
11884
+ *Effects:* Equivalent to: `return i -= n;`
11885
+
11886
+ ``` cpp
11887
+ friend constexpr difference_type operator-(simd-iterator a, simd-iterator b);
11888
+ ```
11889
+
11890
+ *Preconditions:* `a.`*`data_`*` == b.`*`data_`* is `true`.
11891
+
11892
+ *Effects:* Equivalent to: `return a.`*`offset_`*` - b.`*`offset_`*`;`
11893
+
11894
+ ``` cpp
11895
+ friend constexpr difference_type operator-(simd-iterator i, default_sentinel_t) noexcept;
11896
+ ```
11897
+
11898
+ *Effects:* Equivalent to: `return i.`*`offset_`*` - V::size();`
11899
+
11900
+ ``` cpp
11901
+ friend constexpr difference_type operator-(default_sentinel_t, simd-iterator i) noexcept;
11902
+ ```
11903
+
11904
+ *Effects:* Equivalent to: `return V::size() - i.`*`offset_`*`;`
11905
+
11906
+ ### Class template `basic_vec` <a id="simd.class">[[simd.class]]</a>
11907
+
11908
+ #### Overview <a id="simd.overview">[[simd.overview]]</a>
11909
+
11910
+ ``` cpp
11911
+ namespace std::simd {
11912
+ template<class T, class Abi> class basic_vec {
11913
+ public:
11914
+ using value_type = T;
11915
+ using mask_type = basic_mask<sizeof(T), Abi>;
11916
+ using abi_type = Abi;
11917
+ using iterator = simd-iterator<basic_vec>;
11918
+ using const_iterator = simd-iterator<const basic_vec>;
11919
+
11920
+ constexpr iterator begin() noexcept { return {*this, 0}; }
11921
+ constexpr const_iterator begin() const noexcept { return {*this, 0}; }
11922
+ constexpr const_iterator cbegin() const noexcept { return {*this, 0}; }
11923
+ constexpr default_sentinel_t end() const noexcept { return {}; }
11924
+ constexpr default_sentinel_t cend() const noexcept { return {}; }
11925
+
11926
+ static constexpr integral_constant<simd-size-type, simd-size-v<T, Abi>> size {};
11927
+
11928
+ constexpr basic_vec() noexcept = default;
11929
+
11930
+ // [simd.ctor], basic_vec constructors
11931
+ template<class U>
11932
+ constexpr explicit(see below) basic_vec(U&& value) noexcept;
11933
+ template<class U, class UAbi>
11934
+ constexpr explicit(see below) basic_vec(const basic_vec<U, UAbi>&) noexcept;
11935
+ template<class G>
11936
+ constexpr explicit basic_vec(G&& gen);
11937
+ template<class R, class... Flags>
11938
+ constexpr basic_vec(R&& range, flags<Flags...> = {});
11939
+ template<class R, class... Flags>
11940
+ constexpr basic_vec(R&& range, const mask_type& mask, flags<Flags...> = {});
11941
+ template<simd-floating-point V>
11942
+ constexpr explicit(see below) basic_vec(const V& reals, const V& imags = {}) noexcept;
11943
+
11944
+ // [simd.subscr], basic_vec subscript operators
11945
+ constexpr value_type operator[](simd-size-type) const;
11946
+ template<simd-integral I>
11947
+ constexpr resize_t<I::size(), basic_vec> operator[](const I& indices) const;
11948
+
11949
+ // [simd.complex.access], basic_vec complex accessors
11950
+ constexpr auto real() const noexcept;
11951
+ constexpr auto imag() const noexcept;
11952
+ template<simd-floating-point V>
11953
+ constexpr void real(const V& v) noexcept;
11954
+ template<simd-floating-point V>
11955
+ constexpr void imag(const V& v) noexcept;
11956
+
11957
+ // [simd.unary], basic_vec unary operators
11958
+ constexpr basic_vec& operator++() noexcept;
11959
+ constexpr basic_vec operator++(int) noexcept;
11960
+ constexpr basic_vec& operator--() noexcept;
11961
+ constexpr basic_vec operator--(int) noexcept;
11962
+ constexpr mask_type operator!() const noexcept;
11963
+ constexpr basic_vec operator~() const noexcept;
11964
+ constexpr basic_vec operator+() const noexcept;
11965
+ constexpr basic_vec operator-() const noexcept;
11966
+
11967
+ // [simd.binary], basic_vec binary operators
11968
+ friend constexpr basic_vec operator+(const basic_vec&, const basic_vec&) noexcept;
11969
+ friend constexpr basic_vec operator-(const basic_vec&, const basic_vec&) noexcept;
11970
+ friend constexpr basic_vec operator*(const basic_vec&, const basic_vec&) noexcept;
11971
+ friend constexpr basic_vec operator/(const basic_vec&, const basic_vec&) noexcept;
11972
+ friend constexpr basic_vec operator%(const basic_vec&, const basic_vec&) noexcept;
11973
+ friend constexpr basic_vec operator&(const basic_vec&, const basic_vec&) noexcept;
11974
+ friend constexpr basic_vec operator|(const basic_vec&, const basic_vec&) noexcept;
11975
+ friend constexpr basic_vec operator^(const basic_vec&, const basic_vec&) noexcept;
11976
+ friend constexpr basic_vec operator<<(const basic_vec&, const basic_vec&) noexcept;
11977
+ friend constexpr basic_vec operator>>(const basic_vec&, const basic_vec&) noexcept;
11978
+ friend constexpr basic_vec operator<<(const basic_vec&, simd-size-type) noexcept;
11979
+ friend constexpr basic_vec operator>>(const basic_vec&, simd-size-type) noexcept;
11980
+
11981
+ // [simd.cassign], basic_vec compound assignment
11982
+ friend constexpr basic_vec& operator+=(basic_vec&, const basic_vec&) noexcept;
11983
+ friend constexpr basic_vec& operator-=(basic_vec&, const basic_vec&) noexcept;
11984
+ friend constexpr basic_vec& operator*=(basic_vec&, const basic_vec&) noexcept;
11985
+ friend constexpr basic_vec& operator/=(basic_vec&, const basic_vec&) noexcept;
11986
+ friend constexpr basic_vec& operator%=(basic_vec&, const basic_vec&) noexcept;
11987
+ friend constexpr basic_vec& operator&=(basic_vec&, const basic_vec&) noexcept;
11988
+ friend constexpr basic_vec& operator|=(basic_vec&, const basic_vec&) noexcept;
11989
+ friend constexpr basic_vec& operator^=(basic_vec&, const basic_vec&) noexcept;
11990
+ friend constexpr basic_vec& operator<<=(basic_vec&, const basic_vec&) noexcept;
11991
+ friend constexpr basic_vec& operator>>=(basic_vec&, const basic_vec&) noexcept;
11992
+ friend constexpr basic_vec& operator<<=(basic_vec&, simd-size-type) noexcept;
11993
+ friend constexpr basic_vec& operator>>=(basic_vec&, simd-size-type) noexcept;
11994
+
11995
+ // [simd.comparison], basic_vec compare operators
11996
+ friend constexpr mask_type operator==(const basic_vec&, const basic_vec&) noexcept;
11997
+ friend constexpr mask_type operator!=(const basic_vec&, const basic_vec&) noexcept;
11998
+ friend constexpr mask_type operator>=(const basic_vec&, const basic_vec&) noexcept;
11999
+ friend constexpr mask_type operator<=(const basic_vec&, const basic_vec&) noexcept;
12000
+ friend constexpr mask_type operator>(const basic_vec&, const basic_vec&) noexcept;
12001
+ friend constexpr mask_type operator<(const basic_vec&, const basic_vec&) noexcept;
12002
+
12003
+ // [simd.cond], basic_vec exposition only conditional operators
12004
+ friend constexpr basic_vec simd-select-impl( // exposition only
12005
+ const mask_type&, const basic_vec&, const basic_vec&) noexcept;
12006
+ };
12007
+
12008
+ template<class R, class... Ts>
12009
+ basic_vec(R&& r, Ts...) -> see below;
12010
+ }
12011
+ ```
12012
+
12013
+ Every specialization of `basic_vec` is a complete type. The
12014
+ specialization of `basic_vec<T, Abi>` is
12015
+
12016
+ - enabled, if `T` is a vectorizable type, and there exists value `N` in
12017
+ the range \[`1`, `64`\], such that `Abi` is `deduce-abi-t<T, N>`,
12018
+ - otherwise, disabled, if `T` is not a vectorizable type,
12019
+ - otherwise, it is *implementation-defined* if such a specialization is
12020
+ enabled.
12021
+
12022
+ If `basic_vec<T, Abi>` is disabled, then the specialization has a
12023
+ deleted default constructor, deleted destructor, deleted copy
12024
+ constructor, and deleted copy assignment. In addition only the
12025
+ `value_type`, `abi_type`, and `mask_type` members are present.
12026
+
12027
+ If `basic_vec<T, Abi>` is enabled, then `basic_vec<T, Abi>` is trivially
12028
+ copyable, default-initialization of an object of such a type
12029
+ default-initializes all elements, and value-initialization
12030
+ value-initializes all elements [[dcl.init.general]].
12031
+
12032
+ *Recommended practice:* Implementations should support implicit
12033
+ conversions between specializations of `basic_vec` and appropriate
12034
+ *implementation-defined* types.
12035
+
12036
+ [*Note 1*: Appropriate types are non-standard vector types which are
12037
+ available in the implementation. — *end note*]
12038
+
12039
+ #### Constructors <a id="simd.ctor">[[simd.ctor]]</a>
12040
+
12041
+ ``` cpp
12042
+ template<class U> constexpr explicit(see below) basic_vec(U&& value) noexcept;
12043
+ ```
12044
+
12045
+ Let `From` denote the type `remove_cvref_t<U>`.
12046
+
12047
+ *Constraints:* `value_type` satisfies `constructible_from<U>`.
12048
+
12049
+ *Effects:* Initializes each element to the value of the argument after
12050
+ conversion to `value_type`.
12051
+
12052
+ *Remarks:* The expression inside `explicit` evaluates to `false` if and
12053
+ only if `U` satisfies `convertible_to<value_type>`, and either
12054
+
12055
+ - `From` is not an arithmetic type and does not satisfy
12056
+ `constexpr-wrapper-like`,
12057
+ - `From` is an arithmetic type and the conversion from `From` to
12058
+ `value_type` is value-preserving [[simd.general]], or
12059
+ - `From` satisfies `constexpr-wrapper-like`,
12060
+ `remove_const_t<decltype(From::value)>` is an arithmetic type, and
12061
+ `From::value` is representable by `value_type`.
12062
+
12063
+ ``` cpp
12064
+ template<class U, class UAbi>
12065
+ constexpr explicit(see below) basic_vec(const basic_vec<U, UAbi>& x) noexcept;
12066
+ ```
12067
+
12068
+ *Constraints:* *`simd-size-v`*`<U, UAbi> == size()` is `true`.
12069
+
12070
+ *Effects:* Initializes the iᵗʰ element with `static_cast<T>(x[`i`])` for
12071
+ all i in the range of \[`0`, `size()`).
12072
+
12073
+ *Remarks:* The expression inside `explicit` evaluates to `true` if
12074
+ either
12075
+
12076
+ - the conversion from `U` to `value_type` is not value-preserving, or
12077
+ - both `U` and `value_type` are integral types and the integer
12078
+ conversion rank [[conv.rank]] of `U` is greater than the integer
12079
+ conversion rank of `value_type`, or
12080
+ - both `U` and `value_type` are floating-point types and the
12081
+ floating-point conversion rank [[conv.rank]] of `U` is greater than
12082
+ the floating-point conversion rank of `value_type`.
12083
+
12084
+ ``` cpp
12085
+ template<class G> constexpr explicit basic_vec(G&& gen);
12086
+ ```
12087
+
12088
+ Let `From`ᵢ denote the type
12089
+ `decltype(gen(integral_constant<`*`simd-size-type`*`, `i`>()))`.
12090
+
12091
+ *Constraints:* `From`ᵢ satisfies `convertible_to<value_type>` for all i
12092
+ in the range of \[`0`, `size()`). In addition, for all i in the range of
12093
+ \[`0`, `size()`), if `From`ᵢ is an arithmetic type, conversion from
12094
+ `From`ᵢ to `value_type` is value-preserving.
12095
+
12096
+ *Effects:* Initializes the iᵗʰ element with
12097
+ `static_cast<value_type>(gen(integral_constant<`*`simd-size-type`*`, i>()))`
12098
+ for all i in the range of \[`0`, `size()`).
12099
+
12100
+ *Remarks:* `gen` is invoked exactly once for each i, in increasing order
12101
+ of i.
12102
+
12103
+ ``` cpp
12104
+ template<class R, class... Flags>
12105
+ constexpr basic_vec(R&& r, flags<Flags...> = {});
12106
+ template<class R, class... Flags>
12107
+ constexpr basic_vec(R&& r, const mask_type& mask, flags<Flags...> = {});
12108
+ ```
12109
+
12110
+ Let `mask` be `mask_type(true)` for the overload with no `mask`
12111
+ parameter.
12112
+
12113
+ *Constraints:*
12114
+
12115
+ - `R` models `ranges::contiguous_range` and `ranges::sized_range`,
12116
+ - `ranges::size(r)` is a constant expression, and
12117
+ - `ranges::size(r)` is equal to `size()`.
12118
+
12119
+ *Mandates:*
12120
+
12121
+ - `ranges::range_value_t<R>` is a vectorizable type, and
12122
+ - if the template parameter pack `Flags` does not contain
12123
+ *`convert-flag`*, then the conversion from `ranges::range_value_t<R>`
12124
+ to `value_type` is value-preserving.
12125
+
12126
+ *Preconditions:*
12127
+
12128
+ - If the template parameter pack `Flags` contains *`aligned-flag`*,
12129
+ `ranges::data(r)` points to storage aligned by
12130
+ `alignment_v<basic_vec, ranges::range_value_t<R>>`.
12131
+ - If the template parameter pack `Flags` contains
12132
+ *`overaligned-flag`*`<N>`, `ranges::data(r)` points to storage aligned
12133
+ by `N`.
12134
+
12135
+ *Effects:* Initializes the iᵗʰ element with
12136
+ `mask[`i`] ? static_cast<T>(ranges::data(r)[`i`]) : T()` for all i in
12137
+ the range of \[`0`, `size()`).
12138
+
12139
+ ``` cpp
12140
+ template<class R, class... Ts>
12141
+ basic_vec(R&& r, Ts...) -> see below;
12142
+ ```
12143
+
12144
+ *Constraints:*
12145
+
12146
+ - `R` models `ranges::contiguous_range` and `ranges::sized_range`, and
12147
+ - `ranges::size(r)` is a constant expression.
12148
+
12149
+ *Remarks:* The deduced type is equivalent to
12150
+ `vec<ranges::range_value_t<R>, ranges::size(r)>`.
12151
+
12152
+ ``` cpp
12153
+ template<simd-floating-point V>
12154
+ constexpr explicit(see below)
12155
+ basic_vec(const V& reals, const V& imags = {}) noexcept;
12156
+ ```
12157
+
12158
+ *Constraints:*
12159
+
12160
+ - `simd-complex<basic_vec>` is modeled, and
12161
+ - `V::size() == size()` is `true`.
12162
+
12163
+ *Effects:* Initializes the iᵗʰ element with
12164
+ `value_type(reals[`i`], imags[`i`])` for all i in the range \[`0`,
12165
+ `size()`).
12166
+
12167
+ *Remarks:* The expression inside `explicit` evaluates to `false` if and
12168
+ only if the floating-point conversion rank of `T::value_type` is greater
12169
+ than or equal to the floating-point conversion rank of `V::value_type`.
12170
+
12171
+ #### Subscript operator <a id="simd.subscr">[[simd.subscr]]</a>
12172
+
12173
+ ``` cpp
12174
+ constexpr value_type operator[](simd-size-type i) const;
12175
+ ```
12176
+
12177
+ *Preconditions:* `i >= 0 && i < size()` is `true`.
12178
+
12179
+ *Returns:* The value of the iᵗʰ element.
12180
+
12181
+ *Throws:* Nothing.
12182
+
12183
+ ``` cpp
12184
+ template<simd-integral I>
12185
+ constexpr resize_t<I::size(), basic_vec> operator[](const I& indices) const;
12186
+ ```
12187
+
12188
+ *Effects:* Equivalent to: `return permute(*this, indices);`
12189
+
12190
+ #### Complex accessors <a id="simd.complex.access">[[simd.complex.access]]</a>
12191
+
12192
+ ``` cpp
12193
+ constexpr auto real() const noexcept;
12194
+ constexpr auto imag() const noexcept;
12195
+ ```
12196
+
12197
+ *Constraints:* `simd-complex<basic_vec>` is modeled.
12198
+
12199
+ *Returns:* An object of type
12200
+ `rebind_t<typename T::value_type, basic_vec>` where the iᵗʰ element is
12201
+ initialized to the result of *`cmplx-func`*`(operator[](`i`))` for all i
12202
+ in the range \[`0`, `size()`), where *`cmplx-func`* is the corresponding
12203
+ function from `<complex>`.
12204
+
12205
+ ``` cpp
12206
+ template<simd-floating-point V>
12207
+ constexpr void real(const V& v) noexcept;
12208
+ template<simd-floating-point V>
12209
+ constexpr void imag(const V& v) noexcept;
12210
+ ```
12211
+
12212
+ *Constraints:*
12213
+
12214
+ - `simd-complex<basic_vec>` is modeled,
12215
+ - `same_as<typename V::value_type, typename T::value_type>` is modeled,
12216
+ and
12217
+ - `V::size() == size()` is `true`.
12218
+
12219
+ *Effects:* Replaces each element of the `basic_vec` object such that the
12220
+ iᵗʰ element is replaced with
12221
+ `value_type(v[`i`], operator[](`i`).imag())` or
12222
+ `value_type(operator[](`i`).real(), v[`i`])` for `real` and `imag`
12223
+ respectively, for all i in the range \[`0`, `size()`).
12224
+
12225
+ #### Unary operators <a id="simd.unary">[[simd.unary]]</a>
12226
+
12227
+ Effects in [[simd.unary]] are applied as unary element-wise operations.
12228
+
12229
+ ``` cpp
12230
+ constexpr basic_vec& operator++() noexcept;
12231
+ ```
12232
+
12233
+ *Constraints:* `requires (value_type a) { ++a; }` is `true`.
12234
+
12235
+ *Effects:* Increments every element by one.
12236
+
12237
+ *Returns:* `*this`.
12238
+
12239
+ ``` cpp
12240
+ constexpr basic_vec operator++(int) noexcept;
12241
+ ```
12242
+
12243
+ *Constraints:* `requires (value_type a) { a++; }` is `true`.
12244
+
12245
+ *Effects:* Increments every element by one.
12246
+
12247
+ *Returns:* A copy of `*this` before incrementing.
12248
+
12249
+ ``` cpp
12250
+ constexpr basic_vec& operator--() noexcept;
12251
+ ```
12252
+
12253
+ *Constraints:* `requires (value_type a) { –a; }` is `true`.
12254
+
12255
+ *Effects:* Decrements every element by one.
12256
+
12257
+ *Returns:* `*this`.
12258
+
12259
+ ``` cpp
12260
+ constexpr basic_vec operator--(int) noexcept;
12261
+ ```
12262
+
12263
+ *Constraints:* `requires (value_type a) { a–; }` is `true`.
12264
+
12265
+ *Effects:* Decrements every element by one.
12266
+
12267
+ *Returns:* A copy of `*this` before decrementing.
12268
+
12269
+ ``` cpp
12270
+ constexpr mask_type operator!() const noexcept;
12271
+ ```
12272
+
12273
+ *Constraints:* `requires (const value_type a) { !a; }` is `true`.
12274
+
12275
+ *Returns:* A `basic_mask` object with the iᵗʰ element set to
12276
+ `!operator[](`i`)` for all i in the range of \[`0`, `size()`).
12277
+
12278
+ ``` cpp
12279
+ constexpr basic_vec operator~() const noexcept;
12280
+ ```
12281
+
12282
+ *Constraints:* `requires (const value_type a) { ~a; }` is `true`.
12283
+
12284
+ *Returns:* A `basic_vec` object with the iᵗʰ element set to
12285
+ `~operator[](`i`)` for all i in the range of \[`0`, `size()`).
12286
+
12287
+ ``` cpp
12288
+ constexpr basic_vec operator+() const noexcept;
12289
+ ```
12290
+
12291
+ *Constraints:* `requires (const value_type a) { +a; }` is `true`.
12292
+
12293
+ *Returns:* `*this`.
12294
+
12295
+ ``` cpp
12296
+ constexpr basic_vec operator-() const noexcept;
12297
+ ```
12298
+
12299
+ *Constraints:* `requires (const value_type a) { -a; }` is `true`.
12300
+
12301
+ *Returns:* A `basic_vec` object where the iᵗʰ element is initialized to
12302
+ `-operator[](`i`)` for all i in the range of \[`0`, `size()`).
12303
+
12304
+ ### `basic_vec` non-member operations <a id="simd.nonmembers">[[simd.nonmembers]]</a>
12305
+
12306
+ #### Binary operators <a id="simd.binary">[[simd.binary]]</a>
12307
+
12308
+ ``` cpp
12309
+ friend constexpr basic_vec operator+(const basic_vec& lhs, const basic_vec& rhs) noexcept;
12310
+ friend constexpr basic_vec operator-(const basic_vec& lhs, const basic_vec& rhs) noexcept;
12311
+ friend constexpr basic_vec operator*(const basic_vec& lhs, const basic_vec& rhs) noexcept;
12312
+ friend constexpr basic_vec operator/(const basic_vec& lhs, const basic_vec& rhs) noexcept;
12313
+ friend constexpr basic_vec operator%(const basic_vec& lhs, const basic_vec& rhs) noexcept;
12314
+ friend constexpr basic_vec operator&(const basic_vec& lhs, const basic_vec& rhs) noexcept;
12315
+ friend constexpr basic_vec operator|(const basic_vec& lhs, const basic_vec& rhs) noexcept;
12316
+ friend constexpr basic_vec operator^(const basic_vec& lhs, const basic_vec& rhs) noexcept;
12317
+ friend constexpr basic_vec operator<<(const basic_vec& lhs, const basic_vec& rhs) noexcept;
12318
+ friend constexpr basic_vec operator>>(const basic_vec& lhs, const basic_vec& rhs) noexcept;
12319
+ ```
12320
+
12321
+ Let *op* be the operator.
12322
+
12323
+ *Constraints:* `requires (value_type a, value_type b) { a `*`op`*` b; }`
12324
+ is `true`.
12325
+
12326
+ *Returns:* A `basic_vec` object initialized with the results of applying
12327
+ *op* to `lhs` and `rhs` as a binary element-wise operation.
12328
+
12329
+ ``` cpp
12330
+ friend constexpr basic_vec operator<<(const basic_vec& v, simd-size-type n) noexcept;
12331
+ friend constexpr basic_vec operator>>(const basic_vec& v, simd-size-type n) noexcept;
12332
+ ```
12333
+
12334
+ Let *op* be the operator.
12335
+
12336
+ *Constraints:*
12337
+ `requires (value_type a, `*`simd-size-type`*` b) { a `*`op`*` b; }` is
12338
+ `true`.
12339
+
12340
+ *Returns:* A `basic_vec` object where the iᵗʰ element is initialized to
12341
+ the result of applying *op* to `v[`i`]` and `n` for all i in the range
12342
+ of \[`0`, `size()`).
12343
+
12344
+ #### Compound assignment <a id="simd.cassign">[[simd.cassign]]</a>
12345
+
12346
+ ``` cpp
12347
+ friend constexpr basic_vec& operator+=(basic_vec& lhs, const basic_vec& rhs) noexcept;
12348
+ friend constexpr basic_vec& operator-=(basic_vec& lhs, const basic_vec& rhs) noexcept;
12349
+ friend constexpr basic_vec& operator*=(basic_vec& lhs, const basic_vec& rhs) noexcept;
12350
+ friend constexpr basic_vec& operator/=(basic_vec& lhs, const basic_vec& rhs) noexcept;
12351
+ friend constexpr basic_vec& operator%=(basic_vec& lhs, const basic_vec& rhs) noexcept;
12352
+ friend constexpr basic_vec& operator&=(basic_vec& lhs, const basic_vec& rhs) noexcept;
12353
+ friend constexpr basic_vec& operator|=(basic_vec& lhs, const basic_vec& rhs) noexcept;
12354
+ friend constexpr basic_vec& operator^=(basic_vec& lhs, const basic_vec& rhs) noexcept;
12355
+ friend constexpr basic_vec& operator<<=(basic_vec& lhs, const basic_vec& rhs) noexcept;
12356
+ friend constexpr basic_vec& operator>>=(basic_vec& lhs, const basic_vec& rhs) noexcept;
12357
+ ```
12358
+
12359
+ Let *op* be the operator.
12360
+
12361
+ *Constraints:* `requires (value_type a, value_type b) { a `*`op`*` b; }`
12362
+ is `true`.
12363
+
12364
+ *Effects:* These operators apply the indicated operator to `lhs` and
12365
+ `rhs` as an element-wise operation.
12366
+
12367
+ *Returns:* `lhs`.
12368
+
12369
+ ``` cpp
12370
+ friend constexpr basic_vec& operator<<=(basic_vec& lhs, simd-size-type n) noexcept;
12371
+ friend constexpr basic_vec& operator>>=(basic_vec& lhs, simd-size-type n) noexcept;
12372
+ ```
12373
+
12374
+ Let *op* be the operator.
12375
+
12376
+ *Constraints:*
12377
+ `requires (value_type a, `*`simd-size-type`*` b) { a `*`op`*` b; }` is
12378
+ `true`.
12379
+
12380
+ *Effects:* Equivalent to:
12381
+ `return operator `*`op`*` (lhs, basic_vec(n));`
12382
+
12383
+ #### Comparison operators <a id="simd.comparison">[[simd.comparison]]</a>
12384
+
12385
+ ``` cpp
12386
+ friend constexpr mask_type operator==(const basic_vec& lhs, const basic_vec& rhs) noexcept;
12387
+ friend constexpr mask_type operator!=(const basic_vec& lhs, const basic_vec& rhs) noexcept;
12388
+ friend constexpr mask_type operator>=(const basic_vec& lhs, const basic_vec& rhs) noexcept;
12389
+ friend constexpr mask_type operator<=(const basic_vec& lhs, const basic_vec& rhs) noexcept;
12390
+ friend constexpr mask_type operator>(const basic_vec& lhs, const basic_vec& rhs) noexcept;
12391
+ friend constexpr mask_type operator<(const basic_vec& lhs, const basic_vec& rhs) noexcept;
12392
+ ```
12393
+
12394
+ Let *op* be the operator.
12395
+
12396
+ *Constraints:* `requires (value_type a, value_type b) { a `*`op`*` b; }`
12397
+ is `true`.
12398
+
12399
+ *Returns:* A `basic_mask` object initialized with the results of
12400
+ applying *op* to `lhs` and `rhs` as a binary element-wise operation.
12401
+
12402
+ #### Exposition-only conditional operators <a id="simd.cond">[[simd.cond]]</a>
12403
+
12404
+ ``` cpp
12405
+ friend constexpr basic_vec
12406
+ simd-select-impl(const mask_type& mask, const basic_vec& a, const basic_vec& b) noexcept;
12407
+ ```
12408
+
12409
+ *Returns:* A `basic_vec` object where the iᵗʰ element equals
12410
+ `mask[`i`] ? a[`i`] : b[`i`]` for all i in the range of \[`0`,
12411
+ `size()`).
12412
+
12413
+ #### Reductions <a id="simd.reductions">[[simd.reductions]]</a>
12414
+
12415
+ ``` cpp
12416
+ template<class T, class Abi, class BinaryOperation = plus<>>
12417
+ constexpr T reduce(const basic_vec<T, Abi>& x, BinaryOperation binary_op = {});
12418
+ ```
12419
+
12420
+ *Constraints:* `BinaryOperation` models `reduction-binary-operation<T>`.
12421
+
12422
+ *Preconditions:* `binary_op` does not modify `x`.
12423
+
12424
+ *Returns:* *GENERALIZED_SUM*(binary_op, vec\<T, 1\>(x\[0\]), …, vec\<T,
12425
+ 1\>(x\[x.size() - 1\]))\[0\] [[numerics.defns]].
12426
+
12427
+ *Throws:* Any exception thrown from `binary_op`.
12428
+
12429
+ ``` cpp
12430
+ template<class T, class Abi, class BinaryOperation = plus<>>
12431
+ constexpr T reduce(
12432
+ const basic_vec<T, Abi>& x, const typename basic_vec<T, Abi>::mask_type& mask,
12433
+ BinaryOperation binary_op = {}, type_identity_t<T> identity_element = see below);
12434
+ ```
12435
+
12436
+ *Constraints:*
12437
+
12438
+ - `BinaryOperation` models `reduction-binary-operation<T>`.
12439
+ - An argument for `identity_element` is provided for the invocation,
12440
+ unless `BinaryOperation` is one of `plus<>`, `multiplies<>`,
12441
+ `bit_and<>`, `bit_or<>`, or `bit_xor<>`.
12442
+
12443
+ *Preconditions:*
12444
+
12445
+ - `binary_op` does not modify `x`.
12446
+ - For all finite values `y` representable by `T`, the results of
12447
+ `y == binary_op(vec<T, 1>(identity_element), vec<T, 1>(y))[0]` and
12448
+ `y == binary_op(vec<T, 1>(y), vec<T, 1>(identity_element))[0]` are
12449
+ `true`.
12450
+
12451
+ *Returns:* If `none_of(mask)` is `true`, returns `identity_element`.
12452
+ Otherwise, returns *GENERALIZED_SUM*(binary_op, vec\<T, 1\>(x\[k₀\]), …,
12453
+ vec\<T, 1\>(x\[kₙ\]))\[0\] where k₀, …, kₙ are the selected indices of
12454
+ `mask`.
12455
+
12456
+ *Throws:* Any exception thrown from `binary_op`.
12457
+
12458
+ *Remarks:* The default argument for `identity_element` is equal to
12459
+
12460
+ - `T()` if `BinaryOperation` is `plus<>`,
12461
+ - `T(1)` if `BinaryOperation` is `multiplies<>`,
12462
+ - `T(~T())` if `BinaryOperation` is `bit_and<>`,
12463
+ - `T()` if `BinaryOperation` is `bit_or<>`, or
12464
+ - `T()` if `BinaryOperation` is `bit_xor<>`.
12465
+
12466
+ ``` cpp
12467
+ template<class T, class Abi> constexpr T reduce_min(const basic_vec<T, Abi>& x) noexcept;
12468
+ ```
12469
+
12470
+ *Constraints:* `T` models `totally_ordered`.
12471
+
12472
+ *Returns:* The value of an element `x[`j`]` for which `x[`i`] < x[`j`]`
12473
+ is `false` for all i in the range of \[`0`,
12474
+ `basic_vec<T, Abi>::size()`).
12475
+
12476
+ ``` cpp
12477
+ template<class T, class Abi>
12478
+ constexpr T reduce_min(
12479
+ const basic_vec<T, Abi>&, const typename basic_vec<T, Abi>::mask_type&) noexcept;
12480
+ ```
12481
+
12482
+ *Constraints:* `T` models `totally_ordered`.
12483
+
12484
+ *Returns:* If `none_of(mask)` is `true`, returns
12485
+ `numeric_limits<T>::max()`. Otherwise, returns the value of a selected
12486
+ element `x[`j`]` for which `x[`i`] < x[`j`]` is `false` for all selected
12487
+ indices i of `mask`.
12488
+
12489
+ ``` cpp
12490
+ template<class T, class Abi> constexpr T reduce_max(const basic_vec<T, Abi>& x) noexcept;
12491
+ ```
12492
+
12493
+ *Constraints:* `T` models `totally_ordered`.
12494
+
12495
+ *Returns:* The value of an element `x[`j`]` for which `x[`j`] < x[`i`]`
12496
+ is `false` for all i in the range of \[`0`,
12497
+ `basic_vec<T, Abi>::size()`).
12498
+
12499
+ ``` cpp
12500
+ template<class T, class Abi>
12501
+ constexpr T reduce_max(
12502
+ const basic_vec<T, Abi>&, const typename basic_vec<T, Abi>::mask_type&) noexcept;
12503
+ ```
12504
+
12505
+ *Constraints:* `T` models `totally_ordered`.
12506
+
12507
+ *Returns:* If `none_of(mask)` is `true`, returns
12508
+ `numeric_limits<V::value_type>::lowest()`. Otherwise, returns the value
12509
+ of a selected element `x[`j`]` for which `x[`j`] < x[`i`]` is `false`
12510
+ for all selected indices i of `mask`.
12511
+
12512
+ #### Load and store functions <a id="simd.loadstore">[[simd.loadstore]]</a>
12513
+
12514
+ ``` cpp
12515
+ template<class V = see below, ranges::contiguous_range R, class... Flags>
12516
+ requires ranges::sized_range<R>
12517
+ constexpr V unchecked_load(R&& r, flags<Flags...> f = {});
12518
+ template<class V = see below, ranges::contiguous_range R, class... Flags>
12519
+ requires ranges::sized_range<R>
12520
+ constexpr V unchecked_load(R&& r, const typename V::mask_type& mask, flags<Flags...> f = {});
12521
+ template<class V = see below, contiguous_iterator I, class... Flags>
12522
+ constexpr V unchecked_load(I first, iter_difference_t<I> n, flags<Flags...> f = {});
12523
+ template<class V = see below, contiguous_iterator I, class... Flags>
12524
+ constexpr V unchecked_load(I first, iter_difference_t<I> n, const typename V::mask_type& mask,
12525
+ flags<Flags...> f = {});
12526
+ template<class V = see below, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags>
12527
+ constexpr V unchecked_load(I first, S last, flags<Flags...> f = {});
12528
+ template<class V = see below, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags>
12529
+ constexpr V unchecked_load(I first, S last, const typename V::mask_type& mask,
12530
+ flags<Flags...> f = {});
12531
+ ```
12532
+
12533
+ Let
12534
+
12535
+ - `mask` be `V::mask_type(true)` for the overloads with no `mask`
12536
+ parameter;
12537
+ - `R` be `span<const iter_value_t<I>>` for the overloads with no
12538
+ template parameter `R`;
12539
+ - `r` be `R(first, n)` for the overloads with an `n` parameter and
12540
+ `R(first, last)` for the overloads with a `last` parameter.
12541
+
12542
+ *Mandates:* If `ranges::size(r)` is a constant expression then
12543
+ `ranges::size(r)` ≥ `V::size()`.
12544
+
12545
+ *Preconditions:*
12546
+
12547
+ - \[`first`, `first + n`) is a valid range for the overloads with an `n`
12548
+ parameter.
12549
+ - \[`first`, `last`) is a valid range for the overloads with a `last`
12550
+ parameter.
12551
+ - `ranges::size(r)` ≥ `V::size()`
12552
+
12553
+ *Effects:* Equivalent to: `return partial_load<V>(r, mask, f);`
12554
+
12555
+ *Remarks:* The default argument for template parameter `V` is
12556
+ `basic_vec<ranges::range_value_t<R>>`.
12557
+
12558
+ ``` cpp
12559
+ template<class V = see below, ranges::contiguous_range R, class... Flags>
12560
+ requires ranges::sized_range<R>
12561
+ constexpr V partial_load(R&& r, flags<Flags...> f = {});
12562
+ template<class V = see below, ranges::contiguous_range R, class... Flags>
12563
+ requires ranges::sized_range<R>
12564
+ constexpr V partial_load(R&& r, const typename V::mask_type& mask, flags<Flags...> f = {});
12565
+ template<class V = see below, contiguous_iterator I, class... Flags>
12566
+ constexpr V partial_load(I first, iter_difference_t<I> n, flags<Flags...> f = {});
12567
+ template<class V = see below, contiguous_iterator I, class... Flags>
12568
+ constexpr V partial_load(I first, iter_difference_t<I> n, const typename V::mask_type& mask,
12569
+ flags<Flags...> f = {});
12570
+ template<class V = see below, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags>
12571
+ constexpr V partial_load(I first, S last, flags<Flags...> f = {});
12572
+ template<class V = see below, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags>
12573
+ constexpr V partial_load(I first, S last, const typename V::mask_type& mask,
12574
+ flags<Flags...> f = {});
12575
+ ```
12576
+
12577
+ Let
12578
+
12579
+ - `mask` be `V::mask_type(true)` for the overloads with no `mask`
12580
+ parameter;
12581
+ - `R` be `span<const iter_value_t<I>>` for the overloads with no
12582
+ template parameter `R`;
12583
+ - `r` be `R(first, n)` for the overloads with an `n` parameter and
12584
+ `R(first, last)` for the overloads with a `last` parameter.
12585
+
12586
+ *Mandates:*
12587
+
12588
+ - `ranges::range_value_t<R>` is a vectorizable type,
12589
+ - `same_as<remove_cvref_t<V>, V>` is `true`,
12590
+ - `V` is an enabled specialization of `basic_vec`, and
12591
+ - if the template parameter pack `Flags` does not contain
12592
+ *`convert-flag`*, then the conversion from `ranges::range_value_t<R>`
12593
+ to `V::value_type` is value-preserving.
12594
+
12595
+ *Preconditions:*
12596
+
12597
+ - \[`first`, `first + n`) is a valid range for the overloads with an `n`
12598
+ parameter.
12599
+ - \[`first`, `last`) is a valid range for the overloads with a `last`
12600
+ parameter.
12601
+ - If the template parameter pack `Flags` contains *`aligned-flag`*,
12602
+ `ranges::data(r)` points to storage aligned by
12603
+ `alignment_v<V, ranges::range_value_t<R>>`.
12604
+ - If the template parameter pack `Flags` contains
12605
+ *`overaligned-flag`*`<N>`, `ranges::data(r)` points to storage aligned
12606
+ by `N`.
12607
+
12608
+ *Effects:* Initializes the iᵗʰ element with
12609
+ `mask[`i`] && `i` < ranges::size(r) ? static_cast<T>(ranges::data(r)[`i`]) : T()`
12610
+ for all i in the range of \[`0`, `V::size()`).
12611
+
12612
+ *Remarks:* The default argument for template parameter `V` is
12613
+ `basic_vec<ranges::range_value_t<R>>`.
12614
+
12615
+ ``` cpp
12616
+ template<class T, class Abi, ranges::contiguous_range R, class... Flags>
12617
+ requires ranges::sized_range<R> && indirectly_writable<ranges::iterator_t<R>, T>
12618
+ constexpr void unchecked_store(const basic_vec<T, Abi>& v, R&& r, flags<Flags...> f = {});
12619
+ template<class T, class Abi, ranges::contiguous_range R, class... Flags>
12620
+ requires ranges::sized_range<R> && indirectly_writable<ranges::iterator_t<R>, T>
12621
+ constexpr void unchecked_store(const basic_vec<T, Abi>& v, R&& r,
12622
+ const typename basic_vec<T, Abi>::mask_type& mask, flags<Flags...> f = {});
12623
+ template<class T, class Abi, contiguous_iterator I, class... Flags>
12624
+ requires indirectly_writable<I, T>
12625
+ constexpr void unchecked_store(const basic_vec<T, Abi>& v, I first, iter_difference_t<I> n,
12626
+ flags<Flags...> f = {});
12627
+ template<class T, class Abi, contiguous_iterator I, class... Flags>
12628
+ requires indirectly_writable<I, T>
12629
+ constexpr void unchecked_store(const basic_vec<T, Abi>& v, I first, iter_difference_t<I> n,
12630
+ const typename basic_vec<T, Abi>::mask_type& mask, flags<Flags...> f = {});
12631
+ template<class T, class Abi, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags>
12632
+ requires indirectly_writable<I, T>
12633
+ constexpr void unchecked_store(const basic_vec<T, Abi>& v, I first, S last,
12634
+ flags<Flags...> f = {});
12635
+ template<class T, class Abi, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags>
12636
+ requires indirectly_writable<I, T>
12637
+ constexpr void unchecked_store(const basic_vec<T, Abi>& v, I first, S last,
12638
+ const typename basic_vec<T, Abi>::mask_type& mask, flags<Flags...> f = {});
12639
+ ```
12640
+
12641
+ Let
12642
+
12643
+ - `mask` be `basic_vec<T, Abi>::mask_type(true)` for the overloads with
12644
+ no `mask` parameter;
12645
+ - `R` be `span<iter_value_t<I>>` for the overloads with no template
12646
+ parameter `R`;
12647
+ - `r` be `R(first, n)` for the overloads with an `n` parameter and
12648
+ `R(first, last)` for the overloads with a `last` parameter.
12649
+
12650
+ *Mandates:* If `ranges::size(r)` is a constant expression then
12651
+ `ranges::size(r)` ≥ *`simd-size-v`*`<T, Abi>`.
12652
+
12653
+ *Preconditions:*
12654
+
12655
+ - \[`first`, `first + n`) is a valid range for the overloads with an `n`
12656
+ parameter.
12657
+ - \[`first`, `last`) is a valid range for the overloads with a `last`
12658
+ parameter.
12659
+ - `ranges::size(r)` ≥ *`simd-size-v`*`<T, Abi>`
12660
+
12661
+ *Effects:* Equivalent to: `partial_store(v, r, mask, f)`.
12662
+
12663
+ ``` cpp
12664
+ template<class T, class Abi, ranges::contiguous_range R, class... Flags>
12665
+ requires ranges::sized_range<R> && indirectly_writable<ranges::iterator_t<R>, T>
12666
+ constexpr void partial_store(const basic_vec<T, Abi>& v, R&& r, flags<Flags...> f = {});
12667
+ template<class T, class Abi, ranges::contiguous_range R, class... Flags>
12668
+ requires ranges::sized_range<R> && indirectly_writable<ranges::iterator_t<R>, T>
12669
+ constexpr void partial_store(const basic_vec<T, Abi>& v, R&& r,
12670
+ const typename basic_vec<T, Abi>::mask_type& mask, flags<Flags...> f = {});
12671
+ template<class T, class Abi, contiguous_iterator I, class... Flags>
12672
+ requires indirectly_writable<I, T>
12673
+ constexpr void partial_store(const basic_vec<T, Abi>& v, I first, iter_difference_t<I> n,
12674
+ flags<Flags...> f = {});
12675
+ template<class T, class Abi, contiguous_iterator I, class... Flags>
12676
+ requires indirectly_writable<I, T>
12677
+ constexpr void partial_store(const basic_vec<T, Abi>& v, I first, iter_difference_t<I> n,
12678
+ const typename basic_vec<T, Abi>::mask_type& mask, flags<Flags...> f = {});
12679
+ template<class T, class Abi, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags>
12680
+ requires indirectly_writable<I, T>
12681
+ constexpr void partial_store(const basic_vec<T, Abi>& v, I first, S last,
12682
+ flags<Flags...> f = {});
12683
+ template<class T, class Abi, contiguous_iterator I, sized_sentinel_for<I> S, class... Flags>
12684
+ requires indirectly_writable<I, T>
12685
+ constexpr void partial_store(const basic_vec<T, Abi>& v, I first, S last,
12686
+ const typename basic_vec<T, Abi>::mask_type& mask, flags<Flags...> f = {});
12687
+ ```
12688
+
12689
+ Let
12690
+
12691
+ - `mask` be `basic_vec<T, Abi>::mask_type(true)` for the overloads with
12692
+ no `mask` parameter;
12693
+ - `R` be `span<iter_value_t<I>>` for the overloads with no template
12694
+ parameter `R`;
12695
+ - `r` be `R(first, n)` for the overloads with an `n` parameter and
12696
+ `R(first, last)` for the overloads with a `last` parameter.
12697
+
12698
+ *Mandates:*
12699
+
12700
+ - `ranges::range_value_t<R>` is a vectorizable type, and
12701
+ - if the template parameter pack `Flags` does not contain
12702
+ *`convert-flag`*, then the conversion from `T` to
12703
+ `ranges::range_value_t<R>` is value-preserving.
12704
+
12705
+ *Preconditions:*
12706
+
12707
+ - \[`first`, `first + n`) is a valid range for the overloads with an `n`
12708
+ parameter.
12709
+ - \[`first`, `last`) is a valid range for the overloads with a `last`
12710
+ parameter.
12711
+ - If the template parameter pack `Flags` contains *`aligned-flag`*,
12712
+ `ranges::data(r)` points to storage aligned by
12713
+ `alignment_v<basic_vec<T, Abi>, ranges::range_value_t<R>>`.
12714
+ - If the template parameter pack `Flags` contains
12715
+ *`overaligned-flag`*`<N>`, `ranges::data(r)` points to storage aligned
12716
+ by `N`.
12717
+
12718
+ *Effects:* For all i in the range of \[`0`,
12719
+ `basic_vec<T, Abi>::size()`), if `mask[`i`] && `i` < ranges::size(r)` is
12720
+ `true`, evaluates `ranges::data(r)[`i`] = v[`i`]`.
12721
+
12722
+ #### Static permute <a id="simd.permute.static">[[simd.permute.static]]</a>
12723
+
12724
+ ``` cpp
12725
+ template<simd-size-type N = see below, simd-vec-type V, class IdxMap>
12726
+ constexpr resize_t<N, V> permute(const V& v, IdxMap&& idxmap);
12727
+ template<simd-size-type N = see below, simd-mask-type M, class IdxMap>
12728
+ constexpr resize_t<N, M> permute(const M& v, IdxMap&& idxmap);
12729
+ ```
12730
+
12731
+ Let:
12732
+
12733
+ - *`gen-fn`*`(i)` be `idxmap(i, V::size())` if that expression is
12734
+ well-formed, and `idxmap(i)` otherwise.
12735
+ - *perm-fn* be the following exposition-only function template:
12736
+ ``` cpp
12737
+ template<simd-size-type I>
12738
+ typename V::value_type perm-fn() {
12739
+ constexpr auto src_index = gen-fn(I);
12740
+ if constexpr (src_index == zero_element) {
12741
+ return typename V::value_type();
12742
+ } else if constexpr (src_index == uninit_element) {
12743
+ return unspecified-value;
12744
+ } else {
12745
+ return v[src_index];
12746
+ }
12747
+ }
12748
+ ```
12749
+
12750
+ *Constraints:* At least one of
12751
+ `invoke_result_t<IdxMap&, `*`simd-size-type`*`>` and
12752
+ `invoke_result_t<IdxMap&, `*`simd-size-type`*`, `*`simd-size-type`*`>`
12753
+ satisfies `integral`.
12754
+
12755
+ *Mandates:* *`gen-fn`*`(`i`)` is a constant expression whose value is
12756
+ `zero_element`, `uninit_element`, or in the range \[`0`, `V::size()`),
12757
+ for all i in the range \[`0`, `N`).
12758
+
12759
+ *Returns:* A data-parallel object where the iᵗʰ element is initialized
12760
+ to the result of *`perm-fn`*`<`i`>()` for all i in the range \[`0`,
12761
+ `N`).
12762
+
12763
+ *Remarks:* The default argument for template parameter `N` is
12764
+ `V::size()`.
12765
+
12766
+ #### Dynamic permute <a id="simd.permute.dynamic">[[simd.permute.dynamic]]</a>
12767
+
12768
+ ``` cpp
12769
+ template<simd-vec-type V, simd-integral I>
12770
+ constexpr resize_t<I::size(), V> permute(const V& v, const I& indices);
12771
+ template<simd-mask-type M, simd-integral I>
12772
+ constexpr resize_t<I::size(), M> permute(const M& v, const I& indices);
12773
+ ```
12774
+
12775
+ *Preconditions:* All values in `indices` are in the range \[`0`,
12776
+ `V::size()`).
12777
+
12778
+ *Returns:* A data-parallel object where the iᵗʰ element is initialized
12779
+ to the result of `v[indices[`i`]]` for all i in the range \[`0`,
12780
+ `I::size()`).
12781
+
12782
+ #### Mask permute <a id="simd.permute.mask">[[simd.permute.mask]]</a>
12783
+
12784
+ ``` cpp
12785
+ template<simd-vec-type V>
12786
+ constexpr V compress(const V& v, const typename V::mask_type& selector);
12787
+ template<simd-mask-type M>
12788
+ constexpr M compress(const M& v, const type_identity_t<M>& selector);
12789
+ ```
12790
+
12791
+ Let:
12792
+
12793
+ - *`bit-index`*`(`i`)` be a function which returns the index of the iᵗʰ
12794
+ element of `selector` that is `true`.
12795
+ - *`select-value`*`(`i`)` be a function which returns
12796
+ `v[`*`bit-index`*`(`i`)]` for i in the range \[`0`,
12797
+ `reduce_count(selector)`) and a valid but unspecified value otherwise.
12798
+ \[*Note 1*: Different calls to *`select-value`* can return different
12799
+ unspecified values. — *end note*]
12800
+
12801
+ *Returns:* A data-parallel object where the iᵗʰ element is initialized
12802
+ to the result of *`select-value`*`(`i`)` for all i in the range \[`0`,
12803
+ `V::size()`).
12804
+
12805
+ ``` cpp
12806
+ template<simd-vec-type V>
12807
+ constexpr V compress(const V& v, const typename V::mask_type& selector,
12808
+ const typename V::value_type& fill_value);
12809
+ template<simd-mask-type M>
12810
+ constexpr M compress(const M& v, const type_identity_t<M>& selector,
12811
+ const typename M::value_type& fill_value);
12812
+ ```
12813
+
12814
+ Let:
12815
+
12816
+ - *`bit-index`*`(`i`)` be a function which returns the index of the iᵗʰ
12817
+ element of `selector` that is `true`.
12818
+ - *`select-value`*`(`i`)` be a function which returns
12819
+ `v[`*`bit-index`*`(`i`)]` for i in the range \[`0`,
12820
+ `reduce_count(selector)`) and `fill_value` otherwise.
12821
+
12822
+ *Returns:* A data-parallel object where the iᵗʰ element is initialized
12823
+ to the result of *`select-value`*`(`i`)` for all i in the range \[`0`,
12824
+ `V::size()`).
12825
+
12826
+ ``` cpp
12827
+ template<simd-vec-type V>
12828
+ constexpr V expand(const V& v, const typename V::mask_type& selector, const V& original = {});
12829
+ template<simd-mask-type M>
12830
+ constexpr M expand(const M& v, const type_identity_t<M>& selector, const M& original = {});
12831
+ ```
12832
+
12833
+ Let:
12834
+
12835
+ - *set-indices* be a list of the index positions of `true` elements in
12836
+ `selector`, in ascending order.
12837
+ - *`bit-lookup`*`(`b`)` be a function which returns the index where b
12838
+ appears in *`set-indices`*.
12839
+ - *`select-value`*`(`i`)` be a function which returns
12840
+ `v[`*`bit-lookup`*`(`i`)]` if `selector[`i`]` is `true`, otherwise
12841
+ returns `original[`i`]`.
12842
+
12843
+ *Returns:* A data-parallel object where the iᵗʰ element is initialized
12844
+ to the result of *`select-value`*`(`i`)` for all i in the range \[`0`,
12845
+ `V::size()`).
12846
+
12847
+ #### Memory permute <a id="simd.permute.memory">[[simd.permute.memory]]</a>
12848
+
12849
+ ``` cpp
12850
+ template<class V = see below, ranges::contiguous_range R, simd-integral I, class... Flags>
12851
+ requires ranges::sized_range<R>
12852
+ constexpr V unchecked_gather_from(R&& in, const I& indices, flags<Flags...> f = {});
12853
+ template<class V = see below, ranges::contiguous_range R, simd-integral I, class... Flags>
12854
+ requires ranges::sized_range<R>
12855
+ constexpr V unchecked_gather_from(R&& in, const typename I::mask_type& mask,
12856
+ const I& indices, flags<Flags...> f = {});
12857
+ ```
12858
+
12859
+ Let `mask` be `typename I::mask_type(true)` for the overload with no
12860
+ `mask` parameter.
12861
+
12862
+ *Preconditions:* All values in
12863
+ `select(mask, indices, typename I::value_type())` are in the range
12864
+ \[`0`, `ranges::size(in)`).
12865
+
12866
+ *Effects:* Equivalent to:
12867
+ `return partial_gather_from<V>(in, mask, indices, f);`
12868
+
12869
+ *Remarks:* The default argument for template parameter `V` is
12870
+ `vec<ranges::range_value_t<R>, I::size()>`.
12871
+
12872
+ ``` cpp
12873
+ template<class V = see below, ranges::contiguous_range R, simd-integral I, class... Flags>
12874
+ requires ranges::sized_range<R>
12875
+ constexpr V partial_gather_from(R&& in, const I& indices, flags<Flags...> f = {});
12876
+ template<class V = see below, ranges::contiguous_range R, simd-integral I, class... Flags>
12877
+ requires ranges::sized_range<R>
12878
+ constexpr V partial_gather_from(R&& in, const typename I::mask_type& mask,
12879
+ const I& indices, flags<Flags...> f = {});
12880
+ ```
12881
+
12882
+ Let:
12883
+
12884
+ - `mask` be `typename I::mask_type(true)` for the overload with no
12885
+ `mask` parameter;
12886
+ - `T` be `typename V::value_type`.
12887
+
12888
+ *Mandates:*
12889
+
12890
+ - `ranges::range_value_t<R>` is a vectorizable type,
12891
+ - `same_as<remove_cvref_t<V>, V>` is `true`,
12892
+ - `V` is an enabled specialization of `basic_vec`,
12893
+ - `V::size() == I::size()` is `true`, and
12894
+ - if the template parameter pack `Flags` does not contain
12895
+ *convert-flag*, then the conversion from `ranges::range_value_t<R>` to
12896
+ `T` is value-preserving.
12897
+
12898
+ *Preconditions:*
12899
+
12900
+ - If the template parameter pack `Flags` contains *aligned-flag*,
12901
+ `ranges::data(in)` points to storage aligned by
12902
+ `alignment_v<V, ranges::range_value_t<R>>`.
12903
+ - If the template parameter pack `Flags` contains
12904
+ *`overaligned-flag`*`<N>`, `ranges::data(in)` points to storage
12905
+ aligned by `N`.
12906
+
12907
+ *Returns:* A `basic_vec` object where the iᵗʰ element is initialized to
12908
+ the result of
12909
+
12910
+ ``` cpp
12911
+ mask[i] && indices[i] < ranges::size(in) ? static_cast<T>(ranges::data(in)[indices[i]]) : T()
12912
+ ```
12913
+
12914
+ for all i in the range \[`0`, `I::size()`).
12915
+
12916
+ *Remarks:* The default argument for template parameter `V` is
12917
+ `vec<ranges::range_value_t<R>, I::size()>`.
12918
+
12919
+ ``` cpp
12920
+ template<simd-vec-type V, ranges::contiguous_range R, simd-integral I, class... Flags>
12921
+ requires ranges::sized_range<R>
12922
+ constexpr void unchecked_scatter_to(const V& v, R&& out, const I& indices,
12923
+ flags<Flags...> f = {});
12924
+ template<simd-vec-type V, ranges::contiguous_range R, simd-integral I, class... Flags>
12925
+ requires ranges::sized_range<R>
12926
+ constexpr void unchecked_scatter_to(const V& v, R&& out, const typename I::mask_type& mask,
12927
+ const I& indices, flags<Flags...> f = {});
12928
+ ```
12929
+
12930
+ Let `mask` be `typename I::mask_type(true)` for the overload with no
12931
+ `mask` parameter.
12932
+
12933
+ *Preconditions:* All values in
12934
+ `select(mask, indices, typename I::value_type())` are in the range
12935
+ \[`0`, `ranges::size(out)`).
12936
+
12937
+ *Effects:* Equivalent to:
12938
+ `partial_scatter_to(v, out, mask, indices, f);`
12939
+
12940
+ ``` cpp
12941
+ template<simd-vec-type V, ranges::contiguous_range R, simd-integral I, class... Flags>
12942
+ requires ranges::sized_range<R>
12943
+ constexpr void
12944
+ partial_scatter_to(const V& v, R&& out, const I& indices, flags<Flags...> f = {});
12945
+ template<simd-vec-type V, ranges::contiguous_range R, simd-integral I, class... Flags>
12946
+ requires ranges::sized_range<R>
12947
+ constexpr void partial_scatter_to(const V& v, R&& out, const typename I::mask_type& mask,
12948
+ const I& indices, flags<Flags...> f = {});
12949
+ ```
12950
+
12951
+ Let `mask` be `typename I::mask_type(true)` for the overload with no
12952
+ `mask` parameter.
12953
+
12954
+ *Constraints:* `V::size() == I::size()` is `true`.
12955
+
12956
+ *Mandates:*
12957
+
12958
+ - `ranges::range_value_t<R>` is a vectorizable type, and
12959
+ - if the template parameter pack `Flags` does not contain
12960
+ *convert-flag*, then the conversion from `typename V::value_type` to
12961
+ `ranges::range_value_t<R>` is value-preserving.
12962
+
12963
+ *Preconditions:*
12964
+
12965
+ - For all selected indices i the values `indices[`i`]` are unique.
12966
+ - If the template parameter pack `Flags` contains *aligned-flag*,
12967
+ `ranges::data(out)` points to storage aligned by
12968
+ `alignment_v<V, ranges::range_value_t<R>>`.
12969
+ - If the template parameter pack `Flags` contains
12970
+ *`overaligned-flag`*`<N>`, `ranges::data(out)` points to storage
12971
+ aligned by `N`.
12972
+
12973
+ *Effects:* For all i in the range \[`0`, `I::size()`), if
12974
+ `mask[`i`] && (indices[`i`] < ranges::size(out))` is `true`, evaluates
12975
+ `ranges::data(out)[indices[`i`]] = v[`i`]`.
12976
+
12977
+ #### Creation <a id="simd.creation">[[simd.creation]]</a>
12978
+
12979
+ ``` cpp
12980
+ template<class T, class Abi>
12981
+ constexpr auto chunk(const basic_vec<typename T::value_type, Abi>& x) noexcept;
12982
+ template<class T, class Abi>
12983
+ constexpr auto chunk(const basic_mask<mask-element-size<T>, Abi>& x) noexcept;
12984
+ ```
12985
+
12986
+ *Constraints:*
12987
+
12988
+ - For the first overload, `T` is an enabled specialization of
12989
+ `basic_vec`. If
12990
+ `basic_vec<typename T::value_type, Abi>::size() % T::size()` is not
12991
+ `0`, then
12992
+ `resize_t<basic_vec<typename T::value_type, Abi>::size() % T::size(), T>`
12993
+ is valid and denotes a type.
12994
+ - For the second overload, `T` is an enabled specialization of
12995
+ `basic_mask`. If
12996
+ `basic_mask<`*`mask-element-size`*`<T>, Abi>::size() % T::size()` is
12997
+ not `0`, then
12998
+ `resize_t<basic_mask<`*`mask-element-size`*`<T>, Abi>::size() % T::size(), T>`
12999
+ is valid and denotes a type.
13000
+
13001
+ Let N be `x.size() / T::size()`.
13002
+
13003
+ *Returns:*
13004
+
13005
+ - If `x.size() % T::size() == 0` is `true`, an `array<T, `N`>` with the
13006
+ iᵗʰ `basic_vec` or `basic_mask` element of the jᵗʰ `array` element
13007
+ initialized to the value of the element in `x` with index
13008
+ i` + `j` * T::size()`.
13009
+ - Otherwise, a `tuple` of N objects of type `T` and one object of type
13010
+ `resize_t<x.size() % T::size(), T>`. The iᵗʰ `basic_vec` or
13011
+ `basic_mask` element of the jᵗʰ `tuple` element of type `T` is
13012
+ initialized to the value of the element in `x` with index
13013
+ i` + `j` * T::size()`. The iᵗʰ `basic_vec` or `basic_mask` element of
13014
+ the Nᵗʰ `tuple` element is initialized to the value of the element in
13015
+ `x` with index i` + `N` * T::size()`.
13016
+
13017
+ ``` cpp
13018
+ template<simd-size-type N, class T, class Abi>
13019
+ constexpr auto chunk(const basic_vec<T, Abi>& x) noexcept;
13020
+ ```
13021
+
13022
+ *Effects:* Equivalent to:
13023
+ `return chunk<resize_t<N, basic_vec<T, Abi>>>(x);`
13024
+
13025
+ ``` cpp
13026
+ template<simd-size-type N, size_t Bytes, class Abi>
13027
+ constexpr auto chunk(const basic_mask<Bytes, Abi>& x) noexcept;
13028
+ ```
13029
+
13030
+ *Effects:* Equivalent to:
13031
+ `return chunk<resize_t<N, basic_mask<Bytes, Abi>>>(x);`
13032
+
13033
+ ``` cpp
13034
+ template<class T, class... Abis>
13035
+ constexpr vec<T, (basic_vec<T, Abis>::size() + ...)>
13036
+ cat(const basic_vec<T, Abis>&... xs) noexcept;
13037
+ template<size_t Bytes, class... Abis>
13038
+ constexpr basic_mask<Bytes, deduce-abi-t<integer-from<Bytes>,
13039
+ (basic_mask<Bytes, Abis>::size() + ...)>>
13040
+ cat(const basic_mask<Bytes, Abis>&... xs) noexcept;
13041
+ ```
13042
+
13043
+ *Constraints:*
13044
+
13045
+ - For the first overload `vec<T, (basic_vec<T, Abis>::size() + ...)>` is
13046
+ enabled.
13047
+ - For the second overload
13048
+ `basic_mask<Bytes, `*`deduce-abi-t`*`<`*`integer-from`*`<Bytes>, (basic_mask<Bytes, Abis>::size() + ...)>>`
13049
+ is enabled.
13050
+
13051
+ *Returns:* A data-parallel object initialized with the concatenated
13052
+ values in the `xs` pack of data-parallel objects: The iᵗʰ
13053
+ `basic_vec`/`basic_mask` element of the jᵗʰ parameter in the `xs` pack
13054
+ is copied to the return value’s element with index i + the sum of the
13055
+ width of the first j parameters in the `xs` pack.
13056
+
13057
+ #### Algorithms <a id="simd.alg">[[simd.alg]]</a>
13058
+
13059
+ ``` cpp
13060
+ template<class T, class Abi>
13061
+ constexpr basic_vec<T, Abi> min(const basic_vec<T, Abi>& a,
13062
+ const basic_vec<T, Abi>& b) noexcept;
13063
+ ```
13064
+
13065
+ *Constraints:* `T` models `totally_ordered`.
13066
+
13067
+ *Returns:* The result of the element-wise application of
13068
+ `min(a[`i`], b[`i`])` for all i in the range of \[`0`,
13069
+ `basic_vec<T, Abi>::size()`).
13070
+
13071
+ ``` cpp
13072
+ template<class T, class Abi>
13073
+ constexpr basic_vec<T, Abi> max(const basic_vec<T, Abi>& a,
13074
+ const basic_vec<T, Abi>& b) noexcept;
13075
+ ```
13076
+
13077
+ *Constraints:* `T` models `totally_ordered`.
13078
+
13079
+ *Returns:* The result of the element-wise application of
13080
+ `max(a[`i`], b[`i`])` for all i in the range of \[`0`,
13081
+ `basic_vec<T, Abi>::size()`).
13082
+
13083
+ ``` cpp
13084
+ template<class T, class Abi>
13085
+ constexpr pair<basic_vec<T, Abi>, basic_vec<T, Abi>>
13086
+ minmax(const basic_vec<T, Abi>& a, const basic_vec<T, Abi>& b) noexcept;
13087
+ ```
13088
+
13089
+ *Effects:* Equivalent to: `return pair{min(a, b), max(a, b)};`
13090
+
13091
+ ``` cpp
13092
+ template<class T, class Abi>
13093
+ constexpr basic_vec<T, Abi> clamp(
13094
+ const basic_vec<T, Abi>& v, const basic_vec<T, Abi>& lo, const basic_vec<T, Abi>& hi);
13095
+ ```
13096
+
13097
+ *Constraints:* `T` models `totally_ordered`.
13098
+
13099
+ *Preconditions:* No element in `lo` is greater than the corresponding
13100
+ element in `hi`.
13101
+
13102
+ *Returns:* The result of element-wise application of
13103
+ `clamp(v[`i`], lo[`i`], hi[`i`])` for all i in the range of \[`0`,
13104
+ `basic_vec<T, Abi>::size()`).
13105
+
13106
+ ``` cpp
13107
+ template<class T, class U>
13108
+ constexpr auto select(bool c, const T& a, const U& b)
13109
+ -> remove_cvref_t<decltype(c ? a : b)>;
13110
+ ```
13111
+
13112
+ *Effects:* Equivalent to: `return c ? a : b;`
13113
+
13114
+ ``` cpp
13115
+ template<size_t Bytes, class Abi, class T, class U>
13116
+ constexpr auto select(const basic_mask<Bytes, Abi>& c, const T& a, const U& b)
13117
+ noexcept -> decltype(simd-select-impl(c, a, b));
13118
+ ```
13119
+
13120
+ *Effects:* Equivalent to:
13121
+
13122
+ ``` cpp
13123
+ return simd-select-impl(c, a, b);
13124
+ ```
13125
+
13126
+ where *`simd-select-impl`* is found by argument-dependent
13127
+ lookup [[basic.lookup.argdep]] contrary to [[contents]].
13128
+
13129
+ #### Mathematical functions <a id="simd.math">[[simd.math]]</a>
13130
+
13131
+ ``` cpp
13132
+ template<math-floating-point V>
13133
+ constexpr rebind_t<int, deduced-vec-t<V>> ilogb(const V& x);
13134
+ template<math-floating-point V>
13135
+ constexpr deduced-vec-t<V> ldexp(const V& x, const rebind_t<int, deduced-vec-t<V>>& exp);
13136
+ template<math-floating-point V>
13137
+ constexpr deduced-vec-t<V> scalbn(const V& x, const rebind_t<int, deduced-vec-t<V>>& n);
13138
+ template<math-floating-point V>
13139
+ constexpr deduced-vec-t<V>
13140
+ scalbln(const V& x, const rebind_t<long int, deduced-vec-t<V>>& n);
13141
+ template<signed_integral T, class Abi>
13142
+ constexpr basic_vec<T, Abi> abs(const basic_vec<T, Abi>& j);
13143
+ template<math-floating-point V>
13144
+ constexpr deduced-vec-t<V> abs(const V& j);
13145
+ template<math-floating-point V>
13146
+ constexpr deduced-vec-t<V> fabs(const V& x);
13147
+ template<math-floating-point V>
13148
+ constexpr deduced-vec-t<V> ceil(const V& x);
13149
+ template<math-floating-point V>
13150
+ constexpr deduced-vec-t<V> floor(const V& x);
13151
+ template<math-floating-point V>
13152
+ deduced-vec-t<V> nearbyint(const V& x);
13153
+ template<math-floating-point V>
13154
+ deduced-vec-t<V> rint(const V& x);
13155
+ template<math-floating-point V>
13156
+ rebind_t<long int, deduced-vec-t<V>> lrint(const V& x);
13157
+ template<math-floating-point V>
13158
+ rebind_t<long long int, deduced-vec-t<V>> llrint(const V& x);
13159
+ template<math-floating-point V>
13160
+ constexpr deduced-vec-t<V> round(const V& x);
13161
+ template<math-floating-point V>
13162
+ constexpr rebind_t<long int, deduced-vec-t<V>> lround(const V& x);
13163
+ template<math-floating-point V>
13164
+ constexpr rebind_t<long long int, deduced-vec-t<V>> llround(const V& x);
13165
+ template<class V0, class V1>
13166
+ constexpr math-common-simd-t<V0, V1> fmod(const V0& x, const V1& y);
13167
+ template<math-floating-point V>
13168
+ constexpr deduced-vec-t<V> trunc(const V& x);
13169
+ template<class V0, class V1>
13170
+ constexpr math-common-simd-t<V0, V1> remainder(const V0& x, const V1& y);
13171
+ template<class V0, class V1>
13172
+ constexpr math-common-simd-t<V0, V1> copysign(const V0& x, const V1& y);
13173
+ template<class V0, class V1>
13174
+ constexpr math-common-simd-t<V0, V1> nextafter(const V0& x, const V1& y);
13175
+ template<class V0, class V1>
13176
+ constexpr math-common-simd-t<V0, V1> fdim(const V0& x, const V1& y);
13177
+ template<class V0, class V1>
13178
+ constexpr math-common-simd-t<V0, V1> fmax(const V0& x, const V1& y);
13179
+ template<class V0, class V1>
13180
+ constexpr math-common-simd-t<V0, V1> fmin(const V0& x, const V1& y);
13181
+ template<class V0, class V1, class V2>
13182
+ constexpr math-common-simd-t<V0, V1, V2> fma(const V0& x, const V1& y, const V2& z);
13183
+ template<math-floating-point V>
13184
+ constexpr rebind_t<int, deduced-vec-t<V>> fpclassify(const V& x);
13185
+ template<math-floating-point V>
13186
+ constexpr typename deduced-vec-t<V>::mask_type isfinite(const V& x);
13187
+ template<math-floating-point V>
13188
+ constexpr typename deduced-vec-t<V>::mask_type isinf(const V& x);
13189
+ template<math-floating-point V>
13190
+ constexpr typename deduced-vec-t<V>::mask_type isnan(const V& x);
13191
+ template<math-floating-point V>
13192
+ constexpr typename deduced-vec-t<V>::mask_type isnormal(const V& x);
13193
+ template<math-floating-point V>
13194
+ constexpr typename deduced-vec-t<V>::mask_type signbit(const V& x);
13195
+ template<class V0, class V1>
13196
+ constexpr typename math-common-simd-t<V0, V1>::mask_type isgreater(const V0& x, const V1& y);
13197
+ template<class V0, class V1>
13198
+ constexpr typename math-common-simd-t<V0, V1>::mask_type
13199
+ isgreaterequal(const V0& x, const V1& y);
13200
+ template<class V0, class V1>
13201
+ constexpr typename math-common-simd-t<V0, V1>::mask_type isless(const V0& x, const V1& y);
13202
+ template<class V0, class V1>
13203
+ constexpr typename math-common-simd-t<V0, V1>::mask_type islessequal(const V0& x, const V1& y);
13204
+ template<class V0, class V1>
13205
+ constexpr typename math-common-simd-t<V0, V1>::mask_type islessgreater(const V0& x, const V1& y);
13206
+ template<class V0, class V1>
13207
+ constexpr typename math-common-simd-t<V0, V1>::mask_type isunordered(const V0& x, const V1& y);
13208
+ ```
13209
+
13210
+ Let `Ret` denote the return type of the specialization of a function
13211
+ template with the name *`math-func`*. Let *`math-func-vec`* denote:
13212
+
13213
+ ``` cpp
13214
+ template<class... Args>
13215
+ Ret math-func-vec(Args... args) {
13216
+ return Ret([&](simd-size-type i) {
13217
+ return math-func(make-compatible-simd-t<Ret, Args>(args)[i]...);
13218
+ });
13219
+ }
13220
+ ```
13221
+
13222
+ *Returns:* A value `ret` of type `Ret`, that is element-wise equal to
13223
+ the result of calling *`math-func-vec`* with the arguments of the above
13224
+ functions. If in an invocation of a scalar overload of *`math-func`* for
13225
+ index `i` in *`math-func-vec`* a domain, pole, or range error would
13226
+ occur, the value of `ret[i]` is unspecified.
13227
+
13228
+ *Remarks:* It is unspecified whether `errno` [[errno]] is accessed.
13229
+
13230
+ ``` cpp
13231
+ template<math-floating-point V> constexpr deduced-vec-t<V> acos(const V& x);
13232
+ template<math-floating-point V> constexpr deduced-vec-t<V> asin(const V& x);
13233
+ template<math-floating-point V> constexpr deduced-vec-t<V> atan(const V& x);
13234
+ template<class V0, class V1>
13235
+ constexpr math-common-simd-t<V0, V1> atan2(const V0& y, const V1& x);
13236
+ template<math-floating-point V> constexpr deduced-vec-t<V> cos(const V& x);
13237
+ template<math-floating-point V> constexpr deduced-vec-t<V> sin(const V& x);
13238
+ template<math-floating-point V> constexpr deduced-vec-t<V> tan(const V& x);
13239
+ template<math-floating-point V> constexpr deduced-vec-t<V> acosh(const V& x);
13240
+ template<math-floating-point V> constexpr deduced-vec-t<V> asinh(const V& x);
13241
+ template<math-floating-point V> constexpr deduced-vec-t<V> atanh(const V& x);
13242
+ template<math-floating-point V> constexpr deduced-vec-t<V> cosh(const V& x);
13243
+ template<math-floating-point V> constexpr deduced-vec-t<V> sinh(const V& x);
13244
+ template<math-floating-point V> constexpr deduced-vec-t<V> tanh(const V& x);
13245
+ template<math-floating-point V> constexpr deduced-vec-t<V> exp(const V& x);
13246
+ template<math-floating-point V> constexpr deduced-vec-t<V> exp2(const V& x);
13247
+ template<math-floating-point V> constexpr deduced-vec-t<V> expm1(const V& x);
13248
+ template<math-floating-point V> constexpr deduced-vec-t<V> log(const V& x);
13249
+ template<math-floating-point V> constexpr deduced-vec-t<V> log10(const V& x);
13250
+ template<math-floating-point V> constexpr deduced-vec-t<V> log1p(const V& x);
13251
+ template<math-floating-point V> constexpr deduced-vec-t<V> log2(const V& x);
13252
+ template<math-floating-point V> constexpr deduced-vec-t<V> logb(const V& x);
13253
+ template<math-floating-point V> constexpr deduced-vec-t<V> cbrt(const V& x);
13254
+ template<class V0, class V1>
13255
+ constexpr math-common-simd-t<V0, V1> hypot(const V0& x, const V1& y);
13256
+ template<class V0, class V1, class V2>
13257
+ constexpr math-common-simd-t<V0, V1, V2> hypot(const V0& x, const V1& y, const V2& z);
13258
+ template<class V0, class V1>
13259
+ constexpr math-common-simd-t<V0, V1> pow(const V0& x, const V1& y);
13260
+ template<math-floating-point V> constexpr deduced-vec-t<V> sqrt(const V& x);
13261
+ template<math-floating-point V> constexpr deduced-vec-t<V> erf(const V& x);
13262
+ template<math-floating-point V> constexpr deduced-vec-t<V> erfc(const V& x);
13263
+ template<math-floating-point V> constexpr deduced-vec-t<V> lgamma(const V& x);
13264
+ template<math-floating-point V> constexpr deduced-vec-t<V> tgamma(const V& x);
13265
+ template<class V0, class V1, class V2>
13266
+ constexpr math-common-simd-t<V0, V1, V2> lerp(const V0& a, const V1& b, const V2& t) noexcept;
13267
+ template<math-floating-point V>
13268
+ deduced-vec-t<V> assoc_laguerre(const rebind_t<unsigned, deduced-vec-t<V>>& n, const
13269
+ rebind_t<unsigned, deduced-vec-t<V>>& m, const V& x);
13270
+ template<math-floating-point V>
13271
+ deduced-vec-t<V> assoc_legendre(const rebind_t<unsigned, deduced-vec-t<V>>& l, const
13272
+ rebind_t<unsigned, deduced-vec-t<V>>& m, const V& x);
13273
+ template<class V0, class V1>
13274
+ math-common-simd-t<V0, V1> beta(const V0& x, const V1& y);
13275
+ template<math-floating-point V> deduced-vec-t<V> comp_ellint_1(const V& k);
13276
+ template<math-floating-point V> deduced-vec-t<V> comp_ellint_2(const V& k);
13277
+ template<class V0, class V1>
13278
+ math-common-simd-t<V0, V1> comp_ellint_3(const V0& k, const V1& nu);
13279
+ template<class V0, class V1>
13280
+ math-common-simd-t<V0, V1> cyl_bessel_i(const V0& nu, const V1& x);
13281
+ template<class V0, class V1>
13282
+ math-common-simd-t<V0, V1> cyl_bessel_j(const V0& nu, const V1& x);
13283
+ template<class V0, class V1>
13284
+ math-common-simd-t<V0, V1> cyl_bessel_k(const V0& nu, const V1& x);
13285
+ template<class V0, class V1>
13286
+ math-common-simd-t<V0, V1> cyl_neumann(const V0& nu, const V1& x);
13287
+ template<class V0, class V1>
13288
+ math-common-simd-t<V0, V1> ellint_1(const V0& k, const V1& phi);
13289
+ template<class V0, class V1>
13290
+ math-common-simd-t<V0, V1> ellint_2(const V0& k, const V1& phi);
13291
+ template<class V0, class V1, class V2>
13292
+ math-common-simd-t<V0, V1, V2> ellint_3(const V0& k, const V1& nu, const V2& phi);
13293
+ template<math-floating-point V> deduced-vec-t<V> expint(const V& x);
13294
+ template<math-floating-point V> deduced-vec-t<V> hermite(const rebind_t<unsigned,
13295
+ deduced-vec-t<V>>& n, const V& x);
13296
+ template<math-floating-point V> deduced-vec-t<V> laguerre(const rebind_t<unsigned,
13297
+ deduced-vec-t<V>>& n, const V& x);
13298
+ template<math-floating-point V> deduced-vec-t<V> legendre(const rebind_t<unsigned,
13299
+ deduced-vec-t<V>>& l, const V& x);
13300
+ template<math-floating-point V> deduced-vec-t<V> riemann_zeta(const V& x);
13301
+ template<math-floating-point V> deduced-vec-t<V> sph_bessel(const rebind_t<unsigned,
13302
+ deduced-vec-t<V>>& n, const V& x);
13303
+ template<math-floating-point V>
13304
+ deduced-vec-t<V> sph_legendre(const rebind_t<unsigned, deduced-vec-t<V>>& l,
13305
+ const rebind_t<unsigned, deduced-vec-t<V>>& m,
13306
+ const V& theta);
13307
+ template<math-floating-point V> deduced-vec-t<V> sph_neumann(const rebind_t<unsigned,
13308
+ deduced-vec-t<V>>& n, const V& x);
13309
+ ```
13310
+
13311
+ Let `Ret` denote the return type of the specialization of a function
13312
+ template with the name *`math-func`*. Let *`math-func-vec`* denote:
13313
+
13314
+ ``` cpp
13315
+ template<class... Args>
13316
+ Ret math-func-vec(Args... args) {
13317
+ return Ret([&](simd-size-type i) {
13318
+ return math-func(make-compatible-simd-t<Ret, Args>(args)[i]...);
13319
+ });
13320
+ }
13321
+ ```
13322
+
13323
+ *Returns:* A value `ret` of type `Ret`, that is element-wise
13324
+ approximately equal to the result of calling *`math-func-vec`* with the
13325
+ arguments of the above functions. If in an invocation of a scalar
13326
+ overload of *`math-func`* for index `i` in *`math-func-vec`* a domain,
13327
+ pole, or range error would occur, the value of `ret[i]` is unspecified.
13328
+
13329
+ *Remarks:* It is unspecified whether `errno` [[errno]] is accessed.
13330
+
13331
+ ``` cpp
13332
+ template<math-floating-point V>
13333
+ constexpr deduced-vec-t<V> frexp(const V& value, rebind_t<int, deduced-vec-t<V>>* exp);
13334
+ ```
13335
+
13336
+ Let `Ret` be *`deduced-vec-t`*`<V>`. Let *`frexp-vec`* denote:
13337
+
13338
+ ``` cpp
13339
+ template<class V>
13340
+ pair<Ret, rebind_t<int, Ret>> frexp-vec(const V& x) {
13341
+ int r1[Ret::size()];
13342
+ Ret r0([&](simd-size-type i) {
13343
+ return frexp(make-compatible-simd-t<Ret, V>(x)[i], &r1[i]);
13344
+ });
13345
+ return {r0, rebind_t<int, Ret>(r1)};
13346
+ }
13347
+ ```
13348
+
13349
+ Let `ret` be a value of type `pair<Ret, rebind_t<int, Ret>>` that is the
13350
+ same value as the result of calling *`frexp-vec`*`(x)`.
13351
+
13352
+ *Effects:* Sets `*exp` to `ret.second`.
13353
+
13354
+ *Returns:* `ret.first`.
13355
+
13356
+ ``` cpp
13357
+ template<class V0, class V1>
13358
+ constexpr math-common-simd-t<V0, V1> remquo(const V0& x, const V1& y,
13359
+ rebind_t<int, math-common-simd-t<V0, V1>>* quo);
13360
+ ```
13361
+
13362
+ Let `Ret` be *`math-common-simd-t`*`<V0, V1>`. Let *`remquo-vec`*
13363
+ denote:
13364
+
13365
+ ``` cpp
13366
+ template<class V0, class V1>
13367
+ pair<Ret, rebind_t<int, Ret>> remquo-vec(const V0& x, const V1& y) {
13368
+ int r1[Ret::size()];
13369
+ Ret r0([&](simd-size-type i) {
13370
+ return remquo(make-compatible-simd-t<Ret, V0>(x)[i],
13371
+ make-compatible-simd-t<Ret, V1>(y)[i], &r1[i]);
13372
+ });
13373
+ return {r0, rebind_t<int, Ret>(r1)};
13374
+ }
13375
+ ```
13376
+
13377
+ Let `ret` be a value of type `pair<Ret, rebind_t<int, Ret>>` that is the
13378
+ same value as the result of calling *`remquo-vec`*`(x, y)`. If in an
13379
+ invocation of a scalar overload of `remquo` for index `i` in
13380
+ *`remquo-vec`* a domain, pole, or range error would occur, the value of
13381
+ `ret[i]` is unspecified.
13382
+
13383
+ *Effects:* Sets `*quo` to `ret.second`.
13384
+
13385
+ *Returns:* `ret.first`.
13386
+
13387
+ *Remarks:* It is unspecified whether `errno` [[errno]] is accessed.
13388
+
13389
+ ``` cpp
13390
+ template<class T, class Abi>
13391
+ constexpr basic_vec<T, Abi> modf(const type_identity_t<basic_vec<T, Abi>>& value,
13392
+ basic_vec<T, Abi>* iptr);
13393
+ ```
13394
+
13395
+ Let `V` be `basic_vec<T, Abi>`. Let *`modf-vec`* denote:
13396
+
13397
+ ``` cpp
13398
+ pair<V, V> modf-vec(const V& x) {
13399
+ T r1[Ret::size()];
13400
+ V r0([&](simd-size-type i) {
13401
+ return modf(V(x)[i], &r1[i]);
13402
+ });
13403
+ return {r0, V(r1)};
13404
+ }
13405
+ ```
13406
+
13407
+ Let `ret` be a value of type `pair<V, V>` that is the same value as the
13408
+ result of calling *`modf-vec`*`(value)`.
13409
+
13410
+ *Effects:* Sets `*iptr` to `ret.second`.
13411
+
13412
+ *Returns:* `ret.first`.
13413
+
13414
+ #### Bit manipulation <a id="simd.bit">[[simd.bit]]</a>
13415
+
13416
+ ``` cpp
13417
+ template<simd-vec-type V> constexpr V byteswap(const V& v) noexcept;
13418
+ ```
13419
+
13420
+ *Constraints:* The type `V::value_type` models `integral`.
13421
+
13422
+ *Returns:* A `basic_vec` object where the iᵗʰ element is initialized to
13423
+ the result of `std::byteswap(v[`i`])` for all i in the range \[`0`,
13424
+ `V::size()`).
13425
+
13426
+ ``` cpp
13427
+ template<simd-vec-type V> constexpr V bit_ceil(const V& v) noexcept;
13428
+ ```
13429
+
13430
+ *Constraints:* The type `V::value_type` is an unsigned integer
13431
+ type [[basic.fundamental]].
13432
+
13433
+ *Preconditions:* For every i in the range \[`0`, `V::size()`), the
13434
+ smallest power of 2 greater than or equal to `v[`i`]` is representable
13435
+ as a value of type `V::value_type`.
13436
+
13437
+ *Returns:* A `basic_vec` object where the iᵗʰ element is initialized to
13438
+ the result of `std::bit_ceil(v[`i`])` for all i in the range \[`0`,
13439
+ `V::size()`).
13440
+
13441
+ *Remarks:* A function call expression that violates the precondition in
13442
+ the *Preconditions:* element is not a core constant
13443
+ expression [[expr.const]].
13444
+
13445
+ ``` cpp
13446
+ template<simd-vec-type V> constexpr V bit_floor(const V& v) noexcept;
13447
+ ```
13448
+
13449
+ *Constraints:* The type `V::value_type` is an unsigned integer
13450
+ type [[basic.fundamental]].
13451
+
13452
+ *Returns:* A `basic_vec` object where the iᵗʰ element is initialized to
13453
+ the result of `std::bit_floor(v[`i`])` for all i in the range \[`0`,
13454
+ `V::size()`).
13455
+
13456
+ ``` cpp
13457
+ template<simd-vec-type V>
13458
+ constexpr typename V::mask_type has_single_bit(const V& v) noexcept;
13459
+ ```
13460
+
13461
+ *Constraints:* The type `V::value_type` is an unsigned integer
13462
+ type [[basic.fundamental]].
13463
+
13464
+ *Returns:* A `basic_mask` object where the iᵗʰ element is initialized to
13465
+ the result of `std::has_single_bit(v[`i`])` for all i in the range
13466
+ \[`0`, `V::size()`).
13467
+
13468
+ ``` cpp
13469
+ template<simd-vec-type V0, simd-vec-type V1>
13470
+ constexpr V0 rotl(const V0& v0, const V1& v1) noexcept;
13471
+ template<simd-vec-type V0, simd-vec-type V1>
13472
+ constexpr V0 rotr(const V0& v0, const V1& v1) noexcept;
13473
+ ```
13474
+
13475
+ *Constraints:*
13476
+
13477
+ - The type `V0::value_type` is an unsigned integer
13478
+ type [[basic.fundamental]],
13479
+ - the type `V1::value_type` models `integral`,
13480
+ - `V0::size() == V1::size()` is `true`, and
13481
+ - `sizeof(typename V0::value_type) == sizeof(typename V1::value_type)`
13482
+ is `true`.
13483
+
13484
+ *Returns:* A `basic_vec` object where the iᵗʰ element is initialized to
13485
+ the result of *`bit-func`*`(v0[`i`], static_cast<int>(v1[`i`]))` for all
13486
+ i in the range \[`0`, `V0::size()`), where *`bit-func`* is the
13487
+ corresponding scalar function from `<bit>`.
13488
+
13489
+ ``` cpp
13490
+ template<simd-vec-type V> constexpr V rotl(const V& v, int s) noexcept;
13491
+ template<simd-vec-type V> constexpr V rotr(const V& v, int s) noexcept;
13492
+ ```
13493
+
13494
+ *Constraints:* The type `V::value_type` is an unsigned integer
13495
+ type [[basic.fundamental]].
13496
+
13497
+ *Returns:* A `basic_vec` object where the iᵗʰ element is initialized to
13498
+ the result of *`bit-func`*`(v[`i`], s)` for all i in the range \[`0`,
13499
+ `V::size()`), where *`bit-func`* is the corresponding scalar function
13500
+ from `<bit>`.
13501
+
13502
+ ``` cpp
13503
+ template<simd-vec-type V>
13504
+ constexpr rebind_t<make_signed_t<typename V::value_type>, V> bit_width(const V& v) noexcept;
13505
+ template<simd-vec-type V>
13506
+ constexpr rebind_t<make_signed_t<typename V::value_type>, V> countl_zero(const V& v) noexcept;
13507
+ template<simd-vec-type V>
13508
+ constexpr rebind_t<make_signed_t<typename V::value_type>, V> countl_one(const V& v) noexcept;
13509
+ template<simd-vec-type V>
13510
+ constexpr rebind_t<make_signed_t<typename V::value_type>, V> countr_zero(const V& v) noexcept;
13511
+ template<simd-vec-type V>
13512
+ constexpr rebind_t<make_signed_t<typename V::value_type>, V> countr_one(const V& v) noexcept;
13513
+ template<simd-vec-type V>
13514
+ constexpr rebind_t<make_signed_t<typename V::value_type>, V> popcount(const V& v) noexcept;
13515
+ ```
13516
+
13517
+ *Constraints:* The type `V::value_type` is an unsigned integer
13518
+ type [[basic.fundamental]].
13519
+
13520
+ *Returns:* A `basic_vec` object where the iᵗʰ element is initialized to
13521
+ the result of *`bit-func`*`(v[`i`])` for all i in the range \[`0`,
13522
+ `V::size()`), where *`bit-func`* is the corresponding scalar function
13523
+ from `<bit>`.
13524
+
13525
+ #### Complex math <a id="simd.complex.math">[[simd.complex.math]]</a>
13526
+
13527
+ ``` cpp
13528
+ template<simd-complex V>
13529
+ constexpr rebind_t<simd-complex-value-type<V>, V> real(const V&) noexcept;
13530
+ template<simd-complex V>
13531
+ constexpr rebind_t<simd-complex-value-type<V>, V> imag(const V&) noexcept;
13532
+
13533
+ template<simd-complex V>
13534
+ constexpr rebind_t<simd-complex-value-type<V>, V> abs(const V&);
13535
+ template<simd-complex V>
13536
+ constexpr rebind_t<simd-complex-value-type<V>, V> arg(const V&);
13537
+ template<simd-complex V>
13538
+ constexpr rebind_t<simd-complex-value-type<V>, V> norm(const V&);
13539
+ template<simd-complex V> constexpr V conj(const V&);
13540
+ template<simd-complex V> constexpr V proj(const V&);
13541
+
13542
+ template<simd-complex V> constexpr V exp(const V& v);
13543
+ template<simd-complex V> constexpr V log(const V& v);
13544
+ template<simd-complex V> constexpr V log10(const V& v);
13545
+
13546
+ template<simd-complex V> constexpr V sqrt(const V& v);
13547
+ template<simd-complex V> constexpr V sin(const V& v);
13548
+ template<simd-complex V> constexpr V asin(const V& v);
13549
+ template<simd-complex V> constexpr V cos(const V& v);
13550
+ template<simd-complex V> constexpr V acos(const V& v);
13551
+ template<simd-complex V> constexpr V tan(const V& v);
13552
+ template<simd-complex V> constexpr V atan(const V& v);
13553
+ template<simd-complex V> constexpr V sinh(const V& v);
13554
+ template<simd-complex V> constexpr V asinh(const V& v);
13555
+ template<simd-complex V> constexpr V cosh(const V& v);
13556
+ template<simd-complex V> constexpr V acosh(const V& v);
13557
+ template<simd-complex V> constexpr V tanh(const V& v);
13558
+ template<simd-complex V> constexpr V atanh(const V& v);
13559
+ ```
13560
+
13561
+ *Returns:* A `basic_vec` object `ret` where the iᵗʰ element is
13562
+ initialized to the result of *`cmplx-func`*`(v[`i`])` for all i in the
13563
+ range \[`0`, `V::size()`), where *`cmplx-func`* is the corresponding
13564
+ function from `<complex>`. If in an invocation of *`cmplx-func`* for
13565
+ index i a domain, pole, or range error would occur, the value of
13566
+ `ret[`i`]` is unspecified.
13567
+
13568
+ *Remarks:* It is unspecified whether `errno` [[errno]] is accessed.
13569
+
13570
+ ``` cpp
13571
+ template<simd-floating-point V>
13572
+ rebind_t<complex<typename V::value_type>, V> polar(const V& x, const V& y = {});
13573
+
13574
+ template<simd-complex V> constexpr V pow(const V& x, const V& y);
13575
+ ```
13576
+
13577
+ *Returns:* A `basic_vec` object `ret` where the iᵗʰ element is
13578
+ initialized to the result of *`cmplx-func`*`(x[`i`], y[`i`])` for all i
13579
+ in the range \[`0`, `V::size()`), where *`cmplx-func`* is the
13580
+ corresponding function from `<complex>`. If in an invocation of
13581
+ *`cmplx-func`* for index i a domain, pole, or range error would occur,
13582
+ the value of `ret[`i`]` is unspecified.
13583
+
13584
+ *Remarks:* It is unspecified whether `errno` [[errno]] is accessed.
13585
+
13586
+ ### Class template `basic_mask` <a id="simd.mask.class">[[simd.mask.class]]</a>
13587
+
13588
+ #### Overview <a id="simd.mask.overview">[[simd.mask.overview]]</a>
13589
+
13590
+ ``` cpp
13591
+ namespace std::simd {
13592
+ template<size_t Bytes, class Abi> class basic_mask {
13593
+ public:
13594
+ using value_type = bool;
13595
+ using abi_type = Abi;
13596
+ using iterator = simd-iterator<basic_mask>;
13597
+ using const_iterator = simd-iterator<const basic_mask>;
13598
+
13599
+ constexpr iterator begin() noexcept { return {*this, 0}; }
13600
+ constexpr const_iterator begin() const noexcept { return {*this, 0}; }
13601
+ constexpr const_iterator cbegin() const noexcept { return {*this, 0}; }
13602
+ constexpr default_sentinel_t end() const noexcept { return {}; }
13603
+ constexpr default_sentinel_t cend() const noexcept { return {}; }
13604
+
13605
+ static constexpr integral_constant<simd-size-type, simd-size-v<integer-from<Bytes>, Abi>>
13606
+ size {};
13607
+
13608
+ constexpr basic_mask() noexcept = default;
13609
+
13610
+ // [simd.mask.ctor], basic_mask constructors
13611
+ constexpr explicit basic_mask(value_type) noexcept;
13612
+ template<size_t UBytes, class UAbi>
13613
+ constexpr explicit basic_mask(const basic_mask<UBytes, UAbi>&) noexcept;
13614
+ template<class G>
13615
+ constexpr explicit basic_mask(G&& gen);
13616
+ constexpr basic_mask(const bitset<size()>& b) noexcept;
13617
+ constexpr explicit basic_mask(unsigned_integral auto val) noexcept;
13618
+
13619
+ // [simd.mask.subscr], basic_mask subscript operators
13620
+ constexpr value_type operator[](simd-size-type) const;
13621
+ template<simd-integral I>
13622
+ constexpr resize_t<I::size(), basic_mask> operator[](const I& indices) const;
13623
+
13624
+ // [simd.mask.unary], basic_mask unary operators
13625
+ constexpr basic_mask operator!() const noexcept;
13626
+ constexpr basic_vec<integer-from<Bytes>, Abi> operator+() const noexcept;
13627
+ constexpr basic_vec<integer-from<Bytes>, Abi> operator-() const noexcept;
13628
+ constexpr basic_vec<integer-from<Bytes>, Abi> operator~() const noexcept;
13629
+
13630
+ // [simd.mask.conv], basic_mask conversions
13631
+ template<class U, class A>
13632
+ constexpr explicit(sizeof(U) != Bytes) operator basic_vec<U, A>() const noexcept;
13633
+ constexpr bitset<size()> to_bitset() const noexcept;
13634
+ constexpr unsigned long long to_ullong() const;
13635
+
13636
+ // [simd.mask.binary], basic_mask binary operators
13637
+ friend constexpr basic_mask
13638
+ operator&&(const basic_mask&, const basic_mask&) noexcept;
13639
+ friend constexpr basic_mask
13640
+ operator||(const basic_mask&, const basic_mask&) noexcept;
13641
+ friend constexpr basic_mask
13642
+ operator&(const basic_mask&, const basic_mask&) noexcept;
13643
+ friend constexpr basic_mask
13644
+ operator|(const basic_mask&, const basic_mask&) noexcept;
13645
+ friend constexpr basic_mask
13646
+ operator^(const basic_mask&, const basic_mask&) noexcept;
13647
+
13648
+ // [simd.mask.cassign], basic_mask compound assignment
13649
+ friend constexpr basic_mask&
13650
+ operator&=(basic_mask&, const basic_mask&) noexcept;
13651
+ friend constexpr basic_mask&
13652
+ operator|=(basic_mask&, const basic_mask&) noexcept;
13653
+ friend constexpr basic_mask&
13654
+ operator^=(basic_mask&, const basic_mask&) noexcept;
13655
+
13656
+ // [simd.mask.comparison], basic_mask comparisons
13657
+ friend constexpr basic_mask
13658
+ operator==(const basic_mask&, const basic_mask&) noexcept;
13659
+ friend constexpr basic_mask
13660
+ operator!=(const basic_mask&, const basic_mask&) noexcept;
13661
+ friend constexpr basic_mask
13662
+ operator>=(const basic_mask&, const basic_mask&) noexcept;
13663
+ friend constexpr basic_mask
13664
+ operator<=(const basic_mask&, const basic_mask&) noexcept;
13665
+ friend constexpr basic_mask
13666
+ operator>(const basic_mask&, const basic_mask&) noexcept;
13667
+ friend constexpr basic_mask
13668
+ operator<(const basic_mask&, const basic_mask&) noexcept;
13669
+
13670
+ // [simd.mask.cond], basic_mask exposition only conditional operators
13671
+ friend constexpr basic_mask simd-select-impl( // exposition only
13672
+ const basic_mask&, const basic_mask&, const basic_mask&) noexcept;
13673
+ friend constexpr basic_mask simd-select-impl( // exposition only
13674
+ const basic_mask&, same_as<bool> auto, same_as<bool> auto) noexcept;
13675
+ template<class T0, class T1>
13676
+ friend constexpr vec<see below, size()>
13677
+ simd-select-impl(const basic_mask&, const T0&, const T1&) noexcept; // exposition only
13678
+ };
13679
+ }
13680
+ ```
13681
+
13682
+ Every specialization of `basic_mask` is a complete type. The
13683
+ specialization of `basic_mask<Bytes, Abi>` is:
13684
+
13685
+ - disabled, if there is no vectorizable type `T` such that `Bytes` is
13686
+ equal to `sizeof(T)`,
13687
+ - otherwise, enabled, if there exists a vectorizable type `T` and a
13688
+ value `N` in the range \[`1`, `64`\] such that `Bytes` is equal to
13689
+ `sizeof(T)` and `Abi` is `deduce-abi-t<T,
13690
+ N>`,
13691
+ - otherwise, it is *implementation-defined* if such a specialization is
13692
+ enabled.
13693
+
13694
+ If `basic_mask<Bytes, Abi>` is disabled, the specialization has a
13695
+ deleted default constructor, deleted destructor, deleted copy
13696
+ constructor, and deleted copy assignment. In addition only the
13697
+ `value_type` and `abi_type` members are present.
13698
+
13699
+ If `basic_mask<Bytes, Abi>` is enabled, `basic_mask<Bytes, Abi>` is
13700
+ trivially copyable.
13701
+
13702
+ *Recommended practice:* Implementations should support implicit
13703
+ conversions between specializations of `basic_mask` and appropriate
13704
+ *implementation-defined* types.
13705
+
13706
+ [*Note 1*: Appropriate types are non-standard vector types which are
13707
+ available in the implementation. — *end note*]
13708
+
13709
+ #### Constructors <a id="simd.mask.ctor">[[simd.mask.ctor]]</a>
13710
+
13711
+ ``` cpp
13712
+ constexpr explicit basic_mask(value_type x) noexcept;
13713
+ ```
13714
+
13715
+ *Effects:* Initializes each element with `x`.
13716
+
13717
+ ``` cpp
13718
+ template<size_t UBytes, class UAbi>
13719
+ constexpr explicit basic_mask(const basic_mask<UBytes, UAbi>& x) noexcept;
13720
+ ```
13721
+
13722
+ *Constraints:* `basic_mask<UBytes, UAbi>::size() == size()` is `true`.
13723
+
13724
+ *Effects:* Initializes the iᵗʰ element with `x[`i`]` for all i in the
13725
+ range of \[`0`, `size()`).
13726
+
13727
+ ``` cpp
13728
+ template<class G> constexpr explicit basic_mask(G&& gen);
13729
+ ```
13730
+
13731
+ *Constraints:* The expression
13732
+ `gen(integral_constant<`*`simd-size-type`*`, i>())` is well-formed and
13733
+ its type is `bool` for all i in the range of \[`0`, `size()`).
13734
+
13735
+ *Effects:* Initializes the iᵗʰ element with
13736
+ `gen(integral_constant<`*`simd-size-type`*`, i>())` for all i in the
13737
+ range of \[`0`, `size()`).
13738
+
13739
+ *Remarks:* `gen` is invoked exactly once for each i, in increasing order
13740
+ of i.
13741
+
13742
+ ``` cpp
13743
+ constexpr basic_mask(const bitset<size()>& b) noexcept;
13744
+ ```
13745
+
13746
+ *Effects:* Initializes the iᵗʰ element with `b[`i`]` for all i in the
13747
+ range \[`0`, `size()`).
13748
+
13749
+ ``` cpp
13750
+ constexpr explicit basic_mask(unsigned_integral auto val) noexcept;
13751
+ ```
13752
+
13753
+ *Effects:* Initializes the first M elements to the corresponding bit
13754
+ values in `val`, where M is the smaller of `size()` and the number of
13755
+ bits in the value representation [[basic.types.general]] of the type of
13756
+ `val`. If M is less than `size()`, the remaining elements are
13757
+ initialized to zero.
13758
+
13759
+ #### Subscript operator <a id="simd.mask.subscr">[[simd.mask.subscr]]</a>
13760
+
13761
+ ``` cpp
13762
+ constexpr value_type operator[](simd-size-type i) const;
13763
+ ```
13764
+
13765
+ *Preconditions:* `i >= 0 && i < size()` is `true`.
13766
+
13767
+ *Returns:* The value of the iᵗʰ element.
13768
+
13769
+ *Throws:* Nothing.
13770
+
13771
+ ``` cpp
13772
+ template<simd-integral I>
13773
+ constexpr resize_t<I::size(), basic_mask> operator[](const I& indices) const;
13774
+ ```
13775
+
13776
+ *Effects:* Equivalent to: `return permute(*this, indices);`
13777
+
13778
+ #### Unary operators <a id="simd.mask.unary">[[simd.mask.unary]]</a>
13779
+
13780
+ ``` cpp
13781
+ constexpr basic_mask operator!() const noexcept;
13782
+ constexpr basic_vec<integer-from<Bytes>, Abi> operator+() const noexcept;
13783
+ constexpr basic_vec<integer-from<Bytes>, Abi> operator-() const noexcept;
13784
+ constexpr basic_vec<integer-from<Bytes>, Abi> operator~() const noexcept;
13785
+ ```
13786
+
13787
+ Let *op* be the operator.
13788
+
13789
+ *Returns:* A data-parallel object where the iᵗʰ element is initialized
13790
+ to the results of applying *op* to `operator[](`i`)` for all i in the
13791
+ range of \[`0`, `size()`).
13792
+
13793
+ #### Conversions <a id="simd.mask.conv">[[simd.mask.conv]]</a>
13794
+
13795
+ ``` cpp
13796
+ template<class U, class A>
13797
+ constexpr explicit(sizeof(U) != Bytes) operator basic_vec<U, A>() const noexcept;
13798
+ ```
13799
+
13800
+ *Constraints:* *`simd-size-v`*`<U, A> == `*`simd-size-v`*`<T, Abi>`.
13801
+
13802
+ *Returns:* A data-parallel object where the iᵗʰ element is initialized
13803
+ to `static_cast<U>(operator[](`i`))`.
13804
+
13805
+ ``` cpp
13806
+ constexpr bitset<size()> to_bitset() const noexcept;
13807
+ ```
13808
+
13809
+ *Returns:* A `bitset<size()>` object where the iᵗʰ element is
13810
+ initialized to `operator[](`i`)` for all i in the range \[`0`,
13811
+ `size()`).
13812
+
13813
+ ``` cpp
13814
+ constexpr unsigned long long to_ullong() const;
13815
+ ```
13816
+
13817
+ Let N be the width of `unsigned long long`.
13818
+
13819
+ *Preconditions:*
13820
+
13821
+ - `size() <= `N is `true`, or
13822
+ - for all i in the range \[N, `size()`), `operator[](`i`)` returns
13823
+ `false`.
13824
+
13825
+ *Returns:* The integral value corresponding to the bits in `*this`.
13826
+
13827
+ *Throws:* Nothing.
13828
+
13829
+ ### `basic_mask` non-member operations <a id="simd.mask.nonmembers">[[simd.mask.nonmembers]]</a>
13830
+
13831
+ #### Binary operators <a id="simd.mask.binary">[[simd.mask.binary]]</a>
13832
+
13833
+ ``` cpp
13834
+ friend constexpr basic_mask
13835
+ operator&&(const basic_mask& lhs, const basic_mask& rhs) noexcept;
13836
+ friend constexpr basic_mask
13837
+ operator||(const basic_mask& lhs, const basic_mask& rhs) noexcept;
13838
+ friend constexpr basic_mask
13839
+ operator& (const basic_mask& lhs, const basic_mask& rhs) noexcept;
13840
+ friend constexpr basic_mask
13841
+ operator| (const basic_mask& lhs, const basic_mask& rhs) noexcept;
13842
+ friend constexpr basic_mask
13843
+ operator^ (const basic_mask& lhs, const basic_mask& rhs) noexcept;
13844
+ ```
13845
+
13846
+ Let *op* be the operator.
13847
+
13848
+ *Returns:* A `basic_mask` object initialized with the results of
13849
+ applying *op* to `lhs` and `rhs` as a binary element-wise operation.
13850
+
13851
+ #### Compound assignment <a id="simd.mask.cassign">[[simd.mask.cassign]]</a>
13852
+
13853
+ ``` cpp
13854
+ friend constexpr basic_mask&
13855
+ operator&=(basic_mask& lhs, const basic_mask& rhs) noexcept;
13856
+ friend constexpr basic_mask&
13857
+ operator|=(basic_mask& lhs, const basic_mask& rhs) noexcept;
13858
+ friend constexpr basic_mask&
13859
+ operator^=(basic_mask& lhs, const basic_mask& rhs) noexcept;
13860
+ ```
13861
+
13862
+ Let *op* be the operator.
13863
+
13864
+ *Effects:* These operators apply *op* to `lhs` and `rhs` as a binary
13865
+ element-wise operation.
13866
+
13867
+ *Returns:* `lhs`.
13868
+
13869
+ #### Comparisons <a id="simd.mask.comparison">[[simd.mask.comparison]]</a>
13870
+
13871
+ ``` cpp
13872
+ friend constexpr basic_mask
13873
+ operator==(const basic_mask& lhs, const basic_mask& rhs) noexcept;
13874
+ friend constexpr basic_mask
13875
+ operator!=(const basic_mask& lhs, const basic_mask& rhs) noexcept;
13876
+ friend constexpr basic_mask
13877
+ operator>=(const basic_mask& lhs, const basic_mask& rhs) noexcept;
13878
+ friend constexpr basic_mask
13879
+ operator<=(const basic_mask& lhs, const basic_mask& rhs) noexcept;
13880
+ friend constexpr basic_mask
13881
+ operator>(const basic_mask& lhs, const basic_mask& rhs) noexcept;
13882
+ friend constexpr basic_mask
13883
+ operator<(const basic_mask& lhs, const basic_mask& rhs) noexcept;
13884
+ ```
13885
+
13886
+ Let *op* be the operator.
13887
+
13888
+ *Returns:* A `basic_mask` object initialized with the results of
13889
+ applying *op* to `lhs` and `rhs` as a binary element-wise operation.
13890
+
13891
+ #### Exposition-only conditional operators <a id="simd.mask.cond">[[simd.mask.cond]]</a>
13892
+
13893
+ ``` cpp
13894
+ friend constexpr basic_mask simd-select-impl(
13895
+ const basic_mask& mask, const basic_mask& a, const basic_mask& b) noexcept;
13896
+ ```
13897
+
13898
+ *Returns:* A `basic_mask` object where the iᵗʰ element equals
13899
+ `mask[`i`] ? a[`i`] : b[`i`]` for all i in the range of \[`0`,
13900
+ `size()`).
13901
+
13902
+ ``` cpp
13903
+ friend constexpr basic_mask
13904
+ simd-select-impl(const basic_mask& mask, same_as<bool> auto a, same_as<bool> auto b) noexcept;
13905
+ ```
13906
+
13907
+ *Returns:* A `basic_mask` object where the iᵗʰ element equals
13908
+ `mask[`i`] ? a : b` for all i in the range of \[`0`, `size()`).
13909
+
13910
+ ``` cpp
13911
+ template<class T0, class T1>
13912
+ friend constexpr vec<see below, size()>
13913
+ simd-select-impl(const basic_mask& mask, const T0& a, const T1& b) noexcept;
13914
+ ```
13915
+
13916
+ *Constraints:*
13917
+
13918
+ - `same_as<T0, T1>` is `true`,
13919
+ - `T0` is a vectorizable type, and
13920
+ - `sizeof(T0) == Bytes`.
13921
+
13922
+ *Returns:* A `vec<T0, size()>` object where the iᵗʰ element equals
13923
+ `mask[`i`] ? a : b` for all i in the range of \[`0`, `size()`).
13924
+
13925
+ #### Reductions <a id="simd.mask.reductions">[[simd.mask.reductions]]</a>
13926
+
13927
+ ``` cpp
13928
+ template<size_t Bytes, class Abi>
13929
+ constexpr bool all_of(const basic_mask<Bytes, Abi>& k) noexcept;
13930
+ ```
13931
+
13932
+ *Returns:* `true` if all boolean elements in `k` are `true`, otherwise
13933
+ `false`.
13934
+
13935
+ ``` cpp
13936
+ template<size_t Bytes, class Abi>
13937
+ constexpr bool any_of(const basic_mask<Bytes, Abi>& k) noexcept;
13938
+ ```
13939
+
13940
+ *Returns:* `true` if at least one boolean element in `k` is `true`,
13941
+ otherwise `false`.
13942
+
13943
+ ``` cpp
13944
+ template<size_t Bytes, class Abi>
13945
+ constexpr bool none_of(const basic_mask<Bytes, Abi>& k) noexcept;
13946
+ ```
13947
+
13948
+ *Returns:* `!any_of(k)`.
13949
+
13950
+ ``` cpp
13951
+ template<size_t Bytes, class Abi>
13952
+ constexpr simd-size-type reduce_count(const basic_mask<Bytes, Abi>& k) noexcept;
13953
+ ```
13954
+
13955
+ *Returns:* The number of boolean elements in `k` that are `true`.
13956
+
13957
+ ``` cpp
13958
+ template<size_t Bytes, class Abi>
13959
+ constexpr simd-size-type reduce_min_index(const basic_mask<Bytes, Abi>& k);
13960
+ ```
13961
+
13962
+ *Preconditions:* `any_of(k)` is `true`.
13963
+
13964
+ *Returns:* The lowest element index i where `k[`i`]` is `true`.
13965
+
13966
+ ``` cpp
13967
+ template<size_t Bytes, class Abi>
13968
+ constexpr simd-size-type reduce_max_index(const basic_mask<Bytes, Abi>& k);
13969
+ ```
13970
+
13971
+ *Preconditions:* `any_of(k)` is `true`.
13972
+
13973
+ *Returns:* The greatest element index i where `k[`i`]` is `true`.
13974
+
13975
+ ``` cpp
13976
+ constexpr bool all_of(same_as<bool> auto x) noexcept;
13977
+ constexpr bool any_of(same_as<bool> auto x) noexcept;
13978
+ constexpr simd-size-type reduce_count(same_as<bool> auto x) noexcept;
13979
+ ```
13980
+
13981
+ *Returns:* `x`.
13982
+
13983
+ ``` cpp
13984
+ constexpr bool none_of(same_as<bool> auto x) noexcept;
13985
+ ```
13986
+
13987
+ *Returns:* `!x`.
13988
+
13989
+ ``` cpp
13990
+ constexpr simd-size-type reduce_min_index(same_as<bool> auto x);
13991
+ constexpr simd-size-type reduce_max_index(same_as<bool> auto x);
13992
+ ```
13993
+
13994
+ *Preconditions:* `x` is `true`.
13995
+
13996
+ *Returns:* `0`.
13997
+
13998
+ ## C compatibility <a id="numerics.c">[[numerics.c]]</a>
13999
+
14000
+ ### Header `<stdckdint.h>` synopsis <a id="stdckdint.h.syn">[[stdckdint.h.syn]]</a>
14001
+
14002
+ ``` cpp
14003
+ #define __STDC_VERSION_STDCKDINT_H__ 202311L
14004
+
14005
+ template<class type1, class type2, class type3>
14006
+ bool ckd_add(type1* result, type2 a, type3 b);
14007
+ template<class type1, class type2, class type3>
14008
+ bool ckd_sub(type1* result, type2 a, type3 b);
14009
+ template<class type1, class type2, class type3>
14010
+ bool ckd_mul(type1* result, type2 a, type3 b);
14011
+ ```
14012
+
14013
+ See also: ISO C 7.20
14014
+
14015
+ ### Checked integer operations <a id="numerics.c.ckdint">[[numerics.c.ckdint]]</a>
14016
+
14017
+ ``` cpp
14018
+ template<class type1, class type2, class type3>
14019
+ bool ckd_add(type1* result, type2 a, type3 b);
14020
+ template<class type1, class type2, class type3>
14021
+ bool ckd_sub(type1* result, type2 a, type3 b);
14022
+ template<class type1, class type2, class type3>
14023
+ bool ckd_mul(type1* result, type2 a, type3 b);
14024
+ ```
14025
+
14026
+ *Mandates:* Each of the types `type1`, `type2`, and `type3` is a
14027
+ cv-unqualified signed or unsigned integer type [[basic.fundamental]].
14028
+
14029
+ *Remarks:* Each function template has the same semantics as the
14030
+ corresponding type-generic macro with the same name specified in See
14031
+ also: ISO C 7.20.
14032
+
14033
  <!-- Link reference definitions -->
14034
+ [algorithms.parallel.defns]: algorithms.md#algorithms.parallel.defns
14035
  [bad.alloc]: support.md#bad.alloc
14036
+ [basic.extended.fp]: basic.md#basic.extended.fp
14037
  [basic.fundamental]: basic.md#basic.fundamental
14038
+ [basic.lookup.argdep]: basic.md#basic.lookup.argdep
14039
  [basic.stc.thread]: basic.md#basic.stc.thread
14040
+ [basic.types.general]: basic.md#basic.types.general
14041
  [c.math]: #c.math
14042
  [c.math.abs]: #c.math.abs
14043
  [c.math.fpclass]: #c.math.fpclass
14044
  [c.math.hypot3]: #c.math.hypot3
14045
  [c.math.lerp]: #c.math.lerp
 
14060
  [complex.numbers]: #complex.numbers
14061
  [complex.numbers.general]: #complex.numbers.general
14062
  [complex.ops]: #complex.ops
14063
  [complex.syn]: #complex.syn
14064
  [complex.transcendentals]: #complex.transcendentals
14065
+ [complex.tuple]: #complex.tuple
14066
  [complex.value.ops]: #complex.value.ops
14067
  [cons.slice]: #cons.slice
14068
+ [contents]: library.md#contents
14069
  [conv.prom]: expr.md#conv.prom
14070
+ [conv.rank]: basic.md#conv.rank
14071
  [cpp.pragma]: cpp.md#cpp.pragma
14072
  [cpp17.copyassignable]: #cpp17.copyassignable
14073
  [cpp17.copyconstructible]: #cpp17.copyconstructible
14074
  [cpp17.equalitycomparable]: #cpp17.equalitycomparable
14075
  [dcl.init]: dcl.md#dcl.init
14076
+ [dcl.init.general]: dcl.md#dcl.init.general
14077
+ [errno]: diagnostics.md#errno
14078
+ [execpol.type]: algorithms.md#execpol.type
14079
+ [expr.const]: expr.md#expr.const
14080
  [gslice.access]: #gslice.access
14081
  [gslice.array.assign]: #gslice.array.assign
14082
  [gslice.array.comp.assign]: #gslice.array.comp.assign
14083
  [gslice.array.fill]: #gslice.array.fill
14084
  [gslice.cons]: #gslice.cons
 
14091
  [iostate.flags]: input.md#iostate.flags
14092
  [istream.formatted]: input.md#istream.formatted
14093
  [iterator.concept.contiguous]: iterators.md#iterator.concept.contiguous
14094
  [iterator.requirements.general]: iterators.md#iterator.requirements.general
14095
  [library.c]: library.md#library.c
14096
+ [linalg]: #linalg
14097
+ [linalg.algs.blas1]: #linalg.algs.blas1
14098
+ [linalg.algs.blas1.add]: #linalg.algs.blas1.add
14099
+ [linalg.algs.blas1.asum]: #linalg.algs.blas1.asum
14100
+ [linalg.algs.blas1.complexity]: #linalg.algs.blas1.complexity
14101
+ [linalg.algs.blas1.copy]: #linalg.algs.blas1.copy
14102
+ [linalg.algs.blas1.dot]: #linalg.algs.blas1.dot
14103
+ [linalg.algs.blas1.givens]: #linalg.algs.blas1.givens
14104
+ [linalg.algs.blas1.givens.lartg]: #linalg.algs.blas1.givens.lartg
14105
+ [linalg.algs.blas1.givens.rot]: #linalg.algs.blas1.givens.rot
14106
+ [linalg.algs.blas1.iamax]: #linalg.algs.blas1.iamax
14107
+ [linalg.algs.blas1.matfrobnorm]: #linalg.algs.blas1.matfrobnorm
14108
+ [linalg.algs.blas1.matinfnorm]: #linalg.algs.blas1.matinfnorm
14109
+ [linalg.algs.blas1.matonenorm]: #linalg.algs.blas1.matonenorm
14110
+ [linalg.algs.blas1.nrm2]: #linalg.algs.blas1.nrm2
14111
+ [linalg.algs.blas1.scal]: #linalg.algs.blas1.scal
14112
+ [linalg.algs.blas1.ssq]: #linalg.algs.blas1.ssq
14113
+ [linalg.algs.blas1.swap]: #linalg.algs.blas1.swap
14114
+ [linalg.algs.blas2]: #linalg.algs.blas2
14115
+ [linalg.algs.blas2.gemv]: #linalg.algs.blas2.gemv
14116
+ [linalg.algs.blas2.hemv]: #linalg.algs.blas2.hemv
14117
+ [linalg.algs.blas2.rank1]: #linalg.algs.blas2.rank1
14118
+ [linalg.algs.blas2.rank2]: #linalg.algs.blas2.rank2
14119
+ [linalg.algs.blas2.symherrank1]: #linalg.algs.blas2.symherrank1
14120
+ [linalg.algs.blas2.symv]: #linalg.algs.blas2.symv
14121
+ [linalg.algs.blas2.trmv]: #linalg.algs.blas2.trmv
14122
+ [linalg.algs.blas2.trsv]: #linalg.algs.blas2.trsv
14123
+ [linalg.algs.blas3]: #linalg.algs.blas3
14124
+ [linalg.algs.blas3.gemm]: #linalg.algs.blas3.gemm
14125
+ [linalg.algs.blas3.inplacetrsm]: #linalg.algs.blas3.inplacetrsm
14126
+ [linalg.algs.blas3.rank2k]: #linalg.algs.blas3.rank2k
14127
+ [linalg.algs.blas3.rankk]: #linalg.algs.blas3.rankk
14128
+ [linalg.algs.blas3.trmm]: #linalg.algs.blas3.trmm
14129
+ [linalg.algs.blas3.trsm]: #linalg.algs.blas3.trsm
14130
+ [linalg.algs.blas3.xxmm]: #linalg.algs.blas3.xxmm
14131
+ [linalg.algs.reqs]: #linalg.algs.reqs
14132
+ [linalg.conj]: #linalg.conj
14133
+ [linalg.conj.conjugated]: #linalg.conj.conjugated
14134
+ [linalg.conj.conjugatedaccessor]: #linalg.conj.conjugatedaccessor
14135
+ [linalg.conj.intro]: #linalg.conj.intro
14136
+ [linalg.conjtransposed]: #linalg.conjtransposed
14137
+ [linalg.general]: #linalg.general
14138
+ [linalg.helpers]: #linalg.helpers
14139
+ [linalg.helpers.abs]: #linalg.helpers.abs
14140
+ [linalg.helpers.concepts]: #linalg.helpers.concepts
14141
+ [linalg.helpers.conj]: #linalg.helpers.conj
14142
+ [linalg.helpers.imag]: #linalg.helpers.imag
14143
+ [linalg.helpers.mandates]: #linalg.helpers.mandates
14144
+ [linalg.helpers.precond]: #linalg.helpers.precond
14145
+ [linalg.helpers.real]: #linalg.helpers.real
14146
+ [linalg.layout.packed]: #linalg.layout.packed
14147
+ [linalg.layout.packed.cons]: #linalg.layout.packed.cons
14148
+ [linalg.layout.packed.obs]: #linalg.layout.packed.obs
14149
+ [linalg.layout.packed.overview]: #linalg.layout.packed.overview
14150
+ [linalg.overview]: #linalg.overview
14151
+ [linalg.reqs]: #linalg.reqs
14152
+ [linalg.reqs.alg]: #linalg.reqs.alg
14153
+ [linalg.reqs.val]: #linalg.reqs.val
14154
+ [linalg.scaled]: #linalg.scaled
14155
+ [linalg.scaled.intro]: #linalg.scaled.intro
14156
+ [linalg.scaled.scaled]: #linalg.scaled.scaled
14157
+ [linalg.scaled.scaledaccessor]: #linalg.scaled.scaledaccessor
14158
+ [linalg.syn]: #linalg.syn
14159
+ [linalg.tags]: #linalg.tags
14160
+ [linalg.tags.diagonal]: #linalg.tags.diagonal
14161
+ [linalg.tags.order]: #linalg.tags.order
14162
+ [linalg.tags.triangle]: #linalg.tags.triangle
14163
+ [linalg.transp]: #linalg.transp
14164
+ [linalg.transp.helpers]: #linalg.transp.helpers
14165
+ [linalg.transp.intro]: #linalg.transp.intro
14166
+ [linalg.transp.layout.transpose]: #linalg.transp.layout.transpose
14167
+ [linalg.transp.transposed]: #linalg.transp.transposed
14168
  [mask.array.assign]: #mask.array.assign
14169
  [mask.array.comp.assign]: #mask.array.comp.assign
14170
  [mask.array.fill]: #mask.array.fill
14171
  [math.constants]: #math.constants
14172
+ [mdspan.accessor.reqmts]: containers.md#mdspan.accessor.reqmts
14173
+ [mdspan.layout.policy.reqmts]: containers.md#mdspan.layout.policy.reqmts
14174
+ [mdspan.overview]: containers.md#mdspan.overview
14175
  [namespace.std]: library.md#namespace.std
14176
  [numarray]: #numarray
14177
  [numbers]: #numbers
14178
  [numbers.syn]: #numbers.syn
14179
  [numeric.requirements]: #numeric.requirements
14180
  [numerics]: #numerics
14181
+ [numerics.c]: #numerics.c
14182
+ [numerics.c.ckdint]: #numerics.c.ckdint
14183
+ [numerics.defns]: algorithms.md#numerics.defns
14184
  [numerics.general]: #numerics.general
14185
  [numerics.summary]: #numerics.summary
14186
  [output.iterators]: iterators.md#output.iterators
14187
  [over.match.general]: over.md#over.match.general
14188
  [rand]: #rand
 
14221
  [rand.dist.uni.real]: #rand.dist.uni.real
14222
  [rand.eng]: #rand.eng
14223
  [rand.eng.general]: #rand.eng.general
14224
  [rand.eng.lcong]: #rand.eng.lcong
14225
  [rand.eng.mers]: #rand.eng.mers
14226
+ [rand.eng.philox]: #rand.eng.philox
14227
+ [rand.eng.philox.f]: #rand.eng.philox.f
14228
  [rand.eng.sub]: #rand.eng.sub
14229
  [rand.general]: #rand.general
14230
  [rand.predef]: #rand.predef
14231
  [rand.req]: #rand.req
14232
  [rand.req.adapt]: #rand.req.adapt
 
14262
  [sf.cmath.legendre]: #sf.cmath.legendre
14263
  [sf.cmath.riemann.zeta]: #sf.cmath.riemann.zeta
14264
  [sf.cmath.sph.bessel]: #sf.cmath.sph.bessel
14265
  [sf.cmath.sph.legendre]: #sf.cmath.sph.legendre
14266
  [sf.cmath.sph.neumann]: #sf.cmath.sph.neumann
14267
+ [simd]: #simd
14268
+ [simd.alg]: #simd.alg
14269
+ [simd.binary]: #simd.binary
14270
+ [simd.bit]: #simd.bit
14271
+ [simd.cassign]: #simd.cassign
14272
+ [simd.class]: #simd.class
14273
+ [simd.comparison]: #simd.comparison
14274
+ [simd.complex.access]: #simd.complex.access
14275
+ [simd.complex.math]: #simd.complex.math
14276
+ [simd.cond]: #simd.cond
14277
+ [simd.creation]: #simd.creation
14278
+ [simd.ctor]: #simd.ctor
14279
+ [simd.expos]: #simd.expos
14280
+ [simd.expos.abi]: #simd.expos.abi
14281
+ [simd.expos.defn]: #simd.expos.defn
14282
+ [simd.flags]: #simd.flags
14283
+ [simd.flags.oper]: #simd.flags.oper
14284
+ [simd.flags.overview]: #simd.flags.overview
14285
+ [simd.general]: #simd.general
14286
+ [simd.iterator]: #simd.iterator
14287
+ [simd.loadstore]: #simd.loadstore
14288
+ [simd.mask.binary]: #simd.mask.binary
14289
+ [simd.mask.cassign]: #simd.mask.cassign
14290
+ [simd.mask.class]: #simd.mask.class
14291
+ [simd.mask.comparison]: #simd.mask.comparison
14292
+ [simd.mask.cond]: #simd.mask.cond
14293
+ [simd.mask.conv]: #simd.mask.conv
14294
+ [simd.mask.ctor]: #simd.mask.ctor
14295
+ [simd.mask.nonmembers]: #simd.mask.nonmembers
14296
+ [simd.mask.overview]: #simd.mask.overview
14297
+ [simd.mask.reductions]: #simd.mask.reductions
14298
+ [simd.mask.subscr]: #simd.mask.subscr
14299
+ [simd.mask.unary]: #simd.mask.unary
14300
+ [simd.math]: #simd.math
14301
+ [simd.nonmembers]: #simd.nonmembers
14302
+ [simd.overview]: #simd.overview
14303
+ [simd.permute.dynamic]: #simd.permute.dynamic
14304
+ [simd.permute.mask]: #simd.permute.mask
14305
+ [simd.permute.memory]: #simd.permute.memory
14306
+ [simd.permute.static]: #simd.permute.static
14307
+ [simd.reductions]: #simd.reductions
14308
+ [simd.subscr]: #simd.subscr
14309
+ [simd.syn]: #simd.syn
14310
+ [simd.traits]: #simd.traits
14311
+ [simd.unary]: #simd.unary
14312
  [slice.access]: #slice.access
14313
  [slice.arr.assign]: #slice.arr.assign
14314
  [slice.arr.comp.assign]: #slice.arr.comp.assign
14315
  [slice.arr.fill]: #slice.arr.fill
14316
  [slice.ops]: #slice.ops
14317
+ [stdckdint.h.syn]: #stdckdint.h.syn
14318
  [strings]: strings.md#strings
14319
  [template.gslice.array]: #template.gslice.array
14320
  [template.gslice.array.overview]: #template.gslice.array.overview
14321
  [template.indirect.array]: #template.indirect.array
14322
  [template.indirect.array.overview]: #template.indirect.array.overview
 
14342
  [valarray.special]: #valarray.special
14343
  [valarray.sub]: #valarray.sub
14344
  [valarray.syn]: #valarray.syn
14345
  [valarray.transcend]: #valarray.transcend
14346
  [valarray.unary]: #valarray.unary
14347
+ [views.multidim]: containers.md#views.multidim
14348
 
14349
  [^1]: In other words, value types. These include arithmetic types,
14350
  pointers, the library class `complex`, and instantiations of
14351
  `valarray` for value types.
14352
 
 
14363
 
14364
  [^5]: If a device has n states whose respective probabilities are
14365
  P₀, …, Pₙ₋₁, the device entropy S is defined as
14366
  $S = - \sum_{i=0}^{n-1} P_i \cdot \log P_i$.
14367
 
14368
+ [^6]: d is introduced to avoid any attempt to produce more bits of
14369
  randomness than can be held in `RealType`.
14370
 
14371
  [^7]: The distribution corresponding to this probability density
14372
  function is also known (with a possible change of variable) as the
14373
  Gumbel Type I, the log-Weibull, or the Fisher-Tippett Type I