    MODULE sparse_lin_sys_ex02_mod
      ! .. Implicit None Statement ..
      IMPLICIT NONE
      ! .. Default Accessibility ..
      PUBLIC
      ! .. Intrinsic Functions ..
      INTRINSIC KIND
      ! .. Parameters ..
      INTEGER, PARAMETER :: wp = KIND(1.0D0)
      COMPLEX (wp), PARAMETER :: zero = (0.0_wp,0.0_wp)

    CONTAINS

      FUNCTION mat_vec(trans,u,i_mat_comm,a_mat_comm)
        ! .. Implicit None Statement ..
        IMPLICIT NONE
        ! .. Intrinsic Functions ..
        INTRINSIC CONJG, DOT_PRODUCT, SIZE
        ! .. Scalar Arguments ..
        LOGICAL, INTENT (IN) :: trans
        ! .. Array Arguments ..
        INTEGER, OPTIONAL, INTENT (IN) :: i_mat_comm(:)
        COMPLEX (wp), OPTIONAL, INTENT (IN) :: a_mat_comm(:)
        COMPLEX (wp), INTENT (IN) :: u(:)
        ! .. Function Return Value ..
        COMPLEX (wp) :: mat_vec(SIZE(u))
        ! .. Local Scalars ..
        INTEGER :: i, k1, k2, n, nnz
        ! .. Executable Statements ..
        nnz = SIZE(a_mat_comm)
        n = SIZE(u)
        ! Compute matrix vector product.

        IF ( .NOT. trans) THEN

          DO i = 1, n
            k1 = i_mat_comm(i+nnz)
            k2 = i_mat_comm(i+nnz+1) - 1
            mat_vec(i) = DOT_PRODUCT(CONJG(a_mat_comm(k1:k2)),u(i_mat_comm( &
             k1:k2)))
          END DO

        ELSE

          mat_vec = zero
          DO i = 1, n
            k1 = i_mat_comm(i+nnz)
            k2 = i_mat_comm(i+1+nnz) - 1
            mat_vec(i_mat_comm(k1:k2)) = mat_vec(i_mat_comm(k1:k2)) + &
             u(i)*a_mat_comm(k1:k2)
          END DO

        END IF

      END FUNCTION mat_vec

    END MODULE sparse_lin_sys_ex02_mod
    PROGRAM nag_sparse_lin_sys_ex02

      ! Example Program Text for nag_sparse_lin_sys
      ! NAG fl90, Release 4. NAG Copyright 2000.

      ! .. Use Statements ..
      USE sparse_lin_sys_ex02_mod, ONLY : mat_vec, wp, zero
      USE nag_examples_io, ONLY : nag_std_in, nag_std_out
      USE nag_sparse_lin_sys, ONLY : nag_sparse_gen_lin_sol
      ! .. Implicit None Statement ..
      IMPLICIT NONE
      ! .. Local Scalars ..
      INTEGER :: i, n, nnz
      ! .. Local Arrays ..
      INTEGER, ALLOCATABLE :: i_mat_comm(:)
      COMPLEX (wp), ALLOCATABLE :: b(:), value(:), x(:)
      ! .. Executable Statements ..
      WRITE (nag_std_out,*) &
       'Example Program Results for nag_sparse_lin_sys_ex02'

      READ (nag_std_in,*)          ! Skip heading in data file
      READ (nag_std_in,*) n, nnz

      ALLOCATE (value(nnz),b(n),x(n),i_mat_comm(nnz+n+1))

      ! The sparse matrix is given row by row in increasing
      ! row order (Compressed Sparse Row format).
      ! i_mat_comm and value are used to store the sparse matrix
      ! information to be passed to the mat_vec function as follows:
      ! .  SIZE(value) = nnz
      ! .  SIZE(i_mat_comm) = nnz+n+1
      ! value(i) and i_mat_comm(i), for i = 1,..,nnz contain the
      ! .   value and column index for entry i
      ! i_mat_comm (nnz+i) j=1,..,n contains the index of first entry of row j
      ! i_mat_comm (nnz+n+1) = nnz+1

      DO i = 1, nnz
        READ (nag_std_in,*) value(i), i_mat_comm(i)
      END DO
      READ (nag_std_in,*) i_mat_comm(nnz+1:)
      READ (nag_std_in,*) b

      WRITE (nag_std_out,*)
      WRITE (nag_std_out,*) 'Method CGS with user supplied mat_vec'
      WRITE (nag_std_out,*)

      x = zero

      CALL nag_sparse_gen_lin_sol(mat_vec,b,x,method='C', &
       i_mat_comm=i_mat_comm,a_mat_comm=value)

      ! Output results

      WRITE (nag_std_out,*) ' Solution'
      WRITE (nag_std_out,'(3X,''('',F4.1,'','',F4.1,'')'')') x

      DEALLOCATE (b,x,value,i_mat_comm)

    END PROGRAM nag_sparse_lin_sys_ex02
