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

12 KiB
Raw Blame History

[linalg.transp]

29 Numerics library [numerics]

29.9 Basic linear algebra algorithms [linalg]

29.9.10 Transpose in-place transformation [linalg.transp]

29.9.10.1 Introduction [linalg.transp.intro]

1

#

layout_transpose is an mdspan layout mapping policy that swaps the two indices, extents, and strides of any unique mdspan layout mapping policy.

2

#

The transposed function takes an mdspan representing a matrix, and returns a new mdspan representing the transpose of the input matrix.

29.9.10.2 Exposition-only helpers for layout_transpose and transposed [linalg.transp.helpers]

1

#

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.

2

#

The exposition-only alias templatetranspose-extents-t gives the type of transpose-extents(e) for a given extents object e of type InputExtents.

🔗

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

#

Returns: extents<IndexType, InputExtent1, InputExtent0>(in.extent(1), in.extent(0))

templateusing transpose-extents-t =decltype(transpose-extents(declval())); // exposition only

29.9.10.3 Class template layout_transpose [linalg.transp.layout.transpose]

1

#

layout_transpose is an mdspan layout mapping policy that swaps the two indices, extents, and strides of any mdspan layout mapping policy.

namespace std::linalg {templateclass layout_transpose {public:using nested_layout_type = Layout; templatestruct mapping {private:using nested-mapping-type =typename Layout::template mapping<transpose-extents-t>; // exposition onlypublic: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; templatefriend constexpr bool operator==(const mapping& x, const mapping& y); }; private:nested-mapping-type nested-mapping_; // exposition only extents_type extents_; // exposition only};}

2

#

Layout shall meet the layout mapping policy requirements ([mdspan.layout.policy.reqmts]).

3

#

Mandates:

Extents is a specialization of std::extents, and

Extents::rank() equals 2.

🔗

constexpr explicit mapping(const nested-mapping-type& map);

4

#

Effects:

Initializes nested-mapping_ with map, and

initializes extents_ with transpose-extents(map.extents()).

🔗

constexpr index_type stride(size_t r) const;

5

#

Preconditions:

is_strided() is true, and

r < 2 is true.

6

#

Returns: nested-mapping_.stride(r == 0 ? 1 : 0)

🔗

template<class OtherExtents> friend constexpr bool operator==(const mapping& x, const mapping<OtherExtents>& y);

7

#

Constraints: The expressionx.nested-mapping_ == y.nested-mapping_ is well-formed and its result is convertible to bool.

8

#

Returns: x.nested-mapping_ == y.nested-mapping_.

29.9.10.4 Function template transposed [linalg.transp.transposed]

1

#

The transposed function takes a rank-2 mdspan representing a matrix, and returns a new mdspan representing the input matrix's transpose.

The input matrix's data are not modified, and the returned mdspan accesses the input matrix's data in place.

🔗

template<class ElementType, class Extents, class Layout, class Accessor> constexpr auto transposed(mdspan<ElementType, Extents, Layout, Accessor> a);

2

#

Mandates: Extents::rank() == 2 is true.

3

#

Let ReturnExtents betranspose-extents-t.

Let R bemdspan<ElementType, ReturnExtents, ReturnLayout, Accessor>, where ReturnLayout is:

layout_right if Layout is layout_left;

otherwise, layout_left if Layout is layout_right;

otherwise, layout_right_padded if Layout is
layout_left_padded for some size_t value PaddingValue;

otherwise, layout_left_padded if Layout is
layout_right_padded for some size_t value PaddingValue;

otherwise, layout_stride if Layout is layout_stride;

otherwise,layout_blas_packed<OppositeTriangle, OppositeStorageOrder>, if Layout is
layout_blas_packed<Triangle, StorageOrder> for some Triangle and StorageOrder, where

OppositeTriangle isconditional_t<is_same_v<Triangle, upper_triangle_t>, lower_triangle_t, upper_triangle_t> and

OppositeStorageOrder isconditional_t<is_same_v<StorageOrder, column_major_t>, row_major_t, column_major_t>

otherwise, NestedLayout if Layout is layout_transpose for some NestedLayout;

otherwise, layout_transpose.

4

#

Returns: With ReturnMapping being the type typename ReturnLayout::template mapping:

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())

otherwise,R(a.data_handle(), ReturnMapping(transpose-extents(a.mapping().extents()), a.mapping().stride(1)), a.accessor()) if Layout is layout_left_padded for some size_t value PaddingValue;

otherwise,R(a.data_handle(), ReturnMapping(transpose-extents(a.mapping().extents()), a.mapping().stride(0)), a.accessor()) if Layout is layout_right_padded for some size_t value PaddingValue;

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())

otherwise, if Layout is a specialization of layout_transpose,R(a.data_handle(), a.mapping().nested_mapping(), a.accessor())

otherwise,R(a.data_handle(), ReturnMapping(a.mapping()), a.accessor())

5

#

[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]