Blame view
fvn_fnlib/dbesin.f90
2.3 KB
e1aefab23 git-svn-id: https... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
real(8) function dbesin(n,x,factor,big) implicit none ! This function compute the rank n Bessel J function ! using recurrence relation : ! In+1(x)=-2n/x * In(x) + In-1(x) ! ! Two optional parameters : ! factor : an integer that is used in Miller's algorithm to determine the ! starting point of iteration. Default value is 40, an increase of this value ! will increase accuracy. Starting point ~ nearest even integer of sqrt(factor*n) ! big : a real that determine the threshold for taking anti overflow counter measure ! default value is 1e10 ! integer :: n real(8) :: x integer, optional :: factor real(8), optional :: big integer :: tfactor real(8) :: tbig,tsmall real(8) :: two_on_x,binm1,bin,binp1,absx integer :: i,start real(8), external :: dbesi0,dbesi1 ! Initialization of optional parameters tfactor=40 if(present(factor)) tfactor=factor tbig=1e10 if(present(big)) tbig=big tsmall=1./tbig if (n==0) then dbesin=dbesi0(x) return end if if (n==1) then dbesin=dbesi1(x) return end if if (n < 0) then write(*,*) "Error in dbesin, n must be >= 0" stop end if absx=abs(x) if (absx == 0.) then dbesin=0. else ! We use Miller's Algorithm ! as upward reccurence is unstable. ! This is adapted from Numerical Recipes ! Principle : use of downward recurrence from an arbitrary ! higher than n value with an arbitrary seed, ! and then use the normalization formula : ! 1=I0-2I2+2I4-2I6+.... however it is easier to use a ! call to besi0 two_on_x=2./absx start=2*((n+int(sqrt(float(n*tfactor))))/2) ! even start binp1=0. bin=1. do i=start,1,-1 ! begin downward rec binm1=two_on_x*bin*i+binp1 binp1=bin bin=binm1 ! Action to prevent overflow if (abs(bin) > tbig) then bin=bin*tsmall binp1=binp1*tsmall dbesin=dbesin*tsmall end if if (i==n) dbesin=binp1 end do dbesin=dbesin*dbesi0(x)/bin end if ! if n is odd and x <0 if ((x<0.) .and. (mod(n,2)==1)) dbesin=-dbesin end function |