MODULE SF_SPARSE_COMMON USE SF_LINALG, only: deye,zeye implicit none interface append module procedure :: append_I module procedure :: append_D module procedure :: append_Z end interface append !SPARSE MATRIX type sparse_matrix integer :: Nrow integer :: Ncol integer :: Nelements logical :: status=.false. contains procedure,pass :: shape => shape_matrix end type sparse_matrix !RETURN SHAPE OF THE SPARSE MATRIX [Nrow,Ncol] interface shape module procedure :: shape_matrix end interface shape public :: shape contains !+------------------------------------------------------------------+ !PURPOSE: Return the shape of a sparse matrix !+------------------------------------------------------------------+ function shape_matrix(self) result(shape) class(sparse_matrix),intent(in) :: self integer,dimension(2) :: shape shape = [self%Nrow,self%Ncol] end function shape_matrix !+------------------------------------------------------------------+ !PURPOSE : Sort an array, gives the new ordering of the label. !+------------------------------------------------------------------+ subroutine sort_array(array,order) integer,dimension(:) :: array integer,dimension(size(array)) :: order integer,dimension(size(array)) :: backup integer :: i forall(i=1:size(array))order(i)=i call qsort_sort(array, order,1, size(array)) do i=1,size(array) backup(i)=array(order(i)) enddo array=backup contains recursive subroutine qsort_sort( array, order, left, right ) integer, dimension(:) :: array integer, dimension(:) :: order integer :: left integer :: right integer :: i integer :: last if ( left .ge. right ) return call qsort_swap( order, left, qsort_rand(left,right) ) last = left do i = left+1, right if ( compare(array(order(i)), array(order(left)) ) .lt. 0 ) then last = last + 1 call qsort_swap( order, last, i ) endif enddo call qsort_swap( order, left, last ) call qsort_sort( array, order, left, last-1 ) call qsort_sort( array, order, last+1, right ) end subroutine qsort_sort !---------------------------------------------! subroutine qsort_swap( order, first, second ) integer, dimension(:) :: order integer :: first, second integer :: tmp tmp = order(first) order(first) = order(second) order(second) = tmp end subroutine qsort_swap !---------------------------------------------! integer function qsort_rand( lower, upper ) integer :: lower, upper real(8) :: r call random_number(r) qsort_rand = lower + nint(r * (upper-lower)) end function qsort_rand !---------------------------------------------! function compare(f,g) implicit none integer :: f,g integer :: compare if(f<g) then compare=-1 else compare=1 endif end function compare end subroutine sort_array !################################################################## ! AUXILIARY COMPUTATIONAL ROUTINES !################################################################## recursive function binary_search(Ain,value) result(bsresult) integer,intent(in) :: Ain(:), value integer :: bsresult, mid integer,dimension(size(Ain)) :: A,Order ! a = ain call sort_array(a,Order) ! mid = size(a)/2 + 1 if (size(a) == 0) then bsresult = 0 ! not found !stop "binary_search error: value not found" else if (a(mid) > value) then bsresult= binary_search(a(:mid-1), value) else if (a(mid) < value) then bsresult = binary_search(a(mid+1:size(a)), value) if (bsresult /= 0) then bsresult = mid + bsresult end if else bsresult = mid ! SUCCESS ! end if ! bsresult = Order(bsresult) ! end function binary_search subroutine append_I(vec,val) integer,dimension(:),allocatable,intent(inout) :: vec integer,intent(in) :: val integer,dimension(:),allocatable :: tmp integer :: n ! if (allocated(vec)) then n = size(vec) allocate(tmp(n+1)) tmp(:n) = vec call move_alloc(tmp,vec) n = n + 1 else n = 1 allocate(vec(n)) end if ! !Put val as last entry: vec(n) = val ! if(allocated(tmp))deallocate(tmp) end subroutine append_I subroutine append_D(vec,val) real(8),dimension(:),allocatable,intent(inout) :: vec real(8),intent(in) :: val real(8),dimension(:),allocatable :: tmp integer :: n ! if (allocated(vec)) then n = size(vec) allocate(tmp(n+1)) tmp(:n) = vec call move_alloc(tmp,vec) n = n + 1 else n = 1 allocate(vec(n)) end if ! !Put val as last entry: vec(n) = val ! if(allocated(tmp))deallocate(tmp) end subroutine append_D subroutine append_Z(vec,val) complex(8),dimension(:),allocatable,intent(inout) :: vec complex(8),intent(in) :: val complex(8),dimension(:),allocatable :: tmp integer :: n ! if (allocated(vec)) then n = size(vec) allocate(tmp(n+1)) tmp(:n) = vec call move_alloc(tmp,vec) n = n + 1 else n = 1 allocate(vec(n)) end if ! !Put val as last entry: vec(n) = val ! if(allocated(tmp))deallocate(tmp) end subroutine append_Z END MODULE SF_SPARSE_COMMON