Arguments of different types in a same Fortran subroutine

Viewed 184

I want to define a subroutine in modern fortran (90 or newer) to print a matrix (with integer or real numbers) or vectors (with integer o numbers).

SUBROUTINE print_matrix_vector( A )

! WHAT TYPE CAN I WRITE TO A ???

END SUBROUTINE 

Of course, I wanted to call a subrutine

CALL print_matrix_vector( A )

independent if A is a matrix of real or integer numbers, and if A is a vector of real or integer numbers.

Thanks in advance for your comments. I think this is something very usual, but I did not find nothing clear.

1 Answers

So Fortran uses interface statements to declare overloads to functions. I have done the exact same thing recently. The key is to create an interface, I call show which is used as an alias for all the separate functions needed.

interface show
    procedure show_vector_i, show_vector_r, show_vector_d
    procedure show_matrix_i, show_matrix_r, show_matrix_d
end interface

Here is the output first.

 Display Matrices/Vectors

 vector=
    1
    2
    3
    4

 matrix=
    1    5    9   13
    2    6   10   14
    3    7   11   15
    4    8   12   16

 A=
 4.47723     3.36660     1.48809    -.752551
 6.36660     7.19091     6.67333     5.54482
 7.48809     9.67333     10.1187     9.77902
 8.24745     11.5448     12.7790     13.0861

 u=
 6.36660
 7.19091
 6.67333
 5.54482

 v=
 3.36660
 7.19091
 9.67333
 11.5448

and the code

program FortranConsole1
use, intrinsic :: iso_fortran_env
implicit none

interface show
    procedure show_matrix_i, show_matrix_r, show_matrix_d
    procedure show_vector_r, show_vector_d
end interface

integer :: row(16), matrix(4,4), i
real(real64), allocatable, target :: A(:,:)
real(real64), pointer :: B(:,:)
real(real64), allocatable :: v(:), u(:)

row = [(i,i=1,16)]
matrix = reshape( row, [4, 4])

print *, "Display Matrices/Vectors"
print *, ""

print *, "vector="
call show(row(1:4))

print *, "matrix="
call show(matrix)

A = dble(matrix)

A = sqrt( matmul( transpose(A), A) ) - A

print *, "A="
call show(A)

v = A(:,2)
u = A(2,:)

print *, "u="
call show(u)
print *, "v="
call show(v)
    

contains

subroutine show_vector_i(v, w)
! Display the vector 'v' in a single column
!   v : the array of real numbers
!   w : the column width. default = 5
!   s : sig. figures w-5 (calculated)
    integer, intent(in) :: v(:)
    integer, intent(in), optional :: w
    integer :: i,n,wt
    character(len=16) :: fmt
    if(present(w)) then
        wt = w
    else
        wt = 5
    end if
    n = size(v)
    write( fmt, "(a,g0,a)") "(*(g",wt,".0))"
    write( * , fmt ) ( v(i), new_line("A"), i=1,n )    
end subroutine

subroutine show_vector_r(v, w)
! Display the vector 'v' in a single column
!   v : the array of real numbers
!   w : the column width. deafult = 12
!   s : sig. figures w-5 (calculated)
    real(real32), intent(in) :: v(:)
    integer, intent(in), optional :: w
    integer :: i,n,dg,wt
    character(len=16) :: fmt
    if(present(w)) then
        wt = w
    else
        wt = 12
    end if
    dg = wt - 6
    n = size(v)
    write( fmt, "(a,g0,a,g0,a)") "(*(g",wt,".",dg,"))"
    write( * , fmt ) ( v(i), new_line("A"), i=1,n )    
end subroutine

subroutine show_vector_d(v, w)
! Display the vector 'v' in a single column
!   v : the array of real numbers
!   w : the column width. deafult = 12
!   s : sig. figures w-5 (calculated)
    real(real64), intent(in) :: v(:)
    integer, intent(in), optional :: w
    call show_vector_r(real(v),w)
end subroutine

subroutine show_matrix_i(A, w)
! Display the matrix 'A' in columns
!   A : the array of integers
!   w : the column width. Default = 5
    integer, intent(in) :: A(:,:)
    integer, intent(in), optional :: w
    integer :: i,j,n,m, wt
    character(len=16) :: fmt
    if(present(w)) then
        wt = w
    else
        wt = 5
    end if
    n = size(A,1)
    m = size(A,2)
    write( fmt, "(a,g0,a)") "(*(g",wt,".0))"        
    write( * , fmt ) ( (A(i,j),j=1,m), new_line("A"), i=1,n )
end subroutine

subroutine show_matrix_r(A, w)
! Display the matrix 'A' in columns
!   A : the array of real numbers
!   w : the column width. deafult = 12
!   s : sig. figures w-5 (calculated)
    real(real32), intent(in) :: A(:,:)
    integer, intent(in), optional :: w
    integer :: i,j,n,m,dg,wt
    character(len=16) :: fmt
    if(present(w)) then
        wt = w
    else
        wt = 12
    end if
    dg = wt - 6
    n = size(A,1)
    m = size(A,2)
    write( fmt, "(a,g0,a,g0,a)") "(*(g",wt,".",dg,"))"
    write( * , fmt ) ( (A(i,j),j=1,m), new_line("A"), i=1,n )
end subroutine

subroutine show_matrix_d(A,w)
! Display the matrix 'A' in columns
!   A : the array of dble numbers
!   w : the column width. default = 12
! Converts 'A' into single precision and calls `show_matrix_r`
    real(real64), intent(in) :: A(:,:)
    integer, intent(in), optional :: w
    call show_matrix_r(real(A),w)
end subroutine

end program FortranConsole1

In reality, the functions should be in a module file in order to be reused again and again in different programs.

Related