StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
TRSymMatrix.cxx
1 #include <iomanip>
2 #include "TMath.h"
3 #include "TRVector.h"
4 #include "TRSymMatrix.h"
5 #include "TRDiagMatrix.h"
6 #include "TError.h"
7 ClassImp(TRSymMatrix);
8 //________________________________________________________________________________
9 TRSymMatrix::TRSymMatrix(Int_t nrows,Double_t a0, ...) :
10  TRArray(nrows*(nrows+1)/2), fNrows(nrows) {
11  __VA_LIST__(a0);
12 }
13 //________________________________________________________________________________
14 TRSymMatrix::TRSymMatrix(Int_t nrows,const Double_t *Array) : TRArray() {
15  fNrows = TMath::Abs(nrows);
16  if (nrows > 0) Set(fNrows*(fNrows+1)/2,Array);
17  else {// Upper to Lower
18  Set(fNrows*(fNrows+1)/2);
19  Int_t ij;
20  Int_t i = 0, j = 0;
21  for (Int_t l = 0; l < fN; l++) {
22  ij = i*(i+1)/2 + j;
23  fArray[ij] = Array[l];
24  if (i < fNrows - 1) i++;
25  else {
26  j++;
27  i = j;
28  }
29  }
30  }
31 }
32 //________________________________________________________________________________
33 TRSymMatrix::TRSymMatrix(Int_t nrows,const Float_t *Array) : TRArray() {
34  fNrows = TMath::Abs(nrows);
35  if (nrows > 0) {
36  Set(fNrows*(fNrows+1)/2);
37  TCL::ucopy(Array,fArray,fNrows*(fNrows+1)/2);
38  }
39  else {// Upper to Lower
40  Set(fNrows*(fNrows+1)/2);
41  Int_t ij;
42  Int_t i = 0, j = 0;
43  for (Int_t l = 0; l < fN; l++) {
44  ij = i*(i+1)/2 + j;
45  fArray[ij] = Array[l];
46  if (i < fNrows - 1) i++;
47  else {
48  j++;
49  i = j;
50  }
51  }
52  }
53 }
54 //________________________________________________________________________________
55 TRSymMatrix::TRSymMatrix(Int_t nrows,const Char_t *s) : TRArray(nrows*(nrows+1)/2,s), fNrows(nrows) {}
56 //________________________________________________________________________________
57 TRSymMatrix::TRSymMatrix(ETRMatrixCreatorsOp kop,Int_t nrows) :
58  TRArray(nrows*(nrows+1)/2), fNrows(nrows){
59  switch (kop) {
60  case kZero:
61  break;
62  case kUnit:
63  for (int i=0; i<fNrows; i++) fArray[i*(i+1)/2+i] = 1;
64  break;
65  default:
66  Error("TRSymMatrix(ETRMatrixCreatorsOp)", "operation %d not yet implemented", kop);
67  }
68 
69 }
70 //________________________________________________________________________________
71 TRSymMatrix::TRSymMatrix(const TRSymMatrix& S,ETRMatrixCreatorsOp kop) {
72  switch (kop) {
73  case kInvertedPosDef:
74  SpmInv(S);
75  break;
76  case kInverted:
77  fNrows = S.GetNcols();
78  Set(fNrows*(fNrows+1)/2);
79  TCL::trsinv(S.GetArray(),fArray, fNrows);
80  break;
81  case kInvertedA:
82  fNrows = S.GetNcols();
83  Set(fNrows*(fNrows+1)/2);
84  fValid = ! TrsInv(S.GetArray(),fArray, fNrows);
85  break;
86  default:
87  Error("TRSymMatrix(ETRMatrixCreatorsOp)", "operation %d not yet implemented", kop);
88  }
89 }
90 //________________________________________________________________________________
91 TRSymMatrix::TRSymMatrix(const TRMatrix& A) {
92  Int_t NI = A.GetNrows(); fNrows = NI;
93  Int_t NJ = A.GetNcols();
94  assert(NI == NJ);
95  Set(fNrows*(fNrows+1)/2);
96  TCL::trpck(A.GetArray(),fArray,NI);
97 }
98 //________________________________________________________________________________
99 TRSymMatrix::TRSymMatrix(const TRMatrix& A,ETRMatrixCreatorsOp kop,const TRSymMatrix& S) {
100  Int_t M, N;
101  switch (kop) { //
102  case kAxSxAT: //A[M,N]*S[N,N]*AT[M,N] => R[M,M];
103  M = A.GetNrows();
104  N = S.GetNrows();
105  assert(N == A.GetNcols());
106  fNrows = M;
107  Set(fNrows*(fNrows+1)/2);
108  TCL::trasat(A.GetArray(),S.GetArray(),fArray,M,N);
109  break;
110  case kATxSxA: //BT[N,M]*S[N,N]*B[N,M] => R[M,M];
111  M = A.GetNcols();
112  N = S.GetNrows();
113  assert(N == A.GetNrows());
114  fNrows = M;
115  Set(fNrows*(fNrows+1)/2);
116  TCL::tratsa(A.GetArray(),S.GetArray(),fArray,M,N);
117  break;
118  default:
119  Error("TRSymMatrix(ETRMatrixCreatorsOp)", "operation %d not yet implemented", kop);
120  }
121 }
122 //________________________________________________________________________________
123 TRSymMatrix::TRSymMatrix(const TRSymMatrix& Q,ETRMatrixCreatorsOp kop,const TRSymMatrix& T){
124  assert (kop == kRxSxR);
125  Int_t M = Q.GetNcols();
126  assert(M == T.GetNcols());
127  fNrows = M;
128  Set(fNrows*(fNrows+1)/2);
129  TCL::trqsq(Q.GetArray(),T.GetArray(),fArray,M);
130 }
131 //________________________________________________________________________________
132 TRSymMatrix::TRSymMatrix(const TRMatrix& A,ETRMatrixCreatorsOp kop) {
133  Int_t M, N;
134  switch (kop) {
135  case kAxAT: // A[M,N]*AT[M,N] => S[M,M]
136  M = A.GetNrows();
137  N = A.GetNcols();
138  fNrows = M;
139  Set(fNrows*(fNrows+1)/2);
140  TCL::traat(A.GetArray(),fArray,M,N);
141  break;
142  case kATxA: // AT[N,M]*A[N,M] => S[M,M]
143  N = A.GetNrows();
144  M = A.GetNcols();
145  fNrows = M;
146  Set(fNrows*(fNrows+1)/2);
147  TCL::trata(A.GetArray(),fArray,M,N);
148  break;
149  default:
150  Error("TRSymMatrix(ETRMatrixCreatorsOp)", "operation %d not yet implemented", kop);
151  }
152 }
153 //________________________________________________________________________________
154 Double_t TRSymMatrix::Product(const TRVector& A,ETRMatrixCreatorsOp /* kop */) {
155  Int_t M, N; // N == 1
156  Double_t Value;
157  // case kAxSxAT: //A[M,N]*S[N,N]*AT[M,N] => R[M,M];
158  // case kATxSxA: //BT[N,M]*S[N,N]*B[N,M] => R[M,M];
159  M = A.GetNcols();
160  N = GetNrows();
161  assert(N == A.GetNrows());
162  TCL::tratsa(A.GetArray(),GetArray(),&Value,M,N);
163  return Value;
164 }
165 //________________________________________________________________________________
166 ostream& operator<<(ostream& s,const TRSymMatrix &target) {
167  static const int width = 10;
168  Int_t Nrows = target.GetNrows();
169  const Double_t *Array = target.GetArray();
170  s << "Semi Positive DefinedSymMatrix Size \t["
171  << Nrows << "," << Nrows << "]" << endl;
172  if (Array) {
173  s.setf(std::ios::fixed,std::ios::scientific);
174  s.setf(std::ios::showpos);
175  for (int i = 0; i< Nrows; i++) {
176  for (int j = 0; j <= i; j++)
177  s << std::setw(width) << std::setprecision(width-3) << Array[i*(i+1)/2 + j] << ":\t";
178  s << endl;
179  }
180  s.unsetf(std::ios::showpos);
181  }
182  else s << " Empty";
183  return s;
184 }
185 //________________________________________________________________________________
186 void TRSymMatrix::Print(Option_t *opt) const {if (opt) {}; cout << *this << endl;}
187 //________________________________________________________________________________
188 Int_t TRSymMatrix::SpmInv(const TRSymMatrix &S, TRVector *B) {
189  if (&S != this) *this = S;
190  Double_t *diag = new Double_t[fNrows];
191  Bool_t *flag = new Bool_t[fNrows];
192  Double_t *b = 0;
193  if (B) b = B->GetArray();
194  Int_t nrank = 0;
195  spminv(fArray, b, fNrows, nrank, diag, flag);
196  delete [] diag;
197  delete [] flag;
198  return nrank;
199 }
200 //________________________________________________________________________________
201 Int_t TRSymMatrix::spminv(Double_t *v, Double_t *b, Int_t n,
202  Int_t &nrank, Double_t *diag, Bool_t *flag) {
203  // taken from Millepede (V.Blobel)
204  /* Local variables */
205  static Int_t i, j, k, l, jj, jk, kk, jl, lk;
206  static Double_t vjk, vkk;
207 
208  /* obtain solution of a system of linear equations with symmetric */
209  /* matrix and the inverse. */
210 
211  /* - - - */
212  /* CALL SPMINV(V,B,N,NRANK,...,...) solve V * X = B */
213  /* - - ----- */
214 
215  /* V = symmetric N-by-N matrix in symmetric storage mode */
216  /* V(1) = V11, V(2) = V12, V(3) = V22, V(4) = V13, . . . */
217  /* replaced by inverse matrix */
218  /* B = N-vector, replaced by solution vector */
219 
220  /* DIAG(N) = double precision scratch array */
221  /* FLAG(N) = Bool_t scratch array */
222 
223  /* Method of solution is by elimination selecting the pivot on the */
224  /* diagonal each stage. The rank of the matrix is returned in NRANK. */
225  /* For NRANK ne N, all remaining rows and cols of the resulting */
226  /* matrix V and the corresponding elements of B are set to zero. */
227 
228  /* ... */
229  /* Parameter adjustments */
230  --v;
231  --diag;
232  if (b) --b;
233  --flag;
234 
235  /* Function Body */
236  for (i = 1; i <= n; ++i) {
237  flag[i] = kTRUE; /* reset flags */
238  diag[i] = TMath::Abs(v[(i * i + i) / 2]); /* save TMath::Abs of diagonal elements */
239  }
240  nrank = 0;
241  for (i = 1; i <= n; ++i) {/* start of loop */
242  k = jj = kk = 0;
243  vkk = 0.;
244  for (j = 1; j <= n; ++j) {/* search for pivot */
245  jj += j;
246  if (flag[j]) {/* not used so far Computing MAX */
247  if (TMath::Abs(v[jj]) > TMath::Max(TMath::Abs(vkk),diag[j] * 1e-10)) {
248  vkk = v[jj]; /* pivot (candidate) */
249  k = j; /* index of pivot */
250  kk = jj; /* index of diagonal element */
251  }
252  }
253  }
254  if (k != 0) { /* pivot found */
255  ++nrank; /* increase rank and ... */
256  flag[k] = kFALSE; /* ... reset flag */
257  vkk = 1. / vkk;
258  v[kk] = -vkk;
259  if (b) b[k] *= vkk;
260  jk = kk - k;
261  jl = 0;
262  for (j = 1; j <= n; ++j) {/* elimination */
263  if (j == k) {
264  jk = kk;
265  jl += j;
266  } else {
267  if (j < k) {
268  ++jk;
269  } else {
270  jk = jk + j - 1;
271  }
272  vjk = v[jk];
273  v[jk] = vkk * vjk;
274  if (b) b[j] -= b[k] * vjk;
275  lk = kk - k;
276  for (l = 1; l <= j; ++l) {
277  ++jl;
278  if (l == k) {
279  lk = kk;
280  } else {
281  if (l < k) {
282  ++lk;
283  } else {
284  lk = lk + l - 1;
285  }
286  v[jl] -= v[lk] * vjk;
287  }
288  }
289  }
290  }
291  } else {
292  for (k = 1; k <= n; ++k) {
293  if (flag[k]) {
294  if (b) b[k] = 0.; /* clear vector element */
295  for (j = 1; j <= k; ++j) {
296  if (flag[j]) {
297  v[(k * k - k) / 2 + j] = 0.;
298  } /* clear matrix row/col */
299  }
300  }
301  }
302  goto L10;
303  }
304  } /* end of loop */
305  L10: Int_t nn = (n * n + n) / 2;
306  for (Int_t ij = 1; ij <= nn; ++ij) {
307  v[ij] = -v[ij]; /* finally reverse sign of all matrix elements */
308  }
309  return 0;
310 }
311 //________________________________________________________________________________
312 Int_t TRSymMatrix::TrsInv(const Double_t *g, Double_t *gi, Int_t n) {
313  Int_t fail = TrchLU(g, gi, n);
314  fail += TrInv(gi, gi, n);
315  TrsmUL(gi, gi,n);
316  return fail;
317 }
318 //________________________________________________________________________________
319 Int_t TRSymMatrix::TrchLU(const double *a, double *b, int n) {
320  Int_t fail = 0;
321  /* Local variables */
322  int ipiv, kpiv, i__, j;
323  double r__, dc;
324  int id, kd;
325  double sum;
326 
327 
328  /* CERN PROGLIB# F112 TRCHLU .VERSION KERNFOR 4.16 870601 */
329  /* ORIG. 18/12/74 W.HART */
330 
331 
332  /* Parameter adjuTments */
333  --b; --a;
334 
335  /* Function Body */
336  ipiv = 0;
337 
338  i__ = 0;
339 
340  do {
341  ++i__;
342  ipiv += i__;
343  kpiv = ipiv;
344  r__ = a[ipiv];
345 
346  for (j = i__; j <= n; ++j) {
347  sum = 0.;
348  if (i__ == 1) goto L40;
349  if (r__ == 0.) goto L42;
350  id = ipiv - i__ + 1;
351  kd = kpiv - i__ + 1;
352 
353  do {
354  sum += b[kd] * b[id];
355  ++kd; ++id;
356  } while (id < ipiv);
357 
358 L40:
359  sum = a[kpiv] - sum;
360 L42:
361  if (j != i__) b[kpiv] = sum * r__;
362  else {
363  if (sum > 0) dc = TMath::Sqrt(sum);
364  else dc = 0;
365  b[kpiv] = dc;
366  if (r__ > 0. && dc > 0) r__ = (double)1. / dc;
367  else {r__ = 0; fail++;}
368  }
369  kpiv += j;
370  }
371 
372  } while (i__ < n);
373  return fail;
374 }
375 //________________________________________________________________________________
376 Int_t TRSymMatrix::TrInv(const Double_t *g, Double_t *gi, Int_t n) {TCL::trinv(g, gi, n); return 0;}
377 //________________________________________________________________________________
378 Int_t TRSymMatrix::TrsmUL(const Double_t *g, Double_t *gi, Int_t n) {TCL::trsmul(g, gi, n); return 0;}
379 #if 0
380 //________________________________________________________________________________
381 Double_t &TRSymMatrix::operator()(Int_t i,Int_t j){
382  // assert(! (j < 0 || j >= fNrows));
383  if (j < 0 || j >= fNrows) {
384  ::Error("TRSymMatrix::operator()", "index j %d out of bounds (size: %d, this: %p)",
385  j, fNrows, this);
386  j = 0;
387  }
388  // assert(! (i < 0 || i >= fNrows));
389  if (i < 0 || i >= fNrows) {
390  ::Error("TRSymMatrix::operator()", "index i %d out of bounds (size: %d, this: %p)",
391  i, fNrows, this);
392  i = 0;
393  }
394  Int_t m = i;
395  Int_t l = j;
396  if (i > j) {m = j; l = i;}
397  return TArrayD::operator[](m + (l+1)*l/2);
398 }
399 #endif
static float * traat(const float *a, float *s, int m, int n)
Definition: TCernLib.cxx:293
Definition: FJcore.h:367
static float * trsmul(const float *g, float *gi, int n)
Definition: TCernLib.cxx:1212
static float * trata(const float *a, float *r, int m, int n)
Definition: TCernLib.cxx:589
static float * trinv(const float *t, float *s, int n)
Definition: TCernLib.cxx:857
static float * trpck(const float *s, float *u, int n)
Definition: TCernLib.cxx:1010
static float * trqsq(const float *q, const float *s, float *r, int m)
Definition: TCernLib.cxx:1045
static float * trsinv(const float *g, float *gi, int n)
Definition: TCernLib.cxx:1160
static float * trasat(const float *a, const float *s, float *r, int m, int n)
Definition: TCernLib.cxx:540
static float * tratsa(const float *a, const float *s, float *r, int m, int n)
Definition: TCernLib.cxx:677