Skip to content

Commit e71dc91

Browse files
committed
linalg : symmetric_matrix_rank_1_updateを追加 (#1233)
Signed-off-by: Yuya Asano <64895419+sukeya@users.noreply.github.com>
1 parent 17a5018 commit e71dc91

File tree

2 files changed

+247
-1
lines changed

2 files changed

+247
-1
lines changed

reference/linalg.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ BLAS 1, 2, 3のアルゴリズムでテンプレートパラメータが特に
8888
| [`triangular_matrix_vector_solve`](linalg/triangular_matrix_vector_solve.md) | xTRSV: 三角行列を係数とする行列方程式を解く (function template) | C++26 |
8989
| [`matrix_rank_1_update`](linalg/matrix_rank_1_update.md) | xGER, xGERU: 行列のRank-1更新 (function template) | C++26 |
9090
| [`matrix_rank_1_update_c`](linalg/matrix_rank_1_update_c.md) | xGERC: 複素行列のRank-1更新 (function template) | C++26 |
91-
| `symmetric_matrix_rank_1_update` | xSYR: 対称行列のRank-1更新 (function template) | C++26 |
91+
| [`symmetric_matrix_rank_1_update`](linalg/symmetric_matrix_rank_1_update.md) | xSYR: 対称行列のRank-1更新 (function template) | C++26 |
9292
| `hermitian_matrix_rank_1_update` | xHER: ハミルトニアン行列のRank-1更新 (function template) | C++26 |
9393
| `symmetric_matrix_rank_2_update` | xSYR2: 対称行列のRank-2更新 (function template) | C++26 |
9494
| `hermitian_matrix_rank_2_update` | xHER2: ハミルトニアン行列のRank-2更新 (function template) | C++26 |
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
# symmetric_matrix_rank_1_update
2+
3+
4+
* [mathjax enable]
5+
* linalg[meta header]
6+
* function template[meta id-type]
7+
* std::linalg[meta namespace]
8+
* cpp26[meta cpp]
9+
10+
11+
```cpp
12+
namespace std::linalg {
13+
template<in-vector InVec,
14+
possibly-packed-inout-matrix InOutMat,
15+
class Triangle>
16+
void symmetric_matrix_rank_1_update(
17+
InVec x,
18+
InOutMat A,
19+
Triangle t); // (1)
20+
21+
template<class ExecutionPolicy,
22+
in-vector InVec,
23+
possibly-packed-inout-matrix InOutMat,
24+
class Triangle>
25+
void symmetric_matrix_rank_1_update(
26+
ExecutionPolicy&& exec,
27+
InVec x,
28+
InOutMat A,
29+
Triangle t); // (2)
30+
31+
template<class Scalar,
32+
in-vector InVec,
33+
possibly-packed-inout-matrix InOutMat,
34+
class Triangle>
35+
void symmetric_matrix_rank_1_update(
36+
Scalar alpha,
37+
InVec x,
38+
InOutMat A,
39+
Triangle t); // (3)
40+
41+
template<class ExecutionPolicy,
42+
class Scalar,
43+
in-vector InVec,
44+
possibly-packed-inout-matrix InOutMat,
45+
class Triangle>
46+
void symmetric_matrix_rank_1_update(
47+
ExecutionPolicy&& exec,
48+
Scalar alpha,
49+
InVec x,
50+
InOutMat A,
51+
Triangle t); // (4)
52+
}
53+
```
54+
55+
56+
## 概要
57+
対称かつ共役を取らないrank-1 updateを対称行列に行う。
58+
引数`t`は対称行列の成分が上三角にあるのか、それとも下三角にあるのかを示す。
59+
60+
- (1): $A \leftarrow A + xx^T$
61+
- (2): (1)を指定された実行ポリシーで実行する。
62+
- (3): $A \leftarrow A + \alpha xx^T$
63+
- (4): (3)を指定された実行ポリシーで実行する。
64+
65+
66+
## 適格要件
67+
- `Triangle`は[`upper_triangle_t`](upper_triangle_t.md)または[`lower_triangle_t`](lower_triangle_t.md)
68+
- `InMat`が[`layout_blas_packed`](layout_blas_packed.md)を持つなら、レイアウトの`Triangle`テンプレート引数とこの関数の`Triangle`テンプレート引数が同じ型
69+
- [`compatible-static-extents`](compatible-static-extents.md)`<decltype(A), decltype(A)>(0, 1)`が`true` (つまり`A`が正方行列であること)
70+
- [`compatible-static-extents`](compatible-static-extents.md)`<decltype(A), decltype(x)>(0, 0)`が`true` (つまり`A`の次元と`x`の次元が同じであること)
71+
72+
73+
## 事前条件
74+
- `A.extent(0) == A.extent(1)`
75+
- `A.extent(0) == x.extent(0)`
76+
77+
78+
## 効果
79+
- (1), (2): $A \leftarrow A + xx^T$
80+
- (3), (4): $A \leftarrow A + \alpha xx^T$
81+
82+
83+
## 戻り値
84+
なし
85+
86+
87+
## 計算量
88+
$O((\verb|x.extent(0)|)^2)$
89+
90+
91+
## 備考
92+
(3), (4)は$A \leftarrow A - xx^T$を行うために用意された。
93+
94+
95+
## 例
96+
**[注意] 処理系にあるコンパイラで確認していないため、間違っているかもしれません。**
97+
98+
```cpp example
99+
#include <array>
100+
#include <iostream>
101+
#include <linalg>
102+
#include <mdspan>
103+
#include <vector>
104+
105+
template <class Matrix>
106+
void print_mat(const Matrix& A) {
107+
for(int i = 0; i < A.extent(0); ++i) {
108+
for(int j = 0; j < i; ++j) {
109+
std::cout << A[j, i] << ' ';
110+
}
111+
for(int j = i; j < A.extent(1) - 1; ++j) {
112+
std::cout << A[i, j] << ' ';
113+
}
114+
std::cout << A[i, A.extent(1) - 1] << '\n';
115+
}
116+
}
117+
118+
template <class Vector>
119+
void init_vec(Vector& v) {
120+
for (int i = 0; i < v.extent(0); ++i) {
121+
v[i] = i;
122+
}
123+
}
124+
125+
template <class Matrix>
126+
void init_mat(Matrix& A) {
127+
for(int i = 0; i < A.extent(0); ++i) {
128+
for(int j = i; j < A.extent(1); ++j) {
129+
A[i,j] = A.extent(1) * i + j;
130+
}
131+
}
132+
}
133+
134+
int main()
135+
{
136+
constexpr size_t N = 4;
137+
138+
std::vector<double> A_vec(N * N);
139+
std::vector<double> x_vec(N);
140+
std::array<double, N> y_vec;
141+
142+
std::mdspan<
143+
double,
144+
std::extents<size_t, N, N>,
145+
std::linalg::layout_blas_packed<
146+
std::linalg::upper_triangle_t,
147+
std::linalg::row_major_t>
148+
> A(A_vec.data());
149+
std::mdspan x(x_vec.data(), N);
150+
std::mdspan y(y_vec.data(), N);
151+
152+
init_mat(A);
153+
init_vec(x);
154+
init_vec(y);
155+
156+
// (1)
157+
std::cout << "(1)\n";
158+
std::linalg::matrix_rank_1_update(
159+
x,
160+
A,
161+
std::linalg::upper_triangle);
162+
print_mat(A);
163+
164+
// (2)
165+
init_mat(A);
166+
std::cout << "(2)\n";
167+
std::linalg::matrix_rank_1_update(
168+
std::execution::par,
169+
x,
170+
A,
171+
std::linalg::upper_triangle);
172+
print_mat(A);
173+
174+
// (3)
175+
init_mat(A);
176+
std::cout << "(3)\n";
177+
std::linalg::matrix_rank_1_update(
178+
-1.0,
179+
x,
180+
A,
181+
std::linalg::upper_triangle);
182+
print_mat(A);
183+
184+
// (4)
185+
init_mat(A);
186+
std::cout << "(4)\n";
187+
std::linalg::matrix_rank_1_update(
188+
std::execution::par,
189+
-1.0,
190+
x,
191+
A,
192+
std::linalg::upper_triangle);
193+
print_mat(A);
194+
195+
return 0;
196+
}
197+
```
198+
199+
200+
### 出力
201+
```
202+
(1)
203+
0 1 2 3
204+
1 6 8 10
205+
2 8 14 17
206+
3 14 17 24
207+
(2)
208+
0 1 2 3
209+
1 6 8 10
210+
2 8 14 17
211+
3 14 17 24
212+
(3)
213+
0 1 2 3
214+
1 4 4 4
215+
2 4 6 5
216+
3 4 5 6
217+
(4)
218+
0 1 2 3
219+
1 4 4 4
220+
2 4 6 5
221+
3 4 5 6
222+
```
223+
224+
225+
## バージョン
226+
### 言語
227+
- C++26
228+
229+
### 処理系
230+
- [Clang](/implementation.md#clang): ??
231+
- [GCC](/implementation.md#gcc): ??
232+
- [ICC](/implementation.md#icc): ??
233+
- [Visual C++](/implementation.md#visual_cpp): ??
234+
235+
236+
## 関連項目
237+
- [`execution`](/reference/execution.md)
238+
- [`mdspan`](/reference/mdspan.md)
239+
- [`upper_triangle_t`](upper_triangle_t.md)
240+
- [`lower_triangle_t`](lower_triangle_t.md)
241+
242+
243+
## 参照
244+
- [P1673R13 A free function linear algebra interface based on the BLAS](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p1673r13.html)
245+
- [LAPACK: {he,sy}r: Hermitian/symmetric rank-1 update](https://netlib.org/lapack/explore-html/dc/d82/group__her.html)
246+

0 commit comments

Comments
 (0)