I'm trying to use a procedure pointer (new feature in Fortran 2003) to point to an elemental function but it does not work. I really need the function to be ELEMENTAL
and need a pointer to it. Is it truly impossible to point to an elemental function in Fortran?
module elemfunc
implicit none
contains
elemental function fun111(x) result(y)
real*8, intent(in) :: x
real*8 :: y
y = x**2+1
end function fun111
end module elemfunc
program testptr
use elemfunc
implicit none
interface
elemental function func (z)
real*8 :: func
real*8, intent (in) :: z
end function func
end interface
procedure (func), pointer :: ptr
ptr => fun111
print *, ptr( (/1.0d0,2.0d0/) )
end program testptr
Error message:
main.f90:12.7:ptr=>fun111
1
Nonintrinstic elemental procedure pointer 'func111' is invalid in procedure pointer assignment at (1)
In paragraph 7.4.2 Pointer Assignment
of the fortran 2003 standard it is explicitly stated that this is not allowed:
C728 (R742) The proc-target shall not be a nonintrinsic elemental procedure
(This constraint is still there in the fortran 2008 standard, so it hasn't been relaxed.)
I had this exact same issue and did not even realize it was an issue until I compiled with gfortran. Unfortunately, it is also forbidden to have dummy procedure arguments to elemental procedures. It is, however, still possible to achieve the functionality you want, though it is a bit kludgy.
What you can legally do is have an elemental function call a pure function. Depending on your needs, the elemental function can be type bound or not.
Put the procedure pointer and function inside a module:
module A
implicit none
procedure(func_IF), pointer :: ptr => null()
abstract interface
pure function func_IF(x)
real, intent(in) :: x
real :: func_IF
end function
end interface
contains
! Non type bound elemental
elemental function myfun1(x) result(r)
real, intent(in) :: x
real :: r
if(associated(ptr)) r = ptr(x)
end function
end module
Put both pointer and function inside a derived type:
module B
implicit none
type :: foo
procedure(func_IF), nopass, pointer :: ptr => null()
contains
procedure, pass :: myfun2
end type
abstract interface
pure function func_IF(x)
real, intent(in) :: x
real :: func_IF
end function
end interface
contains
! Type bound elemental
elemental function myfun2(this, x) result(r)
class(foo), intent(in) :: this
real, intent(in) :: x
real :: r
if(associated(this%ptr)) r = this%ptr(x)
end function
end module
A small test program:
program main
use A
use B
implicit none
type(foo) :: myfoo
myfoo%ptr => bar
ptr => bar
print*, myfun1([10., 20.])
print*, myfoo%myfun2([10., 20.])
contains
! Demo pure function with interface func_IF
pure function bar(x)
real, intent(in) :: x
real :: bar
bar = x**2
end function
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With