SF_SPARSE_ARRAY_CSC.f90 Source File


This file depends on

sourcefile~~sf_sparse_array_csc.f90~~EfferentGraph sourcefile~sf_sparse_array_csc.f90 SF_SPARSE_ARRAY_CSC.f90 sourcefile~sf_linalg.f90 SF_LINALG.f90 sourcefile~sf_sparse_array_csc.f90->sourcefile~sf_linalg.f90 sourcefile~sf_sparse_common.f90 SF_SPARSE_COMMON.f90 sourcefile~sf_sparse_array_csc.f90->sourcefile~sf_sparse_common.f90 sourcefile~sf_blacs.f90 SF_BLACS.f90 sourcefile~sf_linalg.f90->sourcefile~sf_blacs.f90 sourcefile~sf_mpi.f90 SF_MPI.f90 sourcefile~sf_linalg.f90->sourcefile~sf_mpi.f90 sourcefile~sf_sparse_common.f90->sourcefile~sf_linalg.f90

Files dependent on this one

sourcefile~~sf_sparse_array_csc.f90~~AfferentGraph sourcefile~sf_sparse_array_csc.f90 SF_SPARSE_ARRAY_CSC.f90 sourcefile~sf_sparse.f90 SF_SPARSE.f90 sourcefile~sf_sparse.f90->sourcefile~sf_sparse_array_csc.f90 sourcefile~sf_sparse_array_algebra.f90 SF_SPARSE_ARRAY_ALGEBRA.f90 sourcefile~sf_sparse_array_algebra.f90->sourcefile~sf_sparse_array_csc.f90

Source Code

MODULE SF_SPARSE_ARRAY_CSC
  USE SF_LINALG, only: deye,zeye
  USE SF_SPARSE_COMMON
  !MPI STILL TO BE DONE
#ifdef _MPI
  USE MPI
#endif
  implicit none

  private
  !CSC COLS
  type sparse_col_csc
     integer                                   :: size
     integer,dimension(:),allocatable          :: rows     
  end type sparse_col_csc
  !
  type, extends(sparse_col_csc) :: sparse_dcol_csc
     real(8),dimension(:),allocatable          :: vals
  end type sparse_dcol_csc
  !
  type, extends(sparse_col_csc) :: sparse_zcol_csc
     complex(8),dimension(:),allocatable       :: vals
  end type sparse_zcol_csc

  type, extends(sparse_matrix) :: sparse_dmatrix_csc
     type(sparse_dcol_csc),dimension(:),allocatable :: col
   contains
     procedure,pass :: init      => init_dmatrix_csc
     procedure,pass :: free      => free_dmatrix_csc
     procedure,pass :: load      => load_dmatrix_csc
     procedure,pass :: dump      => dump_dmatrix_csc
     procedure,pass :: insert    => insert_delement_csc
     procedure,pass :: get       => get_delement_csc
     procedure,pass :: as_matrix => as_dmatrix_csc
     procedure,pass :: dgr       => dgr_dmatrix_csc
     procedure,pass :: transpose => transpose_dmatrix_csc
  end type sparse_dmatrix_csc
  
  type, extends(sparse_matrix) :: sparse_zmatrix_csc
     type(sparse_zcol_csc),dimension(:),allocatable :: col
   contains
     procedure,pass :: init      => init_zmatrix_csc
     procedure,pass :: free      => free_zmatrix_csc
     procedure,pass :: load      => load_zmatrix_csc
     procedure,pass :: dump      => dump_zmatrix_csc
     procedure,pass :: insert    => insert_zelement_csc
     procedure,pass :: get       => get_zelement_csc
     procedure,pass :: as_matrix => as_zmatrix_csc
     procedure,pass :: dgr       => dgr_zmatrix_csc
     procedure,pass :: transpose => transpose_zmatrix_csc
     procedure,pass :: conjg     => conjg_zmatrix_csc
  end type sparse_zmatrix_csc

  
  
  interface sparse_matrix
     module procedure :: construct_dmatrix_csc
     module procedure :: construct_zmatrix_csc
  end interface sparse_matrix
  !
  interface as_sparse
     module procedure :: construct_dmatrix_csc
     module procedure :: construct_zmatrix_csc
  end interface as_sparse
  !
  interface sparse
     module procedure :: construct_dmatrix_csc
     module procedure :: construct_zmatrix_csc
  end interface sparse
  
  !EQUALITY with scalar and function (A=B, A=cmplx)
  interface assignment(=)
     module procedure :: dmatrix_equal_scalar_csc
     module procedure :: dmatrix_equal_dmatrix_csc
     module procedure :: zmatrix_equal_scalar_csc
     module procedure :: zmatrix_equal_zmatrix_csc
  end interface assignment(=)

  !ADDITION
  interface operator (+)
     module procedure :: plus_dmatrix_csc
     module procedure :: plus_zmatrix_csc
  end interface operator (+)

  !SUBTRACTION
  interface operator (-)
     module procedure :: minus_dmatrix_csc
     module procedure :: minus_zmatrix_csc
  end interface operator (-)
  
  !SCALAR PRODUCT
  interface operator(*)
     module procedure :: left_product_dmatrix_i_csc
     module procedure :: left_product_dmatrix_d_csc
     module procedure :: left_product_zmatrix_i_csc
     module procedure :: left_product_zmatrix_d_csc
     module procedure :: left_product_zmatrix_z_csc
     !
     module procedure :: right_product_dmatrix_i_csc
     module procedure :: right_product_dmatrix_d_csc
     module procedure :: right_product_zmatrix_i_csc
     module procedure :: right_product_zmatrix_d_csc
     module procedure :: right_product_zmatrix_z_csc
  end interface operator(*)

  !SCALAR DIVISION
  interface operator(/)
     module procedure :: right_division_dmatrix_i_csc
     module procedure :: right_division_dmatrix_d_csc
     module procedure :: right_division_zmatrix_i_csc
     module procedure :: right_division_zmatrix_d_csc
     module procedure :: right_division_zmatrix_z_csc
  end interface operator(/)

  !MATRIX PRODUCT
  interface matmul
     module procedure :: left_matmul_dmatrix_darray_csc
     module procedure :: left_matmul_zmatrix_zarray_csc 
  end interface matmul
  

  !KRONECKER PRODUCT
  interface operator(.x.)
     module procedure :: kron_dmatrix_csc
     module procedure :: kron_zmatrix_csc
  end interface operator(.x.)

  interface sp_kron
     module procedure :: restricted_kron_dmatrix_csc
     module procedure :: restricted_kron_zmatrix_csc
  end interface sp_kron

  interface transpose
     module procedure :: transpose_dmatrix_csc
     module procedure :: transpose_zmatrix_csc
  end interface transpose

  interface hconjg
     module procedure :: dgr_dmatrix_csc
     module procedure :: dgr_zmatrix_csc
  end interface hconjg
  
  public :: sparse_dmatrix_csc, sparse_zmatrix_csc  
  public :: as_sparse
  public :: sparse
  public :: assignment(=)
  public :: operator(+)
  public :: operator(-)
  public :: operator(*)
  public :: operator(/)
  public :: operator(.x.)
  public :: sp_kron
  public :: transpose
  public :: hconjg
  public :: matmul


  
contains
  
  !+------------------------------------------------------------------+
  !PURPOSE:  initialize the sparse matrix list
  !          init:           empty matrix of dimenson (N,N1)
  !          constructor:    dump a dense matrix into the sparse
  !+------------------------------------------------------------------+
  !REAL
  elemental subroutine init_dmatrix_csc(sparse,N,N1)
    class(sparse_dmatrix_csc),intent(inout) :: sparse
    integer,intent(in)                    :: N
    integer,intent(in),optional           :: N1
    integer                               :: i
    !
    !put here a delete statement to avoid problems
    if(sparse%status)call sparse%free()    
    sparse%Nrow=N
    sparse%Ncol=N 
    if(present(N1))sparse%Ncol=N1
    !
    allocate(sparse%col(sparse%Ncol))
    do i=1,sparse%Ncol
       sparse%col(i)%size=0
       allocate(sparse%col(i)%vals(0)) !empty array
       allocate(sparse%col(i)%rows(0)) !empty array
    end do
    !
    sparse%status=.true.
    !
  end subroutine init_dmatrix_csc
  !
  function construct_dmatrix_csc(matrix) result(self)
    real(8),dimension(:,:),intent(in)    :: matrix
    type(sparse_dmatrix_csc)        :: self
    call self%load(matrix)
  end function construct_dmatrix_csc
  !
  subroutine load_dmatrix_csc(sparse,matrix)
    class(sparse_dmatrix_csc),intent(inout) :: sparse
    real(8),dimension(:,:),intent(in)  :: matrix
    integer                            :: i,j,Ndim1,Ndim2
    !
    call sparse%free()
    Ndim1=size(matrix,1)
    Ndim2=size(matrix,2)
    !
    call sparse%init(Ndim1,Ndim2)
    do j=1,Ndim2
       do i=1,Ndim1
          if(matrix(i,j)/=0d0)call insert_delement_csc(sparse,matrix(i,j),i,j)
       enddo
    enddo
  end subroutine load_dmatrix_csc
  !
  !COMPLEX
  elemental subroutine init_zmatrix_csc(sparse,N,N1)
    class(sparse_zmatrix_csc),intent(inout) :: sparse
    integer,intent(in)                      :: N
    integer,intent(in),optional             :: N1
    integer                                 :: i
    !
    !put here a delete statement to avoid problems
    if(sparse%status)call sparse%free()
    !
    sparse%Nrow=N
    sparse%Ncol=N 
    if(present(N1))sparse%Ncol=N1
    !
    allocate(sparse%col(sparse%Ncol))
    do i=1,sparse%Ncol
       sparse%col(i)%size=0
       allocate(sparse%col(i)%vals(0)) !empty array
       allocate(sparse%col(i)%rows(0)) !empty array
    end do
    !
    sparse%status=.true.
    !
  end subroutine init_zmatrix_csc
  !
  function construct_zmatrix_csc(matrix) result(self)
    complex(8),dimension(:,:),intent(in)  :: matrix
    type(sparse_zmatrix_csc)              :: self
    call self%load(matrix)
  end function construct_zmatrix_csc
  !
  subroutine load_zmatrix_csc(sparse,matrix)
    class(sparse_zmatrix_csc),intent(inout) :: sparse
    complex(8),dimension(:,:),intent(in)  :: matrix
    integer                            :: i,j,Ndim1,Ndim2
    !
    call sparse%free()
    Ndim1=size(matrix,1)
    Ndim2=size(matrix,2)
    !
    call sparse%init(Ndim1,Ndim2)
    do j=1,Ndim2
       do i=1,Ndim1
          if(matrix(i,j)/=0d0)call insert_zelement_csc(sparse,matrix(i,j),i,j)
       enddo
    enddo
  end subroutine load_zmatrix_csc

  !+------------------------------------------------------------------+
  !PURPOSE: frees a sparse matrix
  !+------------------------------------------------------------------+
  !REAL
  elemental subroutine free_dmatrix_csc(sparse)    
    class(sparse_dmatrix_csc),intent(inout) :: sparse
    integer                            :: i
    !
    do i=1,sparse%Ncol
       sparse%col(i)%Size  = 0
       if(allocated(sparse%col(i)%vals))deallocate(sparse%col(i)%vals)
       if(allocated(sparse%col(i)%rows))deallocate(sparse%col(i)%rows)
    enddo
    if(allocated(sparse%col))deallocate(sparse%col)
    !
    sparse%Nrow=0
    sparse%Ncol=0
    sparse%Nelements=0
    sparse%status=.false.
  end subroutine free_dmatrix_csc
  !
  !COMPLEX
  elemental subroutine free_zmatrix_csc(sparse)    
    class(sparse_zmatrix_csc),intent(inout) :: sparse
    integer                                 :: i
    !
    do i=1,sparse%Ncol
       sparse%col(i)%Size  = 0
       if(allocated(sparse%col(i)%vals))deallocate(sparse%col(i)%vals)
       if(allocated(sparse%col(i)%rows))deallocate(sparse%col(i)%rows)
    enddo
    if(allocated(sparse%col))deallocate(sparse%col)
    !
    sparse%Nrow=0
    sparse%Ncol=0
    sparse%Nelements=0
    sparse%status=.false.
  end subroutine free_zmatrix_csc



  !+------------------------------------------------------------------+
  !PURPOSE: insert an element value at position (i,j) in the sparse matrix
  !+------------------------------------------------------------------+
  !REAL
  subroutine insert_delement_csc(sparse,value,i,j)
    class(sparse_dmatrix_csc),intent(inout) :: sparse
    real(8),intent(in)                    :: value
    integer,intent(in)                    :: i,j
    integer                               :: row,pos
    logical                               :: iadd
    !
    row = i
    !
    iadd = .false.                          !check if column already exist
    if(any(sparse%col(j)%rows == row))then         !
       pos = binary_search(sparse%col(j)%rows,row) !find the position  column in %cols        
       iadd=.true.                          !set Iadd to true
    endif
    !
    if(iadd)then                            !this column exists so just sum it up       
       sparse%col(j)%vals(pos)=sparse%col(j)%vals(pos) + value  !add up value to the current one in %vals
    else                                    !this column is new. increase counter and store it
       call append(sparse%col(j)%vals,value)
       call append(sparse%col(j)%rows,row)
       sparse%col(j)%Size = sparse%col(j)%Size + 1
       sparse%Nelements = sparse%Nelements+1
    endif
    !
    if(sparse%col(j)%Size > sparse%Nrow)stop "insert_delement_csc ERROR: row%Size > sparse%Ncol"
  end subroutine insert_delement_csc
  !
  !COMPLEX
  subroutine insert_zelement_csc(sparse,value,i,j)
    class(sparse_zmatrix_csc),intent(inout) :: sparse
    complex(8),intent(in)                 :: value
    integer,intent(in)                    :: i,j
    integer                               :: row,pos
    logical                               :: iadd
    !
    !
    row = i
    !
    iadd = .false.                          !check if column already exist
    if(any(sparse%col(j)%rows == row))then         !
       pos = binary_search(sparse%col(j)%rows,row) !find the position  column in %cols        
       iadd=.true.                          !set Iadd to true
    endif
    !
    if(iadd)then                            !this column exists so just sum it up       
       sparse%col(j)%vals(pos)=sparse%col(j)%vals(pos) + value  !add up value to the current one in %vals
    else                                    !this column is new. increase counter and store it 
       call append(sparse%col(j)%vals,value)
       call append(sparse%col(j)%rows,row)
       sparse%col(j)%Size = sparse%col(j)%Size + 1
       sparse%Nelements = sparse%Nelements+1
    endif
    !
    if(sparse%col(j)%Size > sparse%Nrow)stop "insert_zelement_csc ERROR: row%Size > sparse%Ncol"
    !
  end subroutine insert_zelement_csc

    !+------------------------------------------------------------------+
  !PURPOSE: get the element value at position (i,j) in the sparse matrix
  !+------------------------------------------------------------------+
  function get_delement_csc(sparse,i,j) result(value)
    class(sparse_dmatrix_csc),intent(inout) :: sparse    
    integer,intent(in)                 :: i,j
    real(8)                            :: value
    integer                            :: pos
    value=0d0
    do pos=1,sparse%col(j)%size
       if(i==sparse%col(j)%rows(pos))value=sparse%col(j)%vals(pos)
    enddo
  end function get_delement_csc

  function get_zelement_csc(sparse,i,j) result(value)
    class(sparse_zmatrix_csc),intent(inout) :: sparse    
    integer,intent(in)                 :: i,j
    complex(8)                         :: value
    integer                            :: pos
    value=0d0
    do pos=1,sparse%col(j)%size
       if(i==sparse%col(j)%rows(pos))value=sparse%col(j)%vals(pos)
    enddo
  end function get_zelement_csc



  

  !+------------------------------------------------------------------+
  !PURPOSE: dump a sparse matrix into a regular 2dim array summing elements
  !+------------------------------------------------------------------+
  !REAL
  subroutine dump_dmatrix_csc(sparse,matrix)
    class(sparse_dmatrix_csc),intent(in)   :: sparse
    real(8),dimension(:,:),intent(inout) :: matrix
    integer                              :: i,j,Ndim1,Ndim2
    !
    !
    Ndim1=size(matrix,1);  Ndim2=size(matrix,2)
    !
    if(sparse%Nrow/=Ndim1 .OR. sparse%Ncol/=Ndim2)stop "Warning SPARSE/dump_dmatrix: dimensions error"
    !
    do j=1,Ndim2
       do i=1,sparse%col(j)%Size
          matrix(sparse%col(j)%rows(i),j) = matrix(sparse%col(j)%rows(i),j) + sparse%col(j)%vals(i)
       enddo
    enddo
  end subroutine dump_dmatrix_csc
  !
  !COMPLEX
  subroutine dump_zmatrix_csc(sparse,matrix)
    class(sparse_zmatrix_csc),intent(in)      :: sparse
    complex(8),dimension(:,:),intent(inout) :: matrix
    integer                                 :: i,j,Ndim1,Ndim2
    !
    !
    Ndim1=size(matrix,1);   Ndim2=size(matrix,2)
    !
    if(sparse%Nrow/=Ndim1 .OR. sparse%Ncol/=Ndim2)stop "Warning SPARSE/dump_zmatrix: dimensions error"
    !
    matrix=0.d0
    do j=1,Ndim2
       do i=1,sparse%col(j)%Size
          matrix(sparse%col(j)%rows(i),j) = matrix(sparse%col(j)%rows(i),j) + sparse%col(j)%vals(i)
       enddo
    enddo
  end subroutine dump_zmatrix_csc


  !+------------------------------------------------------------------+
  !PURPOSE: dump a sparse matrix into a regular 2dim array replacing elements
  !+------------------------------------------------------------------+
  !REAL
  function as_dmatrix_csc(sparse) result(matrix)
    class(sparse_dmatrix_csc),intent(in)            :: sparse
    real(8),dimension(sparse%Nrow,sparse%Ncol) :: matrix
    integer                                    :: i,j
    matrix = 0d0
    do j=1,sparse%Ncol
       do i=1,sparse%col(j)%Size
          matrix(sparse%col(j)%rows(i),j) = sparse%col(j)%vals(i)
       enddo
    enddo
  end function as_dmatrix_csc
  
  !COMPLEX
  function as_zmatrix_csc(sparse) result(matrix)
    class(sparse_zmatrix_csc),intent(in)            :: sparse
    complex(8),dimension(sparse%Nrow,sparse%Ncol) :: matrix
    integer                                    :: i,j
    matrix = 0d0
    do j=1,sparse%Ncol
       do i=1,sparse%col(j)%Size
          matrix(sparse%col(j)%rows(i),j) = sparse%col(j)%vals(i)
       enddo
    enddo
  end function as_zmatrix_csc


  !##################################################################
  !               SPARSE MATRIX KRON PRODUCT 
  !##################################################################
  !+------------------------------------------------------------------+
  !PURPOSE:  Perform simple Kroenecker product of two sparse matrices
  !AxB(1+rowB*(i-1):rowB*i,1+colB*(j-1):colB*j)  =  A(i,j)*B(:,:)
  !+------------------------------------------------------------------+
  !REAL
  function kron_dmatrix_csc(A,B) result(AxB)
    type(sparse_dmatrix_csc), intent(in) :: A,B
    type(sparse_dmatrix_csc)             :: AxB
    integer                         :: i,j,k,l,jrow,krow
    integer                         :: indx_row,indx_col
    real(8)                         :: value
    call AxB%free()
    call AxB%init(a%Nrow*b%Nrow,a%Ncol*b%Ncol)
    do indx_col =1,A%Ncol*B%Ncol
       k=mod(indx_col,B%Ncol); if(k==0)k=B%Ncol
       j= (indx_col-1)/B%Ncol+1
       do jrow=1,A%col(j)%size
          i=A%col(j)%rows(jrow)
          do krow=1,B%col(k)%size
             l = B%col(k)%rows(krow)
             indx_row = l + (i-1)*B%Nrow
             value = A%col(j)%vals(jrow)*B%col(k)%vals(krow)
             !
             call append(AxB%col(indx_col)%vals,value)
             call append(AxB%col(indx_col)%rows,indx_row)
             AxB%col(indx_col)%Size = AxB%col(indx_col)%Size + 1
             AxB%Nelements = AxB%Nelements+1
          end do
       end do
    end do
  end function kron_dmatrix_csc
  !
  function restricted_kron_dmatrix_csc(A,B,states) result(AxB)
    type(sparse_dmatrix_csc), intent(in)  :: A,B
    integer,dimension(:),intent(in)  :: states
    type(sparse_dmatrix_csc)      :: AxB
    integer                          :: i,irow,j,k,krow,l,istate,jstate
    integer                          :: indx_row,indx_col
    real(8)                          :: value
    integer,dimension(:),allocatable :: inv_states
    call AxB%free()
    call AxB%init(size(states),size(states))
    allocate(inv_states(A%Ncol*B%Ncol))
    do i=1,size(states)
       inv_states(states(i)) = i
    enddo
    do istate = 1,size(states)
       indx_col=states(istate)
       k = mod(indx_col,B%Ncol);if(k==0)k=B%Ncol
       i = (indx_col-1)/B%Ncol+1
       do irow=1,A%col(i)%size
          j = A%col(i)%rows(irow)
          do krow=1,B%col(k)%size
             l = B%col(k)%rows(krow)
             indx_row = l + (j-1)*B%Nrow
             jstate   = inv_states(indx_row)
             value    = A%col(i)%vals(irow)*B%col(k)%vals(krow)
             !
             call append(AxB%col(istate)%vals,value)
             call append(AxB%col(istate)%rows,jstate)
             AxB%col(istate)%Size = AxB%col(istate)%Size + 1
             AxB%Nelements = AxB%Nelements + 1
             !
          enddo
       enddo
    enddo
  end function restricted_kron_dmatrix_csc
  !
  !COMPLEX
  function kron_zmatrix_csc(A,B) result(AxB)
    type(sparse_zmatrix_csc), intent(in) :: A,B
    type(sparse_zmatrix_csc)             :: AxB
    integer                         :: i,jrow,j,k,krow,l
    integer                         :: indx_row,indx_col
    complex(8)                      :: value
    call AxB%free()
    call AxB%init(a%Nrow*b%Nrow,a%Ncol*b%Ncol)
    do indx_col =1,A%Ncol*B%Ncol
       k=mod(indx_col,B%Ncol); if(k==0)k=B%Ncol
       j= (indx_col-1)/B%Ncol+1
       do jrow=1,A%col(j)%size
          i=A%col(j)%rows(jrow)
          do krow=1,B%col(k)%size
             l = B%col(k)%rows(krow)
             indx_row = l + (i-1)*B%Nrow
             value = A%col(j)%vals(jrow)*B%col(k)%vals(krow)
             !
             call append(AxB%col(indx_col)%vals,value)
             call append(AxB%col(indx_col)%rows,indx_row)
             AxB%col(indx_col)%Size = AxB%col(indx_col)%Size + 1
             AxB%Nelements = AxB%Nelements+1
          end do
       end do
    end do
  end function kron_zmatrix_csc
  !
  function restricted_kron_zmatrix_csc(A,B,states) result(AxB)
    type(sparse_zmatrix_csc), intent(in)  :: A,B
    integer,dimension(:),intent(in)  :: states
    type(sparse_zmatrix_csc)      :: AxB
    integer                          :: i,irow,j,k,krow,l,istate,jstate
    integer                          :: indx_row,indx_col
    complex(8)                          :: value
    integer,dimension(:),allocatable :: inv_states
    call AxB%free()
    call AxB%init(size(states),size(states))
    allocate(inv_states(A%Ncol*B%Ncol))
    do i=1,size(states)
       inv_states(states(i)) = i
    enddo
    do istate = 1,size(states)
       indx_col=states(istate)
       k = mod(indx_col,B%Ncol);if(k==0)k=B%Ncol
       i = (indx_col-1)/B%Ncol+1
       do irow=1,A%col(i)%size
          j = A%col(i)%rows(irow)
          do krow=1,B%col(k)%size
             l = B%col(k)%rows(krow)
             indx_row = l + (j-1)*B%Nrow
             jstate   = inv_states(indx_row)
             value    = A%col(i)%vals(irow)*B%col(k)%vals(krow)
             !
             call append(AxB%col(istate)%vals,value)
             call append(AxB%col(istate)%rows,jstate)
             AxB%col(istate)%Size = AxB%col(istate)%Size + 1
             AxB%Nelements = AxB%Nelements + 1
             !
          enddo
       enddo
    enddo
  end function restricted_kron_zmatrix_csc
  !
  

  
  !##################################################################
  !               SPARSE MATRIX BASIC ALGEBRA 
  !##################################################################
  !REAL
  function dgr_dmatrix_csc(a) result(c)
    class(sparse_dmatrix_csc), intent(in) :: a
    type(sparse_dmatrix_csc)              :: c
    integer                          :: row
    real(8)                          :: val
    integer                          :: i,j    
    call c%init(a%Ncol,a%Nrow)      !tranpose
    do j=1,a%Ncol
       do i=1,a%col(j)%size
          row = a%col(j)%rows(i)
          val = a%col(j)%vals(i)
          call c%insert(val,j,row)
       enddo
    enddo
  end function dgr_dmatrix_csc
  !
  function transpose_dmatrix_csc(a) result(c)
    class(sparse_dmatrix_csc), intent(in) :: a
    type(sparse_dmatrix_csc)              :: c
    integer                          :: row
    real(8)                          :: val
    integer                          :: i,j    
    call c%init(a%Ncol,a%Nrow)      !tranpose
    do j=1,a%Ncol
       do i=1,a%col(j)%size
          row = a%col(j)%rows(i)
          val = a%col(j)%vals(i)
          call c%insert(val,j,row)
       enddo
    enddo
  end function transpose_dmatrix_csc
  !
  !+------------------------------------------------------------------+
  !PURPOSE:  Sparse matrix equality spA = spB. Deep copy
  !+------------------------------------------------------------------+
  subroutine dmatrix_equal_dmatrix_csc(a,b)
    type(sparse_dmatrix_csc),intent(inout) :: a
    type(sparse_dmatrix_csc),intent(in)    :: b
    integer                           :: row
    real(8)                           :: val
    integer                           :: i,j    
    call a%free()
    call a%init(b%Nrow,b%Ncol)
    do j=1,b%Ncol
       do i=1,b%col(j)%size
          row = b%col(j)%rows(i)
          val = b%col(j)%vals(i)
          call a%insert(val,row,j)
       enddo
    enddo
  end subroutine dmatrix_equal_dmatrix_csc
  !
  !+------------------------------------------------------------------+
  !PURPOSE:  Sparse matrix scalar equality spA = const. 
  !+------------------------------------------------------------------+
  subroutine dmatrix_equal_scalar_csc(a,c)
    type(sparse_dmatrix_csc),intent(inout) :: a
    real(8),intent(in)                :: c
    integer                           :: i,j    
    ! if(.not.a%status)stop "dmatrix_equal_scalar error: a is not allocated"
    do j=1,a%Ncol
       do i=1,a%col(j)%size
          a%col(j)%vals(i) = c
       enddo
    enddo
  end subroutine dmatrix_equal_scalar_csc
  !
  !+------------------------------------------------------------------+
  !PURPOSE:  Sparse matrix addition spA + spB = spC
  !+------------------------------------------------------------------+
  function plus_dmatrix_csc(a,b) result(c)
    type(sparse_dmatrix_csc), intent(in) :: a,b
    type(sparse_dmatrix_csc)             :: c
    integer                         :: row
    real(8)                         :: val
    integer                         :: i,j
    ! if(.not.a%status)stop "plus_dmatrix error: a is not allocated"
    ! if(.not.b%status)stop "plus_dmatrix error: b is not allocated"
    if(a%Nrow/=b%Nrow)stop "plus_dmatrix error: a.Nrow != b.Nrow"
    if(a%Ncol/=b%Ncol)stop "plus_dmatrix error: a.Ncol != b.Ncol"
    c=a                         !copy a into c
    do j=1,b%Ncol
       do i=1,b%col(j)%size
          row = b%col(j)%rows(i)
          val = b%col(j)%vals(i)
          call c%insert(val,row,j)
       enddo
    enddo
  end function plus_dmatrix_csc
  !
  !+------------------------------------------------------------------+
  !PURPOSE:  Sparse matrix difference spA - spB = spC
  !+------------------------------------------------------------------+
  function minus_dmatrix_csc(a,b) result(c)
    type(sparse_dmatrix_csc), intent(in) :: a,b
    type(sparse_dmatrix_csc)             :: c
    integer                         :: row
    real(8)                         :: val
    integer                         :: i,j    
    if(a%Nrow/=b%Nrow)stop "minus_dmatrix error: a.Nrow != b.Nrow"
    if(a%Ncol/=b%Ncol)stop "minus_dmatrix error: a.Ncol != b.Ncol"
    c=a                         !copy a into c
    do j=1,b%Ncol
       do i=1,b%col(j)%size
          row = b%col(j)%rows(i)
          val = -b%col(j)%vals(i)
          call c%insert(val,row,j)
       enddo
    enddo
  end function minus_dmatrix_csc
  !
  !+------------------------------------------------------------------+
  !PURPOSE:  Sparse matrix left scalar product const*spA = spC.
  ! type[Const]=integer(4),real(8),cmplx(8)
  !+------------------------------------------------------------------+
  function left_product_dmatrix_i_csc(C,A) result(B)
    integer,intent(in)             :: C
    type(sparse_dmatrix_csc),intent(in) :: A
    type(sparse_dmatrix_csc)            :: B
    integer                        :: row
    real(8)                        :: val
    integer                        :: i,j   
    call b%free()
    call b%init(a%Nrow,a%Ncol)
    do j=1,a%Ncol
       do i=1,a%col(j)%size
          row = a%col(j)%rows(i)
          val = a%col(j)%vals(i)*C
          call b%insert(val,row,j)
       enddo
    enddo
  end function left_product_dmatrix_i_csc
  !
  function left_product_dmatrix_d_csc(C,A) result(B)
    real(8),intent(in)             :: C
    type(sparse_dmatrix_csc),intent(in) :: A
    type(sparse_dmatrix_csc)            :: B
    integer                             :: row
    real(8)                             :: val
    integer                             :: i,j   
    call b%free()
    call b%init(a%Nrow,a%Ncol)
    do j=1,a%Ncol
       do i=1,a%col(j)%size
          row = a%col(j)%rows(i)
          val = a%col(j)%vals(i)*C
          call b%insert(val,row,j)
       enddo
    enddo
  end function left_product_dmatrix_d_csc
  !
  !+------------------------------------------------------------------+
  !PURPOSE:  Sparse matrix right scalar product spA*const = spC.
  ! type[Const]=integer(4),real(8),cmplx(8)
  !+------------------------------------------------------------------+
  function right_product_dmatrix_i_csc(A,C) result(B)
    integer,intent(in)             :: C
    type(sparse_dmatrix_csc),intent(in) :: A
    type(sparse_dmatrix_csc)            :: B
    integer                        :: row
    real(8)                        :: val
    integer                        :: i,j   
    call b%free()
    call b%init(a%Nrow,a%Ncol)
    do j=1,a%Ncol
       do i=1,a%col(j)%size
          row = a%col(j)%rows(i)
          val = a%col(j)%vals(i)*C
          call b%insert(val,row,j)
       enddo
    enddo
  end function right_product_dmatrix_i_csc
  !
  function right_product_dmatrix_d_csc(A,C) result(B)
    real(8),intent(in)             :: C
    type(sparse_dmatrix_csc),intent(in) :: A
    type(sparse_dmatrix_csc)            :: B
    integer                        :: row
    real(8)                        :: val
    integer                        :: i,j   
    call b%free()
    call b%init(a%Nrow,a%Ncol)
    do j=1,a%Ncol
       do i=1,a%col(j)%size
          row = a%col(j)%rows(i)
          val = a%col(j)%vals(i)*C
          call b%insert(val,row,j)
       enddo
    enddo
  end function right_product_dmatrix_d_csc
  !
  !+------------------------------------------------------------------+
  !PURPOSE:  Sparse matrix right scalar division spA/const = spC.
  ! type[Const]=integer(4),real(8),cmplx(8)
  !+------------------------------------------------------------------+
  function right_division_dmatrix_i_csc(A,C) result(B)
    integer,intent(in)             :: C
    type(sparse_dmatrix_csc),intent(in) :: A
    type(sparse_dmatrix_csc)            :: B
    integer                        :: row
    real(8)                        :: val
    integer                        :: i,j   
    call b%free()
    call b%init(a%Nrow,a%Ncol)
    do j=1,a%Ncol
       do i=1,a%col(j)%size
          row = a%col(j)%rows(i)
          val = a%col(j)%vals(i)/C
          call b%insert(val,row,j)
       enddo
    enddo
  end function right_division_dmatrix_i_csc
  !
  function right_division_dmatrix_d_csc(A,C) result(B)
    real(8),intent(in)             :: C
    type(sparse_dmatrix_csc),intent(in) :: A
    type(sparse_dmatrix_csc)            :: B
    integer                        :: row
    real(8)                        :: val
    integer                        :: i,j   
    call b%free()
    call b%init(a%Nrow,a%Ncol)
    do j=1,a%Ncol
       do i=1,a%col(j)%size
          row = a%col(j)%rows(i)
          val = a%col(j)%vals(i)/C
          call b%insert(val,row,j)
       enddo
    enddo
  end function right_division_dmatrix_d_csc
  !
  !+------------------------------------------------------------------+
  !PURPOSE:  Return the identiy sparse matrix of given dimension
  !+------------------------------------------------------------------+
  !function  deye_csc(ndim) result(self)
  !   type(sparse_dmatrix_csc) :: self
  !   integer,intent(in)       :: ndim
  !   integer                  :: i
  !   call self%init(ndim,ndim)
  !   do i=1,ndim
  !      call self%insert(1.d0,i,i)
  !   end do
  ! end func
  !tion deye_csc

  !COMPLEX
  function dgr_zmatrix_csc(a) result(c)
    class(sparse_zmatrix_csc), intent(in) :: a
    type(sparse_zmatrix_csc)              :: c
    integer                               :: row
    complex(8)                            :: val
    integer                               :: i,j    
    call c%init(a%Ncol,a%Nrow)      !tranpose
    do j=1,a%Ncol
       do i=1,a%col(j)%size
          row = a%col(j)%rows(i)
          val = conjg(a%col(j)%vals(i))
          call c%insert(val,j,row)
       enddo
    enddo
  end function dgr_zmatrix_csc
  !
  function transpose_zmatrix_csc(a) result(c)
    class(sparse_zmatrix_csc), intent(in) :: a
    type(sparse_zmatrix_csc)              :: c
    integer                               :: row
    complex(8)                            :: val
    integer                               :: i,j    
    call c%init(a%Ncol,a%Nrow)      !tranpose
    do j=1,a%Ncol
       do i=1,a%col(j)%size
          row = a%col(j)%rows(i)
          val = a%col(j)%vals(i)
          call c%insert(val,j,row)
       enddo
    enddo
  end function transpose_zmatrix_csc
  !
  function conjg_zmatrix_csc(a) result(c)
    class(sparse_zmatrix_csc), intent(in) :: a
    type(sparse_zmatrix_csc)              :: c
    integer                          :: row
    complex(8)                       :: val
    integer                          :: i,j    
    call c%init(a%Nrow,a%Ncol)      !tranpose
    do j=1,a%Ncol
       do i=1,a%col(j)%size
          row = a%col(j)%rows(i)
          val = conjg(a%col(j)%vals(i))
          call c%insert(val,row,j)
       enddo
    enddo
  end function conjg_zmatrix_csc
  !
  !+------------------------------------------------------------------+
  !PURPOSE:  Sparse matrix equality spA = spB. Deep copy
  !+------------------------------------------------------------------+
  subroutine zmatrix_equal_zmatrix_csc(a,b)
    type(sparse_zmatrix_csc),intent(inout) :: a
    type(sparse_zmatrix_csc),intent(in)    :: b
    integer                           :: row
    complex(8)                        :: val
    integer                           :: i,j    
    call a%free()
    call a%init(b%Nrow,b%Ncol)
    do j=1,b%Ncol
       do i=1,b%col(j)%size
          row = b%col(j)%rows(i)
          val = b%col(j)%vals(i)
          call a%insert(val,row,j)
       enddo
    enddo
  end subroutine zmatrix_equal_zmatrix_csc
  !
  !+------------------------------------------------------------------+
  !PURPOSE:  Sparse matrix scalar equality spA = const. 
  !+------------------------------------------------------------------+
  subroutine zmatrix_equal_scalar_csc(a,c)
    type(sparse_zmatrix_csc),intent(inout) :: a
    complex(8),intent(in)                :: c
    integer                           :: i,j    
    ! if(.not.a%status)stop "zmatrix_equal_scalar error: a is not allocated"
    do j=1,a%Ncol
       do i=1,a%col(j)%size
          a%col(j)%vals(i) = c
       enddo
    enddo
  end subroutine zmatrix_equal_scalar_csc
  !
  !+------------------------------------------------------------------+
  !PURPOSE:  Sparse matrix addition spA + spB = spC
  !+------------------------------------------------------------------+
  function plus_zmatrix_csc(a,b) result(c)
    type(sparse_zmatrix_csc), intent(in) :: a,b
    type(sparse_zmatrix_csc)             :: c
    integer                         :: row
    complex(8)                      :: val
    integer                         :: i,j
    ! if(.not.a%status)stop "plus_zmatrix error: a is not allocated"
    ! if(.not.b%status)stop "plus_zmatrix error: b is not allocated"
    if(a%Nrow/=b%Nrow)stop "plus_zmatrix error: a.Nrow != b.Nrow"
    if(a%Ncol/=b%Ncol)stop "plus_zmatrix error: a.Ncol != b.Ncol"
    c=a                         !copy a into c
    do j=1,b%Ncol
       do i=1,b%col(j)%size
          row = b%col(j)%rows(i)
          val = b%col(j)%vals(i)
          call c%insert(val,row,j)
       enddo
    enddo
  end function plus_zmatrix_csc
  !
  !+------------------------------------------------------------------+
  !PURPOSE:  Sparse matrix difference spA - spB = spC
  !+------------------------------------------------------------------+
  function minus_zmatrix_csc(a,b) result(c)
    type(sparse_zmatrix_csc), intent(in) :: a,b
    type(sparse_zmatrix_csc)             :: c
    integer                         :: row
    complex(8)                      :: val
    integer                         :: i,j    
    if(a%Nrow/=b%Nrow)stop "plus_zmatrix error: a.Nrow != b.Nrow"
    if(a%Ncol/=b%Ncol)stop "plus_zmatrix error: a.Ncol != b.Ncol"
    c=a                         !copy a into c
    do j=1,b%Ncol
       do i=1,b%col(j)%size
          row = b%col(j)%rows(i)
          val = -b%col(j)%vals(i)
          call c%insert(val,row,j)
       enddo
    enddo
  end function minus_zmatrix_csc
  !
  !+------------------------------------------------------------------+
  !PURPOSE:  Sparse matrix left scalar product const*spA = spC.
  ! type[Const]=integer(4),real(8),cmplx(8)
  !+------------------------------------------------------------------+
  function left_product_zmatrix_i_csc(C,A) result(B)
    integer,intent(in)             :: C
    type(sparse_zmatrix_csc),intent(in) :: A
    type(sparse_zmatrix_csc)            :: B
    integer                        :: row
    complex(8)                     :: val
    integer                        :: i,j   
    call b%free()
    call b%init(a%Nrow,a%Ncol)
    do j=1,a%Ncol
       do i=1,a%col(j)%size
          row = a%col(j)%rows(i)
          val = a%col(j)%vals(i)*C
          call b%insert(val,row,j)
       enddo
    enddo
  end function left_product_zmatrix_i_csc
  !
  function left_product_zmatrix_d_csc(C,A) result(B)
    real(8),intent(in)             :: C
    type(sparse_zmatrix_csc),intent(in) :: A
    type(sparse_zmatrix_csc)            :: B
    integer                        :: row
    complex(8)                     :: val
    integer                        :: i,j   
    call b%free()
    call b%init(a%Nrow,a%Ncol)
    do j=1,a%Ncol
       do i=1,a%col(j)%size
          row = a%col(j)%rows(i)
          val = a%col(j)%vals(i)*C
          call b%insert(val,row,j)
       enddo
    enddo
  end function left_product_zmatrix_d_csc
  !
  function left_product_zmatrix_z_csc(C,A) result(B)
    complex(8),intent(in)             :: C
    type(sparse_zmatrix_csc),intent(in) :: A
    type(sparse_zmatrix_csc)            :: B
    integer                        :: row
    complex(8)                     :: val
    integer                        :: i,j   
    call b%free()
    call b%init(a%Nrow,a%Ncol)
    do j=1,a%Ncol
       do i=1,a%col(j)%size
          row = a%col(j)%rows(i)
          val = a%col(j)%vals(i)*C
          call b%insert(val,row,j)
       enddo
    enddo
  end function left_product_zmatrix_z_csc
  !
  !+------------------------------------------------------------------+
  !PURPOSE:  Sparse matrix right scalar product spA*const = spC.
  ! type[Const]=integer(4),real(8),cmplx(8)
  !+------------------------------------------------------------------+
  function right_product_zmatrix_i_csc(A,C) result(B)
    integer,intent(in)             :: C
    type(sparse_zmatrix_csc),intent(in) :: A
    type(sparse_zmatrix_csc)            :: B
    integer                        :: row
    complex(8)                     :: val
    integer                        :: i,j   
    call b%free()
    call b%init(a%Nrow,a%Ncol)
    do j=1,a%Ncol
       do i=1,a%col(j)%size
          row = a%col(j)%rows(i)
          val = a%col(j)%vals(i)*C
          call b%insert(val,row,j)
       enddo
    enddo
  end function right_product_zmatrix_i_csc
  !
  function right_product_zmatrix_d_csc(A,C) result(B)
    real(8),intent(in)             :: C
    type(sparse_zmatrix_csc),intent(in) :: A
    type(sparse_zmatrix_csc)            :: B
    integer                        :: row
    complex(8)                     :: val
    integer                        :: i,j   
    call b%free()
    call b%init(a%Nrow,a%Ncol)
    do j=1,a%Ncol
       do i=1,a%col(j)%size
          row = a%col(j)%rows(i)
          val = a%col(j)%vals(i)*C
          call b%insert(val,row,j)
       enddo
    enddo
  end function right_product_zmatrix_d_csc
  !
  function right_product_zmatrix_z_csc(A,C) result(B)
    complex(8),intent(in)             :: C
    type(sparse_zmatrix_csc),intent(in) :: A
    type(sparse_zmatrix_csc)            :: B
    integer                        :: row
    complex(8)                     :: val
    integer                        :: i,j   
    call b%free()
    call b%init(a%Nrow,a%Ncol)
    do j=1,a%Ncol
       do i=1,a%col(j)%size
          row = a%col(j)%rows(i)
          val = a%col(j)%vals(i)*C
          call b%insert(val,row,j)
       enddo
    enddo
  end function right_product_zmatrix_z_csc
  !
  !+------------------------------------------------------------------+
  !PURPOSE:  Sparse matrix right scalar division spA/const = spC.
  ! type[Const]=integer(4),real(8),cmplx(8)
  !+------------------------------------------------------------------+
  function right_division_zmatrix_i_csc(A,C) result(B)
    integer,intent(in)             :: C
    type(sparse_zmatrix_csc),intent(in) :: A
    type(sparse_zmatrix_csc)            :: B
    integer                        :: row
    complex(8)                     :: val
    integer                        :: i,j   
    call b%free()
    call b%init(a%Nrow,a%Ncol)
    do j=1,a%Ncol
       do i=1,a%col(j)%size
          row = a%col(j)%rows(i)
          val = a%col(j)%vals(i)/C
          call b%insert(val,row,j)
       enddo
    enddo
  end function right_division_zmatrix_i_csc
  !
  function right_division_zmatrix_d_csc(A,C) result(B)
    real(8),intent(in)             :: C
    type(sparse_zmatrix_csc),intent(in) :: A
    type(sparse_zmatrix_csc)            :: B
    integer                        :: row
    complex(8)                     :: val
    integer                        :: i,j   
    call b%free()
    call b%init(a%Nrow,a%Ncol)
    do j=1,a%Ncol
       do i=1,a%col(j)%size
          row = a%col(j)%rows(i)
          val = a%col(j)%vals(i)/C
          call b%insert(val,row,j)
       enddo
    enddo
  end function right_division_zmatrix_d_csc
  !
  function right_division_zmatrix_z_csc(A,C) result(B)
    complex(8),intent(in)             :: C
    type(sparse_zmatrix_csc),intent(in) :: A
    type(sparse_zmatrix_csc)            :: B
    integer                        :: row
    complex(8)                     :: val
    integer                        :: i,j   
    call b%free()
    call b%init(a%Nrow,a%Ncol)
    do j=1,a%Ncol
       do i=1,a%col(j)%size
          row = a%col(j)%rows(i)
          val = a%col(j)%vals(i)/C
          call b%insert(val,row,j)
       enddo
    enddo
  end function right_division_zmatrix_z_csc

    function left_matmul_dmatrix_darray_csc(C,A) result(B)
    real(8),intent(in),dimension(:)     :: C
    type(sparse_dmatrix_csc),intent(in) :: A
    real(8),dimension(size(C))          :: B
    integer                             :: i,j
    B=0.d0
    if(A%Nrow/=size(C)) stop "size(sparse,1)!=size(array) in left_matmul_dmatrix_darray_csc" 
    do j=1,A%Ncol
       do i=1,A%col(j)%size
          B(j)=B(j)+A%col(j)%vals(i)*C(A%col(j)%rows(i))
       enddo
    end do
  end function left_matmul_dmatrix_darray_csc
  !
  function left_matmul_zmatrix_zarray_csc(C,A) result(B)
    complex(8),intent(in),dimension(:)  :: C
    type(sparse_zmatrix_csc),intent(in) :: A
    complex(8),dimension(size(C))       :: B
    integer                             :: i,j
    B=0.d0
    if(A%Ncol/=size(C)) stop "size(sparse,2)!=size(array) in sparse_matmul_zmatrix_zarray_csc" 
    do j=1,A%Ncol
       do i=1,A%col(j)%size
          B(j)=B(j)+A%col(j)%vals(i)*C(A%col(j)%rows(i))
       enddo
    end do
  end function left_matmul_zmatrix_zarray_csc

  
  !+------------------------------------------------------------------+
  !PURPOSE:  Return the identiy sparse matrix of given dimension
  !+------------------------------------------------------------------+
  ! function zeye_csc(ndim) result(self)
  !   type(sparse_zmatrix_csc) :: self
  !   integer,intent(in)       :: ndim
  !   integer                  :: i
  !   call self%init(ndim,ndim)
  !   do i=1,ndim
  !      call self%insert((1.d0,0.d0),i,i)
  !   end do
  ! end function zeye_csc
  



END MODULE SF_SPARSE_ARRAY_CSC