washout13
washout13

Reputation: 43

Fortran submodules sharing same interface

I'm thinking of using the submodule feature in Fortran and have setup a small test example. I have two questions related to their usage. Below is the example code:

module points
    type :: point
        real :: x, y
    end type point

    interface
        module function point_dist(a, b) result(distance)
            type(point), intent(in) :: a, b
            real :: distance
        end function point_dist
    end interface
end module points

submodule (points) points_a

contains
    module procedure point_dist
        distance = sqrt((a%x - b%x)**2 + (a%y - b%y)**2)
    end procedure point_dist

end submodule points_a

This works and in my program I can just use it as such:

program test

    use points

    real(kind(1.0D0)) :: result
    type (point) :: p1, p2

    p1%x = 1
    p1%y = 1

    p2%x = 2
    p2%y = 2

    result = point_dist(p1, p2)

    write(*,*) result

end program test

Questions

1) However I was wondering if it is possible to have two submodules that use the same interface but provide different outcomes. This has some uses where we have different formulae calculating the same physical quantity. Below is how I imagined it would work, even though it does not.

module points
    type :: point
        real :: x, y
    end type point

    interface
        module function point_dist(a, b) result(distance)
            type(point), intent(in) :: a, b
            real :: distance
        end function point_dist
    end interface
end module points

submodule (points) points_a

contains
    module procedure point_dist
        distance = sqrt((a%x - b%x)**2 + (a%y - b%y)**2)
    end procedure point_dist

end submodule points_a

submodule (points) points_b

contains
    module procedure point_dist
        distance = 2.0*sqrt((a%x - b%x)**2 + (a%y - b%y)**2)
    end procedure point_dist

end submodule points_b

I get an error in the program as I only have the statement use points and it complains about duplicate definitions of point_dist. Is is possible to specify which submodule I want to use?

2) I also looked but couldn't find out if it is possible to use the same module level interface for different procedures inside the same submodule. In my head it would be something like:

module points
    type :: point
        real :: x, y
    end type point

    interface
        module function point_dist(a, b) result(distance)
            type(point), intent(in) :: a, b
            real :: distance
        end function point_dist
    end interface
end module points

submodule (points) points_a

contains
    module procedure (type=point_dist) point_dist_a
        distance = sqrt((a%x - b%x)**2 + (a%y - b%y)**2)
    end procedure point_dist_a

    module procedure (type=point_dist) point_dist_b
        distance = 2.0*sqrt((a%x - b%x)**2 + (a%y - b%y)**2)
    end procedure point_dist_b

end submodule points_a

Although I realise that this could lead to some quite misleading and hard to follow code.

(I'm using gfortran 8.3.0 on OS X)

Upvotes: 0

Views: 340

Answers (1)

Rodrigo Rodrigues
Rodrigo Rodrigues

Reputation: 8546

1) However I was wondering if it is possible to have two submodules that use the same interface but provide different outcomes. This has some uses where we have different formulae calculating the same physical quantity.

If this were possible, how were you plannig to make use of it? I mean, if you have two different implementations avaliable for a function point_dist thay may yield different outcomes, you wouldn´t want to mismatch them, would you?

If you want them to have the same name, you (and the compiler) must be able to identify which one you're calling. This is usually done with function overloading. In Fortran, you may have a generic interface. BUT the dispatched funtions MUST differ in their interface (argument types and/or quantity, position, among other rules). You know, how would anyone else know which of the two you do mean?

2) I also looked but couldn't find out if it is possible to use the same module level interface for different procedures inside the same submodule.

As I said, an interface can indeed encapsulate multiple procedures, if they are distinguishible.

module points
    type :: point
        real :: x, y
    end type point

    interface point_dist
        module function point_dist_a(a, b) result(distance)
            type(point), intent(in) :: a, b
            real :: distance
        end function
        module function point_dist_b(a, b, k) result(distance)
            type(point), intent(in) :: a, b
            real, intent(in) :: k
            real :: distance
        end function
    end interface
end module points

submodule (points) points_a

contains
    module procedure point_dist_a
        distance = sqrt((a%x - b%x)**2 + (a%y - b%y)**2)
    end procedure point_dist_a

end submodule points_a

submodule (points) points_b

contains
    module procedure point_dist_b
        distance = k*sqrt((a%x - b%x)**2 + (a%y - b%y)**2)
    end procedure point_dist_b

end submodule points_b

Testing:

program test

    use points

    real(kind(1.0D0)) :: result
    type (point) :: p1, p2

    p1%x = 1
    p1%y = 1

    p2%x = 2
    p2%y = 2

    result = point_dist(p1, p2)
    write(*,*) result

    result = point_dist(p1, p2, 2.0)
    write(*,*) result

end program test

As an end note, submodules have absolutely nothing to do with all this.

Upvotes: 3

Related Questions