Search code examples
arrayspointersfortransubroutinedimension

Fortran Subroutine Pointers for Mismatching Array Dimensions


I'm having a problem with Fortran and function/subroutine pointers. I have two functions that take an array as an argument. In f1 it is a(n,n), in f2 it's a(n*n). When I call the subroutine manually, I can do this with the same array:

real :: a(5, 5)
call f1(a, 5)
call f2(a, 5)

But when I try to do this with a pointer, the compiler throws it back at me with this error:

ptr => f2
       1
Error: Interface mismatch in procedure pointer assignment at (1): Type/rank missmatch in argument 'a'

Is there a way around this? I was thinking about pointers, but there I have the same problem, to create it I need to know the number of dimensions.

For reference, here's the complete code (I hope it's not too long..)

program ptrtest
implicit none

interface
    subroutine fnc(a, n)
        integer :: n
        real :: a(n, n)
    end subroutine

    subroutine f1(a, n)
        integer :: n
        real :: a(n, n)
    end subroutine

    subroutine f2(a, n)
        integer :: n

        real :: a(n*n)
    end subroutine
end interface

procedure(fnc), pointer :: ptr => null()
real :: a(5, 5)
real :: b(4, 4)

ptr => f1

call ptr(a, 5)
write(*,*) a

!this one does not work..

!ptr => f2
!
!call ptr(b, 4)
!write(*,*) b

call f2(b, 4)
write(*,*) b
end program

subroutine f1(a, n)
integer :: n
real :: a(n, n)
integer :: i

a = 1
end subroutine

subroutine f2(a, n)
integer :: n
real :: a(n*n)

a = 2
end subroutine

I really hope there is a way to do this. I can't really rewrite all the subroutines so the dimensions of the array match every time :/

Regards, Caba


Solution

  • If I change your example program from using explicit interfaces (through the interface block) to using implicit interfaces (through procedure declarations without mentioning an interface), it appears to work for me.

    So remove the interface block, slightly alter the declaration of ptr, and add procedure declarations for f1 and f2, like this:

    procedure(), pointer :: ptr => null()
    procedure() :: f1, f2
    

    (Alternatively, you can use an external statement for f1, and f2, instead of the procedure statement.)

    I don't know how feasible this is for the real program, because you may need the explicit interfaces if the actual subroutines use some of the features introduced in Fortran 90 and later.