-
Notifications
You must be signed in to change notification settings - Fork 1
/
QR_decomp.h
83 lines (70 loc) · 2.42 KB
/
QR_decomp.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <math.h>
#include <stdio.h>
inline void QR_dec(double *A, double *Q, double *R, int rows, int cols) {
// The function decomposes the input matrix A into the matrices Q and R: one
// simmetric, one orthonormal and one upper triangular, by using the
// Gram-Schmidt method. The input matrice A is defined as A[rows][cols], so
// are the output matrices Q and R. This function is meant to be used in the
// polar decomposition algorithm and has been tested with different sizes of
// input matrices. Supposedly the algorithm works with any matrix, as long as
// the columns vectors are independent.
//
// For tests for the standalone function please refer to the original github
// repo this has been developed in.
// https://github.com/DavidePatria/QR_decomposition_C/blob/main/README.md
// As already mentioned in the README the matrices orders are: A mxn => Q mxn
// , R nxn and rank(A) must be n The matrix A[m x n] = [A_00, A_01, ... A_0n;
// ...... ; A_m0, ... , A_mn] can be accessed as a vector that has all its
// rows consecutively written in a long vector, even if passed as a *A and
// defined as A[m][n].
//
// If A(mxn) has m<n the function still returs R(mxn) and Q(nxn), but it is
// enough to get the submatrices Q(mxm) and R(mxn) as a valid decomposition.
// This is what also octave does.
// vectors for internal coputations
double T[rows];
double S[rows];
double norm;
int i, ii, j, jj, k, kk;
double r;
for (i = 0; i < cols; i++) {
printf("\n");
// scrolling a column and copying it
for (ii = 0; ii < rows; ii++) {
Q[ii * cols + i] = A[ii * cols + i];
}
for (j = 0; j < i; j++) {
// copying columns into auxiliary variables
for (jj = 0; jj < rows; jj++) {
T[jj] = Q[cols * jj + j];
S[jj] = A[cols * jj + i];
}
// temporary storing T*K in r
r = 0;
for (k = 0; k < rows; k++) {
r += T[k] * S[k];
}
// setting R[j][i] to r
R[cols * j + i] = r;
for (kk = 0; kk < rows; kk++) {
// multiplying vector T by r
T[kk] *= r;
// subtract T[kk] from i-th column of Q
Q[cols * kk + i] -= T[kk];
}
}
// rezeroing norm at each cycle
norm = 0;
// norm of the i-th column
for (k = 0; k < rows; k++) {
// computing norm^2
norm += Q[cols * k + i] * Q[cols * k + i];
}
norm = sqrt(norm);
// assigning i-th element of R diagonal
R[cols * i + i] = norm;
for (k = 0; k < rows; k++) {
Q[cols * k + i] /= R[cols * i + i];
}
}
}