PLUTO
math_qr_decomp.c
Go to the documentation of this file.
1 /* ///////////////////////////////////////////////////////////////////// */
2 /*!
3  \file
4  \brief Functions for QR decomposition and matrix inversion.
5  \author B. Vaidya (bvaidya@unito.it)
6  \date September 11, 2014
7 */
8 /* ///////////////////////////////////////////////////////////////////// */
9 #include "pluto.h"
10 
11 /* ******************************************** */
12 void RSolve(double **a, int n, double *d, double *b){
13 /*
14  * Solves set of n Linear Equations. R.x = b.
15  * Where is R is upper Triangular Matrix stored in a
16  * and d. The matrix a and vector d are outputs from
17  * QRDecompse and b[] is the input vector.
18  *
19  ********************************************* */
20  int i,j;
21  double sum;
22 
23  b[n-1] /= d[n-1];
24  for(i=n-2;i>=0;i--){
25  sum = 0.0;
26  for (j = i+1; j < n; j++){
27  sum += a[i][j]*b[j];
28  }
29  b[i] = (b[i] - sum)/d[i];
30  }
31 }
32 
33 /* ********************************************************************* */
34 void QRDecompose (double **a, int n, double *c, double *d, int *sing)
35 /*
36  * Perform QR decomposition of matrix a. The upper Triangular matrix R
37  * is returned in a except the diagonal elements which are stored in array d.
38  * The orthogonal matrix Q is represented as a product of n-1 Householder
39  * matrices. Qj = 1.0 - uj \cross uj/cj, where the non-zero components of uj
40  * are returned in a[i][j].
41  * sing returns 1 if there is singularity else on normal exist it returns 0.
42  *
43  *********************************************************************** */
44 {
45  int i, j, k;
46  double scale, sigma, sum, tau, temp;
47 
48  *sing = 0;
49  for (k = 0; k < n-1; k++) {
50  scale = 0.0;
51  for (i = k; i < n; i++){
52  if ((temp = fabs (a[i][k])) > scale)
53  scale = temp;
54  }
55 
56  if (scale == 0.0) {
57  *sing = 1;
58  c[k] = d[k] = 0.0;
59  }else{
60  for (i = k; i < n; i++){
61  a[i][k] /= scale;
62  }
63  sum = 0.0;
64  for (i = k; i < n; i++) {
65  sum += a[i][k] * a[i][k];
66  }
67 
68  if (a[k][k] >= 0){
69  sigma = fabs(sqrt(sum));
70  }else{
71  sigma = -fabs(sqrt(sum));
72  }
73 
74  a[k][k] += sigma;
75  c[k] = sigma*a[k][k];
76  d[k] = -sigma*scale;
77  for (j=k+1;j< n;j++){
78  sum = 0.0;
79  for (i = k; i < n; i++) {
80  sum += a[i][k] * a[i][j];
81  }
82  tau = sum /c[k];
83  for (i = k; i < n; i++) {
84  a[i][j] -= tau * a[i][k];
85  }
86  }
87  }
88  }
89  d[n-1] = a[n-1][n-1];
90  if (d[n-1] == 0.0) *sing = 1;
91 }
92 
93 
94 
95 
96 /* ******************************************** */
97 void QRSolve(double **a, int n, double *c, double *d, double *b){
98 /*
99  * Solves set of n Linear Equations. A.x = b.
100  * The matrix a[4][4] and vector d are outputs from
101  * QRDecompse, thus they represent the fractured R matrix
102  * and b[] is the input RHS vector.
103  *
104  ********************************************* */
105  int i, j;
106  double sum, tau;
107  for(j=0;j<n-1;j++){ /* Form Q^T . b */
108  sum = 0.0;
109  for(i=j;i<n;i++){
110  sum += a[i][j]*b[i];
111  }
112  tau = sum/c[j];
113  for(i=j;i<n;i++){
114  b[i] -= tau*a[i][j];
115  }
116  }
117  RSolve(a, n, d, b);
118 }
119 
120 /* ******************************************** */
121 void QRUpdate(double **r, double **qt, int n, double *u, double *v){
122 /*
123  * Solves set of n Linear Equations. R.x = b.
124  * Where is R is upper Triangular Matrix stored in a
125  * and d. The matrix a and vector d are outputs from
126  * QRDecompse and b[] is the input vector.
127  *
128  ********************************************* */
129 int i, j, k;
130 for (k=n-1;k>=0;k--){ /* Find largest k such that u[k] neq 0 */
131  if (u[k]) break;
132 }
133 
134 for (i = k-1; i>=0; i--){
135  rotate(r,qt, n, i, u[i], -u[i+1]);
136  if (u[i] == 0.0) u[i] = fabs(u[i+1]);
137  else if (fabs(u[i]) > fabs(u[i+1]))
138  u[i] = fabs(u[i])*sqrt(1.0 + (u[i+1]/u[i])*(u[i+1]/u[i]));
139  else
140  u[i] = fabs(u[i+1])*sqrt(1.0 + (u[i]/u[i+1])*(u[i]/u[i+1]));
141 }
142 
143 for (j=0;j<n; j++) r[0][j] += u[0]*v[j];
144 for (i=0;i<k; i++)
145  rotate(r,qt,n,i,r[i][i], -r[i+1][i]);
146 }
147 
148 /* ******************************************** */
149 void rotate(double **r, double **qt, int n, int i, double a, double b){
150 /*
151  * Jacobi rotation.
152  *
153  ********************************************* */
154 int j;
155 double c, s, w, y, fact;
156 
157 if (a == 0.0){
158  c = 0.0;
159  s = (b >= 0.0 ? 1.0 : -1.0);
160  }else if (fabs(a) > fabs(b)){
161  fact = b/a;
162  if (a >= 0.0){
163  c = fabs(1.0/sqrt(1.0 + (fact*fact)));
164  }else{
165  c = -fabs(1.0/sqrt(1.0 + (fact*fact)));
166  }
167  s = fact * c;
168  }else{
169  fact = a/b;
170  if (b >= 0.0) {
171  s = fabs(1.0/sqrt(1.0 + (fact*fact)));
172  }else {
173  s = -fabs(1.0/sqrt(1.0 + (fact*fact)));
174  }
175  c = fact * s;
176  }
177 
178 for (j=i;j<n;j++){
179  y = r[i][j];
180  w = r[i+1][j];
181  r[i][j] = c*y - s*w;
182  r[i+1][j] = s*y + c*w;
183 }
184 
185 for (j=0;j<n;j++){
186  y = qt[i][j];
187  w = qt[i+1][j];
188  qt[i][j] = c*y - s*w;
189  qt[i+1][j] = s*y + c*w;
190 }
191 
192 }
193 
194 
static double a
Definition: init.c:135
void QRDecompose(double **a, int n, double *c, double *d, int *sing)
static int n
Definition: analysis.c:3
void rotate(double **r, double **qt, int n, int i, double a, double b)
void QRUpdate(double **r, double **qt, int n, double *u, double *v)
void RSolve(double **a, int n, double *d, double *b)
int j
Definition: analysis.c:2
int k
Definition: analysis.c:2
void QRSolve(double **a, int n, double *c, double *d, double *b)
tuple c
Definition: menu.py:375
#define s
PLUTO main header file.
int i
Definition: analysis.c:2