/////////////////////////////////////////////////////////////////////
//
// Pluto build-in genbod
// Copied from PData (originally from Ref. 5)
//
// The particles named with "corr1" and "corr2" can be
// folded with the mass distribution named "/correlation"
// 
//
//                                  Author: Kagarlis
//                                  Reimplemented: IF
/////////////////////////////////////////////////////////////////////


using namespace std;
#include <sstream>
#include <iostream>
#include <iomanip>

#include "PGenBod.h"
#include "PKinematics.h"


ClassImp(PGenBod)

PGenBod::PGenBod() {
    Fatal("PGenBod()", "Wrong constructor");
};

PGenBod::PGenBod(const Char_t *id, const Char_t *de, Int_t key) : 
    PChannelModel (id, de, key) {

    parent  = NULL;
    primary = NULL;
    n_daughters = 0;
    correlator = NULL;
    weight_max = 1.0000001;

    for (int i=0; i<MAX_GENBOD_NUM; i++) {
	daughter[i]=NULL;
    }
};

PDistribution *PGenBod::Clone(const char*) const {
    return new PGenBod((const PGenBod &)* this);
};

Bool_t PGenBod::Init(void) {
    parent = GetParticle("parent");
    if (!parent) {
	Warning("Init", "Parent not found");
	return kFALSE;
    }

    daughter[0] = GetParticle("corr1");
    daughter[1] = GetParticle("corr2");
    
    bool myloop=1;
    for (n_daughters=0; n_daughters<MAX_GENBOD_NUM && myloop; n_daughters++) {
	if (!daughter[n_daughters]) 
	    daughter[n_daughters] = GetParticle("daughter");
	if (!daughter[n_daughters]) {
	    myloop = 0;
	}
    }
    n_daughters--;

    correlator = GetSecondaryModel("correlation");
    //if (correlator) SetVersionFlag(VERSION_NO_PHASE_SPACE);

    return kTRUE;    
};

Double_t PGenBod::GetWeight() {
    if (GetVersionFlag(VERSION_WEIGHTING)) return local_weight;
    return 1;
}


Bool_t PGenBod::SampleMomentum(void) {

    double ecm = parent->M();

    const long double twopi = 2.*TMath::Pi();
    int i, j, i4, nm1=n_daughters-1, nm2=n_daughters-2, nnm4=3*n_daughters-4, ir=n_daughters-3;
    double tm=0., emmin=0., emmax, bang, etm, wtmax=1., c, s, cb, sb, r,
	esys, beta=-1, gamma=-1, aa, w0, em[n_daughters], emm[n_daughters],
	sm[n_daughters], ems[n_daughters], pd[n_daughters], rno[nnm4], pv[4*n_daughters];
     
    for (i=0; i<n_daughters; ++i) {
	em[i] = daughter[i]->M();
    }

    //Pluto-Genbod
    for (i=0; i<n_daughters; ++i) {
	ems[i] = (em[i]*em[i]);
	tm += em[i];
	sm[i] = tm;
    }
    emm[0] = em[0];
    etm = ecm-tm;
    emm[nm1] = ecm;
    emmax = etm+em[0];
    
    for (i=1; i<n_daughters; ++i) {
	emmin += em[i-1];
	emmax += em[i];
	wtmax *= PKinematics::pcms(emmax, emmin, em[i]);
    }
    if (wtmax == 0.) {
	Warning("SampleMomentum", "wtmax==0");
	return kFALSE;    
    }

    Int_t w_counter = 0;

 repeat:

    if (correlator) {
	Double_t corr;
	correlator->SampleMass(&corr);
	rno[0] = (corr-sm[1])/etm; 
    }

 repeat2:
    if (correlator) {
	for (i=1; i<nnm4; ++i) 
	    rno[i]=PUtils::sampleFlat();
    } else {
	for (i=0; i<nnm4; ++i) 
	    rno[i]=PUtils::sampleFlat();
    }

    if (nm2 > 0) {
	if (!correlator)
	    PUtils::dsort(rno, nm2);
	else if (nm2 > 3)
	    PUtils::dsort(rno+2, nm2-2);
	for (i=1; i<nm1; ++i) 
	    emm[i] = rno[i-1]*etm+sm[i];
    }
    w0 = 1./wtmax;
    
    for (i=0; i<nm1; ++i) {
	pd[i] = PKinematics::pcms(emm[i+1], emm[i], em[i+1]);
	
	if (i>0 || !correlator) 
	    w0 *= pd[i];
	else if (pd[i] == 0) 
	    w0 = 0;
    }

    if (w0 == 0.) {
	if (w_counter < 100) {
	    //make another try...
	    w_counter++;
	    goto repeat2;
	}
	if ((w_counter < 110) && correlator) {
	    w_counter++;
	    goto repeat;
	    Warning("SampleMomentum", "w0==0");
	}
	return kFALSE;
    }
    
    local_weight = 1.;

    if (GetVersionFlag(VERSION_SAMPLING) && !GetVersionFlag(VERSION_NO_PHASE_SPACE)) {
	if (w0 > weight_max) {
	    Warning("SampleMomentum", "Weight (%lf) > max (%lf)", w0, weight_max);
	    weight_max = w0*1.1;
	    goto repeat2; 
	}
	if (w0/weight_max < PUtils::sampleFlat()) {
	    if (w_counter < 10000) { 
		w_counter++;
		goto repeat2; // take weight into account (R.H.)
	    } else { // happens very rare (fixed bug Nr. 359)
		return kFALSE;
	    }
	}
    } else if (GetVersionFlag(VERSION_WEIGHTING)) {
	local_weight = w0;
    } 

    pv[0] = 0.;
    pv[1] = pd[0];
    pv[2] = 0.;
    for (i=1; i<n_daughters; ++i) {

	i4 = 4*i;
	pv[i4]   = 0.;
	pv[i4+1] = -pd[i-1];
	pv[i4+2] = 0.;
	++ir;
	bang = twopi*rno[ir];
	cb   = cos(bang);          // cos(phi)
	sb   = sin(bang);          // sin(phi)
	++ir;
	r = rno[ir];
	c = 2.*r-1.;             // here comes the scattering angle sampling 

	s = sqrt(1.-c*c);        // sin(theta)
	if (i != nm1) {
	    esys  = sqrt(pd[i]*pd[i]+emm[i]*emm[i]);
	    beta  = pd[i]/esys;
	    gamma = esys/emm[i];
	}
	for (j=0; j<=i; ++j) {
	    //for (j=1;j<=i;++j) {
	    int jj=4*j, jj1=jj+1, jj2=jj1+1, jj3=jj2+1;
	    aa=( pv[jj ] *  pv[jj ] +
		 pv[jj1] *  pv[jj1] +
		 pv[jj2] *  pv[jj2] );
	    pv[jj3]=sqrt(aa + ems[j]);
	    PKinematics::rotes(c, s, cb, sb, pv+jj);
	    if (i != nm1) 
		pv[jj1] = gamma*( pv[jj1] + beta * pv[jj3] );
	}
  }
    
    for (i=0; i<n_daughters; ++i) {
	//k=i+1;
	i4 = 4*i;
	
	// ______________________________________________________________
	// In the original GENBOD the beam was oriented along the y axis.
	// This is irrelevant so long as theta and phi are isotropic.
	// Since we have introduced anisotropic polar angles,
	// p_y must be interchanged with p_z in order that z be
	// the beam axis. This is equivalent to letting the azimuthal
	// angle phi -> 360-phi. For consistency in case phi anisotropy is
	// also introduced in the future, the sign of p_x has been flipped.
	//                                                     MAK 7.10.99
	//	cout << "set:" << -pv[i4]  <<":"<<  pv[i4+2]  <<":"<<  pv[i4+1]   <<":"<<   pv[i4+3] << endl;
	daughter[i]->SetPxPyPzE(-pv[i4], pv[i4+2], pv[i4+1], pv[i4+3]);
	
	// ______________________________________________________________
    }

    return kTRUE;
};

void PGenBod::Print(const Option_t*) const {
    BasePrint();
};


 PGenBod.cc:1
 PGenBod.cc:2
 PGenBod.cc:3
 PGenBod.cc:4
 PGenBod.cc:5
 PGenBod.cc:6
 PGenBod.cc:7
 PGenBod.cc:8
 PGenBod.cc:9
 PGenBod.cc:10
 PGenBod.cc:11
 PGenBod.cc:12
 PGenBod.cc:13
 PGenBod.cc:14
 PGenBod.cc:15
 PGenBod.cc:16
 PGenBod.cc:17
 PGenBod.cc:18
 PGenBod.cc:19
 PGenBod.cc:20
 PGenBod.cc:21
 PGenBod.cc:22
 PGenBod.cc:23
 PGenBod.cc:24
 PGenBod.cc:25
 PGenBod.cc:26
 PGenBod.cc:27
 PGenBod.cc:28
 PGenBod.cc:29
 PGenBod.cc:30
 PGenBod.cc:31
 PGenBod.cc:32
 PGenBod.cc:33
 PGenBod.cc:34
 PGenBod.cc:35
 PGenBod.cc:36
 PGenBod.cc:37
 PGenBod.cc:38
 PGenBod.cc:39
 PGenBod.cc:40
 PGenBod.cc:41
 PGenBod.cc:42
 PGenBod.cc:43
 PGenBod.cc:44
 PGenBod.cc:45
 PGenBod.cc:46
 PGenBod.cc:47
 PGenBod.cc:48
 PGenBod.cc:49
 PGenBod.cc:50
 PGenBod.cc:51
 PGenBod.cc:52
 PGenBod.cc:53
 PGenBod.cc:54
 PGenBod.cc:55
 PGenBod.cc:56
 PGenBod.cc:57
 PGenBod.cc:58
 PGenBod.cc:59
 PGenBod.cc:60
 PGenBod.cc:61
 PGenBod.cc:62
 PGenBod.cc:63
 PGenBod.cc:64
 PGenBod.cc:65
 PGenBod.cc:66
 PGenBod.cc:67
 PGenBod.cc:68
 PGenBod.cc:69
 PGenBod.cc:70
 PGenBod.cc:71
 PGenBod.cc:72
 PGenBod.cc:73
 PGenBod.cc:74
 PGenBod.cc:75
 PGenBod.cc:76
 PGenBod.cc:77
 PGenBod.cc:78
 PGenBod.cc:79
 PGenBod.cc:80
 PGenBod.cc:81
 PGenBod.cc:82
 PGenBod.cc:83
 PGenBod.cc:84
 PGenBod.cc:85
 PGenBod.cc:86
 PGenBod.cc:87
 PGenBod.cc:88
 PGenBod.cc:89
 PGenBod.cc:90
 PGenBod.cc:91
 PGenBod.cc:92
 PGenBod.cc:93
 PGenBod.cc:94
 PGenBod.cc:95
 PGenBod.cc:96
 PGenBod.cc:97
 PGenBod.cc:98
 PGenBod.cc:99
 PGenBod.cc:100
 PGenBod.cc:101
 PGenBod.cc:102
 PGenBod.cc:103
 PGenBod.cc:104
 PGenBod.cc:105
 PGenBod.cc:106
 PGenBod.cc:107
 PGenBod.cc:108
 PGenBod.cc:109
 PGenBod.cc:110
 PGenBod.cc:111
 PGenBod.cc:112
 PGenBod.cc:113
 PGenBod.cc:114
 PGenBod.cc:115
 PGenBod.cc:116
 PGenBod.cc:117
 PGenBod.cc:118
 PGenBod.cc:119
 PGenBod.cc:120
 PGenBod.cc:121
 PGenBod.cc:122
 PGenBod.cc:123
 PGenBod.cc:124
 PGenBod.cc:125
 PGenBod.cc:126
 PGenBod.cc:127
 PGenBod.cc:128
 PGenBod.cc:129
 PGenBod.cc:130
 PGenBod.cc:131
 PGenBod.cc:132
 PGenBod.cc:133
 PGenBod.cc:134
 PGenBod.cc:135
 PGenBod.cc:136
 PGenBod.cc:137
 PGenBod.cc:138
 PGenBod.cc:139
 PGenBod.cc:140
 PGenBod.cc:141
 PGenBod.cc:142
 PGenBod.cc:143
 PGenBod.cc:144
 PGenBod.cc:145
 PGenBod.cc:146
 PGenBod.cc:147
 PGenBod.cc:148
 PGenBod.cc:149
 PGenBod.cc:150
 PGenBod.cc:151
 PGenBod.cc:152
 PGenBod.cc:153
 PGenBod.cc:154
 PGenBod.cc:155
 PGenBod.cc:156
 PGenBod.cc:157
 PGenBod.cc:158
 PGenBod.cc:159
 PGenBod.cc:160
 PGenBod.cc:161
 PGenBod.cc:162
 PGenBod.cc:163
 PGenBod.cc:164
 PGenBod.cc:165
 PGenBod.cc:166
 PGenBod.cc:167
 PGenBod.cc:168
 PGenBod.cc:169
 PGenBod.cc:170
 PGenBod.cc:171
 PGenBod.cc:172
 PGenBod.cc:173
 PGenBod.cc:174
 PGenBod.cc:175
 PGenBod.cc:176
 PGenBod.cc:177
 PGenBod.cc:178
 PGenBod.cc:179
 PGenBod.cc:180
 PGenBod.cc:181
 PGenBod.cc:182
 PGenBod.cc:183
 PGenBod.cc:184
 PGenBod.cc:185
 PGenBod.cc:186
 PGenBod.cc:187
 PGenBod.cc:188
 PGenBod.cc:189
 PGenBod.cc:190
 PGenBod.cc:191
 PGenBod.cc:192
 PGenBod.cc:193
 PGenBod.cc:194
 PGenBod.cc:195
 PGenBod.cc:196
 PGenBod.cc:197
 PGenBod.cc:198
 PGenBod.cc:199
 PGenBod.cc:200
 PGenBod.cc:201
 PGenBod.cc:202
 PGenBod.cc:203
 PGenBod.cc:204
 PGenBod.cc:205
 PGenBod.cc:206
 PGenBod.cc:207
 PGenBod.cc:208
 PGenBod.cc:209
 PGenBod.cc:210
 PGenBod.cc:211
 PGenBod.cc:212
 PGenBod.cc:213
 PGenBod.cc:214
 PGenBod.cc:215
 PGenBod.cc:216
 PGenBod.cc:217
 PGenBod.cc:218
 PGenBod.cc:219
 PGenBod.cc:220
 PGenBod.cc:221
 PGenBod.cc:222
 PGenBod.cc:223
 PGenBod.cc:224
 PGenBod.cc:225
 PGenBod.cc:226
 PGenBod.cc:227
 PGenBod.cc:228
 PGenBod.cc:229
 PGenBod.cc:230
 PGenBod.cc:231
 PGenBod.cc:232
 PGenBod.cc:233
 PGenBod.cc:234
 PGenBod.cc:235
 PGenBod.cc:236
 PGenBod.cc:237
 PGenBod.cc:238
 PGenBod.cc:239
 PGenBod.cc:240
 PGenBod.cc:241
 PGenBod.cc:242
 PGenBod.cc:243
 PGenBod.cc:244
 PGenBod.cc:245
 PGenBod.cc:246
 PGenBod.cc:247
 PGenBod.cc:248
 PGenBod.cc:249