I have a polynomial class TPoly
, see the code below, which takes an array of coefficients coefs
and evaluates the polynomial at some point x
using the eval
method. I was wondering whether it is possible to evaluate the polynomial directly by making the instance p
callable, i.e. instead of p%eval(x)
use p(x)
. In Python, the desirable behaviour can be achieved by defining the __call__
method. Does something similar exist in Fortran?
I want to make another class which will contain many TPoly
attributes and I would like to avoid chaining of component selections object%poly1%eval(x)
. A function pointer to a class method would solve my problem but I found that it is not possible, see another thread.
module polymod
implicit none
integer, parameter :: rp = kind(1.0d0)
! polynomial class
type :: TPoly
real(rp), allocatable :: coefs(:)
contains
procedure, pass :: eval => eval_poly
end type
contains
real(rp) function eval_poly(self, x)
class(TPoly), intent(in) :: self
real(rp), intent(in) :: x
eval_poly = polynomial(x, self%coefs)
end function eval_poly
! use Horner's method to evaluate polynomial
real(rp) function polynomial(x, coefs)
real(rp), intent(in) :: x, coefs(:)
real(rp) :: p
integer :: n, i
n = size(coefs)
p = coefs(n)
do i = n-1, 1, -1
p = p * x + coefs(i)
end do
polynomial = p
end function polynomial
end module polymod
program main
use polymod
implicit none
type(TPoly) :: p
real(rp) :: coefs(3)
real(rp) :: x = 2.0_rp
coefs = (/3.0_rp, -1.0_rp, 1.0_rp/)
p = TPoly(coefs)
print *, p%eval(x)
! I would like to use
! print *, p(x)
end program main
Unfortunately, no, this is not possible. To my knowledge there is no nice workaround which would simulate the behaviour either.
If it were possible, it would need to avoid conflicting with Fortran's array access syntax. Consider the following:
program main
use polymod
implicit none
! Declare an array of type TPoly.
type(TPoly) :: p(1)
! Initialise the array.
p = [TPoly(coefs=[3.0_rp, -1.0_rp, 1.0_rp])]
! Try to print.
print *, p(1)
end program
There would be no way for the compiler to distinguish between p(1)
referring to the first element of the array p
vs p(1)
calling the class function as an elemental
function acting on every element of p
with argument 1
.
You could distinguish the two for non-elemental functions, but you would need some syntax like p(1)(2.0_rp)
, and such syntax doesn't exist in this context in Fortran as it stands.