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

279 lines
12 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[linalg.transp]
# 29 Numerics library [[numerics]](./#numerics)
## 29.9 Basic linear algebra algorithms [[linalg]](linalg#transp)
### 29.9.10 Transpose in-place transformation [linalg.transp]
#### [29.9.10.1](#intro) Introduction [[linalg.transp.intro]](linalg.transp.intro)
[1](#intro-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12943)
layout_transpose is an mdspan layout mapping policy
that swaps the two indices, extents, and strides
of any unique mdspan layout mapping policy[.](#intro-1.sentence-1)
[2](#intro-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12948)
The transposed function takes an mdspan representing a matrix, and returns a new mdspan representing the transpose of the input matrix[.](#intro-2.sentence-1)
#### [29.9.10.2](#helpers) Exposition-only helpers for layout_transpose and transposed [[linalg.transp.helpers]](linalg.transp.helpers)
[1](#helpers-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12955)
The exposition-only *transpose-extents* function
takes an extents object representing the extents of a matrix,
and returns a new extents object
representing the extents of the transpose of the matrix[.](#helpers-1.sentence-1)
[2](#helpers-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12961)
The exposition-only alias template*transpose-extents-t*<InputExtents> gives the type of *transpose-extents*(e) for a given extents object e of type InputExtents[.](#helpers-2.sentence-1)
[🔗](#helpers-itemdecl:1)
`template<class IndexType, size_t InputExtent0, size_t InputExtent1>
constexpr extents<IndexType, InputExtent1, InputExtent0>
transpose-extents(const extents<IndexType, InputExtent0, InputExtent1>& in); // exposition only
`
[3](#helpers-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12973)
*Returns*: extents<IndexType, InputExtent1, InputExtent0>(in.extent(1), in.extent(0))
template<class InputExtents>using *transpose-extents-t* =decltype(*transpose-extents*(declval<InputExtents>())); // *exposition only*
#### [29.9.10.3](#layout.transpose) Class template layout_transpose [[linalg.transp.layout.transpose]](linalg.transp.layout.transpose)
[1](#layout.transpose-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12986)
layout_transpose is an mdspan layout mapping policy
that swaps the two indices, extents, and strides
of any mdspan layout mapping policy[.](#layout.transpose-1.sentence-1)
namespace std::linalg {template<class Layout>class [layout_transpose](#lib:layout_transpose "29.9.10.3Class template layout_­transpose[linalg.transp.layout.transpose]") {public:using nested_layout_type = Layout; template<class Extents>struct mapping {private:using *nested-mapping-type* =typename Layout::template mapping<*transpose-extents-t*<Extents>>; // *exposition only*public:using extents_type = Extents; using index_type = typename extents_type::index_type; using size_type = typename extents_type::size_type; using rank_type = typename extents_type::rank_type; using layout_type = layout_transpose; constexpr explicit mapping(const *nested-mapping-type*&); constexpr const extents_type& extents() const noexcept { return *extents_*; }constexpr index_type required_span_size() const{ return *nested-mapping_*.required_span_size(); template<class Index0, class Index1>constexpr index_type operator()(Index0 ind0, Index1 ind1) const{ return *nested-mapping_*(ind1, ind0); }constexpr const *nested-mapping-type*& nested_mapping() const noexcept{ return *nested-mapping_*; }static constexpr bool is_always_unique() noexcept{ return *nested-mapping-type*::is_always_unique(); }static constexpr bool is_always_exhaustive() noexcept{ return *nested-mapping-type*::is_always_exhaustive(); }static constexpr bool is_always_strided() noexcept{ return *nested-mapping-type*::is_always_strided(); }constexpr bool is_unique() const { return *nested-mapping_*.is_unique(); }constexpr bool is_exhaustive() const { return *nested-mapping_*.is_exhaustive(); }constexpr bool is_strided() const { return *nested-mapping_*.is_strided(); }constexpr index_type stride(size_t r) const; template<class OtherExtents>friend constexpr bool operator==(const mapping& x, const mapping<OtherExtents>& y); }; private:*nested-mapping-type* *nested-mapping_*; // *exposition only* extents_type *extents_*; // *exposition only*};}
[2](#layout.transpose-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13049)
Layout shall meet
the layout mapping policy requirements ([[mdspan.layout.policy.reqmts]](mdspan.layout.policy.reqmts "23.7.3.4.3Layout mapping policy requirements"))[.](#layout.transpose-2.sentence-1)
[3](#layout.transpose-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13053)
*Mandates*:
- [(3.1)](#layout.transpose-3.1)
Extents is a specialization of std::extents, and
- [(3.2)](#layout.transpose-3.2)
Extents::rank() equals 2[.](#layout.transpose-3.sentence-1)
[🔗](#lib:layout_transpose::mapping,constructor)
`constexpr explicit mapping(const nested-mapping-type& map);
`
[4](#layout.transpose-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13068)
*Effects*:
- [(4.1)](#layout.transpose-4.1)
Initializes *nested-mapping_* with map, and
- [(4.2)](#layout.transpose-4.2)
initializes *extents_* with *transpose-extents*(map.extents())[.](#layout.transpose-4.sentence-1)
[🔗](#lib:layout_transpose::mapping,stride)
`constexpr index_type stride(size_t r) const;
`
[5](#layout.transpose-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13085)
*Preconditions*:
- [(5.1)](#layout.transpose-5.1)
is_strided() is true, and
- [(5.2)](#layout.transpose-5.2)
r < 2 is true[.](#layout.transpose-5.sentence-1)
[6](#layout.transpose-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13094)
*Returns*: *nested-mapping_*.stride(r == 0 ? 1 : 0)
[🔗](#lib:layout_transpose::mapping,operator==)
`template<class OtherExtents>
friend constexpr bool operator==(const mapping& x, const mapping<OtherExtents>& y);
`
[7](#layout.transpose-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13106)
*Constraints*: The expressionx.*nested-mapping_* == y.*nested-mapping_* is well-formed and its result is convertible to bool[.](#layout.transpose-7.sentence-1)
[8](#layout.transpose-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13112)
*Returns*: x.*nested-mapping_* == y.*nested-mapping_*[.](#layout.transpose-8.sentence-1)
#### [29.9.10.4](#transposed) Function template transposed [[linalg.transp.transposed]](linalg.transp.transposed)
[1](#transposed-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13119)
The transposed function
takes a rank-2 mdspan representing a matrix, and
returns a new mdspan representing the input matrix's transpose[.](#transposed-1.sentence-1)
The input matrix's data are not modified, and
the returned mdspan accesses the input matrix's data in place[.](#transposed-1.sentence-2)
[🔗](#lib:transposed)
` template<class ElementType, class Extents, class Layout, class Accessor>
constexpr auto transposed(mdspan<ElementType, Extents, Layout, Accessor> a);
`
[2](#transposed-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13132)
*Mandates*: Extents::rank() == 2 is true[.](#transposed-2.sentence-1)
[3](#transposed-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13136)
Let ReturnExtents be*transpose-extents-t*<Extents>[.](#transposed-3.sentence-1)
Let R bemdspan<ElementType, ReturnExtents, ReturnLayout, Accessor>,
where ReturnLayout is:
- [(3.1)](#transposed-3.1)
layout_right if Layout is layout_left;
- [(3.2)](#transposed-3.2)
otherwise, layout_left if Layout is layout_right;
- [(3.3)](#transposed-3.3)
otherwise, layout_right_padded<PaddingValue> if Layout is
layout_left_padded<PaddingValue> for some size_t value PaddingValue;
- [(3.4)](#transposed-3.4)
otherwise, layout_left_padded<PaddingValue> if Layout is
layout_right_padded<PaddingValue> for some size_t value PaddingValue;
- [(3.5)](#transposed-3.5)
otherwise, layout_stride if Layout is layout_stride;
- [(3.6)](#transposed-3.6)
otherwise,layout_blas_packed<OppositeTriangle, OppositeStorageOrder>,
if Layout is
layout_blas_packed<Triangle, StorageOrder> for some Triangle and StorageOrder, where
* [(3.6.1)](#transposed-3.6.1)
OppositeTriangle isconditional_t<is_same_v<Triangle, upper_triangle_t>,
lower_triangle_t, upper_triangle_t> and
* [(3.6.2)](#transposed-3.6.2)
OppositeStorageOrder isconditional_t<is_same_v<StorageOrder, column_major_t>, row_major_t, column_major_t>
- [(3.7)](#transposed-3.7)
otherwise, NestedLayout if Layout is layout_transpose<NestedLayout> for some NestedLayout;
- [(3.8)](#transposed-3.8)
otherwise, layout_transpose<Layout>[.](#transposed-3.sentence-2)
[4](#transposed-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13185)
*Returns*: With ReturnMapping being
the type typename ReturnLayout::template mapping<ReturnExtents>:
- [(4.1)](#transposed-4.1)
if Layout is layout_left, layout_right, or
a specialization of layout_blas_packed,R(a.data_handle(), ReturnMapping(*transpose-extents*(a.mapping().extents())),
a.accessor())
- [(4.2)](#transposed-4.2)
otherwise,R(a.data_handle(), ReturnMapping(*transpose-extents*(a.mapping().extents()),
a.mapping().stride(1)), a.accessor()) if Layout is layout_left_padded<PaddingValue> for some size_t value PaddingValue;
- [(4.3)](#transposed-4.3)
otherwise,R(a.data_handle(), ReturnMapping(*transpose-extents*(a.mapping().extents()),
a.mapping().stride(0)), a.accessor()) if Layout is layout_right_padded<PaddingValue> for some size_t value PaddingValue;
- [(4.4)](#transposed-4.4)
otherwise, if Layout is layout_stride,R(a.data_handle(), ReturnMapping(*transpose-extents*(a.mapping().extents()),
array{a.mapping().stride(1), a.mapping().stride(0)}), a.accessor())
- [(4.5)](#transposed-4.5)
otherwise, if Layout is a specialization of layout_transpose,R(a.data_handle(), a.mapping().nested_mapping(), a.accessor())
- [(4.6)](#transposed-4.6)
otherwise,R(a.data_handle(), ReturnMapping(a.mapping()), a.accessor())
[5](#transposed-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L13232)
[*Example [1](#transposed-example-1)*: void test_transposed(mdspan<double, extents<size_t, 3, 4>> a) {const auto num_rows = a.extent(0); const auto num_cols = a.extent(1); auto a_t = transposed(a);
assert(num_rows == a_t.extent(1));
assert(num_cols == a_t.extent(0));
assert(a.stride(0) == a_t.stride(1));
assert(a.stride(1) == a_t.stride(0)); for (size_t row = 0; row < num_rows; ++row) {for (size_t col = 0; col < num_rows; ++col) { assert(a[row, col] == a_t[col, row]); }}auto a_t_t = transposed(a_t);
assert(num_rows == a_t_t.extent(0));
assert(num_cols == a_t_t.extent(1));
assert(a.stride(0) == a_t_t.stride(0));
assert(a.stride(1) == a_t_t.stride(1)); for (size_t row = 0; row < num_rows; ++row) {for (size_t col = 0; col < num_rows; ++col) { assert(a[row, col] == a_t_t[row, col]); }}} — *end example*]