File indexing completed on 2025-01-18 10:10:14
0001
0002
0003
0004 #ifndef ROOT_Math_CholeskyDecomp
0005 #define ROOT_Math_CholeskyDecomp
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027 #include <cmath>
0028 #include <algorithm>
0029
0030 namespace ROOT {
0031
0032 namespace Math {
0033
0034
0035 namespace CholeskyDecompHelpers {
0036
0037 template<class F, class M> struct _decomposerGenDim;
0038 template<class F, unsigned N, class M> struct _decomposer;
0039 template<class F, class M> struct _inverterGenDim;
0040 template<class F, unsigned N, class M> struct _inverter;
0041 template<class F, class V> struct _solverGenDim;
0042 template<class F, unsigned N, class V> struct _solver;
0043 template<typename G> class PackedArrayAdapter;
0044 }
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076 template<class F, unsigned N> class CholeskyDecomp
0077 {
0078 private:
0079
0080
0081
0082 F fL[N * (N + 1) / 2];
0083
0084 bool fOk;
0085 public:
0086
0087
0088
0089
0090
0091
0092
0093
0094 template<class M> CholeskyDecomp(const M& m) :
0095 fL( ), fOk(false)
0096 {
0097 using CholeskyDecompHelpers::_decomposer;
0098 fOk = _decomposer<F, N, M>()(fL, m);
0099 }
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112 template<typename G> CholeskyDecomp(G* m) :
0113 fL(), fOk(false)
0114 {
0115 using CholeskyDecompHelpers::_decomposer;
0116 using CholeskyDecompHelpers::PackedArrayAdapter;
0117 fOk = _decomposer<F, N, PackedArrayAdapter<G> >()(
0118 fL, PackedArrayAdapter<G>(m));
0119 }
0120
0121
0122
0123 bool ok() const { return fOk; }
0124
0125
0126 operator bool() const { return fOk; }
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136 template<class V> bool Solve(V& rhs) const
0137 {
0138 using CholeskyDecompHelpers::_solver;
0139 if (fOk) _solver<F,N,V>()(rhs, fL);
0140 return fOk;
0141 }
0142
0143
0144
0145
0146
0147
0148
0149 template<class M> bool Invert(M& m) const
0150 {
0151 using CholeskyDecompHelpers::_inverter;
0152 if (fOk) _inverter<F,N,M>()(m, fL);
0153 return fOk;
0154 }
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166 template<typename G> bool Invert(G* m) const
0167 {
0168 using CholeskyDecompHelpers::_inverter;
0169 using CholeskyDecompHelpers::PackedArrayAdapter;
0170 if (fOk) {
0171 PackedArrayAdapter<G> adapted(m);
0172 _inverter<F,N,PackedArrayAdapter<G> >()(adapted, fL);
0173 }
0174 return fOk;
0175 }
0176
0177
0178
0179
0180
0181
0182
0183 template<class M> bool getL(M& m) const
0184 {
0185 if (!fOk) return false;
0186 for (unsigned i = 0; i < N; ++i) {
0187
0188 for (unsigned j = i + 1; j < N; ++j)
0189 m(i, j) = F(0);
0190
0191 for (unsigned j = 0; j <= i; ++j)
0192 m(i, j) = fL[i * (i + 1) / 2 + j];
0193
0194
0195 m(i, i) = F(1) / m(i, i);
0196 }
0197 return true;
0198 }
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208 template<typename G> bool getL(G* m) const
0209 {
0210 if (!fOk) return false;
0211
0212 for (unsigned i = 0; i < (N * (N + 1)) / 2; ++i)
0213 m[i] = fL[i];
0214
0215
0216 for (unsigned i = 0; i < N; ++i)
0217 m[(i * (i + 1)) / 2 + i] = F(1) / fL[(i * (i + 1)) / 2 + i];
0218 return true;
0219 }
0220
0221
0222
0223
0224
0225
0226
0227 template<class M> bool getLi(M& m) const
0228 {
0229 if (!fOk) return false;
0230 for (unsigned i = 0; i < N; ++i) {
0231
0232 for (unsigned j = i + 1; j < N; ++j)
0233 m(j, i) = F(0);
0234
0235 for (unsigned j = 0; j <= i; ++j)
0236 m(j, i) = fL[i * (i + 1) / 2 + j];
0237 }
0238
0239 for (unsigned i = 1; i < N; ++i) {
0240 for (unsigned j = 0; j < i; ++j) {
0241 typename M::value_type tmp = F(0);
0242 for (unsigned k = i; k-- > j;)
0243 tmp -= m(k, i) * m(j, k);
0244 m(j, i) = tmp * m(i, i);
0245 }
0246 }
0247 return true;
0248 }
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258 template<typename G> bool getLi(G* m) const
0259 {
0260 if (!fOk) return false;
0261
0262 for (unsigned i = 0; i < (N * (N + 1)) / 2; ++i)
0263 m[i] = fL[i];
0264
0265 G* base1 = &m[1];
0266 for (unsigned i = 1; i < N; base1 += ++i) {
0267 for (unsigned j = 0; j < i; ++j) {
0268 G tmp = F(0);
0269 const G *base2 = &m[(i * (i - 1)) / 2];
0270 for (unsigned k = i; k-- > j; base2 -= k)
0271 tmp -= base1[k] * base2[j];
0272 base1[j] = tmp * base1[i];
0273 }
0274 }
0275 return true;
0276 }
0277 };
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310 template<class F> class CholeskyDecompGenDim
0311 {
0312 private:
0313
0314
0315 unsigned fN;
0316
0317
0318
0319 F *fL;
0320
0321 bool fOk;
0322 public:
0323
0324
0325
0326
0327
0328
0329
0330
0331 template<class M> CholeskyDecompGenDim(unsigned N, const M& m) :
0332 fN(N), fL(new F[(fN * (fN + 1)) / 2]), fOk(false)
0333 {
0334 using CholeskyDecompHelpers::_decomposerGenDim;
0335 fOk = _decomposerGenDim<F, M>()(fL, m, fN);
0336 }
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349 template<typename G> CholeskyDecompGenDim(unsigned N, G* m) :
0350 fN(N), fL(new F[(fN * (fN + 1)) / 2]), fOk(false)
0351 {
0352 using CholeskyDecompHelpers::_decomposerGenDim;
0353 using CholeskyDecompHelpers::PackedArrayAdapter;
0354 fOk = _decomposerGenDim<F, PackedArrayAdapter<G> >()(
0355 fL, PackedArrayAdapter<G>(m), fN);
0356 }
0357
0358
0359 ~CholeskyDecompGenDim() { delete[] fL; }
0360
0361
0362
0363 bool ok() const { return fOk; }
0364
0365
0366 operator bool() const { return fOk; }
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376 template<class V> bool Solve(V& rhs) const
0377 {
0378 using CholeskyDecompHelpers::_solverGenDim;
0379 if (fOk) _solverGenDim<F,V>()(rhs, fL, fN);
0380 return fOk;
0381 }
0382
0383
0384
0385
0386
0387
0388
0389 template<class M> bool Invert(M& m) const
0390 {
0391 using CholeskyDecompHelpers::_inverterGenDim;
0392 if (fOk) _inverterGenDim<F,M>()(m, fL, fN);
0393 return fOk;
0394 }
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406 template<typename G> bool Invert(G* m) const
0407 {
0408 using CholeskyDecompHelpers::_inverterGenDim;
0409 using CholeskyDecompHelpers::PackedArrayAdapter;
0410 if (fOk) {
0411 PackedArrayAdapter<G> adapted(m);
0412 _inverterGenDim<F,PackedArrayAdapter<G> >()(adapted, fL, fN);
0413 }
0414 return fOk;
0415 }
0416
0417
0418
0419
0420
0421
0422
0423 template<class M> bool getL(M& m) const
0424 {
0425 if (!fOk) return false;
0426 for (unsigned i = 0; i < fN; ++i) {
0427
0428 for (unsigned j = i + 1; j < fN; ++j)
0429 m(i, j) = F(0);
0430
0431 for (unsigned j = 0; j <= i; ++j)
0432 m(i, j) = fL[i * (i + 1) / 2 + j];
0433
0434
0435 m(i, i) = F(1) / m(i, i);
0436 }
0437 return true;
0438 }
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448 template<typename G> bool getL(G* m) const
0449 {
0450 if (!fOk) return false;
0451
0452 for (unsigned i = 0; i < (fN * (fN + 1)) / 2; ++i)
0453 m[i] = fL[i];
0454
0455
0456 for (unsigned i = 0; i < fN; ++i)
0457 m[(i * (i + 1)) / 2 + i] = F(1) / fL[(i * (i + 1)) / 2 + i];
0458 return true;
0459 }
0460
0461
0462
0463
0464
0465
0466
0467 template<class M> bool getLi(M& m) const
0468 {
0469 if (!fOk) return false;
0470 for (unsigned i = 0; i < fN; ++i) {
0471
0472 for (unsigned j = i + 1; j < fN; ++j)
0473 m(j, i) = F(0);
0474
0475 for (unsigned j = 0; j <= i; ++j)
0476 m(j, i) = fL[i * (i + 1) / 2 + j];
0477 }
0478
0479 for (unsigned i = 1; i < fN; ++i) {
0480 for (unsigned j = 0; j < i; ++j) {
0481 typename M::value_type tmp = F(0);
0482 for (unsigned k = i; k-- > j;)
0483 tmp -= m(k, i) * m(j, k);
0484 m(j, i) = tmp * m(i, i);
0485 }
0486 }
0487 return true;
0488 }
0489
0490
0491
0492
0493
0494
0495
0496
0497
0498 template<typename G> bool getLi(G* m) const
0499 {
0500 if (!fOk) return false;
0501
0502 for (unsigned i = 0; i < (fN * (fN + 1)) / 2; ++i)
0503 m[i] = fL[i];
0504
0505 G* base1 = &m[1];
0506 for (unsigned i = 1; i < fN; base1 += ++i) {
0507 for (unsigned j = 0; j < i; ++j) {
0508 G tmp = F(0);
0509 const G *base2 = &m[(i * (i - 1)) / 2];
0510 for (unsigned k = i; k-- > j; base2 -= k)
0511 tmp -= base1[k] * base2[j];
0512 base1[j] = tmp * base1[i];
0513 }
0514 }
0515 return true;
0516 }
0517 };
0518
0519 namespace CholeskyDecompHelpers {
0520
0521 template<typename G> class PackedArrayAdapter
0522 {
0523 private:
0524 G* fArr;
0525 public:
0526
0527 PackedArrayAdapter(G* arr) : fArr(arr) {}
0528
0529 const G operator()(unsigned i, unsigned j) const
0530 { return fArr[((i * (i + 1)) / 2) + j]; }
0531
0532 G& operator()(unsigned i, unsigned j)
0533 { return fArr[((i * (i + 1)) / 2) + j]; }
0534 };
0535
0536 template<class F, class M> struct _decomposerGenDim
0537 {
0538
0539
0540 bool operator()(F* dst, const M& src, unsigned N) const
0541 {
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551
0552
0553
0554 F *base1 = &dst[0];
0555 for (unsigned i = 0; i < N; base1 += ++i) {
0556 F tmpdiag = F(0.0);
0557
0558 F *base2 = &dst[0];
0559 for (unsigned j = 0; j < i; base2 += ++j) {
0560 F tmp = src(i, j);
0561 for (unsigned k = j; k--; )
0562 tmp -= base1[k] * base2[k];
0563 base1[j] = tmp *= base2[j];
0564
0565 tmpdiag += tmp * tmp;
0566 }
0567
0568 tmpdiag = src(i, i) - tmpdiag;
0569
0570 if (tmpdiag <= F(0.0)) return false;
0571 else base1[i] = std::sqrt(F(1.0) / tmpdiag);
0572 }
0573 return true;
0574 }
0575 };
0576
0577
0578 template<class F, unsigned N, class M> struct _decomposer
0579 {
0580
0581
0582 bool operator()(F* dst, const M& src) const
0583 { return _decomposerGenDim<F, M>()(dst, src, N); }
0584 };
0585
0586
0587 template<class F, class M> struct _inverterGenDim
0588 {
0589
0590 void operator()(M& dst, const F* src, unsigned N) const
0591 {
0592
0593 F * l = new F[N * (N + 1) / 2];
0594 std::copy(src, src + ((N * (N + 1)) / 2), l);
0595
0596 F* base1 = &l[1];
0597 for (unsigned i = 1; i < N; base1 += ++i) {
0598 for (unsigned j = 0; j < i; ++j) {
0599 F tmp = F(0.0);
0600 const F *base2 = &l[(i * (i - 1)) / 2];
0601 for (unsigned k = i; k-- > j; base2 -= k)
0602 tmp -= base1[k] * base2[j];
0603 base1[j] = tmp * base1[i];
0604 }
0605 }
0606
0607
0608 for (unsigned i = N; i--; ) {
0609 for (unsigned j = i + 1; j--; ) {
0610 F tmp = F(0.0);
0611 base1 = &l[(N * (N - 1)) / 2];
0612 for (unsigned k = N; k-- > i; base1 -= k)
0613 tmp += base1[i] * base1[j];
0614 dst(i, j) = tmp;
0615 }
0616 }
0617 delete [] l;
0618 }
0619 };
0620
0621
0622 template<class F, unsigned N, class M> struct _inverter
0623 {
0624
0625 void operator()(M& dst, const F* src) const
0626 { return _inverterGenDim<F, M>()(dst, src, N); }
0627 };
0628
0629
0630 template<class F, class V> struct _solverGenDim
0631 {
0632
0633 void operator()(V& rhs, const F* l, unsigned N) const
0634 {
0635
0636 for (unsigned k = 0; k < N; ++k) {
0637 const unsigned base = (k * (k + 1)) / 2;
0638 F sum = F(0.0);
0639 for (unsigned i = k; i--; )
0640 sum += rhs[i] * l[base + i];
0641
0642 rhs[k] = (rhs[k] - sum) * l[base + k];
0643 }
0644
0645 for (unsigned k = N; k--; ) {
0646 F sum = F(0.0);
0647 for (unsigned i = N; --i > k; )
0648 sum += rhs[i] * l[(i * (i + 1)) / 2 + k];
0649
0650 rhs[k] = (rhs[k] - sum) * l[(k * (k + 1)) / 2 + k];
0651 }
0652 }
0653 };
0654
0655
0656 template<class F, unsigned N, class V> struct _solver
0657 {
0658
0659 void operator()(V& rhs, const F* l) const
0660 { _solverGenDim<F, V>()(rhs, l, N); }
0661 };
0662
0663
0664 template<class F, class M> struct _decomposer<F, 6, M>
0665 {
0666
0667 bool operator()(F* dst, const M& src) const
0668 {
0669 if (src(0,0) <= F(0.0)) return false;
0670 dst[0] = std::sqrt(F(1.0) / src(0,0));
0671 dst[1] = src(1,0) * dst[0];
0672 dst[2] = src(1,1) - dst[1] * dst[1];
0673 if (dst[2] <= F(0.0)) return false;
0674 else dst[2] = std::sqrt(F(1.0) / dst[2]);
0675 dst[3] = src(2,0) * dst[0];
0676 dst[4] = (src(2,1) - dst[1] * dst[3]) * dst[2];
0677 dst[5] = src(2,2) - (dst[3] * dst[3] + dst[4] * dst[4]);
0678 if (dst[5] <= F(0.0)) return false;
0679 else dst[5] = std::sqrt(F(1.0) / dst[5]);
0680 dst[6] = src(3,0) * dst[0];
0681 dst[7] = (src(3,1) - dst[1] * dst[6]) * dst[2];
0682 dst[8] = (src(3,2) - dst[3] * dst[6] - dst[4] * dst[7]) * dst[5];
0683 dst[9] = src(3,3) - (dst[6] * dst[6] + dst[7] * dst[7] + dst[8] * dst[8]);
0684 if (dst[9] <= F(0.0)) return false;
0685 else dst[9] = std::sqrt(F(1.0) / dst[9]);
0686 dst[10] = src(4,0) * dst[0];
0687 dst[11] = (src(4,1) - dst[1] * dst[10]) * dst[2];
0688 dst[12] = (src(4,2) - dst[3] * dst[10] - dst[4] * dst[11]) * dst[5];
0689 dst[13] = (src(4,3) - dst[6] * dst[10] - dst[7] * dst[11] - dst[8] * dst[12]) * dst[9];
0690 dst[14] = src(4,4) - (dst[10]*dst[10]+dst[11]*dst[11]+dst[12]*dst[12]+dst[13]*dst[13]);
0691 if (dst[14] <= F(0.0)) return false;
0692 else dst[14] = std::sqrt(F(1.0) / dst[14]);
0693 dst[15] = src(5,0) * dst[0];
0694 dst[16] = (src(5,1) - dst[1] * dst[15]) * dst[2];
0695 dst[17] = (src(5,2) - dst[3] * dst[15] - dst[4] * dst[16]) * dst[5];
0696 dst[18] = (src(5,3) - dst[6] * dst[15] - dst[7] * dst[16] - dst[8] * dst[17]) * dst[9];
0697 dst[19] = (src(5,4) - dst[10] * dst[15] - dst[11] * dst[16] - dst[12] * dst[17] - dst[13] * dst[18]) * dst[14];
0698 dst[20] = src(5,5) - (dst[15]*dst[15]+dst[16]*dst[16]+dst[17]*dst[17]+dst[18]*dst[18]+dst[19]*dst[19]);
0699 if (dst[20] <= F(0.0)) return false;
0700 else dst[20] = std::sqrt(F(1.0) / dst[20]);
0701 return true;
0702 }
0703 };
0704
0705 template<class F, class M> struct _decomposer<F, 5, M>
0706 {
0707
0708 bool operator()(F* dst, const M& src) const
0709 {
0710 if (src(0,0) <= F(0.0)) return false;
0711 dst[0] = std::sqrt(F(1.0) / src(0,0));
0712 dst[1] = src(1,0) * dst[0];
0713 dst[2] = src(1,1) - dst[1] * dst[1];
0714 if (dst[2] <= F(0.0)) return false;
0715 else dst[2] = std::sqrt(F(1.0) / dst[2]);
0716 dst[3] = src(2,0) * dst[0];
0717 dst[4] = (src(2,1) - dst[1] * dst[3]) * dst[2];
0718 dst[5] = src(2,2) - (dst[3] * dst[3] + dst[4] * dst[4]);
0719 if (dst[5] <= F(0.0)) return false;
0720 else dst[5] = std::sqrt(F(1.0) / dst[5]);
0721 dst[6] = src(3,0) * dst[0];
0722 dst[7] = (src(3,1) - dst[1] * dst[6]) * dst[2];
0723 dst[8] = (src(3,2) - dst[3] * dst[6] - dst[4] * dst[7]) * dst[5];
0724 dst[9] = src(3,3) - (dst[6] * dst[6] + dst[7] * dst[7] + dst[8] * dst[8]);
0725 if (dst[9] <= F(0.0)) return false;
0726 else dst[9] = std::sqrt(F(1.0) / dst[9]);
0727 dst[10] = src(4,0) * dst[0];
0728 dst[11] = (src(4,1) - dst[1] * dst[10]) * dst[2];
0729 dst[12] = (src(4,2) - dst[3] * dst[10] - dst[4] * dst[11]) * dst[5];
0730 dst[13] = (src(4,3) - dst[6] * dst[10] - dst[7] * dst[11] - dst[8] * dst[12]) * dst[9];
0731 dst[14] = src(4,4) - (dst[10]*dst[10]+dst[11]*dst[11]+dst[12]*dst[12]+dst[13]*dst[13]);
0732 if (dst[14] <= F(0.0)) return false;
0733 else dst[14] = std::sqrt(F(1.0) / dst[14]);
0734 return true;
0735 }
0736 };
0737
0738 template<class F, class M> struct _decomposer<F, 4, M>
0739 {
0740
0741 bool operator()(F* dst, const M& src) const
0742 {
0743 if (src(0,0) <= F(0.0)) return false;
0744 dst[0] = std::sqrt(F(1.0) / src(0,0));
0745 dst[1] = src(1,0) * dst[0];
0746 dst[2] = src(1,1) - dst[1] * dst[1];
0747 if (dst[2] <= F(0.0)) return false;
0748 else dst[2] = std::sqrt(F(1.0) / dst[2]);
0749 dst[3] = src(2,0) * dst[0];
0750 dst[4] = (src(2,1) - dst[1] * dst[3]) * dst[2];
0751 dst[5] = src(2,2) - (dst[3] * dst[3] + dst[4] * dst[4]);
0752 if (dst[5] <= F(0.0)) return false;
0753 else dst[5] = std::sqrt(F(1.0) / dst[5]);
0754 dst[6] = src(3,0) * dst[0];
0755 dst[7] = (src(3,1) - dst[1] * dst[6]) * dst[2];
0756 dst[8] = (src(3,2) - dst[3] * dst[6] - dst[4] * dst[7]) * dst[5];
0757 dst[9] = src(3,3) - (dst[6] * dst[6] + dst[7] * dst[7] + dst[8] * dst[8]);
0758 if (dst[9] <= F(0.0)) return false;
0759 else dst[9] = std::sqrt(F(1.0) / dst[9]);
0760 return true;
0761 }
0762 };
0763
0764 template<class F, class M> struct _decomposer<F, 3, M>
0765 {
0766
0767 bool operator()(F* dst, const M& src) const
0768 {
0769 if (src(0,0) <= F(0.0)) return false;
0770 dst[0] = std::sqrt(F(1.0) / src(0,0));
0771 dst[1] = src(1,0) * dst[0];
0772 dst[2] = src(1,1) - dst[1] * dst[1];
0773 if (dst[2] <= F(0.0)) return false;
0774 else dst[2] = std::sqrt(F(1.0) / dst[2]);
0775 dst[3] = src(2,0) * dst[0];
0776 dst[4] = (src(2,1) - dst[1] * dst[3]) * dst[2];
0777 dst[5] = src(2,2) - (dst[3] * dst[3] + dst[4] * dst[4]);
0778 if (dst[5] <= F(0.0)) return false;
0779 else dst[5] = std::sqrt(F(1.0) / dst[5]);
0780 return true;
0781 }
0782 };
0783
0784 template<class F, class M> struct _decomposer<F, 2, M>
0785 {
0786
0787 bool operator()(F* dst, const M& src) const
0788 {
0789 if (src(0,0) <= F(0.0)) return false;
0790 dst[0] = std::sqrt(F(1.0) / src(0,0));
0791 dst[1] = src(1,0) * dst[0];
0792 dst[2] = src(1,1) - dst[1] * dst[1];
0793 if (dst[2] <= F(0.0)) return false;
0794 else dst[2] = std::sqrt(F(1.0) / dst[2]);
0795 return true;
0796 }
0797 };
0798
0799 template<class F, class M> struct _decomposer<F, 1, M>
0800 {
0801
0802 bool operator()(F* dst, const M& src) const
0803 {
0804 if (src(0,0) <= F(0.0)) return false;
0805 dst[0] = std::sqrt(F(1.0) / src(0,0));
0806 return true;
0807 }
0808 };
0809
0810 template<class F, class M> struct _decomposer<F, 0, M>
0811 {
0812 private:
0813 _decomposer() { };
0814 bool operator()(F* dst, const M& src) const;
0815 };
0816
0817
0818 template<class F, class M> struct _inverter<F,6,M>
0819 {
0820
0821 inline void operator()(M& dst, const F* src) const
0822 {
0823 const F li21 = -src[1] * src[0] * src[2];
0824 const F li32 = -src[4] * src[2] * src[5];
0825 const F li31 = (src[1] * src[4] * src[2] - src[3]) * src[0] * src[5];
0826 const F li43 = -src[8] * src[9] * src[5];
0827 const F li42 = (src[4] * src[8] * src[5] - src[7]) * src[2] * src[9];
0828 const F li41 = (-src[1] * src[4] * src[8] * src[2] * src[5] +
0829 src[1] * src[7] * src[2] + src[3] * src[8] * src[5] - src[6]) * src[0] * src[9];
0830 const F li54 = -src[13] * src[14] * src[9];
0831 const F li53 = (src[13] * src[8] * src[9] - src[12]) * src[5] * src[14];
0832 const F li52 = (-src[4] * src[8] * src[13] * src[5] * src[9] +
0833 src[4] * src[12] * src[5] + src[7] * src[13] * src[9] - src[11]) * src[2] * src[14];
0834 const F li51 = (src[1]*src[4]*src[8]*src[13]*src[2]*src[5]*src[9] -
0835 src[13]*src[8]*src[3]*src[9]*src[5] - src[12]*src[4]*src[1]*src[2]*src[5] - src[13]*src[7]*src[1]*src[9]*src[2] +
0836 src[11]*src[1]*src[2] + src[12]*src[3]*src[5] + src[13]*src[6]*src[9] -src[10]) * src[0] * src[14];
0837 const F li65 = -src[19] * src[20] * src[14];
0838 const F li64 = (src[19] * src[13] * src[14] - src[18]) * src[9] * src[20];
0839 const F li63 = (-src[8] * src[13] * src[19] * src[9] * src[14] +
0840 src[8] * src[18] * src[9] + src[12] * src[19] * src[14] - src[17]) * src[5] * src[20];
0841 const F li62 = (src[4]*src[8]*src[13]*src[19]*src[5]*src[9]*src[14] -
0842 src[18]*src[8]*src[4]*src[9]*src[5] - src[19]*src[12]*src[4]*src[14]*src[5] -src[19]*src[13]*src[7]*src[14]*src[9] +
0843 src[17]*src[4]*src[5] + src[18]*src[7]*src[9] + src[19]*src[11]*src[14] - src[16]) * src[2] * src[20];
0844 const F li61 = (-src[19]*src[13]*src[8]*src[4]*src[1]*src[2]*src[5]*src[9]*src[14] +
0845 src[18]*src[8]*src[4]*src[1]*src[2]*src[5]*src[9] + src[19]*src[12]*src[4]*src[1]*src[2]*src[5]*src[14] +
0846 src[19]*src[13]*src[7]*src[1]*src[2]*src[9]*src[14] + src[19]*src[13]*src[8]*src[3]*src[5]*src[9]*src[14] -
0847 src[17]*src[4]*src[1]*src[2]*src[5] - src[18]*src[7]*src[1]*src[2]*src[9] - src[19]*src[11]*src[1]*src[2]*src[14] -
0848 src[18]*src[8]*src[3]*src[5]*src[9] - src[19]*src[12]*src[3]*src[5]*src[14] - src[19]*src[13]*src[6]*src[9]*src[14] +
0849 src[16]*src[1]*src[2] + src[17]*src[3]*src[5] + src[18]*src[6]*src[9] + src[19]*src[10]*src[14] - src[15]) *
0850 src[0] * src[20];
0851
0852 dst(0,0) = li61*li61 + li51*li51 + li41*li41 + li31*li31 + li21*li21 + src[0]*src[0];
0853 dst(1,0) = li61*li62 + li51*li52 + li41*li42 + li31*li32 + li21*src[2];
0854 dst(1,1) = li62*li62 + li52*li52 + li42*li42 + li32*li32 + src[2]*src[2];
0855 dst(2,0) = li61*li63 + li51*li53 + li41*li43 + li31*src[5];
0856 dst(2,1) = li62*li63 + li52*li53 + li42*li43 + li32*src[5];
0857 dst(2,2) = li63*li63 + li53*li53 + li43*li43 + src[5]*src[5];
0858 dst(3,0) = li61*li64 + li51*li54 + li41*src[9];
0859 dst(3,1) = li62*li64 + li52*li54 + li42*src[9];
0860 dst(3,2) = li63*li64 + li53*li54 + li43*src[9];
0861 dst(3,3) = li64*li64 + li54*li54 + src[9]*src[9];
0862 dst(4,0) = li61*li65 + li51*src[14];
0863 dst(4,1) = li62*li65 + li52*src[14];
0864 dst(4,2) = li63*li65 + li53*src[14];
0865 dst(4,3) = li64*li65 + li54*src[14];
0866 dst(4,4) = li65*li65 + src[14]*src[14];
0867 dst(5,0) = li61*src[20];
0868 dst(5,1) = li62*src[20];
0869 dst(5,2) = li63*src[20];
0870 dst(5,3) = li64*src[20];
0871 dst(5,4) = li65*src[20];
0872 dst(5,5) = src[20]*src[20];
0873 }
0874 };
0875
0876 template<class F, class M> struct _inverter<F,5,M>
0877 {
0878
0879 inline void operator()(M& dst, const F* src) const
0880 {
0881 const F li21 = -src[1] * src[0] * src[2];
0882 const F li32 = -src[4] * src[2] * src[5];
0883 const F li31 = (src[1] * src[4] * src[2] - src[3]) * src[0] * src[5];
0884 const F li43 = -src[8] * src[9] * src[5];
0885 const F li42 = (src[4] * src[8] * src[5] - src[7]) * src[2] * src[9];
0886 const F li41 = (-src[1] * src[4] * src[8] * src[2] * src[5] +
0887 src[1] * src[7] * src[2] + src[3] * src[8] * src[5] - src[6]) * src[0] * src[9];
0888 const F li54 = -src[13] * src[14] * src[9];
0889 const F li53 = (src[13] * src[8] * src[9] - src[12]) * src[5] * src[14];
0890 const F li52 = (-src[4] * src[8] * src[13] * src[5] * src[9] +
0891 src[4] * src[12] * src[5] + src[7] * src[13] * src[9] - src[11]) * src[2] * src[14];
0892 const F li51 = (src[1]*src[4]*src[8]*src[13]*src[2]*src[5]*src[9] -
0893 src[13]*src[8]*src[3]*src[9]*src[5] - src[12]*src[4]*src[1]*src[2]*src[5] - src[13]*src[7]*src[1]*src[9]*src[2] +
0894 src[11]*src[1]*src[2] + src[12]*src[3]*src[5] + src[13]*src[6]*src[9] -src[10]) * src[0] * src[14];
0895
0896 dst(0,0) = li51*li51 + li41*li41 + li31*li31 + li21*li21 + src[0]*src[0];
0897 dst(1,0) = li51*li52 + li41*li42 + li31*li32 + li21*src[2];
0898 dst(1,1) = li52*li52 + li42*li42 + li32*li32 + src[2]*src[2];
0899 dst(2,0) = li51*li53 + li41*li43 + li31*src[5];
0900 dst(2,1) = li52*li53 + li42*li43 + li32*src[5];
0901 dst(2,2) = li53*li53 + li43*li43 + src[5]*src[5];
0902 dst(3,0) = li51*li54 + li41*src[9];
0903 dst(3,1) = li52*li54 + li42*src[9];
0904 dst(3,2) = li53*li54 + li43*src[9];
0905 dst(3,3) = li54*li54 + src[9]*src[9];
0906 dst(4,0) = li51*src[14];
0907 dst(4,1) = li52*src[14];
0908 dst(4,2) = li53*src[14];
0909 dst(4,3) = li54*src[14];
0910 dst(4,4) = src[14]*src[14];
0911 }
0912 };
0913
0914 template<class F, class M> struct _inverter<F,4,M>
0915 {
0916
0917 inline void operator()(M& dst, const F* src) const
0918 {
0919 const F li21 = -src[1] * src[0] * src[2];
0920 const F li32 = -src[4] * src[2] * src[5];
0921 const F li31 = (src[1] * src[4] * src[2] - src[3]) * src[0] * src[5];
0922 const F li43 = -src[8] * src[9] * src[5];
0923 const F li42 = (src[4] * src[8] * src[5] - src[7]) * src[2] * src[9];
0924 const F li41 = (-src[1] * src[4] * src[8] * src[2] * src[5] +
0925 src[1] * src[7] * src[2] + src[3] * src[8] * src[5] - src[6]) * src[0] * src[9];
0926
0927 dst(0,0) = li41*li41 + li31*li31 + li21*li21 + src[0]*src[0];
0928 dst(1,0) = li41*li42 + li31*li32 + li21*src[2];
0929 dst(1,1) = li42*li42 + li32*li32 + src[2]*src[2];
0930 dst(2,0) = li41*li43 + li31*src[5];
0931 dst(2,1) = li42*li43 + li32*src[5];
0932 dst(2,2) = li43*li43 + src[5]*src[5];
0933 dst(3,0) = li41*src[9];
0934 dst(3,1) = li42*src[9];
0935 dst(3,2) = li43*src[9];
0936 dst(3,3) = src[9]*src[9];
0937 }
0938 };
0939
0940 template<class F, class M> struct _inverter<F,3,M>
0941 {
0942
0943 inline void operator()(M& dst, const F* src) const
0944 {
0945 const F li21 = -src[1] * src[0] * src[2];
0946 const F li32 = -src[4] * src[2] * src[5];
0947 const F li31 = (src[1] * src[4] * src[2] - src[3]) * src[0] * src[5];
0948
0949 dst(0,0) = li31*li31 + li21*li21 + src[0]*src[0];
0950 dst(1,0) = li31*li32 + li21*src[2];
0951 dst(1,1) = li32*li32 + src[2]*src[2];
0952 dst(2,0) = li31*src[5];
0953 dst(2,1) = li32*src[5];
0954 dst(2,2) = src[5]*src[5];
0955 }
0956 };
0957
0958 template<class F, class M> struct _inverter<F,2,M>
0959 {
0960
0961 inline void operator()(M& dst, const F* src) const
0962 {
0963 const F li21 = -src[1] * src[0] * src[2];
0964
0965 dst(0,0) = li21*li21 + src[0]*src[0];
0966 dst(1,0) = li21*src[2];
0967 dst(1,1) = src[2]*src[2];
0968 }
0969 };
0970
0971 template<class F, class M> struct _inverter<F,1,M>
0972 {
0973
0974 inline void operator()(M& dst, const F* src) const
0975 {
0976 dst(0,0) = src[0]*src[0];
0977 }
0978 };
0979
0980 template<class F, class M> struct _inverter<F,0,M>
0981 {
0982 private:
0983 _inverter();
0984 void operator()(M& dst, const F* src) const;
0985 };
0986
0987
0988 template<class F, class V> struct _solver<F,6,V>
0989 {
0990
0991 void operator()(V& rhs, const F* l) const
0992 {
0993
0994 const F y0 = rhs[0] * l[0];
0995 const F y1 = (rhs[1]-l[1]*y0)*l[2];
0996 const F y2 = (rhs[2]-(l[3]*y0+l[4]*y1))*l[5];
0997 const F y3 = (rhs[3]-(l[6]*y0+l[7]*y1+l[8]*y2))*l[9];
0998 const F y4 = (rhs[4]-(l[10]*y0+l[11]*y1+l[12]*y2+l[13]*y3))*l[14];
0999 const F y5 = (rhs[5]-(l[15]*y0+l[16]*y1+l[17]*y2+l[18]*y3+l[19]*y4))*l[20];
1000
1001 rhs[5] = y5 * l[20];
1002 rhs[4] = (y4-l[19]*rhs[5])*l[14];
1003 rhs[3] = (y3-(l[18]*rhs[5]+l[13]*rhs[4]))*l[9];
1004 rhs[2] = (y2-(l[17]*rhs[5]+l[12]*rhs[4]+l[8]*rhs[3]))*l[5];
1005 rhs[1] = (y1-(l[16]*rhs[5]+l[11]*rhs[4]+l[7]*rhs[3]+l[4]*rhs[2]))*l[2];
1006 rhs[0] = (y0-(l[15]*rhs[5]+l[10]*rhs[4]+l[6]*rhs[3]+l[3]*rhs[2]+l[1]*rhs[1]))*l[0];
1007 }
1008 };
1009
1010 template<class F, class V> struct _solver<F,5,V>
1011 {
1012
1013 void operator()(V& rhs, const F* l) const
1014 {
1015
1016 const F y0 = rhs[0] * l[0];
1017 const F y1 = (rhs[1]-l[1]*y0)*l[2];
1018 const F y2 = (rhs[2]-(l[3]*y0+l[4]*y1))*l[5];
1019 const F y3 = (rhs[3]-(l[6]*y0+l[7]*y1+l[8]*y2))*l[9];
1020 const F y4 = (rhs[4]-(l[10]*y0+l[11]*y1+l[12]*y2+l[13]*y3))*l[14];
1021
1022 rhs[4] = (y4)*l[14];
1023 rhs[3] = (y3-(l[13]*rhs[4]))*l[9];
1024 rhs[2] = (y2-(l[12]*rhs[4]+l[8]*rhs[3]))*l[5];
1025 rhs[1] = (y1-(l[11]*rhs[4]+l[7]*rhs[3]+l[4]*rhs[2]))*l[2];
1026 rhs[0] = (y0-(l[10]*rhs[4]+l[6]*rhs[3]+l[3]*rhs[2]+l[1]*rhs[1]))*l[0];
1027 }
1028 };
1029
1030 template<class F, class V> struct _solver<F,4,V>
1031 {
1032
1033 void operator()(V& rhs, const F* l) const
1034 {
1035
1036 const F y0 = rhs[0] * l[0];
1037 const F y1 = (rhs[1]-l[1]*y0)*l[2];
1038 const F y2 = (rhs[2]-(l[3]*y0+l[4]*y1))*l[5];
1039 const F y3 = (rhs[3]-(l[6]*y0+l[7]*y1+l[8]*y2))*l[9];
1040
1041 rhs[3] = (y3)*l[9];
1042 rhs[2] = (y2-(l[8]*rhs[3]))*l[5];
1043 rhs[1] = (y1-(l[7]*rhs[3]+l[4]*rhs[2]))*l[2];
1044 rhs[0] = (y0-(l[6]*rhs[3]+l[3]*rhs[2]+l[1]*rhs[1]))*l[0];
1045 }
1046 };
1047
1048 template<class F, class V> struct _solver<F,3,V>
1049 {
1050
1051 void operator()(V& rhs, const F* l) const
1052 {
1053
1054 const F y0 = rhs[0] * l[0];
1055 const F y1 = (rhs[1]-l[1]*y0)*l[2];
1056 const F y2 = (rhs[2]-(l[3]*y0+l[4]*y1))*l[5];
1057
1058 rhs[2] = (y2)*l[5];
1059 rhs[1] = (y1-(l[4]*rhs[2]))*l[2];
1060 rhs[0] = (y0-(l[3]*rhs[2]+l[1]*rhs[1]))*l[0];
1061 }
1062 };
1063
1064 template<class F, class V> struct _solver<F,2,V>
1065 {
1066
1067 void operator()(V& rhs, const F* l) const
1068 {
1069
1070 const F y0 = rhs[0] * l[0];
1071 const F y1 = (rhs[1]-l[1]*y0)*l[2];
1072
1073 rhs[1] = (y1)*l[2];
1074 rhs[0] = (y0-(l[1]*rhs[1]))*l[0];
1075 }
1076 };
1077
1078 template<class F, class V> struct _solver<F,1,V>
1079 {
1080
1081 void operator()(V& rhs, const F* l) const
1082 {
1083
1084 rhs[0] *= l[0] * l[0];
1085 }
1086 };
1087
1088 template<class F, class V> struct _solver<F,0,V>
1089 {
1090 private:
1091 _solver();
1092 void operator()(V& rhs, const F* l) const;
1093 };
1094 }
1095
1096
1097 }
1098
1099 }
1100
1101 #endif
1102