SDDSlib
Loading...
Searching...
No Matches
wofz.c File Reference

Computes the complex error function $ W(z) $ for a given complex number $ z $. More...

#include "mdb.h"
#include "f2c.h"

Go to the source code of this file.

Macros

#define abs(x)
 

Functions

double pow_di (doublereal *ap, integer *bp)
 
integer i_dnnt (doublereal *x)
 
int wofz (doublereal *xi, doublereal *yi, doublereal *u, doublereal *v, logical *flag__)
 Computes the complex error function $ W(z) $ for a given complex number $ z $.
 

Detailed Description

Computes the complex error function $ W(z) $ for a given complex number $ z $.

License
This file is distributed under the terms of the Software License Agreement found in the file LICENSE included with this distribution.
Author
H. Shang, M. Borland, R. Soliday

Definition in file wofz.c.

Macro Definition Documentation

◆ abs

#define abs ( x)
Value:
((x) >= 0 ? (x) : -(x))

Definition at line 46 of file wofz.c.

Function Documentation

◆ i_dnnt()

integer i_dnnt ( doublereal * x)

Definition at line 48 of file wofz.c.

48 {
49 return (integer)(*x >= 0. ? floor(*x + .5) : -floor(.5 - *x));
50}

◆ pow_di()

double pow_di ( doublereal * ap,
integer * bp )

Definition at line 19 of file wofz.c.

19 {
20 double pow, x;
21 integer n;
22 unsigned long u;
23
24 pow = 1;
25 x = *ap;
26 n = *bp;
27
28 if (n != 0) {
29 if (n < 0) {
30 n = -n;
31 x = 1 / x;
32 }
33 for (u = n;;) {
34 if (u & 01)
35 pow *= x;
36 if (u >>= 1)
37 x *= x;
38 else
39 break;
40 }
41 }
42 return (pow);
43}

◆ wofz()

int wofz ( doublereal * xi,
doublereal * yi,
doublereal * u,
doublereal * v,
logical * flag__ )

Computes the complex error function $ W(z) $ for a given complex number $ z $.

Given a complex number $ z = (\text{xi}, \text{yi}) $, this function computes the value of the Faddeeva function $ W(z) = \exp(-z^2) \cdot \text{ERFC}(-i z) $, where $ \text{ERFC} $ is the complex complementary error function and $ i = \sqrt{-1} $.

The accuracy of the algorithm is:

  • 14 significant digits for $ z $ in the 1st and 2nd quadrants.
  • 13 significant digits for $ z $ in the 3rd and 4th quadrants, outside a circular region with a radius of 0.126 around a zero of the function.
Parameters
xiPointer to the real part of the input complex number $ z $.
yiPointer to the imaginary part of the input complex number $ z $.
uPointer to store the real part of the computed $ W(z) $.
vPointer to store the imaginary part of the computed $ W(z) $.
flag__Pointer to a logical flag indicating whether an overflow has occurred.
  • false: No error condition.
  • true: Overflow has occurred; the routine becomes inactive.
Returns
Returns 0 on successful computation. If an overflow is detected, flag__ is set to true.

Definition at line 79 of file wofz.c.

83{
84 /* System generated locals */
85 doublereal d__1, d__2;
86
87 /* Builtin functions */
88 /*
89 double sqrt();
90 integer i_dnnt();
91 double exp(), cos(), sin(), pow_di();
92 */
93 /* Local variables */
94 static integer kapn;
95 static doublereal xabs, yabs, daux, qrho, xaux, xsum, ysum;
96 static logical a, b;
97 static doublereal c__, h__;
98 static integer i__, j, n;
99 static doublereal x, y, xabsq, xquad, yquad, h2, u1, v1, u2, v2, w1;
100 static integer nu;
101 static doublereal rx, ry, sx, sy, tx, ty;
102 static integer np1;
103 static doublereal qlambda;
104
105 /* GIVEN A COMPLEX NUMBER Z = (XI,YI), THIS SUBROUTINE COMPUTES */
106 /* THE VALUE OF THE FADDEEVA-FUNCTION W(Z) = EXP(-Z**2)*ERFC(-I*Z), */
107 /* WHERE ERFC IS THE COMPLEX COMPLEMENTARY ERROR-FUNCTION AND I */
108 /* MEANS SQRT(-1). */
109 /* THE ACCURACY OF THE ALGORITHM FOR Z IN THE 1ST AND 2ND QUADRANT */
110 /* IS 14 SIGNIFICANT DIGITS; IN THE 3RD AND 4TH IT IS 13 SIGNIFICANT */
111 /* DIGITS OUTSIDE A CIRCULAR REGION WITH RADIUS 0.126 AROUND A ZERO */
112 /* OF THE FUNCTION. */
113 /* ALL REAL VARIABLES IN THE PROGRAM ARE DOUBLE PRECISION. */
114
115 /* THE CODE CONTAINS A FEW COMPILER-DEPENDENT PARAMETERS : */
116 /* RMAXREAL = THE MAXIMUM VALUE OF RMAXREAL EQUALS THE ROOT OF */
117 /* RMAX = THE LARGEST NUMBER WHICH CAN STILL BE */
118 /* IMPLEMENTED ON THE COMPUTER IN DOUBLE PRECISION */
119 /* FLOATING-POINT ARITHMETIC */
120 /* RMAXEXP = LN(RMAX) - LN(2) */
121 /* RMAXGONI = THE LARGEST POSSIBLE ARGUMENT OF A DOUBLE PRECISION */
122 /* GONIOMETRIC FUNCTION (DCOS, DSIN, ...) */
123 /* THE REASON WHY THESE PARAMETERS ARE NEEDED AS THEY ARE DEFINED WILL */
124 /* BE EXPLAINED IN THE CODE BY MEANS OF COMMENTS */
125
126 /* PARAMETER LIST */
127 /* XI = REAL PART OF Z */
128 /* YI = IMAGINARY PART OF Z */
129 /* U = REAL PART OF W(Z) */
130 /* V = IMAGINARY PART OF W(Z) */
131 /* FLAG = AN ERROR FLAG INDICATING WHETHER OVERFLOW WILL */
132 /* OCCUR OR NOT; TYPE LOGICAL; */
133 /* THE VALUES OF THIS VARIABLE HAVE THE FOLLOWING */
134 /* MEANING : */
135 /* FLAG=.FALSE. : NO ERROR CONDITION */
136 /* FLAG=.TRUE. : OVERFLOW WILL OCCUR, THE ROUTINE */
137 /* BECOMES INACTIVE */
138 /* XI, YI ARE THE INPUT-PARAMETERS */
139 /* U, V, FLAG ARE THE OUTPUT-PARAMETERS */
140
141 /* FURTHERMORE THE PARAMETER FACTOR EQUALS 2/SQRT(PI) */
142
143 /* THE ROUTINE IS NOT UNDERFLOW-PROTECTED BUT ANY VARIABLE CAN BE */
144 /* PUT TO 0 UPON UNDERFLOW; */
145
146 /* REFERENCE - GPM POPPE, CMJ WIJERS; MORE EFFICIENT COMPUTATION OF */
147 /* THE COMPLEX ERROR-FUNCTION, ACM TRANS. MATH. SOFTWARE. */
148
149 *flag__ = FALSE_;
150
151 xabs = abs(*xi);
152 yabs = abs(*yi);
153 x = xabs / (float)6.3;
154 y = yabs / (float)4.4;
155
156 /* THE FOLLOWING IF-STATEMENT PROTECTS */
157 /* QRHO = (X**2 + Y**2) AGAINST OVERFLOW */
158
159 if (xabs > 5e153 || yabs > 5e153) {
160 goto L100;
161 }
162
163 /* Computing 2nd power */
164 d__1 = x;
165 /* Computing 2nd power */
166 d__2 = y;
167 qrho = d__1 * d__1 + d__2 * d__2;
168
169 /* Computing 2nd power */
170 d__1 = xabs;
171 xabsq = d__1 * d__1;
172 /* Computing 2nd power */
173 d__1 = yabs;
174 xquad = xabsq - d__1 * d__1;
175 yquad = xabs * 2 * yabs;
176
177 a = qrho < .085264;
178
179 if (a) {
180
181 /* IF (QRHO.LT.0.085264D0) THEN THE FADDEEVA-FUNCTION IS EVALUATED */
182 /* USING A POWER-SERIES (ABRAMOWITZ/STEGUN, EQUATION (7.1.5), P.297)
183*/
184 /* N IS THE MINIMUM NUMBER OF TERMS NEEDED TO OBTAIN THE REQUIRED */
185 /* ACCURACY */
186
187 qrho = (1 - y * (float).85) * sqrt(qrho);
188 d__1 = qrho * 72 + 6;
189 n = i_dnnt(&d__1);
190 j = (n << 1) + 1;
191 xsum = (float)1. / j;
192 ysum = 0.;
193 for (i__ = n; i__ >= 1; --i__) {
194 j += -2;
195 xaux = (xsum * xquad - ysum * yquad) / i__;
196 ysum = (xsum * yquad + ysum * xquad) / i__;
197 xsum = xaux + (float)1. / j;
198 /* L10: */
199 }
200 u1 = (xsum * yabs + ysum * xabs) * -1.12837916709551257388 + (float)1.;
201 v1 = (xsum * xabs - ysum * yabs) * 1.12837916709551257388;
202 daux = exp(-xquad);
203 u2 = daux * cos(yquad);
204 v2 = -daux * sin(yquad);
205
206 *u = u1 * u2 - v1 * v2;
207 *v = u1 * v2 + v1 * u2;
208
209 } else {
210
211 /* IF (QRHO.GT.1.O) THEN W(Z) IS EVALUATED USING THE LAPLACE */
212 /* CONTINUED FRACTION */
213 /* NU IS THE MINIMUM NUMBER OF TERMS NEEDED TO OBTAIN THE REQUIRED */
214 /* ACCURACY */
215
216 /* IF ((QRHO.GT.0.085264D0).AND.(QRHO.LT.1.0)) THEN W(Z) IS EVALUATED
217 */
218 /* BY A TRUNCATED TAYLOR EXPANSION, WHERE THE LAPLACE CONTINUED FRACT
219ION */
220 /* IS USED TO CALCULATE THE DERIVATIVES OF W(Z) */
221 /* KAPN IS THE MINIMUM NUMBER OF TERMS IN THE TAYLOR EXPANSION NEEDED
222 */
223 /* TO OBTAIN THE REQUIRED ACCURACY */
224 /* NU IS THE MINIMUM NUMBER OF TERMS OF THE CONTINUED FRACTION NEEDED
225 */
226 /* TO CALCULATE THE DERIVATIVES WITH THE REQUIRED ACCURACY */
227
228 if (qrho > (float)1.) {
229 h__ = 0.;
230 kapn = 0;
231 qrho = sqrt(qrho);
232 nu = (integer)(1442 / (qrho * 26 + 77) + 3);
233 } else {
234 qrho = (1 - y) * sqrt(1 - qrho);
235 h__ = qrho * (float)1.88;
236 h2 = h__ * 2;
237 d__1 = qrho * 34 + 7;
238 kapn = i_dnnt(&d__1);
239 d__1 = qrho * 26 + 16;
240 nu = i_dnnt(&d__1);
241 }
242
243 b = h__ > (float)0.;
244
245 if (b) {
246 qlambda = pow_di(&h2, &kapn);
247 }
248
249 rx = (float)0.;
250 ry = (float)0.;
251 sx = (float)0.;
252 sy = (float)0.;
253
254 for (n = nu; n >= 0; --n) {
255 np1 = n + 1;
256 tx = yabs + h__ + np1 * rx;
257 ty = xabs - np1 * ry;
258 /* Computing 2nd power */
259 d__1 = tx;
260 /* Computing 2nd power */
261 d__2 = ty;
262 c__ = (float).5 / (d__1 * d__1 + d__2 * d__2);
263 rx = c__ * tx;
264 ry = c__ * ty;
265 if (b && n <= kapn) {
266 tx = qlambda + sx;
267 sx = rx * tx - ry * sy;
268 sy = ry * tx + rx * sy;
269 qlambda /= h2;
270 }
271 /* L11: */
272 }
273
274 if (h__ == (float)0.) {
275 *u = rx * 1.12837916709551257388;
276 *v = ry * 1.12837916709551257388;
277 } else {
278 *u = sx * 1.12837916709551257388;
279 *v = sy * 1.12837916709551257388;
280 }
281
282 if (yabs == (float)0.) {
283 /* Computing 2nd power */
284 d__1 = xabs;
285 *u = exp(-(d__1 * d__1));
286 }
287 }
288
289 /* EVALUATION OF W(Z) IN THE OTHER QUADRANTS */
290
291 if (*yi < (float)0.) {
292
293 if (a) {
294 u2 *= 2;
295 v2 *= 2;
296 } else {
297 xquad = -xquad;
298
299 /* THE FOLLOWING IF-STATEMENT PROTECTS 2*EXP(-Z**2) */
300 /* AGAINST OVERFLOW */
301
302 if (yquad > 3537118876014220. || xquad > 708.503061461606) {
303 goto L100;
304 }
305
306 w1 = exp(xquad) * 2;
307 u2 = w1 * cos(yquad);
308 v2 = -w1 * sin(yquad);
309 }
310
311 *u = u2 - *u;
312 *v = v2 - *v;
313 if (*xi > (float)0.) {
314 *v = -(*v);
315 }
316 } else {
317 if (*xi < (float)0.) {
318 *v = -(*v);
319 }
320 }
321
322 return 0;
323
324L100:
325 *flag__ = TRUE_;
326 return 0;
327
328} /* wofz */