TPCCLIB
Loading...
Searching...
No Matches
qrlsq.c
Go to the documentation of this file.
1
6/*****************************************************************************/
7#include "tpcclibConfig.h"
8/*****************************************************************************/
9#include <stdio.h>
10#include <stdlib.h>
11#include <math.h>
12/*****************************************************************************/
13#include "tpcextensions.h"
14/*****************************************************************************/
15#include "tpclinopt.h"
16/*****************************************************************************/
17
18/*****************************************************************************/
20/* Local functions */
21int qr_get_next_col(
22 double **mat, const unsigned int rows, const unsigned int cols,
23 unsigned int row_pos, unsigned int *p, unsigned int *max_loc
24);
25void qr_swap_cols(
26 unsigned int *p, const unsigned int i, const unsigned int j
27);
28void qr_householder(
29 double **mat, const unsigned int rows, const unsigned int cols,
30 const unsigned int row_pos, const unsigned int col_pos, double *result
31);
32void qr_apply_householder(
33 double **mat, double *rhs, const unsigned int rows, const unsigned int cols,
34 double *house, const unsigned int row_pos, unsigned int *p
35);
36void qr_back_solve(
37 double **mat, double *rhs, const unsigned int rows, const unsigned int cols,
38 double *sol, unsigned int *p
39);
40
41
42
43int qr_QTvec(
44 int M, int N, double **QR, double *tau, double *v, double *help
45);
46int qr_Qvec(
47 int M, int N, double **QR, double *tau, double *v, double *help
48);
49int qr_invRvec(
50 int N, double **A, double *X
51);
53/*****************************************************************************/
54
55/*****************************************************************************/
74 double **mat,
77 double *rhs,
80 double *sol,
82 const unsigned int rows,
84 const unsigned int cols,
87 double *r2
88) {
89 if(rows<1 || cols<1) return(1);
90 if(mat==NULL || rhs==NULL || sol==NULL) return(2);
91
92 unsigned int i, j, max_loc;
93 unsigned int *p=NULL;
94 double *buf=NULL, *ptr, *v=NULL, *orig_b=NULL, **A=NULL;
95
96 /* Allocate memory for index vector and Householder transform vector */
97 /* and original data matrix and vector. */
98 p=malloc(sizeof(unsigned int)*cols);
99 A=malloc(sizeof(double*)*rows);
100 buf=malloc(sizeof(double)*(rows*cols+rows+rows));
101 if(p==NULL || A==NULL || buf==NULL) {
102 free(p); free(A); free(buf);
103 return(3);
104 }
105 ptr=buf;
106 for(i=0; i<rows; i++) {A[i]=ptr; ptr+=cols;}
107 v=ptr; ptr+=rows; orig_b=ptr;
108 /* copy the original data */
109 for(i=0; i<rows; i++) {
110 orig_b[i]=rhs[i];
111 for(j=0; j<cols; j++) A[i][j]=mat[i][j];
112 }
113
114 /* Initial permutation vector. */
115 for(i=0; i<cols; i++) p[i]=i;
116
117 /* Apply rotators to make R and Q'*b */
118 for(i=0; i<cols; i++) {
119 if(qr_get_next_col(A, rows, cols, i, p, &max_loc)==0)
120 qr_swap_cols(p, i, max_loc);
121 qr_householder(A, rows, cols, i, p[i], v);
122 qr_apply_householder(A, rhs, rows, cols, v, i, p);
123 }
124
125 /* Back solve Rx = Q'*b */
126 qr_back_solve(A, rhs, rows, cols, sol, p);
127
128 /* Compute fitted b[] (matrix-vector product A*x) using non-modified A */
129 for(i=0; i<rows; i++) {
130 rhs[i]=0.0;
131 for(j=0; j<cols; j++) rhs[i]+=mat[i][j]*sol[j];
132 }
133
134 /* Compute R^2, if requested */
135 if(r2!=NULL) {
136 double ss=0, d;
137 for(i=0; i<rows; i++) {
138 d=orig_b[i]-rhs[i];
139 ss+=d*d;
140 }
141 *r2=ss;
142 }
143
144 /* Collect garbage. */
145 free(p); free(A); free(buf);
146 return(0);
147}
148
150
153#if(1) // Version without memory allocation by VO
154int qr_get_next_col(
156 double **mat,
158 const unsigned int rows,
160 const unsigned int cols,
162 const unsigned int row_pos,
164 unsigned int *p,
166 unsigned int *max_loc
167) {
168 if(mat==NULL || rows<1 || cols<1 || p==NULL) return(-1);
169
170 unsigned int i, j, maxloc;
171 double col_norm, max_norm;
172
173 // Compute the norms of the sub columns and find the maximum
174 max_norm=DBL_MIN; maxloc=0;
175 for(j=0; j<cols; j++) {
176 col_norm=0;
177 for(i=row_pos; i<rows; i++) col_norm+=mat[i][p[j]]*mat[i][p[j]];
178 if(col_norm>max_norm) {max_norm=col_norm; maxloc=j;}
179 }
180 if(max_norm!=DBL_MIN) {
181 if(max_loc!=NULL) *max_loc=maxloc;
182 return(0);
183 }
184 return(1);
185}
186
187#else
188
189int qr_get_next_col(
191 double **mat,
193 const unsigned int rows,
195 const unsigned int cols,
197 const unsigned int row_pos,
199 unsigned int *p,
201 unsigned int *max_loc
202) {
203 if(mat==NULL || rows<1 || cols<1 || p==NULL) return(-1);
204
205 unsigned int i, j, maxloc;
206 double *col_norms;
207 double max;
208
209 col_norms=malloc(sizeof(double)*cols);
210
211 // Compute the norms of the sub columns.
212 for(j=0; j<cols; j++) {
213 col_norms[j]=0;
214 for(i=row_pos; i<rows; i++) col_norms[j]+=mat[i][p[j]]*mat[i][p[j]];
215 }
216
217 // Find the maximum location.
218 max=DBL_MIN; maxloc=0;
219 for(i=0; i<cols; i++)
220 if(col_norms[i]>max) {max=col_norms[i]; maxloc=i;}
221
222 // Collect garbage and return.
223 free(col_norms);
224 if(max!=DBL_MIN) {
225 if(max_loc!=NULL) *max_loc=maxloc;
226 return(0);
227 }
228 return(1);
229}
230#endif
231
233void qr_swap_cols(unsigned int *p, const unsigned int i, const unsigned int j)
234{
235 unsigned int temp;
236 temp=p[i]; p[i]=p[j]; p[j]=temp;
237}
238
240void qr_householder(
242 double **mat,
244 const unsigned int rows,
246 const unsigned int cols,
248 const unsigned int row_pos,
250 const unsigned int col_pos,
252 double *result
253) {
254 if(rows<1 || cols<1 || mat==NULL || result==NULL) return;
255
256 unsigned int i;
257 double norm=0.0;
258
259 for(i=row_pos; i<rows; i++) norm+=mat[i][col_pos]*mat[i][col_pos];
260 if(norm==0.0) return;
261
262 norm=sqrt(norm);
263 result[0]=(mat[row_pos][col_pos]-norm);
264 for(i=1; i<(rows-row_pos); i++) result[i]=mat[i+row_pos][col_pos];
265
266 norm=0.0;
267 for(i=0; i<(rows-row_pos); i++) norm+=result[i]*result[i];
268 if(norm==0) return;
269
270 norm=sqrt(norm);
271 for(i=0; i<(rows-row_pos); i++) result[i]*=(1.0/norm);
272}
273
275void qr_apply_householder(
277 double **mat,
279 double *rhs,
281 const unsigned int rows,
283 const unsigned int cols,
285 double *house,
287 const unsigned int row_pos,
289 unsigned int *p
290) {
291 if(mat==NULL || rhs==NULL || rows<1 || cols<1 || house==NULL || p==NULL) return;
292
293 unsigned int i, j, k, n;
294 double sum;
295 double **hhmat;
296 double **mat_cpy;
297 double *rhs_cpy;
298
299 // Get the dimensions for the Q matrix.
300 n=rows-row_pos;
301
302 // Allocate memory.
303 hhmat=malloc(sizeof(double*)*n);
304 for(i=0; i<n; i++) hhmat[i]=malloc(sizeof(double)*n);
305 mat_cpy=malloc(sizeof(double*)*rows);
306 for(i=0; i<rows; i++) mat_cpy[i]=malloc(sizeof(double)*cols);
307 rhs_cpy=malloc(sizeof(double)*rows);
308
309 // Copy the matrix.
310 for(i=0; i<rows; i++)
311 for(j=0; j<cols; j++)
312 mat_cpy[i][j]=mat[i][j];
313
314 // Copy the right hand side.
315 for(i=0; i<rows; i++) rhs_cpy[i]=rhs[i];
316
317 // Build the Q matrix from the Householder transform.
318 for(j=0; j<n; j++)
319 for(i=0; i<n; i++)
320 if(i!=j) hhmat[i][j]=-2.0*house[j]*house[i];
321 else hhmat[i][j]=1.0-2.0*house[j]*house[i];
322
323 // Multiply by the Q matrix.
324 for(k=0; k<cols; k++)
325 for(j=0; j<n; j++) {
326 sum=0.0;
327 for(i=0; i<n; i++) sum+=hhmat[j][i]*mat_cpy[i+row_pos][p[k]];
328 mat[j+row_pos][p[k]]=sum;
329 }
330
331 // Multiply the rhs by the Q matrix.
332 for(j=0; j<n; j++) {
333 sum=0.0;
334 for(i=0; i<n; i++) sum+=hhmat[i][j]*rhs_cpy[i+row_pos];
335 rhs[j+row_pos]=sum;
336 }
337
338 // Collect garbage.
339 for(i=0; i<(rows-row_pos); i++) free(hhmat[i]);
340 for(i=0; i<rows; i++) free(mat_cpy[i]);
341 free(hhmat);
342 free(mat_cpy);
343 free(rhs_cpy);
344}
345
347void qr_back_solve(
349 double **mat,
351 double *rhs,
353 const unsigned int rows,
355 const unsigned int cols,
357 double *sol,
359 unsigned int *p
360) {
361 if(mat==NULL || rhs==NULL || rows<1 || cols<1 || sol==NULL || p==NULL)
362 return;
363
364 unsigned int i, j, bottom;
365 double sum;
366
367 /* Fill the solution with zeros initially. */
368 for(i=0; i<cols; i++) sol[i]=0.0;
369
370 /* Find the first non-zero row from the bottom and start solving from here. */
371 i=rows-1; bottom=i;
372 while(1) {
373 if(fabs(mat[i][p[cols-1]]) > 2.0*DBL_MIN) {bottom=i; break;}
374 if(i==0) break; else i--;
375 }
376
377 /* Standard back solving routine starting at the first non-zero diagonal. */
378 i=bottom;
379 while(1) {
380 sum=0.0;
381 j=cols-1;
382 while(1) {
383 if(j>i) sum+=sol[p[j]]*mat[i][p[j]];
384 if(j==0) break; else j--;
385 }
386 if(i<cols) { // Added by VO
387 if(mat[i][p[i]] > 2.0*DBL_MIN) sol[p[i]]=(rhs[i]-sum)/mat[i][p[i]];
388 else sol[p[i]]=0.0;
389 }
390 if(i==0) break; else i--;
391 }
392}
394/*****************************************************************************/
395
396/*****************************************************************************/
411int qr(
414 double **A,
416 int m,
418 int n,
420 double *B,
422 double *X,
425 double *rnorm,
428 double *tau,
431 double *res,
433 double **wws,
435 double *ws
436) {
437 int i;
438 double *qrRes, *qrTau, **qrWws, *qrWs, *chain;
439
440 /* Check the parameters and data */
441 if(m<=0 || n<=0 || A==NULL || B==NULL || X==NULL) return(1);
442 if(m<n) return(1);
443
444 /* Allocate memory for working space, if required */
445 if(tau!=NULL) qrTau=tau; else qrTau=(double*)calloc(n, sizeof(double));
446 if(res!=NULL) qrRes=res; else qrRes=(double*)calloc(m, sizeof(double));
447 if(wws!=NULL) {
448 qrWws=wws; chain=(double*)NULL;
449 } else {
450 qrWws=(double**)malloc(m * sizeof(double*));
451 chain=(double*)malloc(m*n * sizeof(double));
452 for(i=0; i<m; i++) qrWws[i]=chain + i*n;
453 }
454 if(ws!=NULL) qrWs=ws; else qrWs=(double*)calloc(2*m, sizeof(double));
455 if(qrTau==NULL || qrRes==NULL || qrWws==NULL || qrWs==NULL) return(1);
456
457 /* Form the householder decomposition and solve the least square problem */
458 if(qr_decomp(A, m, n, qrTau, qrWws, qrWs)) return(2);
459 if(qr_solve(A, m, n, qrTau, B, X, qrRes, rnorm, qrWws, qrWs)) return(3);
460
461 /* Free working space, if it was allocated here */
462 //if(tau==NULL || res==NULL || wws==NULL || ws==NULL) printf("free in qr()\n");
463 if(tau==NULL) free(qrTau);
464 if(res==NULL) free(qrRes);
465 if(wws==NULL) {free(qrWws); free(chain);}
466 if(ws==NULL) free(qrWs);
467 for(i=0; i<n; i++) if(isnan(X[i])) return(4);
468 return(0);
469} /* qr */
470/*****************************************************************************/
471
472/*****************************************************************************/
495 double **a,
497 int M,
499 int N,
501 double *tau,
503 double **cchain,
505 double *chain
506) {
507 //printf("qr_decomp()\n");
508 int i, m, n, MNmin;
509 double *subvector, **submatrix;
510
511 /* Local variables */
512 if(M<N) MNmin=M; else MNmin=N;
513 if(MNmin<1 || a==NULL || tau==NULL || cchain==NULL || chain==NULL) return(1);
514 subvector=chain;
515 submatrix=cchain;
516
517 for(i=0; i<MNmin; i++) {
518 //printf("i=%d (MNmin=%d)\n", i, MNmin);
519 /* Compute the Householder transformation to reduce the j-th column of the matrix A to
520 a multiple of the j-th unit vector. Householder vector h_i is saved in the lower triangular
521 part of the column and Householder coefficient tau_i in the vector tau. */
522 for(m=i; m<M; m++) {
523 //printf("subvector[%d]=a[%d][%d]\n", m-1, m, i);
524 subvector[m-i]=a[m][i];
525 }
526 tau[i] = householder_transform(subvector, M-i);
527 for(m=i; m<M; m++) a[m][i]=subvector[m-i];
528
529 /* Apply the transformation to the remaining columns to get upper triangular part of matrix R */
530 if(i+1 < N) {
531 printf(" apply transformation\n");
532 for(m=i; m<M; m++) for(n=i+1; n<N; n++) {
533 if((m-i)<0 || (m-i)>=M || (n-i-1)<0 || (n-i-1)>=N) printf("OVERFLOW!\n");
534 submatrix[m-i][n-i-1]=a[m][n];
535 }
536 if(householder_hm(tau[i], subvector, submatrix, M-i, N-i)) return(2);
537 for(m=i; m<M; m++) for(n=i+1; n<N; n++)
538 a[m][n]=submatrix[m-i][n-i-1];
539 }
540 }
541
542 return(0);
543}
544/*****************************************************************************/
545
546/*****************************************************************************/
565 double **QR,
567 int M,
569 int N,
571 double *tau,
573 double *b,
575 double *x,
577 double *residual,
579 double *resNorm,
581 double **cchain,
583 double *chain
584) {
585 //printf("qr_solve()\n");
586 if(QR==NULL || tau==NULL || b==NULL || x==NULL || residual==NULL) return(1);
587 if(cchain==NULL || chain==NULL) return(1);
588 if(M<1 || N<1) return(2);
589
590 int m, n;
591 double **Rmatrix;
592
593 /* Local variable */
594 Rmatrix=cchain;
595
596 /* Get matrix R from the upper triangular part of QR
597 First the rows N - M-1 are eliminated from R matrix*/
598 for(m=0; m<N; m++) for(n=0; n<N; n++) Rmatrix[m][n]=QR[m][n];
599 for(m=0; m<M; m++) residual[m]=b[m];
600
601 /* Compute b = Q^T b */
602 if(qr_QTvec(M, N, QR, tau, residual, chain)) return(3);
603
604 /* Solve R x = b by computing x = R^-1 b */
605 for(n=0; n<N; n++) x[n]=residual[n];
606 if(qr_invRvec(N, Rmatrix, x)) return(4);
607
608 /* Compute residual = b - A x = Q (Q^T b - R x) */
609 for(n=0; n<N; n++) residual[n]=0.0;
610 /* Compute residual= Q*residual */
611 if(qr_Qvec(M, N, QR, tau, residual, chain)) return(4);
612
613 /* Compute norm^2 of the residual vector, if needed */
614 if(resNorm!=NULL)
615 for(m=0, *resNorm=0.0; m<M; m++) *resNorm +=residual[m]*residual[m];
616
617 return(0);
618}
619/*****************************************************************************/
620
621/*****************************************************************************/
623
627int qr_QTvec(
629 int M,
631 int N,
633 double **QR,
634 /* Vector tau of length M or N, which is smaller. */
635 double *tau,
637 double *v,
639 double *help
640) {
641 //printf("qr_QTvec()\n");
642 int i, m, MNmin;
643 double *h, *w;
644
645 /* Local variables */
646 if(M<N) MNmin=M; else MNmin=N;
647 if(MNmin<1 || QR==NULL || tau==NULL || v==NULL || help==NULL) return(1);
648 h=help; w=help+M;
649
650 /* compute Q^T v */
651 for(i=0; i<MNmin; i++) {
652 for(m=i; m<M; m++) {
653 if((m-i)<0 || (m-i)>=M || (i)<0 || (i)>=N) printf("OVERFLOW!\n");
654 h[m-i]=QR[m][i];
655 w[m-i]=v[m];
656 }
657 if(householder_hv(tau[i], M-i, h, w)) return(2);
658 for(m=i; m<M; m++) v[m]=w[m-i];
659 }
660 return(0);
661}
662/*****************************************************************************/
663
664/*****************************************************************************/
669int qr_Qvec(
671 int M,
673 int N,
675 double **QR,
676 /* Vector tau of length M or N, which is smaller. */
677 double *tau,
678 /* Vector v of length M. */
679 double *v,
681 double *help
682) {
683 //printf("qr_Qvec()\n");
684 int i, m, MNmin;
685 double *h, *w;
686
687 /* Local variables */
688 if(M<N) MNmin=M; else MNmin=N;
689 if(MNmin<1 || QR==NULL || tau==NULL || v==NULL || help==NULL) return(1);
690 h=help; w=help+M;
691
692 /* compute Q v */
693 for(i=MNmin-1; i>=0; i--) {
694 for(m=i; m<M; m++) {
695 if((m-i)<0 || (m-i)>=M || (i)<0 || (i)>=N) printf("OVERFLOW!\n");
696 h[m-i]=QR[m][i];
697 w[m-i]=v[m];
698 }
699 if(householder_hv(tau[i], M-i, h, w)) return(2);
700 for(m=i; m<M; m++) v[m]=w[m-i];
701 }
702 return(0);
703}
704/*****************************************************************************/
705
706/*****************************************************************************/
710int qr_invRvec(
712 int N,
714 double **A,
716 double *X
717) {
718 //printf("qr_invRvec()\n");
719 int i, j;
720 double tmp;
721
722 if(N<1 || A==NULL || X==NULL) return(1);
723 /* form x := inv( A )*x */
724 /* back-substitution */
725 X[N-1] = X[N-1]/A[N-1][N-1];
726 for(i=N-2; i>=0; i--) {
727 for(j=i+1, tmp=X[i]; j<N; j++) {
728 //if((i)<0 || (i)>=N || (j)<0 || (j)>=N) printf("OVERFLOW!\n");
729 tmp-=A[i][j]*X[j];
730 }
731 X[i] = tmp/A[i][i];
732 }
733 return(0);
734}
735/*****************************************************************************/
737
738/*****************************************************************************/
747 int N,
749 int M,
751 double **A,
753 double *b,
756 double *weight,
758 double *ws
759) {
760 int n, m;
761 double *w;
762
763 /* Check the arguments */
764 if(N<1 || M<1 || A==NULL || b==NULL || weight==NULL) return(1);
765
766 /* Allocate memory, if necessary */
767 if(ws==NULL) {
768 w=(double*)malloc(M*sizeof(double)); if(w==NULL) return(2);
769 } else {
770 w=ws;
771 }
772
773 /* Check that weights are not zero and get the square roots of them to w[]. */
774 for(m=0; m<M; m++) {
775 if(weight[m]<=1.0e-100) w[m]=1.0e-50;
776 else w[m]=sqrt(weight[m]);
777 }
778
779 /* Multiply rows of matrix A and elements of vector b with weights. */
780 for(m=0; m<M; m++) {
781 for(n=0; n<N; n++) A[m][n]*=w[m];
782 b[m]*=w[m];
783 }
784
785 if(ws==NULL) free(w);
786 return(0);
787}
788/*****************************************************************************/
789
790/*****************************************************************************/
798 int N,
800 int M,
802 double **A,
805 double *b,
808 double *weight,
810 double *ws
811) {
812 int n, m;
813 double *w;
814
815 /* Check the arguments */
816 if(N<1 || M<1 || weight==NULL) return(1);
817 if(A==NULL && b==NULL) return(0); // nothing to do
818
819 /* Allocate memory, if necessary */
820 if(ws==NULL) {
821 w=(double*)malloc(M*sizeof(double)); if(w==NULL) return(2);
822 } else {
823 w=ws;
824 }
825
826 /* Check that weights are not zero and get the square roots of them to w[] */
827 for(m=0; m<M; m++) {
828 if(weight[m]<=1.0e-100) w[m]=1.0e-50;
829 else w[m]=sqrt(weight[m]);
830 }
831
832 /* Multiply rows of matrix A and elements of vector b with weights */
833 for(m=0; m<M; m++) {
834 if(A!=NULL) for(n=0; n<N; n++) A[m][n]/=w[m];
835 if(b!=NULL) b[m]/=w[m];
836 }
837
838 if(ws==NULL) free(w);
839 return(0);
840}
841/*****************************************************************************/
842
843/*****************************************************************************/
856 double **A,
858 double *B,
860 int M,
862 int N,
864 double *X,
867 double *r2
868) {
869 //printf("qrSimpleLSQ()\n");
870 if(A==NULL || B==NULL || X==NULL || N<1 || M<N) return(1);
871
872 const double closeZero=1.0E-20;
873
874 double cc[M], orig_B[M];
875 double p[M][N], c[M][N];
876
877 /* Householder transformation of matrix A into matrix P */
878 for(int n=0; n<N; n++) {
879 for(int nn=0; nn<n; nn++) p[nn][n]=0.0;
880 p[n][n]=0.0;
881 for(int m=n; m<M; m++) p[n][n]+=A[m][n]*A[m][n];
882 p[n][n]=copysign(sqrt(p[n][n]), A[n][n]);
883 p[n][n]+=A[n][n];
884 if(fabs(p[n][n])<closeZero) return(2);
885 for(int m=n+1; m<M; m++) p[m][n]=A[m][n];
886 double norm=0.0;
887 for(int m=n; m<M; m++) norm+=p[m][n]*p[m][n];
888 norm=sqrt(norm);
889 for(int m=n; m<M; m++) p[m][n]/=norm;
890 for(int m=n; m<M; m++) {
891 for(int nn=n; nn<N; nn++) {
892 c[m][nn]=A[m][nn];
893 for(int mm=n; mm<M; mm++) c[m][nn]-=2.0*p[m][n]*p[mm][n]*A[mm][nn];
894 }
895 }
896 for(int m=n; m<M; m++)
897 for(int nn=n; nn<N; nn++) A[m][nn]=c[m][nn];
898 }
899
900 /* Keep the original B[] for R^2 calculation */
901 for(int m=0; m<M; m++) orig_B[m]=B[m];
902
903 /* Compute P'b */
904 for(int n=0; n<N; n++) {
905 for(int m=n; m<M; m++) {
906 cc[m]=B[m];
907 for(int mm=n; mm<M; mm++) cc[m]-=2.0*p[m][n]*p[mm][n]*B[mm];
908 }
909 for(int m=n; m<M; m++) B[m]=cc[m];
910 }
911
912 /* Solve the linear system with backward substitution */
913 X[N-1]=B[N-1]/A[N-1][N-1];
914 for(int n=N-2; n>=0; n--) {
915 X[n]=B[n];
916 for(int nn=n+1; nn<N; nn++) X[n]-=A[n][nn]*X[nn];
917 X[n]/=A[n][n];
918 }
919
920 /* Compute R^2, if requested */
921 if(r2!=NULL) {
922 double ss=0, d;
923 for(int m=0; m<M; m++) {
924 d=orig_B[m]-B[m];
925 ss+=d*d;
926 }
927 *r2=ss;
928 }
929
930 return(0);
931}
932/*****************************************************************************/
933
934/*****************************************************************************/
948 const unsigned int m,
951 const unsigned int n,
955 double *a,
958 double *b,
960 double *x,
962 double *r2
963) {
964 /* Check the input */
965 if(a==NULL || b==NULL || x==NULL || r2==NULL) return(2);
966 if(n<1 || m<n) {*r2=nan(""); return(2);}
967
968 /* Initiate output to zeroes, in case of exit because of singularity */
969 for(unsigned int ni=0; ni<n; ni++) x[ni]=0.0;
970 *r2=0.0;
971
972 /* Rotates matrix A into upper triangular form */
973 for(unsigned int ni=0; ni<n; ni++) {
974 /* Find constants for rotation and diagonal entry */
975 double sq=0.0;
976 for(unsigned int mi=ni; mi<m; mi++) sq+=a[mi + ni*m]*a[mi + ni*m];
977 if(sq==0.0) return(1);
978 double qv1=-copysign(sqrt(sq), a[ni + ni*m]);
979 double u1=a[ni + ni*m] - qv1;
980 a[ni + ni*m]=qv1;
981 unsigned int ni1=ni+1;
982 /* Rotate the remaining columns of sub-matrix. */
983 for(unsigned int nj=ni1; nj<n; nj++) {
984 double dot=u1*a[ni + nj*m];
985 for(unsigned int mi=ni1; mi<m; mi++)
986 dot+=a[mi + nj*m] * a[mi + ni*m];
987 double c=dot/fabs(qv1*u1);
988 for(unsigned int mi=ni1; mi<m; mi++)
989 a[mi + nj*m]-=c*a[mi + ni*m];
990 a[ni + nj*m]-=c*u1;
991 }
992 /* Rotate vector B */
993 double dot=u1*b[ni];
994 for(unsigned int mi=ni1; mi<m; mi++)
995 dot+=b[mi]*a[mi + ni*m];
996 double c=dot/fabs(qv1*u1);
997 b[ni]-=c*u1;
998 for(unsigned int mi=ni1; mi<m; mi++)
999 b[mi]-=c*a[mi + ni*m];
1000 } // end of rotation loop
1001
1002 /* Solve triangular system by back-substitution. */
1003 for(unsigned int ni=0; ni<n; ni++) {
1004 int k=n-ni-1;
1005 double s=b[k];
1006 for(unsigned int nj=k+1; nj<n; nj++)
1007 s-=a[k + nj*m] * x[nj];
1008 if(a[k + k*m]==0.0) return(1);
1009 x[k]=s/a[k + k*m];
1010 }
1011
1012 /* Calculate the sum of squared residuals. */
1013 *r2=0.0;
1014 for(unsigned int mi=n; mi<m; mi++)
1015 *r2 += b[mi]*b[mi];
1016
1017 return(0);
1018}
1019/*****************************************************************************/
1020
1021/*****************************************************************************/
int householder_hv(double tau, int size, double *v, double *w)
Definition hholder.c:126
int householder_hm(double tau, double *vector, double **matrix, int rowNr, int columnNr)
Definition hholder.c:87
double householder_transform(double *v, int N)
Definition hholder.c:33
int qrLH(const unsigned int m, const unsigned int n, double *a, double *b, double *x, double *r2)
Solve over-determined least-squares problem A x ~ b using successive Householder rotations.
Definition qrlsq.c:946
int qrWeightRm(int N, int M, double **A, double *b, double *weight, double *ws)
Definition qrlsq.c:796
int qrLSQ(double **mat, double *rhs, double *sol, const unsigned int rows, const unsigned int cols, double *r2)
QR least-squares solving routine.
Definition qrlsq.c:72
int qrSimpleLSQ(double **A, double *B, int M, int N, double *X, double *r2)
Definition qrlsq.c:854
int qr_solve(double **QR, int M, int N, double *tau, double *b, double *x, double *residual, double *resNorm, double **cchain, double *chain)
Definition qrlsq.c:563
int qr(double **A, int m, int n, double *B, double *X, double *rnorm, double *tau, double *res, double **wws, double *ws)
Definition qrlsq.c:411
int qrWeight(int N, int M, double **A, double *b, double *weight, double *ws)
Definition qrlsq.c:745
int qr_decomp(double **a, int M, int N, double *tau, double **cchain, double *chain)
Definition qrlsq.c:493
Header file for library libtpcextensions.
Header file for libtpclinopt.