@@ -58,6 +58,19 @@ module stdlib_sparse_conversion
5858 #:endfor
5959 end interface
6060 public :: coo2csr
61+
62+ !! version: experimental
63+ !!
64+ !! Conversion from coo to csc
65+ !! Enables transferring data from a COO matrix to a CSC matrix
66+ !! under the hypothesis that the COO is already ordered.
67+ !! [Specifications](../page/specs/stdlib_sparse.html#sparse_conversion)
68+ interface coo2csc
69+ #:for k1, t1, s1 in (KINDS_TYPES)
70+ module procedure :: coo2csc_${s1}$
71+ #:endfor
72+ end interface
73+ public :: coo2csc
6174
6275 !! version: experimental
6376 !!
@@ -111,6 +124,34 @@ module stdlib_sparse_conversion
111124 end interface
112125 public :: csr2sellc
113126
127+ !! version: experimental
128+ !!
129+ !! Conversion from csc to coo
130+ !! Enables transferring data from a CSC matrix to a COO matrix
131+ !! under the hypothesis that the CSC is already ordered.
132+ !! [Specifications](../page/specs/stdlib_sparse.html#sparse_conversion)
133+ interface csc2coo
134+ #:for k1, t1, s1 in (KINDS_TYPES)
135+ module procedure :: csc2coo_${s1}$
136+ #:endfor
137+ end interface
138+ public :: csc2coo
139+
140+ !! version: experimental
141+ !!
142+ !! Extraction of diagonal values
143+ !! [Specifications](../page/specs/stdlib_sparse.html#sparse_conversion)
144+ interface diag
145+ #:for k1, t1, s1 in (KINDS_TYPES)
146+ module procedure :: dense2diagonal_${s1}$
147+ module procedure :: coo2diagonal_${s1}$
148+ module procedure :: csr2diagonal_${s1}$
149+ module procedure :: csc2diagonal_${s1}$
150+ module procedure :: ell2diagonal_${s1}$
151+ #:endfor
152+ end interface
153+ public :: diag
154+
114155 !! version: experimental
115156 !!
116157 !! Enable creating a sparse matrix from ijv (row,col,data) triplet
@@ -202,6 +243,45 @@ contains
202243
203244 #:endfor
204245
246+ #:for k1, t1, s1 in (KINDS_TYPES)
247+ subroutine coo2csc_${s1}$(COO,CSC)
248+ type(COO_${s1}$_type), intent(in) :: COO
249+ type(CSC_${s1}$_type), intent(out) :: CSC
250+ ${t1}$, allocatable :: data(:)
251+ integer(ilp), allocatable :: temp(:,:)
252+ integer(ilp) :: i, nnz
253+
254+ CSC%nnz = COO%nnz; CSC%nrows = COO%nrows; CSC%ncols = COO%ncols
255+ CSC%storage = COO%storage
256+
257+ allocate(temp(2,COO%nnz))
258+ temp(1,1:COO%nnz) = COO%index(2,1:COO%nnz)
259+ temp(2,1:COO%nnz) = COO%index(1,1:COO%nnz)
260+ allocate(data, source = COO%data )
261+ nnz = COO%nnz
262+ call sort_coo_unique_${s1}$( temp, data, nnz, COO%nrows, COO%ncols )
263+
264+ if( allocated(CSC%row) ) then
265+ CSC%row(1:COO%nnz) = temp(2,1:COO%nnz)
266+ CSC%colptr(1:CSC%ncols) = 0
267+ CSC%data(1:CSC%nnz) = data(1:COO%nnz)
268+ else
269+ allocate( CSC%row(CSC%nnz) , source = temp(2,1:COO%nnz) )
270+ allocate( CSC%colptr(CSC%ncols+1) , source = 0 )
271+ allocate( CSC%data(CSC%nnz) , source = data(1:COO%nnz) )
272+ end if
273+
274+ CSC%colptr(1) = 1
275+ do i = 1, COO%nnz
276+ CSC%colptr( temp(1,i)+1 ) = CSC%colptr( temp(1,i)+1 ) + 1
277+ end do
278+ do i = 1, CSC%ncols
279+ CSC%colptr( i+1 ) = CSC%colptr( i+1 ) + CSC%colptr( i )
280+ end do
281+ end subroutine
282+
283+ #:endfor
284+
205285 #:for k1, t1, s1 in (KINDS_TYPES)
206286 subroutine csr2dense_${s1}$(CSR,dense)
207287 type(CSR_${s1}$_type), intent(in) :: CSR
@@ -254,6 +334,33 @@ contains
254334
255335 #:endfor
256336
337+ #:for k1, t1, s1 in (KINDS_TYPES)
338+ subroutine csc2coo_${s1}$(CSC,COO)
339+ type(CSC_${s1}$_type), intent(in) :: CSC
340+ type(COO_${s1}$_type), intent(out) :: COO
341+ integer(ilp) :: i, j
342+
343+ COO%nnz = CSC%nnz; COO%nrows = CSC%nrows; COO%ncols = CSC%ncols
344+ COO%storage = CSC%storage
345+
346+ if( .not.allocated(COO%data) ) then
347+ allocate( COO%data(CSC%nnz) , source = CSC%data(1:CSC%nnz) )
348+ else
349+ COO%data(1:CSC%nnz) = CSC%data(1:CSC%nnz)
350+ end if
351+
352+ if( .not.allocated(COO%index) ) allocate( COO%index(2,CSC%nnz) )
353+
354+ do j = 1, CSC%ncols
355+ do i = CSC%colptr(j), CSC%colptr(j+1)-1
356+ COO%index(1:2,i) = [CSC%row(i),j]
357+ end do
358+ end do
359+ call sort_coo_unique_${s1}$( COO%index, COO%data, COO%nnz, COO%nrows, COO%ncols )
360+ end subroutine
361+
362+ #:endfor
363+
257364 #:for k1, t1, s1 in (KINDS_TYPES)
258365 subroutine csr2ell_${s1}$(CSR,ELL,num_nz_rows)
259366 type(CSR_${s1}$_type), intent(in) :: CSR
@@ -712,4 +819,119 @@ contains
712819 end subroutine
713820 #:endfor
714821
822+ !! Diagonal extraction
823+
824+ #:for k1, t1, s1 in (KINDS_TYPES)
825+ subroutine dense2diagonal_${s1}$(dense,diagonal)
826+ ${t1}$, intent(in) :: dense(:,:)
827+ ${t1}$, intent(inout), allocatable :: diagonal(:)
828+ integer :: num_rows
829+ integer :: i
830+
831+ num_rows = size(dense,dim=1)
832+ if(.not.allocated(diagonal)) allocate(diagonal(num_rows))
833+
834+ do i = 1, num_rows
835+ diagonal(i) = dense(i,i)
836+ end do
837+ end subroutine
838+
839+ #:endfor
840+
841+ #:for k1, t1, s1 in (KINDS_TYPES)
842+ subroutine coo2diagonal_${s1}$(COO,diagonal)
843+ type(COO_${s1}$_type), intent(in) :: COO
844+ ${t1}$, intent(inout), allocatable :: diagonal(:)
845+ integer :: idx
846+
847+ if(.not.allocated(diagonal)) allocate(diagonal(COO%nrows))
848+
849+ do concurrent(idx = 1:COO%nnz)
850+ if(COO%index(1,idx)==COO%index(2,idx)) &
851+ & diagonal( COO%index(1,idx) ) = COO%data(idx)
852+ end do
853+ end subroutine
854+
855+ #:endfor
856+
857+ #:for k1, t1, s1 in (KINDS_TYPES)
858+ subroutine csr2diagonal_${s1}$(CSR,diagonal)
859+ type(CSR_${s1}$_type), intent(in) :: CSR
860+ ${t1}$, intent(inout), allocatable :: diagonal(:)
861+ integer :: i, j
862+
863+ if(.not.allocated(diagonal)) allocate(diagonal(CSR%nrows))
864+
865+ select case(CSR%storage)
866+ case(sparse_lower)
867+ do i = 1, CSR%nrows
868+ diagonal(i) = CSR%data( CSR%rowptr(i+1)-1 )
869+ end do
870+ case(sparse_upper)
871+ do i = 1, CSR%nrows
872+ diagonal(i) = CSR%data( CSR%rowptr(i) )
873+ end do
874+ case(sparse_full)
875+ do i = 1, CSR%nrows
876+ do j = CSR%rowptr(i), CSR%rowptr(i+1)-1
877+ if( CSR%col(j) == i ) then
878+ diagonal(i) = CSR%data(j)
879+ exit
880+ end if
881+ end do
882+ end do
883+ end select
884+ end subroutine
885+
886+ #:endfor
887+
888+ #:for k1, t1, s1 in (KINDS_TYPES)
889+ subroutine csc2diagonal_${s1}$(CSC,diagonal)
890+ type(CSC_${s1}$_type), intent(in) :: CSC
891+ ${t1}$, intent(inout), allocatable :: diagonal(:)
892+ integer :: i, j
893+
894+ if(.not.allocated(diagonal)) allocate(diagonal(CSC%nrows))
895+
896+ select case(CSC%storage)
897+ case(sparse_lower)
898+ do i = 1, CSC%ncols
899+ diagonal(i) = CSC%data( CSC%colptr(i+1)-1 )
900+ end do
901+ case(sparse_upper)
902+ do i = 1, CSC%ncols
903+ diagonal(i) = CSC%data( CSC%colptr(i) )
904+ end do
905+ case(sparse_full)
906+ do i = 1, CSC%ncols
907+ do j = CSC%colptr(i), CSC%colptr(i+1)-1
908+ if( CSC%row(j) == i ) then
909+ diagonal(i) = CSC%data(j)
910+ exit
911+ end if
912+ end do
913+ end do
914+ end select
915+ end subroutine
916+
917+ #:endfor
918+
919+ #:for k1, t1, s1 in (KINDS_TYPES)
920+ subroutine ell2diagonal_${s1}$(ELL,diagonal)
921+ type(ELL_${s1}$_type), intent(in) :: ELL
922+ ${t1}$, intent(inout), allocatable :: diagonal(:)
923+ integer :: i, k
924+
925+ if(.not.allocated(diagonal)) allocate(diagonal(ELL%nrows))
926+ if( ELL%storage == sparse_full) then
927+ do i = 1, ELL%nrows
928+ do k = 1, ELL%K
929+ if(ELL%index(i,k)==i) diagonal(i) = ELL%data(i,k)
930+ end do
931+ end do
932+ end if
933+ end subroutine
934+
935+ #:endfor
936+
715937end module
0 commit comments