[linalg.layout.packed.overview]

# 29 Numerics library [[numerics]](./#numerics)

## 29.9 Basic linear algebra algorithms [[linalg]](linalg#layout.packed.overview)

### 29.9.6 Layouts for packed matrix types [[linalg.layout.packed]](linalg.layout.packed#overview)

#### 29.9.6.1 Overview [linalg.layout.packed.overview]

[1](#1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12015)

layout_blas_packed is an mdspan layout mapping policy
that represents a square matrix that stores only the entries in one
triangle, in a packed contiguous format[.](#1.sentence-1)

Its Triangle template parameter determines
whether an mdspan with this layout
stores the upper or lower triangle of the matrix[.](#1.sentence-2)

Its StorageOrder template parameter determines
whether the layout packs the matrix's elements
in column-major or row-major order[.](#1.sentence-3)

[2](#2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12026)

A StorageOrder of column_major_t indicates column-major ordering[.](#2.sentence-1)

This packs matrix elements
starting with the leftmost (least column index) column, and
proceeding column by column, from the top entry (least row index)[.](#2.sentence-2)

[3](#3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12033)

A StorageOrder of row_major_t indicates row-major ordering[.](#3.sentence-1)

This packs matrix elements
starting with the topmost (least row index) row, and
proceeding row by row, from the leftmost (least column index) entry[.](#3.sentence-2)

[4](#4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12040)

[*Note [1](#note-1)*:

layout_blas_packed describes the data layout used by
the BLAS'
Symmetric Packed (SP), Hermitian Packed (HP), and Triangular Packed (TP)
matrix types[.](#4.sentence-1)

â *end note*]

namespace std::linalg {template<class Triangle, class StorageOrder>class [layout_blas_packed](#lib:layout_blas_packed "29.9.6.1 Overview [linalg.layout.packed.overview]") {public:using triangle_type = Triangle; using storage_order_type = StorageOrder; template<class Extents>struct mapping {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_blas_packed; // [[linalg.layout.packed.cons]](linalg.layout.packed.cons "29.9.6.2 Constructors"), constructorsconstexpr mapping() noexcept = default; constexpr mapping(const mapping&) noexcept = default; constexpr mapping(const extents_type&) noexcept; template<class OtherExtents>constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) mapping(const mapping<OtherExtents>& other) noexcept; constexpr mapping& operator=(const mapping&) noexcept = default; // [[linalg.layout.packed.obs]](linalg.layout.packed.obs "29.9.6.3 Observers"), observersconstexpr const extents_type& extents() const noexcept { return *extents_*; }constexpr index_type required_span_size() const noexcept; template<class Index0, class Index1>constexpr index_type operator() (Index0 ind0, Index1 ind1) const noexcept; static constexpr bool is_always_unique() noexcept {return (extents_type::static_extent(0) != dynamic_extent && extents_type::static_extent(0) < 2) ||(extents_type::static_extent(1) != dynamic_extent && extents_type::static_extent(1) < 2); }static constexpr bool is_always_exhaustive() noexcept { return true; }static constexpr bool is_always_strided() noexcept{ return is_always_unique(); }constexpr bool is_unique() const noexcept {return *extents_*.extent(0) < 2; }constexpr bool is_exhaustive() const noexcept { return true; }constexpr bool is_strided() const noexcept {return *extents_*.extent(0) < 2; }constexpr index_type stride(rank_type) const noexcept; template<class OtherExtents>friend constexpr bool operator==(const mapping&, const mapping<OtherExtents>&) noexcept; private: extents_type *extents_*{}; // *exposition only*}; };}

[5](#5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12113)

*Mandates*: 

- [(5.1)](#5.1)

Triangle is either upper_triangle_t or lower_triangle_t,

- [(5.2)](#5.2)

StorageOrder is either column_major_t or row_major_t,

- [(5.3)](#5.3)

Extents is a specialization of std​::​extents,

- [(5.4)](#5.4)

Extents​::​rank() equals 2,

- [(5.5)](#5.5)

one ofextents_type::static_extent(0) == dynamic_extent, extents_type::static_extent(1) == dynamic_extent, or extents_type::static_extent(0) == extents_type::static_extent(1) is true, and

- [(5.6)](#5.6)

if Extents​::​rank_dynamic() == 0 is true,
let Ns be equal to Extents​::​static_extent(0); then,NsÃ(Ns+1) is representable as a value of type index_type[.](#5.sentence-1)

[6](#6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L12138)

layout_blas_packed<T, SO>​::​mapping<E> is a trivially copyable type
that models [regular](concepts.object#concept:regular "18.6 Object concepts [concepts.object]") for each T, SO, and E[.](#6.sentence-1)
