Curious problem with an interface block (converting old code)

I ran into a curious problem with an interface block that I am using while converting an old library. This library contains specific implementations of standard functions like log and exp, the double-precision versions being called dexp and dlog. I have used this interface in a number of source files without any problem:

integer, parameter :: dp = kind(1.0d0)
interface
    real(kind=dp) function dexp( x )     -- why is this a problem?
        import :: dp
        real(kind=dp), intent(in) :: x
    end function dexp
end interface

But with one source file where I use that both gfortran and Intel Fortran claim that something is wrong, but I cannot determine what is wrong, quite probably it is staring me in the face, but I seem to be blind for it (mind you, I simply copied fragments from source files where this was no problem!). My workaround is to comment it out.

Here is the source file:

! dgami.f90 –
! Original:
! july 1977 edition. w. fullerton, c3, los alamos scientific lab.
!
! evaluate the incomplete gamma function defined by
!
! gami = integral from t = 0 to x of exp(-t) * t**(a-1.0) .
!
! gami is evaluated for positive values of a and non-negative values
! of x. a slight deterioration of 2 or 3 digits accuracy will occur
! when gami is very large or very small, because logarithmic variables
! are used.
!
function dgami (a, x)
use ieee_arithmetic

implicit none

integer, parameter :: dp = kind(1.0d0)

interface
    real(kind=dp) function dgamit( a, x )
        import :: dp
        real(kind=dp), intent(in) :: a, x
    end function dgamit

    real(kind=dp) function dlngam( x )
        import :: dp
        real(kind=dp), intent(in) :: x
    end function dlngam

    real(kind=dp) function dexp( x )
        import :: dp
        real(kind=dp), intent(in) :: x
    end function dexp

    real(kind=dp) function dlog( x )
        import :: dp
        real(kind=dp), intent(in) :: x
    end function dlog

    !real(kind=dp) function dexp( x )     -- why is this a problem?
    !    import :: dp
    !    real(kind=dp), intent(in) :: x
    !end function dexp
end interface

real(kind=dp) :: dgami
real(kind=dp) :: a, x

real(kind=dp) :: factor

if ( a <= 0.0d0 .or. x <= 0.0d0 ) then
    dgami = ieee_value( x, ieee_quiet_nan )

else
    dgami = 0.d0

    if ( x /= 0.0d0 ) then
        !
        ! the only error possible in the expression below is a fatal overflow.
        factor = dexp (dlngam(a) + a*dlog(x))

        dgami = factor * dgamit (a, x)
    endif
endif

end function dgami

Can anyone point out what is wrong?

(I also posted this in comp.lang.fortran, but that has been very quiet for the past couple of weeks. I suspect Google is to blame …)

You have twice the same dexp function in the interface block :slight_smile:

1 Like

I do? Oh, dear! That is what you get when you are trying to work fast…

no worries… it happens all the time!

@Arjen,

This is for future reference.

As you look back on this thread and the one at comp.lang.fortran, what you will hopefully notice is you never posted what “both gfortran and Intel Fortran” claimed “is wrong” with your interface block definitions. Isn’t that the basic action all long-time readers including yourself at various forums would inform posters to take?

Aren’t compilers are getting tremendously better after all that the text of the message from those processors would have informed you “why is this a problem?”

real function fn(x)
   real, intent(in) :: x
   interface
      real function foo(x)
         real, intent(in) :: x
      end function 
      real function foo(x)
         real, intent(in) :: x
      end function 
   end interface
   fn = foo(x)
end function 
C:\temp>gfortran -c f.f90
f.f90:7:26:

    7 |       real function foo(x)
      |                          1
Error: Symbol 'foo' at (1) already has an explicit interface
..

Posting the actual code, however, was very useful; which is in my opinion a bigger problem than not showing the errors. When someone just posts a error message with no reproducer it is difficult to deal with. In this case since the simple case you created does not cause the cascade of messages the actual code does that was particularly important and appreciated. In other cases like loading errors the messages and the commands used are the most important. Perhaps directions for everyone somewhat like the rules usually associated with a bug report, how/where to post longer code sections, etc. would be useful; but being too formal would discourage a lot of useful posts, I suspect. Personally, I had been thinking just the opposite earlier – that posting the code was just the right approach for this type of issue!

There are several additional issues with the original post: the reader has to take the code and edit it to perhaps guess at what OP might have experienced e.g.,

  1. Uncomment a section of code viz. the interface block in question
  2. Deal with the hanging text “-- why is this a problem?” and hope that is not what the OP was dealing with.

Then with one of the processors mentioned - Intel Fortran - the reader can arrive at the following and notice the single message error #6623 and find that it is informative enough and wonder what might have been the challenge after all:

C:\temp>ifort /c /standard-semantics dgami.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.7.0 Build 20220726_000000
Copyright (C) 1985-2022 Intel Corporation. All rights reserved.

dgami.f90(42): error #6623: The procedure name of the INTERFACE block conflicts with a name in the encompassing scoping unit. [DEXP]
real(kind=dp) function dexp( x ) ! -- why is this a problem?
-----------------------^
compilation aborted for dgami.f90 (code 1)