# 1 "<stdin>"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "<stdin>"
module chain1_mod
  implicit none
  logical, parameter, private :: T = .true., F = .false.
  interface chain0
  module procedure chain20
  module procedure chain30
  end interface
  contains
  subroutine row0(op1,op2, adj,add, m1, m2, d, eps)
! ROW d = Am1+epsBm2
    interface
      integer function op1(adj,add,m,d)
        real::m(:),d(:)
        logical,intent(in)::adj,add
      end function
      integer function op2(adj,add,m,d)
        real::m(:),d(:)
        logical,intent(in)::adj,add
      end function
    end interface
    logical, intent (in) :: adj, add
    real, dimension (:) :: m1,m2,d
    real :: eps
    integer :: st
    if (adj) then
      st = op1 (T, add, m1, d) ! m1 = A'd
      st = op2 (T, add, m2, d) ! m2 = B'd
      m2 = eps*m2 ! m2 = eps(B'd)
    else
      st = op2 (F, add, eps*m2, d) ! d = epsBm2
      st = op1 (F, T, m1, d) ! d = Am1+epsBm2
    end if
  end subroutine
  subroutine chain20(op1,op2, adj,add, m,d,t1)
! CHAIN 2
    interface
      integer function op1(adj,add,m,d)
        real::m(:),d(:)
        logical,intent(in)::adj,add
      end function
      integer function op2(adj,add,m,d)
        real::m(:),d(:)
        logical,intent(in)::adj,add
      end function
    end interface
    logical, intent(in) :: adj, add
    real, dimension(:) :: m,d, t1
    integer :: st
    if (adj) then
      st = op1( T, F, t1,d ) ! t = A' d
      st = op2( T, add, m, t1) ! m = B' t = B' A' d
    else
      st = op2( F, F, m, t1) ! t = B m
      st = op1( F, add, t1,d ) ! d = A t = A B m
    end if
  end subroutine
  subroutine chain30(op1,op2,op3, adj,add, m,d,t1,t2)
! CHAIN 3
    interface
      integer function op1(adj,add,m,d)
        real::m(:),d(:)
        logical,intent(in)::adj,add
      end function
      integer function op2(adj,add,m,d)
        real::m(:),d(:)
        logical,intent(in)::adj,add
      end function
      integer function op3(adj,add,m,d)
        real::m(:),d(:)
        logical,intent(in)::adj,add
      end function
    end interface
    logical, intent(in) :: adj, add
    real, dimension(:) :: m,d, t1,t2
    integer :: st
    if (adj) then
      st = op1( T, F, t2, d ) ! t1 = A' d
      st = op2( T, F, t1, t2) ! t2 = B' t1 =    B' A' d
      st = op3( T, add, m , t1) ! m = C' t2 =         C' B' A' d
    else
      st = op3( F, F, m , t1) ! t1 = C m
      st = op2( F, F, t1, t2) ! t2 = B t1 = B C m
      st = op1( F, add, t2, d ) ! d = A t2 = A B C m
    end if
  end subroutine
end module
