MoDeNa  1.0
Software framework facilitating sequential multi-scale modelling
complex.f90
1 ! ---------------------------------------------------------------------
2 ! Utility subroutines used by any program from Numath library
3 ! with (not intrinsic) complex numbers z = (zr,zi).
4 ! ---------------------------------------------------------------------
5 ! Reference: From Numath Library By Tuan Dang Trong in Fortran 77
6 ! [BIBLI 18].
7 !
8 ! F90 Release 1.0 By J-P Moreau, Paris
9 ! (www.jpmoreau.fr)
10 ! ---------------------------------------------------------------------
11 MODULE complex
12 
13 CONTAINS
14 
15 SUBROUTINE zsqrt(AR, AI, BR, BI)
16 !***BEGIN PROLOGUE ZSQRT
17 !***REFER TO ZBESH,ZBESI,ZBESJ,ZBESK,ZBESY,ZAIRY,ZBIRY
18 !
19 ! DOUBLE PRECISION COMPLEX SQUARE ROOT, B=CSQRT(A)
20 !
21 !***ROUTINES CALLED ZABS
22 !***END PROLOGUE ZSQRT
23  DOUBLE PRECISION ar, ai, br, bi, zm, dtheta, dpi, drt
24  DATA drt , dpi / 7.071067811865475244008443621d-1, &
25  3.141592653589793238462643383d+0/
26  zm = zabs(ar,ai)
27  zm = dsqrt(zm)
28  IF (ar.EQ.0.0d+0) GO TO 10
29  IF (ai.EQ.0.0d+0) GO TO 20
30  dtheta = datan(ai/ar)
31  IF (dtheta.LE.0.0d+0) GO TO 40
32  IF (ar.LT.0.0d+0) dtheta = dtheta - dpi
33  GO TO 50
34  10 IF (ai.GT.0.0d+0) GO TO 60
35  IF (ai.LT.0.0d+0) GO TO 70
36  br = 0.0d+0
37  bi = 0.0d+0
38  RETURN
39  20 IF (ar.GT.0.0d+0) GO TO 30
40  br = 0.0d+0
41  bi = dsqrt(dabs(ar))
42  RETURN
43  30 br = dsqrt(ar)
44  bi = 0.0d+0
45  RETURN
46  40 IF (ar.LT.0.0d+0) dtheta = dtheta + dpi
47  50 dtheta = dtheta*0.5d+0
48  br = zm*dcos(dtheta)
49  bi = zm*dsin(dtheta)
50  RETURN
51  60 br = zm*drt
52  bi = zm*drt
53  RETURN
54  70 br = zm*drt
55  bi = -zm*drt
56  RETURN
57 END SUBROUTINE zsqrt
58 
59 SUBROUTINE zexp(AR, AI, BR, BI)
60 !***BEGIN PROLOGUE ZEXP
61 !***REFER TO ZBESH,ZBESI,ZBESJ,ZBESK,ZBESY,ZAIRY,ZBIRY
62 !
63 ! DOUBLE PRECISION COMPLEX EXPONENTIAL FUNCTION B=EXP(A)
64 !
65 !***ROUTINES CALLED (NONE)
66 !***END PROLOGUE ZEXP
67  DOUBLE PRECISION ar, ai, br, bi, zm, ca, cb
68  zm = dexp(ar)
69  ca = zm*dcos(ai)
70  cb = zm*dsin(ai)
71  br = ca
72  bi = cb
73 RETURN
74 END SUBROUTINE zexp
75 
76 SUBROUTINE zmlt(AR, AI, BR, BI, CR, CI)
77 !***BEGIN PROLOGUE ZMLT
78 !***REFER TO ZBESH,ZBESI,ZBESJ,ZBESK,ZBESY,ZAIRY,ZBIRY
79 !
80 ! DOUBLE PRECISION COMPLEX MULTIPLY, C=A*B.
81 !
82 !***ROUTINES CALLED (NONE)
83 !***END PROLOGUE ZMLT
84 DOUBLE PRECISION ar, ai, br, bi, cr, ci, ca, cb
85  ca = ar*br - ai*bi
86  cb = ar*bi + ai*br
87  cr = ca
88  ci = cb
89 RETURN
90 END SUBROUTINE zmlt
91 
92 SUBROUTINE zdiv(AR, AI, BR, BI, CR, CI)
93 !***BEGIN PROLOGUE ZDIV
94 !***REFER TO ZBESH,ZBESI,ZBESJ,ZBESK,ZBESY,ZAIRY,ZBIRY
95 !
96 ! DOUBLE PRECISION COMPLEX DIVIDE C=A/B.
97 
98 !***ROUTINES CALLED ZABS
99 !***END PROLOGUE ZDIV
100  DOUBLE PRECISION ar, ai, br, bi, cr, ci, bm, ca, cb, cc, cd
101  bm = 1.0d0/zabs(br,bi)
102  cc = br*bm
103  cd = bi*bm
104  ca = (ar*cc+ai*cd)*bm
105  cb = (ai*cc-ar*cd)*bm
106  cr = ca
107  ci = cb
108 RETURN
109 END SUBROUTINE zdiv
110 
111 SUBROUTINE zlog(AR, AI, BR, BI, IERR)
112 !***BEGIN PROLOGUE ZLOG
113 !***REFER TO ZBESH,ZBESI,ZBESJ,ZBESK,ZBESY,ZAIRY,ZBIRY
114 
115 ! DOUBLE PRECISION COMPLEX LOGARITHM B=CLOG(A)
116 ! IERR=0,NORMAL RETURN IERR=1, Z=CMPLX(0.0,0.0)
117 !***ROUTINES CALLED ZABS
118 !***END PROLOGUE ZLOG
119  DOUBLE PRECISION ar, ai, br, bi, zm, dtheta, dpi, dhpi
120  DATA dpi , dhpi / 3.141592653589793238462643383d+0, &
121  1.570796326794896619231321696d+0/
122 
123  ierr=0
124  IF (ar.EQ.0.0d+0) GO TO 10
125  IF (ai.EQ.0.0d+0) GO TO 20
126  dtheta = datan(ai/ar)
127  IF (dtheta.LE.0.0d+0) GO TO 40
128  IF (ar.LT.0.0d+0) dtheta = dtheta - dpi
129  GO TO 50
130  10 IF (ai.EQ.0.0d+0) GO TO 60
131  bi = dhpi
132  br = dlog(dabs(ai))
133  IF (ai.LT.0.0d+0) bi = -bi
134  RETURN
135  20 IF (ar.GT.0.0d+0) GO TO 30
136  br = dlog(dabs(ar))
137  bi = dpi
138  RETURN
139  30 br = dlog(ar)
140  bi = 0.0d+0
141  RETURN
142  40 IF (ar.LT.0.0d+0) dtheta = dtheta + dpi
143  50 zm = zabs(ar,ai)
144  br = dlog(zm)
145  bi = dtheta
146  RETURN
147  60 CONTINUE
148  ierr=1
149 RETURN
150 END SUBROUTINE zlog
151 
152 DOUBLE PRECISION FUNCTION zabs(ZR, ZI)
153 !***BEGIN PROLOGUE ZABS
154 !***REFER TO ZBESH,ZBESI,ZBESJ,ZBESK,ZBESY,ZAIRY,ZBIRY
155 
156 ! ZABS COMPUTES THE ABSOLUTE VALUE OR MAGNITUDE OF A DOUBLE
157 ! PRECISION COMPLEX VARIABLE CMPLX(ZR,ZI)
158 
159 !***ROUTINES CALLED (NONE)
160 !***END PROLOGUE ZABS
161  DOUBLE PRECISION zr, zi, u, v, q, s
162  u = dabs(zr)
163  v = dabs(zi)
164  s = u + v
165 !-----------------------------------------------------------------------
166 ! S*1.0D0 MAKES AN UNNORMALIZED UNDERFLOW ON CD! MACHINES INTO A
167 ! TRUE FLOATING ZERO
168 !-----------------------------------------------------------------------
169  s = s*1.0d+0
170  IF (s.EQ.0.0d+0) GO TO 20
171  IF (u.GT.v) GO TO 10
172  q = u/v
173  zabs = v*dsqrt(1.d+0+q*q)
174  RETURN
175  10 q = v/u
176  zabs = u*dsqrt(1.d+0+q*q)
177  RETURN
178  20 zabs = 0.0d+0
179  RETURN
180 END FUNCTION zabs
181 
182 END MODULE complex
183 ! end of file Complex.f90