00001 #ifndef LHCBMATH_SYMMATRIXINVERTER_H
00002 #define LHCBMATH_SYMMATRIXINVERTER_H
00003
00011 namespace Gaudi
00012 {
00013 namespace Math
00014 {
00018 namespace SymMatrixInverter
00019 {
00021 template<class T> struct inverterForAllN
00022 {
00023 typedef typename T::value_type F;
00024 inline bool operator()(T& m, int N) const
00025 {
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 F l[(N * (N + 1)) / 2];
00037
00038 F o[N];
00039
00040
00041
00042
00043
00044 F *base1 = &l[0];
00045 for (int i = 0; i < N; base1 += ++i) {
00046 F tmpdiag = F(0);
00047
00048 F *base2 = &l[0];
00049 for (int j = 0; j < i; base2 += ++j) {
00050 F tmp = m(i, j);
00051 for (int k = j; k--; )
00052 tmp -= base1[k] * base2[k] * o[k];
00053 base1[j] = tmp *= base2[j] * o[j];
00054
00055 tmpdiag -= tmp * tmp * o[j];
00056 }
00057
00058 tmpdiag = m(i, i) + tmpdiag;
00059
00060 if (tmpdiag < F(0)) {
00061 tmpdiag = -tmpdiag;
00062 o[i] = F(-1);
00063 } else {
00064
00065 o[i] = F(1);
00066 }
00067 if (tmpdiag == F(0)) return false;
00068 else base1[i] = std::sqrt(F(1) / tmpdiag);
00069 }
00070
00071
00072 base1 = &l[1];
00073 for (int i = 1; i < N; base1 += ++i) {
00074 for (int j = 0; j < i; ++j) {
00075 F tmp = F(0);
00076 F *base2 = &l[(i * (i - 1)) / 2];
00077 for (int k = i; k-- > j; base2 -= k)
00078 tmp -= base1[k] * base2[j];
00079 base1[j] = tmp * base1[i];
00080 }
00081 }
00082
00083
00084 for (int i = N; i--; ) {
00085 for (int j = i + 1; j--; ) {
00086 F tmp = F(0);
00087 base1 = &l[(N * (N - 1)) / 2];
00088 for (int k = N; k-- > i; base1 -= k)
00089 tmp += base1[i] * base1[j] * o[k];
00090 m(i,j) = tmp;
00091 }
00092 }
00093
00094 return true;
00095 }
00096 };
00097
00099 template<class T, class F, int N> struct inverter
00100 {
00101 inline bool operator()(T& m) const
00102 { return inverterForAllN<T>()(m, T::kRows); }
00103 };
00104
00106 template<class T, class F> struct inverter<T,F,6>
00107 {
00108 inline bool operator()(T& m) const
00109 {
00110 F li11 = m(0,0), o1 = F(1);
00111 if (li11 < F(0)) li11 = -li11, o1 = -o1;
00112 if (li11 == F(0)) return false;
00113 else li11 = std::sqrt(F(1) / li11);
00114
00115 const F l21 = m(1,0) * li11 * o1;
00116 F li22 = m(1,1) - l21 * l21 * o1, o2 = F(1);
00117 if (li22 < F(0)) li22 = -li22, o2 = -o2;
00118 if (li22 == F(0)) return false;
00119 else li22 = std::sqrt(F(1) / li22);
00120
00121 const F l31 = m(2,0) * li11 * o1;
00122 const F l32 = (m(2,1) - l21 * l31 * o1) * li22 * o2;
00123
00124 F li33 = m(2,2) - (l31 * l31 * o1 + l32 * l32 * o2), o3 = F(1);
00125 if (li33 < F(0)) li33 = -li33, o3 = -o3;
00126 if (li33 == F(0)) return false;
00127 else li33 = std::sqrt(F(1) / li33);
00128
00129 const F l41 = m(3,0) * li11 * o1;
00130 const F l42 = (m(3,1) - l21 * l41 * o1) * li22 * o2;
00131 const F l43 = (m(3,2) - l31 * l41 * o1 - l32 * l42 * o2) * li33 * o3;
00132
00133 F li44 = m(3,3) - (l41 * l41 * o1 + l42 * l42 * o2 + l43 * l43 * o3),
00134 o4 = F(1);
00135 if (li44 < F(0)) li44 = -li44, o4 = -o4;
00136 if (li44 == F(0)) return false;
00137 else li44 = std::sqrt(F(1) / li44);
00138
00139 const F l51 = m(4,0) * li11 * o1;
00140 const F l52 = (m(4,1) - l21 * l51 * o1) * li22 * o2;
00141 const F l53 = (m(4,2) - l31 * l51 * o1 - l32 * l52 * o2) * li33 * o3;
00142 const F l54 = (m(4,3) - l41*l51*o1 - l42*l52*o2 - l43*l53*o3) * li44*o4;
00143
00144 F li55 = m(4,4) - (l51*l51*o1+l52*l52*o2+l53*l53*o3+l54*l54*o4), o5=F(1);
00145 if (li55 < F(0)) li55 = -li55, o5 = -o5;
00146 if (li55 == F(0)) return false;
00147 else li55 = std::sqrt(F(1) / li55);
00148
00149 const F l61 = m(5,0) * li11 * o1;
00150 const F l62 = (m(5,1) - l21 * l61 * o1) * li22 * o2;
00151 const F l63 = (m(5,2) - l31 * l61 * o1 - l32 * l62 * o2) * li33 * o3;
00152 const F l64 = (m(5,3) - l41*l61*o1-l42*l62*o2-l43*l63*o3)*li44*o4;
00153 const F l65=(m(5,4)-l51*l61*o1-l52*l62*o2-l53*l63*o3-l54*l64*o4)*li55*o5;
00154
00155 F li66 = m(5,5)-(l61*l61*o1+l62*l62*o2+l63*l63*o3+l64*l64*o4+l65*l65*o5),
00156 o6 = F(1);
00157 if (li66 < F(0)) li66 = -li66, o6 = -o6;
00158 if (li66 == F(0)) return false;
00159 else li66 = std::sqrt(F(1) / li66);
00160
00161 const F li21 = -l21 * li11 * li22;
00162 const F li32 = -l32 * li22 * li33;
00163 const F li31 = (l21 * l32 * li22 - l31) * li11 * li33;
00164 const F li43 = -l43 * li44 * li33;
00165 const F li42 = (l32 * l43 * li33 - l42) * li22 * li44;
00166 const F li41 = (-l21 * l32 * l43 * li22 * li33 +
00167 l21 * l42 * li22 + l31 * l43 * li33 - l41) * li11 * li44;
00168 const F li54 = -l54 * li55 * li44;
00169 const F li53 = (l54 * l43 * li44 - l53) * li33 * li55;
00170 const F li52 = (-l32 * l43 * l54 * li33 * li44 +
00171 l32 * l53 * li33 + l42 * l54 * li44 - l52) * li22 * li55;
00172 const F li51 = (l21*l32*l43*l54*li22*li33*li44 -
00173 l54*l43*l31*li44*li33 - l53*l32*l21*li22*li33 - l54*l42*l21*li44*li22 +
00174 l52*l21*li22 + l53*l31*li33 + l54*l41*li44 -l51) * li11 * li55;
00175 const F li65 = -l65 * li66 * li55;
00176 const F li64 = (l65 * l54 * li55 - l64) * li44 * li66;
00177 const F li63 = (-l43 * l54 * l65 * li44 * li55 +
00178 l43 * l64 * li44 + l53 * l65 * li55 - l63) * li33 * li66;
00179 const F li62 = (l32*l43*l54*l65*li33*li44*li55 -
00180 l64*l43*l32*li44*li33 - l65*l53*l32*li55*li33 - l65*l54*l42*li55*li44 +
00181 l63*l32*li33 + l64*l42*li44 + l65*l52*li55 - l62) * li22 * li66;
00182 const F li61 = (-l65*l54*l43*l32*l21*li22*li33*li44*li55 +
00183 l64*l43*l32*l21*li22*li33*li44 + l65*l53*l32*l21*li22*li33*li55 +
00184 l65*l54*l42*l21*li22*li44*li55 + l65*l54*l43*l31*li33*li44*li55 -
00185 l63*l32*l21*li22*li33 - l64*l42*l21*li22*li44 - l65*l52*l21*li22*li55 -
00186 l64*l43*l31*li33*li44 - l65*l53*l31*li33*li55 - l65*l54*l41*li44*li55 +
00187 l62*l21*li22 + l63*l31*li33 + l64*l41*li44 + l65*l51*li55 - l61) *
00188 li11 * li66;
00189
00190 m(0,0)=li61*li61*o6+li51*li51*o5+li41*li41*o4+li31*li31*o3+li21*li21*o2+
00191 li11*li11*o1;
00192 m(1,0)=li61*li62*o6+li51*li52*o5+li41*li42*o4+li31*li32*o3+li21*li22*o2;
00193 m(1,1)=li62*li62*o6+li52*li52*o5+li42*li42*o4+li32*li32*o3+li22*li22*o2;
00194 m(2,0)=li61*li63*o6+li51*li53*o5+li41*li43*o4+li31*li33*o3;
00195 m(2,1)=li62*li63*o6+li52*li53*o5+li42*li43*o4+li32*li33*o3;
00196 m(2,2)=li63*li63*o6+li53*li53*o5+li43*li43*o4+li33*li33*o3;
00197 m(3,0)=li61*li64*o6+li51*li54*o5+li41*li44*o4;
00198 m(3,1)=li62*li64*o6+li52*li54*o5+li42*li44*o4;
00199 m(3,2)=li63*li64*o6+li53*li54*o5+li43*li44*o4;
00200 m(3,3)=li64*li64*o6+li54*li54*o5+li44*li44*o4;
00201 m(4,0)=li61*li65*o6+li51*li55*o5;
00202 m(4,1)=li62*li65*o6+li52*li55*o5;
00203 m(4,2)=li63*li65*o6+li53*li55*o5;
00204 m(4,3)=li64*li65*o6+li54*li55*o5;
00205 m(4,4)=li65*li65*o6+li55*li55*o5;
00206 m(5,0)=li61*li66*o6;
00207 m(5,1)=li62*li66*o6;
00208 m(5,2)=li63*li66*o6;
00209 m(5,3)=li64*li66*o6;
00210 m(5,4)=li65*li66*o6;
00211 m(5,5)=li66*li66*o6;
00212
00213 return true;
00214 }
00215 };
00216
00218 template<class T, class F> struct inverter<T,F,5>
00219 {
00220 inline bool operator()(T& m) const
00221 {
00222 F li11 = m(0,0), o1 = F(1);
00223 if (li11 < F(0)) li11 = -li11, o1 = -o1;
00224 if (li11 == F(0)) return false;
00225 else li11 = std::sqrt(F(1) / li11);
00226
00227 const F l21 = m(1,0) * li11 * o1;
00228 F li22 = m(1,1) - l21 * l21 * o1, o2 = F(1);
00229 if (li22 < F(0)) li22 = -li22, o2 = -o2;
00230 if (li22 == F(0)) return false;
00231 else li22 = std::sqrt(F(1) / li22);
00232
00233 const F l31 = m(2,0) * li11 * o1;
00234 const F l32 = (m(2,1) - l21 * l31 * o1) * li22 * o2;
00235
00236 F li33 = m(2,2) - (l31 * l31 * o1 + l32 * l32 * o2), o3 = F(1);
00237 if (li33 < F(0)) li33 = -li33, o3 = -o3;
00238 if (li33 == F(0)) return false;
00239 else li33 = std::sqrt(F(1) / li33);
00240
00241 const F l41 = m(3,0) * li11 * o1;
00242 const F l42 = (m(3,1) - l21 * l41 * o1) * li22 * o2;
00243 const F l43 = (m(3,2) - l31 * l41 * o1 - l32 * l42 * o2) * li33 * o3;
00244
00245 F li44 = m(3,3) - (l41 * l41 * o1 + l42 * l42 * o2 + l43 * l43 * o3),
00246 o4 = F(1);
00247 if (li44 < F(0)) li44 = -li44, o4 = -o4;
00248 if (li44 == F(0)) return false;
00249 else li44 = std::sqrt(F(1) / li44);
00250
00251 const F l51 = m(4,0) * li11 * o1;
00252 const F l52 = (m(4,1) - l21 * l51 * o1) * li22 * o2;
00253 const F l53 = (m(4,2) - l31 * l51 * o1 - l32 * l52 * o2) * li33 * o3;
00254 const F l54 = (m(4,3) - l41*l51*o1 - l42*l52*o2 - l43*l53*o3) * li44*o4;
00255
00256 F li55 = m(4,4) - (l51*l51*o1+l52*l52*o2+l53*l53*o3+l54*l54*o4), o5=F(1);
00257 if (li55 < F(0)) li55 = -li55, o5 = -o5;
00258 if (li55 == F(0)) return false;
00259 else li55 = std::sqrt(F(1) / li55);
00260
00261 const F li21 = -l21 * li11 * li22;
00262 const F li32 = -l32 * li22 * li33;
00263 const F li31 = (l21 * l32 * li22 - l31) * li11 * li33;
00264 const F li43 = -l43 * li44 * li33;
00265 const F li42 = (l32 * l43 * li33 - l42) * li22 * li44;
00266 const F li41 = (-l21 * l32 * l43 * li22 * li33 +
00267 l21 * l42 * li22 + l31 * l43 * li33 - l41) * li11 * li44;
00268 const F li54 = -l54 * li55 * li44;
00269 const F li53 = (l54 * l43 * li44 - l53) * li33 * li55;
00270 const F li52 = (-l32 * l43 * l54 * li33 * li44 +
00271 l32 * l53 * li33 + l42 * l54 * li44 - l52) * li22 * li55;
00272 const F li51 = (l21*l32*l43*l54*li22*li33*li44 -
00273 l54*l43*l31*li44*li33 - l53*l32*l21*li22*li33 - l54*l42*l21*li44*li22 +
00274 l52*l21*li22 + l53*l31*li33 + l54*l41*li44 -l51) * li11 * li55;
00275
00276 m(0,0)=li51*li51*o5+li41*li41*o4+li31*li31*o3+li21*li21*o2+li11*li11*o1;
00277 m(1,0)=li51*li52*o5+li41*li42*o4+li31*li32*o3+li21*li22*o2;
00278 m(1,1)=li52*li52*o5+li42*li42*o4+li32*li32*o3+li22*li22*o2;
00279 m(2,0)=li51*li53*o5+li41*li43*o4+li31*li33*o3;
00280 m(2,1)=li52*li53*o5+li42*li43*o4+li32*li33*o3;
00281 m(2,2)=li53*li53*o5+li43*li43*o4+li33*li33*o3;
00282 m(3,0)=li51*li54*o5+li41*li44*o4;
00283 m(3,1)=li52*li54*o5+li42*li44*o4;
00284 m(3,2)=li53*li54*o5+li43*li44*o4;
00285 m(3,3)=li54*li54*o5+li44*li44*o4;
00286 m(4,0)=li51*li55*o5;
00287 m(4,1)=li52*li55*o5;
00288 m(4,2)=li53*li55*o5;
00289 m(4,3)=li54*li55*o5;
00290 m(4,4)=li55*li55*o5;
00291
00292 return true;
00293 }
00294 };
00295
00297 template<class T, class F> struct inverter<T,F,4>
00298 {
00299 inline bool operator()(T& m) const
00300 {
00301 F li11 = m(0,0), o1 = F(1);
00302 if (li11 < F(0)) li11 = -li11, o1 = -o1;
00303 if (li11 == F(0)) return false;
00304 else li11 = std::sqrt(F(1) / li11);
00305
00306 const F l21 = m(1,0) * li11 * o1;
00307 F li22 = m(1,1) - l21 * l21 * o1, o2 = F(1);
00308 if (li22 < F(0)) li22 = -li22, o2 = -o2;
00309 if (li22 == F(0)) return false;
00310 else li22 = std::sqrt(F(1) / li22);
00311
00312 const F l31 = m(2,0) * li11 * o1;
00313 const F l32 = (m(2,1) - l21 * l31 * o1) * li22 * o2;
00314
00315 F li33 = m(2,2) - (l31 * l31 * o1 + l32 * l32 * o2), o3 = F(1);
00316 if (li33 < F(0)) li33 = -li33, o3 = -o3;
00317 if (li33 == F(0)) return false;
00318 else li33 = std::sqrt(F(1) / li33);
00319
00320 const F l41 = m(3,0) * li11 * o1;
00321 const F l42 = (m(3,1) - l21 * l41 * o1) * li22 * o2;
00322 const F l43 = (m(3,2) - l31 * l41 * o1 - l32 * l42 * o2) * li33 * o3;
00323
00324 F li44 = m(3,3) - (l41 * l41 * o1 + l42 * l42 * o2 + l43 * l43 * o3),
00325 o4 = F(1);
00326 if (li44 < F(0)) li44 = -li44, o4 = -o4;
00327 if (li44 == F(0)) return false;
00328 else li44 = std::sqrt(F(1) / li44);
00329
00330 const F li21 = -l21 * li11 * li22;
00331 const F li32 = -l32 * li22 * li33;
00332 const F li31 = (l21 * l32 * li22 - l31) * li11 * li33;
00333 const F li43 = -l43 * li44 * li33;
00334 const F li42 = (l32 * l43 * li33 - l42) * li22 * li44;
00335 const F li41 = (-l21 * l32 * l43 * li22 * li33 +
00336 l21 * l42 * li22 + l31 * l43 * li33 - l41) * li11 * li44;
00337
00338 m(0,0)=li41*li41*o4+li31*li31*o3+li21*li21*o2+li11*li11*o1;
00339 m(1,0)=li41*li42*o4+li31*li32*o3+li21*li22*o2;
00340 m(1,1)=li42*li42*o4+li32*li32*o3+li22*li22*o2;
00341 m(2,0)=li41*li43*o4+li31*li33*o3;
00342 m(2,1)=li42*li43*o4+li32*li33*o3;
00343 m(2,2)=li43*li43*o4+li33*li33*o3;
00344 m(3,0)=li41*li44*o4;
00345 m(3,1)=li42*li44*o4;
00346 m(3,2)=li43*li44*o4;
00347 m(3,3)=li44*li44*o4;
00348
00349 return true;
00350 }
00351 };
00352
00354 template<class T, class F> struct inverter<T,F,3>
00355 {
00356 inline bool operator()(T& m) const
00357 {
00358 F li11 = m(0,0), o1 = F(1);
00359 if (li11 < F(0)) li11 = -li11, o1 = -o1;
00360 if (li11 == F(0)) return false;
00361 else li11 = std::sqrt(F(1) / li11);
00362
00363 const F l21 = m(1,0) * li11 * o1;
00364 F li22 = m(1,1) - l21 * l21 * o1, o2 = F(1);
00365 if (li22 < F(0)) li22 = -li22, o2 = -o2;
00366 if (li22 == F(0)) return false;
00367 else li22 = std::sqrt(F(1) / li22);
00368
00369 const F l31 = m(2,0) * li11 * o1;
00370 const F l32 = (m(2,1) - l21 * l31 * o1) * li22 * o2;
00371
00372 F li33 = m(2,2) - (l31 * l31 * o1 + l32 * l32 * o2), o3 = F(1);
00373 if (li33 < F(0)) li33 = -li33, o3 = -o3;
00374 if (li33 == F(0)) return false;
00375 else li33 = std::sqrt(F(1) / li33);
00376
00377 const F li21 = -l21 * li11 * li22;
00378 const F li32 = -l32 * li22 * li33;
00379 const F li31 = (l21 * l32 * li22 - l31) * li11 * li33;
00380
00381 m(0,0)=li31*li31*o3+li21*li21*o2+li11*li11*o1;
00382 m(1,0)=li31*li32*o3+li21*li22*o2;
00383 m(1,1)=li32*li32*o3+li22*li22*o2;
00384 m(2,0)=li31*li33*o3;
00385 m(2,1)=li32*li33*o3;
00386 m(2,2)=li33*li33*o3;
00387
00388 return true;
00389 }
00390 };
00391
00393 template<class T, class F> struct inverter<T,F,2>
00394 {
00395 inline bool operator()(T& m) const
00396 {
00397 F li11 = m(0,0), o1 = F(1);
00398 if (li11 < F(0)) li11 = -li11, o1 = -o1;
00399 if (li11 == F(0)) return false;
00400 else li11 = std::sqrt(F(1) / li11);
00401
00402 const F l21 = m(1,0) * li11 * o1;
00403 F li22 = m(1,1) - l21 * l21 * o1, o2 = F(1);
00404 if (li22 < F(0)) li22 = -li22, o2 = -o2;
00405 if (li22 == F(0)) return false;
00406 else li22 = std::sqrt(F(1) / li22);
00407
00408 const F li21 = -l21 * li11 * li22;
00409
00410 m(0,0)=li21*li21*o2+li11*li11*o1;
00411 m(1,0)=li21*li22*o2;
00412 m(1,1)=li22*li22*o2;
00413
00414 return true;
00415 }
00416 };
00417
00419 template<class T, class F> struct inverter<T,F,1>
00420 {
00421 inline bool operator()(T& m) const
00422 {
00423 if (std::abs(m(0,0)) == F(0)) return false;
00424 m(0,0) = F(1) / m(0,0);
00425 return true;
00426 }
00427 };
00428
00430 template<class T, class F> struct inverter<T,F,0>
00431 {
00432 private:
00433
00434 virtual bool operator()(T& m) const = 0;
00435 };
00436 }
00437 }
00438 }
00439
00440 #endif // LHCBMATH_SYMMATRIXINVERTER_H
00441
00442