forked from gravitationalwave01/eDDA
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcisi.f90
executable file
·93 lines (85 loc) · 2.09 KB
/
cisi.f90
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
81
82
83
84
85
86
87
88
89
90
91
92
SUBROUTINE CISI(X,CI,SI)
USE DDPRECISION,ONLY: WP
IMPLICIT NONE
! Given:
! X = real argument
! Returns
! CI = gamma + ln(x) + \int_0^x [(cos(t)-1)/t] dt = "cosine integral"
! SI = \int_0^x [sin(t)/t] dt = "sine integral"
!
! Code adapted from Numerical Recipes in FORTRAN (2e)
! by Press, Teukolsky, Vetterling, and Flannery (1994)
! Arguments:
REAL(WP) :: CI,SI,X
! Local variables:
INTEGER :: MAXIT
REAL(WP) :: EPMIN,EPS,EULER,FPMIN,PIBY2,TMIN
PARAMETER(EPS=6.E-8,EULER=0.57721566_WP,MAXIT=100, &
PIBY2=1.5707963_WP,FPMIN=1.E-30,TMIN=2._WP)
INTEGER :: I,K
REAL(WP) :: A,ERR,FACT,SGN,SU,SUMC,SUMS,T,TERM,ABSC
COMPLEX(WP) :: B,C,D,DEL,H
LOGICAL ODD
ABSC(H)=ABS(REAL(H))+ABS(AIMAG(H))
T=ABS(X)
IF(T.EQ.0.)THEN
SI=0.
CI=-1._WP/FPMIN
RETURN
ENDIF
IF(T.GT.TMIN)THEN
B=CMPLX(1._WP,T)
C=1._WP/FPMIN
D=1._WP/B
H=D
DO I=2,MAXIT
A=-(I-1)**2
B=B+2.
D=1._WP/(A*D+B)
C=B+A/C
DEL=C*D
H=H*DEL
IF(ABSC(DEL-1._WP).LT.EPS)GOTO 1
ENDDO
CALL ERRMSG('FATAL','CISI', &
'Fatal error: failed in cisi')
1 CONTINUE
H=CMPLX(COS(T),-SIN(T))*H
CI=-REAL(H)
SI=PIBY2+AIMAG(H)
ELSE
IF(T.LT.SQRT(FPMIN))THEN
SUMC=0.
SUMS=T
ELSE
SU=0.
SUMS=0.
SUMC=0.
SGN=1._WP
FACT=1._WP
ODD=.TRUE.
DO K=1,MAXIT
FACT=FACT*T/K
TERM=FACT/K
SU=SU+SGN*TERM
ERR=TERM/ABS(SU)
IF(ODD)THEN
SGN=-SGN
SUMS=SU
SU=SUMC
ELSE
SUMC=SU
SU=SUMS
ENDIF
IF(ERR.LT.EPS)GOTO 2
ODD=.NOT.ODD
ENDDO
CALL ERRMSG('FATAL','CISI', &
'maxits exceeded in CISI')
ENDIF
2 SI=SUMS
CI=SUMC+LOG(T)+EULER
ENDIF
IF(X.LT.0._WP)SI=-SI
RETURN
END SUBROUTINE CISI