Files
cppdraft_translate/cppdraft/linalg/helpers.md
2025-10-25 03:02:53 +03:00

15 KiB
Raw Blame History

[linalg.helpers]

29 Numerics library [numerics]

29.9 Basic linear algebra algorithms [linalg]

29.9.7 Exposition-only helpers [linalg.helpers]

29.9.7.1 abs-if-needed [linalg.helpers.abs]

1

#

The name abs-if-needed denotes an exposition-only function object.

The expression abs-if-needed(E) for a subexpression E whose type is T is expression-equivalent to:

E if T is an unsigned integer;

otherwise, std::abs(E) if T is an arithmetic type,

otherwise, abs(E), if that expression is valid, with overload resolution performed in a context that includes the declarationtemplate U abs(U) = delete; If the function selected by overload resolution does not return the absolute value of its input, the program is ill-formed, no diagnostic required.

29.9.7.2 conj-if-needed [linalg.helpers.conj]

1

#

The name conj-if-needed denotes an exposition-only function object.

The expression conj-if-needed(E) for a subexpression E whose type is T is expression-equivalent to:

conj(E), if T is not an arithmetic type and the expression conj(E) is valid, with overload resolution performed in a context that includes the declarationtemplate U conj(const U&) = delete; If the function selected by overload resolution does not return the complex conjugate of its input, the program is ill-formed, no diagnostic required;

otherwise, E.

29.9.7.3 real-if-needed [linalg.helpers.real]

1

#

The name real-if-needed denotes an exposition-only function object.

The expression real-if-needed(E) for a subexpression E whose type is T is expression-equivalent to:

real(E), if T is not an arithmetic type and the expression real(E) is valid, with overload resolution performed in a context that includes the declarationtemplate U real(const U&) = delete; If the function selected by overload resolution does not return the real part of its input, the program is ill-formed, no diagnostic required;

otherwise, E.

29.9.7.4 imag-if-needed [linalg.helpers.imag]

1

#

The name imag-if-needed denotes an exposition-only function object.

The expression imag-if-needed(E) for a subexpression E whose type is T is expression-equivalent to:

imag(E), if T is not an arithmetic type and the expression imag(E) is valid, with overload resolution performed in a context that includes the declarationtemplate U imag(const U&) = delete; If the function selected by overload resolution does not return the imaginary part of its input, the program is ill-formed, no diagnostic required;

otherwise, ((void)E, T{}).

29.9.7.5 Argument concepts [linalg.helpers.concepts]

1

#

The exposition-only concepts defined in this section constrain the algorithms in [linalg].

templateconstexpr bool is-mdspan = false;

template<class ElementType, class Extents, class Layout, class Accessor>constexpr bool is-mdspan<mdspan<ElementType, Extents, Layout, Accessor>> = true;

templateconcept in-vector =is-mdspan && T::rank() == 1;

templateconcept out-vector =is-mdspan && T::rank() == 1 && is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();

templateconcept inout-vector =is-mdspan && T::rank() == 1 && is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();

templateconcept in-matrix =is-mdspan && T::rank() == 2;

templateconcept out-matrix =is-mdspan && T::rank() == 2 && is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();

templateconcept inout-matrix =is-mdspan && T::rank() == 2 && is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();

templateconstexpr bool is-layout-blas-packed = false; // exposition onlytemplate<class Triangle, class StorageOrder>constexpr bool is-layout-blas-packed<layout_blas_packed<Triangle, StorageOrder>> = true;

templateconcept possibly-packed-inout-matrix =is-mdspan && T::rank() == 2 && is_assignable_v<typename T::reference, typename T::element_type> &&(T::is_always_unique() || is-layout-blas-packed);

templateconcept in-object =is-mdspan && (T::rank() == 1 || T::rank() == 2);

templateconcept out-object =is-mdspan && (T::rank() == 1 || T::rank() == 2) && is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();

templateconcept inout-object =is-mdspan && (T::rank() == 1 || T::rank() == 2) && is_assignable_v<typename T::reference, typename T::element_type> && T::is_always_unique();

2

#

If a function in [linalg] accesses the elements of a parameter constrained byin-vector,in-matrix, orin-object, those accesses will not modify the elements.

3

#

Unless explicitly permitted, anyinout-vector,inout-matrix,inout-object,out-vector,out-matrix,out-object, orpossibly-packed-inout-matrix parameter of a function in [linalg] shall not overlap any other mdspan parameter of the function.

29.9.7.6 Mandates [linalg.helpers.mandates]

1

#

[Note 1:

These exposition-only helper functions use the less constraining input concepts even for the output arguments, because the additional constraint for assignability of elements is not necessary, and they are sometimes used in a context where the third argument is an input type too.

— end note]

template<class MDS1, class MDS2>requires(is-mdspan && is-mdspan)constexprbool compatible-static-extents(size_t r1, size_t r2) { // exposition onlyreturn MDS1::static_extent(r1) == dynamic_extent || MDS2::static_extent(r2) == dynamic_extent || MDS1::static_extent(r1) == MDS2::static_extent(r2); }template<in-vector In1, in-vector In2, in-vector Out>constexpr bool possibly-addable() { // exposition onlyreturn compatible-static-extents<Out, In1>(0, 0) &&compatible-static-extents<Out, In2>(0, 0) &&compatible-static-extents<In1, In2>(0, 0); }template<in-matrix In1, in-matrix In2, in-matrix Out>constexpr bool possibly-addable() { // exposition onlyreturn compatible-static-extents<Out, In1>(0, 0) &&compatible-static-extents<Out, In1>(1, 1) &&compatible-static-extents<Out, In2>(0, 0) &&compatible-static-extents<Out, In2>(1, 1) &&compatible-static-extents<In1, In2>(0, 0) &&compatible-static-extents<In1, In2>(1, 1); }template<in-matrix InMat, in-vector InVec, in-vector OutVec>constexpr bool possibly-multipliable() { // exposition onlyreturn compatible-static-extents<OutVec, InMat>(0, 0) &&compatible-static-extents<InMat, InVec>(1, 0); }template<in-vector InVec, in-matrix InMat, in-vector OutVec>constexpr bool possibly-multipliable() { // exposition onlyreturn compatible-static-extents<OutVec, InMat>(0, 1) &&compatible-static-extents<InMat, InVec>(0, 0); }template<in-matrix InMat1, in-matrix InMat2, in-matrix OutMat>constexpr bool possibly-multipliable() { // exposition onlyreturn compatible-static-extents<OutMat, InMat1>(0, 0) &&compatible-static-extents<OutMat, InMat2>(1, 1) &&compatible-static-extents<InMat1, InMat2>(1, 0); }

29.9.7.7 Preconditions [linalg.helpers.precond]

1

#

[Note 1:

These exposition-only helper functions use the less constraining input concepts even for the output arguments, because the additional constraint for assignability of elements is not necessary, and they are sometimes used in a context where the third argument is an input type too.

— end note]

constexpr bool addable( // exposition onlyconst in-vector auto& in1, const in-vector auto& in2, const in-vector auto& out) {return out.extent(0) == in1.extent(0) && out.extent(0) == in2.extent(0);}constexpr bool addable( // exposition onlyconst in-matrix auto& in1, const in-matrix auto& in2, const in-matrix auto& out) {return out.extent(0) == in1.extent(0) && out.extent(1) == in1.extent(1) && out.extent(0) == in2.extent(0) && out.extent(1) == in2.extent(1);}constexpr bool multipliable( // exposition onlyconst in-matrix auto& in_mat, const in-vector auto& in_vec, const in-vector auto& out_vec) {return out_vec.extent(0) == in_mat.extent(0) && in_mat.extent(1) == in_vec.extent(0);}constexpr bool multipliable( // exposition onlyconst in-vector auto& in_vec, const in-matrix auto& in_mat, const in-vector auto& out_vec) {return out_vec.extent(0) == in_mat.extent(1) && in_mat.extent(0) == in_vec.extent(0);}constexpr bool multipliable( // exposition onlyconst in-matrix auto& in_mat1, const in-matrix auto& in_mat2, const in-matrix auto& out_mat) {return out_mat.extent(0) == in_mat1.extent(0) && out_mat.extent(1) == in_mat2.extent(1) && in_mat1.extent(1) == in_mat2.extent(0);}