module row3_mod

  implicit none
  logical, parameter, private :: T = .true., F = .false.  

contains

  subroutine row3 (oper1, oper2, oper3, adj, add, mod, &
		dat, eps1, eps2, n1,n2,n3)
    interface
       function oper1 (adj, add, mod, dat1) result (stat)
         integer              :: stat
         logical, intent (in) :: adj, add
         real, dimension (:)  :: mod, dat
       end function oper1
       function oper2 (adj, add, mod, dat) result (stat)
         integer    :: stat
         logical, intent (in) :: adj, add
         real, dimension (:)  :: mod, dat
       end function oper2
       function oper3 (adj, add, mod, dat) result (stat)
         integer    :: stat
         logical, intent (in) :: adj, add
         real, dimension (:)  :: mod, dat
       end function oper3
    end interface

    logical, intent (in)  :: adj, add
    integer, intent (in)  :: n1,n2,n3
    real, dimension (:)   :: mod
	real, dimension (:)		:: dat
    real                  :: eps1, eps2

    real, dimension(:), allocatable :: tmp,tmp1,tmp2,tmp3

    integer               :: stat1, stat2, stat3

    allocate(tmp(size(mod)))
    allocate(tmp1(n1))
    allocate(tmp2(n2))
    allocate(tmp3(n3))

    if (adj) then
	
		tmp1=0.	
		tmp2=0.	
		tmp3=0.	

       stat1 = oper1 (T, add, tmp1, dat(1:n1))
       stat2 = oper2 (T, add, tmp2, dat(n1+1:n1+n2)
       stat3 = oper3 (T, add, tmp3, dat(n1+n2+1:n1+n2+n3)

		if (add) then
			mod=mod+tmp1+eps1*tmp2+eps2*tmp3
		else
			mod=tmp1+eps1*tmp2+eps2*tmp3
		end if

    else

       stat1 = oper1 (F, add, mod, dat(1:n1))

       tmp = 0.

       stat1 = oper2 (F, F, mod, tmp)

       if (add) then
          dat(n1+1:n1+n2) = dat(n1+1:n1+n2)+tmp
       else
          dat(n1+1:n1+n2) = tmp
       end if

       tmp = 0.

       stat3 = oper3 (F, F, mod, tmp)

       if (add) then
          dat(n1+n2+1:n1+n2+n3) = dat(n1+n2+1:n1+n2+n3)+tmp
       else
          dat(n1+n2+1:n1+n2+n3) = tmp
       end if

    end if

    deallocate(tmp,tmp1,tmp2,tmp3)

  end subroutine row3

end module row3_mod
