# 1 "<stdin>"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "<stdin>"
module solver_tiny_mod
! Fit 0 = F m - d
  implicit none
  contains
  subroutine solver_tiny( m,d, Fop, stepper, niter, m0,resd)
    optional :: m0,resd
    interface
!------------------------------------------------ begin definitions -------
      integer function Fop(adj,add,m,d)
        real,dimension(:) :: m,d
        logical,intent(in):: adj,add
      end function
      integer function stepper(forget,m,g,rr,gg)
        real, dimension(:) :: m,g,rr,gg
        logical :: forget
      end function
    end interface
    real, dimension(:), intent(in) :: d ! data
    real, dimension(:), intent(out) :: m ! model
    real, dimension(:), intent(in) :: m0 ! initial model
    integer, intent(in) :: niter
    ! number of iterations
    integer :: iter ! iteration number
    real, dimension(size( m)) :: g ! gradient (dm)
    real, dimension(size( d)),target :: rr
    ! data residual ( vector)
    real, dimension(:), pointer :: rd
    ! data residual (pointer)
    real, dimension(size( d)),target :: gg
    ! conjugate gradient ( vector)
    real, dimension(:), pointer :: gd
    ! conjugate gradient (pointer)
    integer :: stat ! status flag
    real, dimension(:), intent(out) :: resd
    ! residual (collecttion)
    rd => rr(1:size( d))
    gd => gg(1:size( d))
!----------------------------------------------------- begin initialization -----------
    rd = -d
    ! Rd = - d
    m = 0
    if (present( m0)) then
      m = m0 ! m = m0
      stat = Fop(.false.,.false.,m,rd)
      ! Rd = Rd + F m0
    end if
    do iter = 1,niter
!------------------------------------- begin iterations -----------
      stat = Fop( .true.,.false.,g,rd)
      ! g = F' Rd
      stat = Fop(.false.,.false.,g,gd)
      ! Gd = F g
      stat = stepper(.false., m,g, rr,gg)
      ! m = m+dm; R = R + dR
    end do
    if (present( resd)) then
      resd = rd
    end if
  end subroutine
end module
