!generic procedures
!a subroutine to add any data type int,real,string,composite data
!use of interface

module generic_add
type:: vect
	real::x
	real::y
end type

interface add_data_type_indep
	module procedure add_i
	module procedure add_r
	module procedure add_s
	module procedure add_v
end interface

contains

subroutine add_i(i,j,k)
integer,intent(in)::i,j
integer,intent(out)::k
	k=i+j
end subroutine add_i

subroutine add_r(x,y,z)
real,intent(in)::x,y
real,intent(out)::z
	z=x+y
end subroutine add_r

subroutine add_s(s1,s2,s3)
character(len=*),intent(in)::s1,s2
character(len=*),intent(out)::s3
	s3=trim(s1)//trim(s2)
end subroutine add_s

subroutine add_v(v1,v2,v3)
type(vect),intent(in)::v1,v2
type(vect),intent(out)::v3
	v3%x=v1%x+v2%x
	v3%y=v1%y+v2%y
end subroutine add_v
end module


program generic_add_test
use generic_add
implicit none

integer:: i,j,k ! k=i+j
real:: x,y,z ! z=x+y
character(len=10)::str1,str2
character(len=20)::str3 !str3=str1//str2
type(vect)::v1,v2,v3 !v3=v1+v2

write(*,'("Give integers i,j")')
read *, i,j
write(*,'("Give reals x,y")')
read *, x,y
write(*,'("Give strings str1,str2")')
read *, str1,str2
write(*,'("Give vectors v1,v2")')
call read_vect(v1)
call read_vect(v2)
 
call add_data_type_indep(i,j,k)
call add_data_type_indep(x,y,z)
call add_data_type_indep(str1,str2,str3)
call add_data_type_indep(v1,v2,v3)

write (*,*)
write (*,10) k
write (*,20) z
write (*,30) str3
call print_vect(v3)

10 format("Integer addition result=",i3)
20 format("Real addition result=",f5.2)
30 format("String addition result=",a)

contains

subroutine read_vect(v)
type(vect),intent(out)::v
	read *, v%x,v%y
end subroutine

subroutine print_vect(v)
type(vect),intent(in)::v
	write(*,40) v%x,v%y
	40 format("Vector addition result=",f5.2,"i+",f5.2,"j")
end subroutine
end program

