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
28#include <math.h>
29#include <stdio.h>
30
45inline void QR_dec(double *A, double *Q, double *R, int rows, int cols)
46{
47 // The function decomposes the input matrix A into the matrices Q and R: one
48 // simmetric, one orthonormal and one upper triangular, by using the
49 // Gram-Schmidt method. The input matrice A is defined as A[rows][cols], so
50 // are the output matrices Q and R. This function is meant to be used in the
51 // polar decomposition algorithm and has been tested with different sizes of
52 // input matrices. Supposedly the algorithm works with any matrix, as long as
53 // the columns vectors are independent.
54 //
55 // For tests for the standalone function please refer to the original github
56 // repo this has been developed in.
57 // https://github.com/DavidePatria/QR_decomposition_C/blob/main/README.md
58
59 // As already mentioned in the README the matrices orders are: A mxn => Q mxn
60 // , R nxn and rank(A) must be n The matrix A[m x n] = [A_00, A_01, ... A_0n;
61 // ...... ; A_m0, ... , A_mn] can be accessed as a vector that has all its
62 // rows consecutively written in a long vector, even if passed as a *A and
63 // defined as A[m][n].
64 //
65 // If A(mxn) has m<n the function still returs R(mxn) and Q(nxn), but it is
66 // enough to get the submatrices Q(mxm) and R(mxn) as a valid decomposition.
67 // This is what also octave does.
68
69 // vectors for internal coputations
70 double T[rows];
71 double S[rows];
72 double norm;
73 int i, ii, j, jj, k, kk;
74 double r;
75
76 for(i = 0; i < cols; i++)
77 {
78 printf("\n");
79
80 // scrolling a column and copying it
81 for(ii = 0; ii < rows; ii++)
82 {
83 Q[ii * cols + i] = A[ii * cols + i];
84 }
85
86 for(j = 0; j < i; j++)
87 {
88
89 // copying columns into auxiliary variables
90 for(jj = 0; jj < rows; jj++)
91 {
92 T[jj] = Q[cols * jj + j];
93 S[jj] = A[cols * jj + i];
94 }
95
96 // temporary storing T*K in r
97 r = 0;
98 for(k = 0; k < rows; k++)
99 {
100 r += T[k] * S[k];
101 }
102
103 // setting R[j][i] to r
104 R[cols * j + i] = r;
105
106 for(kk = 0; kk < rows; kk++)
107 {
108 // multiplying vector T by r
109 T[kk] *= r;
110 // subtract T[kk] from i-th column of Q
111 Q[cols * kk + i] -= T[kk];
112 }
113 }
114
115 // rezeroing norm at each cycle
116 norm = 0;
117 // norm of the i-th column
118 for(k = 0; k < rows; k++)
119 {
120 // computing norm^2
121 norm += Q[cols * k + i] * Q[cols * k + i];
122 }
123 norm = sqrt(norm);
124
125 // assigning i-th element of R diagonal
126 R[cols * i + i] = norm;
127
128 for(k = 0; k < rows; k++)
129 {
130 Q[cols * k + i] /= R[cols * i + i];
131 }
132 }
133}
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:45
#define A(y, x)
Definition colorspaces.c:186
const float i
Definition colorspaces_inline_conversions.h:440
#define S(V, params)
Definition common/histogram.c:36
float *const restrict const size_t k
Definition luminance_mask.h:78
#define R
const float r
Definition src/develop/noise_generator.h:101