This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.
vector_two_norm
and matrix_frob_norm
Section: 29.9.13.9 [linalg.algs.blas1.nrm2], 29.9.13.12 [linalg.algs.blas1.matfrobnorm] Status: New Submitter: Mark Hoemmen Opened: 2025-08-14 Last modified: 2025-08-22
Priority: Not Prioritized
View all issues with New status.
Discussion:
The Returns clauses of vector_two_norm
29.9.13.9 [linalg.algs.blas1.nrm2] and
matrix_frob_norm
29.9.13.12 [linalg.algs.blas1.matfrobnorm] say that the
functions return the "square root" of the sum of squares of the initial value and
the absolute values of the elements of the input mdspan
. However, nowhere in
29.9 [linalg] explains how to compute a square root.
The input mdspan
's value_type
and the initial value type are
not constrained in a way that would ensure that calling std::sqrt
on
this expression would be well-formed.
There is no provision to find sqrt
via argument-dependent lookup,
even though 29.9 [linalg] has provisions to find abs
, conj
, real
, and
imag
via argument-dependent lookup. There is no "sqrt-if-needed
"
analog to abs-if-needed
, conj-if-needed
,
real-if-needed
, and imag-if-needed
.
The easiest fix for both issues is just to Constrain both Scalar
and
the input mdspan
's value_type
to be floating-point numbers or
specializations of std::complex
for these two functions. This
presumes that relaxing this Constraint and fixing the above two issues
later would be a non-breaking change. If that is not the case, then
I would suggest removing the two functions entirely.
Proposed resolution:
This wording is relative to N5014.
[Drafting note: As a drive-by fix the proposed wording adds a missing closing parentheses in 29.9.13.9 [linalg.algs.blas1.nrm2] p2.]
Modify 29.9.13.9 [linalg.algs.blas1.nrm2] as indicated:
template<in-vector InVec, class Scalar> Scalar vector_two_norm(InVec v, Scalar init); template<class ExecutionPolicy, in-vector InVec, class Scalar> Scalar vector_two_norm(ExecutionPolicy&& exec, InVec v, Scalar init);-1- [Note 1: […] — end note]
-?- Constraints:InVec::value_type
andScalar
are either a floating-point type, or a specialization ofcomplex
. -2- Mandates: Leta
beabs-if-needed(declval<typename InVec::value_type>())
. Then,decltype(init + a * a)
is convertible toScalar
. -3- Returns: The square root of the sum of the square ofinit
and the squares of the absolute values of the elements ofv
. [Note 2: Forinit
equal to zero, this is the Euclidean norm (also called 2-norm) of the vectorv
. — end note] -4- Remarks: IfInVec::value_type
, andScalar
are all floating-point types or specializations ofcomplex
, and ifScalar
has higher precision thanInVec::value_type
, then intermediate terms in the sum useScalar
's precision or greater. [Note 3: An implementation of this function for floating-point typesT
can use thescaled_sum_of_squares
resultfrom vector_sum_of_squares(x, {.scaling_factor=1.0, .scaled_sum_of_squares=init})
. — end note]
Modify 29.9.13.12 [linalg.algs.blas1.matfrobnorm] as indicated:
template<in-matrix InMat, class Scalar> Scalar matrix_frob_norm(InMat A, Scalar init); template<class ExecutionPolicy, in-matrix InMat, class Scalar> Scalar matrix_frob_norm(ExecutionPolicy&& exec, InMat A, Scalar init);-?- Constraints:
-2- Mandates: LetInVec::value_type
andScalar
are either a floating-point type, or a specialization ofcomplex
.a
beabs-if-needed(declval<typename InMat::value_type>())
. Then,decltype(init + a * a)
is convertible toScalar
. -3- Returns: The square root of the sum of squares ofinit
and the absolute values of the elements ofA
. [Note 2: Forinit
equal to zero, this is the Frobenius norm of the matrixA
. — end note] -4- Remarks: IfInMat::value_type
andScalar
are all floating-point types or specializations ofcomplex
, and ifScalar
has higher precision thanInMat::value_type
, then intermediate terms in the sum useScalar
's precision or greater.