[linalg.algs.blas1]

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

## 29.9 Basic linear algebra algorithms [[linalg]](linalg#algs.blas1)

### 29.9.13 BLAS 1 algorithms [linalg.algs.blas1]

#### [29.9.13.1](#complexity) Complexity [[linalg.algs.blas1.complexity]](linalg.algs.blas1.complexity)

[1](#complexity-1)

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

*Complexity*: All algorithms in [linalg.algs.blas1] with mdspan parameters
perform a count of mdspan array accesses
and arithmetic operations that is linear in
the maximum product of extents of any mdspan parameter[.](#complexity-1.sentence-1)

#### [29.9.13.2](#givens) Givens rotations [[linalg.algs.blas1.givens]](linalg.algs.blas1.givens)

#### [29.9.13.2.1](#givens.lartg) Compute Givens rotation [[linalg.algs.blas1.givens.lartg]](linalg.algs.blas1.givens.lartg)

[ð](#lib:setup_givens_rotation)

`template<class Real>
  setup_givens_rotation_result<Real> setup_givens_rotation(Real a, Real b) noexcept;

template<class Real>
  setup_givens_rotation_result<complex<Real>>
    setup_givens_rotation(complex<Real> a, complex<Real> b) noexcept;
`

[1](#givens.lartg-1)

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

These functions compute the Givens plane rotation
represented by the two values c and s such that the 2 x 2 system of equations  
[csâÂ¯Â¯Â¯sc]â[ab]=[r0]

holds, where c is always a real scalar, and c2+|s|2=1[.](#givens.lartg-1.sentence-2)

That is, c and s represent a 2 x 2 matrix,
that when multiplied by the right by the input vector
whose components are a and b,
produces a result vector
whose first component r is the Euclidean norm of the input vector, and
whose second component is zero[.](#givens.lartg-1.sentence-3)

[*Note [1](#givens.lartg-note-1)*:

These functions correspond to the LAPACK function xLARTG[[bib]](bibliography#bib:lapack "Bibliography")[.](#givens.lartg-1.sentence-4)

â *end note*]

[2](#givens.lartg-2)

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

*Returns*: c, s, r,
where c and s form the Givens plane rotation
corresponding to the input a and b,
and r is the Euclidean norm of the two-component vector
formed by a and b[.](#givens.lartg-2.sentence-1)

#### [29.9.13.2.2](#givens.rot) Apply a computed Givens rotation to vectors [[linalg.algs.blas1.givens.rot]](linalg.algs.blas1.givens.rot)

[ð](#lib:apply_givens_rotation)

`template<[inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutVec1, [inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutVec2, class Real>
  void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, Real s);
template<class ExecutionPolicy, [inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutVec1, [inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutVec2, class Real>
  void apply_givens_rotation(ExecutionPolicy&& exec,
                             InOutVec1 x, InOutVec2 y, Real c, Real s);
template<[inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutVec1, [inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutVec2, class Real>
  void apply_givens_rotation(InOutVec1 x, InOutVec2 y, Real c, complex<Real> s);
template<class ExecutionPolicy, [inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutVec1, [inout-vector](linalg.helpers.concepts#concept:inout-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutVec2, class Real>
  void apply_givens_rotation(ExecutionPolicy&& exec,
                             InOutVec1 x, InOutVec2 y, Real c, complex<Real> s);
`

[1](#givens.rot-1)

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

[*Note [1](#givens.rot-note-1)*:

These functions correspond to the BLAS function xROT[[bib]](bibliography#bib:blas1 "Bibliography")[.](#givens.rot-1.sentence-1)

â *end note*]

[2](#givens.rot-2)

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

*Mandates*: *compatible-static-extents*<InOutVec1, InOutVec2>(0, 0) is true[.](#givens.rot-2.sentence-1)

[3](#givens.rot-3)

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

*Preconditions*: x.extent(0) equals y.extent(0)[.](#givens.rot-3.sentence-1)

[4](#givens.rot-4)

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

*Effects*: Applies the plane rotation
specified by c and s to
the input vectors x and y,
as if the rotation were a 2 x 2 matrix and
the input vectors were successive rows of a matrix with two rows[.](#givens.rot-4.sentence-1)

#### [29.9.13.3](#swap) Swap matrix or vector elements [[linalg.algs.blas1.swap]](linalg.algs.blas1.swap)

[ð](#lib:swap_elements)

`template<[inout-object](linalg.helpers.concepts#concept:inout-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutObj1, [inout-object](linalg.helpers.concepts#concept:inout-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutObj2>
  void swap_elements(InOutObj1 x, InOutObj2 y);
template<class ExecutionPolicy, [inout-object](linalg.helpers.concepts#concept:inout-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutObj1, [inout-object](linalg.helpers.concepts#concept:inout-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutObj2>
  void swap_elements(ExecutionPolicy&& exec, InOutObj1 x, InOutObj2 y);
`

[1](#swap-1)

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

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

These functions correspond to the BLAS function xSWAP[[bib]](bibliography#bib:blas1 "Bibliography")[.](#swap-1.sentence-1)

â *end note*]

[2](#swap-2)

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

*Constraints*: x.rank() equals y.rank()[.](#swap-2.sentence-1)

[3](#swap-3)

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

*Mandates*: For all r in the range [0, x.rank()),*compatible-static-extents*<InOutObj1, InOutObj2>(r, r) is true[.](#swap-3.sentence-1)

[4](#swap-4)

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

*Preconditions*: x.extents() equals y.extents()[.](#swap-4.sentence-1)

[5](#swap-5)

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

*Effects*: Swaps all corresponding elements of x and y[.](#swap-5.sentence-1)

#### [29.9.13.4](#scal) Multiply the elements of an object in place by a scalar [[linalg.algs.blas1.scal]](linalg.algs.blas1.scal)

[ð](#lib:scale)

`template<class Scalar, [inout-object](linalg.helpers.concepts#concept:inout-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutObj>
  void scale(Scalar alpha, InOutObj x);
template<class ExecutionPolicy, class Scalar, [inout-object](linalg.helpers.concepts#concept:inout-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InOutObj>
  void scale(ExecutionPolicy&& exec, Scalar alpha, InOutObj x);
`

[1](#scal-1)

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

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

These functions correspond to the BLAS function xSCAL[[bib]](bibliography#bib:blas1 "Bibliography")[.](#scal-1.sentence-1)

â *end note*]

[2](#scal-2)

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

*Effects*: Overwrites x with the result of
computing the elementwise multiplication Î±x,
where the scalar Î± is alpha[.](#scal-2.sentence-1)

#### [29.9.13.5](#copy) Copy elements of one matrix or vector into another [[linalg.algs.blas1.copy]](linalg.algs.blas1.copy)

[ð](#lib:copy)

`template<[in-object](linalg.helpers.concepts#concept:in-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InObj, [out-object](linalg.helpers.concepts#concept:out-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutObj>
  void copy(InObj x, OutObj y);
template<class ExecutionPolicy, [in-object](linalg.helpers.concepts#concept:in-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InObj, [out-object](linalg.helpers.concepts#concept:out-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutObj>
  void copy(ExecutionPolicy&& exec, InObj x, OutObj y);
`

[1](#copy-1)

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

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

These functions correspond to the BLAS function xCOPY[[bib]](bibliography#bib:blas1 "Bibliography")[.](#copy-1.sentence-1)

â *end note*]

[2](#copy-2)

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

*Constraints*: x.rank() equals y.rank()[.](#copy-2.sentence-1)

[3](#copy-3)

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

*Mandates*: For all r in the range [0,x.rank()),*compatible-static-extents*<InObj, OutObj>(r, r) is true[.](#copy-3.sentence-1)

[4](#copy-4)

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

*Preconditions*: x.extents() equals y.extents()[.](#copy-4.sentence-1)

[5](#copy-5)

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

*Effects*: Assigns each element of x to the corresponding element of y[.](#copy-5.sentence-1)

#### [29.9.13.6](#add) Add vectors or matrices elementwise [[linalg.algs.blas1.add]](linalg.algs.blas1.add)

[ð](#lib:add)

`template<[in-object](linalg.helpers.concepts#concept:in-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InObj1, [in-object](linalg.helpers.concepts#concept:in-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InObj2, [out-object](linalg.helpers.concepts#concept:out-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutObj>
  void add(InObj1 x, InObj2 y, OutObj z);
template<class ExecutionPolicy, [in-object](linalg.helpers.concepts#concept:in-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InObj1, [in-object](linalg.helpers.concepts#concept:in-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InObj2, [out-object](linalg.helpers.concepts#concept:out-object "29.9.7.5 Argument concepts [linalg.helpers.concepts]") OutObj>
  void add(ExecutionPolicy&& exec,
           InObj1 x, InObj2 y, OutObj z);
`

[1](#add-1)

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

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

These functions correspond to the BLAS function xAXPY[[bib]](bibliography#bib:blas1 "Bibliography")[.](#add-1.sentence-1)

â *end note*]

[2](#add-2)

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

*Constraints*: x.rank(), y.rank(), and z.rank() are all equal[.](#add-2.sentence-1)

[3](#add-3)

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

*Mandates*: *possibly-addable*<InObj1, InObj2, OutObj>() is true[.](#add-3.sentence-1)

[4](#add-4)

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

*Preconditions*: *addable*(x,y,z) is true[.](#add-4.sentence-1)

[5](#add-5)

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

*Effects*: Computes z=x+y[.](#add-5.sentence-1)

[6](#add-6)

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

*Remarks*: z may alias x or y[.](#add-6.sentence-1)

#### [29.9.13.7](#dot) Dot product of two vectors [[linalg.algs.blas1.dot]](linalg.algs.blas1.dot)

[1](#dot-1)

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

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

The functions in this section correspond to the BLAS
functions xDOT, xDOTU, and xDOTC[[bib]](bibliography#bib:blas1 "Bibliography")[.](#dot-1.sentence-1)

â *end note*]

[2](#dot-2)

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

The following elements apply to all functions in [[linalg.algs.blas1.dot]](#dot "29.9.13.7 Dot product of two vectors")[.](#dot-2.sentence-1)

[3](#dot-3)

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

*Mandates*: *compatible-static-extents*<InVec1, InVec2>(0, 0) is true[.](#dot-3.sentence-1)

[4](#dot-4)

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

*Preconditions*: v1.extent(0) equals v2.extent(0)[.](#dot-4.sentence-1)

[ð](#lib:dot)

`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2, class Scalar>
  Scalar dot(InVec1 v1, InVec2 v2, Scalar init);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2, class Scalar>
  Scalar dot(ExecutionPolicy&& exec,
             InVec1 v1, InVec2 v2, Scalar init);
`

[5](#dot-5)

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

These functions compute a non-conjugated dot product
with an explicitly specified result type[.](#dot-5.sentence-1)

[6](#dot-6)

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

*Returns*: Let N be v1.extent(0)[.](#dot-6.sentence-1)

- [(6.1)](#dot-6.1)

init if N is zero;

- [(6.2)](#dot-6.2)

otherwise,*GENERALIZED_SUM*(plus<>(), init, v1[0]*v2[0], …, v1[N-1]*v2[N-1]).

[7](#dot-7)

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

*Remarks*: If InVec1​::​value_type, InVec2​::​value_type, and Scalar are all floating-point types or specializations of complex,
and if Scalar has higher precision
than InVec1​::​value_type or InVec2​::​value_type,
then intermediate terms in the sum use Scalar's precision or greater[.](#dot-7.sentence-1)

[ð](#lib:dot_)

`  template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2>
    auto dot(InVec1 v1, InVec2 v2);
  template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2>
    auto dot(ExecutionPolicy&& exec,
             InVec1 v1, InVec2 v2);
`

[8](#dot-8)

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

These functions compute a non-conjugated dot product with a default result type[.](#dot-8.sentence-1)

[9](#dot-9)

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

*Effects*: Let T bedecltype(declval<typename InVec1​::​value_type>() * declval<typename InVec2​::​value_type>())[.](#dot-9.sentence-1)

Then,

- [(9.1)](#dot-9.1)

the two-parameter overload is equivalent to:return dot(v1, v2, T{}); and

- [(9.2)](#dot-9.2)

the three-parameter overload is equivalent to:return dot(std::forward<ExecutionPolicy>(exec), v1, v2, T{});

[ð](#lib:dotc)

`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2, class Scalar>
  Scalar dotc(InVec1 v1, InVec2 v2, Scalar init);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2, class Scalar>
  Scalar dotc(ExecutionPolicy&& exec,
              InVec1 v1, InVec2 v2, Scalar init);
`

[10](#dot-10)

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

These functions compute a conjugated dot product
with an explicitly specified result type[.](#dot-10.sentence-1)

[11](#dot-11)

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

*Effects*: 

- [(11.1)](#dot-11.1)

The three-parameter overload is equivalent to:return dot(conjugated(v1), v2, init); and

- [(11.2)](#dot-11.2)

the four-parameter overload is equivalent to:return dot(std::forward<ExecutionPolicy>(exec), conjugated(v1), v2, init);

[ð](#lib:dotc_)

`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2>
  auto dotc(InVec1 v1, InVec2 v2);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec1, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec2>
  auto dotc(ExecutionPolicy&& exec,
            InVec1 v1, InVec2 v2);
`

[12](#dot-12)

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

These functions compute a conjugated dot product with a default result type[.](#dot-12.sentence-1)

[13](#dot-13)

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

*Effects*: Let T be decltype(*conj-if-needed*(declval<typename InVec1​::​value_type>()) * declval<typename InVec2​::​value_type>())[.](#dot-13.sentence-1)

Then,

- [(13.1)](#dot-13.1)

the two-parameter overload is equivalent to:return dotc(v1, v2, T{}); and

- [(13.2)](#dot-13.2)

the three-parameter overload is equivalent toreturn dotc(std::forward<ExecutionPolicy>(exec), v1, v2, T{});

#### [29.9.13.8](#ssq) Scaled sum of squares of a vector's elements [[linalg.algs.blas1.ssq]](linalg.algs.blas1.ssq)

[ð](#lib:vector_sum_of_squares)

`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec, class Scalar>
  sum_of_squares_result<Scalar> vector_sum_of_squares(InVec v, sum_of_squares_result<Scalar> init);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec, class Scalar>
  sum_of_squares_result<Scalar> vector_sum_of_squares(ExecutionPolicy&& exec,
                                                      InVec v, sum_of_squares_result<Scalar> init);
`

[1](#ssq-1)

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

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

These functions correspond to the LAPACK function xLASSQ[[bib]](bibliography#bib:lapack "Bibliography")[.](#ssq-1.sentence-1)

â *end note*]

[2](#ssq-2)

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

*Mandates*: decltype(*abs-if-needed*(declval<typename InVec​::​value_type>())) is convertible to Scalar[.](#ssq-2.sentence-1)

[3](#ssq-3)

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

*Effects*: Returns a value result such that

- [(3.1)](#ssq-3.1)

result.scaling_factor is the maximum of init.scaling_factor and*abs-if-needed*(x[i]) for all i in the domain of v; and

- [(3.2)](#ssq-3.2)

let s2init beinit.scaling_factor * init.scaling_factor * init.scaled_sum_of_squares then result.scaling_factor * result.scaling_factor * result.scaled_sum_of_squares equals the sum of s2init and
the squares of *abs-if-needed*(x[i]) for all i in the domain of v[.](#ssq-3.sentence-1)

[4](#ssq-4)

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

*Remarks*: If InVec​::​value_type, and Scalar are all floating-point types or specializations of complex,
and if Scalar has higher precision
than InVec​::​value_type,
then intermediate terms in the sum use Scalar's precision or greater[.](#ssq-4.sentence-1)

#### [29.9.13.9](#nrm2) Euclidean norm of a vector [[linalg.algs.blas1.nrm2]](linalg.algs.blas1.nrm2)

[ð](#lib:vector_two_norm)

`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec, class Scalar>
  Scalar vector_two_norm(InVec v, Scalar init);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec, class Scalar>
  Scalar vector_two_norm(ExecutionPolicy&& exec, InVec v, Scalar init);
`

[1](#nrm2-1)

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

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

These functions correspond to the BLAS function xNRM2[[bib]](bibliography#bib:blas1 "Bibliography")[.](#nrm2-1.sentence-1)

â *end note*]

[2](#nrm2-2)

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

*Mandates*: Let a be*abs-if-needed*(declval<typename InVec​::​value_type>())[.](#nrm2-2.sentence-1)

Then, decltype(init + a * a is convertible to Scalar[.](#nrm2-2.sentence-2)

[3](#nrm2-3)

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

*Returns*: The square root of the sum of the square of init and the squares of the absolute values of the elements of v[.](#nrm2-3.sentence-1)

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

For init equal to zero, this is the Euclidean norm
(also called 2-norm) of the vector v[.](#nrm2-3.sentence-2)

â *end note*]

[4](#nrm2-4)

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

*Remarks*: If InVec​::​value_type, and Scalar are all floating-point types or specializations of complex,
and if Scalar has higher precision
than InVec​::​value_type,
then intermediate terms in the sum use Scalar's precision or greater[.](#nrm2-4.sentence-1)

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

An implementation of this function for floating-point types T can use the scaled_sum_of_squares result fromvector_sum_of_squares(x, {.scaling_factor=1.0, .scaled_sum_of_squares=init})[.](#nrm2-4.sentence-2)

â *end note*]

[ð](#lib:vector_two_norm_)

`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec>
  auto vector_two_norm(InVec v);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec>
  auto vector_two_norm(ExecutionPolicy&& exec, InVec v);
`

[5](#nrm2-5)

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

*Effects*: Let a be*abs-if-needed*(declval<typename InVec​::​value_type>())[.](#nrm2-5.sentence-1)

Let T be decltype(a * a)[.](#nrm2-5.sentence-2)

Then,

- [(5.1)](#nrm2-5.1)

the one-parameter overload is equivalent to:return vector_two_norm(v, T{}); and

- [(5.2)](#nrm2-5.2)

the two-parameter overload is equivalent to:return vector_two_norm(std::forward<ExecutionPolicy>(exec), v, T{});

#### [29.9.13.10](#asum) Sum of absolute values of vector elements [[linalg.algs.blas1.asum]](linalg.algs.blas1.asum)

[ð](#lib:vector_abs_sum)

`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec, class Scalar>
  Scalar vector_abs_sum(InVec v, Scalar init);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec, class Scalar>
  Scalar vector_abs_sum(ExecutionPolicy&& exec, InVec v, Scalar init);
`

[1](#asum-1)

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

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

These functions correspond to the BLAS functionsSASUM, DASUM, SCASUM, and DZASUM[[bib]](bibliography#bib:blas1 "Bibliography")[.](#asum-1.sentence-1)

â *end note*]

[2](#asum-2)

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

*Mandates*: decltype(init + *abs-if-needed*(*real-if-needed*(declval<typename InVec::value_type>())) +*abs-if-needed*(*imag-if-needed*(declval<typename InVec::value_type>()))) is convertible to Scalar[.](#asum-2.sentence-1)

[3](#asum-3)

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

*Returns*: Let N be v.extent(0)[.](#asum-3.sentence-1)

- [(3.1)](#asum-3.1)

init if N is zero;

- [(3.2)](#asum-3.2)

otherwise, if InVec​::​value_type is an arithmetic type,*GENERALIZED_SUM*(plus<>(), init, *abs-if-needed*(v[0]), …, *abs-if-needed*(v[N-1]))

- [(3.3)](#asum-3.3)

otherwise,*GENERALIZED_SUM*(plus<>(), init, *abs-if-needed*(*real-if-needed*(v[0])) + *abs-if-needed*(*imag-if-needed*(v[0])),
 …, *abs-if-needed*(*real-if-needed*(v[N-1])) + *abs-if-needed*(*imag-if-needed*(v[N-1])))

[4](#asum-4)

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

*Remarks*: If InVec​::​value_type and Scalar are all floating-point types or specializations of complex,
and if Scalar has higher precision
than InVec​::​value_type,
then intermediate terms in the sum use Scalar's precision or greater[.](#asum-4.sentence-1)

[ð](#lib:vector_abs_sum_)

`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec>
  auto vector_abs_sum(InVec v);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec>
  auto vector_abs_sum(ExecutionPolicy&& exec, InVec v);
`

[5](#asum-5)

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

*Effects*: Let T be typename InVec​::​value_type[.](#asum-5.sentence-1)

Then,

- [(5.1)](#asum-5.1)

the one-parameter overload is equivalent to:return vector_abs_sum(v, T{}); and

- [(5.2)](#asum-5.2)

the two-parameter overload is equivalent to:return vector_abs_sum(std::forward<ExecutionPolicy>(exec), v, T{});

#### [29.9.13.11](#iamax) Index of maximum absolute value of vector elements [[linalg.algs.blas1.iamax]](linalg.algs.blas1.iamax)

[ð](#lib:vector_idx_abs_max)

`template<[in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec>
  typename InVec::extents_type vector_idx_abs_max(InVec v);
template<class ExecutionPolicy, [in-vector](linalg.helpers.concepts#concept:in-vector "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InVec>
  typename InVec::extents_type vector_idx_abs_max(ExecutionPolicy&& exec, InVec v);
`

[1](#iamax-1)

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

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

These functions correspond to the BLAS function IxAMAX[[bib]](bibliography#bib:blas1 "Bibliography")[.](#iamax-1.sentence-1)

â *end note*]

[2](#iamax-2)

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

Let T bedecltype(*abs-if-needed*(*real-if-needed*(declval<typename InVec::value_type>())) +*abs-if-needed*(*imag-if-needed*(declval<typename InVec::value_type>())))

[3](#iamax-3)

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

*Mandates*: declval<T>() < declval<T>() is a valid expression[.](#iamax-3.sentence-1)

[4](#iamax-4)

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

*Returns*: 

- [(4.1)](#iamax-4.1)

numeric_limits<typename InVec​::​size_type>​::​max() if v has zero elements;

- [(4.2)](#iamax-4.2)

otherwise, the index of the first element of v having largest absolute value,
if InVec​::​value_type is an arithmetic type;

- [(4.3)](#iamax-4.3)

otherwise, the index of the first element ve of v for which*abs-if-needed*(*real-if-needed*(ve)) + *abs-if-needed*(*imag-if-needed*(ve)) has the largest value[.](#iamax-4.sentence-1)

#### [29.9.13.12](#matfrobnorm) Frobenius norm of a matrix [[linalg.algs.blas1.matfrobnorm]](linalg.algs.blas1.matfrobnorm)

[1](#matfrobnorm-1)

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

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

These functions exist in the BLAS standard[[bib]](bibliography#bib:blas-std "Bibliography") but are not part of the reference implementation[.](#matfrobnorm-1.sentence-1)

â *end note*]

[ð](#lib:matrix_frob_norm)

`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat, class Scalar>
  Scalar matrix_frob_norm(InMat A, Scalar init);
template<class ExecutionPolicy, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat, class Scalar>
  Scalar matrix_frob_norm(ExecutionPolicy&& exec, InMat A, Scalar init);
`

[2](#matfrobnorm-2)

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

*Mandates*: Let a be*abs-if-needed*(declval<typename InMat​::​value_type>())[.](#matfrobnorm-2.sentence-1)

Then, decltype(init + a * a) is convertible to Scalar[.](#matfrobnorm-2.sentence-2)

[3](#matfrobnorm-3)

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

*Returns*: The square root of the sum of squares
of init and the absolute values of the elements of A[.](#matfrobnorm-3.sentence-1)

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

For init equal to zero,
this is the Frobenius norm of the matrix A[.](#matfrobnorm-3.sentence-2)

â *end note*]

[4](#matfrobnorm-4)

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

*Remarks*: If InMat​::​value_type and Scalar are all floating-point types or specializations of complex,
and if Scalar has higher precision
than InMat​::​value_type,
then intermediate terms in the sum use Scalar's precision or greater[.](#matfrobnorm-4.sentence-1)

[ð](#lib:matrix_frob_norm_)

`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat>
  auto matrix_frob_norm(InMat A);
template<class ExecutionPolicy, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat>
  auto matrix_frob_norm(ExecutionPolicy&& exec, InMat A);
`

[5](#matfrobnorm-5)

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

*Effects*: Let a be*abs-if-needed*(declval<typename InMat​::​value_type>())[.](#matfrobnorm-5.sentence-1)

Let T bedecltype(a * a)[.](#matfrobnorm-5.sentence-2)

Then,

- [(5.1)](#matfrobnorm-5.1)

the one-parameter overload is equivalent to:return matrix_frob_norm(A, T{}); and

- [(5.2)](#matfrobnorm-5.2)

the two-parameter overload is equivalent to:return matrix_frob_norm(std::forward<ExecutionPolicy>(exec), A, T{});

#### [29.9.13.13](#matonenorm) One norm of a matrix [[linalg.algs.blas1.matonenorm]](linalg.algs.blas1.matonenorm)

[1](#matonenorm-1)

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

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

These functions exist in the BLAS standard[[bib]](bibliography#bib:blas-std "Bibliography") but are not part of the reference implementation[.](#matonenorm-1.sentence-1)

â *end note*]

[ð](#lib:matrix_one_norm)

`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat, class Scalar>
  Scalar matrix_one_norm(InMat A, Scalar init);
template<class ExecutionPolicy, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat, class Scalar>
  Scalar matrix_one_norm(ExecutionPolicy&& exec, InMat A, Scalar init);
`

[2](#matonenorm-2)

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

*Mandates*: decltype(*abs-if-needed*(declval<typename InMat​::​value_type>())) is convertible to Scalar[.](#matonenorm-2.sentence-1)

[3](#matonenorm-3)

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

*Returns*: 

- [(3.1)](#matonenorm-3.1)

init if A.extent(1) is zero;

- [(3.2)](#matonenorm-3.2)

otherwise, the sum of init and the one norm of the matrix A[.](#matonenorm-3.sentence-1)

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

The one norm of the matrix A is the maximum over all columns of A,
of the sum of the absolute values of the elements of the column[.](#matonenorm-3.sentence-2)

â *end note*]

[4](#matonenorm-4)

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

*Remarks*: If InMat​::​value_type and Scalar are all floating-point types or specializations of complex,
and if Scalar has higher precision
than InMat​::​value_type,
then intermediate terms in the sum use Scalar's precision or greater[.](#matonenorm-4.sentence-1)

[ð](#lib:matrix_one_norm_)

`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat>
  auto matrix_one_norm(InMat A);
template<class ExecutionPolicy, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat>
  auto matrix_one_norm(ExecutionPolicy&& exec, InMat A);
`

[5](#matonenorm-5)

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

*Effects*: Let T bedecltype(*abs-if-needed*(declval<typename InMat​::​value_type>())[.](#matonenorm-5.sentence-1)

Then,

- [(5.1)](#matonenorm-5.1)

the one-parameter overload is equivalent to:return matrix_one_norm(A, T{}); and

- [(5.2)](#matonenorm-5.2)

the two-parameter overload is equivalent to:return matrix_one_norm(std::forward<ExecutionPolicy>(exec), A, T{});

#### [29.9.13.14](#matinfnorm) Infinity norm of a matrix [[linalg.algs.blas1.matinfnorm]](linalg.algs.blas1.matinfnorm)

[1](#matinfnorm-1)

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

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

These functions exist in the BLAS standard[[bib]](bibliography#bib:blas-std "Bibliography") but are not part of the reference implementation[.](#matinfnorm-1.sentence-1)

â *end note*]

[ð](#lib:matrix_inf_norm)

`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat, class Scalar>
  Scalar matrix_inf_norm(InMat A, Scalar init);
template<class ExecutionPolicy, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat, class Scalar>
  Scalar matrix_inf_norm(ExecutionPolicy&& exec, InMat A, Scalar init);
`

[2](#matinfnorm-2)

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

*Mandates*: decltype(*abs-if-needed*(declval<typename InMat​::​value_type>())) is convertible to Scalar[.](#matinfnorm-2.sentence-1)

[3](#matinfnorm-3)

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

*Returns*: 

- [(3.1)](#matinfnorm-3.1)

init if A.extent(0) is zero;

- [(3.2)](#matinfnorm-3.2)

otherwise,
the sum of init and the infinity norm of the matrix A[.](#matinfnorm-3.sentence-1)

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

The infinity norm of the matrix A is the maximum over all rows of A,
of the sum of the absolute values
of the elements of the row[.](#matinfnorm-3.sentence-2)

â *end note*]

[4](#matinfnorm-4)

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

*Remarks*: If InMat​::​value_type and Scalar are all floating-point types or specializations of complex,
and if Scalar has higher precision
than InMat​::​value_type,
then intermediate terms in the sum use Scalar's precision or greater[.](#matinfnorm-4.sentence-1)

[ð](#lib:matrix_inf_norm_)

`template<[in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat>
  auto matrix_inf_norm(InMat A);
template<class ExecutionPolicy, [in-matrix](linalg.helpers.concepts#concept:in-matrix "29.9.7.5 Argument concepts [linalg.helpers.concepts]") InMat>
  auto matrix_inf_norm(ExecutionPolicy&& exec, InMat A);
`

[5](#matinfnorm-5)

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

*Effects*: Let T bedecltype(*abs-if-needed*(declval<typename InMat​::​value_type>())[.](#matinfnorm-5.sentence-1)

Then,

- [(5.1)](#matinfnorm-5.1)

the one-parameter overload is equivalent to:return matrix_inf_norm(A, T{}); and

- [(5.2)](#matinfnorm-5.2)

the two-parameter overload is equivalent to:return matrix_inf_norm(std::forward<ExecutionPolicy>(exec), A, T{});
