Numerical integration: Difference between revisions
Content added Content deleted
Line 642: | Line 642: | ||
end |
end |
||
end.</syntaxhighlight> |
end.</syntaxhighlight> |
||
=={{header|ATS}}== |
|||
<syntaxhighlight lang="ats"> |
|||
#include "share/atspre_staload.hats" |
|||
%{^ |
|||
#include <math.h> |
|||
%} |
|||
typedef FILEstar = $extype"FILE *" |
|||
extern castfn FILEref2star : FILEref -<> FILEstar |
|||
(* This type declarations is for composite quadrature functions for |
|||
all the different g0float typekinds. The function must either prove |
|||
termination or mask the requirement. (All of ours will prove |
|||
termination.) The function to be integrated will not be passed as |
|||
an argument, but inlined via the template mechanism. (This design |
|||
is more general. It can easily be used to write a quadrature |
|||
function that takes the argument, but also can be used for faster |
|||
code that requires no function call.) *) |
|||
typedef composite_quadrature (tk : tkind) = |
|||
(g0float tk, g0float tk, intGte 2) -<> g0float tk |
|||
extern fn {tk : tkind} |
|||
composite_quadrature$func : g0float tk -<> g0float tk |
|||
extern fn {tk : tkind} left_rule : composite_quadrature tk |
|||
extern fn {tk : tkind} right_rule : composite_quadrature tk |
|||
extern fn {tk : tkind} midpoint_rule : composite_quadrature tk |
|||
extern fn {tk : tkind} trapezium_rule : composite_quadrature tk |
|||
extern fn {tk : tkind} simpson_rule : composite_quadrature tk |
|||
extern fn {tk : tkind} |
|||
_one_point_rule$init_x : |
|||
g0float tk -<> g0float tk |
|||
fn {tk : tkind} |
|||
_one_point_rule : composite_quadrature tk = |
|||
lam (a, b, n) => |
|||
let |
|||
prval [n : int] EQINT () = eqint_make_gint n |
|||
macdef f = composite_quadrature$func |
|||
val h = (b - a) / g0i2f n |
|||
val x0 = _one_point_rule$init_x<tk> h |
|||
fun |
|||
loop {i : nat | i <= n} .<n - i>. |
|||
(i : int i, |
|||
sum : g0float tk) :<> g0float tk = |
|||
if i = n then |
|||
sum |
|||
else |
|||
loop (succ i, sum + f(x0 + (g0i2f i * h))) |
|||
in |
|||
loop (0, g0i2f 0) * h |
|||
end |
|||
(* The left rule, for any floating point type. *) |
|||
implement {tk} |
|||
left_rule (a, b, n) = |
|||
let |
|||
implement _one_point_rule$init_x<tk> _ = a |
|||
in |
|||
_one_point_rule<tk> (a, b, n) |
|||
end |
|||
(* The right rule, for any floating point type. *) |
|||
implement {tk} |
|||
right_rule (a, b, n) = |
|||
let |
|||
implement _one_point_rule$init_x<tk> h = a + h |
|||
in |
|||
_one_point_rule<tk> (a, b, n) |
|||
end |
|||
(* The midpoint rule, for any floating point type. *) |
|||
implement {tk} |
|||
midpoint_rule (a, b, n) = |
|||
let |
|||
implement _one_point_rule$init_x<tk> h = a + (h / g0i2f 2) |
|||
in |
|||
_one_point_rule<tk> (a, b, n) |
|||
end |
|||
implement {tk} |
|||
trapezium_rule : composite_quadrature tk = |
|||
lam (a, b, n) => |
|||
let |
|||
prval [n : int] EQINT () = eqint_make_gint n |
|||
macdef f = composite_quadrature$func |
|||
val h = (b - a) / g0i2f n |
|||
fun |
|||
loop {i : pos | i <= n} .<n - i>. |
|||
(i : int i, |
|||
sum : g0float tk) :<> g0float tk = |
|||
if i = n then |
|||
sum |
|||
else |
|||
loop (succ i, sum + f(a + (g0i2f i * h))) |
|||
val sum = loop (1, g0i2f 0) |
|||
in |
|||
((f(a) + sum + sum + f(b)) * h) / g0i2f 2 |
|||
end |
|||
(* Simpson’s 1/3 rule, for any floating point type. *) |
|||
implement {tk} |
|||
simpson_rule : composite_quadrature tk = |
|||
lam (a, b, n) => |
|||
let |
|||
(* I have noticed that the Simpson rule is a weighted average of |
|||
the trapezium and midpoint rules, which themselves evaluate |
|||
the function at different points. Therefore, the following |
|||
should be efficient and produce good results. *) |
|||
val estimate1 = trapezium_rule<tk> (a, b, n) |
|||
val estimate2 = midpoint_rule<tk> (a, b, n) |
|||
in |
|||
(estimate1 + estimate2 + estimate2) / (g0i2f 3) |
|||
end |
|||
extern fn {tk : tkind} |
|||
fprint_result$rule : composite_quadrature tk |
|||
extern fn {tk : tkind} |
|||
fprint_result (outf : FILEref, |
|||
message : string, |
|||
a : g0float tk, |
|||
b : g0float tk, |
|||
n : intGte 2, |
|||
nominal : g0float tk) : void |
|||
implement |
|||
fprint_result<dblknd> (outf, message, a, b, n, nominal) = |
|||
let |
|||
val integral = fprint_result$rule<dblknd> (a, b, n) |
|||
in |
|||
fprint! (outf, " ", message, " "); |
|||
ignoret ($extfcall (int, "fprintf", FILEref2star outf, |
|||
"%18.15le", integral)); |
|||
fprint! (outf, " (nominal + "); |
|||
ignoret ($extfcall (int, "fprintf", FILEref2star outf, |
|||
"% .6le", integral - nominal)); |
|||
fprint! (outf, ")\n") |
|||
end |
|||
fn {tk : tkind} |
|||
fprint_rule_results (outf : FILEref, |
|||
a : g0float tk, |
|||
b : g0float tk, |
|||
n : intGte 2, |
|||
nominal : g0float tk) : void = |
|||
let |
|||
implement fprint_result$rule<tk> (a, b, n) = left_rule<tk> (a, b, n) |
|||
val () = fprint_result (outf, "left rule ", a, b, n, nominal) |
|||
implement fprint_result$rule<tk> (a, b, n) = right_rule<tk> (a, b, n) |
|||
val () = fprint_result (outf, "right rule ", a, b, n, nominal) |
|||
implement fprint_result$rule<tk> (a, b, n) = midpoint_rule<tk> (a, b, n) |
|||
val () = fprint_result (outf, "midpoint rule ", a, b, n, nominal) |
|||
implement fprint_result$rule<tk> (a, b, n) = trapezium_rule<tk> (a, b, n) |
|||
val () = fprint_result (outf, "trapezium rule ", a, b, n, nominal) |
|||
implement fprint_result$rule<tk> (a, b, n) = simpson_rule<tk> (a, b, n) |
|||
val () = fprint_result (outf, "Simpson rule ", a, b, n, nominal) |
|||
in |
|||
end |
|||
implement |
|||
main () = |
|||
let |
|||
val outf = stdout_ref |
|||
val () = fprint! (outf, "\nx³ in [0,1] with n = 100\n") |
|||
implement composite_quadrature$func<dblknd> x = x * x * x |
|||
val () = fprint_rule_results<dblknd> (outf, 0.0, 1.0, 100, 0.25) |
|||
val () = fprint! (outf, "\n1/x in [1,100] with n = 1000\n") |
|||
implement composite_quadrature$func<dblknd> x = g0i2f 1 / x |
|||
val () = fprint_rule_results<dblknd> (outf, 1.0, 100.0, 1000, |
|||
$extfcall (double, "log", 100.0)) |
|||
val () = fprint! (outf, "\nx in [0,5000] with n = 5000000\n") |
|||
implement composite_quadrature$func<dblknd> x = x |
|||
val () = fprint_rule_results<dblknd> (outf, 0.0, 5000.0, 5000000, |
|||
12500000.0) |
|||
val () = fprint! (outf, "\nx in [0,6000] with n = 6000000\n") |
|||
implement composite_quadrature$func<dblknd> x = x |
|||
val () = fprint_rule_results<dblknd> (outf, 0.0, 6000.0, 6000000, |
|||
18000000.0) |
|||
val () = fprint! (outf, "\n") |
|||
in |
|||
0 |
|||
end |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre>$ patscc -std=gnu2x -Ofast numerical_integration_task.dats -lm && ./a.out |
|||
x³ in [0,1] with n = 100 |
|||
left rule 2.450250000000000e-01 (nominal + -4.975000e-03) |
|||
right rule 2.550250000000000e-01 (nominal + 5.025000e-03) |
|||
midpoint rule 2.499875000000000e-01 (nominal + -1.250000e-05) |
|||
trapezium rule 2.500250000000000e-01 (nominal + 2.500000e-05) |
|||
Simpson rule 2.500000000000000e-01 (nominal + 0.000000e+00) |
|||
1/x in [1,100] with n = 1000 |
|||
left rule 4.654991057514675e+00 (nominal + 4.982087e-02) |
|||
right rule 4.556981057514675e+00 (nominal + -4.818913e-02) |
|||
midpoint rule 4.604762548678376e+00 (nominal + -4.076373e-04) |
|||
trapezium rule 4.605986057514674e+00 (nominal + 8.158715e-04) |
|||
Simpson rule 4.605170384957142e+00 (nominal + 1.989691e-07) |
|||
x in [0,5000] with n = 5000000 |
|||
left rule 1.249999750000000e+07 (nominal + -2.500000e+00) |
|||
right rule 1.250000250000000e+07 (nominal + 2.500000e+00) |
|||
midpoint rule 1.250000000000000e+07 (nominal + 0.000000e+00) |
|||
trapezium rule 1.250000000000000e+07 (nominal + -1.862645e-09) |
|||
Simpson rule 1.250000000000000e+07 (nominal + 0.000000e+00) |
|||
x in [0,6000] with n = 6000000 |
|||
left rule 1.799999700000000e+07 (nominal + -3.000000e+00) |
|||
right rule 1.800000300000000e+07 (nominal + 3.000000e+00) |
|||
midpoint rule 1.800000000000000e+07 (nominal + 0.000000e+00) |
|||
trapezium rule 1.800000000000000e+07 (nominal + 0.000000e+00) |
|||
Simpson rule 1.800000000000000e+07 (nominal + 0.000000e+00) |
|||
</pre> |
|||
=={{header|AutoHotkey}}== |
=={{header|AutoHotkey}}== |