Re: (very) slow recursive function
- From: mecej4@xxxxxxxxx
- Date: 30 Oct 2006 08:09:53 -0800
Ralf Schaa wrote:
Hi there,
for computing Bessel functions and Legendre polynomials there exists
recursive formulas (see for example Numerical Recipes in F77, p.172),
which can be implemented straightforward using only a few lines of
Fortran. Comparing with iterative (and much more sophisticated)
versions, the recursive versions are *really* slow.
The example below computes the Legendre polynomials recursively as
given in equations (6.8.7), (6.8.8) and (6.8.9) from Numerical Recipes
in F77, p.247
Only for 'l' up to 20 this version is suitable, for higher orders it is
really slow and takes ages. The iterative version from Numerical
Recipes however has no problems at all. Similar problems are
encountered with the computation of the modified Bessel functions with
fractional order ...
So my question: why is this so slow compared with the iterative
versions. Is this an 'inherently' problem of recursion? Is it my
program?
Cheers
-Ralf
Example:
pure recursive function legendrePoly(x,m,l) result(Plm)
! Computes the (associated) Legendre polynomial Plm(x)
! with (0 <= m <= l) and (-1 <= x <= 1) after the recursive
! formula in Numerical Recipes in Fortran 77 (Volume 1, p. 247).
! 'Ordinary' Legendre polynomals are given for m=0.
!
! Calls: pure recursive function ifact -> double factorial n!!
implicit none
real(dp) :: Plm
real(dp), intent(in) :: x
integer, intent(in) :: m
integer, intent(in) :: l
if(l == m) then
Plm = (-1)**m * ifact(2.0d0*m-1.0d0) * (1.0d0-x**2)**(m/2.0d0)
elseif(l == m-1) then
Plm = 0.0d0
else
Plm = (x*(2.0d0*l-1.0d0)*legendrePoly_(x,m,l-1) - &
(l+m-1.0d0)*legendrePoly_(x,m,l-2)) / (l-m)
endif
end function legendrePoly
First of all, an aside on the comment in your code: The condition m <=
l is neither necessary (this is a property of the Legendre functions)
nor honored during the course of the recursion.
If you wish to retain the benefits of recursion, but wish to improve
efficiency, a simple means is to maintain two associated global arrays,
one boolean (b) and another real (p). In the user code that calls Plm,
initialize the booleans to false before calling Plm. At the top of your
function Plm, check to see whether b(l) is true; if so, set Plm to p(l)
and return immediately. If not, use the recursion rule and update b(l)
and p(l) before returning.
If the user code makes more than one call to Plm, the initialization
needs to be done every time m or x is changed, or b and p will need to
become two or three dimensional arrays.
Alas, this bookkeeping improves the efficiency but makes the Plm
function impure.
.
- References:
- (very) slow recursive function
- From: Ralf Schaa
- (very) slow recursive function
- Prev by Date: Re: Online F77 information...
- Next by Date: Re: fortran program reading an external text (and numbers) file and writing with edits
- Previous by thread: Re: (very) slow recursive function
- Next by thread: Re: (very) slow recursive function
- Index(es):
Relevant Pages
|