TheAlgorithms/C++ 1.0.0
All the algorithms implemented in C++
Loading...
Searching...
No Matches
qr_decompose.h
Go to the documentation of this file.
1
9#ifndef NUMERICAL_METHODS_QR_DECOMPOSE_H_
10#define NUMERICAL_METHODS_QR_DECOMPOSE_H_
11
12#include <cmath>
13#include <cstdlib>
14#include <iomanip>
15#include <iostream>
16#include <limits>
17#include <numeric>
18#include <valarray>
19#ifdef _OPENMP
20#include <omp.h>
21#endif
22
28namespace qr_algorithm {
32template <typename T>
33std::ostream &operator<<(std::ostream &out,
34 std::valarray<std::valarray<T>> const &v) {
35 const int width = 12;
36 const char separator = ' ';
37
38 out.precision(4);
39 for (size_t row = 0; row < v.size(); row++) {
40 for (size_t col = 0; col < v[row].size(); col++)
41 out << std::right << std::setw(width) << std::setfill(separator)
42 << v[row][col];
43 out << std::endl;
44 }
45
46 return out;
47}
48
52template <typename T>
53std::ostream &operator<<(std::ostream &out, std::valarray<T> const &v) {
54 const int width = 10;
55 const char separator = ' ';
56
57 out.precision(4);
58 for (size_t row = 0; row < v.size(); row++) {
59 out << std::right << std::setw(width) << std::setfill(separator)
60 << v[row];
61 }
62
63 return out;
64}
65
75template <typename T>
76inline double vector_dot(const std::valarray<T> &a, const std::valarray<T> &b) {
77 return (a * b).sum();
78 // could also use following
79 // return std::inner_product(std::begin(a), std::end(a), std::begin(b),
80 // 0.f);
81}
82
91template <typename T>
92inline double vector_mag(const std::valarray<T> &a) {
93 double dot = vector_dot(a, a);
94 return std::sqrt(dot);
95}
96
103template <typename T>
104std::valarray<T> vector_proj(const std::valarray<T> &a,
105 const std::valarray<T> &b) {
106 double num = vector_dot(a, b);
107 double deno = vector_dot(b, b);
108
110 if (deno <= std::numeric_limits<double>::epsilon()) {
111 std::cerr << "[" << __func__ << "] Possible division by zero\n";
112 return a; // return vector a back
113 }
114
115 double scalar = num / deno;
116
117 return b * scalar;
118}
119
145template <typename T>
147 const std::valarray<std::valarray<T>> &A,
148 std::valarray<std::valarray<T>> *Q,
149 std::valarray<std::valarray<T>> *R
150) {
151 std::size_t ROWS = A.size(); // number of rows of A
152 std::size_t COLUMNS = A[0].size(); // number of columns of A
153 std::valarray<T> col_vector(ROWS);
154 std::valarray<T> col_vector2(ROWS);
155 std::valarray<T> tmp_vector(ROWS);
156
157 for (int i = 0; i < COLUMNS; i++) {
158 /* for each column => R is a square matrix of NxN */
159 int j;
160 R[0][i] = 0.; /* make R upper triangular */
161
162 /* get corresponding Q vector */
163#ifdef _OPENMP
164// parallelize on threads
165#pragma omp for
166#endif
167 for (j = 0; j < ROWS; j++) {
168 tmp_vector[j] = A[j][i]; /* accumulator for uk */
169 col_vector[j] = A[j][i];
170 }
171 for (j = 0; j < i; j++) {
172 for (int k = 0; k < ROWS; k++) {
173 col_vector2[k] = Q[0][k][j];
174 }
175 col_vector2 = vector_proj(col_vector, col_vector2);
176 tmp_vector -= col_vector2;
177 }
178
179 double mag = vector_mag(tmp_vector);
180
181#ifdef _OPENMP
182// parallelize on threads
183#pragma omp for
184#endif
185 for (j = 0; j < ROWS; j++) Q[0][j][i] = tmp_vector[j] / mag;
186
187 /* compute upper triangular values of R */
188#ifdef _OPENMP
189// parallelize on threads
190#pragma omp for
191#endif
192 for (int kk = 0; kk < ROWS; kk++) {
193 col_vector[kk] = Q[0][kk][i];
194 }
195
196#ifdef _OPENMP
197// parallelize on threads
198#pragma omp for
199#endif
200 for (int k = i; k < COLUMNS; k++) {
201 for (int kk = 0; kk < ROWS; kk++) {
202 col_vector2[kk] = A[kk][k];
203 }
204 R[0][i][k] = (col_vector * col_vector2).sum();
205 }
206 }
207}
208} // namespace qr_algorithm
209
210#endif // NUMERICAL_METHODS_QR_DECOMPOSE_H_
Functions to compute QR decomposition of any rectangular matrix.
std::valarray< T > vector_proj(const std::valarray< T > &a, const std::valarray< T > &b)
void qr_decompose(const std::valarray< std::valarray< T > > &A, std::valarray< std::valarray< T > > *Q, std::valarray< std::valarray< T > > *R)
double vector_dot(const std::valarray< T > &a, const std::valarray< T > &b)
double vector_mag(const std::valarray< T > &a)
std::ostream & operator<<(std::ostream &out, std::valarray< std::valarray< T > > const &v)