2// ********************************************************************
3// * License and Disclaimer *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
26// G4Integrator inline methods implementation
28// Author: V.Grichine, 04.09.1999 - First implementation based on
29// G4SimpleIntegration class with H.P.Wellisch, G.Cosmo, and
30// E.TCherniaev advises
31// --------------------------------------------------------------------
33/////////////////////////////////////////////////////////////////////
35// Sympson integration method
37/////////////////////////////////////////////////////////////////////
39// Integration of class member functions T::f by Simpson method.
41template <class T, class F>
42G4double G4Integrator<T, F>::Simpson(T& typeT, F f, G4double xInitial,
43 G4double xFinal, G4int iterationNumber)
46 G4double step = (xFinal - xInitial) / iterationNumber;
47 G4double x = xInitial;
48 G4double xPlus = xInitial + 0.5 * step;
49 G4double mean = ((typeT.*f)(xInitial) + (typeT.*f)(xFinal)) * 0.5;
50 G4double sum = (typeT.*f)(xPlus);
52 for(i = 1; i < iterationNumber; ++i)
56 mean += (typeT.*f)(x);
57 sum += (typeT.*f)(xPlus);
61 return mean * step / 3.0;
64/////////////////////////////////////////////////////////////////////
66// Integration of class member functions T::f by Simpson method.
67// Convenient to use with 'this' pointer
69template <class T, class F>
70G4double G4Integrator<T, F>::Simpson(T* ptrT, F f, G4double xInitial,
71 G4double xFinal, G4int iterationNumber)
74 G4double step = (xFinal - xInitial) / iterationNumber;
75 G4double x = xInitial;
76 G4double xPlus = xInitial + 0.5 * step;
77 G4double mean = ((ptrT->*f)(xInitial) + (ptrT->*f)(xFinal)) * 0.5;
78 G4double sum = (ptrT->*f)(xPlus);
80 for(i = 1; i < iterationNumber; ++i)
84 mean += (ptrT->*f)(x);
85 sum += (ptrT->*f)(xPlus);
89 return mean * step / 3.0;
92/////////////////////////////////////////////////////////////////////
94// Integration of class member functions T::f by Simpson method.
95// Convenient to use, when function f is defined in global scope, i.e. in main()
98template <class T, class F>
99G4double G4Integrator<T, F>::Simpson(G4double (*f)(G4double), G4double xInitial,
100 G4double xFinal, G4int iterationNumber)
103 G4double step = (xFinal - xInitial) / iterationNumber;
104 G4double x = xInitial;
105 G4double xPlus = xInitial + 0.5 * step;
106 G4double mean = ((*f)(xInitial) + (*f)(xFinal)) * 0.5;
107 G4double sum = (*f)(xPlus);
109 for(i = 1; i < iterationNumber; ++i)
118 return mean * step / 3.0;
121//////////////////////////////////////////////////////////////////////////
123// Adaptive Gauss method
125//////////////////////////////////////////////////////////////////////////
129template <class T, class F>
130G4double G4Integrator<T, F>::Gauss(T& typeT, F f, G4double xInitial,
133 static const G4double root = 1.0 / std::sqrt(3.0);
135 G4double xMean = (xInitial + xFinal) / 2.0;
136 G4double Step = (xFinal - xInitial) / 2.0;
137 G4double delta = Step * root;
138 G4double sum = ((typeT.*f)(xMean + delta) + (typeT.*f)(xMean - delta));
143//////////////////////////////////////////////////////////////////////
147template <class T, class F>
148G4double G4Integrator<T, F>::Gauss(T* ptrT, F f, G4double a, G4double b)
150 return Gauss(*ptrT, f, a, b);
153///////////////////////////////////////////////////////////////////////
157template <class T, class F>
158G4double G4Integrator<T, F>::Gauss(G4double (*f)(G4double), G4double xInitial,
161 static const G4double root = 1.0 / std::sqrt(3.0);
163 G4double xMean = (xInitial + xFinal) / 2.0;
164 G4double Step = (xFinal - xInitial) / 2.0;
165 G4double delta = Step * root;
166 G4double sum = ((*f)(xMean + delta) + (*f)(xMean - delta));
171///////////////////////////////////////////////////////////////////////////
175template <class T, class F>
176void G4Integrator<T, F>::AdaptGauss(T& typeT, F f, G4double xInitial,
177 G4double xFinal, G4double fTolerance,
178 G4double& sum, G4int& depth)
182 G4cout << "G4Integrator<T,F>::AdaptGauss: WARNING !!!" << G4endl;
183 G4cout << "Function varies too rapidly to get stated accuracy in 100 steps "
188 G4double xMean = (xInitial + xFinal) / 2.0;
189 G4double leftHalf = Gauss(typeT, f, xInitial, xMean);
190 G4double rightHalf = Gauss(typeT, f, xMean, xFinal);
191 G4double full = Gauss(typeT, f, xInitial, xFinal);
192 if(std::fabs(leftHalf + rightHalf - full) < fTolerance)
199 AdaptGauss(typeT, f, xInitial, xMean, fTolerance, sum, depth);
200 AdaptGauss(typeT, f, xMean, xFinal, fTolerance, sum, depth);
204template <class T, class F>
205void G4Integrator<T, F>::AdaptGauss(T* ptrT, F f, G4double xInitial,
206 G4double xFinal, G4double fTolerance,
207 G4double& sum, G4int& depth)
209 AdaptGauss(*ptrT, f, xInitial, xFinal, fTolerance, sum, depth);
212/////////////////////////////////////////////////////////////////////////
215template <class T, class F>
216void G4Integrator<T, F>::AdaptGauss(G4double (*f)(G4double), G4double xInitial,
217 G4double xFinal, G4double fTolerance,
218 G4double& sum, G4int& depth)
222 G4cout << "G4SimpleIntegration::AdaptGauss: WARNING !!!" << G4endl;
223 G4cout << "Function varies too rapidly to get stated accuracy in 100 steps "
228 G4double xMean = (xInitial + xFinal) / 2.0;
229 G4double leftHalf = Gauss(f, xInitial, xMean);
230 G4double rightHalf = Gauss(f, xMean, xFinal);
231 G4double full = Gauss(f, xInitial, xFinal);
232 if(std::fabs(leftHalf + rightHalf - full) < fTolerance)
239 AdaptGauss(f, xInitial, xMean, fTolerance, sum, depth);
240 AdaptGauss(f, xMean, xFinal, fTolerance, sum, depth);
244////////////////////////////////////////////////////////////////////////
246// Adaptive Gauss integration with accuracy 'e'
247// Convenient for using with class object typeT
249template <class T, class F>
250G4double G4Integrator<T, F>::AdaptiveGauss(T& typeT, F f, G4double xInitial,
251 G4double xFinal, G4double e)
255 AdaptGauss(typeT, f, xInitial, xFinal, e, sum, depth);
259////////////////////////////////////////////////////////////////////////
261// Adaptive Gauss integration with accuracy 'e'
262// Convenient for using with 'this' pointer
264template <class T, class F>
265G4double G4Integrator<T, F>::AdaptiveGauss(T* ptrT, F f, G4double xInitial,
266 G4double xFinal, G4double e)
268 return AdaptiveGauss(*ptrT, f, xInitial, xFinal, e);
271////////////////////////////////////////////////////////////////////////
273// Adaptive Gauss integration with accuracy 'e'
274// Convenient for using with global scope function f
276template <class T, class F>
277G4double G4Integrator<T, F>::AdaptiveGauss(G4double (*f)(G4double),
278 G4double xInitial, G4double xFinal,
283 AdaptGauss(f, xInitial, xFinal, e, sum, depth);
287////////////////////////////////////////////////////////////////////////////
288// Gauss integration methods involving ortogonal polynomials
289////////////////////////////////////////////////////////////////////////////
291// Methods involving Legendre polynomials
293/////////////////////////////////////////////////////////////////////////
295// The value nLegendre set the accuracy required, i.e the number of points
296// where the function pFunction will be evaluated during integration.
297// The function creates the arrays for abscissas and weights that used
298// in Gauss-Legendre quadrature method.
299// The values a and b are the limits of integration of the function f .
300// nLegendre MUST BE EVEN !!!
301// Returns the integral of the function f between a and b, by 2*fNumber point
302// Gauss-Legendre integration: the function is evaluated exactly
303// 2*fNumber times at interior points in the range of integration.
304// Since the weights and abscissas are, in this case, symmetric around
305// the midpoint of the range of integration, there are actually only
306// fNumber distinct values of each.
307// Convenient for using with some class object dataT
309template <class T, class F>
310G4double G4Integrator<T, F>::Legendre(T& typeT, F f, G4double a, G4double b,
313 G4double nwt, nwt1, temp1, temp2, temp3, temp;
314 G4double xDiff, xMean, dx, integral;
316 const G4double tolerance = 1.6e-10;
317 G4int i, j, k = nLegendre;
318 G4int fNumber = (nLegendre + 1) / 2;
322 G4Exception("G4Integrator<T,F>::Legendre(T&,F, ...)", "InvalidCall",
323 FatalException, "Invalid (odd) nLegendre in constructor.");
326 G4double* fAbscissa = new G4double[fNumber];
327 G4double* fWeight = new G4double[fNumber];
329 for(i = 1; i <= fNumber; ++i) // Loop over the desired roots
331 nwt = std::cos(CLHEP::pi * (i - 0.25) /
332 (k + 0.5)); // Initial root approximation
334 do // loop of Newton's method
338 for(j = 1; j <= k; ++j)
342 temp1 = ((2.0 * j - 1.0) * nwt * temp2 - (j - 1.0) * temp3) / j;
344 temp = k * (nwt * temp1 - temp2) / (nwt * nwt - 1.0);
346 nwt = nwt1 - temp1 / temp; // Newton's method
347 } while(std::fabs(nwt - nwt1) > tolerance);
349 fAbscissa[fNumber - i] = nwt;
350 fWeight[fNumber - i] = 2.0 / ((1.0 - nwt * nwt) * temp * temp);
354 // Now we ready to get integral
357 xMean = 0.5 * (a + b);
358 xDiff = 0.5 * (b - a);
360 for(i = 0; i < fNumber; ++i)
362 dx = xDiff * fAbscissa[i];
363 integral += fWeight[i] * ((typeT.*f)(xMean + dx) + (typeT.*f)(xMean - dx));
367 return integral *= xDiff;
370///////////////////////////////////////////////////////////////////////
372// Convenient for using with the pointer 'this'
374template <class T, class F>
375G4double G4Integrator<T, F>::Legendre(T* ptrT, F f, G4double a, G4double b,
378 return Legendre(*ptrT, f, a, b, nLegendre);
381///////////////////////////////////////////////////////////////////////
383// Convenient for using with global scope function f
385template <class T, class F>
386G4double G4Integrator<T, F>::Legendre(G4double (*f)(G4double), G4double a,
387 G4double b, G4int nLegendre)
389 G4double nwt, nwt1, temp1, temp2, temp3, temp;
390 G4double xDiff, xMean, dx, integral;
392 const G4double tolerance = 1.6e-10;
393 G4int i, j, k = nLegendre;
394 G4int fNumber = (nLegendre + 1) / 2;
398 G4Exception("G4Integrator<T,F>::Legendre(...)", "InvalidCall",
399 FatalException, "Invalid (odd) nLegendre in constructor.");
402 G4double* fAbscissa = new G4double[fNumber];
403 G4double* fWeight = new G4double[fNumber];
405 for(i = 1; i <= fNumber; i++) // Loop over the desired roots
407 nwt = std::cos(CLHEP::pi * (i - 0.25) /
408 (k + 0.5)); // Initial root approximation
410 do // loop of Newton's method
414 for(j = 1; j <= k; ++j)
418 temp1 = ((2.0 * j - 1.0) * nwt * temp2 - (j - 1.0) * temp3) / j;
420 temp = k * (nwt * temp1 - temp2) / (nwt * nwt - 1.0);
422 nwt = nwt1 - temp1 / temp; // Newton's method
423 } while(std::fabs(nwt - nwt1) > tolerance);
425 fAbscissa[fNumber - i] = nwt;
426 fWeight[fNumber - i] = 2.0 / ((1.0 - nwt * nwt) * temp * temp);
430 // Now we ready to get integral
433 xMean = 0.5 * (a + b);
434 xDiff = 0.5 * (b - a);
436 for(i = 0; i < fNumber; ++i)
438 dx = xDiff * fAbscissa[i];
439 integral += fWeight[i] * ((*f)(xMean + dx) + (*f)(xMean - dx));
444 return integral *= xDiff;
447////////////////////////////////////////////////////////////////////////////
449// Returns the integral of the function to be pointed by T::f between a and b,
450// by ten point Gauss-Legendre integration: the function is evaluated exactly
451// ten times at interior points in the range of integration. Since the weights
452// and abscissas are, in this case, symmetric around the midpoint of the
453// range of integration, there are actually only five distinct values of each
454// Convenient for using with class object typeT
456template <class T, class F>
457G4double G4Integrator<T, F>::Legendre10(T& typeT, F f, G4double a, G4double b)
460 G4double xDiff, xMean, dx, integral;
462 // From Abramowitz M., Stegan I.A. 1964 , Handbook of Math... , p. 916
464 static const G4double abscissa[] = { 0.148874338981631, 0.433395394129247,
465 0.679409568299024, 0.865063366688985,
468 static const G4double weight[] = { 0.295524224714753, 0.269266719309996,
469 0.219086362515982, 0.149451349150581,
471 xMean = 0.5 * (a + b);
472 xDiff = 0.5 * (b - a);
474 for(i = 0; i < 5; ++i)
476 dx = xDiff * abscissa[i];
477 integral += weight[i] * ((typeT.*f)(xMean + dx) + (typeT.*f)(xMean - dx));
479 return integral *= xDiff;
482///////////////////////////////////////////////////////////////////////////
484// Convenient for using with the pointer 'this'
486template <class T, class F>
487G4double G4Integrator<T, F>::Legendre10(T* ptrT, F f, G4double a, G4double b)
489 return Legendre10(*ptrT, f, a, b);
492//////////////////////////////////////////////////////////////////////////
494// Convenient for using with global scope functions
496template <class T, class F>
497G4double G4Integrator<T, F>::Legendre10(G4double (*f)(G4double), G4double a,
501 G4double xDiff, xMean, dx, integral;
503 // From Abramowitz M., Stegan I.A. 1964 , Handbook of Math... , p. 916
505 static const G4double abscissa[] = { 0.148874338981631, 0.433395394129247,
506 0.679409568299024, 0.865063366688985,
509 static const G4double weight[] = { 0.295524224714753, 0.269266719309996,
510 0.219086362515982, 0.149451349150581,
512 xMean = 0.5 * (a + b);
513 xDiff = 0.5 * (b - a);
515 for(i = 0; i < 5; ++i)
517 dx = xDiff * abscissa[i];
518 integral += weight[i] * ((*f)(xMean + dx) + (*f)(xMean - dx));
520 return integral *= xDiff;
523///////////////////////////////////////////////////////////////////////
525// Returns the integral of the function to be pointed by T::f between a and b,
526// by 96 point Gauss-Legendre integration: the function is evaluated exactly
527// ten Times at interior points in the range of integration. Since the weights
528// and abscissas are, in this case, symmetric around the midpoint of the
529// range of integration, there are actually only five distinct values of each
530// Convenient for using with some class object typeT
532template <class T, class F>
533G4double G4Integrator<T, F>::Legendre96(T& typeT, F f, G4double a, G4double b)
536 G4double xDiff, xMean, dx, integral;
538 // From Abramowitz M., Stegan I.A. 1964 , Handbook of Math... , p. 919
540 static const G4double abscissa[] = {
541 0.016276744849602969579, 0.048812985136049731112,
542 0.081297495464425558994, 0.113695850110665920911,
543 0.145973714654896941989, 0.178096882367618602759, // 6
545 0.210031310460567203603, 0.241743156163840012328,
546 0.273198812591049141487, 0.304364944354496353024,
547 0.335208522892625422616, 0.365696861472313635031, // 12
549 0.395797649828908603285, 0.425478988407300545365,
550 0.454709422167743008636, 0.483457973920596359768,
551 0.511694177154667673586, 0.539388108324357436227, // 18
553 0.566510418561397168404, 0.593032364777572080684,
554 0.618925840125468570386, 0.644163403784967106798,
555 0.668718310043916153953, 0.692564536642171561344, // 24
557 0.715676812348967626225, 0.738030643744400132851,
558 0.759602341176647498703, 0.780369043867433217604,
559 0.800308744139140817229, 0.819400310737931675539, // 30
561 0.837623511228187121494, 0.854959033434601455463,
562 0.871388505909296502874, 0.886894517402420416057,
563 0.901460635315852341319, 0.915071423120898074206, // 36
565 0.927712456722308690965, 0.939370339752755216932,
566 0.950032717784437635756, 0.959688291448742539300,
567 0.968326828463264212174, 0.975939174585136466453, // 42
569 0.982517263563014677447, 0.988054126329623799481,
570 0.992543900323762624572, 0.995981842987209290650,
571 0.998364375863181677724, 0.999689503883230766828 // 48
574 static const G4double weight[] = {
575 0.032550614492363166242, 0.032516118713868835987,
576 0.032447163714064269364, 0.032343822568575928429,
577 0.032206204794030250669, 0.032034456231992663218, // 6
579 0.031828758894411006535, 0.031589330770727168558,
580 0.031316425596862355813, 0.031010332586313837423,
581 0.030671376123669149014, 0.030299915420827593794, // 12
583 0.029896344136328385984, 0.029461089958167905970,
584 0.028994614150555236543, 0.028497411065085385646,
585 0.027970007616848334440, 0.027412962726029242823, // 18
587 0.026826866725591762198, 0.026212340735672413913,
588 0.025570036005349361499, 0.024900633222483610288,
589 0.024204841792364691282, 0.023483399085926219842, // 24
591 0.022737069658329374001, 0.021966644438744349195,
592 0.021172939892191298988, 0.020356797154333324595,
593 0.019519081140145022410, 0.018660679627411467385, // 30
595 0.017782502316045260838, 0.016885479864245172450,
596 0.015970562902562291381, 0.015038721026994938006,
597 0.014090941772314860916, 0.013128229566961572637, // 36
599 0.012151604671088319635, 0.011162102099838498591,
600 0.010160770535008415758, 0.009148671230783386633,
601 0.008126876925698759217, 0.007096470791153865269, // 42
603 0.006058545504235961683, 0.005014202742927517693,
604 0.003964554338444686674, 0.002910731817934946408,
605 0.001853960788946921732, 0.000796792065552012429 // 48
607 xMean = 0.5 * (a + b);
608 xDiff = 0.5 * (b - a);
610 for(i = 0; i < 48; ++i)
612 dx = xDiff * abscissa[i];
613 integral += weight[i] * ((typeT.*f)(xMean + dx) + (typeT.*f)(xMean - dx));
615 return integral *= xDiff;
618///////////////////////////////////////////////////////////////////////
620// Convenient for using with the pointer 'this'
622template <class T, class F>
623G4double G4Integrator<T, F>::Legendre96(T* ptrT, F f, G4double a, G4double b)
625 return Legendre96(*ptrT, f, a, b);
628///////////////////////////////////////////////////////////////////////
630// Convenient for using with global scope function f
632template <class T, class F>
633G4double G4Integrator<T, F>::Legendre96(G4double (*f)(G4double), G4double a,
637 G4double xDiff, xMean, dx, integral;
639 // From Abramowitz M., Stegan I.A. 1964 , Handbook of Math... , p. 919
641 static const G4double abscissa[] = {
642 0.016276744849602969579, 0.048812985136049731112,
643 0.081297495464425558994, 0.113695850110665920911,
644 0.145973714654896941989, 0.178096882367618602759, // 6
646 0.210031310460567203603, 0.241743156163840012328,
647 0.273198812591049141487, 0.304364944354496353024,
648 0.335208522892625422616, 0.365696861472313635031, // 12
650 0.395797649828908603285, 0.425478988407300545365,
651 0.454709422167743008636, 0.483457973920596359768,
652 0.511694177154667673586, 0.539388108324357436227, // 18
654 0.566510418561397168404, 0.593032364777572080684,
655 0.618925840125468570386, 0.644163403784967106798,
656 0.668718310043916153953, 0.692564536642171561344, // 24
658 0.715676812348967626225, 0.738030643744400132851,
659 0.759602341176647498703, 0.780369043867433217604,
660 0.800308744139140817229, 0.819400310737931675539, // 30
662 0.837623511228187121494, 0.854959033434601455463,
663 0.871388505909296502874, 0.886894517402420416057,
664 0.901460635315852341319, 0.915071423120898074206, // 36
666 0.927712456722308690965, 0.939370339752755216932,
667 0.950032717784437635756, 0.959688291448742539300,
668 0.968326828463264212174, 0.975939174585136466453, // 42
670 0.982517263563014677447, 0.988054126329623799481,
671 0.992543900323762624572, 0.995981842987209290650,
672 0.998364375863181677724, 0.999689503883230766828 // 48
675 static const G4double weight[] = {
676 0.032550614492363166242, 0.032516118713868835987,
677 0.032447163714064269364, 0.032343822568575928429,
678 0.032206204794030250669, 0.032034456231992663218, // 6
680 0.031828758894411006535, 0.031589330770727168558,
681 0.031316425596862355813, 0.031010332586313837423,
682 0.030671376123669149014, 0.030299915420827593794, // 12
684 0.029896344136328385984, 0.029461089958167905970,
685 0.028994614150555236543, 0.028497411065085385646,
686 0.027970007616848334440, 0.027412962726029242823, // 18
688 0.026826866725591762198, 0.026212340735672413913,
689 0.025570036005349361499, 0.024900633222483610288,
690 0.024204841792364691282, 0.023483399085926219842, // 24
692 0.022737069658329374001, 0.021966644438744349195,
693 0.021172939892191298988, 0.020356797154333324595,
694 0.019519081140145022410, 0.018660679627411467385, // 30
696 0.017782502316045260838, 0.016885479864245172450,
697 0.015970562902562291381, 0.015038721026994938006,
698 0.014090941772314860916, 0.013128229566961572637, // 36
700 0.012151604671088319635, 0.011162102099838498591,
701 0.010160770535008415758, 0.009148671230783386633,
702 0.008126876925698759217, 0.007096470791153865269, // 42
704 0.006058545504235961683, 0.005014202742927517693,
705 0.003964554338444686674, 0.002910731817934946408,
706 0.001853960788946921732, 0.000796792065552012429 // 48
708 xMean = 0.5 * (a + b);
709 xDiff = 0.5 * (b - a);
711 for(i = 0; i < 48; ++i)
713 dx = xDiff * abscissa[i];
714 integral += weight[i] * ((*f)(xMean + dx) + (*f)(xMean - dx));
716 return integral *= xDiff;
719//////////////////////////////////////////////////////////////////////////////
721// Methods involving Chebyshev polynomials
723///////////////////////////////////////////////////////////////////////////
725// Integrates function pointed by T::f from a to b by Gauss-Chebyshev
727// Convenient for using with class object typeT
729template <class T, class F>
730G4double G4Integrator<T, F>::Chebyshev(T& typeT, F f, G4double a, G4double b,
734 G4double xDiff, xMean, dx, integral = 0.0;
736 G4int fNumber = nChebyshev; // Try to reduce fNumber twice ??
737 G4double cof = CLHEP::pi / fNumber;
738 G4double* fAbscissa = new G4double[fNumber];
739 G4double* fWeight = new G4double[fNumber];
740 for(i = 0; i < fNumber; ++i)
742 fAbscissa[i] = std::cos(cof * (i + 0.5));
743 fWeight[i] = cof * std::sqrt(1 - fAbscissa[i] * fAbscissa[i]);
747 // Now we ready to estimate the integral
750 xMean = 0.5 * (a + b);
751 xDiff = 0.5 * (b - a);
752 for(i = 0; i < fNumber; ++i)
754 dx = xDiff * fAbscissa[i];
755 integral += fWeight[i] * (typeT.*f)(xMean + dx);
759 return integral *= xDiff;
762///////////////////////////////////////////////////////////////////////
764// Convenient for using with 'this' pointer
766template <class T, class F>
767G4double G4Integrator<T, F>::Chebyshev(T* ptrT, F f, G4double a, G4double b,
770 return Chebyshev(*ptrT, f, a, b, n);
773////////////////////////////////////////////////////////////////////////
775// For use with global scope functions f
777template <class T, class F>
778G4double G4Integrator<T, F>::Chebyshev(G4double (*f)(G4double), G4double a,
779 G4double b, G4int nChebyshev)
782 G4double xDiff, xMean, dx, integral = 0.0;
784 G4int fNumber = nChebyshev; // Try to reduce fNumber twice ??
785 G4double cof = CLHEP::pi / fNumber;
786 G4double* fAbscissa = new G4double[fNumber];
787 G4double* fWeight = new G4double[fNumber];
788 for(i = 0; i < fNumber; ++i)
790 fAbscissa[i] = std::cos(cof * (i + 0.5));
791 fWeight[i] = cof * std::sqrt(1 - fAbscissa[i] * fAbscissa[i]);
795 // Now we ready to estimate the integral
798 xMean = 0.5 * (a + b);
799 xDiff = 0.5 * (b - a);
800 for(i = 0; i < fNumber; ++i)
802 dx = xDiff * fAbscissa[i];
803 integral += fWeight[i] * (*f)(xMean + dx);
807 return integral *= xDiff;
810//////////////////////////////////////////////////////////////////////
812// Method involving Laguerre polynomials
814//////////////////////////////////////////////////////////////////////
816// Integral from zero to infinity of std::pow(x,alpha)*std::exp(-x)*f(x).
817// The value of nLaguerre sets the accuracy.
818// The function creates arrays fAbscissa[0,..,nLaguerre-1] and
819// fWeight[0,..,nLaguerre-1] .
820// Convenient for using with class object 'typeT' and (typeT.*f) function
823template <class T, class F>
824G4double G4Integrator<T, F>::Laguerre(T& typeT, F f, G4double alpha,
827 const G4double tolerance = 1.0e-10;
828 const G4int maxNumber = 12;
830 G4double nwt = 0., nwt1, temp1, temp2, temp3, temp, cofi;
831 G4double integral = 0.0;
833 G4int fNumber = nLaguerre;
834 G4double* fAbscissa = new G4double[fNumber];
835 G4double* fWeight = new G4double[fNumber];
837 for(i = 1; i <= fNumber; ++i) // Loop over the desired roots
841 nwt = (1.0 + alpha) * (3.0 + 0.92 * alpha) /
842 (1.0 + 2.4 * fNumber + 1.8 * alpha);
846 nwt += (15.0 + 6.25 * alpha) / (1.0 + 0.9 * alpha + 2.5 * fNumber);
851 nwt += ((1.0 + 2.55 * cofi) / (1.9 * cofi) +
852 1.26 * cofi * alpha / (1.0 + 3.5 * cofi)) *
853 (nwt - fAbscissa[i - 3]) / (1.0 + 0.3 * alpha);
855 for(k = 1; k <= maxNumber; ++k)
860 for(j = 1; j <= fNumber; ++j)
865 ((2 * j - 1 + alpha - nwt) * temp2 - (j - 1 + alpha) * temp3) / j;
867 temp = (fNumber * temp1 - (fNumber + alpha) * temp2) / nwt;
869 nwt = nwt1 - temp1 / temp;
871 if(std::fabs(nwt - nwt1) <= tolerance)
878 G4Exception("G4Integrator<T,F>::Laguerre(T,F, ...)", "Error",
879 FatalException, "Too many (>12) iterations.");
882 fAbscissa[i - 1] = nwt;
883 fWeight[i - 1] = -std::exp(GammaLogarithm(alpha + fNumber) -
884 GammaLogarithm((G4double) fNumber)) /
885 (temp * fNumber * temp2);
889 // Integral evaluation
892 for(i = 0; i < fNumber; ++i)
894 integral += fWeight[i] * (typeT.*f)(fAbscissa[i]);
901//////////////////////////////////////////////////////////////////////
905template <class T, class F>
906G4double G4Integrator<T, F>::Laguerre(T* ptrT, F f, G4double alpha,
909 return Laguerre(*ptrT, f, alpha, nLaguerre);
912////////////////////////////////////////////////////////////////////////
914// For use with global scope functions f
916template <class T, class F>
917G4double G4Integrator<T, F>::Laguerre(G4double (*f)(G4double), G4double alpha,
920 const G4double tolerance = 1.0e-10;
921 const G4int maxNumber = 12;
923 G4double nwt = 0., nwt1, temp1, temp2, temp3, temp, cofi;
924 G4double integral = 0.0;
926 G4int fNumber = nLaguerre;
927 G4double* fAbscissa = new G4double[fNumber];
928 G4double* fWeight = new G4double[fNumber];
930 for(i = 1; i <= fNumber; ++i) // Loop over the desired roots
934 nwt = (1.0 + alpha) * (3.0 + 0.92 * alpha) /
935 (1.0 + 2.4 * fNumber + 1.8 * alpha);
939 nwt += (15.0 + 6.25 * alpha) / (1.0 + 0.9 * alpha + 2.5 * fNumber);
944 nwt += ((1.0 + 2.55 * cofi) / (1.9 * cofi) +
945 1.26 * cofi * alpha / (1.0 + 3.5 * cofi)) *
946 (nwt - fAbscissa[i - 3]) / (1.0 + 0.3 * alpha);
948 for(k = 1; k <= maxNumber; ++k)
953 for(j = 1; j <= fNumber; ++j)
958 ((2 * j - 1 + alpha - nwt) * temp2 - (j - 1 + alpha) * temp3) / j;
960 temp = (fNumber * temp1 - (fNumber + alpha) * temp2) / nwt;
962 nwt = nwt1 - temp1 / temp;
964 if(std::fabs(nwt - nwt1) <= tolerance)
971 G4Exception("G4Integrator<T,F>::Laguerre( ...)", "Error", FatalException,
972 "Too many (>12) iterations.");
975 fAbscissa[i - 1] = nwt;
976 fWeight[i - 1] = -std::exp(GammaLogarithm(alpha + fNumber) -
977 GammaLogarithm((G4double) fNumber)) /
978 (temp * fNumber * temp2);
982 // Integral evaluation
985 for(i = 0; i < fNumber; i++)
987 integral += fWeight[i] * (*f)(fAbscissa[i]);
994///////////////////////////////////////////////////////////////////////
996// Auxiliary function which returns the value of std::log(gamma-function(x))
997// Returns the value ln(Gamma(xx) for xx > 0. Full accuracy is obtained for
998// xx > 1. For 0 < xx < 1. the reflection formula (6.1.4) can be used first.
999// (Adapted from Numerical Recipes in C)
1002template <class T, class F>
1003G4double G4Integrator<T, F>::GammaLogarithm(G4double xx)
1005 static const G4double cof[6] = { 76.18009172947146, -86.50532032941677,
1006 24.01409824083091, -1.231739572450155,
1007 0.1208650973866179e-2, -0.5395239384953e-5 };
1009 G4double x = xx - 1.0;
1010 G4double tmp = x + 5.5;
1011 tmp -= (x + 0.5) * std::log(tmp);
1012 G4double ser = 1.000000000190015;
1014 for(j = 0; j <= 5; ++j)
1019 return -tmp + std::log(2.5066282746310005 * ser);
1022///////////////////////////////////////////////////////////////////////
1024// Method involving Hermite polynomials
1026///////////////////////////////////////////////////////////////////////
1029// Gauss-Hermite method for integration of std::exp(-x*x)*f(x)
1030// from minus infinity to plus infinity .
1033template <class T, class F>
1034G4double G4Integrator<T, F>::Hermite(T& typeT, F f, G4int nHermite)
1036 const G4double tolerance = 1.0e-12;
1037 const G4int maxNumber = 12;
1040 G4double integral = 0.0;
1041 G4double nwt = 0., nwt1, temp1, temp2, temp3, temp;
1043 G4double piInMinusQ =
1044 std::pow(CLHEP::pi, -0.25); // 1.0/std::sqrt(std::sqrt(pi)) ??
1046 G4int fNumber = (nHermite + 1) / 2;
1047 G4double* fAbscissa = new G4double[fNumber];
1048 G4double* fWeight = new G4double[fNumber];
1050 for(i = 1; i <= fNumber; ++i)
1054 nwt = std::sqrt((G4double)(2 * nHermite + 1)) -
1055 1.85575001 * std::pow((G4double)(2 * nHermite + 1), -0.16666999);
1059 nwt -= 1.14001 * std::pow((G4double) nHermite, 0.425999) / nwt;
1063 nwt = 1.86002 * nwt - 0.86002 * fAbscissa[0];
1067 nwt = 1.91001 * nwt - 0.91001 * fAbscissa[1];
1071 nwt = 2.0 * nwt - fAbscissa[i - 3];
1073 for(k = 1; k <= maxNumber; ++k)
1078 for(j = 1; j <= nHermite; ++j)
1082 temp1 = nwt * std::sqrt(2.0 / j) * temp2 -
1083 std::sqrt(((G4double)(j - 1)) / j) * temp3;
1085 temp = std::sqrt((G4double) 2 * nHermite) * temp2;
1087 nwt = nwt1 - temp1 / temp;
1089 if(std::fabs(nwt - nwt1) <= tolerance)
1096 G4Exception("G4Integrator<T,F>::Hermite(T,F, ...)", "Error",
1097 FatalException, "Too many (>12) iterations.");
1099 fAbscissa[i - 1] = nwt;
1100 fWeight[i - 1] = 2.0 / (temp * temp);
1104 // Integral calculation
1107 for(i = 0; i < fNumber; ++i)
1110 fWeight[i] * ((typeT.*f)(fAbscissa[i]) + (typeT.*f)(-fAbscissa[i]));
1117////////////////////////////////////////////////////////////////////////
1119// For use with 'this' pointer
1121template <class T, class F>
1122G4double G4Integrator<T, F>::Hermite(T* ptrT, F f, G4int n)
1124 return Hermite(*ptrT, f, n);
1127////////////////////////////////////////////////////////////////////////
1129// For use with global scope f
1131template <class T, class F>
1132G4double G4Integrator<T, F>::Hermite(G4double (*f)(G4double), G4int nHermite)
1134 const G4double tolerance = 1.0e-12;
1135 const G4int maxNumber = 12;
1138 G4double integral = 0.0;
1139 G4double nwt = 0., nwt1, temp1, temp2, temp3, temp;
1141 G4double piInMinusQ =
1142 std::pow(CLHEP::pi, -0.25); // 1.0/std::sqrt(std::sqrt(pi)) ??
1144 G4int fNumber = (nHermite + 1) / 2;
1145 G4double* fAbscissa = new G4double[fNumber];
1146 G4double* fWeight = new G4double[fNumber];
1148 for(i = 1; i <= fNumber; ++i)
1152 nwt = std::sqrt((G4double)(2 * nHermite + 1)) -
1153 1.85575001 * std::pow((G4double)(2 * nHermite + 1), -0.16666999);
1157 nwt -= 1.14001 * std::pow((G4double) nHermite, 0.425999) / nwt;
1161 nwt = 1.86002 * nwt - 0.86002 * fAbscissa[0];
1165 nwt = 1.91001 * nwt - 0.91001 * fAbscissa[1];
1169 nwt = 2.0 * nwt - fAbscissa[i - 3];
1171 for(k = 1; k <= maxNumber; ++k)
1176 for(j = 1; j <= nHermite; ++j)
1180 temp1 = nwt * std::sqrt(2.0 / j) * temp2 -
1181 std::sqrt(((G4double)(j - 1)) / j) * temp3;
1183 temp = std::sqrt((G4double) 2 * nHermite) * temp2;
1185 nwt = nwt1 - temp1 / temp;
1187 if(std::fabs(nwt - nwt1) <= tolerance)
1194 G4Exception("G4Integrator<T,F>::Hermite(...)", "Error", FatalException,
1195 "Too many (>12) iterations.");
1197 fAbscissa[i - 1] = nwt;
1198 fWeight[i - 1] = 2.0 / (temp * temp);
1202 // Integral calculation
1205 for(i = 0; i < fNumber; ++i)
1207 integral += fWeight[i] * ((*f)(fAbscissa[i]) + (*f)(-fAbscissa[i]));
1214////////////////////////////////////////////////////////////////////////////
1216// Method involving Jacobi polynomials
1218////////////////////////////////////////////////////////////////////////////
1220// Gauss-Jacobi method for integration of ((1-x)^alpha)*((1+x)^beta)*f(x)
1221// from minus unit to plus unit .
1224template <class T, class F>
1225G4double G4Integrator<T, F>::Jacobi(T& typeT, F f, G4double alpha,
1226 G4double beta, G4int nJacobi)
1228 const G4double tolerance = 1.0e-12;
1229 const G4double maxNumber = 12;
1231 G4double alphaBeta, alphaReduced, betaReduced, root1 = 0., root2 = 0.,
1233 G4double a, b, c, nwt1, nwt2, nwt3, nwt, temp, root = 0., rootTemp;
1235 G4int fNumber = nJacobi;
1236 G4double* fAbscissa = new G4double[fNumber];
1237 G4double* fWeight = new G4double[fNumber];
1239 for(i = 1; i <= nJacobi; ++i)
1243 alphaReduced = alpha / nJacobi;
1244 betaReduced = beta / nJacobi;
1245 root1 = (1.0 + alpha) * (2.78002 / (4.0 + nJacobi * nJacobi) +
1246 0.767999 * alphaReduced / nJacobi);
1247 root2 = 1.0 + 1.48 * alphaReduced + 0.96002 * betaReduced +
1248 0.451998 * alphaReduced * alphaReduced +
1249 0.83001 * alphaReduced * betaReduced;
1250 root = 1.0 - root1 / root2;
1254 root1 = (4.1002 + alpha) / ((1.0 + alpha) * (1.0 + 0.155998 * alpha));
1255 root2 = 1.0 + 0.06 * (nJacobi - 8.0) * (1.0 + 0.12 * alpha) / nJacobi;
1257 1.0 + 0.012002 * beta * (1.0 + 0.24997 * std::fabs(alpha)) / nJacobi;
1258 root -= (1.0 - root) * root1 * root2 * root3;
1262 root1 = (1.67001 + 0.27998 * alpha) / (1.0 + 0.37002 * alpha);
1263 root2 = 1.0 + 0.22 * (nJacobi - 8.0) / nJacobi;
1264 root3 = 1.0 + 8.0 * beta / ((6.28001 + beta) * nJacobi * nJacobi);
1265 root -= (fAbscissa[0] - root) * root1 * root2 * root3;
1267 else if(i == nJacobi - 1)
1269 root1 = (1.0 + 0.235002 * beta) / (0.766001 + 0.118998 * beta);
1270 root2 = 1.0 / (1.0 + 0.639002 * (nJacobi - 4.0) /
1271 (1.0 + 0.71001 * (nJacobi - 4.0)));
1272 root3 = 1.0 / (1.0 + 20.0 * alpha / ((7.5 + alpha) * nJacobi * nJacobi));
1273 root += (root - fAbscissa[nJacobi - 4]) * root1 * root2 * root3;
1275 else if(i == nJacobi)
1277 root1 = (1.0 + 0.37002 * beta) / (1.67001 + 0.27998 * beta);
1278 root2 = 1.0 / (1.0 + 0.22 * (nJacobi - 8.0) / nJacobi);
1280 1.0 / (1.0 + 8.0 * alpha / ((6.28002 + alpha) * nJacobi * nJacobi));
1281 root += (root - fAbscissa[nJacobi - 3]) * root1 * root2 * root3;
1285 root = 3.0 * fAbscissa[i - 2] - 3.0 * fAbscissa[i - 3] + fAbscissa[i - 4];
1287 alphaBeta = alpha + beta;
1288 for(k = 1; k <= maxNumber; ++k)
1290 temp = 2.0 + alphaBeta;
1291 nwt1 = (alpha - beta + temp * root) / 2.0;
1293 for(j = 2; j <= nJacobi; ++j)
1297 temp = 2 * j + alphaBeta;
1298 a = 2 * j * (j + alphaBeta) * (temp - 2.0);
1300 (alpha * alpha - beta * beta + temp * (temp - 2.0) * root);
1301 c = 2.0 * (j - 1 + alpha) * (j - 1 + beta) * temp;
1302 nwt1 = (b * nwt2 - c * nwt3) / a;
1304 nwt = (nJacobi * (alpha - beta - temp * root) * nwt1 +
1305 2.0 * (nJacobi + alpha) * (nJacobi + beta) * nwt2) /
1306 (temp * (1.0 - root * root));
1308 root = rootTemp - nwt1 / nwt;
1309 if(std::fabs(root - rootTemp) <= tolerance)
1316 G4Exception("G4Integrator<T,F>::Jacobi(T,F, ...)", "Error",
1317 FatalException, "Too many (>12) iterations.");
1319 fAbscissa[i - 1] = root;
1321 std::exp(GammaLogarithm((G4double)(alpha + nJacobi)) +
1322 GammaLogarithm((G4double)(beta + nJacobi)) -
1323 GammaLogarithm((G4double)(nJacobi + 1.0)) -
1324 GammaLogarithm((G4double)(nJacobi + alphaBeta + 1.0))) *
1325 temp * std::pow(2.0, alphaBeta) / (nwt * nwt2);
1329 // Calculation of the integral
1332 G4double integral = 0.0;
1333 for(i = 0; i < fNumber; ++i)
1335 integral += fWeight[i] * (typeT.*f)(fAbscissa[i]);
1342/////////////////////////////////////////////////////////////////////////
1344// For use with 'this' pointer
1346template <class T, class F>
1347G4double G4Integrator<T, F>::Jacobi(T* ptrT, F f, G4double alpha, G4double beta,
1350 return Jacobi(*ptrT, f, alpha, beta, n);
1353/////////////////////////////////////////////////////////////////////////
1355// For use with global scope f
1357template <class T, class F>
1358G4double G4Integrator<T, F>::Jacobi(G4double (*f)(G4double), G4double alpha,
1359 G4double beta, G4int nJacobi)
1361 const G4double tolerance = 1.0e-12;
1362 const G4double maxNumber = 12;
1364 G4double alphaBeta, alphaReduced, betaReduced, root1 = 0., root2 = 0.,
1366 G4double a, b, c, nwt1, nwt2, nwt3, nwt, temp, root = 0., rootTemp;
1368 G4int fNumber = nJacobi;
1369 G4double* fAbscissa = new G4double[fNumber];
1370 G4double* fWeight = new G4double[fNumber];
1372 for(i = 1; i <= nJacobi; ++i)
1376 alphaReduced = alpha / nJacobi;
1377 betaReduced = beta / nJacobi;
1378 root1 = (1.0 + alpha) * (2.78002 / (4.0 + nJacobi * nJacobi) +
1379 0.767999 * alphaReduced / nJacobi);
1380 root2 = 1.0 + 1.48 * alphaReduced + 0.96002 * betaReduced +
1381 0.451998 * alphaReduced * alphaReduced +
1382 0.83001 * alphaReduced * betaReduced;
1383 root = 1.0 - root1 / root2;
1387 root1 = (4.1002 + alpha) / ((1.0 + alpha) * (1.0 + 0.155998 * alpha));
1388 root2 = 1.0 + 0.06 * (nJacobi - 8.0) * (1.0 + 0.12 * alpha) / nJacobi;
1390 1.0 + 0.012002 * beta * (1.0 + 0.24997 * std::fabs(alpha)) / nJacobi;
1391 root -= (1.0 - root) * root1 * root2 * root3;
1395 root1 = (1.67001 + 0.27998 * alpha) / (1.0 + 0.37002 * alpha);
1396 root2 = 1.0 + 0.22 * (nJacobi - 8.0) / nJacobi;
1397 root3 = 1.0 + 8.0 * beta / ((6.28001 + beta) * nJacobi * nJacobi);
1398 root -= (fAbscissa[0] - root) * root1 * root2 * root3;
1400 else if(i == nJacobi - 1)
1402 root1 = (1.0 + 0.235002 * beta) / (0.766001 + 0.118998 * beta);
1403 root2 = 1.0 / (1.0 + 0.639002 * (nJacobi - 4.0) /
1404 (1.0 + 0.71001 * (nJacobi - 4.0)));
1405 root3 = 1.0 / (1.0 + 20.0 * alpha / ((7.5 + alpha) * nJacobi * nJacobi));
1406 root += (root - fAbscissa[nJacobi - 4]) * root1 * root2 * root3;
1408 else if(i == nJacobi)
1410 root1 = (1.0 + 0.37002 * beta) / (1.67001 + 0.27998 * beta);
1411 root2 = 1.0 / (1.0 + 0.22 * (nJacobi - 8.0) / nJacobi);
1413 1.0 / (1.0 + 8.0 * alpha / ((6.28002 + alpha) * nJacobi * nJacobi));
1414 root += (root - fAbscissa[nJacobi - 3]) * root1 * root2 * root3;
1418 root = 3.0 * fAbscissa[i - 2] - 3.0 * fAbscissa[i - 3] + fAbscissa[i - 4];
1420 alphaBeta = alpha + beta;
1421 for(k = 1; k <= maxNumber; ++k)
1423 temp = 2.0 + alphaBeta;
1424 nwt1 = (alpha - beta + temp * root) / 2.0;
1426 for(j = 2; j <= nJacobi; ++j)
1430 temp = 2 * j + alphaBeta;
1431 a = 2 * j * (j + alphaBeta) * (temp - 2.0);
1433 (alpha * alpha - beta * beta + temp * (temp - 2.0) * root);
1434 c = 2.0 * (j - 1 + alpha) * (j - 1 + beta) * temp;
1435 nwt1 = (b * nwt2 - c * nwt3) / a;
1437 nwt = (nJacobi * (alpha - beta - temp * root) * nwt1 +
1438 2.0 * (nJacobi + alpha) * (nJacobi + beta) * nwt2) /
1439 (temp * (1.0 - root * root));
1441 root = rootTemp - nwt1 / nwt;
1442 if(std::fabs(root - rootTemp) <= tolerance)
1449 G4Exception("G4Integrator<T,F>::Jacobi(...)", "Error", FatalException,
1450 "Too many (>12) iterations.");
1452 fAbscissa[i - 1] = root;
1454 std::exp(GammaLogarithm((G4double)(alpha + nJacobi)) +
1455 GammaLogarithm((G4double)(beta + nJacobi)) -
1456 GammaLogarithm((G4double)(nJacobi + 1.0)) -
1457 GammaLogarithm((G4double)(nJacobi + alphaBeta + 1.0))) *
1458 temp * std::pow(2.0, alphaBeta) / (nwt * nwt2);
1462 // Calculation of the integral
1465 G4double integral = 0.0;
1466 for(i = 0; i < fNumber; ++i)
1468 integral += fWeight[i] * (*f)(fAbscissa[i]);
1477///////////////////////////////////////////////////////////////////