FEDRA emulsion software from the OPERA Collaboration
Dsinv.hh
Go to the documentation of this file.
1 #ifndef __DSINV_HH
2 #define __DSINV_HH
3 // ********************************************************************
4 //
5 // source:
6 //
7 // type: source code
8 //
9 // created: 22. Mar 2001
10 //
11 // author: Thorsten Glebe
12 // HERA-B Collaboration
13 // Max-Planck-Institut fuer Kernphysik
14 // Saupfercheckweg 1
15 // 69117 Heidelberg
16 // Germany
17 // E-mail: T.Glebe@mpi-hd.mpg.de
18 //
19 // Description: Inversion of a symmetric, positive definite matrix.
20 // Code was taken from CERNLIB::kernlib dsinv function, translated
21 // from FORTRAN to C++ and optimized.
22 //
23 // changes:
24 // 22 Mar 2001 (TG) creation
25 //
26 // ********************************************************************
27 
34 template <class T, int n, int idim>
35 bool Dsinv(T* a) {
36 
37  /* Local variables */
38  static int i, j, k, l;
39  static T s31, s32;
40  static int jm1, jp1;
41 
42  /* Parameter adjustments */
43  a -= idim + 1;
44 
45  /* Function Body */
46  if (idim < n || n <= 1) {
47  return false;
48  }
49 
50  /* sfact.inc */
51  for (j = 1; j <= n; ++j) {
52  const int ja = j * idim;
53  const int jj = j + ja;
54  const int ja1 = ja + idim;
55 
56  if (a[jj] <= 0.) { return false; }
57  a[jj] = 1. / a[jj];
58  if (j == n) { break; }
59 
60  for (l = j + 1; l <= n; ++l) {
61  a[j + l * idim] = a[jj] * a[l + ja];
62  const int lj = l + ja1;
63  for (i = 1; i <= j; ++i) {
64  a[lj] -= a[l + i * idim] * a[i + ja1];
65  }
66  }
67  }
68 
69  /* sfinv.inc */
70  // idim << 1 is equal to idim * 2
71  // compiler will compute the arguments!
72  a[(idim << 1) + 1] = -a[(idim << 1) + 1];
73  a[idim + 2] = a[(idim << 1) + 1] * a[(idim << 1) + 2];
74 
75  if(n > 2) {
76 
77  for (j = 3; j <= n; ++j) {
78  const int jm2 = j - 2;
79  const int ja = j * idim;
80  const int jj = j + ja;
81  const int j1 = j - 1 + ja;
82 
83  for (k = 1; k <= jm2; ++k) {
84  s31 = a[k + ja];
85 
86  for (i = k; i <= jm2; ++i) {
87  s31 += a[k + (i + 1) * idim] * a[i + 1 + ja];
88  } // for i
89  a[k + ja] = -s31;
90  a[j + k * idim] = -s31 * a[jj];
91  } // for k
92  a[j1] *= -1;
93  // a[j1] = -a[j1];
94  a[jj - idim] = a[j1] * a[jj];
95  } // for j
96  } // if (n>2)
97 
98  j = 1;
99  do {
100  const int jad = j * idim;
101  const int jj = j + jad;
102 
103  jp1 = j + 1;
104  for (i = jp1; i <= n; ++i) {
105  a[jj] += a[j + i * idim] * a[i + jad];
106  } // for i
107 
108  jm1 = j;
109  j = jp1;
110  const int ja = j * idim;
111 
112  for (k = 1; k <= jm1; ++k) {
113  s32 = 0.;
114  for (i = j; i <= n; ++i) {
115  s32 += a[k + i * idim] * a[i + ja];
116  } // for i
117  a[k + ja] = a[j + k * idim] = s32;
118  } // for k
119  } while(j < n);
120 
121  return true;
122 } // end of Dsinv
123 
124 #endif
bool Dsinv(T *a)
Definition: Dsinv.hh:35
void a()
Definition: check_aligned.C:59