module mod_roots
  use fgsl
  use, intrinsic :: iso_c_binding
  implicit none
contains
  function quadratic(x, params) bind(c)
    real(c_double), value :: x
    type(c_ptr), value :: params
    real(c_double) :: quadratic
!
    real(fgsl_double), pointer :: p(:)
    call c_f_pointer(params, p, (/3/))
    quadratic = (p(1)*x + p(2))*x + p(3)
  end function quadratic
end module mod_roots
program roots
  use mod_roots
  implicit none
  real(fgsl_double), parameter :: eps = 1.0E-8_fgsl_double
  integer(fgsl_int), parameter :: itmax = 30
  real(fgsl_double), target :: fpar(3)
  real(fgsl_double) :: root, xlo, xhi
  character(kind=fgsl_char,len=fgsl_strmax) :: name
  integer :: i
  integer(fgsl_int) :: status
  type(c_ptr) :: ptr
  type(fgsl_root_fsolver) :: root_fslv
  type(fgsl_function) :: func
!
  fpar = (/-1.0_fgsl_double, 0.0_fgsl_double, 5.0_fgsl_double/)
  ptr = c_loc(fpar)
!
  root_fslv = fgsl_root_fsolver_alloc(fgsl_root_fsolver_brent)
  func = fgsl_function_init(quadratic, ptr)
  if (fgsl_well_defined(root_fslv)) then
     status = fgsl_root_fsolver_set(root_fslv, func, 0.0_fgsl_double, &
          5.0_fgsl_double)
     name = fgsl_root_fsolver_name (root_fslv)
     i = 0
     do
        i = i + 1
        status = fgsl_root_fsolver_iterate(root_fslv)
        if (status /= fgsl_success .or. i > itmax) then
           write(6, *) 'Failed to converge or iterate'
           exit
        end if
        root = fgsl_root_fsolver_root(root_fslv)
        xlo = fgsl_root_fsolver_x_lower(root_fslv)
        xhi = fgsl_root_fsolver_x_upper(root_fslv)
        status = fgsl_root_test_interval (xlo, xhi, 0.0_fgsl_double, eps)
        if (status == fgsl_success) exit
     end do
  end if
  write(6, '(''Output for root finding algorithm '',A,'':'')') trim(name)
  write(6, '(''Number of iterations needed: '',i2)') i
  write(6, '(''Root of '',F5.2,''*x*x + '',F5.2,''*x +'',F5.2,'' is: '',1PE18.10)') &
       fpar, root
  write(6, '(''Function value at root is: '',1PE18.10)') quadratic(root,ptr)
  call fgsl_root_fsolver_free(root_fslv)
  call fgsl_function_free(func)
end program roots
