00001 #include "AtlfastAlgs/CorrelatedData.h"
00002 #include <cmath>
00003
00004 namespace Atlfast{
00005 using std::abs;
00006 using std::pair;
00007 using std::vector;
00008 using std::cout;
00009 using std::endl;
00010
00011 CorrelatedData::CorrelatedData(int randSeed) {
00012 m_randomEngine = new HepJamesRandom( randSeed );
00013 m_ellipse = pair<double,double>(0.27597,0.27846);
00014 m_stFactors = pair<double, double>(0.449871,-0.386595);
00015 m_abFactors = pair<double, double>(0.19600,0.25472);
00016 }
00017
00018 vector<double> CorrelatedData::normal(int nDev) const{
00019 vector<double> deviates;
00020 double deviate;
00021 for (int i=0; i<nDev; i++)
00022 {
00023 bool success=false;
00024 while (success == false) {
00025 pair<double,double> randoms( m_randomEngine->flat(),
00026 m_randomEngine->flat() );
00027 success = makeDeviate(randoms, deviate);
00028 }
00029
00030 deviates.push_back(deviate);
00031 }
00032 return deviates;
00033 }
00034
00035 bool CorrelatedData::makeDeviate(pair<double,double> randoms,
00036 double& deviate) const{
00037
00038 double v, x, y, q;
00039 bool success = false;
00040
00041
00042 v = 1.7156*(randoms.second - 0.5);
00043 x = randoms.first - m_stFactors.first;
00044 y = abs(v) - m_stFactors.second;
00045 q = x*x + y*( (m_abFactors.first)*y - (m_abFactors.second)*x);
00046
00047 if ( (q <= m_ellipse.second) &&
00048 (v*v <= -4*log( (randoms.first) ) * (randoms.first) * (randoms.first) )
00049 ) success = true;
00050 if ( (q < m_ellipse.first) || success )
00051 {
00052 deviate = v/(randoms.first);
00053 return true;}
00054 else
00055 {return false;}
00056
00057 }
00058
00059 vector<double> CorrelatedData::generate(const HepMatrix& matrix) const{
00060
00061 int size = matrix.num_col();
00062 if( size != matrix.num_row() ) {
00063 cout << "CorrelatedData: WARNING: Matrix not square; using sub matrix"
00064 << endl;
00065 size = size < matrix.num_row() ? size : matrix.num_row();
00066 }
00067
00068 vector<double> generated(size,0.0);
00069 vector<double> norm = normal(size);
00070
00071 for (int i = 0; i < size; i++) {
00072 generated[i]=0;
00073 for (int j = 0; j < i+1; j++){
00074 generated[i] += matrix[i][j]*norm[j];
00075 }
00076 }
00077 return generated;
00078 }
00079
00080 double CorrelatedData::generate(double element) const{
00081 HepMatrix matrix(1,1,0);
00082 matrix(1,1) = element;
00083 return (generate(matrix)).front();
00084 }
00085
00086 HepMatrix CorrelatedData::root(const HepMatrix& matrix) const{
00087 int size = matrix.num_col();
00088 if( size != matrix.num_row() ) {
00089 cout << "CorrelatedData: WARNING: Matrix not square; using sub matrix"
00090 << endl;
00091 size = size < matrix.num_row() ? size : matrix.num_row();
00092 }
00093
00094 HepMatrix sqRoot(size, size, 0);
00095 double ck, rootElementSquared;
00096
00097
00098
00099 for (int j = 0; j < size; j++) {
00100
00101 ck = 0;
00102 for (int k = 0; k < j; k++){
00103 ck += sqRoot[j][k]*sqRoot[j][k];
00104 }
00105 if ( ( rootElementSquared = abs(matrix[j][j] - ck) ) < 0 ) {
00106 sqRoot[j][j] = 1;
00107 cout << "CorrelatedData: WARNING: CRITICAL error in 'root(matrix)'"
00108 << endl;
00109 }else{
00110 sqRoot[j][j] = sqrt(rootElementSquared);}
00111
00112 for (int l = j+1; l < size; l++){
00113 ck = 0;
00114 for (int m = 0; m < j; m++){
00115 ck += sqRoot[l][m]*sqRoot[j][m];
00116 }
00117
00118 sqRoot[l][j] = (matrix[l][j] - ck)/sqRoot[j][j];
00119 }
00120
00121 }
00122 return sqRoot;
00123 }
00124
00125 }