2
0

CalcGauss.Mod 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  1. (* CAPO - Computational Analysis Platform for Oberon - by Alan Freed and Felix Friedrich. *)
  2. (* Version 1, Update 2 *)
  3. MODULE CalcGauss; (** AUTHOR "adf"; PURPOSE "Accurate computation of an integral"; *)
  4. (* To change to 64-bit reals, go to the module body and select the appropriate constants commented in light red. *)
  5. (** Gauss-Kronrod integrators that solve to a specified error tolerance achieved by automatic subdivision. *)
  6. IMPORT NbrInt, NbrRe, NbrCplx, Data, DataLists, CalcFn;
  7. CONST
  8. (** Admissible parameters to pass that select the 'integrator'.
  9. Coarse should only be selected for smooth integrands.
  10. Medium should be used as the default.
  11. Fine should be selected for oscillating integrands. *)
  12. Coarse* = 99; Medium* = 100; Fine* = 101;
  13. (** Status of an integration, i.e., the admissible values for the returned parameter 'res'. *)
  14. OKay* = 0; MaxSubDivReached* = 1; RoundoffError* = 2; RoughIntegrand* = 3;
  15. VAR
  16. (** Upper bound on the number of subintervals of integration. *)
  17. MaxIntervals-: NbrInt.Integer;
  18. node8, wgtGauss4, wgtKronrod8, node16, wgtGauss8, wgtKronrod16, node31, wgtGauss15,
  19. wgtKronrod31: POINTER TO ARRAY OF NbrRe.Real;
  20. TYPE
  21. (* The Read and Write methods are not required because Intervals belong to lists that are not saved to file. *)
  22. Interval = OBJECT (Data.Datum)
  23. VAR a, b, error: NbrRe.Real;
  24. PROCEDURE & Initialize*;
  25. BEGIN
  26. Initialize^;
  27. (* Intialize the local data. *)
  28. a := 0; b := 0; error := 0
  29. END Initialize;
  30. PROCEDURE Copy*( VAR copy: Data.Datum );
  31. VAR new, obj: Interval;
  32. BEGIN
  33. (* Create object copy. *)
  34. IF (copy = NIL ) OR ~(copy IS Interval) THEN NEW( new ); copy := new END;
  35. (* Copy the lower-level data structures first. *)
  36. Copy^( copy );
  37. (* Type cast copy so that the local data structure can be copied. *)
  38. obj := copy( Interval );
  39. (* Make a deep copy of the local data to obj. *)
  40. obj.a := a; obj.b := b; obj.error := error;
  41. (* Reassign the copied object for returning. *)
  42. copy := obj
  43. END Copy;
  44. END Interval;
  45. ReInterval = OBJECT (Interval)
  46. VAR soln: NbrRe.Real;
  47. PROCEDURE & Initialize*;
  48. BEGIN
  49. Initialize^;
  50. (* Intialize the local data. *)
  51. soln := 0
  52. END Initialize;
  53. PROCEDURE Copy*( VAR copy: Data.Datum );
  54. VAR new, obj: ReInterval;
  55. BEGIN
  56. (* Create object copy. *)
  57. IF (copy = NIL ) OR ~(copy IS ReInterval) THEN NEW( new ); copy := new END;
  58. (* Copy the lower-level data structures first. *)
  59. Copy^( copy );
  60. (* Type cast copy so that the local data structure can be copied. *)
  61. obj := copy( ReInterval );
  62. (* Make a deep copy of the local data to obj. *)
  63. obj.soln := soln;
  64. (* Reassign the copied object for returning. *)
  65. copy := obj
  66. END Copy;
  67. END ReInterval;
  68. CplxInterval = OBJECT (Interval)
  69. VAR soln: NbrCplx.Complex;
  70. PROCEDURE & Initialize*;
  71. BEGIN
  72. Initialize^;
  73. (* Intialize the local data. *)
  74. soln := 0
  75. END Initialize;
  76. PROCEDURE Copy*( VAR copy: Data.Datum );
  77. VAR new, obj: CplxInterval;
  78. BEGIN
  79. (* Create object copy. *)
  80. IF (copy = NIL ) OR ~(copy IS CplxInterval) THEN NEW( new ); copy := new END;
  81. (* Copy the lower-level data structures first. *)
  82. Copy^( copy );
  83. (* Type cast copy so that the local data structure can be copied. *)
  84. obj := copy( CplxInterval );
  85. (* Make a deep copy of the local data to obj. *)
  86. obj.soln := soln;
  87. (* Reassign the copied object for returning. *)
  88. copy := obj
  89. END Copy;
  90. END CplxInterval;
  91. PROCEDURE GetKey( a, b, atX: NbrRe.Real ): Data.Key;
  92. VAR k: Data.Key;
  93. BEGIN
  94. k := NbrRe.Int( MaxIntervals * (atX - a)/(b - a) ); RETURN k
  95. END GetKey;
  96. PROCEDURE ReGaussKronrod( f: CalcFn.ReArg; fromX, toX: NbrRe.Real; integrator: NbrInt.Integer;
  97. VAR result, absError, absResult: NbrRe.Real );
  98. (* f : integrand
  99. fromX : lower limit of integration
  100. toX (> fromX) : upper limit of integration
  101. integrator N {Coarse, Medium, Fine}
  102. result : approximation to the integral
  103. absError : estimate of the absolute error
  104. absResult : approximation to the integral of ABS(f(x)) over [fromX, toX]
  105. *)
  106. VAR i, len: NbrInt.Integer;
  107. abscissa, center, fCenter, fSum, halfLength, resultGauss, resultKronrod, tolerance: NbrRe.Real;
  108. fAbove, fBelow, node, wgtGauss, wgtKronrod: POINTER TO ARRAY OF NbrRe.Real;
  109. BEGIN
  110. IF integrator = Coarse THEN
  111. len := 8; NEW( node, 8 ); NEW( wgtGauss, 4 ); NEW( wgtKronrod, 8 );
  112. FOR i := 0 TO 7 DO node[i] := node8[i]; wgtKronrod[i] := wgtKronrod8[i] END;
  113. FOR i := 0 TO 3 DO wgtGauss[i] := wgtGauss4[i] END
  114. ELSIF integrator = Fine THEN
  115. len := 31; NEW( node, 31 ); NEW( wgtGauss, 15 ); NEW( wgtKronrod, 31 );
  116. FOR i := 0 TO 30 DO node[i] := node31[i]; wgtKronrod[i] := wgtKronrod31[i] END;
  117. FOR i := 0 TO 14 DO wgtGauss[i] := wgtGauss15[i] END
  118. ELSE (* integrator = Medium, the default *)
  119. len := 16; NEW( node, 16 ); NEW( wgtGauss, 8 ); NEW( wgtKronrod, 16 );
  120. FOR i := 0 TO 15 DO node[i] := node16[i]; wgtKronrod[i] := wgtKronrod16[i] END;
  121. FOR i := 0 TO 7 DO wgtGauss[i] := wgtGauss8[i] END
  122. END;
  123. NEW( fAbove, len - 1 ); NEW( fBelow, len - 1 ); center := (fromX + toX) / 2; halfLength := (toX - fromX) / 2;
  124. fCenter := f( center ); resultKronrod := wgtKronrod[len - 1] * fCenter; absResult := ABS( resultKronrod );
  125. IF NbrInt.Odd( len ) THEN resultGauss := 0 ELSE resultGauss := wgtGauss[(len DIV 2) - 1] * fCenter END;
  126. FOR i := 0 TO len - 2 DO
  127. abscissa := halfLength * node[i]; fAbove[i] := f( center + abscissa ); fBelow[i] := f( center - abscissa );
  128. fSum := fAbove[i] + fBelow[i]; resultKronrod := resultKronrod + wgtKronrod[i] * fSum;
  129. absResult := absResult + wgtKronrod[i] * (ABS( fAbove[i] ) + ABS( fBelow[i] ));
  130. IF NbrInt.Odd( i ) THEN resultGauss := resultGauss + wgtGauss[i DIV 2] * fSum END
  131. END;
  132. result := halfLength * resultKronrod; absResult := halfLength * absResult;
  133. absError := ABS( halfLength * (resultKronrod - resultGauss) ); tolerance := 50 * NbrRe.Epsilon;
  134. IF absResult > 1/NbrRe.MaxNbr*tolerance THEN absError := NbrRe.Max( absError, tolerance * absResult ) END
  135. END ReGaussKronrod;
  136. (** Computes I(f) = xab f(x) dx to a specified error tolerance. *)
  137. PROCEDURE Solve*( f: CalcFn.ReArg; a, b: NbrRe.Real; integrator: NbrInt.Integer; VAR error: NbrRe.Real;
  138. VAR res: NbrInt.Integer ): NbrRe.Real;
  139. (* This algorithm is a partial port of the FORTRAN subroutine DPAG from the QUADPACK library of routines.
  140. R. Piessens, E. de Doncker-Kapenga, C. überhuber, and D. K. Kahaner. QUADPACK - A Subroutine Package for
  141. Automatic Integration. No. 1 in: Springer Series in Computational Mathematics, Springer, Berlin, 1983. *)
  142. VAR ignor, successful: BOOLEAN; key, maxKey: Data.Key; sign: NbrInt.Integer;
  143. aa, bb, maxError, maxTol, midPoint, sumError, sumResult, tolerance: NbrRe.Real; datum: Data.Datum;
  144. interval, intervalL, intervalR: ReInterval; history: DataLists.List;
  145. PROCEDURE Create( withKey: Data.Key ): ReInterval;
  146. VAR int: ReInterval;
  147. BEGIN
  148. NEW( int ); int.SetKey( withKey ); RETURN int
  149. END Create;
  150. PROCEDURE Update( VAR int: ReInterval );
  151. VAR absApprox, absError, approx: NbrRe.Real;
  152. BEGIN
  153. ReGaussKronrod( f, int.a, int.b, integrator, approx, absError, absApprox ); int.soln := approx;
  154. int.error := absError * (int.b - int.a) / (bb - aa);
  155. IF (absError < 100 * NbrRe.Epsilon * absApprox) & (absError > tolerance) THEN
  156. res := RoundoffError
  157. END;
  158. IF NbrRe.Abs( int.b ) < ((1 + 100*NbrRe.Epsilon) * (NbrRe.Abs( int.a ) + 1000/NbrRe.MaxNbr)) THEN
  159. res := RoughIntegrand
  160. END
  161. END Update;
  162. BEGIN
  163. IF f # NIL THEN
  164. res := OKay;
  165. IF a = b THEN error := 0; sign := 1; sumResult := 0
  166. ELSE (* integrate *)
  167. maxTol := 0.1; tolerance := NbrRe.Max( 100 * NbrRe.Epsilon, NbrRe.Min( maxTol, error ) );
  168. IF a < b THEN sign := 1; aa := a; bb := b ELSE sign := -1; aa := b; bb := a END;
  169. key := GetKey( aa, bb, bb ); interval := Create( key ); interval.a := aa; interval.b := bb;
  170. Update( interval ); sumResult := interval.soln; sumError := interval.error;
  171. IF NbrRe.Abs( sumResult ) < 1 THEN error := sumError
  172. ELSE error := NbrRe.Abs( sumError / sumResult )
  173. END;
  174. IF error > tolerance THEN
  175. NEW( history ); history.Insert( interval, ignor );
  176. (* Refine the integration. *)
  177. LOOP
  178. (* Search for the interval with the largest error estimate. *)
  179. history.rider.Home; datum := history.rider.Inspect(); interval := datum( ReInterval );
  180. maxError := interval.error; interval.GetKey( maxKey );
  181. WHILE ~history.rider.eol DO
  182. history.rider.Next; datum := history.rider.Inspect(); interval := datum( ReInterval );
  183. IF interval.error > maxError THEN
  184. maxError := interval.error; interval.GetKey( maxKey )
  185. END
  186. END;
  187. (* Bisect the interval with the largest error estimate and integrate these two subintervals. *)
  188. datum := history.rider.Retrieve( maxKey ); interval := datum( ReInterval );
  189. history.Delete( maxKey, ignor ); midPoint := (interval.a + interval.b) / 2;
  190. key := GetKey( interval.a, interval.b, midPoint ); intervalL := Create( key );
  191. intervalL.a := interval.a; intervalL.b := midPoint; Update( intervalL );
  192. history.Insert( intervalL, successful );
  193. IF successful & (key # maxKey) THEN
  194. intervalR := Create( maxKey ); intervalR.a := midPoint; intervalR.b := interval.b;
  195. Update( intervalR ); history.Insert( intervalR, ignor )
  196. ELSE
  197. IF successful THEN history.Delete( key, ignor ) END;
  198. history.Insert( interval, ignor ); res := MaxSubDivReached
  199. END;
  200. IF res # OKay THEN EXIT END;
  201. sumResult := sumResult + intervalL.soln + intervalR.soln - interval.soln;
  202. sumError := sumError + intervalL.error + intervalR.error - interval.error;
  203. IF NbrRe.Abs( sumResult ) < 1 THEN error := sumError
  204. ELSE error := NbrRe.Abs( sumError / sumResult )
  205. END;
  206. IF error < tolerance THEN EXIT END
  207. END
  208. END
  209. END
  210. ELSE sign := 1; sumResult := 0
  211. END;
  212. RETURN sign * sumResult
  213. END Solve;
  214. PROCEDURE CplxGaussKronrod( f: CalcFn.MixedArg; fromX, toX: NbrRe.Real; z: NbrCplx.Complex;
  215. integrator: NbrInt.Integer; VAR result: NbrCplx.Complex;
  216. VAR absError, absResult: NbrRe.Real );
  217. (* f : integrand
  218. fromX : lower limit of integration
  219. toX (> fromX) : upper limit of integration
  220. z is a passed parameter to f
  221. integrator N {Coarse, Medium, Fine}
  222. result : approximation to the integral
  223. absError : estimate of the absolute error
  224. absResult : approximation to the integral of ABS(f(x)) over [fromX, toX]
  225. *)
  226. VAR i, len: NbrInt.Integer; abscissa, center, halfLength, tolerance: NbrRe.Real;
  227. fCenter, fSum, resultGauss, resultKronrod: NbrCplx.Complex;
  228. node, wgtGauss, wgtKronrod: POINTER TO ARRAY OF NbrRe.Real;
  229. fAbove, fBelow: POINTER TO ARRAY OF NbrCplx.Complex;
  230. BEGIN
  231. IF integrator = Coarse THEN
  232. len := 8; NEW( node, 8 ); NEW( wgtGauss, 4 ); NEW( wgtKronrod, 8 );
  233. FOR i := 0 TO 7 DO node[i] := node8[i]; wgtKronrod[i] := wgtKronrod8[i] END;
  234. FOR i := 0 TO 3 DO wgtGauss[i] := wgtGauss4[i] END
  235. ELSIF integrator = Fine THEN
  236. len := 31; NEW( node, 31 ); NEW( wgtGauss, 15 ); NEW( wgtKronrod, 31 );
  237. FOR i := 0 TO 30 DO node[i] := node31[i]; wgtKronrod[i] := wgtKronrod31[i] END;
  238. FOR i := 0 TO 14 DO wgtGauss[i] := wgtGauss15[i] END
  239. ELSE (* integrator = Medium, the default *)
  240. len := 16; NEW( node, 16 ); NEW( wgtGauss, 8 ); NEW( wgtKronrod, 16 );
  241. FOR i := 0 TO 15 DO node[i] := node16[i]; wgtKronrod[i] := wgtKronrod16[i] END;
  242. FOR i := 0 TO 7 DO wgtGauss[i] := wgtGauss8[i] END
  243. END;
  244. NEW( fAbove, len - 1 ); NEW( fBelow, len - 1 ); center := (fromX + toX) / 2; halfLength := (toX - fromX) / 2;
  245. fCenter := f( center, z ); resultKronrod := wgtKronrod[len - 1] * fCenter;
  246. absResult := NbrCplx.Abs( resultKronrod );
  247. IF NbrInt.Odd( len ) THEN resultGauss := 0 ELSE resultGauss := wgtGauss[(len DIV 2) - 1] * fCenter END;
  248. FOR i := 0 TO len - 2 DO
  249. abscissa := halfLength * node[i]; fAbove[i] := f( center + abscissa, z ); fBelow[i] := f( center - abscissa, z );
  250. fSum := fAbove[i] + fBelow[i]; resultKronrod := resultKronrod + wgtKronrod[i] * fSum;
  251. absResult := absResult + wgtKronrod[i] * (NbrCplx.Abs( fAbove[i] ) + NbrCplx.Abs( fBelow[i] ));
  252. IF NbrInt.Odd( i ) THEN resultGauss := resultGauss + wgtGauss[i DIV 2] * fSum END
  253. END;
  254. result := halfLength * resultKronrod; absResult := halfLength * absResult;
  255. absError := NbrCplx.Abs( halfLength * (resultKronrod - resultGauss) ); tolerance := 50 * NbrRe.Epsilon;
  256. IF absResult > 1/NbrRe.MaxNbr*tolerance THEN absError := NbrRe.Max( absError, tolerance * absResult ) END
  257. END CplxGaussKronrod;
  258. (** Computes I(f) = xab f(x,z) dx to a specified error tolerance. *)
  259. PROCEDURE SolveCplx*( f: CalcFn.MixedArg; a, b: NbrRe.Real; z: NbrCplx.Complex; integrator: NbrInt.Integer;
  260. VAR error: NbrRe.Real; VAR res: NbrInt.Integer ): NbrCplx.Complex;
  261. VAR ignor, successful: BOOLEAN; key, maxKey: Data.Key; sign: NbrInt.Integer;
  262. aa, bb, maxError, maxTol, midPoint, sumError, tolerance: NbrRe.Real; sumResult: NbrCplx.Complex;
  263. datum: Data.Datum; interval, intervalL, intervalR: CplxInterval; history: DataLists.List;
  264. PROCEDURE Create( withKey: Data.Key ): CplxInterval;
  265. VAR int: CplxInterval;
  266. BEGIN
  267. NEW( int ); int.SetKey( withKey ); RETURN int
  268. END Create;
  269. PROCEDURE Update( VAR int: CplxInterval );
  270. VAR absApprox, absError: NbrRe.Real; approx: NbrCplx.Complex;
  271. BEGIN
  272. CplxGaussKronrod( f, int.a, int.b, z, integrator, approx, absError, absApprox ); int.soln := approx;
  273. int.error := absError * (int.b - int.a) / (bb - aa);
  274. IF (absError < 100 * NbrRe.Epsilon * absApprox) & (absError > tolerance) THEN
  275. res := RoundoffError
  276. END;
  277. IF NbrRe.Abs( int.b ) < ((1 + 100*NbrRe.Epsilon) * (NbrRe.Abs( int.a ) + 1000/NbrRe.MaxNbr)) THEN
  278. res := RoughIntegrand
  279. END
  280. END Update;
  281. BEGIN
  282. IF f # NIL THEN
  283. res := OKay;
  284. IF a = b THEN error := 0; sign := 1; sumResult := 0
  285. ELSE (* integrate *)
  286. maxTol := 0.1; tolerance := NbrRe.Max( 100 * NbrRe.Epsilon, NbrRe.Min( maxTol, error ) );
  287. IF a < b THEN sign := 1; aa := a; bb := b ELSE sign := -1; aa := b; bb := a END;
  288. key := GetKey( aa, bb, bb ); interval := Create( key ); interval.a := aa; interval.b := bb;
  289. Update( interval ); sumResult := interval.soln; sumError := interval.error;
  290. IF NbrCplx.Abs( sumResult ) < 1 THEN error := sumError
  291. ELSE error := NbrCplx.Abs( sumError / sumResult )
  292. END;
  293. IF error > tolerance THEN
  294. NEW( history ); history.Insert( interval, ignor );
  295. (* Refine the integration. *)
  296. LOOP
  297. (* Search for the interval with the largest error estimate. *)
  298. history.rider.Home; datum := history.rider.Inspect(); interval := datum( CplxInterval );
  299. maxError := interval.error; interval.GetKey( maxKey );
  300. WHILE ~history.rider.eol DO
  301. history.rider.Next; datum := history.rider.Inspect(); interval := datum( CplxInterval );
  302. IF interval.error > maxError THEN
  303. maxError := interval.error; interval.GetKey( maxKey )
  304. END
  305. END;
  306. (* Bisect the interval with the largest error estimate and integrate these two subintervals. *)
  307. datum := history.rider.Retrieve( maxKey ); interval := datum( CplxInterval );
  308. history.Delete( maxKey, ignor ); midPoint := (interval.a + interval.b) / 2;
  309. key := GetKey( interval.a, interval.b, midPoint ); intervalL := Create( key );
  310. intervalL.a := interval.a; intervalL.b := midPoint; Update( intervalL );
  311. history.Insert( intervalL, successful );
  312. IF successful & (key # maxKey) THEN
  313. intervalR := Create( maxKey ); intervalR.a := midPoint; intervalR.b := interval.b;
  314. Update( intervalR ); history.Insert( intervalR, ignor )
  315. ELSE
  316. IF successful THEN history.Delete( key, ignor ) END;
  317. history.Insert( interval, ignor ); res := MaxSubDivReached
  318. END;
  319. IF res # OKay THEN EXIT END;
  320. sumResult := sumResult + intervalL.soln + intervalR.soln - interval.soln;
  321. sumError := sumError + intervalL.error + intervalR.error - interval.error;
  322. IF NbrCplx.Abs( sumResult ) < 1 THEN error := sumError
  323. ELSE error := NbrCplx.Abs( sumError / sumResult )
  324. END;
  325. IF error < tolerance THEN EXIT END
  326. END
  327. END
  328. END
  329. ELSE sign := 1; sumResult := 0
  330. END;
  331. RETURN sign * sumResult
  332. END SolveCplx;
  333. PROCEDURE Quadrature;
  334. (* Gauss-Kronrod integration parameters for solving I(f) = x-11 f(y) dy via I(f) p Si=1N wi f(ni).
  335. Because of symmetry over [-1, 1], only the positive nodes and their corresponding weights are given.
  336. Kronrod integration takes place at all the nodes. Gauss integration only takes place at the odd nodes.
  337. These weights and nodes came from the FORTRAN subroutine DPAG from the QUADPACK library of routines.
  338. R. Piessens, E. de Doncker-Kapenga, C. überhuber, and D. K. Kahaner. QUADPACK - A Subroutine Package for
  339. Automatic Integration. No. 1 in: Springer Series in Computational Mathematics, Springer, Berlin, 1983. *)
  340. BEGIN
  341. (* Whenever NbrRe.Real is a 32-bit real, use the following eonstants. *)
  342. (* For Coarse integration *)
  343. NEW( node8, 8 ); NEW( wgtGauss4, 4 ); NEW( wgtKronrod8, 8 ); node8[0] := 0.99145537112081263920E0;
  344. node8[1] := 0.949107912; node8[2] := 0.864864423; node8[3] := 0.741531185; node8[4] := 0.586087235;
  345. node8[5] := 0.405845151; node8[6] := 0.207784955; node8[7] := 0.0;
  346. wgtGauss4[0] := 0.129484966; wgtGauss4[1] := 0.279705391; wgtGauss4[2] := 0.381830051;
  347. wgtGauss4[3] := 0.417959183;
  348. wgtKronrod8[0] := 0.022935322;
  349. wgtKronrod8[1] := 0.063092093; wgtKronrod8[2] := 0.104790010; wgtKronrod8[3] := 0.140653260;
  350. wgtKronrod8[4] := 0.169004727; wgtKronrod8[5] := 0.190350578; wgtKronrod8[6] := 0.204432940;
  351. wgtKronrod8[7] := 0.209482141;
  352. (* For Medium integration *)
  353. NEW( node16, 16 ); NEW( wgtGauss8, 8 ); NEW( wgtKronrod16, 16 );
  354. node16[0] := 0.998002299; node16[1] := 0.987992518; node16[2] := 0.967739076; node16[3] := 0.937273392;
  355. node16[4] := 0.897264532; node16[5] := 0.848206583; node16[6] := 0.790418501; node16[7] := 0.724417731;
  356. node16[8] := 0.650996741; node16[9] := 0.570972173; node16[10] := 0.48508186; node16[11] := 0.39415135;
  357. node16[12] := 0.29918001; node16[13] := 0.20119409; node16[14] := 0.10114207; node16[15] := 0.0;
  358. wgtGauss8[0] := 0.030753242; wgtGauss8[1] := 0.070366047; wgtGauss8[2] := 0.107159220;
  359. wgtGauss8[3] := 0.139570678; wgtGauss8[4] := 0.166269206; wgtGauss8[5] := 0.186161000;
  360. wgtGauss8[6] := 0.198431485; wgtGauss8[7] := 0.202578242;
  361. wgtKronrod16[0] := 0.005377480; wgtKronrod16[1] := 0.015007947; wgtKronrod16[2] := 0.025460847;
  362. wgtKronrod16[3] := 0.035346361; wgtKronrod16[4] := 0.044589751; wgtKronrod16[5] := 0.053481525;
  363. wgtKronrod16[6] := 0.062009568; wgtKronrod16[7] := 0.069854121; wgtKronrod16[8] := 0.076849681;
  364. wgtKronrod16[9] := 0.083080503; wgtKronrod16[10] := 0.088564443; wgtKronrod16[11] := 0.093126598;
  365. wgtKronrod16[12] := 0.096642727; wgtKronrod16[13] := 0.099173599; wgtKronrod16[14] := 0.100769846;
  366. wgtKronrod16[15] := 0.101330007;
  367. (* For Fine integration *)
  368. NEW( node31, 31 ); NEW( wgtGauss15, 15 ); NEW( wgtKronrod31, 31 );
  369. node31[0] := 0.999484410; node31[1] := 0.996893484; node31[2] := 0.991630997; node31[3] := 0.983668123;
  370. node31[4] := 0.973116323; node31[5] := 0.960021865; node31[6] := 0.944374445; node31[7] := 0.926200047;
  371. node31[8] := 0.905573308; node31[9] := 0.882560536; node31[10] := 0.857205234; node31[11] := 0.829565762;
  372. node31[12] := 0.799727836; node31[13] := 0.767777432; node31[14] := 0.733790062; node31[15] := 0.697850495;
  373. node31[16] := 0.660061064; node31[17] := 0.620526183; node31[18] := 0.579345236; node31[19] := 0.536624148;
  374. node31[20] := 0.492480468; node31[21] := 0.447033770; node31[22] := 0.400401255; node31[23] := 0.352704726;
  375. node31[24] := 0.304073202; node31[25] := 0.254636926; node31[26] := 0.204525117; node31[27] := 0.153869914;
  376. node31[28] := 0.102806938; node31[29] := 0.051471843; node31[30] := 0.0;
  377. wgtGauss15[0] := 0.007968192; wgtGauss15[1] := 0.018466468; wgtGauss15[2] := 0.028784708;
  378. wgtGauss15[3] := 0.038799193; wgtGauss15[4] := 0.048402673; wgtGauss15[5] := 0.057493156;
  379. wgtGauss15[6] := 0.065974230; wgtGauss15[7] := 0.073755975; wgtGauss15[8] := 0.080755895;
  380. wgtGauss15[9] := 0.086899787; wgtGauss15[10] := 0.092122522; wgtGauss15[11] := 0.096368737;
  381. wgtGauss15[12] := 0.099593421; wgtGauss15[13] := 0.101762390; wgtGauss15[14] := 0.102852653;
  382. wgtKronrod31[0] := 0.001389014; wgtKronrod31[1] := 0.003890461; wgtKronrod31[2] := 0.006630704;
  383. wgtKronrod31[3] := 0.009273280; wgtKronrod31[4] := 0.011823015; wgtKronrod31[5] := 0.014369730;
  384. wgtKronrod31[6] := 0.016920889; wgtKronrod31[7] := 0.019414141; wgtKronrod31[8] := 0.021828036;
  385. wgtKronrod31[9] := 0.024191162; wgtKronrod31[10] := 0.026509955; wgtKronrod31[11] := 0.028754049;
  386. wgtKronrod31[12] := 0.030907258; wgtKronrod31[13] := 0.032981447; wgtKronrod31[14] := 0.034979338;
  387. wgtKronrod31[15] := 0.036882365; wgtKronrod31[16] := 0.038678946; wgtKronrod31[17] := 0.040374539;
  388. wgtKronrod31[18] := 0.041969810; wgtKronrod31[19] := 0.043452540; wgtKronrod31[20] := 0.044814800;
  389. wgtKronrod31[21] := 0.046059238; wgtKronrod31[22] := 0.047185547; wgtKronrod31[23] := 0.048185862;
  390. wgtKronrod31[24] := 0.049055435; wgtKronrod31[25] := 0.049795683; wgtKronrod31[26] := 0.050405921;
  391. wgtKronrod31[27] := 0.050881796; wgtKronrod31[28] := 0.051221548; wgtKronrod31[29] := 0.051426129;
  392. wgtKronrod31[30] := 0.051494729
  393. (* Or, whenever NbrRe.Real is a 64-bit real, use the following eonstants. *)
  394. (* (* For Coarse integration *)
  395. NEW( node8, 8 ); NEW( wgtGauss4, 4 ); NEW( wgtKronrod8, 8 ); node8[0] := 0.99145537112081263920D0;
  396. node8[1] := 0.94910791234275852452D0; node8[2] := 0.86486442335976907278D0;
  397. node8[3] := 0.74153118559939443986D0; node8[4] := 0.58608723546769113029D0;
  398. node8[5] := 0.40584515137739716690D0; node8[6] := 0.20778495500789846760D0;
  399. node8[7] := 0.00000000000000000000D0; wgtGauss4[0] := 0.12948496616886969327D0;
  400. wgtGauss4[1] := 0.27970539148927666790D0; wgtGauss4[2] := 0.38183005050511894495D0;
  401. wgtGauss4[3] := 0.41795918367346938775D0; wgtKronrod8[0] := 0.02293532201052922496D0;
  402. wgtKronrod8[1] := 0.06309209262997855329D0; wgtKronrod8[2] := 0.10479001032225018383D0;
  403. wgtKronrod8[3] := 0.14065325971552591874D0; wgtKronrod8[4] := 0.16900472663926790282D0;
  404. wgtKronrod8[5] := 0.19035057806478540991D0; wgtKronrod8[6] := 0.20443294007529889241D0;
  405. wgtKronrod8[7] := 0.20948214108472782801D0;
  406. (* For Medium integration *)
  407. NEW( node16, 16 ); NEW( wgtGauss8, 8 ); NEW( wgtKronrod16, 16 );
  408. node16[0] := 0.99800229869339706028D0; node16[1] := 0.98799251802048542848D0;
  409. node16[2] := 0.96773907567913913425D0; node16[3] := 0.93727339240070590430D0;
  410. node16[4] := 0.89726453234408190088D0; node16[5] := 0.84820658341042721620D0;
  411. node16[6] := 0.79041850144246593296D0; node16[7] := 0.72441773136017004741D0;
  412. node16[8] := 0.65099674129741697053D0; node16[9] := 0.57097217260853884753D0;
  413. node16[10] := 0.48508186364023968069D0; node16[11] := 0.39415134707756336989D0;
  414. node16[12] := 0.29918000715316881216D0; node16[13] := 0.20119409399743452230D0;
  415. node16[14] := 0.10114206691871749902D0; node16[15] := 0.00000000000000000000D0;
  416. wgtGauss8[0] := 0.03075324199611726835D0; wgtGauss8[1] := 0.07036604748810812470D0;
  417. wgtGauss8[2] := 0.10715922046717193501D0; wgtGauss8[3] := 0.13957067792615431444D0;
  418. wgtGauss8[4] := 0.16626920581699393355D0; wgtGauss8[5] := 0.18616100001556221102D0;
  419. wgtGauss8[6] := 0.19843148532711157645D0; wgtGauss8[7] := 0.20257824192556127288D0;
  420. wgtKronrod16[0] := 0.00537747987292334898D0; wgtKronrod16[1] := 0.01500794732931612253D0;
  421. wgtKronrod16[2] := 0.02546084732671532018D0; wgtKronrod16[3] := 0.03534636079137584622D0;
  422. wgtKronrod16[4] := 0.04458975132476487660D0; wgtKronrod16[5] := 0.05348152469092808726D0;
  423. wgtKronrod16[6] := 0.06200956780067064028D0; wgtKronrod16[7] := 0.06985412131872825870D0;
  424. wgtKronrod16[8] := 0.07684968075772037889D0; wgtKronrod16[9] := 0.08308050282313302103D0;
  425. wgtKronrod16[10] := 0.08856444305621177064D0; wgtKronrod16[11] := 0.09312659817082532122D0;
  426. wgtKronrod16[12] := 0.09664272698362367850D0; wgtKronrod16[13] := 0.09917359872179195933D0;
  427. wgtKronrod16[14] := 0.10076984552387559504D0; wgtKronrod16[15] := 0.10133000701479154901D0;
  428. (* For Fine integration *)
  429. NEW( node31, 31 ); NEW( wgtGauss15, 15 ); NEW( wgtKronrod31, 31 );
  430. node31[0] := 0.99948441005049063757D0; node31[1] := 0.99689348407464954027D0;
  431. node31[2] := 0.99163099687040459485D0; node31[3] := 0.98366812327974720997D0;
  432. node31[4] := 0.97311632250112626837D0; node31[5] := 0.96002186496830751221D0;
  433. node31[6] := 0.94437444474855997941D0; node31[7] := 0.92620004742927432587D0;
  434. node31[8] := 0.90557330769990779854D0; node31[9] := 0.88256053579205268154D0;
  435. node31[10] := 0.85720523354606109895D0; node31[11] := 0.82956576238276839744D0;
  436. node31[12] := 0.79972783582183908301D0; node31[13] := 0.76777743210482619491D0;
  437. node31[14] := 0.73379006245322680472D0; node31[15] := 0.69785049479331579693D0;
  438. node31[16] := 0.66006106412662696137D0; node31[17] := 0.62052618298924286114D0;
  439. node31[18] := 0.57934523582636169175D0; node31[19] := 0.53662414814201989926D0;
  440. node31[20] := 0.49248046786177857499D0; node31[21] := 0.44703376953808917678D0;
  441. node31[22] := 0.40040125483039439253D0; node31[23] := 0.35270472553087811347D0;
  442. node31[24] := 0.30407320227362507737D0; node31[25] := 0.25463692616788984643D0;
  443. node31[26] := 0.20452511668230989143D0; node31[27] := 0.15386991360858354696D0;
  444. node31[28] := 0.10280693796673703014D0; node31[29] := 0.05147184255531769583D0;
  445. node31[30] := 0.00000000000000000000D0; wgtGauss15[0] := 0.00796819249616660561D0;
  446. wgtGauss15[1] := 0.01846646831109095914D0; wgtGauss15[2] := 0.02878470788332336934D0;
  447. wgtGauss15[3] := 0.03879919256962704959D0; wgtGauss15[4] := 0.04840267283059405290D0;
  448. wgtGauss15[5] := 0.05749315621761906648D0; wgtGauss15[6] := 0.06597422988218049512D0;
  449. wgtGauss15[7] := 0.07375597473770520626D0; wgtGauss15[8] := 0.08075589522942021535D0;
  450. wgtGauss15[9] := 0.08689978720108297980D0; wgtGauss15[10] := 0.09212252223778612871D0;
  451. wgtGauss15[11] := 0.09636873717464425963D0; wgtGauss15[12] := 0.09959342058679526706D0;
  452. wgtGauss15[13] := 0.10176238974840550459D0; wgtGauss15[14] := 0.10285265289355884034D0;
  453. wgtKronrod31[0] := 0.00138901369867700762D0; wgtKronrod31[1] := 0.00389046112709988405D0;
  454. wgtKronrod31[2] := 0.00663070391593129217D0; wgtKronrod31[3] := 0.00927327965951776342D0;
  455. wgtKronrod31[4] := 0.01182301525349634174D0; wgtKronrod31[5] := 0.01436972950704580481D0;
  456. wgtKronrod31[6] := 0.01692088918905327262D0; wgtKronrod31[7] := 0.01941414119394238117D0;
  457. wgtKronrod31[8] := 0.02182803582160919229D0; wgtKronrod31[9] := 0.02419116207808060136D0;
  458. wgtKronrod31[10] := 0.02650995488233310161D0; wgtKronrod31[11] := 0.02875404876504129284D0;
  459. wgtKronrod31[12] := 0.03090725756238776247D0; wgtKronrod31[13] := 0.03298144705748372603D0;
  460. wgtKronrod31[14] := 0.03497933802806002413D0; wgtKronrod31[15] := 0.03688236465182122922D0;
  461. wgtKronrod31[16] := 0.03867894562472759295D0; wgtKronrod31[17] := 0.04037453895153595911D0;
  462. wgtKronrod31[18] := 0.04196981021516424614D0; wgtKronrod31[19] := 0.04345253970135606931D0;
  463. wgtKronrod31[20] := 0.04481480013316266319D0; wgtKronrod31[21] := 0.04605923827100698811D0;
  464. wgtKronrod31[22] := 0.04718554656929915394D0; wgtKronrod31[23] := 0.04818586175708712914D0;
  465. wgtKronrod31[24] := 0.04905543455502977888D0; wgtKronrod31[25] := 0.04979568342707420635D0;
  466. wgtKronrod31[26] := 0.05040592140278234684D0; wgtKronrod31[27] := 0.05088179589874960649D0;
  467. wgtKronrod31[28] := 0.05122154784925877217D0; wgtKronrod31[29] := 0.05142612853745902593D0;
  468. wgtKronrod31[30] := 0.05149472942945156755D0 *)
  469. END Quadrature;
  470. BEGIN
  471. Quadrature; MaxIntervals := NbrInt.MaxNbr
  472. END CalcGauss.