Numerical integration/Adaptive Simpson's method: Difference between revisions

Added FreeBASIC
(Added FreeBASIC)
(48 intermediate revisions by 5 users not shown)
Line 10:
|-
|
''; Lyness's ASRAdaptive Simpson's Rule, Modifications 1, 2, 3''
'''procedure''' _quad_asr_simpsonssimpson_rule(f, a, fa, b, fb)
m := (a + b) / 2
fm := f(m)
h := b - a
'''return multiple''' [m, fm, (h / 6) * (f(a)fa + 4*fm + f(b)fb)]
'''procedure''' _quad_asrrecursive_simpson(f, a, fa, b, fb, tol, whole, m, fm, depth)
lm, flm, left := _quad_asr_simpsonssimpson_rule(f, a, fa, m, fm)
rm, frm, right := _quad_asr_simpsonssimpson_rule(f, m, fm, b, fb)
delta := left + right - whole
tol' := tol / 2
'''if''' depth <= 0 ''or'' tol' == tol ''or'' abs(delta) <= 15 * tol:
'''return''' left + right + (delta / 15)
'''else''':
'''return''' _quad_asrrecursive_simpson(f, a, fa, m, fm, tol', left , lm, flm, depth - 1) +
_quad_asrrecursive_simpson(f, m, fm, b, fb, tol', right, rm, frm, depth - 1)
'''procedure''' quad_asr(f, a, b, tol, depth)
fa := f(a)
fb := f(b)
m, fm, whole := _quad_asr_simpsonssimpson_rule(f, a, fa, b, fb)
'''return''' _quad_asrrecursive_simpson(f, a, fa, b, fb, tol, whole, m, fm, depth)
|}
 
Line 84 ⟶ 83:
Simpson's integration of sine from 0 to 1 = 0.459697694
</pre>
 
=={{header|Ada}}==
 
<syntaxhighlight lang="ada">
with ada.text_io; use ada.text_io;
with ada.numerics; use ada.numerics;
 
with ada.numerics.elementary_functions;
use ada.numerics.elementary_functions;
 
procedure adaptive_simpson_task is
 
subtype flt is float;
type function_flt_to_flt is
access function (x : in flt) return flt;
 
procedure simpson_rule (f : in function_flt_to_flt;
a, fa, b, fb : in flt;
m, fm, quadval : out flt) is
begin
m := 0.5 * (a + b);
fm := f(m);
quadval := ((b - a) / 6.0) * (fa + (4.0 * fm) + fb);
end;
 
function recursive_simpson (f : in function_flt_to_flt;
a, fa, b, fb : in flt;
tol, whole, m, fm : in flt;
depth : in integer) return flt is
lm, flm, left : flt;
rm, frm, right : flt;
diff, tol2, quadval : flt;
begin
simpson_rule (f, a, fa, m, fm, lm, flm, left);
simpson_rule (f, m, fm, b, fb, rm, frm, right);
diff := left + right - whole;
tol2 := 0.5 * tol;
if depth <= 0 or tol2 = tol or abs (diff) <= 15.0 * tol then
quadval := left + right + (diff / 15.0);
else
quadval := recursive_simpson (f, a, fa, m, fm, tol2,
left, lm, flm, depth - 1)
+ recursive_simpson (f, m, fm, b, fb, tol2,
right, rm, frm, depth - 1);
end if;
return quadval;
end;
 
function quad_asr (f : in function_flt_to_flt;
a, b, tol : in flt;
depth : in integer) return flt is
fa, fb, m, fm, whole : flt;
begin
fa := f(a);
fb := f(b);
simpson_rule (f, a, fa, b, fb, m, fm, whole);
return recursive_simpson (f, a, fa, b, fb, tol,
whole, m, fm, depth);
end;
 
function sine (x : in flt) return flt is
begin
return sin (x);
end;
 
quadval : flt;
 
begin
quadval := quad_asr (sine'access, 0.0, 1.0, 1.0e-5, 100);
put ("estimate of ∫ sin x dx from 0 to 1:");
put_line (quadval'image);
end;
 
-- local variables:
-- mode: indented-text
-- tab-width: 2
-- end:
</syntaxhighlight>
 
{{out}}
<pre>$ gnatmake -q adaptive_simpson_task.adb && ./adaptive_simpson_task
estimate of ∫ sin x dx from 0 to 1: 4.59698E-01</pre>
 
=={{header|ALGOL 60}}==
{{works with|GNU MARST|2.7}}
 
<syntaxhighlight lang="algol60">
procedure simpsonrule (f, a, fa, b, fb, m, fm, quadval);
value a, fa, b, fb;
real procedure f;
real a, fa, b, fb, m, fm, quadval;
begin
m := (a + b) / 2;
fm := f(m);
quadval := ((b - a) / 6) * (fa + (4 * fm) + fb)
end simpsonrule;
 
real procedure recursion (f, a, fa, b, fb, tol, whole, m, fm, depth);
value a, fa, b, fb, tol, whole, m, fm, depth;
real procedure f;
real a, fa, b, fb, tol, whole, m, fm;
integer depth;
begin
real lm, flm, left;
real rm, frm, right;
real delta, tol2;
simpsonrule (f, a, fa, m, fm, lm, flm, left);
simpsonrule (f, m, fm, b, fb, rm, frm, right);
delta := left + right - whole;
tol2 := tol / 2;
if depth <= 0 | tol2 = tol | abs (delta) <= 15 * tol then
recursion := left + right + (delta / 15)
else
recursion :=
recursion (f, a, fa, m, fm, tol2, left , lm, flm, depth - 1)
+ recursion (f, m, fm, b, fb, tol2, right, rm, frm, depth - 1)
end recursion;
 
real procedure quadASR (f, a, b, tol, depth);
value a, b, tol, depth;
real procedure f;
real a, b, tol;
integer depth;
begin
real fa, fb, m, fm, whole;
fa := f(a);
fb := f(b);
simpsonrule (f, a, fa, b, fb, m, fm, whole);
quadASR := recursion (f, a, fa, b, fb, tol, whole, m, fm, depth)
end quadASR;
 
begin
real q;
q := quadASR (sin, 0, 1, 0.000000001, 1000);
outstring (1, "estimated definite integral of sin(x) ");
outstring (1, "for x from 0 to 1: ");
outreal (1, q);
outstring (1, "\n")
end
</syntaxhighlight>
 
{{out}}
<pre>$ marst adaptive_simpson_task.algol60 -o adaptive_simpson_task_algol60.c && gcc -g adaptive_simpson_task_algol60.c -lalgol -lm && ./a.out
estimated definite integral of sin(x) for x from 0 to 1: 0.459697694132</pre>
 
=={{header|ALGOL 68}}==
{{Trans|C}}...with the helper routines nested inside the mademain quadrature routine.
<syntaxhighlight lang="algol68">
BEGIN # Numerical integration using an AddaptiveAdaptive Simpson's method #
 
PROC quad asr = ( PROC(REAL)REAL f, REAL a, b, eps )REAL:
Line 135 ⟶ 278:
<pre>
Simpson's integration of sine from 0.000 to 1.000 = 0.459698
</pre>
 
=={{header|ALGOL W}}==
{{Trans|ALGOL 68}} which is
{{Trans|C}}
<syntaxhighlight lang="algolw">
begin % Numerical integration using an Adaptive Simpson's method %
 
real procedure quad_asr ( real procedure f; real value a, b, eps ) ;
begin
record triple ( real mOf, fmOf, simpOf );
 
% "structured" adaptive version, translated from Racket %
reference(triple) procedure quad_simpsons_mem ( real procedure f
; real value a, fa, b, fb
) ;
begin % Evaluates Simpson's Rule, also returning m and f(m) to reuse. %
real m, fm, simp;
m := ( a + b ) / 2;
fm := f( m );
simp := abs ( b - a ) / 6 * ( fa + 4*fm + fb );
triple( m, fm, simp )
end quad_simpsons_mem ;
 
real procedure quad_asr_rec ( real procedure f
; real value a, fa, b, fb, eps, whole, m, fm
) ;
begin
% Efficient recursive implementation of adaptive Simpson's rule. %
% Function values at the start, middle, end of the intervals are retained. %
reference(triple) lt, rt;
real delta;
lt := quad_simpsons_mem( f, a, fa, m, fm );
rt := quad_simpsons_mem( f, m, fm, b, fb );
delta := simpOf(lt) + simpOf(rt) - whole;
if abs delta <= eps * 15
then simpOf(lt) + simpOf(rt) + delta / 15
else quad_asr_rec( f, a, fa, m, fm, eps / 2, simpOf(lt), mOf(lt), fmOf(lt) )
+ quad_asr_rec( f, m, fm, b, fb, eps / 2, simpOf(rt), mOf(rt), fmOf(rt) )
end quad_asr ;
 
real fa, fb;
reference(triple) t;
 
% Integrate f from a to b using ASR with max error of eps. %
fa := f( a );
fb := f( b );
t := quad_simpsons_mem( f, a, fa, b, fb );
quad_asr_rec( f, a, fa, b, fb, eps, simpOf(t), mOf(t), fmOf(t) )
end quad_asr ;
 
real a, b, sinx;
a := 0.0; b := 1.0;
sinx := quad_asr( sin, a, b, 1'-09 );
write( s_w := 0, r_format := "A", r_w := 6, r_d := 3
, "Simpson's integration of sine from ", a, " to ", b, " = "
, r_w := 12, r_d := 8
, sinx
)
end.
</syntaxhighlight>
{{out}}
<pre>
Simpson's integration of sine from 0.000 to 1.000 = 0.45969769
</pre>
 
Line 175 ⟶ 382:
quadrature_by_adaptive_simpson (f, a, b, tol, depth) =
let
(* SomeA shorthandsshorthand. Sometimes you will see typedefs written instead as
instead as "stadef", which is a more general notation. *)
typedef real = g0float tk
typedef real_func = real -> real
 
(* In ATS, you can nest functions inside functions to whatever
depth you like. *)
fn
_quad_asr_simpsons (fa : real_funcreal,
a : real,
fa : real,
b : real,
Line 207 ⟶ 412:
val h = b - a
in
@(m, fm, (h / g0i2f 6) * (f(a)fa + (g0i2f 4 * fm) + f(b)fb))
end
 
Line 222 ⟶ 427:
run out of stack space, etc.). *)
.<depth>.
(fa : real_funcreal,
a : real,
fa : real,
b : real,
Line 238 ⟶ 442:
perhaps it is good as documentation. In some instances it
is REALLY what you want. *)
val @(lm, flm, left) = _quad_asr_simpsons (f, a, fa, m, fm)
and @(rm, frm, right) = _quad_asr_simpsons (f, m, fm, b, fb)
 
val delta = left + right - whole
Line 257 ⟶ 461:
else
let
val left_val = _quad_asr (f, a, fa, m, fm, tol_, left,
lm, flm, depth - 1)
and right_val = _quad_asr (f, m, fm, b, fb, tol_, right,
rm, frm, depth - 1)
in
Line 270 ⟶ 474:
val @(fa, fb) = @(f(a), f(b))
 
val @(m, fm, whole) = _quad_asr_simpsons (f, a, fa, b, fb)
in
_quad_asr (f, a, fa, b, fb, tol, whole, m, fm, depth)
end
 
Line 356 ⟶ 560:
estimate of ∫ sin x dx from 0 to 1, by call to a compiled function: 0.459698
estimate of ∫ sin x dx from 0 to 1, by call to the template: 0.459698</pre>
 
=={{header|AWK}}==
<syntaxhighlight lang="awk">
BEGIN {
printf ("estimate of ∫ sin x dx from 0 to 1: %f\n",
quad_asr(0.0, 1.0, 1.0e-9, 100))
}
 
function f(x)
{
return sin(x)
}
 
function midpoint(a, b)
{
return 0.5 * (a + b)
}
 
function simpson_rule(a, fa, b, fb, fm)
{
return ((b - a) / 6.0) * (fa + (4.0 * fm) + fb)
}
 
function recursive_simpson(a, fa, b, fb, tol, whole, m, fm, depth,
# Local variables:
lm, flm, left,
rm, frm, right,
delta, tol_,
leftval, rightval, quadval)
{
lm = midpoint(a, m)
flm = f(lm)
left = simpson_rule(a, fa, m, fm, flm)
 
rm = midpoint(m, b)
frm = f(rm)
right = simpson_rule(m, fm, b, fb, frm)
 
delta = left + right - whole
tol_ = 0.5 * tol
 
if (depth <= 0 || tol_ == tol || abs(delta) <= 15.0 * tol)
quadval = left + right + (delta / 15.0)
else
{
leftval = recursive_simpson(a, fa, m, fm, tol_,
left, lm, flm, depth - 1)
rightval = recursive_simpson(m, fm, b, fb, tol_,
right, rm, frm, depth - 1)
quadval = leftval + rightval
}
return quadval
}
 
function quad_asr(a, b, tol, depth,
# Local variables:
fa, fb, whole, m, fm)
{
fa = f(a)
fb = f(b)
 
m = midpoint(a, b)
fm = f(m)
whole = simpson_rule(a, fa, b, fb, fm)
 
return recursive_simpson(a, fa, b, fb, tol,
whole, m, fm, depth)
}
 
function abs(x)
{
return (x < 0 ? -x : x)
}
</syntaxhighlight>
 
{{out}}
Just about any modern Awk should work: nawk, mawk, gawk, busybox awk, goawk, etc. But the ancient Old Awk does not work.
<pre>$ nawk -f adaptive_simpson_task.awk
estimate of ∫ sin x dx from 0 to 1: 0.459698</pre>
 
=={{header|C}}==
Line 404 ⟶ 687:
Simpson's integration of sine from 0 to 1 = 0.459698
</pre>
 
=={{header|COBOL}}==
{{works with|GnuCOBOL|3.1.2.0}}
 
Rather than do recursions, I compute the x-intervals iteratively. No attempt is made to avoid recomputing values of sin(x).
 
<syntaxhighlight lang="cobol">
*> -*- mode: cobol -*-
*>
*> I do the computations (except perhaps for the call to the
*> "sin" function) in decimal fixed point.
*>
 
identification division.
program-id. adaptive_simpson_task.
 
data division.
working-storage section.
01 numer picture s9(25). *> 25 decimal digits.
01 denom picture s9(25).
01 numer2 picture s9(25).
01 a picture s9(5)V9(20). *> 5+20 decimal digits.
01 b picture s9(5)V9(20).
01 tol picture s9(5)V9(20).
01 x picture s9(5)V9(20).
01 y picture s9(5)V9(20).
01 x0 picture s9(5)V9(20).
01 y0 picture s9(5)V9(20).
01 x1 picture s9(5)V9(20).
01 y1 picture s9(5)V9(20).
01 x2 picture s9(5)V9(20).
01 y2 picture s9(5)V9(20).
01 x3 picture s9(5)V9(20).
01 y3 picture s9(5)V9(20).
01 x4 picture s9(5)V9(20).
01 y4 picture s9(5)V9(20).
01 ruleval picture s9(5)V9(20).
01 ruleval0 picture s9(5)V9(20).
01 ruleval1 picture s9(5)V9(20).
01 delta picture s9(5)V9(20).
01 abs-delta picture 9(5)V9(20). *> unsigned.
01 tol0 picture s9(5)V9(20).
01 tol1 picture s9(5)V9(20).
01 delta15 picture s9(5)V9(20).
01 stepval picture s9(5)V9(20).
01 quadval picture s9(5)V9(20).
01 result picture -9.9(9).
procedure division.
move 0.0 to a
move 1.0 to b
move 0.000000001 to tol
perform adaptive-quadrature
move quadval to result
display result
stop run.
 
adaptive-quadrature.
move 0 to numer
move 1 to denom
perform until (numer = denom) and (denom = 1)
perform get-interval
perform simpson-rule-thrice
compute delta = ruleval0 + ruleval1 - ruleval
compute abs-delta = delta
compute tol0 = tol * (x4 - x0)
compute tol1 = tol * (x2 - x0)
if (tol1 = tol0) or (abs-delta <= 15 * tol0) then
compute delta15 = delta / 15
compute stepval = ruleval0 + ruleval1 + delta15
compute quadval = quadval + stepval
perform go-to-next-interval
else
perform bisect-current-interval
end-if
end-perform.
 
simpson-rule-thrice.
*> There is no attempt here to minimize the number of
*> recomputations of sin(x).
 
compute x2 = (x0 + x4) / 2
compute x1 = (x0 + x2) / 2
compute x3 = (x2 + x4) / 2
 
compute x = x0
perform compute-function
compute y0 = y
 
compute x = x1
perform compute-function
compute y1 = y
 
compute x = x2
perform compute-function
compute y2 = y
 
compute x = x3
perform compute-function
compute y3 = y
 
compute x = x4
perform compute-function
compute y4 = y
 
compute ruleval = ((x4 - x0) / 6) * (y0 + (4 * y2) + y4)
compute ruleval0 = ((x2 - x0) / 6) * (y0 + (4 * y1) + y2)
compute ruleval1 = ((x4 - x2) / 6) * (y2 + (4 * y3) + y4).
 
bisect-current-interval.
compute numer = numer + numer
compute denom = denom + denom.
 
go-to-next-interval.
compute numer = numer + 1
divide numer by 2 giving numer2
if numer2 + numer2 = numer then
perform until not (numer2 + numer2 = numer)
move numer2 to numer
divide denom by 2 giving denom
divide numer by 2 giving numer2
end-perform
end-if.
 
get-interval.
compute x0 = numer / denom
compute x0 = (a * (1 - x0)) + (b * x0)
compute x4 = (numer + 1) / denom
compute x4 = (a * (1 - x4)) + (b * x4).
 
compute-function.
compute y = function sin (x).
</syntaxhighlight>
 
{{out}}
<pre>$ cobc -std=cobol2014 -x adaptive_simpson_task.cob && ./adaptive_simpson_task
0.459697694</pre>
 
=={{header|Common Lisp}}==
Line 414 ⟶ 834:
;; is no need to return them explicitly as a data structure
;; (though that also could be done).
(values m fm (* (/ h 6) (+ fa (* 4 fm) fb)))))
(+ (funcall f a) (* 4 fm) (funcall f b))))))
 
(defun %%quad-asr (f a fa b fb tol whole m fm depth)
Line 465 ⟶ 884:
auto h = b - a;
return tuple!("m", "fm", "quadval")
(m, fm, (h / 6) * (f(a)fa + 4*fm + f(b)fb));
}
 
Line 531 ⟶ 950:
Simpson's rule integration of sin from 0 to 1 is: 0.4596976941573994
</pre>
 
=={{header|Forth}}==
{{works with|Gforth|0.7.3}}
 
<syntaxhighlight lang="forth">
\ -*- mode: forth -*-
\
\ The following was written for Gforth, using its implementation of
\ local variables and of f=
\
 
Defer f
 
: simpson-rule { F: a F: fa F: b F: fb -- m fm quadval }
a b f+ 0.5e0 f* \ -- m
fdup f \ -- m fm
fdup 4.0e0 f* fa f+ fb f+
b a f- 6.0e0 f/ f* \ -- m fm quadval
;
 
: recursive-simpson
{ F: a F: fa F: b F: fb F: tol F: whole F: m F: fm depth -- quadval }
a fa m fm simpson-rule { F: lm F: flm F: left }
m fm b fb simpson-rule { F: rm F: frm F: right }
left right f+ whole f- { F: delta }
tol 0.5e0 f* { F: tol_ }
depth 0 <=
tol_ tol f= or
delta fabs 15.0e0 tol f* f<= or
if
left right f+ delta 15.0e0 f/ f+
else
a fa m fm tol_ left lm flm depth 1 - recurse
m fm b fb tol_ right rm frm depth 1 - recurse
f+
then
;
 
: quad-asr { F: a F: b F: tol depth -- quadval }
a f { F: fa }
b f { F: fb }
a fa b fb simpson-rule { F: m F: fm F: whole }
a fa b fb tol whole m fm depth recursive-simpson
;
 
:noname fsin ; IS f
 
." estimate of ∫ sin x dx from 0 to 1: "
0.0e0 1.0e0 1.0e-12 100 quad-asr f.
cr
</syntaxhighlight>
 
{{out}}
<pre>$ gforth adaptive_simpson_task.fs -e bye
estimate of ∫ sin x dx from 0 to 1: 0.45969769413186</pre>
 
=={{header|Fortran}}==
<syntaxhighlight lang="Fortran">
program adaptive_simpson_task
implicit none
 
integer, parameter :: dbl = kind (1.0d0)
 
interface
function function_dbl_to_dbl (x) result (y)
import dbl
real(dbl), intent(in) :: x
real(dbl) :: y
end function function_dbl_to_dbl
end interface
 
write (*, 1000) quad_asr (sine, 0.0_dbl, 1.0_dbl, 1E-9_dbl, 1000)
1000 format ("estimated definite integral of sin(x) ", &
& "for x from 0 to 1: ", F15.13)
 
contains
 
function sine (x) result (y)
real(dbl), intent(in) :: x
real(dbl) :: y
 
y = sin (x)
end function sine
 
function quad_asr (f, a, b, tol, depth) result (quadval)
procedure(function_dbl_to_dbl) :: f
real(dbl), intent(in) :: a, b, tol
integer, intent(in) :: depth
real(dbl) :: quadval
 
real(dbl) :: fa, fb, m, fm, whole
 
fa = f(a)
fb = f(b)
call quad_asr_simpsons_ (f, a, fa, b, fb, m, fm, whole)
quadval = quad_asr_ (f, a, fa, b, fb, tol, whole, m, fm, depth)
end function quad_asr
 
recursive function quad_asr_ (f, a, fa, b, fb, tol, whole, &
& m, fm, depth) result (quadval)
procedure(function_dbl_to_dbl) :: f
real(dbl), intent(in) :: a, fa, b, fb, tol, whole, m, fm
integer, intent(in) :: depth
real(dbl) :: quadval
 
real(dbl) :: lm, flm, left
real(dbl) :: rm, frm, right
real(dbl) :: delta, tol_
 
call quad_asr_simpsons_ (f, a, fa, m, fm, lm, flm, left)
call quad_asr_simpsons_ (f, m, fm, b, fb, rm, frm, right)
delta = left + right - whole
tol_ = tol / 2
if (depth <= 0 .or. tol_ == tol .or. abs (delta) <= 15 * tol) then
quadval = left + right + (delta / 15)
else
quadval = quad_asr_ (f, a, fa, m, fm, tol_, left, &
& lm, flm, depth - 1)
quadval = quadval + quad_asr_ (f, m, fm, b, fb, tol_, &
& right, rm, frm, depth - 1)
end if
end function quad_asr_
 
subroutine quad_asr_simpsons_ (f, a, fa, b, fb, m, fm, quadval)
procedure(function_dbl_to_dbl) :: f
real(dbl), intent(in) :: a, fa, b, fb
real(dbl), intent(out) :: m, fm, quadval
 
m = (a + b) / 2
fm = f(m)
quadval = ((b - a) / 6) * (fa + (4 * fm) + fb)
end subroutine quad_asr_simpsons_
 
end program adaptive_simpson_task
</syntaxhighlight>
 
{{out}}
<pre>$ gfortran -O -std=f2018 -fbounds-check -g adaptive_simpson_task.f90 && ./a.out
estimated definite integral of sin(x) for x from 0 to 1: 0.4596976941318</pre>
 
On x86-64, if you leave out the optimizer you get a trampoline:
<pre>$ gfortran -std=f2018 -fbounds-check -g adaptive_simpson_task.f90 && ./a.out
adaptive_simpson_task.f90:20:2:
 
20 | function sine (x) result (y)
| ^
Warning: trampoline generated for nested function ‘sine’ [-Wtrampolines]
/usr/lib/gcc/x86_64-pc-linux-gnu/12/../../../../x86_64-pc-linux-gnu/bin/ld: warning: /tmp/cc2mQOD2.o: requires executable stack (because the .note.GNU-stack section is executable)
estimated definite integral of sin(x) for x from 0 to 1: 0.4596976941318</pre>
 
Such a bit of executable code on the stack often is not allowed on systems hardened against hackers. Otherwise you probably needn't be concerned, even though warnings are being generated both by the compiler ''and'' the linker. :)
 
=={{header|FreeBASIC}}==
{{trans|Wren}}
<syntaxhighlight lang="vbnet">Type QuadSimpsonMem
As Double m, fm, simp
End Type
 
Function quadSimpsonMem(f As Function(As Double) As Double, a As Double, fa As Double, b As Double, fb As Double) As QuadSimpsonMem
Dim As QuadSimpsonMem r
r.m = (a + b) / 2
r.fm = f(r.m)
r.simp = Abs(b - a) / 6 * (fa + 4 * r.fm + fb)
Return r
End Function
 
Function quadAsrRec(f As Function(As Double) As Double, a As Double, fa As Double, b As Double, fb As Double, eps As Double, whole As Double, m As Double, fm As Double) As Double
Dim As QuadSimpsonMem r1 = quadSimpsonMem(f, a, fa, m, fm)
Dim As QuadSimpsonMem r2 = quadSimpsonMem(f, m, fm, b, fb)
Dim As Double delta = r1.simp + r2.simp - whole
If Abs(delta) < eps * 15 Then Return r1.simp + r2.simp + delta / 15
Return quadAsrRec(f, a, fa, m, fm, eps / 2, r1.simp, r1.m, r1.fm) + quadAsrRec(f, m, fm, b, fb, eps / 2, r2.simp, r2.m, r2.fm)
End Function
 
Function quadAsr(f As Function(As Double) As Double, a As Double, b As Double, eps As Double) As Double
Dim As Double fa = f(a), fb = f(b)
Dim As QuadSimpsonMem r = quadSimpsonMem(f, a, fa, b, fb)
Return quadAsrRec(f, a, fa, b, fb, eps, r.simp, r.m, r.fm)
End Function
 
Function sinx(x As Double) As Double
Return Sin(x)
End Function
 
Dim As Double a = 0, b = 1
Dim As Double result = quadAsr(@sinx, a, b, 1e-09)
Print "Simpson's integration of sine from"; a; " to"; b; " ="; result
 
Sleep</syntaxhighlight>
{{out}}
<pre>Simpson's integration of sine from 0 to 1 = 0.4596976941317858</pre>
 
=={{header|Go}}==
Line 582 ⟶ 1,192:
Simpson's integration of sine from 0 to 1 = 0.459698
</pre>
 
=={{header|Icon}}==
<syntaxhighlight lang="icon">
record simpson_result (m, fm, quadval)
 
procedure main ()
write ("estimate of ∫ sin x dx from 0 to 1: ",
quad_asr (sin, 0.0, 1.0, 1E-9, 100))
end
 
procedure quad_asr(f, a, b, tol, depth)
local fa, fb, whole
 
fa := f(a)
fb := f(b)
whole := simpson_rule (f, a, fa, b, fb)
return recursive_simpson(f, a, fa, b, fb, tol, whole.quadval,
whole.m, whole.fm, depth)
end
 
procedure recursive_simpson (f, a, fa, b, fb, tol, whole,
m, fm, depth)
local left, right, delta, tol2
local leftval, rightval, quadval
 
left := simpson_rule (f, a, fa, m, fm)
right := simpson_rule (f, m, fm, b, fb)
delta := left.quadval + right.quadval - whole
tol2 := 0.5 * tol
if depth <= 0 | tol2 = tol | abs (delta) <= 15 * tol then
quadval := left.quadval + right.quadval + (delta / 15)
else
{
leftval := recursive_simpson (f, a, fa, m, fm, tol2,
left.quadval, left.m, left.fm,
depth - 1)
rightval := recursive_simpson (f, m, fm, b, fb, tol2,
right.quadval, right.m, right.fm,
depth - 1)
quadval := leftval + rightval
}
return quadval
end
 
procedure simpson_rule (f, a, fa, b, fb)
local m, fm, quadval
 
m := 0.5 * (a + b)
fm := f(m)
quadval := ((b - a) / 6) * (fa + (4 * fm) + fb)
return simpson_result (m, fm, quadval)
end
</syntaxhighlight>
 
{{out}}
<pre>$ icon adaptive_simpson_task_arizona.icn
estimate of ∫ sin x dx from 0 to 1: 0.4596976941</pre>
 
=={{header|J}}==
Line 729 ⟶ 1,396:
Simpson's rule integration of sin from 0 to 1 is: 0.45969769415739936
</pre>
 
=={{header|K}}==
{{works with|ngn/k}}<syntaxhighlight lang=K>simpsonsRule:{[f;a;b] m: (a+b)%2; h: b-a; m, (h%6)*f[a]+f[b]+4*f[m]}
 
recursiveSimpson:{[f;a;b;tol;whole;m;depth]
(lm;left): simpsonsRule[f;a;m]
(rm;right): simpsonsRule[f;m;b]
delta: left+right-whole
tol2: tol%2
$[(1>depth)|(tol2=tol)|~(15*tol)<delta|-delta
left+right+delta%15
recursiveSimpson[f;a;m;tol2;left;lm;depth-1]+recursiveSimpson[f;m;b;tol2;right;rm;depth-1]]}
 
quadAsr:{[f;a;b;tol;depth]; (m;whole): simpsonsRule[f;a;b]; recursiveSimpson[f;a;b;tol;whole;m;depth]}</syntaxhighlight>
 
<syntaxhighlight lang=K>quadAsr[`sin;0;1;1e-12;100]
0.45969769413186023</syntaxhighlight>
 
=={{header|Kotlin}}==
Line 834 ⟶ 1,518:
(0.45969769413186023) // reference value
</syntaxhighlight>
 
=={{header|Mercury}}==
<syntaxhighlight lang="mercury">
%%% -*- mode: mercury; prolog-indent-width: 2; -*-
 
:- module adaptive_simpson_task_mercury.
 
:- interface.
:- import_module io.
:- pred main(io::di, io::uo) is det.
 
:- implementation.
:- import_module float.
:- import_module int.
:- import_module math.
:- import_module string.
 
:- pred simpson_rule((func(float) = float)::in,
float::in, float::in, float::in, float::in,
float::out, float::out, float::out) is det.
simpson_rule(F, A, FA, B, FB, M, FM, QuadVal) :-
FM = F(M), (M = 0.5 * (A + B)),
(QuadVal = ((B - A) / 6.0) * (FA + (4.0 * FM) + FB)).
 
:- func recursive_simpson(func(float) = float,
float, float, float, float,
float, float, float, float, int) = float.
recursive_simpson(F, A, FA, B, FB, Tol,
Whole, M, FM, Depth) = QuadVal :-
simpson_rule(F, A, FA, M, FM, LM, FLM, Left),
simpson_rule(F, M, FM, B, FB, RM, FRM, Right),
(Left + Right - Whole = Delta),
(0.5 * Tol = Tol_),
(if (Depth =< 0; Tol_ = Tol; abs(Delta) =< 15.0 * Tol)
then (QuadVal = Left + Right + (Delta / 15.0))
else (QuadVal = recursive_simpson(F, A, FA, M, FM, Tol_,
Left, LM, FLM, Depth - 1)
+ recursive_simpson(F, M, FM, B, FB, Tol_,
Right, RM, FRM, Depth - 1))).
 
:- func quad_asr(func(float) = float,
float, float, float, int) = float.
quad_asr(F, A, B, Tol, Depth) = QuadVal :-
F(A) = FA, F(B) = FB,
simpson_rule(F, A, FA, B, FB, M, FM, Whole),
(QuadVal = recursive_simpson(F, A, FA, B, FB, Tol,
Whole, M, FM, Depth)).
 
main(!IO) :-
print("estimate of ∫ sin x dx from 0 to 1: ", !IO),
(QuadVal = quad_asr(sin, 0.0, 1.0, 1.0e-9, 100)),
print(from_float(QuadVal), !IO),
nl(!IO).
 
:- end_module adaptive_simpson_task_mercury.
</syntaxhighlight>
 
{{out}}
<pre>$ mmc --no-verbose-make --make --use-subdirs adaptive_simpson_task_mercury && ./adaptive_simpson_task_mercury
estimate of ∫ sin x dx from 0 to 1: 0.4596976941317858</pre>
 
=={{header|Modula-2}}==
{{works with|GCC|13.1.0}}
 
<syntaxhighlight lang="modula2">
MODULE adaptive_simpson_task_Modula2;
 
(* ISO Modula-2 libraries. *)
IMPORT RealMath;
IMPORT SRealIO;
IMPORT STextIO;
 
TYPE functionReal2Real = PROCEDURE (REAL) : REAL;
 
PROCEDURE simpsonRule (f : functionReal2Real;
a, fa, b, fb : REAL;
VAR m, fm, quadVal : REAL);
BEGIN
m := 0.5 * (a + b);
fm := f(m);
quadVal := ((b - a) / 6.0) * (fa + (4.0 * fm) + fb)
END simpsonRule;
 
PROCEDURE recursiveSimpson (f : functionReal2Real;
a, fa, b, fb, tol, whole, m, fm : REAL;
depth : INTEGER) : REAL;
VAR lm, flm, left : REAL;
rm, frm, right : REAL;
delta, tol2, quadVal : REAL;
BEGIN
simpsonRule (f, a, fa, m, fm, lm, flm, left);
simpsonRule (f, m, fm, b, fb, rm, frm, right);
delta := left + right - whole;
tol2 := 0.5 * tol;
IF (depth <= 0) OR (tol2 = tol) OR (ABS (delta) <= 15.0 * tol) THEN
quadVal := left + right + (delta / 15.0)
ELSE
quadVal := (recursiveSimpson (f, a, fa, m, fm, tol2,
left, lm, flm, depth - 1)
+ recursiveSimpson (f, m, fm, b, fb, tol2,
right, rm, frm, depth - 1))
END;
RETURN quadVal;
END recursiveSimpson;
 
PROCEDURE quadASR (f : functionReal2Real;
a, b, tol : REAL;
depth : INTEGER) : REAL;
VAR fa, fb, m, fm, whole : REAL;
BEGIN
fa := f(a); fb := f(b);
simpsonRule (f, a, fa, b, fb, m, fm, whole);
RETURN recursiveSimpson (f, a, fa, b, fb, tol,
whole, m, fm, depth)
END quadASR;
 
BEGIN
STextIO.WriteString ('estimate of ∫ sin x dx from 0 to 1: ');
SRealIO.WriteReal (quadASR (RealMath.sin, 0.0, 1.0,
0.000000001, 100),
10);
STextIO.WriteLn;
END adaptive_simpson_task_Modula2.
</syntaxhighlight>
 
{{out}}
<pre>$ gm2 -fiso adaptive_simpson_task_Modula2.mod && ./a.out
estimate of ∫ sin x dx from 0 to 1: 0.45969769</pre>
 
=={{header|Nim}}==
Line 841 ⟶ 1,653:
type Func = float -> float
 
funcproc quadSimpsonsMem(f: Func; a, fa, b, fb: float): tuple[m, fm, val: float] =
## Evaluates the Simpson's Rule, also returning m and f(m) to reuse
result.m = (a + b) / 2
Line 847 ⟶ 1,659:
result.val = abs(b - a) * (fa + 4 * result.fm + fb) / 6
 
funcproc quadAsr(f: Func; a, fa, b, fb, eps, whole, m, fm: float): float =
## Efficient recursive implementation of adaptive Simpson's rule.
## Function values at the start, middle, end of the intervals are retained.
Line 859 ⟶ 1,671:
f.quadAsr(m, fm, b, fb, eps / 2, right, rm, frm)
 
funcproc quadAsr(f: Func; a, b, eps: float): float =
## Integrate f from a to b using Adaptive Simpson's Rule with max error of eps.
let fa = f(a)
Line 870 ⟶ 1,682:
{{out}}
<pre>Simpson's integration of sine from 0 to 1 = 0.4596976941317859</pre>
 
=={{header|Oberon-2}}==
{{trans|Modula-2}}
{{works with|Oxford Oberon-2 Compiler|3.3.0}}
 
<syntaxhighlight lang="modula2">
(* -*- mode: Modula2 -*- *)
 
MODULE adaptiveSimpsonTask;
 
IMPORT Math, Out;
 
TYPE functionReal2Real = PROCEDURE (x : REAL) : REAL;
 
PROCEDURE simpsonRule (f : functionReal2Real;
a, fa, b, fb : REAL;
VAR m, fm, quadVal : REAL);
BEGIN
m := 0.5 * (a + b);
fm := f(m);
quadVal := ((b - a) / 6.0) * (fa + (4.0 * fm) + fb)
END simpsonRule;
 
PROCEDURE recursiveSimpson (f : functionReal2Real;
a, fa, b, fb, tol, whole, m, fm : REAL;
depth : INTEGER) : REAL;
VAR lm, flm, left : REAL;
rm, frm, right : REAL;
delta, tol2, quadVal : REAL;
BEGIN
simpsonRule (f, a, fa, m, fm, lm, flm, left);
simpsonRule (f, m, fm, b, fb, rm, frm, right);
delta := left + right - whole;
tol2 := 0.5 * tol;
IF (depth <= 0) OR (tol2 = tol) OR (ABS (delta) <= 15.0 * tol) THEN
quadVal := left + right + (delta / 15.0)
ELSE
quadVal := (recursiveSimpson (f, a, fa, m, fm, tol2,
left, lm, flm, depth - 1)
+ recursiveSimpson (f, m, fm, b, fb, tol2,
right, rm, frm, depth - 1))
END;
RETURN quadVal
END recursiveSimpson;
 
PROCEDURE quadASR (f : functionReal2Real;
a, b, tol : REAL;
depth : INTEGER) : REAL;
VAR fa, fb, m, fm, whole : REAL;
BEGIN
fa := f(a); fb := f(b);
simpsonRule (f, a, fa, b, fb, m, fm, whole);
RETURN recursiveSimpson (f, a, fa, b, fb, tol,
whole, m, fm, depth)
END quadASR;
 
BEGIN
Out.String ('estimate of ∫ sin x dx from 0 to 1: ');
Out.Real (quadASR (Math.Sin, 0.0, 1.0, 0.000001, 100), 7);
Out.Ln
END adaptiveSimpsonTask.
</syntaxhighlight>
 
{{out}}
<pre>$ obc adaptiveSimpsonTask.Mod && ./a.out
estimate of ∫ sin x dx from 0 to 1: 0.459698
</pre>
 
=={{header|ObjectIcon}}==
<syntaxhighlight lang="objecticon">
$encoding UTF-8
 
import
io(write),
util(Math)
 
procedure main ()
write (u"estimate of ∫ sin x dx from 0 to 1: ",
ASR.quadrature (Math.sin, 0.0, 1.0, 1E-9, 100))
end
 
class Simpson_rule ()
public m, fm, quadval
 
public new (f, a, fa, b, fb)
m := 0.5 * (a + b)
fm := f(m)
quadval := ((b - a) / 6) * (fa + (4 * fm) + fb)
return
end
end
 
final abstract class ASR ()
 
public static quadrature (f, a, b, tol, depth)
local fa, fb, whole
 
fa := f(a)
fb := f(b)
whole := Simpson_rule (f, a, fa, b, fb)
return recursive_simpson (f, a, fa, b, fb, tol, whole.quadval,
whole.m, whole.fm, depth)
end
 
private static recursive_simpson (f, a, fa, b, fb, tol, whole,
m, fm, depth)
local left, right, delta, tol2
local leftval, rightval, quadval
 
left := Simpson_rule (f, a, fa, m, fm)
right := Simpson_rule (f, m, fm, b, fb)
delta := left.quadval + right.quadval - whole
tol2 := 0.5 * tol
if depth <= 0 | tol2 = tol | abs (delta) <= 15 * tol then
quadval := left.quadval + right.quadval + (delta / 15)
else
{
leftval := recursive_simpson (f, a, fa, m, fm, tol2,
left.quadval, left.m, left.fm,
depth - 1)
rightval := recursive_simpson (f, m, fm, b, fb, tol2,
right.quadval, right.m, right.fm,
depth - 1)
quadval := leftval + rightval
}
return quadval
end
 
end
</syntaxhighlight>
 
{{out}}
<pre>$ oiscript ./adaptive_simpson_task_oi.icn
estimate of ∫ sin x dx from 0 to 1: 0.4596976941</pre>
 
=={{header|OCaml}}==
Line 878 ⟶ 1,824:
let fm = f m in
let h = b -. a in
(m, fm, (h /. 6.0) *. (f afa +. (4.0 *. fm) +. f bfb))
in
let rec _quad_asr a fa b fb tol whole m fm depth =
Line 906 ⟶ 1,852:
<pre>$ ocaml adaptive_simpson_task.ml
estimated definite integral of sin(x) for x from 0 to 1: 0.459697694132</pre>
 
=={{header|Ol}}==
This program also works with R7RS Scheme implementations that cannot run the [[#Scheme]] implementation.
{{trans|Scheme}}
{{works with|Ol|2.4}}
{{works with|Chibi Scheme|0.10.0}}
 
<syntaxhighlight lang="scheme">
(import (scheme base)
(scheme inexact)
(scheme write))
 
(define (quad-asr f a b tol depth)
(letrec ;; Recursive let, so %%quad-asr can call itself.
((%%quad-asr-simpsons
(lambda (a fa b fb)
(let* ((m (/ (+ a b) 2))
(fm (f m))
(h (- b a)))
;; Scheme supports returning multiple values at
;; once. There is no need to return them explicitly as
;; a data structure (though that also could be done).
(values m fm (* (/ h 6) (+ fa (* 4 fm) fb))))))
(%%quad-asr
(lambda (a fa b fb tol whole m fm depth)
;; The R7RS standard specifies there must be
;; "let-values" and "let*-values" for receiving multiple
;; values. However, I do not want to assume its
;; presence. I will use the most widely supported
;; method, which is "call-with-values". (Typically
;; "let*-values" would be implemented as syntactic sugar
;; for the following.)
(call-with-values
(lambda () (%%quad-asr-simpsons a fa m fm))
(lambda (lm flm left)
(call-with-values
(lambda () (%%quad-asr-simpsons m fm b fb))
(lambda (rm frm right)
(let ((delta (- (+ left right) whole))
(tol^ (/ tol 2)))
(if (or (<= depth 0)
(= tol^ tol)
(<= (abs delta) (* 15 tol)))
(+ left right (/ delta 15))
(+ (%%quad-asr a fa m fm tol^ left
lm flm (- depth 1))
(%%quad-asr m fm b fb tol^ right
rm frm (- depth 1))))))))))))
(let ((fa (f a))
(fb (f b)))
(call-with-values (lambda () (%%quad-asr-simpsons a fa b fb))
(lambda (m fm whole)
(%%quad-asr a fa b fb tol whole m fm depth))))))
 
(display "estimated definite integral of sin(x) for x from 0 to 1: ")
(display (quad-asr sin 0 1 1e-9 1000))
(newline)
</syntaxhighlight>
 
{{out}}
<pre>$ ol adaptive_simpson_task_ol.scm
estimated definite integral of sin(x) for x from 0 to 1: 0.459697694
$ chibi adaptive_simpson_task_ol.scm
estimated definite integral of sin(x) for x from 0 to 1: 0.4596976941317858</pre>
 
[[Gauche Scheme]] can be told to start up with the R7RS default environment, and thus to need ''this'' version of the Scheme program:
 
<pre>$ gosh -r7 adaptive_simpson_task_ol.scm
estimated definite integral of sin(x) for x from 0 to 1: 0.4596976941317858</pre>
 
=={{header|Pascal}}==
{{works with|Free Pascal Compiler|3.2.2}}
 
<syntaxhighlight lang="pascal">
program adaptive_simpson_task;
 
type function_real_to_real = function(value : real) : real;
var fa, fb, m, fm, whole : real;
 
function quad_asr (f : function_real_to_real;
a, b, tol : real;
depth : integer) : real;
 
procedure quad_asr_simpsons_ ( a, fa, b, fb : real;
var m, fm, quadval : real);
begin
m := (a + b) / 2;
fm := f(m);
quadval := ((b - a) / 6) * (fa + (4 * fm) + fb)
end;
 
function quad_asr_ (a, fa, b, fb : real;
tol, whole, m, fm : real;
depth : integer) : real;
var
lm, flm, left : real;
rm, frm, right : real;
delta, tol_ : real;
begin
quad_asr_simpsons_ (a, fa, m, fm, lm, flm, left);
quad_asr_simpsons_ (m, fm, b, fb, rm, frm, right);
delta := left + right - whole;
tol_ := tol / 2;
if (depth <= 0) or (tol_ = tol) or (abs(delta) <= 15 * tol) then
quad_asr_ := left + right + (delta / 15)
else
quad_asr_ := (quad_asr_ (a, fa, m, fm, tol_,
left , lm, flm, depth - 1)
+ quad_asr_ (m, fm, b, fb, tol_,
right, rm, frm, depth - 1))
end;
 
begin
fa := f(a);
fb := f(b);
quad_asr_simpsons_ (a, fa, b, fb, m, fm, whole);
quad_asr := quad_asr_ (a, fa, b, fb, tol, whole, m, fm, depth)
end;
 
function sine (x : real) : real;
begin
sine := sin (x);
end;
 
begin
writeln ('estimated definite integral of sin(x) ',
'for x from 0 to 1: ', quad_asr (@sine, 0, 1, 1e-9, 1000))
end.
</syntaxhighlight>
 
{{out}}
<pre>estimated definite integral of sin(x) for x from 0 to 1: 4.5969769413178579E-001</pre>
 
=={{header|Perl}}==
Line 990 ⟶ 2,068:
<pre>
Simpson's integration of sine from 0 to 1 = 0.459698
</pre>
 
=={{header|PostScript}}==
{{trans|COBOL}}
 
The following program makes little effort to be efficient. It iteratively computes the intervals, rather than do recursions.
 
<syntaxhighlight lang="postscript">
%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox: 0 0 280 30
 
/origstate save def
 
% We have to convert radians to degrees.
/f { 57.29577951308232 mul sin } def
 
/a 0.0 def
/b 1.0 def
/tol 0.000000001 def
 
/bisect-current-interval {
numer 2 mul /numer exch def
denom 2 mul /denom exch def
} def
 
/go-to-next-interval {
numer 1 add /numer exch def
{
numer 2 mod 1 eq { exit } if
numer 2 idiv /numer exch def
denom 2 idiv /denom exch def
} loop
} def
 
/there-are-no-more-intervals {
numer denom eq
denom 1 eq
and
} def
 
/x0 {
numer denom div
dup 1 exch sub
a mul
exch b mul
add
} def
 
/x1 {
x0 0.75 mul
x4 0.25 mul
add
} def
 
/x2 {
x0 0.5 mul
x4 0.5 mul
add
} def
 
/x3 {
x0 0.25 mul
x4 0.75 mul
add
} def
 
/x4 {
numer 1 add denom div
dup 1 exch sub
a mul
exch b mul
add
} def
 
/simpson-rule-thrice {
x0 f /y0 exch def
x1 f /y1 exch def
x2 f /y2 exch def
x3 f /y3 exch def
x4 f /y4 exch def
 
x4 x0 sub 6.0 div /h04 exch def
x2 x0 sub 6.0 div /h02 exch def
x4 x2 sub 6.0 div /h24 exch def
 
y2 4.0 mul y0 add y4 add h04 mul /whole exch def
y1 4.0 mul y0 add y2 add h02 mul /left exch def
y3 4.0 mul y2 add y4 add h24 mul /right exch def
} def
 
/adaptive-simpson {
/numer 0 def
/denom 1 def
/sum 0.0 def
{
there-are-no-more-intervals { exit } if
simpson-rule-thrice
left right add whole sub /delta exch def
x4 x0 sub tol mul /tol0 exch def
x2 x0 sub tol mul /tol1 exch def
tol1 tol0 eq delta abs 15.0 tol0 mul le or
{
left right add delta 15.0 div add
sum add /sum exch def
go-to-next-interval
}
{
bisect-current-interval
} ifelse
} loop
} def
 
/Times-Roman findfont 12 scalefont setfont
10 10 moveto (estimate of integral of sin x dx from 0 to 1: ) show
adaptive-simpson
sum 20 string cvs show
 
showpage
origstate restore
%%EOF
</syntaxhighlight>
 
{{out}}
I ran the program thus:
<pre>magick convert -flatten adaptive_simpson_task.eps adaptive_simpson_task.png</pre>
And obtained:
[[File:Adaptive simpson task EPS.png|none|alt=Output from the PostScript for Adaptive Simpson. It shows 0.459698]]
 
=={{header|Prolog}}==
{{works with|SWI-Prolog|9.1.2}}
{{works with|GNU Prolog|1.5.0}}
 
<syntaxhighlight lang="prolog">
%%% -*- mode: prolog; prolog-indent-width: 2; -*-
 
main :-
quad_asr(sine, 0.0, 1.0, 0.000000001, 1000, QuadVal),
write('estimate of ∫ sin x dx from 0 to 1: '),
write(QuadVal),
write('\n'),
halt.
 
sine(X, Y) :- Y is sin(X).
 
quad_asr(F, A, B, Tol, Depth, QuadVal) :-
call(F, A, FA),
call(F, B, FB),
simpson_rule(F, A, FA, B, FB, M, FM, Whole),
recursive_simpson(F, A, FA, B, FB, Tol, Whole, M, FM, Depth,
QuadVal).
 
recursive_simpson(F, A, FA, B, FB, Tol, Whole, M, FM, Depth,
QuadVal) :-
simpson_rule(F, A, FA, M, FM, LM, FLM, Left),
simpson_rule(F, M, FM, B, FB, RM, FRM, Right),
Delta is (Left + Right - Whole),
Tol_ is (0.5 * Tol),
((Depth > 0,
Tol_ =\= Tol,
AbsDelta is abs(Delta),
Tol15 is (15.0 * Tol),
AbsDelta > Tol15)
-> (Depth_ is Depth - 1,
recursive_simpson(F, A, FA, M, FM, Tol_, Left, LM, FLM,
Depth_, QuadValLeft),
recursive_simpson(F, M, FM, B, FB, Tol_, Right, RM, FRM,
Depth_, QuadValRight),
QuadVal is QuadValLeft + QuadValRight)
; left_right_estimate(Left, Right, Delta, QuadVal)).
 
left_right_estimate(Left, Right, Delta, Estimate) :-
Estimate is Left + Right + (Delta / 15.0).
 
simpson_rule(F, A, FA, B, FB, M, FM, QuadVal) :-
M is (0.5 * (A + B)),
call(F, M, FM),
QuadVal is ((B - A) / 6.0) * (FA + (4.0 * FM) + FB).
 
:- initialization(main).
</syntaxhighlight>
 
{{out}}
The number is printed differently by different Prolog implementations:
<pre>$ swipl adaptive_simpson_task_prolog.pl
estimate of ∫ sin x dx from 0 to 1: 0.4596976941317858
$ gplc adaptive_simpson_task_prolog.pl && ./adaptive_simpson_task_prolog
estimate of ∫ sin x dx from 0 to 1: 0.45969769413178579
</pre>
 
Line 1,089 ⟶ 2,354:
{{out}}
<pre>Simpson's integration of sine from 0 to 1 = 0.459697694</pre>
 
=={{header|RATFOR}}==
I make available a copy of the public domain ratfor77, with some bug fixes, at https://sourceforge.net/p/chemoelectric/ratfor77/ It is written in C89.
 
<syntaxhighlight lang="ratfor">
#
# This is RATFOR 77, which is a preprocessor for FORTRAN 77. In
# neither language can you do anything that might look like it would
# be a recursive call, and have it actually be a recursive call. They
# are languages that assume all variables are equivalent to "extern"
# or "static" variables in C.
#
# There are other options, however.
#
# One method would be to keep track of interval size as one goes
# along, and perform the whole computation "flat": without anything
# resembling a stack. This could result, in this case, in the
# recalculation of intermediate results. Usually, however, it is my
# favorite way to do adaptive bisection, because it is safest
# (especially if you have big integers). There is no possibility of
# running out of stack.
#
# Another method is to build up a queue or stack of subtasks to
# perform, as if these subtasks were on the system stack. This also
# can be safer than recursion, because it lets you put the subtasks in
# the heap instead of the stack. (A stack of subtasks to perform is,
# in fact, how most compilers for other languages would implement
# recursive calls.)
#
# I will use the latter method, but without a heap. (An external heap
# would require either a language extension or a foreign function
# call.)
#
 
define(STKSZ,1000)
 
subroutine simpsn (f, a, fa, b, fb, m, fm, quad)
implicit none
 
external f
double precision f
double precision a, fa, b, fb, m, fm, quad
 
m = (a + b) / 2
fm = f(m)
quad = ((b - a) / 6) * (fa + (4 * fm) + fb)
end
 
subroutine adapt (sum, f, a, fa, b, fb, tol, quad, m, fm)
implicit none
 
external f, simpsn
double precision f
double precision a(STKSZ), fa(STKSZ), b(STKSZ), fb(STKSZ)
double precision tol(STKSZ), quad(STKSZ), m(STKSZ), fm(STKSZ)
double precision sum
 
integer i
double precision lm, flm, left
double precision rm, frm, right
double precision delta, tol2
 
i = 1
while (i != 0)
{
if (i == STKSZ)
{ # It is not possible to bisect further.
sum = sum + quad(i)
i = i - 1
}
else
{
call simpsn (f, a(i), fa(i), m(i), fm(i), lm, flm, left)
call simpsn (f, m(i), fm(i), b(i), fb(i), rm, frm, right)
delta = left + right - quad(i)
tol2 = tol(i) / 2
if (tol2 == tol(i) .or. abs (delta) <= 15 * tol(i))
{ # The tolerance is satisfied.
sum = sum + left + right + (delta / 15)
i = i - 1
}
else
{ # The tolerance is not satisfied. Bisect further.
b(i + 1) = b(i); fb(i + 1) = fb(i)
a(i + 1) = m(i); fa(i + 1) = fm(i)
b(i) = m(i); fb(i) = fm(i)
tol(i + 1) = tol2; tol(i) = tol2
quad(i + 1) = right; quad(i) = left
m(i + 1) = rm; m(i) = lm
fm(i + 1) = frm; fm(i) = flm
i = i + 1
}
}
}
end
 
function asimps (f, a0, b0, tol0)
implicit none
double precision asimps
 
external f, simpsn, adapt
double precision f, a0, b0, tol0
 
double precision sum
double precision a(STKSZ), fa(STKSZ)
double precision b(STKSZ), fb(STKSZ)
double precision m(STKSZ), fm(STKSZ)
double precision quad(STKSZ), tol(STKSZ)
 
sum = 0
tol(1) = tol0
a(1) = a0; fa(1) = f(a0)
b(1) = b0; fb(1) = f(b0)
call simpsn (f, a(1), fa(1), b(1), fb(1), m(1), fm(1), quad(1))
call adapt (sum, f, a, fa, b, fb, tol, quad, m, fm)
asimps = sum
end
 
function sine (x)
implicit none
double precision sine, x
sine = dsin (x)
end
 
program asrtsk
implicit none
 
external asimps, sine
double precision asimps, sine
double precision quad
 
quad = asimps (sine, 0.0D0, 1.0D0, 1D-9)
write (*, 1000) quad
1000 format ("estimated definite integral of sin(x) ", _
"for x from 0 to 1: ", F15.13)
end
</syntaxhighlight>
 
{{out}}
The output looks different, depending on which of my Fortran compilers I use:
 
<pre>$ ratfor77 adaptive_simpson_task_ratfor.r > asr.f && gfortran -fbounds-check -g asr.f && ./a.out
estimated definite integral of sin(x) for x from 0 to 1: 0.4596976941318
$ ratfor77 adaptive_simpson_task_ratfor.r > asr.f && f2c asr.f 2>/dev/null > asr.c && gcc -g asr.c -lf2c -lm && ./a.out
estimated definite integral of sin(x) for x from 0 to 1: .4596976941318</pre>
 
=={{header|REXX}}==
Line 1,131 ⟶ 2,541:
 
=={{header|Scheme}}==
 
For an R7RS-specific version, see [[#Ol]].
 
<syntaxhighlight lang="scheme">
Line 1,143 ⟶ 2,555:
;; once. There is no need to return them explicitly as
;; a data structure (though that also could be done).
(values m fm (* (/ h 6) (+ (f a)fa (* 4 fm) (f b)fb))))))
(%%quad-asr
(lambda (a fa b fb tol whole m fm depth)
Line 1,192 ⟶ 2,604:
<pre>$ gsi adaptive_simpson_task.scm
estimated definite integral of sin(x) for x from 0 to 1: .4596976941317858</pre>
 
=={{header|Shen}}==
<syntaxhighlight lang="shen">
(define simpson-rule
F A FA B FB ->
(let M (* 0.5 (+ A B))
FM (F M)
QuadVal (* (/ (- B A) 6.0) (+ FA (* 4.0 FM) FB))
[M FM QuadVal]))
 
(define recursive-simpson
F A FA B FB Tol Whole M FM Depth ->
(let TheLeftStuff (simpson-rule F A FA M FM)
TheRightStuff (simpson-rule F M FM B FB)
(recursive-simpson-united F A FA B FB Tol Whole M FM Depth
TheLeftStuff TheRightStuff)))
 
(define recursive-simpson-united
F A FA B FB Tol Whole M FM Depth
[LM FLM Left] [RM FRM Right] ->
(let Delta (- (+ Left Right) Whole)
Tol_ (* 0.5 Tol)
(if (or (<= Depth 0)
(= Tol_ Tol)
(<= (abs Delta) (* 15.0 Tol)))
(+ Left Right (/ Delta 15.0))
(+ (recursive-simpson F A FA M FM Tol_
Left LM FLM (- Depth 1))
(recursive-simpson F M FM B FB Tol_
Right RM FRM (- Depth 1))))))
 
(define quad-asr
F A B Tol Depth ->
(let FA (F A)
FB (F B)
TheWholeStuff (simpson-rule F A FA B FB)
(quad-asr-part-two F A FA B FB Tol Depth TheWholeStuff)))
 
(define quad-asr-part-two
F A FA B FB Tol Depth [M FM Whole] ->
(recursive-simpson F A FA B FB Tol Whole M FM Depth))
 
\\ The Shen standard library contains only an unserious
\\ implementation of sin(x), so I might as well toss together
\\ my own! Thus: an uneconomized Maclaurin expansion. Gotten
\\ via "taylor(sin(x),x,0,20);" in Maxima. Using up to x**13
\\ should give an error bound on the order of 1e-12, for
\\ 0 <= x <= 1. That is much better than we need.
(define sin
X -> (compute-sin X (* X X)))
(define compute-sin
X XX ->
(* X (+ 1.0
(* XX (+ (/ -1.0 6.0)
(* XX (+ (/ 1.0 120.0)
(* XX (+ (/ -1.0 5040.0)
(* XX (+ (/ 1.0 362880.0)
(* XX (+ (/ -1.0 39916800.0)
(* XX (/ 1.0 6227020800.0)))))))))))))))
 
(define abs
\\ Like sin, abs is in the standard library, but it is very
\\ easy to write.
X -> (if (< X 0) (- 0 X) X))
 
(output "estimate of the definite integral of sin x dx from 0 to 1: ")
(print (quad-asr (lambda x (sin x)) 0.0 1.0 1.0e-9 100))
(nl)
 
\\ local variables:
\\ mode: indented-text
\\ tab-width: 2
\\ end:
</syntaxhighlight>
 
{{out}}
<pre>$ shen-scheme script adaptive_simpson_task.shen
estimate of the definite integral of sin x dx from 0 to 1: 0.4596976941318334</pre>
 
=={{header|Sidef}}==
Line 1,225 ⟶ 2,715:
Simpson's integration of sine from 0 to 1 ≈ 0.45969769413186
</pre>
 
=={{header|Standard ML}}==
<syntaxhighlight lang="sml">
fun quad_asr (tol, depth) (f, a, b) =
let
fun quad_asr_simpsons_ (a, fa, b, fb) =
let
val m = 0.5 * (a + b)
val fm = f (m)
val h = b - a
in
(m, fm, (h / 6.0) * (fa + (4.0 * fm) + fb))
end
 
fun quad_asr_ (a, fa, b, fb, tol, whole, m, fm, depth) =
let
val (lm, flm, left) = quad_asr_simpsons_ (a, fa, m, fm)
and (rm, frm, right) = quad_asr_simpsons_ (m, fm, b, fb)
val delta = left + right - whole
and tol_ = 0.5 * tol
in
if depth <= 0
orelse abs (tol_ - tol) <= 0.0 (* <-- SML silliness *)
orelse Real.abs (delta) <= 15.0 * tol then
left + right + (delta / 15.0)
else
quad_asr_ (a, fa, m, fm, tol_,
left, lm, flm, depth - 1)
+ quad_asr_ (m, fm, b, fb, tol_,
right, rm, frm, depth - 1)
end
 
val fa = f (a) and fb = f (b)
val (m, fm, whole) = quad_asr_simpsons_ (a, fa, b, fb)
in
quad_asr_ (a, fa, b, fb, tol, whole, m, fm, depth)
end
;
 
val quadrature = quad_asr (0.000000001, 1000);
 
print "estimated definite integral of sin(x) for x from 0 to 1: ";
print (Real.toString (quadrature (Math.sin, 0.0, 1.0)));
print "\n";
</syntaxhighlight>
 
{{out}}
<pre>$ mlton adaptive_simpson_task.sml && ./adaptive_simpson_task
estimated definite integral of sin(x) for x from 0 to 1: 0.459697694132</pre>
 
=={{header|Wren}}==
{{trans|Go}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="ecmascriptwren">import "./fmt" for Fmt
 
/* "structured" adaptive version, translated from Racket */
2,122

edits