source: trunk/source/global/HEPNumerics/include/G4Integrator.icc@ 1059

Last change on this file since 1059 was 1058, checked in by garnier, 17 years ago

file release beta

File size: 48.8 KB
Line 
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
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. *
10// * *
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. *
17// * *
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// ********************************************************************
25//
26//
27// $Id: G4Integrator.icc,v 1.13 2006/06/29 18:59:47 gunter Exp $
28// GEANT4 tag $Name: geant4-09-02-ref-02 $
29//
30// Implementation of G4Integrator methods.
31//
32//
33
34/////////////////////////////////////////////////////////////////////
35//
36// Sympson integration method
37//
38/////////////////////////////////////////////////////////////////////
39//
40// Integration of class member functions T::f by Simpson method.
41
42template <class T, class F>
43G4double G4Integrator<T,F>::Simpson( T& typeT,
44 F f,
45 G4double xInitial,
46 G4double xFinal,
47 G4int iterationNumber )
48{
49 G4int i ;
50 G4double step = (xFinal - xInitial)/iterationNumber ;
51 G4double x = xInitial ;
52 G4double xPlus = xInitial + 0.5*step ;
53 G4double mean = ( (typeT.*f)(xInitial) + (typeT.*f)(xFinal) )*0.5 ;
54 G4double sum = (typeT.*f)(xPlus) ;
55
56 for(i=1;i<iterationNumber;i++)
57 {
58 x += step ;
59 xPlus += step ;
60 mean += (typeT.*f)(x) ;
61 sum += (typeT.*f)(xPlus) ;
62 }
63 mean += 2.0*sum ;
64
65 return mean*step/3.0 ;
66}
67
68/////////////////////////////////////////////////////////////////////
69//
70// Integration of class member functions T::f by Simpson method.
71// Convenient to use with 'this' pointer
72
73template <class T, class F>
74G4double G4Integrator<T,F>::Simpson( T* ptrT,
75 F f,
76 G4double xInitial,
77 G4double xFinal,
78 G4int iterationNumber )
79{
80 G4int i ;
81 G4double step = (xFinal - xInitial)/iterationNumber ;
82 G4double x = xInitial ;
83 G4double xPlus = xInitial + 0.5*step ;
84 G4double mean = ( (ptrT->*f)(xInitial) + (ptrT->*f)(xFinal) )*0.5 ;
85 G4double sum = (ptrT->*f)(xPlus) ;
86
87 for(i=1;i<iterationNumber;i++)
88 {
89 x += step ;
90 xPlus += step ;
91 mean += (ptrT->*f)(x) ;
92 sum += (ptrT->*f)(xPlus) ;
93 }
94 mean += 2.0*sum ;
95
96 return mean*step/3.0 ;
97}
98
99/////////////////////////////////////////////////////////////////////
100//
101// Integration of class member functions T::f by Simpson method.
102// Convenient to use, when function f is defined in global scope, i.e. in main()
103// program
104
105template <class T, class F>
106G4double G4Integrator<T,F>::Simpson( G4double (*f)(G4double),
107 G4double xInitial,
108 G4double xFinal,
109 G4int iterationNumber )
110{
111 G4int i ;
112 G4double step = (xFinal - xInitial)/iterationNumber ;
113 G4double x = xInitial ;
114 G4double xPlus = xInitial + 0.5*step ;
115 G4double mean = ( (*f)(xInitial) + (*f)(xFinal) )*0.5 ;
116 G4double sum = (*f)(xPlus) ;
117
118 for(i=1;i<iterationNumber;i++)
119 {
120 x += step ;
121 xPlus += step ;
122 mean += (*f)(x) ;
123 sum += (*f)(xPlus) ;
124 }
125 mean += 2.0*sum ;
126
127 return mean*step/3.0 ;
128}
129
130//////////////////////////////////////////////////////////////////////////
131//
132// Adaptive Gauss method
133//
134//////////////////////////////////////////////////////////////////////////
135//
136//
137
138template <class T, class F>
139G4double G4Integrator<T,F>::Gauss( T& typeT, F f,
140 G4double xInitial, G4double xFinal )
141{
142 static G4double root = 1.0/std::sqrt(3.0) ;
143
144 G4double xMean = (xInitial + xFinal)/2.0 ;
145 G4double Step = (xFinal - xInitial)/2.0 ;
146 G4double delta = Step*root ;
147 G4double sum = ((typeT.*f)(xMean + delta) +
148 (typeT.*f)(xMean - delta)) ;
149
150 return sum*Step ;
151}
152
153//////////////////////////////////////////////////////////////////////
154//
155//
156
157template <class T, class F> G4double
158G4Integrator<T,F>::Gauss( T* ptrT, F f, G4double a, G4double b )
159{
160 return Gauss(*ptrT,f,a,b) ;
161}
162
163///////////////////////////////////////////////////////////////////////
164//
165//
166
167template <class T, class F>
168G4double G4Integrator<T,F>::Gauss( G4double (*f)(G4double),
169 G4double xInitial, G4double xFinal)
170{
171 static G4double root = 1.0/std::sqrt(3.0) ;
172
173 G4double xMean = (xInitial + xFinal)/2.0 ;
174 G4double Step = (xFinal - xInitial)/2.0 ;
175 G4double delta = Step*root ;
176 G4double sum = ( (*f)(xMean + delta) + (*f)(xMean - delta) ) ;
177
178 return sum*Step ;
179}
180
181///////////////////////////////////////////////////////////////////////////
182//
183//
184
185template <class T, class F>
186void G4Integrator<T,F>::AdaptGauss( T& typeT, F f, G4double xInitial,
187 G4double xFinal, G4double fTolerance,
188 G4double& sum,
189 G4int& depth )
190{
191 if(depth > 100)
192 {
193 G4cout<<"G4Integrator<T,F>::AdaptGauss: WARNING !!!"<<G4endl ;
194 G4cout<<"Function varies too rapidly to get stated accuracy in 100 steps "
195 <<G4endl ;
196
197 return ;
198 }
199 G4double xMean = (xInitial + xFinal)/2.0 ;
200 G4double leftHalf = Gauss(typeT,f,xInitial,xMean) ;
201 G4double rightHalf = Gauss(typeT,f,xMean,xFinal) ;
202 G4double full = Gauss(typeT,f,xInitial,xFinal) ;
203 if(std::fabs(leftHalf+rightHalf-full) < fTolerance)
204 {
205 sum += full ;
206 }
207 else
208 {
209 depth++ ;
210 AdaptGauss(typeT,f,xInitial,xMean,fTolerance,sum,depth) ;
211 AdaptGauss(typeT,f,xMean,xFinal,fTolerance,sum,depth) ;
212 }
213}
214
215template <class T, class F>
216void G4Integrator<T,F>::AdaptGauss( T* ptrT, F f, G4double xInitial,
217 G4double xFinal, G4double fTolerance,
218 G4double& sum,
219 G4int& depth )
220{
221 AdaptGauss(*ptrT,f,xInitial,xFinal,fTolerance,sum,depth) ;
222}
223
224/////////////////////////////////////////////////////////////////////////
225//
226//
227template <class T, class F>
228void G4Integrator<T,F>::AdaptGauss( G4double (*f)(G4double),
229 G4double xInitial, G4double xFinal,
230 G4double fTolerance, G4double& sum,
231 G4int& depth )
232{
233 if(depth > 100)
234 {
235 G4cout<<"G4SimpleIntegration::AdaptGauss: WARNING !!!"<<G4endl ;
236 G4cout<<"Function varies too rapidly to get stated accuracy in 100 steps "
237 <<G4endl ;
238
239 return ;
240 }
241 G4double xMean = (xInitial + xFinal)/2.0 ;
242 G4double leftHalf = Gauss(f,xInitial,xMean) ;
243 G4double rightHalf = Gauss(f,xMean,xFinal) ;
244 G4double full = Gauss(f,xInitial,xFinal) ;
245 if(std::fabs(leftHalf+rightHalf-full) < fTolerance)
246 {
247 sum += full ;
248 }
249 else
250 {
251 depth++ ;
252 AdaptGauss(f,xInitial,xMean,fTolerance,sum,depth) ;
253 AdaptGauss(f,xMean,xFinal,fTolerance,sum,depth) ;
254 }
255}
256
257////////////////////////////////////////////////////////////////////////
258//
259// Adaptive Gauss integration with accuracy 'e'
260// Convenient for using with class object typeT
261
262template<class T, class F>
263G4double G4Integrator<T,F>::AdaptiveGauss( T& typeT, F f, G4double xInitial,
264 G4double xFinal, G4double e )
265{
266 G4int depth = 0 ;
267 G4double sum = 0.0 ;
268 AdaptGauss(typeT,f,xInitial,xFinal,e,sum,depth) ;
269 return sum ;
270}
271
272////////////////////////////////////////////////////////////////////////
273//
274// Adaptive Gauss integration with accuracy 'e'
275// Convenient for using with 'this' pointer
276
277template<class T, class F>
278G4double G4Integrator<T,F>::AdaptiveGauss( T* ptrT, F f, G4double xInitial,
279 G4double xFinal, G4double e )
280{
281 return AdaptiveGauss(*ptrT,f,xInitial,xFinal,e) ;
282}
283
284////////////////////////////////////////////////////////////////////////
285//
286// Adaptive Gauss integration with accuracy 'e'
287// Convenient for using with global scope function f
288
289template <class T, class F>
290G4double G4Integrator<T,F>::AdaptiveGauss( G4double (*f)(G4double),
291 G4double xInitial, G4double xFinal, G4double e )
292{
293 G4int depth = 0 ;
294 G4double sum = 0.0 ;
295 AdaptGauss(f,xInitial,xFinal,e,sum,depth) ;
296 return sum ;
297}
298
299////////////////////////////////////////////////////////////////////////////
300// Gauss integration methods involving ortogonal polynomials
301////////////////////////////////////////////////////////////////////////////
302//
303// Methods involving Legendre polynomials
304//
305/////////////////////////////////////////////////////////////////////////
306//
307// The value nLegendre set the accuracy required, i.e the number of points
308// where the function pFunction will be evaluated during integration.
309// The function creates the arrays for abscissas and weights that used
310// in Gauss-Legendre quadrature method.
311// The values a and b are the limits of integration of the function f .
312// nLegendre MUST BE EVEN !!!
313// Returns the integral of the function f between a and b, by 2*fNumber point
314// Gauss-Legendre integration: the function is evaluated exactly
315// 2*fNumber times at interior points in the range of integration.
316// Since the weights and abscissas are, in this case, symmetric around
317// the midpoint of the range of integration, there are actually only
318// fNumber distinct values of each.
319// Convenient for using with some class object dataT
320
321template <class T, class F>
322G4double G4Integrator<T,F>::Legendre( T& typeT, F f, G4double a, G4double b,
323 G4int nLegendre )
324{
325 G4double newton, newton1, temp1, temp2, temp3, temp ;
326 G4double xDiff, xMean, dx, integral ;
327
328 const G4double tolerance = 1.6e-10 ;
329 G4int i, j, k = nLegendre ;
330 G4int fNumber = (nLegendre + 1)/2 ;
331
332 if(2*fNumber != k)
333 {
334 G4Exception("G4Integrator<T,F>::Legendre(T&,F, ...)", "InvalidCall",
335 FatalException, "Invalid (odd) nLegendre in constructor.");
336 }
337
338 G4double* fAbscissa = new G4double[fNumber] ;
339 G4double* fWeight = new G4double[fNumber] ;
340
341 for(i=1;i<=fNumber;i++) // Loop over the desired roots
342 {
343 newton = std::cos(pi*(i - 0.25)/(k + 0.5)) ; // Initial root approximation
344
345 do // loop of Newton's method
346 {
347 temp1 = 1.0 ;
348 temp2 = 0.0 ;
349 for(j=1;j<=k;j++)
350 {
351 temp3 = temp2 ;
352 temp2 = temp1 ;
353 temp1 = ((2.0*j - 1.0)*newton*temp2 - (j - 1.0)*temp3)/j ;
354 }
355 temp = k*(newton*temp1 - temp2)/(newton*newton - 1.0) ;
356 newton1 = newton ;
357 newton = newton1 - temp1/temp ; // Newton's method
358 }
359 while(std::fabs(newton - newton1) > tolerance) ;
360
361 fAbscissa[fNumber-i] = newton ;
362 fWeight[fNumber-i] = 2.0/((1.0 - newton*newton)*temp*temp) ;
363 }
364
365 //
366 // Now we ready to get integral
367 //
368
369 xMean = 0.5*(a + b) ;
370 xDiff = 0.5*(b - a) ;
371 integral = 0.0 ;
372 for(i=0;i<fNumber;i++)
373 {
374 dx = xDiff*fAbscissa[i] ;
375 integral += fWeight[i]*( (typeT.*f)(xMean + dx) +
376 (typeT.*f)(xMean - dx) ) ;
377 }
378 delete[] fAbscissa;
379 delete[] fWeight;
380 return integral *= xDiff ;
381}
382
383///////////////////////////////////////////////////////////////////////
384//
385// Convenient for using with the pointer 'this'
386
387template <class T, class F>
388G4double G4Integrator<T,F>::Legendre( T* ptrT, F f, G4double a,
389 G4double b, G4int nLegendre )
390{
391 return Legendre(*ptrT,f,a,b,nLegendre) ;
392}
393
394///////////////////////////////////////////////////////////////////////
395//
396// Convenient for using with global scope function f
397
398template <class T, class F>
399G4double G4Integrator<T,F>::Legendre( G4double (*f)(G4double),
400 G4double a, G4double b, G4int nLegendre)
401{
402 G4double newton, newton1, temp1, temp2, temp3, temp ;
403 G4double xDiff, xMean, dx, integral ;
404
405 const G4double tolerance = 1.6e-10 ;
406 G4int i, j, k = nLegendre ;
407 G4int fNumber = (nLegendre + 1)/2 ;
408
409 if(2*fNumber != k)
410 {
411 G4Exception("G4Integrator<T,F>::Legendre(...)", "InvalidCall",
412 FatalException, "Invalid (odd) nLegendre in constructor.");
413 }
414
415 G4double* fAbscissa = new G4double[fNumber] ;
416 G4double* fWeight = new G4double[fNumber] ;
417
418 for(i=1;i<=fNumber;i++) // Loop over the desired roots
419 {
420 newton = std::cos(pi*(i - 0.25)/(k + 0.5)) ; // Initial root approximation
421
422 do // loop of Newton's method
423 {
424 temp1 = 1.0 ;
425 temp2 = 0.0 ;
426 for(j=1;j<=k;j++)
427 {
428 temp3 = temp2 ;
429 temp2 = temp1 ;
430 temp1 = ((2.0*j - 1.0)*newton*temp2 - (j - 1.0)*temp3)/j ;
431 }
432 temp = k*(newton*temp1 - temp2)/(newton*newton - 1.0) ;
433 newton1 = newton ;
434 newton = newton1 - temp1/temp ; // Newton's method
435 }
436 while(std::fabs(newton - newton1) > tolerance) ;
437
438 fAbscissa[fNumber-i] = newton ;
439 fWeight[fNumber-i] = 2.0/((1.0 - newton*newton)*temp*temp) ;
440 }
441
442 //
443 // Now we ready to get integral
444 //
445
446 xMean = 0.5*(a + b) ;
447 xDiff = 0.5*(b - a) ;
448 integral = 0.0 ;
449 for(i=0;i<fNumber;i++)
450 {
451 dx = xDiff*fAbscissa[i] ;
452 integral += fWeight[i]*( (*f)(xMean + dx) + (*f)(xMean - dx) ) ;
453 }
454 delete[] fAbscissa;
455 delete[] fWeight;
456
457 return integral *= xDiff ;
458}
459
460////////////////////////////////////////////////////////////////////////////
461//
462// Returns the integral of the function to be pointed by T::f between a and b,
463// by ten point Gauss-Legendre integration: the function is evaluated exactly
464// ten times at interior points in the range of integration. Since the weights
465// and abscissas are, in this case, symmetric around the midpoint of the
466// range of integration, there are actually only five distinct values of each
467// Convenient for using with class object typeT
468
469template <class T, class F>
470G4double G4Integrator<T,F>::Legendre10( T& typeT, F f,G4double a, G4double b)
471{
472 G4int i ;
473 G4double xDiff, xMean, dx, integral ;
474
475 // From Abramowitz M., Stegan I.A. 1964 , Handbook of Math... , p. 916
476
477 static G4double abscissa[] = { 0.148874338981631, 0.433395394129247,
478 0.679409568299024, 0.865063366688985,
479 0.973906528517172 } ;
480
481 static G4double weight[] = { 0.295524224714753, 0.269266719309996,
482 0.219086362515982, 0.149451349150581,
483 0.066671344308688 } ;
484 xMean = 0.5*(a + b) ;
485 xDiff = 0.5*(b - a) ;
486 integral = 0.0 ;
487 for(i=0;i<5;i++)
488 {
489 dx = xDiff*abscissa[i] ;
490 integral += weight[i]*( (typeT.*f)(xMean + dx) + (typeT.*f)(xMean - dx)) ;
491 }
492 return integral *= xDiff ;
493}
494
495///////////////////////////////////////////////////////////////////////////
496//
497// Convenient for using with the pointer 'this'
498
499template <class T, class F>
500G4double G4Integrator<T,F>::Legendre10( T* ptrT, F f,G4double a, G4double b)
501{
502 return Legendre10(*ptrT,f,a,b) ;
503}
504
505//////////////////////////////////////////////////////////////////////////
506//
507// Convenient for using with global scope functions
508
509template <class T, class F>
510G4double G4Integrator<T,F>::Legendre10( G4double (*f)(G4double),
511 G4double a, G4double b )
512{
513 G4int i ;
514 G4double xDiff, xMean, dx, integral ;
515
516 // From Abramowitz M., Stegan I.A. 1964 , Handbook of Math... , p. 916
517
518 static G4double abscissa[] = { 0.148874338981631, 0.433395394129247,
519 0.679409568299024, 0.865063366688985,
520 0.973906528517172 } ;
521
522 static G4double weight[] = { 0.295524224714753, 0.269266719309996,
523 0.219086362515982, 0.149451349150581,
524 0.066671344308688 } ;
525 xMean = 0.5*(a + b) ;
526 xDiff = 0.5*(b - a) ;
527 integral = 0.0 ;
528 for(i=0;i<5;i++)
529 {
530 dx = xDiff*abscissa[i] ;
531 integral += weight[i]*( (*f)(xMean + dx) + (*f)(xMean - dx)) ;
532 }
533 return integral *= xDiff ;
534}
535
536///////////////////////////////////////////////////////////////////////
537//
538// Returns the integral of the function to be pointed by T::f between a and b,
539// by 96 point Gauss-Legendre integration: the function is evaluated exactly
540// ten Times at interior points in the range of integration. Since the weights
541// and abscissas are, in this case, symmetric around the midpoint of the
542// range of integration, there are actually only five distinct values of each
543// Convenient for using with some class object typeT
544
545template <class T, class F>
546G4double G4Integrator<T,F>::Legendre96( T& typeT, F f,G4double a, G4double b)
547{
548 G4int i ;
549 G4double xDiff, xMean, dx, integral ;
550
551 // From Abramowitz M., Stegan I.A. 1964 , Handbook of Math... , p. 919
552
553 static G4double
554 abscissa[] = {
555 0.016276744849602969579, 0.048812985136049731112,
556 0.081297495464425558994, 0.113695850110665920911,
557 0.145973714654896941989, 0.178096882367618602759, // 6
558
559 0.210031310460567203603, 0.241743156163840012328,
560 0.273198812591049141487, 0.304364944354496353024,
561 0.335208522892625422616, 0.365696861472313635031, // 12
562
563 0.395797649828908603285, 0.425478988407300545365,
564 0.454709422167743008636, 0.483457973920596359768,
565 0.511694177154667673586, 0.539388108324357436227, // 18
566
567 0.566510418561397168404, 0.593032364777572080684,
568 0.618925840125468570386, 0.644163403784967106798,
569 0.668718310043916153953, 0.692564536642171561344, // 24
570
571 0.715676812348967626225, 0.738030643744400132851,
572 0.759602341176647498703, 0.780369043867433217604,
573 0.800308744139140817229, 0.819400310737931675539, // 30
574
575 0.837623511228187121494, 0.854959033434601455463,
576 0.871388505909296502874, 0.886894517402420416057,
577 0.901460635315852341319, 0.915071423120898074206, // 36
578
579 0.927712456722308690965, 0.939370339752755216932,
580 0.950032717784437635756, 0.959688291448742539300,
581 0.968326828463264212174, 0.975939174585136466453, // 42
582
583 0.982517263563014677447, 0.988054126329623799481,
584 0.992543900323762624572, 0.995981842987209290650,
585 0.998364375863181677724, 0.999689503883230766828 // 48
586 } ;
587
588 static G4double
589 weight[] = {
590 0.032550614492363166242, 0.032516118713868835987,
591 0.032447163714064269364, 0.032343822568575928429,
592 0.032206204794030250669, 0.032034456231992663218, // 6
593
594 0.031828758894411006535, 0.031589330770727168558,
595 0.031316425596862355813, 0.031010332586313837423,
596 0.030671376123669149014, 0.030299915420827593794, // 12
597
598 0.029896344136328385984, 0.029461089958167905970,
599 0.028994614150555236543, 0.028497411065085385646,
600 0.027970007616848334440, 0.027412962726029242823, // 18
601
602 0.026826866725591762198, 0.026212340735672413913,
603 0.025570036005349361499, 0.024900633222483610288,
604 0.024204841792364691282, 0.023483399085926219842, // 24
605
606 0.022737069658329374001, 0.021966644438744349195,
607 0.021172939892191298988, 0.020356797154333324595,
608 0.019519081140145022410, 0.018660679627411467385, // 30
609
610 0.017782502316045260838, 0.016885479864245172450,
611 0.015970562902562291381, 0.015038721026994938006,
612 0.014090941772314860916, 0.013128229566961572637, // 36
613
614 0.012151604671088319635, 0.011162102099838498591,
615 0.010160770535008415758, 0.009148671230783386633,
616 0.008126876925698759217, 0.007096470791153865269, // 42
617
618 0.006058545504235961683, 0.005014202742927517693,
619 0.003964554338444686674, 0.002910731817934946408,
620 0.001853960788946921732, 0.000796792065552012429 // 48
621 } ;
622 xMean = 0.5*(a + b) ;
623 xDiff = 0.5*(b - a) ;
624 integral = 0.0 ;
625 for(i=0;i<48;i++)
626 {
627 dx = xDiff*abscissa[i] ;
628 integral += weight[i]*((typeT.*f)(xMean + dx) + (typeT.*f)(xMean - dx)) ;
629 }
630 return integral *= xDiff ;
631}
632
633///////////////////////////////////////////////////////////////////////
634//
635// Convenient for using with the pointer 'this'
636
637template <class T, class F>
638G4double G4Integrator<T,F>::Legendre96( T* ptrT, F f,G4double a, G4double b)
639{
640 return Legendre96(*ptrT,f,a,b) ;
641}
642
643///////////////////////////////////////////////////////////////////////
644//
645// Convenient for using with global scope function f
646
647template <class T, class F>
648G4double G4Integrator<T,F>::Legendre96( G4double (*f)(G4double),
649 G4double a, G4double b )
650{
651 G4int i ;
652 G4double xDiff, xMean, dx, integral ;
653
654 // From Abramowitz M., Stegan I.A. 1964 , Handbook of Math... , p. 919
655
656 static G4double
657 abscissa[] = {
658 0.016276744849602969579, 0.048812985136049731112,
659 0.081297495464425558994, 0.113695850110665920911,
660 0.145973714654896941989, 0.178096882367618602759, // 6
661
662 0.210031310460567203603, 0.241743156163840012328,
663 0.273198812591049141487, 0.304364944354496353024,
664 0.335208522892625422616, 0.365696861472313635031, // 12
665
666 0.395797649828908603285, 0.425478988407300545365,
667 0.454709422167743008636, 0.483457973920596359768,
668 0.511694177154667673586, 0.539388108324357436227, // 18
669
670 0.566510418561397168404, 0.593032364777572080684,
671 0.618925840125468570386, 0.644163403784967106798,
672 0.668718310043916153953, 0.692564536642171561344, // 24
673
674 0.715676812348967626225, 0.738030643744400132851,
675 0.759602341176647498703, 0.780369043867433217604,
676 0.800308744139140817229, 0.819400310737931675539, // 30
677
678 0.837623511228187121494, 0.854959033434601455463,
679 0.871388505909296502874, 0.886894517402420416057,
680 0.901460635315852341319, 0.915071423120898074206, // 36
681
682 0.927712456722308690965, 0.939370339752755216932,
683 0.950032717784437635756, 0.959688291448742539300,
684 0.968326828463264212174, 0.975939174585136466453, // 42
685
686 0.982517263563014677447, 0.988054126329623799481,
687 0.992543900323762624572, 0.995981842987209290650,
688 0.998364375863181677724, 0.999689503883230766828 // 48
689 } ;
690
691 static G4double
692 weight[] = {
693 0.032550614492363166242, 0.032516118713868835987,
694 0.032447163714064269364, 0.032343822568575928429,
695 0.032206204794030250669, 0.032034456231992663218, // 6
696
697 0.031828758894411006535, 0.031589330770727168558,
698 0.031316425596862355813, 0.031010332586313837423,
699 0.030671376123669149014, 0.030299915420827593794, // 12
700
701 0.029896344136328385984, 0.029461089958167905970,
702 0.028994614150555236543, 0.028497411065085385646,
703 0.027970007616848334440, 0.027412962726029242823, // 18
704
705 0.026826866725591762198, 0.026212340735672413913,
706 0.025570036005349361499, 0.024900633222483610288,
707 0.024204841792364691282, 0.023483399085926219842, // 24
708
709 0.022737069658329374001, 0.021966644438744349195,
710 0.021172939892191298988, 0.020356797154333324595,
711 0.019519081140145022410, 0.018660679627411467385, // 30
712
713 0.017782502316045260838, 0.016885479864245172450,
714 0.015970562902562291381, 0.015038721026994938006,
715 0.014090941772314860916, 0.013128229566961572637, // 36
716
717 0.012151604671088319635, 0.011162102099838498591,
718 0.010160770535008415758, 0.009148671230783386633,
719 0.008126876925698759217, 0.007096470791153865269, // 42
720
721 0.006058545504235961683, 0.005014202742927517693,
722 0.003964554338444686674, 0.002910731817934946408,
723 0.001853960788946921732, 0.000796792065552012429 // 48
724 } ;
725 xMean = 0.5*(a + b) ;
726 xDiff = 0.5*(b - a) ;
727 integral = 0.0 ;
728 for(i=0;i<48;i++)
729 {
730 dx = xDiff*abscissa[i] ;
731 integral += weight[i]*((*f)(xMean + dx) + (*f)(xMean - dx)) ;
732 }
733 return integral *= xDiff ;
734}
735
736//////////////////////////////////////////////////////////////////////////////
737//
738// Methods involving Chebyshev polynomials
739//
740///////////////////////////////////////////////////////////////////////////
741//
742// Integrates function pointed by T::f from a to b by Gauss-Chebyshev
743// quadrature method.
744// Convenient for using with class object typeT
745
746template <class T, class F>
747G4double G4Integrator<T,F>::Chebyshev( T& typeT, F f, G4double a,
748 G4double b, G4int nChebyshev )
749{
750 G4int i ;
751 G4double xDiff, xMean, dx, integral = 0.0 ;
752
753 G4int fNumber = nChebyshev ; // Try to reduce fNumber twice ??
754 G4double cof = pi/fNumber ;
755 G4double* fAbscissa = new G4double[fNumber] ;
756 G4double* fWeight = new G4double[fNumber] ;
757 for(i=0;i<fNumber;i++)
758 {
759 fAbscissa[i] = std::cos(cof*(i + 0.5)) ;
760 fWeight[i] = cof*std::sqrt(1 - fAbscissa[i]*fAbscissa[i]) ;
761 }
762
763 //
764 // Now we ready to estimate the integral
765 //
766
767 xMean = 0.5*(a + b) ;
768 xDiff = 0.5*(b - a) ;
769 for(i=0;i<fNumber;i++)
770 {
771 dx = xDiff*fAbscissa[i] ;
772 integral += fWeight[i]*(typeT.*f)(xMean + dx) ;
773 }
774 delete[] fAbscissa;
775 delete[] fWeight;
776 return integral *= xDiff ;
777}
778
779///////////////////////////////////////////////////////////////////////
780//
781// Convenient for using with 'this' pointer
782
783template <class T, class F>
784G4double G4Integrator<T,F>::Chebyshev( T* ptrT, F f, G4double a,
785 G4double b, G4int n )
786{
787 return Chebyshev(*ptrT,f,a,b,n) ;
788}
789
790////////////////////////////////////////////////////////////////////////
791//
792// For use with global scope functions f
793
794template <class T, class F>
795G4double G4Integrator<T,F>::Chebyshev( G4double (*f)(G4double),
796 G4double a, G4double b, G4int nChebyshev )
797{
798 G4int i ;
799 G4double xDiff, xMean, dx, integral = 0.0 ;
800
801 G4int fNumber = nChebyshev ; // Try to reduce fNumber twice ??
802 G4double cof = pi/fNumber ;
803 G4double* fAbscissa = new G4double[fNumber] ;
804 G4double* fWeight = new G4double[fNumber] ;
805 for(i=0;i<fNumber;i++)
806 {
807 fAbscissa[i] = std::cos(cof*(i + 0.5)) ;
808 fWeight[i] = cof*std::sqrt(1 - fAbscissa[i]*fAbscissa[i]) ;
809 }
810
811 //
812 // Now we ready to estimate the integral
813 //
814
815 xMean = 0.5*(a + b) ;
816 xDiff = 0.5*(b - a) ;
817 for(i=0;i<fNumber;i++)
818 {
819 dx = xDiff*fAbscissa[i] ;
820 integral += fWeight[i]*(*f)(xMean + dx) ;
821 }
822 delete[] fAbscissa;
823 delete[] fWeight;
824 return integral *= xDiff ;
825}
826
827//////////////////////////////////////////////////////////////////////
828//
829// Method involving Laguerre polynomials
830//
831//////////////////////////////////////////////////////////////////////
832//
833// Integral from zero to infinity of std::pow(x,alpha)*std::exp(-x)*f(x).
834// The value of nLaguerre sets the accuracy.
835// The function creates arrays fAbscissa[0,..,nLaguerre-1] and
836// fWeight[0,..,nLaguerre-1] .
837// Convenient for using with class object 'typeT' and (typeT.*f) function
838// (T::f)
839
840template <class T, class F>
841G4double G4Integrator<T,F>::Laguerre( T& typeT, F f, G4double alpha,
842 G4int nLaguerre )
843{
844 const G4double tolerance = 1.0e-10 ;
845 const G4int maxNumber = 12 ;
846 G4int i, j, k ;
847 G4double newton=0., newton1, temp1, temp2, temp3, temp, cofi ;
848 G4double integral = 0.0 ;
849
850 G4int fNumber = nLaguerre ;
851 G4double* fAbscissa = new G4double[fNumber] ;
852 G4double* fWeight = new G4double[fNumber] ;
853
854 for(i=1;i<=fNumber;i++) // Loop over the desired roots
855 {
856 if(i == 1)
857 {
858 newton = (1.0 + alpha)*(3.0 + 0.92*alpha)
859 / (1.0 + 2.4*fNumber + 1.8*alpha) ;
860 }
861 else if(i == 2)
862 {
863 newton += (15.0 + 6.25*alpha)/(1.0 + 0.9*alpha + 2.5*fNumber) ;
864 }
865 else
866 {
867 cofi = i - 2 ;
868 newton += ((1.0+2.55*cofi)/(1.9*cofi)
869 + 1.26*cofi*alpha/(1.0+3.5*cofi))
870 * (newton - fAbscissa[i-3])/(1.0 + 0.3*alpha) ;
871 }
872 for(k=1;k<=maxNumber;k++)
873 {
874 temp1 = 1.0 ;
875 temp2 = 0.0 ;
876
877 for(j=1;j<=fNumber;j++)
878 {
879 temp3 = temp2 ;
880 temp2 = temp1 ;
881 temp1 = ((2*j - 1 + alpha - newton)*temp2 - (j - 1 + alpha)*temp3)/j ;
882 }
883 temp = (fNumber*temp1 - (fNumber +alpha)*temp2)/newton ;
884 newton1 = newton ;
885 newton = newton1 - temp1/temp ;
886
887 if(std::fabs(newton - newton1) <= tolerance)
888 {
889 break ;
890 }
891 }
892 if(k > maxNumber)
893 {
894 G4Exception("G4Integrator<T,F>::Laguerre(T,F, ...)", "Error",
895 FatalException, "Too many (>12) iterations.");
896 }
897
898 fAbscissa[i-1] = newton ;
899 fWeight[i-1] = -std::exp(GammaLogarithm(alpha + fNumber) -
900 GammaLogarithm((G4double)fNumber))/(temp*fNumber*temp2) ;
901 }
902
903 //
904 // Integral evaluation
905 //
906
907 for(i=0;i<fNumber;i++)
908 {
909 integral += fWeight[i]*(typeT.*f)(fAbscissa[i]) ;
910 }
911 delete[] fAbscissa;
912 delete[] fWeight;
913 return integral ;
914}
915
916
917
918//////////////////////////////////////////////////////////////////////
919//
920//
921
922template <class T, class F> G4double
923G4Integrator<T,F>::Laguerre( T* ptrT, F f, G4double alpha, G4int nLaguerre )
924{
925 return Laguerre(*ptrT,f,alpha,nLaguerre) ;
926}
927
928////////////////////////////////////////////////////////////////////////
929//
930// For use with global scope functions f
931
932template <class T, class F> G4double
933G4Integrator<T,F>::Laguerre( G4double (*f)(G4double),
934 G4double alpha, G4int nLaguerre )
935{
936 const G4double tolerance = 1.0e-10 ;
937 const G4int maxNumber = 12 ;
938 G4int i, j, k ;
939 G4double newton=0., newton1, temp1, temp2, temp3, temp, cofi ;
940 G4double integral = 0.0 ;
941
942 G4int fNumber = nLaguerre ;
943 G4double* fAbscissa = new G4double[fNumber] ;
944 G4double* fWeight = new G4double[fNumber] ;
945
946 for(i=1;i<=fNumber;i++) // Loop over the desired roots
947 {
948 if(i == 1)
949 {
950 newton = (1.0 + alpha)*(3.0 + 0.92*alpha)
951 / (1.0 + 2.4*fNumber + 1.8*alpha) ;
952 }
953 else if(i == 2)
954 {
955 newton += (15.0 + 6.25*alpha)/(1.0 + 0.9*alpha + 2.5*fNumber) ;
956 }
957 else
958 {
959 cofi = i - 2 ;
960 newton += ((1.0+2.55*cofi)/(1.9*cofi)
961 + 1.26*cofi*alpha/(1.0+3.5*cofi))
962 * (newton - fAbscissa[i-3])/(1.0 + 0.3*alpha) ;
963 }
964 for(k=1;k<=maxNumber;k++)
965 {
966 temp1 = 1.0 ;
967 temp2 = 0.0 ;
968
969 for(j=1;j<=fNumber;j++)
970 {
971 temp3 = temp2 ;
972 temp2 = temp1 ;
973 temp1 = ((2*j - 1 + alpha - newton)*temp2 - (j - 1 + alpha)*temp3)/j ;
974 }
975 temp = (fNumber*temp1 - (fNumber +alpha)*temp2)/newton ;
976 newton1 = newton ;
977 newton = newton1 - temp1/temp ;
978
979 if(std::fabs(newton - newton1) <= tolerance)
980 {
981 break ;
982 }
983 }
984 if(k > maxNumber)
985 {
986 G4Exception("G4Integrator<T,F>::Laguerre( ...)", "Error",
987 FatalException, "Too many (>12) iterations.");
988 }
989
990 fAbscissa[i-1] = newton ;
991 fWeight[i-1] = -std::exp(GammaLogarithm(alpha + fNumber) -
992 GammaLogarithm((G4double)fNumber))/(temp*fNumber*temp2) ;
993 }
994
995 //
996 // Integral evaluation
997 //
998
999 for(i=0;i<fNumber;i++)
1000 {
1001 integral += fWeight[i]*(*f)(fAbscissa[i]) ;
1002 }
1003 delete[] fAbscissa;
1004 delete[] fWeight;
1005 return integral ;
1006}
1007
1008///////////////////////////////////////////////////////////////////////
1009//
1010// Auxiliary function which returns the value of std::log(gamma-function(x))
1011// Returns the value ln(Gamma(xx) for xx > 0. Full accuracy is obtained for
1012// xx > 1. For 0 < xx < 1. the reflection formula (6.1.4) can be used first.
1013// (Adapted from Numerical Recipes in C)
1014//
1015
1016template <class T, class F>
1017G4double G4Integrator<T,F>::GammaLogarithm(G4double xx)
1018{
1019 static G4double cof[6] = { 76.18009172947146, -86.50532032941677,
1020 24.01409824083091, -1.231739572450155,
1021 0.1208650973866179e-2, -0.5395239384953e-5 } ;
1022 register G4int j;
1023 G4double x = xx - 1.0 ;
1024 G4double tmp = x + 5.5 ;
1025 tmp -= (x + 0.5) * std::log(tmp) ;
1026 G4double ser = 1.000000000190015 ;
1027
1028 for ( j = 0; j <= 5; j++ )
1029 {
1030 x += 1.0 ;
1031 ser += cof[j]/x ;
1032 }
1033 return -tmp + std::log(2.5066282746310005*ser) ;
1034}
1035
1036///////////////////////////////////////////////////////////////////////
1037//
1038// Method involving Hermite polynomials
1039//
1040///////////////////////////////////////////////////////////////////////
1041//
1042//
1043// Gauss-Hermite method for integration of std::exp(-x*x)*f(x)
1044// from minus infinity to plus infinity .
1045//
1046
1047template <class T, class F>
1048G4double G4Integrator<T,F>::Hermite( T& typeT, F f, G4int nHermite )
1049{
1050 const G4double tolerance = 1.0e-12 ;
1051 const G4int maxNumber = 12 ;
1052
1053 G4int i, j, k ;
1054 G4double integral = 0.0 ;
1055 G4double newton=0., newton1, temp1, temp2, temp3, temp ;
1056
1057 G4double piInMinusQ = std::pow(pi,-0.25) ; // 1.0/std::sqrt(std::sqrt(pi)) ??
1058
1059 G4int fNumber = (nHermite +1)/2 ;
1060 G4double* fAbscissa = new G4double[fNumber] ;
1061 G4double* fWeight = new G4double[fNumber] ;
1062
1063 for(i=1;i<=fNumber;i++)
1064 {
1065 if(i == 1)
1066 {
1067 newton = std::sqrt((G4double)(2*nHermite + 1)) -
1068 1.85575001*std::pow((G4double)(2*nHermite + 1),-0.16666999) ;
1069 }
1070 else if(i == 2)
1071 {
1072 newton -= 1.14001*std::pow((G4double)nHermite,0.425999)/newton ;
1073 }
1074 else if(i == 3)
1075 {
1076 newton = 1.86002*newton - 0.86002*fAbscissa[0] ;
1077 }
1078 else if(i == 4)
1079 {
1080 newton = 1.91001*newton - 0.91001*fAbscissa[1] ;
1081 }
1082 else
1083 {
1084 newton = 2.0*newton - fAbscissa[i - 3] ;
1085 }
1086 for(k=1;k<=maxNumber;k++)
1087 {
1088 temp1 = piInMinusQ ;
1089 temp2 = 0.0 ;
1090
1091 for(j=1;j<=nHermite;j++)
1092 {
1093 temp3 = temp2 ;
1094 temp2 = temp1 ;
1095 temp1 = newton*std::sqrt(2.0/j)*temp2 -
1096 std::sqrt(((G4double)(j - 1))/j)*temp3 ;
1097 }
1098 temp = std::sqrt((G4double)2*nHermite)*temp2 ;
1099 newton1 = newton ;
1100 newton = newton1 - temp1/temp ;
1101
1102 if(std::fabs(newton - newton1) <= tolerance)
1103 {
1104 break ;
1105 }
1106 }
1107 if(k > maxNumber)
1108 {
1109 G4Exception("G4Integrator<T,F>::Hermite(T,F, ...)", "Error",
1110 FatalException, "Too many (>12) iterations.");
1111 }
1112 fAbscissa[i-1] = newton ;
1113 fWeight[i-1] = 2.0/(temp*temp) ;
1114 }
1115
1116 //
1117 // Integral calculation
1118 //
1119
1120 for(i=0;i<fNumber;i++)
1121 {
1122 integral += fWeight[i]*( (typeT.*f)(fAbscissa[i]) +
1123 (typeT.*f)(-fAbscissa[i]) ) ;
1124 }
1125 delete[] fAbscissa;
1126 delete[] fWeight;
1127 return integral ;
1128}
1129
1130
1131////////////////////////////////////////////////////////////////////////
1132//
1133// For use with 'this' pointer
1134
1135template <class T, class F>
1136G4double G4Integrator<T,F>::Hermite( T* ptrT, F f, G4int n )
1137{
1138 return Hermite(*ptrT,f,n) ;
1139}
1140
1141////////////////////////////////////////////////////////////////////////
1142//
1143// For use with global scope f
1144
1145template <class T, class F>
1146G4double G4Integrator<T,F>::Hermite( G4double (*f)(G4double), G4int nHermite)
1147{
1148 const G4double tolerance = 1.0e-12 ;
1149 const G4int maxNumber = 12 ;
1150
1151 G4int i, j, k ;
1152 G4double integral = 0.0 ;
1153 G4double newton=0., newton1, temp1, temp2, temp3, temp ;
1154
1155 G4double piInMinusQ = std::pow(pi,-0.25) ; // 1.0/std::sqrt(std::sqrt(pi)) ??
1156
1157 G4int fNumber = (nHermite +1)/2 ;
1158 G4double* fAbscissa = new G4double[fNumber] ;
1159 G4double* fWeight = new G4double[fNumber] ;
1160
1161 for(i=1;i<=fNumber;i++)
1162 {
1163 if(i == 1)
1164 {
1165 newton = std::sqrt((G4double)(2*nHermite + 1)) -
1166 1.85575001*std::pow((G4double)(2*nHermite + 1),-0.16666999) ;
1167 }
1168 else if(i == 2)
1169 {
1170 newton -= 1.14001*std::pow((G4double)nHermite,0.425999)/newton ;
1171 }
1172 else if(i == 3)
1173 {
1174 newton = 1.86002*newton - 0.86002*fAbscissa[0] ;
1175 }
1176 else if(i == 4)
1177 {
1178 newton = 1.91001*newton - 0.91001*fAbscissa[1] ;
1179 }
1180 else
1181 {
1182 newton = 2.0*newton - fAbscissa[i - 3] ;
1183 }
1184 for(k=1;k<=maxNumber;k++)
1185 {
1186 temp1 = piInMinusQ ;
1187 temp2 = 0.0 ;
1188
1189 for(j=1;j<=nHermite;j++)
1190 {
1191 temp3 = temp2 ;
1192 temp2 = temp1 ;
1193 temp1 = newton*std::sqrt(2.0/j)*temp2 -
1194 std::sqrt(((G4double)(j - 1))/j)*temp3 ;
1195 }
1196 temp = std::sqrt((G4double)2*nHermite)*temp2 ;
1197 newton1 = newton ;
1198 newton = newton1 - temp1/temp ;
1199
1200 if(std::fabs(newton - newton1) <= tolerance)
1201 {
1202 break ;
1203 }
1204 }
1205 if(k > maxNumber)
1206 {
1207 G4Exception("G4Integrator<T,F>::Hermite(...)", "Error",
1208 FatalException, "Too many (>12) iterations.");
1209 }
1210 fAbscissa[i-1] = newton ;
1211 fWeight[i-1] = 2.0/(temp*temp) ;
1212 }
1213
1214 //
1215 // Integral calculation
1216 //
1217
1218 for(i=0;i<fNumber;i++)
1219 {
1220 integral += fWeight[i]*( (*f)(fAbscissa[i]) + (*f)(-fAbscissa[i]) ) ;
1221 }
1222 delete[] fAbscissa;
1223 delete[] fWeight;
1224 return integral ;
1225}
1226
1227////////////////////////////////////////////////////////////////////////////
1228//
1229// Method involving Jacobi polynomials
1230//
1231////////////////////////////////////////////////////////////////////////////
1232//
1233// Gauss-Jacobi method for integration of ((1-x)^alpha)*((1+x)^beta)*f(x)
1234// from minus unit to plus unit .
1235//
1236
1237template <class T, class F>
1238G4double G4Integrator<T,F>::Jacobi( T& typeT, F f, G4double alpha,
1239 G4double beta, G4int nJacobi)
1240{
1241 const G4double tolerance = 1.0e-12 ;
1242 const G4double maxNumber = 12 ;
1243 G4int i, k, j ;
1244 G4double alphaBeta, alphaReduced, betaReduced, root1=0., root2=0., root3=0. ;
1245 G4double a, b, c, newton1, newton2, newton3, newton, temp, root=0., rootTemp ;
1246
1247 G4int fNumber = nJacobi ;
1248 G4double* fAbscissa = new G4double[fNumber] ;
1249 G4double* fWeight = new G4double[fNumber] ;
1250
1251 for (i=1;i<=nJacobi;i++)
1252 {
1253 if (i == 1)
1254 {
1255 alphaReduced = alpha/nJacobi ;
1256 betaReduced = beta/nJacobi ;
1257 root1 = (1.0+alpha)*(2.78002/(4.0+nJacobi*nJacobi)+
1258 0.767999*alphaReduced/nJacobi) ;
1259 root2 = 1.0+1.48*alphaReduced+0.96002*betaReduced +
1260 0.451998*alphaReduced*alphaReduced +
1261 0.83001*alphaReduced*betaReduced ;
1262 root = 1.0-root1/root2 ;
1263 }
1264 else if (i == 2)
1265 {
1266 root1=(4.1002+alpha)/((1.0+alpha)*(1.0+0.155998*alpha)) ;
1267 root2=1.0+0.06*(nJacobi-8.0)*(1.0+0.12*alpha)/nJacobi ;
1268 root3=1.0+0.012002*beta*(1.0+0.24997*std::fabs(alpha))/nJacobi ;
1269 root -= (1.0-root)*root1*root2*root3 ;
1270 }
1271 else if (i == 3)
1272 {
1273 root1=(1.67001+0.27998*alpha)/(1.0+0.37002*alpha) ;
1274 root2=1.0+0.22*(nJacobi-8.0)/nJacobi ;
1275 root3=1.0+8.0*beta/((6.28001+beta)*nJacobi*nJacobi) ;
1276 root -= (fAbscissa[0]-root)*root1*root2*root3 ;
1277 }
1278 else if (i == nJacobi-1)
1279 {
1280 root1=(1.0+0.235002*beta)/(0.766001+0.118998*beta) ;
1281 root2=1.0/(1.0+0.639002*(nJacobi-4.0)/(1.0+0.71001*(nJacobi-4.0))) ;
1282 root3=1.0/(1.0+20.0*alpha/((7.5+alpha)*nJacobi*nJacobi)) ;
1283 root += (root-fAbscissa[nJacobi-4])*root1*root2*root3 ;
1284 }
1285 else if (i == nJacobi)
1286 {
1287 root1 = (1.0+0.37002*beta)/(1.67001+0.27998*beta) ;
1288 root2 = 1.0/(1.0+0.22*(nJacobi-8.0)/nJacobi) ;
1289 root3 = 1.0/(1.0+8.0*alpha/((6.28002+alpha)*nJacobi*nJacobi)) ;
1290 root += (root-fAbscissa[nJacobi-3])*root1*root2*root3 ;
1291 }
1292 else
1293 {
1294 root = 3.0*fAbscissa[i-2]-3.0*fAbscissa[i-3]+fAbscissa[i-4] ;
1295 }
1296 alphaBeta = alpha + beta ;
1297 for (k=1;k<=maxNumber;k++)
1298 {
1299 temp = 2.0 + alphaBeta ;
1300 newton1 = (alpha-beta+temp*root)/2.0 ;
1301 newton2 = 1.0 ;
1302 for (j=2;j<=nJacobi;j++)
1303 {
1304 newton3 = newton2 ;
1305 newton2 = newton1 ;
1306 temp = 2*j+alphaBeta ;
1307 a = 2*j*(j+alphaBeta)*(temp-2.0) ;
1308 b = (temp-1.0)*(alpha*alpha-beta*beta+temp*(temp-2.0)*root) ;
1309 c = 2.0*(j-1+alpha)*(j-1+beta)*temp ;
1310 newton1 = (b*newton2-c*newton3)/a ;
1311 }
1312 newton = (nJacobi*(alpha - beta - temp*root)*newton1 +
1313 2.0*(nJacobi + alpha)*(nJacobi + beta)*newton2)/
1314 (temp*(1.0 - root*root)) ;
1315 rootTemp = root ;
1316 root = rootTemp - newton1/newton ;
1317 if (std::fabs(root-rootTemp) <= tolerance)
1318 {
1319 break ;
1320 }
1321 }
1322 if (k > maxNumber)
1323 {
1324 G4Exception("G4Integrator<T,F>::Jacobi(T,F, ...)", "Error",
1325 FatalException, "Too many (>12) iterations.");
1326 }
1327 fAbscissa[i-1] = root ;
1328 fWeight[i-1] = std::exp(GammaLogarithm((G4double)(alpha+nJacobi)) +
1329 GammaLogarithm((G4double)(beta+nJacobi)) -
1330 GammaLogarithm((G4double)(nJacobi+1.0)) -
1331 GammaLogarithm((G4double)(nJacobi + alphaBeta + 1.0)))
1332 *temp*std::pow(2.0,alphaBeta)/(newton*newton2) ;
1333 }
1334
1335 //
1336 // Calculation of the integral
1337 //
1338
1339 G4double integral = 0.0 ;
1340 for(i=0;i<fNumber;i++)
1341 {
1342 integral += fWeight[i]*(typeT.*f)(fAbscissa[i]) ;
1343 }
1344 delete[] fAbscissa;
1345 delete[] fWeight;
1346 return integral ;
1347}
1348
1349
1350/////////////////////////////////////////////////////////////////////////
1351//
1352// For use with 'this' pointer
1353
1354template <class T, class F>
1355G4double G4Integrator<T,F>::Jacobi( T* ptrT, F f, G4double alpha,
1356 G4double beta, G4int n)
1357{
1358 return Jacobi(*ptrT,f,alpha,beta,n) ;
1359}
1360
1361/////////////////////////////////////////////////////////////////////////
1362//
1363// For use with global scope f
1364
1365template <class T, class F>
1366G4double G4Integrator<T,F>::Jacobi( G4double (*f)(G4double), G4double alpha,
1367 G4double beta, G4int nJacobi)
1368{
1369 const G4double tolerance = 1.0e-12 ;
1370 const G4double maxNumber = 12 ;
1371 G4int i, k, j ;
1372 G4double alphaBeta, alphaReduced, betaReduced, root1=0., root2=0., root3=0. ;
1373 G4double a, b, c, newton1, newton2, newton3, newton, temp, root=0., rootTemp ;
1374
1375 G4int fNumber = nJacobi ;
1376 G4double* fAbscissa = new G4double[fNumber] ;
1377 G4double* fWeight = new G4double[fNumber] ;
1378
1379 for (i=1;i<=nJacobi;i++)
1380 {
1381 if (i == 1)
1382 {
1383 alphaReduced = alpha/nJacobi ;
1384 betaReduced = beta/nJacobi ;
1385 root1 = (1.0+alpha)*(2.78002/(4.0+nJacobi*nJacobi)+
1386 0.767999*alphaReduced/nJacobi) ;
1387 root2 = 1.0+1.48*alphaReduced+0.96002*betaReduced +
1388 0.451998*alphaReduced*alphaReduced +
1389 0.83001*alphaReduced*betaReduced ;
1390 root = 1.0-root1/root2 ;
1391 }
1392 else if (i == 2)
1393 {
1394 root1=(4.1002+alpha)/((1.0+alpha)*(1.0+0.155998*alpha)) ;
1395 root2=1.0+0.06*(nJacobi-8.0)*(1.0+0.12*alpha)/nJacobi ;
1396 root3=1.0+0.012002*beta*(1.0+0.24997*std::fabs(alpha))/nJacobi ;
1397 root -= (1.0-root)*root1*root2*root3 ;
1398 }
1399 else if (i == 3)
1400 {
1401 root1=(1.67001+0.27998*alpha)/(1.0+0.37002*alpha) ;
1402 root2=1.0+0.22*(nJacobi-8.0)/nJacobi ;
1403 root3=1.0+8.0*beta/((6.28001+beta)*nJacobi*nJacobi) ;
1404 root -= (fAbscissa[0]-root)*root1*root2*root3 ;
1405 }
1406 else if (i == nJacobi-1)
1407 {
1408 root1=(1.0+0.235002*beta)/(0.766001+0.118998*beta) ;
1409 root2=1.0/(1.0+0.639002*(nJacobi-4.0)/(1.0+0.71001*(nJacobi-4.0))) ;
1410 root3=1.0/(1.0+20.0*alpha/((7.5+alpha)*nJacobi*nJacobi)) ;
1411 root += (root-fAbscissa[nJacobi-4])*root1*root2*root3 ;
1412 }
1413 else if (i == nJacobi)
1414 {
1415 root1 = (1.0+0.37002*beta)/(1.67001+0.27998*beta) ;
1416 root2 = 1.0/(1.0+0.22*(nJacobi-8.0)/nJacobi) ;
1417 root3 = 1.0/(1.0+8.0*alpha/((6.28002+alpha)*nJacobi*nJacobi)) ;
1418 root += (root-fAbscissa[nJacobi-3])*root1*root2*root3 ;
1419 }
1420 else
1421 {
1422 root = 3.0*fAbscissa[i-2]-3.0*fAbscissa[i-3]+fAbscissa[i-4] ;
1423 }
1424 alphaBeta = alpha + beta ;
1425 for (k=1;k<=maxNumber;k++)
1426 {
1427 temp = 2.0 + alphaBeta ;
1428 newton1 = (alpha-beta+temp*root)/2.0 ;
1429 newton2 = 1.0 ;
1430 for (j=2;j<=nJacobi;j++)
1431 {
1432 newton3 = newton2 ;
1433 newton2 = newton1 ;
1434 temp = 2*j+alphaBeta ;
1435 a = 2*j*(j+alphaBeta)*(temp-2.0) ;
1436 b = (temp-1.0)*(alpha*alpha-beta*beta+temp*(temp-2.0)*root) ;
1437 c = 2.0*(j-1+alpha)*(j-1+beta)*temp ;
1438 newton1 = (b*newton2-c*newton3)/a ;
1439 }
1440 newton = (nJacobi*(alpha - beta - temp*root)*newton1 +
1441 2.0*(nJacobi + alpha)*(nJacobi + beta)*newton2) /
1442 (temp*(1.0 - root*root)) ;
1443 rootTemp = root ;
1444 root = rootTemp - newton1/newton ;
1445 if (std::fabs(root-rootTemp) <= tolerance)
1446 {
1447 break ;
1448 }
1449 }
1450 if (k > maxNumber)
1451 {
1452 G4Exception("G4Integrator<T,F>::Jacobi(...)", "Error",
1453 FatalException, "Too many (>12) iterations.");
1454 }
1455 fAbscissa[i-1] = root ;
1456 fWeight[i-1] =
1457 std::exp(GammaLogarithm((G4double)(alpha+nJacobi)) +
1458 GammaLogarithm((G4double)(beta+nJacobi)) -
1459 GammaLogarithm((G4double)(nJacobi+1.0)) -
1460 GammaLogarithm((G4double)(nJacobi + alphaBeta + 1.0)))
1461 *temp*std::pow(2.0,alphaBeta)/(newton*newton2);
1462 }
1463
1464 //
1465 // Calculation of the integral
1466 //
1467
1468 G4double integral = 0.0 ;
1469 for(i=0;i<fNumber;i++)
1470 {
1471 integral += fWeight[i]*(*f)(fAbscissa[i]) ;
1472 }
1473 delete[] fAbscissa;
1474 delete[] fWeight;
1475 return integral ;
1476}
1477
1478//
1479//
1480///////////////////////////////////////////////////////////////////
Note: See TracBrowser for help on using the repository browser.