00001 #ifndef LHCBMATH_SYMPOSDEFMATRIXINVERTER_H
00002 #define LHCBMATH_SYMPOSDEFMATRIXINVERTER_H
00003
00011 namespace Gaudi
00012 {
00013 namespace Math
00014 {
00018 namespace SymPosDefMatrixInverter
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 F l[(N * (N + 1)) / 2];
00033
00034
00035
00036
00037
00038 F *base1 = &l[0];
00039 for (int i = 0; i < N; base1 += ++i) {
00040 F tmpdiag = F(0);
00041
00042 F *base2 = &l[0];
00043 for (int j = 0; j < i; base2 += ++j) {
00044 F tmp = m(i, j);
00045 for (int k = j; k--; )
00046 tmp -= base1[k] * base2[k];
00047 base1[j] = tmp *= base2[j];
00048
00049 tmpdiag += tmp * tmp;
00050 }
00051
00052 tmpdiag = m(i, i) - tmpdiag;
00053
00054 if (tmpdiag <= F(0)) return false;
00055 else base1[i] = std::sqrt(F(1) / tmpdiag);
00056 }
00057
00058
00059 base1 = &l[1];
00060 for (int i = 1; i < N; base1 += ++i) {
00061 for (int j = 0; j < i; ++j) {
00062 F tmp = F(0);
00063 F *base2 = &l[(i * (i - 1)) / 2];
00064 for (int k = i; k-- > j; base2 -= k)
00065 tmp -= base1[k] * base2[j];
00066 base1[j] = tmp * base1[i];
00067 }
00068 }
00069
00070
00071 for (int i = N; i--; ) {
00072 for (int j = i + 1; j--; ) {
00073 F tmp = F(0);
00074 base1 = &l[(N * (N - 1)) / 2];
00075 for (int k = N; k-- > i; base1 -= k)
00076 tmp += base1[i] * base1[j];
00077 m(i,j) = tmp;
00078 }
00079 }
00080
00081 return true;
00082 }
00083 };
00084
00086 template<class T, class F, int N> struct inverter
00087 {
00089 inline bool operator()(T& m) const
00090 { return inverterForAllN<T>()(m, T::kRows); }
00091 };
00092
00094 template<class T, class F> struct inverter<T,F,6>
00095 {
00096 inline bool operator()(T& m) const
00097 {
00098 if (m(0,0) <= F(0)) return false;
00099 const F li11 = std::sqrt(F(1) / m(0,0));
00100 const F l21 = m(1,0) * li11;
00101 F li22 = m(1,1) - l21 * l21;
00102 if (li22 <= F(0)) return false;
00103 else li22 = std::sqrt(F(1) / li22);
00104 const F l31 = m(2,0) * li11;
00105 const F l32 = (m(2,1) - l21 * l31) * li22;
00106 F li33 = m(2,2) - (l31 * l31 + l32 * l32);
00107 if (li33 <= F(0)) return false;
00108 else li33 = std::sqrt(F(1) / li33);
00109 const F l41 = m(3,0) * li11;
00110 const F l42 = (m(3,1) - l21 * l41) * li22;
00111 const F l43 = (m(3,2) - l31 * l41 - l32 * l42) * li33;
00112 F li44 = m(3,3) - (l41 * l41 + l42 * l42 + l43 * l43);
00113 if (li44 <= F(0)) return false;
00114 else li44 = std::sqrt(F(1) / li44);
00115 const F l51 = m(4,0) * li11;
00116 const F l52 = (m(4,1) - l21 * l51) * li22;
00117 const F l53 = (m(4,2) - l31 * l51 - l32 * l52) * li33;
00118 const F l54 = (m(4,3) - l41 * l51 - l42 * l52 - l43 * l53) * li44;
00119 F li55 = m(4,4) - (l51*l51+l52*l52+l53*l53+l54*l54);
00120 if (li55 <= F(0)) return false;
00121 else li55 = std::sqrt(F(1) / li55);
00122 const F l61 = m(5,0) * li11;
00123 const F l62 = (m(5,1) - l21 * l61) * li22;
00124 const F l63 = (m(5,2) - l31 * l61 - l32 * l62) * li33;
00125 const F l64 = (m(5,3) - l41 * l61 - l42 * l62 - l43 * l63) * li44;
00126 const F l65 = (m(5,4) - l51 * l61 - l52 * l62 - l53 * l63 - l54 * l64) * li55;
00127 F li66 = m(5,5) - (l61*l61+l62*l62+l63*l63+l64*l64+l65*l65);
00128 if (li66 <= F(0)) return false;
00129 else li66 = std::sqrt(F(1) / li66);
00130
00131 const F li21 = -l21 * li11 * li22;
00132 const F li32 = -l32 * li22 * li33;
00133 const F li31 = (l21 * l32 * li22 - l31) * li11 * li33;
00134 const F li43 = -l43 * li44 * li33;
00135 const F li42 = (l32 * l43 * li33 - l42) * li22 * li44;
00136 const F li41 = (-l21 * l32 * l43 * li22 * li33 +
00137 l21 * l42 * li22 + l31 * l43 * li33 - l41) * li11 * li44;
00138 const F li54 = -l54 * li55 * li44;
00139 const F li53 = (l54 * l43 * li44 - l53) * li33 * li55;
00140 const F li52 = (-l32 * l43 * l54 * li33 * li44 +
00141 l32 * l53 * li33 + l42 * l54 * li44 - l52) * li22 * li55;
00142 const F li51 = (l21*l32*l43*l54*li22*li33*li44 -
00143 l54*l43*l31*li44*li33 - l53*l32*l21*li22*li33 - l54*l42*l21*li44*li22 +
00144 l52*l21*li22 + l53*l31*li33 + l54*l41*li44 -l51) * li11 * li55;
00145 const F li65 = -l65 * li66 * li55;
00146 const F li64 = (l65 * l54 * li55 - l64) * li44 * li66;
00147 const F li63 = (-l43 * l54 * l65 * li44 * li55 +
00148 l43 * l64 * li44 + l53 * l65 * li55 - l63) * li33 * li66;
00149 const F li62 = (l32*l43*l54*l65*li33*li44*li55 -
00150 l64*l43*l32*li44*li33 - l65*l53*l32*li55*li33 -l65*l54*l42*li55*li44 +
00151 l63*l32*li33 + l64*l42*li44 + l65*l52*li55 - l62) * li22 * li66;
00152 const F li61 = (-l65*l54*l43*l32*l21*li22*li33*li44*li55 +
00153 l64*l43*l32*l21*li22*li33*li44 + l65*l53*l32*l21*li22*li33*li55 +
00154 l65*l54*l42*l21*li22*li44*li55 + l65*l54*l43*l31*li33*li44*li55 -
00155 l63*l32*l21*li22*li33 - l64*l42*l21*li22*li44 - l65*l52*l21*li22*li55 -
00156 l64*l43*l31*li33*li44 - l65*l53*l31*li33*li55 - l65*l54*l41*li44*li55 +
00157 l62*l21*li22 + l63*l31*li33 + l64*l41*li44 + l65*l51*li55 - l61) *
00158 li11 * li66;
00159
00160 m(0,0) = li61*li61 + li51*li51 + li41*li41 + li31*li31 + li21*li21 + li11*li11;
00161 m(1,0) = li61*li62 + li51*li52 + li41*li42 + li31*li32 + li21*li22;
00162 m(1,1) = li62*li62 + li52*li52 + li42*li42 + li32*li32 + li22*li22;
00163 m(2,0) = li61*li63 + li51*li53 + li41*li43 + li31*li33;
00164 m(2,1) = li62*li63 + li52*li53 + li42*li43 + li32*li33;
00165 m(2,2) = li63*li63 + li53*li53 + li43*li43 + li33*li33;
00166 m(3,0) = li61*li64 + li51*li54 + li41*li44;
00167 m(3,1) = li62*li64 + li52*li54 + li42*li44;
00168 m(3,2) = li63*li64 + li53*li54 + li43*li44;
00169 m(3,3) = li64*li64 + li54*li54 + li44*li44;
00170 m(4,0) = li61*li65 + li51*li55;
00171 m(4,1) = li62*li65 + li52*li55;
00172 m(4,2) = li63*li65 + li53*li55;
00173 m(4,3) = li64*li65 + li54*li55;
00174 m(4,4) = li65*li65 + li55*li55;
00175 m(5,0) = li61*li66;
00176 m(5,1) = li62*li66;
00177 m(5,2) = li63*li66;
00178 m(5,3) = li64*li66;
00179 m(5,4) = li65*li66;
00180 m(5,5) = li66*li66;
00181
00182 return true;
00183 }
00184 };
00185
00187 template<class T, class F> struct inverter<T,F,5>
00188 {
00189 inline bool operator()(T& m) const
00190 {
00191 if (m(0,0) <= F(0)) return false;
00192 const F li11 = std::sqrt(F(1) / m(0,0));
00193 const F l21 = m(1,0) * li11;
00194 F li22 = m(1,1) - l21 * l21;
00195 if (li22 <= F(0)) return false;
00196 else li22 = std::sqrt(F(1) / li22);
00197 const F l31 = m(2,0) * li11;
00198 const F l32 = (m(2,1) - l21 * l31) * li22;
00199 F li33 = m(2,2) - (l31 * l31 + l32 * l32);
00200 if (li33 <= F(0)) return false;
00201 else li33 = std::sqrt(F(1) / li33);
00202 const F l41 = m(3,0) * li11;
00203 const F l42 = (m(3,1) - l21 * l41) * li22;
00204 const F l43 = (m(3,2) - l31 * l41 - l32 * l42) * li33;
00205 F li44 = m(3,3) - (l41 * l41 + l42 * l42 + l43 * l43);
00206 if (li44 <= F(0)) return false;
00207 else li44 = std::sqrt(F(1) / li44);
00208 const F l51 = m(4,0) * li11;
00209 const F l52 = (m(4,1) - l21 * l51) * li22;
00210 const F l53 = (m(4,2) - l31 * l51 - l32 * l52) * li33;
00211 const F l54 = (m(4,3) - l41 * l51 - l42 * l52 - l43 * l53) * li44;
00212 F li55 = m(4,4) - (l51*l51+l52*l52+l53*l53+l54*l54);
00213 if (li55 <= F(0)) return false;
00214 else li55 = std::sqrt(F(1) / li55);
00215
00216 const F li21 = -l21 * li11 * li22;
00217 const F li32 = -l32 * li22 * li33;
00218 const F li31 = (l21 * l32 * li22 - l31) * li11 * li33;
00219 const F li43 = -l43 * li44 * li33;
00220 const F li42 = (l32 * l43 * li33 - l42) * li22 * li44;
00221 const F li41 = (-l21 * l32 * l43 * li22 * li33 +
00222 l21 * l42 * li22 + l31 * l43 * li33 - l41) * li11 * li44;
00223 const F li54 = -l54 * li55 * li44;
00224 const F li53 = (l54 * l43 * li44 - l53) * li33 * li55;
00225 const F li52 = (-l32 * l43 * l54 * li33 * li44 +
00226 l32 * l53 * li33 + l42 * l54 * li44 - l52) * li22 * li55;
00227 const F li51 = (l21*l32*l43*l54*li22*li33*li44 -
00228 l54*l43*l31*li44*li33 - l53*l32*l21*li22*li33 - l54*l42*l21*li44*li22 +
00229 l52*l21*li22 + l53*l31*li33 + l54*l41*li44 -l51) * li11 * li55;
00230
00231 m(0,0) = li51*li51 + li41*li41 + li31*li31 + li21*li21 + li11*li11;
00232 m(1,0) = li51*li52 + li41*li42 + li31*li32 + li21*li22;
00233 m(1,1) = li52*li52 + li42*li42 + li32*li32 + li22*li22;
00234 m(2,0) = li51*li53 + li41*li43 + li31*li33;
00235 m(2,1) = li52*li53 + li42*li43 + li32*li33;
00236 m(2,2) = li53*li53 + li43*li43 + li33*li33;
00237 m(3,0) = li51*li54 + li41*li44;
00238 m(3,1) = li52*li54 + li42*li44;
00239 m(3,2) = li53*li54 + li43*li44;
00240 m(3,3) = li54*li54 + li44*li44;
00241 m(4,0) = li51*li55;
00242 m(4,1) = li52*li55;
00243 m(4,2) = li53*li55;
00244 m(4,3) = li54*li55;
00245 m(4,4) = li55*li55;
00246
00247 return true;
00248 }
00249 };
00250
00252 template<class T, class F> struct inverter<T,F,4>
00253 {
00254 inline bool operator()(T& m) const
00255 {
00256 if (m(0,0) <= F(0)) return false;
00257 const F li11 = std::sqrt(F(1) / m(0,0));
00258 const F l21 = m(1,0) * li11;
00259 F li22 = m(1,1) - l21 * l21;
00260 if (li22 <= F(0)) return false;
00261 else li22 = std::sqrt(F(1) / li22);
00262 const F l31 = m(2,0) * li11;
00263 const F l32 = (m(2,1) - l21 * l31) * li22;
00264 F li33 = m(2,2) - (l31 * l31 + l32 * l32);
00265 if (li33 <= F(0)) return false;
00266 else li33 = std::sqrt(F(1) / li33);
00267 const F l41 = m(3,0) * li11;
00268 const F l42 = (m(3,1) - l21 * l41) * li22;
00269 const F l43 = (m(3,2) - l31 * l41 - l32 * l42) * li33;
00270 F li44 = m(3,3) - (l41 * l41 + l42 * l42 + l43 * l43);
00271 if (li44 <= F(0)) return false;
00272 else li44 = std::sqrt(F(1) / li44);
00273
00274 const F li21 = -l21 * li11 * li22;
00275 const F li32 = -l32 * li22 * li33;
00276 const F li31 = (l21 * l32 * li22 - l31) * li11 * li33;
00277 const F li43 = -l43 * li44 * li33;
00278 const F li42 = (l32 * l43 * li33 - l42) * li22 * li44;
00279 const F li41 = (-l21 * l32 * l43 * li22 * li33 +
00280 l21 * l42 * li22 + l31 * l43 * li33 - l41) * li11 * li44;
00281
00282 m(0,0) = li41*li41 + li31*li31 + li21*li21 + li11*li11;
00283 m(1,0) = li41*li42 + li31*li32 + li21*li22;
00284 m(1,1) = li42*li42 + li32*li32 + li22*li22;
00285 m(2,0) = li41*li43 + li31*li33;
00286 m(2,1) = li42*li43 + li32*li33;
00287 m(2,2) = li43*li43 + li33*li33;
00288 m(3,0) = li41*li44;
00289 m(3,1) = li42*li44;
00290 m(3,2) = li43*li44;
00291 m(3,3) = li44*li44;
00292
00293 return true;
00294 }
00295 };
00296
00298 template<class T, class F> struct inverter<T,F,3>
00299 {
00300 inline bool operator()(T& m) const
00301 {
00302 if (m(0,0) <= F(0)) return false;
00303 const F li11 = std::sqrt(F(1) / m(0,0));
00304 const F l21 = m(1,0) * li11;
00305 F li22 = m(1,1) - l21 * l21;
00306 if (li22 <= F(0)) return false;
00307 else li22 = std::sqrt(F(1) / li22);
00308 const F l31 = m(2,0) * li11;
00309 const F l32 = (m(2,1) - l21 * l31) * li22;
00310 F li33 = m(2,2) - (l31 * l31 + l32 * l32);
00311 if (li33 <= F(0)) return false;
00312 else li33 = std::sqrt(F(1) / li33);
00313
00314 const F li21 = -l21 * li11 * li22;
00315 const F li32 = -l32 * li22 * li33;
00316 const F li31 = (l21 * l32 * li22 - l31) * li11 * li33;
00317
00318 m(0,0) = li31*li31 + li21*li21 + li11*li11;
00319 m(1,0) = li31*li32 + li21*li22;
00320 m(1,1) = li32*li32 + li22*li22;
00321 m(2,0) = li31*li33;
00322 m(2,1) = li32*li33;
00323 m(2,2) = li33*li33;
00324
00325 return true;
00326 }
00327 };
00328
00330 template<class T, class F> struct inverter<T,F,2>
00331 {
00332 inline bool operator()(T& m) const
00333 {
00334 if (m(0,0) <= F(0)) return false;
00335 const F li11 = std::sqrt(F(1) / m(0,0));
00336 const F l21 = m(1,0) * li11;
00337 F li22 = m(1,1) - l21 * l21;
00338 if (li22 <= F(0)) return false;
00339 else li22 = std::sqrt(F(1) / li22);
00340
00341 const F li21 = -l21 * li11 * li22;
00342
00343 m(0,0) = li21*li21 + li11*li11;
00344 m(1,0) = li21*li22;
00345 m(1,1) = li22*li22;
00346
00347 return true;
00348 }
00349 };
00350
00352 template<class T, class F> struct inverter<T,F,1>
00353 {
00354 inline bool operator()(T& m) const
00355 {
00356 if (m(0,0) <= F(0)) return false;
00357 m(0,0) = F(1) / m(0,0);
00358 return true;
00359 }
00360 };
00361
00363 template<class T, class F> struct inverter<T,F,0>
00364 {
00365 private:
00366
00367 virtual bool operator()(T& m) const = 0;
00368 };
00369 }
00370 }
00371 }
00372
00373 #endif // LHCBMATH_SYMPOSDEFMATRIXINVERTER_H
00374
00375