Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
QR_decomp.h
Go to the documentation of this file.
1/*
2 This file is part of the Ansel project.
3 Copyright (C) 2023 Davide Patria.
4
5 Ansel is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 Ansel is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with Ansel. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19#ifndef DT_MATH_QR_DECOMP_H
20#define DT_MATH_QR_DECOMP_H
21
31#include <math.h>
32#include <stdio.h>
33
48inline void QR_dec(double *A, double *Q, double *R, int rows, int cols)
49{
50 // The function decomposes the input matrix A into the matrices Q and R: one
51 // simmetric, one orthonormal and one upper triangular, by using the
52 // Gram-Schmidt method. The input matrice A is defined as A[rows][cols], so
53 // are the output matrices Q and R. This function is meant to be used in the
54 // polar decomposition algorithm and has been tested with different sizes of
55 // input matrices. Supposedly the algorithm works with any matrix, as long as
56 // the columns vectors are independent.
57 //
58 // For tests for the standalone function please refer to the original github
59 // repo this has been developed in.
60 // https://github.com/DavidePatria/QR_decomposition_C/blob/main/README.md
61
62 // As already mentioned in the README the matrices orders are: A mxn => Q mxn
63 // , R nxn and rank(A) must be n The matrix A[m x n] = [A_00, A_01, ... A_0n;
64 // ...... ; A_m0, ... , A_mn] can be accessed as a vector that has all its
65 // rows consecutively written in a long vector, even if passed as a *A and
66 // defined as A[m][n].
67 //
68 // If A(mxn) has m<n the function still returs R(mxn) and Q(nxn), but it is
69 // enough to get the submatrices Q(mxm) and R(mxn) as a valid decomposition.
70 // This is what also octave does.
71
72 // vectors for internal coputations
73 double T[rows];
74 double S[rows];
75 double norm;
76 int i, ii, j, jj, k, kk;
77 double r;
78
79 for(i = 0; i < cols; i++)
80 {
81 printf("\n");
82
83 // scrolling a column and copying it
84 for(ii = 0; ii < rows; ii++)
85 {
86 Q[ii * cols + i] = A[ii * cols + i];
87 }
88
89 for(j = 0; j < i; j++)
90 {
91
92 // copying columns into auxiliary variables
93 for(jj = 0; jj < rows; jj++)
94 {
95 T[jj] = Q[cols * jj + j];
96 S[jj] = A[cols * jj + i];
97 }
98
99 // temporary storing T*K in r
100 r = 0;
101 for(k = 0; k < rows; k++)
102 {
103 r += T[k] * S[k];
104 }
105
106 // setting R[j][i] to r
107 R[cols * j + i] = r;
108
109 for(kk = 0; kk < rows; kk++)
110 {
111 // multiplying vector T by r
112 T[kk] *= r;
113 // subtract T[kk] from i-th column of Q
114 Q[cols * kk + i] -= T[kk];
115 }
116 }
117
118 // rezeroing norm at each cycle
119 norm = 0;
120 // norm of the i-th column
121 for(k = 0; k < rows; k++)
122 {
123 // computing norm^2
124 norm += Q[cols * k + i] * Q[cols * k + i];
125 }
126 norm = sqrt(norm);
127
128 // assigning i-th element of R diagonal
129 R[cols * i + i] = norm;
130
131 for(k = 0; k < rows; k++)
132 {
133 Q[cols * k + i] /= R[cols * i + i];
134 }
135 }
136}
137
138#endif // DT_MATH_QR_DECOMP_H
void QR_dec(double *A, double *Q, double *R, int rows, int cols)
Decompose a dense matrix into an orthonormal basis and an upper-triangular factor.
Definition QR_decomp.h:48
#define A(y, x)
#define S(V, params)
float *const restrict const size_t k
#define R
const float r