Xmipp  v3.23.11-Nereus
Matrix.cpp
Go to the documentation of this file.
1 /*
2 
3 CONDOR 1.06 - COnstrained, Non-linear, Direct, parallel Optimization
4  using trust Region method for high-computing load,
5  noisy functions
6 Copyright (C) 2004 Frank Vanden Berghen
7 
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation version 2
11 of the License.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 
22 If you want to include this tools in any commercial product,
23 you can contact the author at fvandenb@iridia.ulb.ac.be
24 
25 */
26 
27 #include <memory.h>
28 #include <stdlib.h>
29 #include <iostream>
30 #include <string.h>
31 #include <math.h>
32 #include "Matrix.h"
33 #include "tools.h"
34 
36 
37 void Matrix::init(int _nLine, int _nColumn, int _extLine, int _extColumn,MatrixData* md)
38 {
39  if (md==NULL)
40  {
41  d=(MatrixData*)malloc(sizeof(MatrixData));
42  d->columnNames=NULL;
43  d->ref_count=1;
44  } else d=md;
45  d->nLine=_nLine; d->nColumn=_nColumn;
46  d->extLine=_extLine; d->extColumn=_extColumn;
47 
48  if ((_extLine>0)&&(_extColumn>0))
49  {
50  double **t,*t2;
51  t=d->p=(double**)malloc(_extLine*sizeof(double*));
52  t2=(double*)malloc(_extColumn*_extLine*sizeof(double));
53  while(_extLine--)
54  {
55  *(t++)=t2; t2+=_extColumn;
56  }
57  } else d->p=NULL;
58 }
59 
60 Matrix::Matrix(int _nLine,int _nColumn)
61 {
62  init(_nLine,_nColumn,_nLine, _nColumn);
63 }
64 
65 void Matrix::diagonal(double dd)
66 {
67  zero();
68  double *p=*d->p;
69  int n=nLine(), i=d->extColumn+1;
70  while (n--) { *p=dd; p+=i; }
71 
72 }
73 
75 {
76  int nl=1, nc=a.sz();
77  init(nl,nc,nl,nc);
78  memcpy(*d->p,a,a.sz()*sizeof(double));
79 }
80 
82 {
83  int nl=a.sz(), nc=b.sz(), i,j;
84  double *pa=a, *pb=b;
85  init(nl,nc,nl,nc);
86  double **pp=d->p;
87  for (i=0; i<nl; i++)
88  for (j=0; j<nc; j++)
89  pp[i][j]=pa[i]*pb[j];
90 }
91 
92 Matrix::Matrix(int _nLine,int _nColumn,int _extLine,int _extColumn)
93 {
94  init(_nLine,_nColumn,_extLine,_extColumn);
95 }
96 
97 Matrix::Matrix(const char *filename, char ascii)
98 {
99  // FIXME refactor
100  int _nLine,_nColumn;
101  char c[13];
102  FILE *f=fopen(filename,"rb");
103  if (f==NULL)
104  {
105  printf("file not found.\n"); exit(255);
106  }
107  if (ascii)
108  {
109  char line[30000];
110  char *r=fgets(line,30000,f);
111  if (r==NULL) { init(0,0,0,0); return; }
112  if (line[7]!='A')
113  {
114  printf("not a ASCII matrix.\n"); exit(255);
115  }
116  if (fgets(line,30000,f) != line) {
117  std::cerr << "error while reading " << filename << std::endl; exit(255);
118  }
119  _nLine=atol(line);
120  if (fgets(line,30000,f) != line) {
121  std::cerr << "error while reading " << filename << std::endl; exit(255);
122  }
123  _nColumn=atol(line);
124  init(_nLine,_nColumn,_nLine,_nColumn);
125  if (fgets(line,30000,f) != line) {
126  std::cerr << "error while reading " << filename << std::endl; exit(255);
127  }
128  setColNames(getNameTable(line,&_nColumn));
129  Vector tt(_nColumn);
130  int i;
131  for (i=0; i<_nLine; i++)
132  {
133  if (fgets(line,30000,f) != line) {
134  std::cerr << "error while reading " << filename << std::endl; exit(255);
135  }
136  tt.getFromLine(line);
137  setLine(i,tt);
138  }
139  return;
140  }
141  if (fread(c, 13, sizeof(char), f)==0) { init(0,0,0,0); return; }
142  if (c[7]!='B')
143  {
144  printf("not a binary matrix.\n"); exit(255);
145  }
146  if (fread(&_nLine, sizeof(unsigned), 1, f) != sizeof(unsigned)) {
147  std::cerr << "error while reading " << filename << std::endl; exit(255);
148  }
149  if (fread(&_nColumn, sizeof(unsigned), 1, f) != sizeof(unsigned)) {
150  std::cerr << "error while reading " << filename << std::endl; exit(255);
151  }
152  init(_nLine,_nColumn,_nLine,_nColumn);
153  int i,j=0;
154  if (fread(&i, sizeof(int), 1, f) != sizeof(int)) {
155  std::cerr << "error while reading " << filename << std::endl; exit(255);
156  }
157  if (i)
158  {
159  char **names=(char**)malloc(_nColumn*sizeof(char**)),
160  *n=(char*)malloc(i);
161  if (fread(n,i,1,f) != i) {
162  std::cerr << "error while reading " << filename << std::endl; exit(255);
163  }
164  for (j=0;j<_nColumn-1;j++)
165  {
166  names[j]=n;
167  while (*(n++));
168  }
169  names[j]=n;
170  setColNames(names);
171  free(*names);free(names);
172  }
173  size_t noOfLines = d->nColumn*d->nLine;
174  if (noOfLines)
175  if (fread(*d->p,sizeof(double)*noOfLines,1,f) != sizeof(double)*noOfLines){
176  std::cerr << "error while reading " << filename << std::endl; exit(255);
177  }
178  fclose(f);
179 }
180 
182 {
183  d->nLine++;
184  if (d->nLine>d->extLine) setExtSize(d->nLine+9,d->extColumn);
185 }
186 
187 void Matrix::setNLine(int _nLine)
188 {
189  d->nLine=_nLine;
190  if (_nLine>d->extLine) setExtSize(_nLine,d->extColumn);
191 }
192 
194 {
195  d->nColumn++;
197 }
198 
199 void Matrix::setNColumn(int _nColumn)
200 {
201  d->nColumn=_nColumn;
202  if (_nColumn>d->extColumn) setExtSize(d->extLine,_nColumn);
203 }
204 
205 void Matrix::setSize(int _nLine,int _nColumn)
206 {
207  d->nLine=_nLine;
208  d->nColumn=_nColumn;
209  if ((_nLine>d->extLine)||(_nColumn>d->extColumn)) setExtSize(_nLine,_nColumn);
210 }
211 
212 void Matrix::setExtSize(int _extLine, int _extColumn)
213 {
214  int ec=d->extColumn;
215  if ((ec==0)||(d->extLine==0))
216  {
217  init(d->nLine,d->nColumn,_extLine,_extColumn,d);
218  return;
219  }
220  if (_extColumn>ec)
221  {
222  int nc=d->nColumn,i;
223  double *tmp,*tmp2,**tmp3=d->p,*oldBuffer=*tmp3;
224 
225  if (d->extLine<_extLine)
226  tmp3=d->p=(double**)realloc(tmp3,_extLine*sizeof(double*));
227  else _extLine=d->extLine;
228 
229  tmp2=tmp=(double *)malloc(_extLine*_extColumn*sizeof(double));
230  if (tmp==NULL)
231  {
232  printf("memory allocation error");
233  getchar(); exit(255);
234  }
235 
236  i=_extLine;
237  while (i--)
238  {
239  *(tmp3++)=tmp2;
240  tmp2+=_extColumn;
241  };
242 
243  if ((nc)&&(d->nLine))
244  {
245  tmp2=oldBuffer;
246  i=d->nLine;
247  nc*=sizeof(double);
248  while(i--)
249  {
250  memmove(tmp,tmp2,nc);
251  tmp+=_extColumn;
252  tmp2+=ec;
253  };
254  free(oldBuffer);
255  };
256  d->extLine=_extLine;
257  d->extColumn=_extColumn;
258  return;
259  }
260  if (_extLine>d->extLine)
261  {
262  int i;
263  double *tmp,**tmp3;
264  tmp=(double *)realloc(*d->p,_extLine*ec*sizeof(double));
265  if (tmp==NULL)
266  {
267  printf("memory allocation error");
268  getchar(); exit(255);
269  }
270  free(d->p);
271  tmp3=d->p=(double **)malloc(_extLine*sizeof(double*));
272  i=_extLine;
273  while (i--)
274  {
275  *(tmp3++)=tmp;
276  tmp+=ec;
277  };
278  d->extLine=_extLine;
279  }
280 }
281 
282 void Matrix::save(char *filename,char ascii)
283 {
284  FILE *f;
285  if (ascii)
286  {
287  f=fopen(filename,"w");
288  if (f==NULL)
289  {
290  printf("cannot save ascii Matrix into file '%s'.\n",filename);
291  exit(255);
292  }
293  } else
294  {
295  f=fopen(filename,"wb");
296  if (f==NULL)
297  {
298  printf("cannot save binary Matrix into file '%s'.\n",filename);
299  exit(255);
300  }
301  }
302  save(f,ascii);
303  fclose(f);
304 }
305 
306 void Matrix::save(FILE *f,char ascii)
307 {
308  char cc[32]="CONDORMBv1.0";
309  double **p=(d->p);
310  int i,j;
311  if (ascii)
312  {
313  if (ascii<2) fprintf(f,"CONDORMAv1.0\n%i\n%i\n",d->nLine,d->nColumn);
314  if (ascii<3)
315  {
316  if (d->columnNames)
317  {
318  for (i=0; i<d->nColumn-1; i++)
319  fprintf(f,"%s\t",d->columnNames[i]);
320  fprintf(f,"%s\n",d->columnNames[i]);
321  } else fprintf(f,"null\n");
322  }
323  for (i=0; i<d->nLine; i++)
324  {
325  for (j=0; j<d->nColumn-1; j++)
326  fprintf(f,"%.16e\t",p[i][j]);
327  fprintf(f,"%.16e\n",p[i][j]);
328  }
329  } else
330  {
331  fwrite(cc, sizeof(char), 13, f);
332  fwrite(&d->nLine, sizeof(unsigned), 1, f);
333  fwrite(&d->nColumn, sizeof(unsigned), 1, f);
334  if (d->columnNames)
335  {
336  j=0; for (i=0; i<d->nColumn; i++) j+=(int)strlen(d->columnNames[i])+1;
337  fwrite(&j, sizeof(int), 1, f);
338  for (i=0; i<d->nColumn; i++)
339  fwrite(d->columnNames[i],strlen(d->columnNames[i])+1,1,f);
340  } else
341  {
342  j=0; fwrite(&j, sizeof(int), 1, f);
343  }
344  for (i=0; i<d->nLine; i++)
345  fwrite(p[i],sizeof(double)*d->nColumn,1,f);
346  };
347 }
348 
349 void Matrix::updateSave(char *saveFileName)
350 {
351  // FIXME refactor
352  FILE *f=fopen(saveFileName,"rb+");
353  if (f==NULL)
354  {
355  save(saveFileName,0);
356  return;
357  }
358  fseek(f,0,SEEK_END);
359  long l=ftell(f);
360  if (l==0)
361  {
362  save(saveFileName,0);
363  return;
364  }
365  int nc=d->nColumn, nlfile, nl=d->nLine, i;
366  fseek(f,13,SEEK_SET);
367  if (fread(&nlfile,sizeof(int),1,f) != sizeof(int)) {
368  std::cerr << "error while updating file " << saveFileName << std::endl; exit(255);
369  }
370  fseek(f,13,SEEK_SET);
371  fwrite(&d->nLine, sizeof(unsigned), 1, f);
372  fseek(f,0,SEEK_END);
373  double **p=d->p;
374  for (i=nlfile; i<nl; i++)
375  fwrite(p[i],sizeof(double)*nc,1,f);
376  fclose(f);
377 }
378 
380 {
381  int i, nc=d->nColumn, ec=d->extColumn, nl=d->nLine, el=d->extLine;
382  double *tmp,*tmp2,**tmp3;
383 
384  if ((nc==ec)&&(nl==el)) return;
385 
386  if (nc!=ec)
387  {
388  i=nl;
389  tmp=tmp2=*d->p;
390  while(i--)
391  {
392  memmove(tmp,tmp2,nc*sizeof(double));
393  tmp+=nc;
394  tmp2+=ec;
395  };
396  }
397 
398  tmp=(double *)realloc(*d->p,nl*nc*sizeof(double));
399  if (tmp==NULL)
400  {
401  printf("memory allocation error");
402  getchar(); exit(255);
403  }
404  if (tmp!=*d->p)
405  {
406  tmp3=d->p=(double **)realloc(d->p,nl*sizeof(double*));
407  i=nl;
408  while (i--)
409  {
410  *(tmp3++)=tmp;
411  tmp+=nc;
412  };
413  } else d->p=(double **)realloc(d->p,nl*sizeof(double*));
414 
415  d->extLine=nl; d->extColumn=nc;
416 }
417 
419 {
420  double **p=d->p;
421  int i,j;
422 
423  printf("[");
424  for (i=0; i<d->nLine; i++)
425  {
426  for (j=0; j<d->nColumn; j++)
427  if (p[i][j]>=0.0) printf(" %2.3f ",p[i][j]);
428  else printf("%2.3f ",p[i][j]);
429  if (i==d->nLine-1) printf("]\n"); else printf(";\n");
430  }
431  fflush(0);
432 }
433 
435 {
437 }
438 
440 {
441  if (!d) return;
442  (d->ref_count) --;
443  if (d->ref_count==0)
444  {
445  if (d->columnNames) { free(*d->columnNames); free(d->columnNames); }
446  if (d->p) { free(*d->p); free(d->p); }
447  free(d);
448  }
449 }
450 
452 {
453  // shallow copy
454  if (this != &A)
455  {
457  d=A.d;
458  (d->ref_count) ++ ;
459  }
460  return *this;
461 }
462 
464 {
465  // shallow copy
466  d=A.d;
467  (d->ref_count)++ ;
468 }
469 
471 {
472  // a deep copy
473  Matrix m(nLine(),nColumn());
474  m.copyFrom(*this);
475  return m;
476 }
477 
479 {
480  int nl=m.nLine(),nc=m.nColumn(), ec=m.d->extColumn;
481  if ((nl!=nLine())||(nc!=nColumn()))
482  {
483  printf("Matrix: copyFrom: size do not agree");
484  getchar(); exit(254);
485  }
486  if (ec==nc)
487  {
488  memcpy(*d->p,*m.d->p,nc*nl*sizeof(double));
489  return;
490  }
491  double *pD=*d->p,*pS=*m.d->p;
492  while(nl--)
493  {
494  memcpy(pD,pS,nc*sizeof(double));
495  pD+=nc;
496  pS+=ec;
497  };
498 }
499 
501 {
502  int nl=nLine(),nc=nColumn(),i,j;
503  if (nl==nc)
504  {
505  double **p=(*this),t;
506  for (i=0; i<nl; i++)
507  for (j=0; j<i; j++)
508  {
509  t=p[i][j];
510  p[i][j]=p[j][i];
511  p[j][i]=t;
512  }
513  return;
514  }
515  Matrix temp=clone();
516  setSize(nc,nl);
517  double **sp=temp, **dp=(*this);
518  i=nl;
519  while (i--)
520  {
521  j=nc;
522  while (j--) dp[j][i]=sp[i][j];
523  }
524 }
525 
527 {
528  int nl=nLine(),nc=nColumn(),i,j;
529  temp.setSize(nc,nl);
530  double **sp=temp, **dp=(*this);
531  i=nl;
532  while (i--)
533  {
534  j=nc;
535  while (j--) sp[j][i]=dp[i][j];
536  }
537 }
538 
540 {
541  Matrix temp(nColumn(),nLine());
542  transpose(temp);
543  return temp;
544 }
545 
546 //Matrix Matrix::deepCopy()
547 //{
548 // Matrix cop(this); // contructor of class matrix
549 // return cop; // copy of class Matrix in return Variable
550 // // destruction of instance cop.
551 //};
552 
554 {
555  memset(*d->p,0,nLine()*d->extColumn*sizeof(double));
556 }
557 
559 {
560  int i,j,nc=nColumn(),nl=nLine();
561  if ((int)v.sz()!=nc)
562  {
563  printf("(matrix * matrix_diagonal) error");
564  getchar(); exit(249);
565  }
566  double **p1=(*this),*p2=v;
567 
568  for (i=0; i<nl; i++)
569  for (j=0; j<nc; j++)
570  p1[i][j]*=p2[j];
571 }
572 
574 {
575  if (Bplus.nLine()!=nColumn())
576  {
577  printf("(matrix * matrix) error");
578  getchar(); exit(249);
579  }
580  int i,j,k, nl=nLine(), nc=Bplus.nColumn(), n=nColumn();
581  R.setSize(nl,nc);
582  double sum,**p1=(*this),**p2=Bplus,**pr=R;
583 
584  for (i=0; i<nl; i++)
585  for (j=0; j<nc; j++)
586  {
587  sum=0;
588  for (k=0; k<n; k++) sum+=p1[i][k]*p2[k][j];
589  pr[i][j]=sum;
590  }
591 }
592 
594 {
595  if (Bplus.nLine()!=nLine())
596  {
597  printf("(matrix^t * matrix) error");
598  getchar(); exit(249);
599  }
600  int i,j,k, nl=nColumn(), nc=Bplus.nColumn(), n=nLine();
601  R.setSize(nl,nc);
602  double sum,**p1=(*this),**p2=Bplus,**pr=R;
603 
604  for (i=0; i<nl; i++)
605  for (j=0; j<nc; j++)
606  {
607  sum=0;
608  for (k=0; k<n; k++) sum+=p1[k][i]*p2[k][j];
609  pr[i][j]=sum;
610  }
611 }
612 
614 {
615  if (Bplus.nColumn()!=nColumn())
616  {
617  printf("(matrix * matrix^t) error");
618  getchar(); exit(249);
619  }
620  int i,j,k, nl=nLine(), nc=Bplus.nLine(), n=nColumn();
621  R.setSize(nl,nc);
622  double sum,**p1=(*this),**p2=Bplus,**pr=R;
623 
624  for (i=0; i<nl; i++)
625  for (j=0; j<nc; j++)
626  {
627  sum=0;
628  for (k=0; k<n; k++) sum+=p1[i][k]*p2[j][k];
629  pr[i][j]=sum;
630  }
631 }
632 
634 {
635  Matrix R(nLine(),Bplus.nColumn());
636  multiply(R,Bplus);
637  return R;
638 }
639 
640 void Matrix::multiplyInPlace(double dd)
641 {
642  int i,j, nl=nLine(), nc=nColumn();
643  double **p1=(*this);
644 
645  for (i=0; i<nl; i++)
646  for (j=0; j<nc; j++)
647  p1[i][j]*=dd;
648 }
649 
651 {
652  int i,j, nl=nLine(), nc=nColumn();
653  rv.setSize(nl);
654  if (nc!=(int)v.sz())
655  {
656  printf("matrix multiply error");
657  getchar(); exit(250);
658  };
659  double **p=(*this), *x=v, *r=rv, sum;
660 
661  for (i=0; i<nl; i++)
662  {
663  sum=0; j=nc;
664  while (j--) sum+=p[i][j]*x[j];
665  r[i]=sum;
666  }
667 }
668 
670 {
671  int i,j, nc=nLine(), nl=nColumn();
672  rv.setSize(nl);
673  if (nc!=(int)v.sz())
674  {
675  printf("matrix multiply error");
676  getchar(); exit(250);
677  };
678  double **p=(*this), *x=v, *r=rv, sum;
679 
680  for (i=0; i<nl; i++)
681  {
682  sum=0; j=nc;
683  while (j--) sum+=p[j][i]*x[j];
684  r[i]=sum;
685  }
686 }
687 
689 {
690  Vector r(nLine());
691  multiply(r,v);
692  return r;
693 }
694 
695 double Matrix::scalarProduct(int nl, Vector v)
696 {
697  double *x1=v, *x2=d->p[nl], sum=0;
698  int n=v.sz();
699  while (n--) { sum+=*(x1++) * *(x2++); };
700  return sum;
701 }
702 
704 {
705  if ((B.nLine()!=nLine())||
706  (B.nColumn()!=nColumn()))
707  {
708  printf("matrix addition error");
709  getchar(); exit(250);
710  };
711 
712  int i,j, nl=nLine(), nc=nColumn();
713  double **p1=(*this),**p2=B;
714 
715  for (i=0; i<nl; i++)
716  for (j=0; j<nc; j++)
717  p1[i][j]+=p2[i][j];
718 }
719 
721 {
722  if ((B.nLine()!=nLine())||
723  (B.nColumn()!=nColumn()))
724  {
725  printf("matrix addition error");
726  getchar(); exit(250);
727  };
728 
729  int i,j, nl=nLine(), nc=nColumn();
730  double **p1=(*this),**p2=B;
731 
732  for (i=0; i<nl; i++)
733  for (j=0; j<nc; j++)
734  p1[i][j]+=d*p2[i][j];
735 }
736 
737 //inline double sqr(double a){return a*a;};
738 
739 #ifndef NOMATRIXTRIANGLE
741 
742 Matrix::Matrix(MatrixTriangle A, char bTranspose)
743 {
744  int n=A.nLine(),i,j;
745  init(n,n,n,n);
746  double **pD=(*this), **pS=A;
747 
748  if (bTranspose)
749  {
750  for (i=0; i<n; i++)
751  for (j=0; j<n; j++)
752  if (j>=i) pD[i][j]=pS[j][i];
753  else pD[i][j]=0;
754  } else
755  {
756  for (i=0; i<n; i++)
757  for (j=0; j<n; j++)
758  if (j<=i) pD[i][j]=pS[i][j];
759  else pD[i][j]=0;
760  }
761 }
762 
763 bool Matrix::cholesky(MatrixTriangle matL, double lambda, double *lambdaCorrection)
764 // factorize (*this)+lambda.I into L.L^t
765 {
766  double s,s2;
767  int i,j,k,n=nLine();
768  matL.setSize(n);
769 
770  double **A=(*this), **L_=matL;
771  if (lambdaCorrection) *lambdaCorrection=0;
772 
773  for (i=0; i<n; i++)
774  {
775  s2=A[i][i]+lambda; k=i;
776  while ( k-- ) s2-=sqr(L_[i][k]);
777  if (s2<=0)
778  {
779  if (lambdaCorrection)
780  {
781  // lambdaCorrection
782  n=i+1;
783  Vector X(n); // zero everywhere
784  double *x=X, sum;
785  x[i]=1.0;
786  while(i--)
787  {
788  sum=0.0;
789  for (k=i+1; k<n; k++) sum-=L_[k][i]*x[k];
790  x[i]=sum/L_[i][i];
791  }
792  *lambdaCorrection=-s2/X.euclidianNorm();
793  }
794  return false;
795  }
796  L_[i][i] = s2 = sqrt(s2);
797 
798  for (j=i+1; j<n; j++)
799  {
800  s=A[i][j]; k=i;
801  while (k--) s-=L_[j][k]*L_[i][k];
802  L_[j][i]=s/s2;
803  }
804  }
805  return true;
806 }
807 
809 {
810  MatrixTriangle M(nLine());
811  if (!cholesky(M))
812  {
813  b.setSize(0); // no cholesky decomposition => return emptyVector
814  return;
815  }
816  M.solveInPlace(b);
818 }
819 
820 void Matrix::QR(Matrix Q, MatrixTriangle Rt, VectorInt vPermutation)
821 {
822 // QR factorization of the transpose of (*this)
823 // beware!! :
824 // 1. (*this) is destroyed during the process.
825 // 2. Rt contains the tranpose of R (get an easy manipulation matrix using:
826 // Matrix R(Rt,1); ).
827 // 3. use of permutation IS tested
828 //
829 //
830 // subroutine qrfac(m,n,a,lda,pivot,ipvt,lipvt,rdiag,acnorm,wa)
831 // integer m,n,lda,lipvt
832 // integer ipvt(lipvt)
833 // logical pivot
834 //
835 //
836 // double precision a(lda,n),rdiag(n),acnorm(n),wa(n)
837 //c **********
838 //c
839 //c subroutine qrfac
840 //c
841 //c this subroutine uses householder transformations with column
842 //c pivoting (optional) to compute a qr factorization of the
843 //c m by n matrix a. that is, qrfac determines an orthogonal
844 //c matrix q, a permutation matrix p, and an upper trapezoidal
845 //c matrix r with diagonal elements of nonincreasing magnitude,
846 //c such that a*p = q*r. the householder transformation for
847 //c column k, k = 1,2,...,min(m,n), is of the form
848 //c
849 //c t
850 //c i - (1/u(k))*u*u
851 //c
852 //c where u has zeros in the first k-1 positions. the form of
853 //c this transformation and the method of pivoting first
854 //c appeared in the corresponding linpack subroutine.
855 //c
856 //c the subroutine statement is
857 //c
858 //c subroutine qrfac(m,n,a,lda,pivot,ipvt,lipvt,rdiag,acnorm,wa)
859 //c
860 //c where
861 //c
862 //c m is a positive integer input variable set to the number
863 //c of rows of a.
864 //c
865 //c n is a positive integer input variable set to the number
866 //c of columns of a.
867 //c
868 //c a is an m by n array. on input a contains the matrix for
869 
870 //c which the qr factorization is to be computed. on output
871 //c the strict upper trapezoidal part of a contains the strict
872 //c upper trapezoidal part of r, and the lower trapezoidal
873 //c part of a contains a factored form of q (the non-trivial
874 //c elements of the u vectors described above).
875 //c
876 //c lda is a positive integer input variable not less than m
877 //c which specifies the leading dimension of the array a.
878 //c
879 //c pivot is a logical input variable. if pivot is set true,
880 //c then column pivoting is enforced. if pivot is set false,
881 //c then no column pivoting is done.
882 //c
883 //c ipvt is an integer output array of length lipvt. ipvt
884 //c defines the permutation matrix p such that a*p = q*r.
885 //c column j of p is column ipvt(j) of the identity matrix.
886 //c if pivot is false, ipvt is not referenced.
887 //c
888 //c lipvt is a positive integer input variable. if pivot is false,
889 //c then lipvt may be as small as 1. if pivot is true, then
890 //c lipvt must be at least n.
891 //c
892 //c rdiag is an output array of length n which contains the
893 //c diagonal elements of r.
894 //c
895 //c wa is a work array of length n. if pivot is false, then wa
896 //c can coincide with rdiag.
897  char pivot=!(vPermutation==VectorInt::emptyVectorInt);
898  int i,j,k,kmax,minmn;
899  double ajnorm,sum,temp;
900  // data one,p05,zero /1.0d0,5.0d-2,0.0d0/
901 
902  const double epsmch = 1e-20; // machine precision
903  int nc=nColumn(), nl=nLine();
904 
905  if (nl>nc)
906  {
907  printf("QR factorisation of A^t is currently not possible when number of lines is greater than number of columns.\n");
908  getchar(); exit(255);
909  }
910 
911  Vector vWA(nl), vRDiag;
912  int *ipvt;
913  double *wa=vWA, *rdiag, **a=*this;
914 
915  if (pivot)
916  {
917  vPermutation.setSize(nl);
918  ipvt=vPermutation;
919  vRDiag.setSize(nl);
920  rdiag=vRDiag;
921  } else rdiag=wa;
922 
923 //c
924 //c compute the initial line norms and initialize several arrays.
925 //c
926  for (j=0; j<nl; j++)
927  {
928  rdiag[j]=wa[j]=euclidianNorm(j);
929  if (pivot) ipvt[j]=j;
930  }
931 //c
932 //c reduce a to r with householder transformations.
933 //c
934  minmn=mmin(nl,nc);
935  for (j=0; j<minmn; j++)
936  {
937  if (pivot)
938  {
939 //c
940 //c bring the line of largest norm into the pivot position.
941 //c
942  kmax=j;
943  for (k=j+1; k<nl; k++)
944  if (rdiag[k]>rdiag[kmax]) kmax=k;
945 
946  if (kmax!=j)
947  {
948  for (i=0; i<nc; i++)
949  {
950  temp = a[j][i];
951  a[j][i] = a[kmax][i];
952  a[kmax][i] = temp;
953  }
954  rdiag[kmax] = rdiag[j];
955  wa[kmax] = wa[j];
956  k = ipvt[j];
957  ipvt[j] = ipvt[kmax];
958  ipvt[kmax] = k;
959  }
960  }
961 //c
962 //c compute the householder transformation to reduce the
963 //c j-th line of a to a multiple of the j-th unit vector.
964 //c
965 
966 // ajnorm = enorm(nl-j+1,a(j,j))
967  ajnorm=::euclidianNorm(nc-j, &a[j][j]);
968 
969  if (ajnorm==0.0) { rdiag[j]=0.0; continue; }
970  if (a[j][j]<0.0) ajnorm = -ajnorm;
971  for (i=j; i<nc; i++) a[j][i]=a[j][i]/ajnorm;
972  a[j][j]+=1.0;
973 
974 //c
975 //c apply the transformation to the remaining lines
976 //c and update the norms.
977 //c
978  if (j>=nc) { rdiag[j] = -ajnorm; continue; }
979 
980  for (k = j+1; k<nl; k++)
981  {
982  sum=0.0;
983  for (i=j; i<nc; i++) sum=sum+a[j][i]*a[k][i];
984 
985  temp = sum/a[j][j];
986  for (i=j; i<nc; i++) a[k][i]=a[k][i]-temp*a[j][i];
987 
988  if ((!pivot)||(rdiag[k]==0.0)) continue;
989 
990  temp = a[k][j]/rdiag[k];
991  rdiag[k] *= sqrt(mmax(0.0,1.0-temp*temp));
992 
993  if (0.05*sqr(rdiag[k]/wa[k])> epsmch) continue;
994 
995  //rdiag(k) = enorm(nl-j,a(jp1,k))
996  rdiag[k]=::euclidianNorm(nc-j, &a[k][j+1]);
997  wa[k] = rdiag[k];
998  }
999  rdiag[j] = -ajnorm;
1000  }
1001 //c
1002 //c last card of subroutine qrfac.
1003 //c
1004  if (!(Rt==MatrixTriangle::emptyMatrixTriangle))
1005  {
1006  Rt.setSize(minmn);
1007  double **r=Rt;
1008  for (i=0; i<minmn; i++)
1009  {
1010  r[i][i]=rdiag[i];
1011  for (j=i+1; j<minmn; j++)
1012  r[j][i]=a[j][i];
1013  }
1014  }
1015 
1016  if (!(Q==Matrix::emptyMatrix))
1017  {
1018  Q.setSize(nc,nc);
1019  double **q=Q;
1020  Q.diagonal(1.0);
1021  for (j=nl-1; j>=0; j--)
1022  {
1023  if (a[j][j]==0.0) continue;
1024  for (k=j; k<nc; k++)
1025  {
1026  sum=0.0;
1027  for (i=j; i<nc; i++) sum=sum+a[j][i]*q[i][k];
1028 
1029  temp = sum/a[j][j];
1030  for (i=j; i<nc; i++) q[i][k]=q[i][k]-temp*a[j][i];
1031  }
1032  }
1033  }
1034 }
1035 
1036 #endif
1037 
1039 {
1040  int nn=d->extColumn+1, i=nLine();
1041  double *a=*d->p;
1042  while (i--) { (*a)+=dd; a+=nn; };
1043 }
1044 
1046 {
1047 // no tested
1048 // same code for the Vector eucilidian norm
1049 /*
1050  double sum=0, *a=*p;
1051  int i=nLine()*nColumn();
1052  while (i--) sum+=sqr(*(a++));
1053  return sqrt(sum);
1054 */
1056 }
1057 
1059 {
1060 // not tested
1061  double m=0, sum;
1062  int j,nl=nLine(), nc=nColumn();
1063  double **a=(*this), *xp;
1064  while (nl--)
1065  {
1066  sum=0; j=nc; xp=*(a++);
1067  while (j--) sum+=condorAbs(*(xp++));
1068  m=::mmax(m,sum);
1069  }
1070  return m;
1071 }
1072 
1074 {
1075  double **a=(*this), sum, maxSum=0;
1076  int i=nColumn(),j,k=0, nl=nLine();
1077  while (i--)
1078  {
1079  sum=0; j=nl;
1080  while(j--) sum+=sqr(a[j][i]);
1081  if (sum>maxSum)
1082  {
1083  maxSum=sum; k=i;
1084  }
1085  }
1086  Vector rr(nl);
1087  double *r=rr;
1088  j=nl;
1089 // while (j--) *(r++)=a[j][k];
1090  while (j--) r[j]=a[j][k];
1091  return rr;
1092 }
1093 
1094 Vector Matrix::getLine(int i, int n, int startc)
1095 {
1096  if (n==0) n=nColumn()-startc;
1097  Vector r(n,d->p[i]+startc);
1098  return r;
1099 }
1100 
1101 void Matrix::getLine(int i, Vector r, int n, int startc)
1102 {
1103  if (n==0) n=nColumn()-startc;
1104  r.setSize(n);
1105  memcpy((double*)r, d->p[i]+startc, n*sizeof(double));
1106 }
1107 
1109 {
1110  if (n==0) n=nLine();
1111  Vector r(n);
1112  double **d=*this, *rr=r;
1113  while (n--) rr[n]=d[n][i];
1114  return r;
1115 }
1116 
1117 void Matrix::getColumn(int i, Vector r, int n)
1118 {
1119  if (n==0) n=nLine();
1120  r.setSize(n);
1121  double **d=*this, *rr=r;
1122  while (n--) rr[n]=d[n][i];
1123 }
1124 
1125 void Matrix::setLine(int i, Vector v, int n)
1126 {
1127  if (n==0) n=nColumn();
1128  memcpy(d->p[i], (double*)v, n*sizeof(double));
1129 }
1130 
1131 void Matrix::setLines(int indexDest, Matrix Source, int indexSource, int number)
1132 {
1133  if (!Source.nLine()) return;
1134  double **dest=(*this), **sour=Source;
1135  int snl=d->nColumn*sizeof(double);
1136  if (number==0) number=Source.nLine()-indexSource;
1137  while (number--) memcpy(dest[indexDest+number], sour[indexSource+number], snl);
1138 }
1139 
1141 {
1143 }
1144 
1145 void Matrix::getSubMatrix(Matrix R, int startL, int startC, int nl, int nc)
1146 {
1147  if (nl==0) nl= nLine()-startL; else nl=mmin(nl, nLine()-startL);
1148  if (nc==0) nc=nColumn()-startC; else nc=mmin(nc,nColumn()-startC);
1149  R.setSize(nl,nc);
1150  double **sd=(*this), **dd=R;
1151  while (nl--)
1152  memcpy(dd[nl], sd[nl+startL]+startC, nc*sizeof(double));
1153 }
1154 
1155 void Matrix::swapLines(int i, int j)
1156 {
1157  if (i==j) return;
1158  int n=nColumn();
1159  double *p1=d->p[i], *p2=d->p[j], t;
1160  while (n--)
1161  {
1162  t=p1[n];
1163  p1[n]=p2[n];
1164  p2[n]=t;
1165  }
1166 }
1167 
1169 {
1170  if (nn==0) nn=mmin((int)nColumn(),(int)r.sz())*sizeof(double);
1171  else nn*=sizeof(double);
1172 
1173  int i=nLine();
1174  double **dp=d->p, *dp2=r;
1175  while (i--)
1176  if (memcmp(dp[i],dp2,nn)==0) break;
1177  return i;
1178 }
1179 
1180 void Matrix::setColNames(char **c, int nc)
1181 {
1182  if (c==NULL)
1183  {
1184  if (d->columnNames)
1185  {
1187  }
1188  return;
1189  }
1190  int l=0,i;
1191  if (nc==0) nc=d->nColumn;
1192  d->columnNames=(char**)malloc(nc*sizeof(char*));
1193  for (i=0; i<nc; i++) l+=(int)strlen(c[i])+1;
1194  char *t1=(char*)malloc(l);
1195  for (i=0; i<nc; i++)
1196  {
1197  d->columnNames[i]=t1;
1198  strcpy(t1,c[i]);
1199  t1+=(int)strlen(t1)+1;
1200  }
1201 }
1202 
1203 void Matrix::merge(Matrix m,int eliminateDoubles)
1204 {
1205  int nc=nColumn(), nlm=m.nLine();
1206  if (nlm==0) return;
1207  if (nc!=m.nColumn())
1208  {
1209  printf("Merging: Size do not agree.\n");
1210  exit(255);
1211  }
1212  int nl=nLine(),i,j;
1213  nc*=sizeof(double);
1214  double *pdi;
1215  for (i=0; i<nlm; i++)
1216  {
1217  pdi=((double**)m)[i];
1218  for (j=0; j<nl; j++)
1219  if (memcmp(d->p[j],pdi,nc)==0) break;
1220  if (j!=nl) continue;
1221  extendLine();
1222  memcpy(d->p[nl],pdi,nc);
1223  nl++;
1224  }
1225 }
1226 
1228 {
1229  int nl=nLine(), nc=nColumn(), mdim=tmp.sz();
1230  if (nc==0) setSize(1,mdim); else extendLine();
1231  setLine(nl,tmp,mdim);
1232 }
1233 
1234 /*
1235 int Matrix::solve(Vector vB)
1236 {
1237  double t;
1238  int i, j, k, l, info=0;
1239  int nl=nLine(), nc=nColumns();
1240 
1241  // gaussian elimination with partial pivoting
1242  if ( nl>1 )
1243  {
1244  for ( k=0; k<nl-1 ; k++ )
1245  {
1246  // find l = pivot index
1247  l=k; maxp=condorAbs(x[k][k]);
1248  for (i=k+1; i<nl; i++)
1249  if (condorAbs(x[i][k])>maxp) { maxp=condorAbs(x[i][k]); l=i; }
1250 
1251  jpvt[k] = l;
1252  // zero pivot implies this column already triangularized
1253  if ( maxp==0.0 ) info = k;
1254  else
1255  {
1256  // interchange if necessary
1257  if ( l!=k )
1258  {
1259  for (i=k; i<nc; i++)
1260  {
1261  t=x[l][i];
1262  x[l][i]=x[k][k];
1263  x[k][k]=t;
1264  }
1265  t=b[l]; b[l]=b[k]; b[k]=t;
1266  }
1267  // compute multipliers
1268  maxp=-1.0/maxp;
1269  for (i=k+1; i<nc; j++ ) x[k][i]*=maxp;
1270 
1271  // row elimination
1272  for (j=k+1; j<nl; j++ )
1273  {
1274  t=x[k][j];
1275  for (i=k+1; i<nc; i++) x[j][i] += t*x[k][i];
1276  }
1277  }
1278  }
1279  }
1280  if ( x[nl-1][nl-1]==0.0 ) info=nl-1;
1281  return;
1282 }
1283 */
void zero()
Definition: Matrix.cpp:553
double LnftyNorm()
Definition: Matrix.cpp:1058
int * mmax
double scalarProduct(int nl, Vector v)
Definition: Matrix.cpp:695
void setColNames(char **c, int nc=0)
Definition: Matrix.cpp:1180
void merge(Matrix m, int eliminateDoubles=1)
Definition: Matrix.cpp:1203
doublereal * c
#define pp(s, x)
Definition: ml2d.cpp:473
void transposeInPlace()
Definition: Matrix.cpp:500
void sqrt(Image< double > &op)
void QR(Matrix Q=Matrix::emptyMatrix, MatrixTriangle R=MatrixTriangle::emptyMatrixTriangle, VectorInt permutation=VectorInt::emptyVectorInt)
Definition: Matrix.cpp:820
Matrix multiply(Matrix B)
Definition: Matrix.cpp:633
Definition: Vector.h:37
void swapLines(int i, int j)
Definition: Matrix.cpp:1155
MatrixData * d
Definition: Matrix.h:48
void addInPlace(Matrix B)
Definition: Matrix.cpp:703
double euclidianNorm()
Definition: Vector.cpp:222
double mmin(const double t1, const double t2)
Definition: tools.h:69
void exactshape()
Definition: Matrix.cpp:379
void copyFrom(Matrix a)
Definition: Matrix.cpp:478
Matrix & operator=(const Matrix &A)
Definition: Matrix.cpp:451
void setSize(int _nLine, int _nColumn)
Definition: Matrix.cpp:205
void append(Vector tmp)
Definition: Matrix.cpp:1227
int nColumn()
Definition: Matrix.h:84
doublereal * x
#define i
ql0001_ & k(htemp+1),(cvec+1),(atemp+1),(bj+1),(bl+1),(bu+1),(x+1),(clamda+1), &iout, infoqp, &zero,(w+1), &lenw,(iw+1), &leniw, &glob_grd.epsmac
void setSize(int _n)
Definition: VectorInt.cpp:126
void setSize(int _n)
Definition: Vector.cpp:112
char * getFromLine(char *line)
Definition: Vector.cpp:575
void extendLine()
Definition: Matrix.cpp:181
char ** columnNames
Definition: Matrix.h:43
void print()
Definition: Matrix.cpp:418
void solveTransposInPlace(Vector y)
unsigned sz()
Definition: Vector.h:79
int nLine()
Definition: Matrix.h:83
double sqr(const double &t)
Definition: tools.h:99
int lineIndex(Vector r, int nn=0)
Definition: Matrix.cpp:1168
doublereal * b
void setNColumn(int _nColumn)
Definition: Matrix.cpp:199
void getSubMatrix(Matrix R, int startL, int StartC, int nl=0, int nc=0)
Definition: Matrix.cpp:1145
bool cholesky(MatrixTriangle matL, double lambda=0, double *lambdaCorrection=NULL)
Definition: Matrix.cpp:763
double * lambda
void solveInPlace(Vector b)
double euclidianNorm(int i, double *xp)
Definition: tools.cpp:113
double * f
void extendColumn()
Definition: Matrix.cpp:193
double frobeniusNorm()
Definition: Matrix.cpp:1045
void multiplyInPlace(double d)
Definition: Matrix.cpp:640
double euclidianNorm(int i)
Definition: Matrix.cpp:1140
static MatrixTriangle emptyMatrixTriangle
Vector getMaxColumn()
Definition: Matrix.cpp:1073
double condorAbs(const double t1)
Definition: tools.h:47
free((char *) ob)
Vector getColumn(int i, int n=0)
Definition: Matrix.cpp:1108
Definition: Matrix.h:38
Matrix(int _ligne=0, int _nColumn=0)
Definition: Matrix.cpp:60
#define j
int m
void setExtSize(int _extLine, int _extColumn)
Definition: Matrix.cpp:212
void setLines(int indexDest, Matrix Source, int indexSource=0, int number=0)
Definition: Matrix.cpp:1131
void init(int _nLine, int _nColumn, int _extLine, int _extColumn, MatrixData *d=NULL)
Definition: Matrix.cpp:37
void save(char *filename, char ascii)
Definition: Matrix.cpp:282
Vector getLine(int i, int n=0, int startCol=0)
Definition: Matrix.cpp:1094
Matrix transpose()
Definition: Matrix.cpp:539
void addUnityInPlace(double d)
Definition: Matrix.cpp:1038
void setLine(int i, Vector v, int n=0)
Definition: Matrix.cpp:1125
static VectorInt emptyVectorInt
Definition: VectorInt.h:70
Matrix clone()
Definition: Matrix.cpp:470
fprintf(glob_prnt.io, "\)
void multiplyByTranspose(Matrix R, Matrix a)
Definition: Matrix.cpp:613
void transposeAndMultiply(Vector R, Vector a)
Definition: Matrix.cpp:669
void setNLine(int _nLine)
Definition: Matrix.cpp:187
static Matrix emptyMatrix
Definition: Matrix.h:134
void addMultiplyInPlace(double d, Matrix B)
Definition: Matrix.cpp:720
int * n
doublereal * a
void setSize(int _n)
void choleskySolveInPlace(Vector b)
Definition: Matrix.cpp:808
char ** getNameTable(const char *line, int *ncolumn)
Definition: tools.cpp:204
void destroyCurrentBuffer()
Definition: Matrix.cpp:439
void diagonal(double d)
Definition: Matrix.cpp:65
void updateSave(char *saveFileName)
Definition: Matrix.cpp:349
void multiplyByDiagonalMatrix(Vector v)
Definition: Matrix.cpp:558
~Matrix()
Definition: Matrix.cpp:434