CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/CommonTools/Statistics/src/RandomMultiGauss.cc

Go to the documentation of this file.
00001 //#include "CommonDet/DetUtilities/interface/DetExceptions.h"
00002 #include "CommonTools/Statistics/interface/RandomMultiGauss.h"
00003 #include "CLHEP/Random/RandGauss.h"
00004 
00005 #include <cfloat>
00006 //
00007 // constructor with means and covariance
00008 //
00009 RandomMultiGauss::RandomMultiGauss (const AlgebraicVector& aVector, const AlgebraicSymMatrix& aMatrix) :
00010   theSize(aMatrix.num_row()),
00011   theMeans(aVector),
00012   theTriangle(theSize,theSize,0) {
00013   //
00014   // Check consistency
00015   //
00016   if ( theMeans.num_row() == theSize ) {
00017     initialise(aMatrix);
00018   }
00019   else {
00020 //    throw DetLogicError("RandomMultiGauss: size of vector and matrix do not match");
00021     theMeans = AlgebraicVector(theSize,0);
00022   }
00023 }
00024 //
00025 // constructor with covariance (mean = 0)
00026 //
00027 RandomMultiGauss::RandomMultiGauss (const AlgebraicSymMatrix& aMatrix) :
00028   theSize(aMatrix.num_row()),
00029   theMeans(theSize,0),
00030   theTriangle(theSize,theSize,0) {
00031   //
00032   initialise(aMatrix);
00033 }
00034 //
00035 // construct triangular matrix (Cholesky decomposition)
00036 //
00037 void RandomMultiGauss::initialise (const AlgebraicSymMatrix& aMatrix) {
00038   //
00039   // Cholesky decomposition with protection against empty rows/columns
00040   //
00041   for ( int i1=0; i1<theSize; i1++ ) {
00042     if ( fabs(aMatrix[i1][i1])<FLT_MIN )  continue;
00043 
00044     for ( int i2=i1; i2<theSize; i2++ ) {
00045       if ( fabs(aMatrix[i2][i2])<FLT_MIN )  continue;
00046 
00047       double sum = aMatrix[i2][i1];
00048       for ( int i3=i1-1; i3>=0; i3-- ) {
00049         if ( fabs(aMatrix[i3][i3])<FLT_MIN )  continue;
00050         sum -= theTriangle[i1][i3]*theTriangle[i2][i3];
00051       }
00052       
00053       if ( i1==i2 ) {
00054         //
00055         // check for positive definite input matrix, but allow for effects
00056         // due to finite precision
00057         //
00058         if ( sum<=0 ) {
00059 //        if ( sum<-FLT_MIN )  throw DetLogicError("RandomMultiGauss: input matrix is not positive definite");
00060           sum = FLT_MIN;
00061         }
00062         theTriangle[i1][i1] = sqrt(sum);
00063       }
00064       else {
00065         theTriangle[i1][i2] = 0.;
00066         theTriangle[i2][i1] = sum / theTriangle[i1][i1];
00067       }
00068     }
00069   }
00070 }
00071 //
00072 // generate vector of random numbers
00073 //
00074 AlgebraicVector RandomMultiGauss::fire() {
00075   AlgebraicVector vRandom(theSize,0);
00076   for ( int i=0; i<theSize; i++ ) {
00077     if ( theTriangle[i][i]!=0 ) 
00078       vRandom[i] = CLHEP::RandGauss::shoot();
00079   }
00080   return theTriangle*vRandom+theMeans;
00081 }
00082