This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of LEWG status.
vector_sum_of_squares wordingSection: 29.9.13.8 [linalg.algs.blas1.ssq] Status: LEWG Submitter: Mark Hoemmen Opened: 2025-07-23 Last modified: 2025-10-27
Priority: 1
View all issues with LEWG status.
Discussion:
The current wording for vector_sum_of_squares
29.9.13.8 [linalg.algs.blas1.ssq] has three problems with its specification of the
value of result.scaling_factor.
The function permits InVec::value_type and Scalar to be any
linear algebra value types. However, computing
result.scaling_factor that satisfies both (3.1) and (3.2) requires
more operations, such as division. Even if those operations are
defined, they might not make result.scaling_factor satisfy the
required properties. For example, integers have division, but integer
division won't help here.
LAPACK's xLASSQ (the algorithm to which Note 1 in 29.9.13.8 [linalg.algs.blas1.ssq] refers) changed its algorithm recently (see Reference-LAPACK/lapack/pull/#494) so that the scaling factor is no longer necessarily the maximum of the input scaling factor and the absolute value of all the input elements. It's a better algorithm and we would like to be able to use it.
Both members of sum_of_squares_result<Scalar> have the same type,
Scalar. If the input mdspan's value_type represents a quantity
with units, this would not be correct. For example, if value_type
has units of distance (say [m]), the sum of squares should have units
of area ([m2]), while the scaling factor should have units of
distance ([m]).
Problem (1) means that the current wording is broken. I suggest two different ways to fix this.
Remove vector_sum_of_squares entirely (both overloads from
29.9.2 [linalg.syn], and the entire
29.9.13.8 [linalg.algs.blas1.ssq]). That way, we
won't be baking an old, less good algorithm into the Standard. Remove
Note 3 from 29.9.13.9 [linalg.algs.blas1.nrm2], which is the only
other reference to vector_sum_of_squares in the Standard.
Fix 29.9.13.8 [linalg.algs.blas1.ssq] by adding to the
Mandates element (para 2) that InVec::value_type and Scalar
are both floating-point types (so that we could fix this later if
we want), and remove 29.9.13.8 [linalg.algs.blas1.ssq] 3.1.
Optionally add Recommended Practice, though Note 1 already
suggests the intent.
I prefer just removing vector_sum_of_squares. Implementers who care
about QoI of vector_two_norm should already know what to do. If
somebody cares sufficiently, they can propose it back for C++29 and
think about how to make it work for generic number types.
[2025-10-17; Reflector poll. Status changed: New → LEWG.]
Set priority to 1 after reflector poll. Send to LEWG.
This is the subject of NB comment 169-276. LWG took a poll in the 2025-10-10 telecon and recommends that LEWG confirms this resolution.
[2025-10-24; Resolves US 169-276]
Proposed resolution:
This wording is relative to N5014.
[Drafting note: The wording below implements option 1 of the issue discussion]
Modify 29.9.2 [linalg.syn], header <linalg> synopsis, as indicated:
namespace std::linalg {
[…]
// 29.9.13.8 [linalg.algs.blas1.ssq], scaled sum of squares of a vector's elements
template<class Scalar>
struct sum_of_squares_result {
Scalar scaling_factor;
};
template<in-vector 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 InVec, class Scalar>
sum_of_squares_result<Scalar>
vector_sum_of_squares(ExecutionPolicy&& exec,
InVec v, sum_of_squares_result<Scalar> init);
[…]
}
Delete the entire 29.9.13.8 [linalg.algs.blas1.ssq] as indicated:
29.9.13.8 Scaled sum of squares of a vector's elements [linalg.algs.blas1.ssq]template<in-vector 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 InVec, class Scalar> sum_of_squares_result<Scalar> vector_sum_of_squares(ExecutionPolicy&& exec, InVec v, sum_of_squares_result<Scalar> init);
-1- [Note 1: These functions correspond to the LAPACK function xLASSQ[20]. — end note]-2- Mandates:decltype(abs-if-needed(declval<typename InVec::value_type>()))is convertible toScalar.-3- Effects: Returns a valueresultsuch that
(3.1) —result.scaling_factoris the maximum ofinit.scaling_factorandabs-if-needed(x[i])for alliin the domain ofv; and
(3.2) — lets2initbeinit.scaling_factor * init.scaling_factor * init.scaled_sum_of_squares
thenresult.scaling_factor * result.scaling_factor * result.scaled_sum_of_squaresequals the sum ofs2initand the squares ofabs-if-needed(x[i])for alliin the domain ofv.
-4- Remarks: IfInVec::value_type, andScalarare all floating-point types or specializations ofcomplex, and ifScalarhas higher precision thanInVec::value_type, then intermediate terms in the sum useScalar's precision or greater.
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: […] ]
-2- Mandates: […] -3- Returns: […] [Note 2: […] ] -4- Remarks: […][Note 3: An implementation of this function for floating-point typesTcan use thescaled_sum_of_squaresresult fromvector_sum_of_squares(x, {.scaling_factor=1.0, .scaled_sum_of_squares=init}). — end note]