45 fX1(x1), fX2(x2), fChanged(true), fTolerance(1.e-8), fVerbose(0)
78 G4cout <<
"G4PolynomialPDF::Simplify() WARNING: had to pop coefficient "
90 G4cout <<
"G4PolynomialPDF::SetDomain() WARNING: Invalid domain! "
91 <<
"(x1 = " << x1 <<
", x2 = " << x2 <<
")." <<
G4endl;
118 G4cout <<
"G4PolynomialPDF::Normalize() WARNING: PDF has non-positive area: "
138 if(ddxPower < -1 || ddxPower > 2) {
140 G4cout <<
"G4PolynomialPDF::GetX() WARNING: ddxPower " << ddxPower
141 <<
" not implemented" <<
G4endl;
155 else if(ddxPower == 1) {
158 else if(ddxPower == 2) {
171 if(x1 < fX1 || x2 >
fX2 || x2 < x1) {
173 G4cout <<
"G4PolynomialPDF::HasNegativeMinimum() WARNING: Invalid range "
174 << x1 <<
" - " << x2 <<
G4endl;
192 if(xMin < x1) xMin = x1;
193 if(xMin > x2) xMin = x2;
202 extremum >= x2-(x2-x1)*
fTolerance)
return false;
213 G4cout <<
"G4PolynomialPDF::GetRandomX() WARNING: PDF has negative values, returning 0..."
236 G4cout <<
"G4PolynomialPDF::GetX() WARNING: no PDF defined!" <<
G4endl;
240 if(ddxPower < -1 || ddxPower > 1) {
242 G4cout <<
"G4PolynomialPDF::GetX() WARNING: ddxPower " << ddxPower
243 <<
" not implemented" <<
G4endl;
247 if(ddxPower == -1 && (p<0 || p>1)) {
249 G4cout <<
"G4PolynomialPDF::GetX() WARNING: p is out of range" <<
G4endl;
255 if(x2 <= x1 || x1 < fX1 || x2 >
fX2) {
257 G4cout <<
"G4PolynomialPDF::GetX() WARNING: domain must have fX1 <= x1 < x2 <= fX2. "
258 <<
"You sent x1 = " << x1 <<
", x2 = " << x2 <<
"." <<
G4endl;
275 G4cout <<
"G4PolynomialPDF::GetX() WARNING: Got slope = 0. "
276 <<
"Did you forget to Simplify()?" <<
G4endl;
280 if(ddxPower == 1) slope *= 2.;
285 else if(value > x2) {
300 if(ddxPower == 1) b *= 2.;
304 G4cout <<
"G4PolynomialPDF::GetX() WARNING: Got a = 0. "
305 <<
"Did you forget to Simplify()?" <<
G4endl;
309 if(ddxPower == 1) a *= 3;
310 else if(ddxPower == -1) a *= 0.5;
311 double sqrtFactor = b*b - 4.*a*c;
312 if(sqrtFactor < 0)
return x2;
313 sqrtFactor = sqrt(sqrtFactor)/2./fabs(a);
314 G4double valueMinus = -b/2./a - sqrtFactor;
315 if(valueMinus >= x1 && valueMinus <= x2)
return valueMinus;
316 else if(valueMinus > x2)
return x2;
317 G4double valuePlus = -b/2./a + sqrtFactor;
318 if(valuePlus >= x1 && valuePlus <= x2)
return valuePlus;
319 else if(valuePlus < x1)
return x2;
320 return (x1-valueMinus <= valuePlus-x2) ? x1 : x2;
325 if(guess < x1 || guess > x2) guess = (x2+x1)*0.5;
327 size_t iterations = 0;
340 else if(ddxPower == 0) {
350 if(f == 0)
return guess;
353 G4cout <<
"G4PolynomialPDF::GetX() WARNING: got f != 0 but slope = 0 for ddxPower = "
358 lastChange = - f/dfdx;
360 if(guess + lastChange < x1) {
361 lastChange = x1 - guess;
362 }
else if(guess + lastChange > x2) {
363 lastChange = x2 - guess;
370 if(iterations > 50) {
373 G4cout <<
"G4PolynomialPDF::GetX() WARNING: got stuck searching for " << p
374 <<
" between " << x1 <<
" and " << x2 <<
" with ddxPower = "
376 <<
". Last guess was " << guess <<
"." <<
G4endl;
379 if(ddxPower==-1 && bisect) {
381 G4cout <<
"G4PolynomialPDF::GetX() WARNING: Biseting and trying again..."
397 if(fz < 0)
return Bisect(p, z, x2);
403 G4cout <<
"G4PolynomialPDF::Dump() - PDF(x) = ";
408 if(i>1)
G4cout <<
"^" << i;
411 G4cout <<
"G4PolynomialPDF::Dump() - Interval: " <<
fX1 <<
" <= x < "
G4GLOB_DLL std::ostream G4cout
void SetNCoefficients(size_t n)
size_t GetNCoefficients() const
G4double Evaluate(G4double x, G4int ddxPower=0)
void SetCoefficient(size_t i, G4double value, bool doSimplify)
G4double GetCoefficient(size_t i) const
std::vector< G4double > fCoefficients
G4PolynomialPDF(size_t n=0, const double *coeffs=nullptr, G4double x1=0, G4double x2=1)
G4bool HasNegativeMinimum(G4double x1, G4double x2)
G4double GetX(G4double p, G4double x1, G4double x2, G4int ddxPower=0, G4double guess=1.e99, G4bool bisect=true)
void SetDomain(G4double x1, G4double x2)
G4double EvalInverseCDF(G4double p)
void SetCoefficients(const std::vector< G4double > &v)
G4double Bisect(G4double p, G4double x1, G4double x2)