module solver_tiny_mod {                                      # Fit            0 = F m - d
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    }
       integer function stepper(forget,m,g,rr,gg) {
         real, dimension(:)  ::        m,g,rr,gg    
         logical             :: forget            }
    }
    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)){ m = m0                                 #        m =        m0
	stat = Fop(.false.,.false.,m,rd)                             #       Rd = Rd + F m0
    }
    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
    }
    if(present( resd)) resd = rd
  }
}
