MathErf.Mod 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. (* CAPO - Computational Analysis Platform for Oberon - by Alan Freed and Felix Friedrich. *)
  2. (* Version 1, Update 2 *)
  3. MODULE MathErf; (** AUTHOR "adf"; PURPOSE "The error function: erf(x) = (2/Vp) x0x exp(-t2) dt"; *)
  4. (* To change to 64-bit reals, address the code fragments written in light red. *)
  5. (* Ref: J.F. Hart, E.W. Cheney, C.L. Lawson, H.J. Maehly, C.K. Mesztenyi, J.R. Rice, H.G. Thacher, Jr., and C. Witzgall,
  6. "Computer Approximations," in: The SIAM Series in Applied MathLematics, Wiley, New York, 1968. *)
  7. IMPORT NbrInt, NbrRe, DataErrors, MathRe, MathReSeries;
  8. VAR
  9. maxIterations: NbrInt.Integer; twoBySqrtPi: NbrRe.Real;
  10. (* Whenever NbrRe.Real is a 32-bit real, define the following arrays. *)
  11. erfcP1: ARRAY 3 OF NbrRe.Real;
  12. erfcP, erfcQ1: ARRAY 4 OF NbrRe.Real;
  13. erfcQ: ARRAY 5 OF NbrRe.Real;
  14. (* Or whenever NbrRe.Real is a 64-bit real, define the following arrays. *)
  15. (* erfcP1: ARRAY 6 OF NbrRe.Real;
  16. erfcP, erfcQ1: ARRAY 7 OF NbrRe.Real;
  17. erfcQ: ARRAY 8 OF NbrRe.Real; *)
  18. TYPE
  19. ErfP = OBJECT (MathReSeries.Coefficient)
  20. PROCEDURE Evaluate*;
  21. VAR m: NbrInt.Integer;
  22. BEGIN
  23. IF n = 0 THEN coef := 0
  24. ELSIF n = 1 THEN coef := 1
  25. ELSE
  26. coef := 2 * (n - 1) * x; m := n + 1;
  27. IF NbrInt.Odd( m ) THEN coef := -coef END
  28. END;
  29. IF n > maxIterations THEN eos := TRUE; DataErrors.ReWarning( x, "Did not converge - timed out." ) END
  30. END Evaluate;
  31. END ErfP;
  32. ErfQ = OBJECT (MathReSeries.Coefficient)
  33. PROCEDURE Evaluate*;
  34. BEGIN
  35. IF n = 0 THEN coef := 0
  36. ELSIF n = 1 THEN coef := 1
  37. ELSE coef := 1 + 2 * (n - 1)
  38. END
  39. END Evaluate;
  40. END ErfQ;
  41. PROCEDURE Erfc( x: NbrRe.Real ): NbrRe.Real;
  42. VAR max: NbrInt.Integer; erfc: NbrRe.Real;
  43. BEGIN
  44. max := 26; (* Asymptote reached by this value. *)
  45. IF x > max THEN erfc := 0
  46. ELSIF x < -max THEN erfc := 2
  47. ELSE
  48. IF NbrRe.Abs( x ) > 9 THEN
  49. erfc := MathReSeries.TruncatedRationalFunction( erfcP1, erfcQ1, NbrRe.Abs( x ) )
  50. ELSE erfc := MathReSeries.TruncatedRationalFunction( erfcP, erfcQ, NbrRe.Abs( x ) )
  51. END;
  52. erfc := erfc * NbrRe.Exp( -x * x );
  53. IF x < 0 THEN erfc := 2 - erfc END
  54. END;
  55. RETURN erfc
  56. END Erfc;
  57. PROCEDURE Fn*( x: NbrRe.Real ): NbrRe.Real;
  58. VAR erf: NbrRe.Real; p: ErfP; q: ErfQ;
  59. BEGIN
  60. IF NbrRe.Abs( x ) > 0.1 THEN erf := 1 - Erfc( x )
  61. ELSE
  62. NEW( p ); NEW( q );
  63. erf := twoBySqrtPi * MathRe.Exp( -x * x ) * MathReSeries.ContinuedFraction( p, q, x )
  64. END;
  65. RETURN erf
  66. END Fn;
  67. (*
  68. PROCEDURE CplxFn*( z: NbrCplx.Complex ): NbrCplx.Complex;
  69. VAR
  70. BEGIN
  71. END CplxFn;
  72. *)
  73. BEGIN
  74. maxIterations := 1000; twoBySqrtPi := 2 / MathRe.Sqrt( NbrRe.Pi );
  75. (* Whenever NbrRe.Real is a 32-bit real, use the following eonstants. *)
  76. (* Constants from Table ERFC 5663 from "Computer Approximations". *)
  77. erfcP[0] := 1.000464117E1; erfcP[1] := 8.426552865; erfcP[2] := 3.460259332; erfcP[3] := 5.623536121E-1;
  78. erfcQ[0] := 1.000464117E1; erfcQ[1] := 1.971558074E1; erfcQ[2] := 1.570228809E1; erfcQ[3] := 6.090748787;
  79. erfcQ[4] := 1.0;
  80. (* Constants from Table ERFC 5722 from "Computer Approximations". *)
  81. erfcP1[0] := 6.141050179E-1; erfcP1[1] := 3.295899049E-1; erfcP1[2] := 5.641895902E-1;
  82. erfcQ1[0] := 2.953483222E-1; erfcQ1[1] := 1.588352760; erfcQ1[2] := 5.841849230E-1; erfcQ1[3] := 1.0
  83. (* Or, whenever NbrRe.Real is a 64-bit real, use the following eonstants. *)
  84. (* (* Constants from Table ERFC 5666 from "Computer Approximations". *)
  85. erfcP[0] := 4.4041373582475223325269D2; erfcP[1] := 6.25686535769683006135193D2;
  86. erfcP[2] := 4.483171659914834429345063D2; erfcP[3] := 1.9184014058796685752390301D2;
  87. erfcP[4] := 5.0991697628253203795669523D1; erfcP[5] := 7.9239298287415448527194039D0;
  88. erfcP[6] := 0.56419994559825748305038673D0; erfcQ[0] := 4.4041373582475221430599D2;
  89. erfcQ[1] := 1.122640220177046578853681D3; erfcQ[2] := 1.2746672667576622866580268D3;
  90. erfcQ[3] := 8.3881036547840644197941778D2; erfcQ[4] := 3.47122928811784331429078057D2;
  91. erfcQ[5] := 9.08727112035370362595507371D1; erfcQ[6] := 1.404533730546113829847322587D1;
  92. erfcQ[7] := 1.0D0;
  93. (* Constants from Table ERFC 5725 from "Computer Approximations". *)
  94. erfcP1[0] := 2.9788656263939928862D0; erfcP1[1] := 7.409740605964741794425D0;
  95. erfcP1[2] := 6.1602098531096305440906D0; erfcP1[3] := 5.019049726784267463450058D0;
  96. erfcP1[4] := 1.275366644729965952479585264D0; erfcP1[5] := 0.5641895835477550741253201704D0;
  97. erfcQ1[0] := 3.3690752069827527677D0; erfcQ1[1] := 9.608965327192787870698D0;
  98. erfcQ1[2] := 1.708144074746600431571095D1; erfcQ1[3] := 1.20489519278551290360340491D1;
  99. erfcQ1[4] := 9.396034016235054150430579648D0; erfcQ1[5] := 2.260528520767326969591866945D0;
  100. erfcQ1[6] := 1.0D0 *)
  101. END MathErf.