zbrent Function

function zbrent(func, x1, x2, tol)

Arguments

Type IntentOptional Attributes Name
function func(x)
Arguments
Type IntentOptional Attributes Name
real(kind=8), intent(in) :: x
Return Value real(kind=8)
real(kind=8), intent(in) :: x1
real(kind=8), intent(in) :: x2
real(kind=8), intent(in) :: tol

Return Value real(kind=8)


Source Code

function zbrent(func,x1,x2,tol)
  implicit none
  interface
     function func(x)
       implicit none
       real(8), intent(in) :: x
       real(8)             :: func
     end function func
  end interface
  real(8), intent(in) :: x1,x2,tol
  real(8)             :: zbrent
  integer, parameter  :: itmax=100
  real(8), parameter  :: eps=epsilon(x1)
  integer             :: iter
  real(8)             :: a,b,c,d,e,fa,fb,fc,p,q,r,s,tol1,xm
  a=x1       ; b=x2
  fa=func(a) ; fb=func(b)
  if ((fa > 0.d0 .AND. fb > 0.d0) .OR. (fa < 0.d0 .AND. fb < 0.d0))then
     write(*,"(A)")'ROOT MUST BE BRACKETED FOR ZBRENT'
     stop
  endif
  c=b ; fc=fb
  do iter=1,itmax
     if ((fb > 0.d0 .AND. fc > 0.d0) .OR. (fb < 0.d0 .AND. fc < 0.d0)) then
        c=a
        fc=fa
        d=b-a
        e=d
     end if
     if (abs(fc) < abs(fb)) then
        a=b
        b=c
        c=a
        fa=fb
        fb=fc
        fc=fa
     end if
     tol1=2.d0*eps*abs(b)+0.5d0*tol
     xm=0.5d0*(c-b)
     if (abs(xm) <= tol1 .or. fb == 0.d0) then
        zbrent=b
        return
     end if
     !
     if (abs(e) >= tol1 .AND. abs(fa) > abs(fb)) then
        s=fb/fa
        if (a == c) then
           p=2.d0*xm*s
           q=1.d0-s
        else
           q=fa/fc
           r=fb/fc
           p=s*(2.d0*xm*q*(q-r)-(b-a)*(r-1.d0))
           q=(q-1.d0)*(r-1.d0)*(s-1.d0)
        end if
        if (p > 0.d0) q=-q
        p=abs(p)
        if (2.d0*p  <  min(3.d0*xm*q-abs(tol1*q),abs(e*q))) then
           e=d
           d=p/q
        else
           d=xm
           e=d
        end if
     else
        d=xm
        e=d
     end if
     a=b
     fa=fb
     b=b+merge(d,sign(tol1,xm), abs(d) > tol1 )
     fb=func(b)
  end do
  write(*,"(A)")'zbrent: exceeded maximum iterations'
  zbrent=b
end function zbrent