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

Content added Content deleted
Line 595: Line 595:
Simpson's rule integration of sin from 0 to 1 is: 0.4596976941573994
Simpson's rule integration of sin from 0 to 1 is: 0.4596976941573994
</pre>
</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|Go}}==
=={{header|Go}}==