00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114 #include "TDecompBase.h"
00115 #include "TMath.h"
00116 #include "TError.h"
00117
00118 ClassImp(TDecompBase)
00119
00120
00121 TDecompBase::TDecompBase()
00122 {
00123
00124
00125 fTol = std::numeric_limits<double>::epsilon();
00126 fDet1 = 0;
00127 fDet2 = 0;
00128 fCondition = -1.0;
00129 fRowLwb = 0;
00130 fColLwb = 0;
00131 }
00132
00133
00134 TDecompBase::TDecompBase(const TDecompBase &another) : TObject(another)
00135 {
00136
00137
00138 *this = another;
00139 }
00140
00141
00142 Int_t TDecompBase::Hager(Double_t &est,Int_t iter)
00143 {
00144
00145
00146
00147
00148
00149
00150
00151
00152 est = -1.0;
00153
00154 const TMatrixDBase &m = GetDecompMatrix();
00155 if (!m.IsValid())
00156 return iter;
00157
00158 const Int_t n = m.GetNrows();
00159
00160 TVectorD b(n); TVectorD y(n); TVectorD z(n);
00161 b = Double_t(1.0/n);
00162 Double_t inv_norm1 = 0.0;
00163 Bool_t stop = kFALSE;
00164 do {
00165 y = b;
00166 if (!Solve(y))
00167 return iter;
00168 const Double_t ynorm1 = y.Norm1();
00169 if ( ynorm1 <= inv_norm1 ) {
00170 stop = kTRUE;
00171 } else {
00172 inv_norm1 = ynorm1;
00173 Int_t i;
00174 for (i = 0; i < n; i++)
00175 z(i) = ( y(i) >= 0.0 ? 1.0 : -1.0 );
00176 if (!TransSolve(z))
00177 return iter;
00178 Int_t imax = 0;
00179 Double_t maxz = TMath::Abs(z(0));
00180 for (i = 1; i < n; i++) {
00181 const Double_t absz = TMath::Abs(z(i));
00182 if ( absz > maxz ) {
00183 maxz = absz;
00184 imax = i;
00185 }
00186 }
00187 stop = (maxz <= b*z);
00188 if (!stop) {
00189 b = 0.0;
00190 b(imax) = 1.0;
00191 }
00192 }
00193 iter--;
00194 } while (!stop && iter);
00195 est = inv_norm1;
00196
00197 return iter;
00198 }
00199
00200
00201 void TDecompBase::DiagProd(const TVectorD &diag,Double_t tol,Double_t &d1,Double_t &d2)
00202 {
00203
00204
00205
00206
00207
00208
00209 const Double_t zero = 0.0;
00210 const Double_t one = 1.0;
00211 const Double_t four = 4.0;
00212 const Double_t sixteen = 16.0;
00213 const Double_t sixteenth = 0.0625;
00214
00215 const Int_t n = diag.GetNrows();
00216
00217 Double_t t1 = 1.0;
00218 Double_t t2 = 0.0;
00219 for (Int_t i = 0; (i < n) && (t1 != zero); i++) {
00220 if (TMath::Abs(diag(i)) > tol) {
00221 t1 *= (Double_t) diag(i);
00222 while (TMath::Abs(t1) > one) {
00223 t1 *= sixteenth;
00224 t2 += four;
00225 }
00226 while (TMath::Abs(t1) < sixteenth) {
00227 t1 *= sixteen;
00228 t2 -= four;
00229 }
00230 } else {
00231 t1 = zero;
00232 t2 = zero;
00233 }
00234 }
00235 d1 = t1;
00236 d2 = t2;
00237
00238 return;
00239 }
00240
00241
00242 Double_t TDecompBase::Condition()
00243 {
00244
00245
00246 if ( !TestBit(kCondition) ) {
00247 fCondition = -1;
00248 if (TestBit(kSingular))
00249 return fCondition;
00250 if ( !TestBit(kDecomposed) ) {
00251 if (!Decompose())
00252 return fCondition;
00253 }
00254 Double_t invNorm;
00255 if (Hager(invNorm))
00256 fCondition *= invNorm;
00257 else
00258 Error("Condition()","Hager procedure did NOT converge");
00259 SetBit(kCondition);
00260 }
00261 return fCondition;
00262 }
00263
00264
00265 Bool_t TDecompBase::MultiSolve(TMatrixD &B)
00266 {
00267
00268
00269 const TMatrixDBase &m = GetDecompMatrix();
00270 R__ASSERT(m.IsValid() && B.IsValid());
00271
00272 const Int_t colLwb = B.GetColLwb();
00273 const Int_t colUpb = B.GetColUpb();
00274 Bool_t status = kTRUE;
00275 for (Int_t icol = colLwb; icol <= colUpb && status; icol++) {
00276 TMatrixDColumn b(B,icol);
00277 status &= Solve(b);
00278 }
00279
00280 return status;
00281 }
00282
00283
00284 void TDecompBase::Det(Double_t &d1,Double_t &d2)
00285 {
00286
00287
00288 if ( !TestBit(kDetermined) ) {
00289 if ( !TestBit(kDecomposed) )
00290 Decompose();
00291 if (TestBit(kSingular) ) {
00292 fDet1 = 0.0;
00293 fDet2 = 0.0;
00294 } else {
00295 const TMatrixDBase &m = GetDecompMatrix();
00296 R__ASSERT(m.IsValid());
00297 TVectorD diagv(m.GetNrows());
00298 for (Int_t i = 0; i < diagv.GetNrows(); i++)
00299 diagv(i) = m(i,i);
00300 DiagProd(diagv,fTol,fDet1,fDet2);
00301 }
00302 SetBit(kDetermined);
00303 }
00304 d1 = fDet1;
00305 d2 = fDet2;
00306 }
00307
00308
00309 void TDecompBase::Print(Option_t * ) const
00310 {
00311
00312
00313 printf("fTol = %.4e\n",fTol);
00314 printf("fDet1 = %.4e\n",fDet1);
00315 printf("fDet2 = %.4e\n",fDet2);
00316 printf("fCondition = %.4e\n",fCondition);
00317 printf("fRowLwb = %d\n",fRowLwb);
00318 printf("fColLwb = %d\n",fColLwb);
00319 }
00320
00321
00322 TDecompBase &TDecompBase::operator=(const TDecompBase &source)
00323 {
00324
00325
00326 if (this != &source) {
00327 TObject::operator=(source);
00328 fTol = source.fTol;
00329 fDet1 = source.fDet1;
00330 fDet2 = source.fDet2;
00331 fCondition = source.fCondition;
00332 fRowLwb = source.fRowLwb;
00333 fColLwb = source.fColLwb;
00334 }
00335 return *this;
00336 }
00337
00338
00339 Bool_t DefHouseHolder(const TVectorD &vc,Int_t lp,Int_t l,Double_t &up,Double_t &beta,
00340 Double_t tol)
00341 {
00342
00343
00344 const Int_t n = vc.GetNrows();
00345 const Double_t * const vp = vc.GetMatrixArray();
00346
00347 Double_t c = TMath::Abs(vp[lp]);
00348 Int_t i;
00349 for (i = l; i < n; i++)
00350 c = TMath::Max(TMath::Abs(vp[i]),c);
00351
00352 up = 0.0;
00353 beta = 0.0;
00354 if (c <= tol) {
00355
00356 return kFALSE;
00357 }
00358
00359 Double_t sd = vp[lp]/c; sd *= sd;
00360 for (i = l; i < n; i++) {
00361 const Double_t tmp = vp[i]/c;
00362 sd += tmp*tmp;
00363 }
00364
00365 Double_t vpprim = c*TMath::Sqrt(sd);
00366 if (vp[lp] > 0.) vpprim = -vpprim;
00367 up = vp[lp]-vpprim;
00368 beta = 1./(vpprim*up);
00369
00370 return kTRUE;
00371 }
00372
00373
00374 void ApplyHouseHolder(const TVectorD &vc,Double_t up,Double_t beta,
00375 Int_t lp,Int_t l,TMatrixDRow &cr)
00376 {
00377
00378
00379 const Int_t nv = vc.GetNrows();
00380 const Int_t nc = (cr.GetMatrix())->GetNcols();
00381
00382 if (nv > nc) {
00383 Error("ApplyHouseHolder(const TVectorD &,..,TMatrixDRow &)","matrix row too short");
00384 return;
00385 }
00386
00387 const Int_t inc_c = cr.GetInc();
00388 const Double_t * const vp = vc.GetMatrixArray();
00389 Double_t * cp = cr.GetPtr();
00390
00391 Double_t s = cp[lp*inc_c]*up;
00392 Int_t i;
00393 for (i = l; i < nv; i++)
00394 s += cp[i*inc_c]*vp[i];
00395
00396 s = s*beta;
00397 cp[lp*inc_c] += s*up;
00398 for (i = l; i < nv; i++)
00399 cp[i*inc_c] += s*vp[i];
00400 }
00401
00402
00403 void ApplyHouseHolder(const TVectorD &vc,Double_t up,Double_t beta,
00404 Int_t lp,Int_t l,TMatrixDColumn &cc)
00405 {
00406
00407
00408 const Int_t nv = vc.GetNrows();
00409 const Int_t nc = (cc.GetMatrix())->GetNrows();
00410
00411 if (nv > nc) {
00412 Error("ApplyHouseHolder(const TVectorD &,..,TMatrixDRow &)","matrix column too short");
00413 return;
00414 }
00415
00416 const Int_t inc_c = cc.GetInc();
00417 const Double_t * const vp = vc.GetMatrixArray();
00418 Double_t * cp = cc.GetPtr();
00419
00420 Double_t s = cp[lp*inc_c]*up;
00421 Int_t i;
00422 for (i = l; i < nv; i++)
00423 s += cp[i*inc_c]*vp[i];
00424
00425 s = s*beta;
00426 cp[lp*inc_c] += s*up;
00427 for (i = l; i < nv; i++)
00428 cp[i*inc_c] += s*vp[i];
00429 }
00430
00431
00432 void ApplyHouseHolder(const TVectorD &vc,Double_t up,Double_t beta,
00433 Int_t lp,Int_t l,TVectorD &cv)
00434 {
00435
00436
00437 const Int_t nv = vc.GetNrows();
00438 const Int_t nc = cv.GetNrows();
00439
00440 if (nv > nc) {
00441 Error("ApplyHouseHolder(const TVectorD &,..,TVectorD &)","vector too short");
00442 return;
00443 }
00444
00445 const Double_t * const vp = vc.GetMatrixArray();
00446 Double_t * cp = cv.GetMatrixArray();
00447
00448 Double_t s = cp[lp]*up;
00449 Int_t i;
00450 for (i = l; i < nv; i++)
00451 s += cp[i]*vp[i];
00452
00453 s = s*beta;
00454 cp[lp] += s*up;
00455 for (i = l; i < nv; i++)
00456 cp[i] += s*vp[i];
00457 }
00458
00459
00460 void DefGivens(Double_t v1,Double_t v2,Double_t &c,Double_t &s)
00461 {
00462
00463
00464
00465 const Double_t a1 = TMath::Abs(v1);
00466 const Double_t a2 = TMath::Abs(v2);
00467 if (a1 > a2) {
00468 const Double_t w = v2/v1;
00469 const Double_t q = TMath::Hypot(1.,w);
00470 c = 1./q;
00471 if (v1 < 0.) c = -c;
00472 s = c*w;
00473 } else {
00474 if (v2 != 0) {
00475 const Double_t w = v1/v2;
00476 const Double_t q = TMath::Hypot(1.,w);
00477 s = 1./q;
00478 if (v2 < 0.) s = -s;
00479 c = s*w;
00480 } else {
00481 c = 1.;
00482 s = 0.;
00483 }
00484 }
00485 }
00486
00487
00488 void DefAplGivens(Double_t &v1,Double_t &v2,Double_t &c,Double_t &s)
00489 {
00490
00491
00492
00493
00494 const Double_t a1 = TMath::Abs(v1);
00495 const Double_t a2 = TMath::Abs(v2);
00496 if (a1 > a2) {
00497 const Double_t w = v2/v1;
00498 const Double_t q = TMath::Hypot(1.,w);
00499 c = 1./q;
00500 if (v1 < 0.) c = -c;
00501 s = c*w;
00502 v1 = a1*q;
00503 v2 = 0.;
00504 } else {
00505 if (v2 != 0) {
00506 const Double_t w = v1/v2;
00507 const Double_t q = TMath::Hypot(1.,w);
00508 s = 1./q;
00509 if (v2 < 0.) s = -s;
00510 c = s*w;
00511 v1 = a2*q;
00512 v2 = 0.;
00513 } else {
00514 c = 1.;
00515 s = 0.;
00516 }
00517 }
00518 }
00519
00520
00521 void ApplyGivens(Double_t &z1,Double_t &z2,Double_t c,Double_t s)
00522 {
00523
00524
00525
00526 const Double_t w = z1*c+z2*s;
00527 z2 = -z1*s+z2*c;
00528 z1 = w;
00529 }