00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <stdio.h>
00012 #include <stdlib.h>
00013 #include <string.h>
00014 #include <math.h>
00015 #include <assert.h>
00016 #include "TRandomVector.h"
00017 ClassImp(TRandomVector)
00018
00019 TRandomVector::TRandomVector()
00020 {
00021 fDim=0;
00022 }
00023
00024 TRandomVector::TRandomVector(const TMatrixDSym& errMtx,UInt_t seed)
00025 { assert(! Set(errMtx,seed)); }
00026
00027 TRandomVector::TRandomVector(const TVectorD& errDia,UInt_t seed)
00028 {
00029 fDim = errDia.GetNrows();
00030 TMatrixDSym mtx(fDim);
00031 fRandom.SetSeed(seed);
00032 for (int i=0;i<fDim;i++){assert(errDia[i]>0); mtx[i][i] = errDia[i];}
00033
00034 RandRotate(mtx);
00035 assert(! Set(mtx,seed));
00036 }
00037
00038 int TRandomVector::Set(const TMatrixDSym& errMtx,UInt_t seed)
00039 {
00040 if (seed) fRandom.SetSeed(seed);
00041 fDim = errMtx.GetNcols();
00042 fErrMtx.ResizeTo(fDim,fDim);
00043 fEigMtx.ResizeTo(fDim,fDim);
00044 fEigVal.ResizeTo(fDim);
00045 fResult.ResizeTo(fDim);
00046
00047 fErrMtx = errMtx;
00048 if (fDim<1) { Error("Set","Size too small %d",fDim);
00049 fDim=0; return 1;}
00050 fEigMtx= fErrMtx.EigenVectors(fEigVal);
00051
00052 for (int i=0;i<fDim;i++) {
00053 for (int j=0;j<fDim;j++) {
00054 double sum=0;
00055 for (int k=0;k<fDim;k++) {
00056 sum += fEigMtx[i][k]*fEigMtx[j][k]*fEigVal[k];}
00057 double dif = fErrMtx[i][j]-sum;
00058 if (fabs(dif)>1e-6)
00059 printf("*** %2i %2i %g = %g %g\n",i,j,fErrMtx[i][j],sum,dif);
00060 } }
00061
00062 for (int i=0;i<fDim;i++) {
00063 if (fEigVal[i]<0) {
00064 Error("Set","Non positive error matrix: eigen(%d)=%g",i,fEigVal[i]);
00065 fDim=0; return 2;}
00066 fEigVal[i] = sqrt(fEigVal[i]);
00067 }
00068
00069 return 0;
00070 }
00071
00072 const TVectorD& TRandomVector::Gaus()
00073 {
00074 if (!fDim) {Error("Gaus","Not initialised properly");}
00075 TVectorD rnd(fDim);
00076 for (int i=0;i<fDim;i++){ rnd[i]= gRandom->Gaus()*fEigVal[i];};
00077 fResult = fEigMtx*rnd;
00078 return fResult;
00079 }
00080
00081 void TRandomVector::Test(int nevt)
00082 {
00083 enum {kMySize=15};
00084 TRandomVector *RV=0;
00085 TMatrixDSym S(kMySize);
00086
00087 TVectorD V(kMySize);
00088 for (int i=0;i<kMySize;i++) {
00089 V[i] = (i+1)*(1+0.1*gRandom->Rndm());
00090 S[i][i] = V[i];
00091 }
00092
00093 if (nevt>0 ) {
00094 RandRotate(S);
00095 assert(TRandomVector::Sign(S)>0);
00096 RV = new TRandomVector(S);
00097 } else {
00098 RV = new TRandomVector(V);
00099 S = RV->GetMtx();
00100 }
00101 nevt = abs(nevt);
00102
00103 TVectorD res(kMySize);
00104 TMatrixD SS(kMySize,kMySize);
00105 for (int evt=0;evt<nevt;evt++) {
00106 const TVectorD &res = RV->Gaus();
00107 for (int ii=0;ii<kMySize;ii++) {
00108 for (int jj=0;jj<=ii;jj++) {SS[ii][jj]+=res[ii]*res[jj];}}
00109 }
00110 SS*=(1./nevt);
00111
00112 double Qa = 0,maxQa=0;;
00113 for (int i=0;i<kMySize;i++) {
00114 for (int k=0;k<=i;k++) {
00115 double nor = sqrt(S[i][i]*S[k][k]);
00116 double dif = (S[i][k]-SS[i][k])/nor;
00117 if (fabs(dif)> 0.1)
00118 printf("(%d %d) \t%g = \t%g \t%g\n",i,k,S[i][k]/nor,SS[i][k]/nor,dif);
00119 dif = fabs(dif);
00120 Qa+= (dif); if (dif>maxQa) maxQa=dif;
00121 }}
00122 int n = ((kMySize*kMySize+kMySize)/2);
00123 Qa/=(n);
00124 printf("Quality %g < %g < 1\n",Qa,maxQa);
00125 }
00126
00127 void TRandomVector::RandRotate(TMatrixDSym& errMtx)
00128 {
00129 int nDim = errMtx.GetNrows();
00130 assert(Sign(errMtx)>0);
00131 TVectorD dia(nDim);
00132 for (int i=0;i<nDim;i++){dia[i]=sqrt(errMtx[i][i]);}
00133 for (int i=0;i<nDim;i++){for (int j=0;j<nDim;j++){errMtx[i][j]/=dia[i]*dia[j];}}
00134
00135 TMatrixD T(nDim,nDim);for (int i=0;i<nDim;i++){T[i][i]=1.;}
00136 for (int ir1=0;ir1<nDim;ir1++) {
00137 for (int ir2=0;ir2<ir1 ;ir2++) {
00138 for (int ic =0;ic <nDim;ic++ ) {
00139 double x = T[ir1][ic];
00140 double y = T[ir2][ic];
00141 if (fabs(x)+fabs(y)<=0.) continue;
00142 double c = gRandom->Rndm();
00143 double s = sqrt(fabs(1.-c*c));
00144 T[ir1][ic] = x*c + y*s;
00145 T[ir2][ic] =-x*s + y*c;
00146 }}}
00147 errMtx.Similarity(T);
00148 for (int i=0;i<nDim;i++){ for (int j=0;j<nDim;j++){errMtx[i][j]*=dia[i]*dia[j];}}
00149 assert(Sign(errMtx)>0);
00150 }
00151
00152
00153 double TRandomVector::Sign(const TMatrixDSym &Si)
00154 {
00155 int n = Si.GetNrows();
00156 TMatrixDSym S(Si);
00157 TVectorD coe(n);
00158 for (int i=0;i< n;++i) {
00159 double qwe = S[i][i];
00160 if(qwe<=0) return qwe;
00161 qwe = pow(2.,-int(log(qwe)/(2*log(2))));
00162 coe[i]=qwe;
00163 }
00164
00165 for (int i=0;i< n;++i) {
00166 for (int j=0;j< n;j++) {S[i][j]*=coe[i]*coe[j];}}
00167
00168 TVectorD EigVal(n);
00169 S.EigenVectors(EigVal);
00170
00171 double ans = 3e33;
00172 for (int i=0;i<n;i++) {if (EigVal[i]<ans) ans = EigVal[i];}
00173 return ans;
00174 }
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192