program sprs_mat
implicit none
type:: mat_cell
	integer:: row
	integer:: col
	integer:: val
	type(mat_cell),pointer:: rt,dn
end type

type(mat_cell),target:: anchor !first cell
type(mat_cell),pointer::moving,moving1
integer:: nrows,ncols

call init_opns
call create_guards
call print_guards
call read_mat
call print_guards
write(*,'("The matrix values are")')
call print_mat

contains

subroutine init_opns
anchor%row=0
anchor%col=0
anchor%val=0
nullify(anchor%rt,anchor%dn)
write(*,'("Give row and col values")')
read *, nrows, ncols
end subroutine

!adding linked list elts
subroutine add_elt(direction,r_val,c_val,e_val) 
integer,intent(in):: direction,r_val,c_val,e_val
type(mat_cell),pointer::temp
nullify(temp)
allocate(temp)
temp%row=r_val
temp%col=c_val
temp%val=e_val
nullify(temp%rt,temp%dn)
if (direction==1) then !row linking
	moving%rt=>temp
	moving=>moving%rt
else !col linking
	moving%dn=>temp
	moving=>moving%dn
end if
end subroutine

!create guards 
subroutine create_guards
integer:: i,j
moving=>anchor
do i=1,nrows
	call add_elt(2,i,0,0) !2 for col linking
end do
moving=>anchor
do j=1,ncols
	call add_elt(1,0,j,0)
end do
end subroutine

!printing the guards
subroutine print_guards
moving=>anchor
do 
	write(*,'(3i2," ")',advance='no') moving%row,moving%col,moving%val
	moving=>moving%rt
	if (.not.associated(moving)) exit
end do
write(*,*)
moving=>anchor%dn
do 
	write(*,'(3i2)') moving%row,moving%col,moving%val
	moving=>moving%dn
	if (.not.associated(moving)) exit
end do
end subroutine

!read matrix
subroutine read_mat
integer:: i,j
integer:: r,c,v,nvals
write(*,'("Give the no. of non-zero elements")')
read *,nvals
print *, "nvals=",nvals
do i=1,nvals
	write(*,'("Give row, col and elt values")')
	read *, r, c, v
	!move down to the rth row guard
	moving=>anchor
	do j=1,r
		moving=>moving%dn
	end do
        !increment count in the row guard
	moving%val=moving%val+1 
	do 
		if (.not. associated(moving%rt)) exit
		moving=>moving%rt
	end do
	call add_elt(1,r,c,v) !1 for row linking
	moving1=>moving
	!move right to the cth col guard
	moving=>anchor
	do j=1,c
		moving=>moving%rt
	end do
        !increment count in the row guard
	moving%val=moving%val+1 
	do 
		if (.not. associated(moving%dn)) exit
		moving=>moving%dn
	end do
	moving%dn=>moving1	
end do
end subroutine

!print matrix
subroutine print_mat
integer::i
integer:: zero=0 !'zero' for actual printing of 0
moving=>anchor%dn
do
	moving1=>moving
	do
		if (.not.associated(moving%rt)) then
			do i=moving%col+1,ncols
				write(*,'(i2)',advance='no') zero
			end do
			exit
		else
			do i=moving%col+2,moving%rt%col
				write(*,'(i2)',advance='no') zero
			end do
			write(*,'(i2)',advance='no') moving%rt%val
		end if
		!advance both pointers
		moving=>moving%rt
	end do
	write(*,*) !end of line after the row printing is over
	moving=>moving1%dn
	if (.not.associated(moving)) exit
end do
end subroutine
end program
