TRIQS/nda 1.3.0
Multi-dimensional array library for C++
Loading...
Searching...
No Matches
matrix_functions.hpp
Go to the documentation of this file.
1// Copyright (c) 2019-2023 Simons Foundation
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0.txt
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// Authors: Olivier Parcollet, Nils Wentzell
16
17/**
18 * @file
19 * @brief Provides functions to create and manipulate matrices, i.e. arrays/view with 'M' algebra.
20 */
21
22#pragma once
23
24#include "./accessors.hpp"
25#include "./concepts.hpp"
26#include "./declarations.hpp"
27#include "./layout/policies.hpp"
28#include "./layout_transforms.hpp"
29#include "./macros.hpp"
30#include "./mapped_functions.hpp"
31#include "./mem/policies.hpp"
32#include "./stdutil/array.hpp"
33
34#include <algorithm>
35#include <concepts>
36#include <ranges>
37#include <type_traits>
38
39namespace nda {
40
41 /**
42 * @addtogroup av_factories
43 * @{
44 */
45
46 /**
47 * @brief Create an identity nda::matrix with ones on the diagonal.
48 *
49 * @tparam S nda::Scalar value type of the matrix.
50 * @tparam Int Integral type.
51 * @param dim Dimension of the square matrix.
52 * @return Identity nda::matrix of size `dim x dim`.
53 */
54 template <Scalar S, std::integral Int = long>
55 auto eye(Int dim) {
56 auto r = matrix<S>(dim, dim);
57 r = S{1};
58 return r;
59 }
60
61 /**
62 * @ingroup av_math
63 * @brief Get the trace of a 2-dimensional square array/view.
64 *
65 * @tparam M nda::ArrayOfRank<2> type.
66 * @param m 2-dimensional array/view.
67 * @return Sum of the diagonal elements of the array/view.
68 */
69 template <ArrayOfRank<2> M>
70 auto trace(M const &m) {
71 static_assert(get_rank<M> == 2, "Error in nda::trace: Array/View must have rank 2");
72 EXPECTS(m.shape()[0] == m.shape()[1]);
73 auto r = get_value_t<M>{};
74 auto d = m.shape()[0];
75 for (int i = 0; i < d; ++i) r += m(i, i);
76 return r;
77 }
78
79 /**
80 * @ingroup av_math
81 * @brief Get the conjugate transpose of 2-dimensional array/view.
82 *
83 * @details It first calls nda::transpose and then the lazy nda::conj function in case the array/view is complex
84 * valued.
85 *
86 * @tparam M nda::ArrayOfRank<2> type.
87 * @param m 2-dimensional array/view.
88 * @return (Lazy) Conjugate transpose of the array/view.
89 */
90 template <ArrayOfRank<2> M>
91 ArrayOfRank<2> auto dagger(M const &m) {
92 if constexpr (is_complex_v<typename M::value_type>)
93 return conj(transpose(m));
94 else
95 return transpose(m);
96 }
97
98 /**
99 * @brief Get a view of the diagonal of a 2-dimensional array/view.
100 *
101 * @tparam M nda::MemoryArrayOfRank<2> type.
102 * @param m 2-dimensional array/view.
103 * @return A view with the 'V' algebra of the diagonal of the array/view.
104 */
105 template <MemoryArrayOfRank<2> M>
106 ArrayOfRank<1> auto diagonal(M &m) {
107 long dim = std::min(m.shape()[0], m.shape()[1]);
108 long stride = stdutil::sum(m.indexmap().strides());
109 using vector_view_t =
110 basic_array_view<std::remove_reference_t<decltype(*m.data())>, 1, C_stride_layout, 'V', nda::default_accessor, nda::borrowed<>>;
111 return vector_view_t{C_stride_layout::mapping<1>{{dim}, {stride}}, m.data()};
112 }
113
114 /**
115 * @brief Get a new nda::matrix with the given values on the diagonal.
116 *
117 * @tparam V nda::ArrayOfRank<1> or `std::ranges::contiguous_range` type.
118 * @param v 1-dimensional array/view/container containing the diagonal values.
119 * @return nda::matrix with the given values on the diagonal.
120 */
121 template <typename V>
122 requires(std::ranges::contiguous_range<V> or ArrayOfRank<V, 1>)
123 ArrayOfRank<2> auto diag(V const &v) {
124 if constexpr (std::ranges::contiguous_range<V>) {
125 return diag(nda::basic_array_view{v});
126 } else {
127 auto m = matrix<std::remove_const_t<typename V::value_type>>::zeros({v.size(), v.size()});
128 diagonal(m) = v;
129 return m;
130 }
131 }
132
133 /**
134 * @brief Stack two 2-dimensional arrays/views vertically.
135 *
136 * @details This is a more restricted implementation then nda::concatenate. It is only for 2D arrays/views.
137 *
138 * Given a an array A of size `n x q` and an array B of size `p x q`, the function returns a new array C of size
139 * `(n + p) x q` such that `C(range(0, n), range::all) == A` and `C(range(n, n + p), range::all) == B` is true.
140 *
141 * @tparam A nda::ArrayOfRank<2> type.
142 * @tparam B nda::ArrayOfRank<2> type.
143 * @param a 2-dimensional array/view.
144 * @param b 2-dimensional array/view.
145 * @return A new 2-dimensional array/view with the two arrays stacked vertically.
146 */
147 template <ArrayOfRank<2> A, ArrayOfRank<2> B>
148 requires(std::same_as<get_value_t<A>, get_value_t<B>>) // NB the get_value_t gets rid of const if any
149 matrix<get_value_t<A>> vstack(A const &a, B const &b) {
150 static_assert(get_rank<A> == 2, "Error in nda::vstack: Only rank 2 arrays/views are allowed");
151 static_assert(get_rank<A> == 2, "Error in nda::vstack: Only rank 2 arrays/views are allowed");
152 EXPECTS_WITH_MESSAGE(a.shape()[1] == b.shape()[1], "Error in nda::vstack: The second dimension of the two matrices must be equal");
153
154 auto [n, q] = a.shape();
155 auto p = b.shape()[0];
156 matrix<get_value_t<A>> res(n + p, q);
157 res(range(0, n), range::all) = a;
158 res(range(n, n + p), range::all) = b;
159 return res;
160 }
161
162 /** @} */
163
164} // namespace nda
A generic view of a multi-dimensional array.
idx_map(std::array< long, Rank > const &shape, std::array< long, Rank > const &strides) noexcept(!check_stride_order)
Construct a new map from a given shape and strides.
Definition idx_map.hpp:374
auto eye(Int dim)
Create an identity nda::matrix with ones on the diagonal.
ArrayOfRank< 1 > auto diagonal(M &m)
Get a view of the diagonal of a 2-dimensional array/view.
ArrayOfRank< 2 > auto diag(V const &v)
Get a new nda::matrix with the given values on the diagonal.
matrix< get_value_t< A > > vstack(A const &a, B const &b)
Stack two 2-dimensional arrays/views vertically.
auto trace(M const &m)
Get the trace of a 2-dimensional square array/view.
ArrayOfRank< 2 > auto dagger(M const &m)
Get the conjugate transpose of 2-dimensional array/view.
#define EXPECTS(X)
Definition macros.hpp:59
#define EXPECTS_WITH_MESSAGE(X,...)
Definition macros.hpp:75
Strided (non-contiguous) layout policy with C-order (row-major order).
Definition policies.hpp:79
Memory policy using an nda::mem::handle_borrowed.
Definition policies.hpp:108
Default accessor for various array and view types.
Definition accessors.hpp:36