[Fortran] 纯文本查看 复制代码
FUNCTION cgam0(z) RESULT(fn_val)
!-----------------------------------------------------------------------
! EVALUATION OF 1/GAMMA(1 + Z) FOR ABS(Z) < 1.0
!-----------------------------------------------------------------------
COMPLEX (dp), INTENT(IN) :: z
COMPLEX (dp) :: fn_val
COMPLEX (dp) :: w
INTEGER :: i, k, n
!-----------------------
REAL (dp) :: x, y
REAL, PARAMETER :: a(25) = (/ .577215664901533_dp, -.655878071520254_dp, &
-.420026350340952D-01, .166538611382291_dp, -.421977345555443D-01, &
-.962197152787697D-02, .721894324666310D-02, -.116516759185907D-02, &
-.215241674114951D-03, .128050282388116D-03, -.201348547807882D-04, &
-.125049348214267D-0, .113302723198170D-05, -.205633841697761D-0, &
.611609510448142D-08, .500200764446922D-08, -.118127457048702D-08, &
.104342671169110D-09, .778226343990507D-11, -.369680561864221D-11, &
.510037028745448D-12, -.205832605356651D-13, -.534812253942302D-14, &
.122677862823826D-14, -.118125930169746D-15 /)
!-----------------------
n = 25
x = REAL(z, KIND=dp)
y = AIMAG(z)
IF (x*x+y*y <= 0.04D0) n = 14
k = n
w = a(n)
DO i = 2, n
k = k - 1
w = a(k) + z * w
END DO
fn_val = 1.0D0 + z * w
RETURN
END FUNCTION cgam0
FUNCTION dgamma(a) RESULT(fn_val)
!-----------------------------------------------------------------------
! EVALUATION OF THE GAMMA FUNCTION FOR
! REAL (dp) ARGUMENTS
! -----------
! DGAMMA(A) IS ASSIGNED THE VALUE 0 WHEN THE GAMMA FUNCTION CANNOT
! BE COMPUTED.
!-----------------------------------------------------------------------
! WRITTEN BY ALFRED H. MORRIS, JR.
! NAVAL SURFACE WEAPONS CENTER
! DAHLGREN, VIRGINIA
!-----------------------------------------------------------------------
REAL (dp), INTENT(IN) :: a
REAL (dp) :: fn_val
! Local variables
REAL (dp), PARAMETER :: d = 0.41893853320467274178032973640562_dp, &
pi = 3.14159265358979323846264338327950_dp
REAL (dp) :: s, t, x, w
INTEGER :: j, n
!-----------------------------------------------------------------------
! D = 0.5*(LN(2*PI) - 1)
!-----------------------------------------------------------------------
fn_val = 0.0_dp
x = a
IF (ABS(a) <= 20._dp) THEN
!-----------------------------------------------------------------------
! EVALUATION OF DGAMMA(A) FOR ABS(A) <= 20
!-----------------------------------------------------------------------
t = 1.0_dp
n = x
n = n - 1
! LET T BE THE PRODUCT OF A-J WHEN A >= 2
IF (n < 0) THEN
GO TO 40
ELSE IF (n == 0) THEN
GO TO 30
END IF
DO j = 1, n
x = x - 1._dp
t = x * t
END DO
30 x = x - 1._dp
GO TO 60
! LET T BE THE PRODUCT OF A+J WHEN A < 1
40 t = a
IF (a <= 0._dp) THEN
n = -n - 1
IF (n /= 0) THEN
DO j = 1, n
x = x + 1._dp
t = x * t
END DO
END IF
x = (x+0.5_dp) + 0.5_dp
t = x * t
IF (t == 0._dp) RETURN
END IF
! THE FOLLOWING CODE CHECKS IF 1/T CAN OVERFLOW. THIS
! CODE MAY BE OMITTED IF DESIRED.
IF (ABS(t) < 1.d-33) THEN
IF (ABS(t)*HUGE(1.0_dp) <= 1.000000001_dp) RETURN
fn_val = 1._dp / t
RETURN
END IF
! COMPUTE DGAMMA(1 + X) FOR 0 <= X < 1
60 fn_val = 1._dp / (1._dp + dgam1(x))
! TERMINATION
IF (a >= 1._dp) THEN
fn_val = fn_val * t
RETURN
END IF
fn_val = fn_val / t
RETURN
END IF
!-----------------------------------------------------------------------
! EVALUATION OF DGAMMA(A) FOR ABS(A) > 20
!-----------------------------------------------------------------------
IF (ABS(a) >= 1.d3) RETURN
IF (a <= 0._dp) THEN
s = dsin1(a) / pi
IF (s == 0._dp) RETURN
x = -a
END IF
! COMPUTE THE MODIFIED ASYMPTOTIC SUM
w = dpdel(x)
! FINAL ASSEMBLY
w = (d+w) + (x-0.5_dp) * (LOG(x)-1._dp)
IF (w > dxparg(0)) RETURN
fn_val = EXP(w)
IF (a < 0._dp) fn_val = (1._dp/(fn_val*s)) / x
RETURN
END FUNCTION dgamma
FUNCTION glog(x) RESULT(fn_val)
! -------------------
! EVALUATION OF LN(X) FOR X >= 15
! -------------------
REAL (dp), INTENT(IN) :: x
REAL (dp) :: fn_val
! Local variables
REAL (dp), PARAMETER :: c1 = .286228750476730_dp, c2 = .399999628131494+dp, &
c3 = .666666666752663_dp
REAL (dp), PARAMETER :: w(163) = (/ .270805020110221007D+01, .277258872223978124D+01, &
.283321334405621608D+01, .289037175789616469D+01, .294443897916644046D+01, .299573227355399099D+01, .304452243772342300D+01, &
.309104245335831585D+01, .313549421592914969D+01, .317805383034794562D+01, .321887582486820075D+01, .325809653802148205D+01, &
.329583686600432907D+01, .333220451017520392D+01, .336729582998647403D+01, .340119738166215538D+01, .343398720448514625D+01, &
.346573590279972655D+01, .349650756146648024D+01, .352636052461616139D+01, .355534806148941368D+01, .358351893845611000D+01, &
.361091791264422444D+01, .363758615972638577D+01, .366356164612964643D+01, .368887945411393630D+01, .371357206670430780D+01, &
.373766961828336831D+01, .376120011569356242D+01, .378418963391826116D+01, .380666248977031976D+01, .382864139648909500D+01, &
.385014760171005859D+01, .387120101090789093D+01, .389182029811062661D+01, .391202300542814606D+01, .393182563272432577D+01, &
.395124371858142735D+01, .397029191355212183D+01, .398898404656427438D+01, .400733318523247092D+01, .402535169073514923D+01, &
.404305126783455015D+01, .406044301054641934D+01, .407753744390571945D+01, .409434456222210068D+01, .411087386417331125D+01, &
.412713438504509156D+01, .414313472639153269D+01, .415888308335967186D+01, .417438726989563711D+01, .418965474202642554D+01, &
.420469261939096606D+01, .421950770517610670D+01, .423410650459725938D+01, .424849524204935899D+01, .426267987704131542D+01, &
.427666611901605531D+01, .429045944114839113D+01, .430406509320416975D+01, .431748811353631044D+01, .433073334028633108D+01, &
.434380542185368385D+01, .435670882668959174D+01, .436944785246702149D+01, .438202663467388161D+01, .439444915467243877D+01, &
.440671924726425311D+01, .441884060779659792D+01, .443081679884331362D+01, .444265125649031645D+01, .445434729625350773D+01, &
.446590811865458372D+01, .447733681447820647D+01, .448863636973213984D+01, .449980967033026507D+01, .451085950651685004D+01, &
.452178857704904031D+01, .453259949315325594D+01, .454329478227000390D+01, .455387689160054083D+01, .456434819146783624D+01, &
.457471097850338282D+01, .458496747867057192D+01, .459511985013458993D+01, .460517018598809137D+01, .461512051684125945D+01, &
.462497281328427108D+01, .463472898822963577D+01, .464439089914137266D+01, .465396035015752337D+01, .466343909411206714D+01, &
.467282883446190617D+01, .468213122712421969D+01, .469134788222914370D+01, .470048036579241623D+01, .470953020131233414D+01, &
.471849887129509454D+01, .472738781871234057D+01, .473619844839449546D+01, .474493212836325007D+01, .475359019110636465D+01, &
.476217393479775612D+01, .477068462446566476D+01, .477912349311152939D+01, .478749174278204599D+01, .479579054559674109D+01, &
.480402104473325656D+01, .481218435537241750D+01, .482028156560503686D+01, .482831373730230112D+01, .483628190695147800D+01, &
.484418708645859127D+01, .485203026391961717D+01, .485981240436167211D+01, .486753445045558242D+01, .487519732320115154D+01, &
.488280192258637085D+01, .489034912822175377D+01, .489783979995091137D+01, .490527477843842945D+01, .491265488573605201D+01, &
.491998092582812492D+01, .492725368515720469D+01, .493447393313069176D+01, .494164242260930430D+01, .494875989037816828D+01, &
.495582705760126073D+01, .496284463025990728D+01, .496981329957600062D+01, .497673374242057440D+01, .498360662170833644D+01, &
.499043258677873630D+01, .499721227376411506D+01, .500394630594545914D+01, .501063529409625575D+01, .501727983681492433D+01, &
.502388052084627639D+01, .503043792139243546D+01, .503695260241362916D+01, .504342511691924662D+01, .504985600724953705D+01, &
.505624580534830806D+01, .506259503302696680D+01, .506890420222023153D+01, .507517381523382692D+01, .508140436498446300D+01, &
.508759633523238407D+01, .509375020080676233D+01, .509986642782419842D+01, .510594547390058061D+01, .511198778835654323D+01, &
.511799381241675511D+01, .512396397940325892D+01, .512989871492307347D+01, .513579843705026176D+01, .514166355650265984D+01, &
.514749447681345304D+01, .515329159449777895D+01, .515905529921452903D+01, .516478597392351405D+01, .517048399503815178D+01, &
.517614973257382914D+01 /)
REAL (dp) :: t, t2, z
INTEGER :: n
! -------------------
IF (x < 178.0_dp) THEN
n = x
t = (x-n) / (x+n)
t2 = t * t
z = (((c1*t2 + c2)*t2 + c3)*t2 + 2.0) * t
fn_val = w(n-14) + z
RETURN
END IF
fn_val = LOG(x)
RETURN
END FUNCTION glog