/src/r-source/src/main/complex.c
Line | Count | Source |
1 | | /* |
2 | | * R : A Computer Language for Statistical Data Analysis |
3 | | * Copyright (C) 2000-2025 The R Core Team |
4 | | * Copyright (C) 2005 The R Foundation |
5 | | * Copyright (C) 1995-1997 Robert Gentleman and Ross Ihaka |
6 | | * |
7 | | * This program is free software; you can redistribute it and/or modify |
8 | | * it under the terms of the GNU General Public License as published by |
9 | | * the Free Software Foundation; either version 2 of the License, or |
10 | | * (at your option) any later version. |
11 | | * |
12 | | * This program is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | | * GNU General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU General Public License |
18 | | * along with this program; if not, a copy is available at |
19 | | * https://www.R-project.org/Licenses/ |
20 | | */ |
21 | | |
22 | | #ifdef HAVE_CONFIG_H |
23 | | #include <config.h> |
24 | | #endif |
25 | | |
26 | | /* Note: gcc -pedantic may warn in several places about C99 features |
27 | | as extensions. |
28 | | This was a very-long-standing GCC bug, http://gcc.gnu.org/PR7263 |
29 | | The system <complex.h> header can work around it: some do. |
30 | | It should have been resolved (after a decade) in 2012. |
31 | | */ |
32 | | |
33 | | #if defined(HAVE_CTANH) && !defined(HAVE_WORKING_CTANH) |
34 | | #undef HAVE_CTANH |
35 | | #endif |
36 | | |
37 | | #if 0 |
38 | | /* For testing substitute fns */ |
39 | | #undef HAVE_CARG |
40 | | #undef HAVE_CABS |
41 | | #undef HAVE_CPOW |
42 | | #undef HAVE_CEXP |
43 | | #undef HAVE_CLOG |
44 | | #undef HAVE_CSQRT |
45 | | #undef HAVE_CSIN |
46 | | #undef HAVE_CCOS |
47 | | #undef HAVE_CTAN |
48 | | #undef HAVE_CASIN |
49 | | #undef HAVE_CACOS |
50 | | #undef HAVE_CATAN |
51 | | #undef HAVE_CSINH |
52 | | #undef HAVE_CCOSH |
53 | | #undef HAVE_CTANH |
54 | | #endif |
55 | | |
56 | | #ifdef __SUNPRO_C |
57 | | /* segfaults in Solaris Studio 12.3 */ |
58 | | #undef HAVE_CPOW |
59 | | #endif |
60 | | |
61 | | #include <Defn.h> /* -> ../include/R_ext/Complex.h */ |
62 | | #include <Internal.h> |
63 | | #include <Rmath.h> |
64 | | |
65 | | #include "arithmetic.h" /* complex_* */ |
66 | | #include <complex.h> /* incl "complex math.h" */ |
67 | | #include "Rcomplex.h" /* I, SET_C99_COMPLEX, toC99 */ |
68 | | #include <R_ext/Itermacros.h> |
69 | | |
70 | | |
71 | | /* interval at which to check interrupts, a guess */ |
72 | | #define NINTERRUPT 10000000 |
73 | | |
74 | | |
75 | | attribute_hidden SEXP complex_unary(ARITHOP_TYPE code, SEXP s1, SEXP call) |
76 | 0 | { |
77 | 0 | R_xlen_t i, n; |
78 | 0 | SEXP ans; |
79 | |
|
80 | 0 | switch(code) { |
81 | 0 | case PLUSOP: |
82 | 0 | return s1; |
83 | 0 | case MINUSOP: |
84 | 0 | ans = NO_REFERENCES(s1) ? s1 : duplicate(s1); |
85 | 0 | Rcomplex *pans = COMPLEX(ans); |
86 | 0 | const Rcomplex *ps1 = COMPLEX_RO(s1); |
87 | 0 | n = XLENGTH(s1); |
88 | 0 | for (i = 0; i < n; i++) { |
89 | 0 | Rcomplex x = ps1[i]; |
90 | 0 | pans[i].r = -x.r; |
91 | 0 | pans[i].i = -x.i; |
92 | 0 | } |
93 | 0 | return ans; |
94 | 0 | default: |
95 | 0 | errorcall(call, _("invalid complex unary operator")); |
96 | 0 | } |
97 | 0 | return R_NilValue; /* -Wall */ |
98 | 0 | } |
99 | | |
100 | | static R_INLINE double complex R_cpow_n(double complex X, int k) |
101 | 0 | { |
102 | 0 | if(k == 0) return (double complex) 1.; |
103 | 0 | else if(k == 1) return X; |
104 | 0 | else if(k < 0) return 1. / R_cpow_n(X, -k); |
105 | 0 | else {/* k > 0 */ |
106 | 0 | double complex z = (double complex) 1.;; |
107 | 0 | while (k > 0) { |
108 | 0 | if (k & 1) z = z * X; |
109 | 0 | if (k == 1) break; |
110 | 0 | k >>= 1; /* efficient division by 2; now have k >= 1 */ |
111 | 0 | X = X * X; |
112 | 0 | } |
113 | 0 | return z; |
114 | 0 | } |
115 | 0 | } |
116 | | |
117 | | #if defined(Win32) |
118 | | # undef HAVE_CPOW |
119 | | #endif |
120 | | /* reason for this: |
121 | | 1) X^n (e.g. for n = +/- 2, 3) is unnecessarily inaccurate in glibc; |
122 | | cut-off 65536 : guided from empirical speed measurements |
123 | | |
124 | | 2) On Mingw (but not Mingw-w64) the system cpow is explicitly linked |
125 | | against the (slow) MSVCRT pow, and gets (0+0i)^Y as 0+0i for all Y. |
126 | | |
127 | | 3) PPC macOS crashed on powers of 0+0i (at least under Rosetta). |
128 | | Really 0i^-1 should by Inf+NaNi, but getting that portably seems too hard. |
129 | | (C1x's CMPLX will eventually be possible.) |
130 | | */ |
131 | | |
132 | | static double complex mycpow (double complex X, double complex Y) |
133 | 0 | { |
134 | 0 | double complex Z; |
135 | 0 | double yr = creal(Y), yi = cimag(Y); |
136 | 0 | int k; |
137 | 0 | if (X == 0.0) { |
138 | 0 | if (yi == 0.0) Z = R_pow(0.0, yr); else Z = R_NaN + R_NaN*I; |
139 | 0 | } else if (yi == 0.0 && yr == (k = (int) yr) && abs(k) <= 65536) |
140 | 0 | Z = R_cpow_n(X, k); |
141 | 0 | else |
142 | 0 | #ifdef HAVE_CPOW |
143 | 0 | Z = cpow(X, Y); |
144 | | #else |
145 | | { |
146 | | /* Used for FreeBSD and MingGW, hence mainly with gcc */ |
147 | | double rho, r, i, theta; |
148 | | r = hypot(creal(X), cimag(X)); |
149 | | i = atan2(cimag(X), creal(X)); |
150 | | theta = i * yr; |
151 | | if (yi == 0.0) |
152 | | rho = pow(r, yr); |
153 | | else { |
154 | | /* rearrangement of cexp(X * clog(Y)) */ |
155 | | r = log(r); |
156 | | theta += r * yi; |
157 | | rho = exp(r * yr - i * yi); |
158 | | } |
159 | | #ifdef __GNUC__ |
160 | | __real__ Z = rho * cos(theta); |
161 | | __imag__ Z = rho * sin(theta); |
162 | | #else |
163 | | Z = rho * cos(theta) + (rho * sin(theta)) * I; |
164 | | #endif |
165 | | } |
166 | | #endif |
167 | 0 | return Z; |
168 | 0 | } |
169 | | |
170 | | |
171 | | |
172 | | attribute_hidden SEXP complex_binary(ARITHOP_TYPE code, SEXP s1, SEXP s2) |
173 | 0 | { |
174 | 0 | R_xlen_t i, i1, i2, n, n1, n2; |
175 | 0 | SEXP ans; |
176 | | |
177 | | /* Note: "s1" and "s2" are protected in the calling code. */ |
178 | 0 | n1 = XLENGTH(s1); |
179 | 0 | n2 = XLENGTH(s2); |
180 | | /* S4-compatibility change: if n1 or n2 is 0, result is of length 0 */ |
181 | 0 | if (n1 == 0 || n2 == 0) return(allocVector(CPLXSXP, 0)); |
182 | | |
183 | 0 | n = (n1 > n2) ? n1 : n2; |
184 | 0 | ans = R_allocOrReuseVector(s1, s2, CPLXSXP, n); |
185 | 0 | PROTECT(ans); |
186 | |
|
187 | 0 | Rcomplex *pans = COMPLEX(ans); |
188 | 0 | const Rcomplex *ps1 = COMPLEX_RO(s1); |
189 | 0 | const Rcomplex *ps2 = COMPLEX_RO(s2); |
190 | |
|
191 | 0 | switch (code) { |
192 | 0 | case PLUSOP: |
193 | 0 | MOD_ITERATE2_CHECK(NINTERRUPT, n, n1, n2, i, i1, i2, { |
194 | 0 | Rcomplex x1 = ps1[i1]; |
195 | 0 | Rcomplex x2 = ps2[i2]; |
196 | 0 | pans[i].r = x1.r + x2.r; |
197 | 0 | pans[i].i = x1.i + x2.i; |
198 | 0 | }); |
199 | 0 | break; |
200 | 0 | case MINUSOP: |
201 | 0 | MOD_ITERATE2_CHECK(NINTERRUPT, n, n1, n2, i, i1, i2, { |
202 | 0 | Rcomplex x1 = ps1[i1]; |
203 | 0 | Rcomplex x2 = ps2[i2]; |
204 | 0 | pans[i].r = x1.r - x2.r; |
205 | 0 | pans[i].i = x1.i - x2.i; |
206 | 0 | }); |
207 | 0 | break; |
208 | 0 | case TIMESOP: |
209 | 0 | MOD_ITERATE2_CHECK(NINTERRUPT, n, n1, n2, i, i1, i2, { |
210 | 0 | SET_C99_COMPLEX(pans, i, |
211 | 0 | toC99(&ps1[i1]) * toC99(&ps2[i2])); |
212 | 0 | }); |
213 | 0 | break; |
214 | 0 | case DIVOP: |
215 | 0 | MOD_ITERATE2_CHECK(NINTERRUPT, n, n1, n2, i, i1, i2, { |
216 | 0 | SET_C99_COMPLEX(pans, i, |
217 | 0 | toC99(&ps1[i1]) / toC99(&ps2[i2])); |
218 | 0 | }); |
219 | 0 | break; |
220 | 0 | case POWOP: |
221 | 0 | MOD_ITERATE2_CHECK(NINTERRUPT, n, n1, n2, i, i1, i2, { |
222 | 0 | SET_C99_COMPLEX(pans, i, |
223 | 0 | mycpow(toC99(&ps1[i1]), toC99(&ps2[i2]))); |
224 | 0 | }); |
225 | 0 | break; |
226 | 0 | default: |
227 | 0 | error(_("unimplemented complex operation")); |
228 | 0 | } |
229 | 0 | UNPROTECT(1); |
230 | | |
231 | | /* quick return if there are no attributes */ |
232 | 0 | if (ATTRIB(s1) == R_NilValue && ATTRIB(s2) == R_NilValue) |
233 | 0 | return ans; |
234 | | |
235 | | /* Copy attributes from longer argument. */ |
236 | | |
237 | 0 | if (ans != s2 && n == n2 && ATTRIB(s2) != R_NilValue) |
238 | 0 | copyMostAttrib(s2, ans); |
239 | 0 | if (ans != s1 && n == n1 && ATTRIB(s1) != R_NilValue) |
240 | 0 | copyMostAttrib(s1, ans); /* Done 2nd so s1's attrs overwrite s2's */ |
241 | |
|
242 | 0 | return ans; |
243 | 0 | } |
244 | | |
245 | | attribute_hidden SEXP do_cmathfuns(SEXP call, SEXP op, SEXP args, SEXP env) |
246 | 0 | { |
247 | 0 | SEXP x, y = R_NilValue; /* -Wall*/ |
248 | 0 | R_xlen_t i, n; |
249 | |
|
250 | 0 | checkArity(op, args); |
251 | 0 | check1arg(args, call, "z"); |
252 | 0 | if (DispatchGroup("Complex", call, op, args, env, &x)) |
253 | 0 | return x; |
254 | 0 | x = CAR(args); |
255 | 0 | if (isComplex(x)) { |
256 | 0 | n = XLENGTH(x); |
257 | 0 | const Rcomplex *px = COMPLEX_RO(x); |
258 | 0 | switch(PRIMVAL(op)) { |
259 | 0 | case 1: /* Re */ |
260 | 0 | { |
261 | 0 | y = allocVector(REALSXP, n); |
262 | 0 | double *py = REAL(y); |
263 | 0 | for(i = 0 ; i < n ; i++) |
264 | 0 | py[i] = px[i].r; |
265 | 0 | } |
266 | 0 | break; |
267 | 0 | case 2: /* Im */ |
268 | 0 | { |
269 | 0 | y = allocVector(REALSXP, n); |
270 | 0 | double *py = REAL(y); |
271 | 0 | for(i = 0 ; i < n ; i++) |
272 | 0 | py[i] = px[i].i; |
273 | 0 | } |
274 | 0 | break; |
275 | 0 | case 3: /* Mod */ |
276 | 0 | case 6: /* abs */ |
277 | 0 | { |
278 | 0 | y = allocVector(REALSXP, n); |
279 | 0 | double *py = REAL(y); |
280 | 0 | for(i = 0 ; i < n ; i++) |
281 | 0 | #if HAVE_CABS |
282 | 0 | py[i] = cabs(toC99(&px[i])); |
283 | | #else |
284 | | py[i] = hypot(px[i].r, px[i].i); |
285 | | #endif |
286 | 0 | } |
287 | 0 | break; |
288 | 0 | case 4: /* Arg */ |
289 | 0 | { |
290 | 0 | y = allocVector(REALSXP, n); |
291 | 0 | double *py = REAL(y); |
292 | 0 | for(i = 0 ; i < n ; i++) |
293 | 0 | #if HAVE_CARG |
294 | 0 | py[i] = carg(toC99(&px[i])); |
295 | | #else |
296 | | py[i] = atan2(px[i].i, px[i].r); |
297 | | #endif |
298 | 0 | } |
299 | 0 | break; |
300 | 0 | case 5: /* Conj */ |
301 | 0 | { |
302 | 0 | y = NO_REFERENCES(x) ? x : allocVector(CPLXSXP, n); |
303 | 0 | Rcomplex *py = COMPLEX(y); |
304 | 0 | for(i = 0 ; i < n ; i++) { |
305 | 0 | py[i].r = px[i].r; |
306 | 0 | py[i].i = -px[i].i; |
307 | 0 | } |
308 | 0 | } |
309 | 0 | break; |
310 | 0 | } |
311 | 0 | } |
312 | 0 | else if(isNumeric(x)) { /* so no complex numbers involved */ |
313 | 0 | n = XLENGTH(x); |
314 | 0 | if(isReal(x)) PROTECT(x); |
315 | 0 | else PROTECT(x = coerceVector(x, REALSXP)); |
316 | 0 | y = NO_REFERENCES(x) ? x : allocVector(REALSXP, n); |
317 | 0 | double *py = REAL(y); |
318 | 0 | const double *px = REAL_RO(x); |
319 | |
|
320 | 0 | switch(PRIMVAL(op)) { |
321 | 0 | case 1: /* Re */ |
322 | 0 | case 5: /* Conj */ |
323 | 0 | for(i = 0 ; i < n ; i++) |
324 | 0 | py[i] = px[i]; |
325 | 0 | break; |
326 | 0 | case 2: /* Im */ |
327 | 0 | for(i = 0 ; i < n ; i++) |
328 | 0 | py[i] = 0.0; |
329 | 0 | break; |
330 | 0 | case 4: /* Arg */ |
331 | 0 | for(i = 0 ; i < n ; i++) |
332 | 0 | if(ISNAN(px[i])) |
333 | 0 | py[i] = px[i]; |
334 | 0 | else if (px[i] >= 0) |
335 | 0 | py[i] = 0; |
336 | 0 | else |
337 | 0 | py[i] = M_PI; |
338 | 0 | break; |
339 | 0 | case 3: /* Mod */ |
340 | 0 | case 6: /* abs */ |
341 | 0 | for(i = 0 ; i < n ; i++) |
342 | 0 | py[i] = fabs(px[i]); |
343 | 0 | break; |
344 | 0 | } |
345 | 0 | UNPROTECT(1); |
346 | 0 | } |
347 | 0 | else errorcall(call, _("non-numeric argument to function")); |
348 | | |
349 | 0 | if (x != y && ATTRIB(x) != R_NilValue) { |
350 | 0 | PROTECT(x); |
351 | 0 | PROTECT(y); |
352 | 0 | SHALLOW_DUPLICATE_ATTRIB(y, x); |
353 | 0 | UNPROTECT(2); |
354 | 0 | } |
355 | 0 | return y; |
356 | 0 | } |
357 | | |
358 | | /* Implementing signif(<complex>) *and* used in format.c and printutils.c */ |
359 | 0 | #define MAX_DIGITS 22 |
360 | | attribute_hidden void z_prec_r(Rcomplex *r, const Rcomplex *x, double digits) |
361 | 0 | { |
362 | | // Implement r <- signif(x, digits) |
363 | |
|
364 | 0 | r->r = x->r; r->i = x->i; |
365 | 0 | double m = 0.0, |
366 | 0 | m1 = fabs(x->r), |
367 | 0 | m2 = fabs(x->i); |
368 | 0 | if(R_FINITE(m1)) m = m1; |
369 | 0 | if(R_FINITE(m2) && m2 > m) m = m2; |
370 | 0 | if (m == 0.0) return; |
371 | 0 | if (!R_FINITE(digits)) { |
372 | 0 | if(digits > 0) return; else {r->r = r->i = 0.0; return ;} |
373 | 0 | } |
374 | 0 | int dig = (int)floor(digits+0.5); |
375 | 0 | if (dig > MAX_DIGITS) return; else if (dig < 1) dig = 1; |
376 | 0 | int mag = (int)floor(log10(m)); |
377 | 0 | dig = dig - mag - 1; |
378 | 0 | if (dig > 306) { |
379 | 0 | double pow10 = 1.0e4; |
380 | 0 | digits = (double)(dig - 4); |
381 | 0 | r->r = fround(pow10 * x->r, digits)/pow10; |
382 | 0 | r->i = fround(pow10 * x->i, digits)/pow10; |
383 | 0 | } else { |
384 | 0 | digits = (double)(dig); |
385 | 0 | r->r = fround(x->r, digits); |
386 | 0 | r->i = fround(x->i, digits); |
387 | 0 | } |
388 | 0 | } |
389 | | |
390 | | /* These substitute functions are rarely used, and not extensively |
391 | | tested, e.g. over CRAN. Please do not change without very good |
392 | | reason! |
393 | | |
394 | | Currently (Feb 2011) they are used on FreeBSD. |
395 | | */ |
396 | | |
397 | | #ifndef HAVE_CLOG |
398 | | #define clog R_clog |
399 | | /* FIXME: maybe add full IEC60559 support */ |
400 | | static double complex clog(double complex x) |
401 | | { |
402 | | double xr = creal(x), xi = cimag(x); |
403 | | return log(hypot(xr, xi)) + atan2(xi, xr)*I; |
404 | | } |
405 | | #endif |
406 | | |
407 | | #ifndef HAVE_CSQRT |
408 | | #define csqrt R_csqrt |
409 | | /* FreeBSD does have this one */ |
410 | | static double complex csqrt(double complex x) |
411 | | { |
412 | | return mycpow(x, 0.5+0.0*I); |
413 | | } |
414 | | #endif |
415 | | |
416 | | #ifndef HAVE_CEXP |
417 | | #define cexp R_cexp |
418 | | /* FIXME: check/add full IEC60559 support */ |
419 | | static double complex cexp(double complex x) |
420 | | { |
421 | | double expx = exp(creal(x)), y = cimag(x); |
422 | | return expx * cos(y) + (expx * sin(y)) * I; |
423 | | } |
424 | | #endif |
425 | | |
426 | | #ifndef HAVE_CCOS |
427 | | #define ccos R_ccos |
428 | | static double complex ccos(double complex x) |
429 | | { |
430 | | double xr = creal(x), xi = cimag(x); |
431 | | return cos(xr)*cosh(xi) - sin(xr)*sinh(xi)*I; /* A&S 4.3.56 */ |
432 | | } |
433 | | #endif |
434 | | |
435 | | #ifndef HAVE_CSIN |
436 | | #define csin R_csin |
437 | | static double complex csin(double complex x) |
438 | | { |
439 | | double xr = creal(x), xi = cimag(x); |
440 | | return sin(xr)*cosh(xi) + cos(xr)*sinh(xi)*I; /* A&S 4.3.55 */ |
441 | | } |
442 | | #endif |
443 | | |
444 | | #ifndef HAVE_CTAN |
445 | | #define ctan R_ctan |
446 | | static double complex ctan(double complex z) |
447 | | { |
448 | | /* A&S 4.3.57 */ |
449 | | double x2, y2, den, ri; |
450 | | x2 = 2.0 * creal(z); |
451 | | y2 = 2.0 * cimag(z); |
452 | | den = cos(x2) + cosh(y2); |
453 | | /* any threshold between -log(DBL_EPSILON) and log(DBL_XMAX) will do*/ |
454 | | if (ISNAN(y2) || fabs(y2) < 50.0) ri = sinh(y2)/den; |
455 | | else ri = (y2 < 0 ? -1.0 : 1.0); |
456 | | return sin(x2)/den + ri * I; |
457 | | } |
458 | | #endif |
459 | | |
460 | | #ifndef HAVE_CASIN |
461 | | #define casin R_casin |
462 | | static double complex casin(double complex z) |
463 | | { |
464 | | /* A&S 4.4.37 */ |
465 | | double x = creal(z), y = cimag(z), |
466 | | t1 = 0.5 * hypot(x + 1, y), |
467 | | t2 = 0.5 * hypot(x - 1, y), |
468 | | alpha = t1 + t2, |
469 | | ri = log(alpha + sqrt(alpha*alpha - 1)); |
470 | | /* This comes from |
471 | | 'z_asin() is continuous from below if x >= 1 |
472 | | and continuous from above if x <= -1.' |
473 | | */ |
474 | | if(y < 0 || (y == 0 && x > 1)) ri *= -1; |
475 | | return asin(t1 - t2) + ri*I; |
476 | | } |
477 | | #endif |
478 | | |
479 | | #ifndef HAVE_CACOS |
480 | | #define cacos R_cacos |
481 | | static double complex cacos(double complex z) |
482 | | { |
483 | | return M_PI_2 - casin(z); |
484 | | } |
485 | | #endif |
486 | | |
487 | | #ifndef HAVE_CATAN |
488 | | #define catan R_catan |
489 | | static double complex catan(double complex z) |
490 | | { |
491 | | double x = creal(z), y = cimag(z), rr, ri; |
492 | | rr = 0.5 * atan2(2 * x, (1 - x * x - y * y)); |
493 | | ri = 0.25 * log((x * x + (y + 1) * (y + 1)) / |
494 | | (x * x + (y - 1) * (y - 1))); |
495 | | return rr + ri*I; |
496 | | } |
497 | | #endif |
498 | | |
499 | | #ifndef HAVE_CCOSH |
500 | | #define ccosh R_ccosh |
501 | | static double complex ccosh(double complex z) |
502 | | { |
503 | | return ccos(z * I); /* A&S 4.5.8 */ |
504 | | } |
505 | | #endif |
506 | | |
507 | | #ifndef HAVE_CSINH |
508 | | #define csinh R_csinh |
509 | | static double complex csinh(double complex z) |
510 | | { |
511 | | return -I * csin(z * I); /* A&S 4.5.7 */ |
512 | | } |
513 | | #endif |
514 | | |
515 | | static double complex z_tan(double complex z) |
516 | 0 | { |
517 | 0 | double y = cimag(z); |
518 | 0 | double complex r = ctan(z); |
519 | 0 | if(R_FINITE(y) && fabs(y) > 25.0) { |
520 | | /* at this point the real part is nearly zero, and the |
521 | | imaginary part is one: but some OSes get the imag as NaN */ |
522 | 0 | #if __GNUC__ |
523 | 0 | __imag__ r = y < 0 ? -1.0 : 1.0; |
524 | | #else |
525 | | r = creal(r) + (y < 0 ? -1.0 : 1.0) * I; |
526 | | #endif |
527 | 0 | } |
528 | 0 | return r; |
529 | 0 | } |
530 | | |
531 | | #ifndef HAVE_CTANH |
532 | | #define ctanh R_ctanh |
533 | | static double complex ctanh(double complex z) |
534 | | { |
535 | | return -I * z_tan(z * I); /* A&S 4.5.9 */ |
536 | | } |
537 | | #endif |
538 | | |
539 | | |
540 | | /* Don't rely on the OS at the branch cuts */ |
541 | | |
542 | | static double complex z_asin(double complex z) |
543 | 0 | { |
544 | 0 | if(cimag(z) == 0 && fabs(creal(z)) > 1) { |
545 | 0 | double alpha, t1, t2, x = creal(z), ri; |
546 | 0 | t1 = 0.5 * fabs(x + 1); |
547 | 0 | t2 = 0.5 * fabs(x - 1); |
548 | 0 | alpha = t1 + t2; |
549 | 0 | ri = log(alpha + sqrt(alpha*alpha - 1)); |
550 | 0 | if(x > 1) ri *= -1; |
551 | 0 | return asin(t1 - t2) + ri*I; |
552 | 0 | } |
553 | 0 | return casin(z); |
554 | 0 | } |
555 | | |
556 | | static double complex z_acos(double complex z) |
557 | 0 | { |
558 | 0 | if(cimag(z) == 0 && fabs(creal(z)) > 1) return M_PI_2 - z_asin(z); |
559 | 0 | return cacos(z); |
560 | 0 | } |
561 | | |
562 | | static double complex z_atan(double complex z) |
563 | 0 | { |
564 | 0 | if(creal(z) == 0 && fabs(cimag(z)) > 1) { |
565 | 0 | double y = cimag(z), rr, ri; |
566 | 0 | rr = (y > 0) ? M_PI_2 : -M_PI_2; |
567 | 0 | ri = 0.25 * log(((y + 1) * (y + 1))/((y - 1) * (y - 1))); |
568 | 0 | return rr + ri*I; |
569 | 0 | } |
570 | 0 | return catan(z); |
571 | 0 | } |
572 | | |
573 | | static double complex z_acosh(double complex z) |
574 | 0 | { |
575 | 0 | return z_acos(z) * I; |
576 | 0 | } |
577 | | |
578 | | static double complex z_asinh(double complex z) |
579 | 0 | { |
580 | 0 | return -I * z_asin(z * I); |
581 | 0 | } |
582 | | |
583 | | static double complex z_atanh(double complex z) |
584 | 0 | { |
585 | 0 | return -I * z_atan(z * I); |
586 | 0 | } |
587 | | |
588 | | #ifdef HAVE_CABS |
589 | | # define R_CABS(Z) cabs(Z) |
590 | | #else |
591 | | # define R_CABS(Z) hypot(creal(Z), cimag(Z)) |
592 | | #endif |
593 | | |
594 | | |
595 | | static bool cmath1(double complex (*f)(double complex), |
596 | | const Rcomplex *x, Rcomplex *y, R_xlen_t n) |
597 | 0 | { |
598 | 0 | R_xlen_t i; |
599 | 0 | bool naflag = false; |
600 | 0 | for (i = 0 ; i < n ; i++) { |
601 | 0 | if (ISNA(x[i].r) || ISNA(x[i].i)) { |
602 | 0 | y[i].r = NA_REAL; y[i].i = NA_REAL; |
603 | 0 | } else { |
604 | 0 | SET_C99_COMPLEX(y, i, f(toC99(x + i))); |
605 | 0 | if ( (ISNAN(y[i].r) || ISNAN(y[i].i)) && |
606 | 0 | !(ISNAN(x[i].r) || ISNAN(x[i].i)) ) naflag = true; |
607 | 0 | } |
608 | 0 | } |
609 | 0 | return naflag; |
610 | 0 | } |
611 | | |
612 | | attribute_hidden SEXP complex_math1(SEXP call, SEXP op, SEXP args, SEXP env) |
613 | 0 | { |
614 | 0 | SEXP x, y; |
615 | 0 | R_xlen_t n; |
616 | 0 | bool naflag = false; |
617 | |
|
618 | 0 | PROTECT(x = CAR(args)); |
619 | 0 | n = XLENGTH(x); |
620 | 0 | PROTECT(y = allocVector(CPLXSXP, n)); |
621 | |
|
622 | 0 | const Rcomplex *px = COMPLEX_RO(x); |
623 | 0 | Rcomplex *py = COMPLEX(y); |
624 | |
|
625 | 0 | switch (PRIMVAL(op)) { |
626 | 0 | case 10003: naflag = cmath1(clog, px, py, n); break; |
627 | | // 1: floor |
628 | | // 2: ceil[ing] |
629 | 0 | case 3: naflag = cmath1(csqrt, px, py, n); break; |
630 | | // 4: sign |
631 | 0 | case 10: naflag = cmath1(cexp, px, py, n); break; |
632 | | // 11: expm1 |
633 | | // 12: log1p |
634 | 0 | case 20: naflag = cmath1(ccos, px, py, n); break; |
635 | 0 | case 21: naflag = cmath1(csin, px, py, n); break; |
636 | 0 | case 22: naflag = cmath1(z_tan, px, py, n); break; |
637 | 0 | case 23: naflag = cmath1(z_acos, px, py, n); break; |
638 | 0 | case 24: naflag = cmath1(z_asin, px, py, n); break; |
639 | 0 | case 25: naflag = cmath1(z_atan, px, py, n); break; |
640 | | |
641 | 0 | case 30: naflag = cmath1(ccosh, px, py, n); break; |
642 | 0 | case 31: naflag = cmath1(csinh, px, py, n); break; |
643 | 0 | case 32: naflag = cmath1(ctanh, px, py, n); break; |
644 | 0 | case 33: naflag = cmath1(z_acosh, px, py, n); break; |
645 | 0 | case 34: naflag = cmath1(z_asinh, px, py, n); break; |
646 | 0 | case 35: naflag = cmath1(z_atanh, px, py, n); break; |
647 | | |
648 | 0 | default: |
649 | | /* such as sign, gamma */ |
650 | 0 | errorcall(call, _("unimplemented complex function")); |
651 | 0 | } |
652 | 0 | if (naflag) |
653 | 0 | warningcall(call, "NaNs produced in function \"%s\"", PRIMNAME(op)); |
654 | 0 | SHALLOW_DUPLICATE_ATTRIB(y, x); |
655 | 0 | UNPROTECT(2); |
656 | 0 | return y; |
657 | 0 | } |
658 | | |
659 | | static void z_rround(Rcomplex *r, Rcomplex *x, Rcomplex *p) |
660 | 0 | { |
661 | 0 | r->r = fround(x->r, p->r); |
662 | 0 | r->i = fround(x->i, p->r); |
663 | 0 | } |
664 | | |
665 | | static void z_prec(Rcomplex *r, Rcomplex *x, Rcomplex *p) |
666 | 0 | { |
667 | 0 | z_prec_r(r, x, p->r); |
668 | 0 | } |
669 | | |
670 | | static void z_logbase(Rcomplex *r, Rcomplex *z, Rcomplex *base) |
671 | 0 | { |
672 | 0 | double complex dz = toC99(z), dbase = toC99(base); |
673 | 0 | SET_C99_COMPLEX(r, 0, clog(dz)/clog(dbase)); |
674 | 0 | } |
675 | | |
676 | | static void z_atan2(Rcomplex *r, Rcomplex *csn, Rcomplex *ccs) |
677 | 0 | { |
678 | 0 | double complex dr, dcsn = toC99(csn), dccs = toC99(ccs); |
679 | 0 | if (dccs == 0) { |
680 | 0 | if(dcsn == 0) { |
681 | 0 | r->r = NA_REAL; r->i = NA_REAL; /* Why not R_NaN? */ |
682 | 0 | return; |
683 | 0 | } else { |
684 | 0 | double y = creal(dcsn); |
685 | 0 | if (ISNAN(y)) dr = y; |
686 | 0 | else dr = ((y >= 0) ? M_PI_2 : -M_PI_2); |
687 | 0 | } |
688 | 0 | } else { |
689 | 0 | dr = catan(dcsn / dccs); |
690 | 0 | if(creal(dccs) < 0) dr += M_PI; |
691 | 0 | if(creal(dr) > M_PI) dr -= 2 * M_PI; |
692 | 0 | } |
693 | 0 | SET_C99_COMPLEX(r, 0, dr); |
694 | 0 | } |
695 | | |
696 | | |
697 | | /* Complex Functions of Two Arguments */ |
698 | | |
699 | | typedef void (*cm2_fun)(Rcomplex *, Rcomplex *, Rcomplex *); |
700 | | attribute_hidden SEXP complex_math2(SEXP call, SEXP op, SEXP args, SEXP env) |
701 | 0 | { |
702 | 0 | cm2_fun f; |
703 | 0 | switch (PRIMVAL(op)) { |
704 | 0 | case 0: /* atan2 */ |
705 | 0 | f = z_atan2; break; |
706 | 0 | case 10001: /* round */ |
707 | 0 | f = z_rround; break; |
708 | 0 | case 10002: /* passed from do_log1arg */ |
709 | 0 | case 10010: /* " " " */ |
710 | 0 | case 10003: /* passed from do_log */ |
711 | 0 | f = z_logbase; break; |
712 | 0 | case 10004: /* signif */ |
713 | 0 | f = z_prec; break; |
714 | 0 | default: |
715 | 0 | error_return(_("unimplemented complex function")); |
716 | 0 | } |
717 | | |
718 | 0 | SEXP |
719 | 0 | sa = PROTECT(coerceVector(CAR(args), CPLXSXP)), |
720 | 0 | sb = PROTECT(coerceVector(CADR(args), CPLXSXP)); |
721 | 0 | R_xlen_t na = XLENGTH(sa), nb = XLENGTH(sb), n; |
722 | 0 | if ((na == 0) || (nb == 0)) { |
723 | 0 | UNPROTECT(2); |
724 | 0 | return(allocVector(CPLXSXP, 0)); |
725 | 0 | } |
726 | 0 | n = (na < nb) ? nb : na; |
727 | 0 | SEXP sy = PROTECT(allocVector(CPLXSXP, n)); |
728 | 0 | const Rcomplex |
729 | 0 | *a = COMPLEX_RO(sa), |
730 | 0 | *b = COMPLEX_RO(sb); |
731 | 0 | Rcomplex ai, bi, *y = COMPLEX(sy); |
732 | 0 | R_xlen_t i, ia, ib; |
733 | 0 | bool naflag = false; |
734 | 0 | MOD_ITERATE2(n, na, nb, i, ia, ib, { |
735 | 0 | ai = a[ia]; bi = b[ib]; |
736 | 0 | if(ISNA(ai.r) && ISNA(ai.i) && |
737 | 0 | ISNA(bi.r) && ISNA(bi.i)) { |
738 | 0 | y[i].r = NA_REAL; y[i].i = NA_REAL; |
739 | 0 | } else { |
740 | 0 | f(&y[i], &ai, &bi); |
741 | 0 | if ( (ISNAN(y[i].r) || ISNAN(y[i].i)) && |
742 | 0 | !(ISNAN(ai.r) || ISNAN(ai.i) || ISNAN(bi.r) || ISNAN(bi.i)) ) |
743 | 0 | naflag = true; |
744 | 0 | } |
745 | 0 | }); |
746 | 0 | if (naflag) |
747 | 0 | warning("NaNs produced in function \"%s\"", PRIMNAME(op)); |
748 | 0 | if(n == na) { |
749 | 0 | SHALLOW_DUPLICATE_ATTRIB(sy, sa); |
750 | 0 | } else if(n == nb) { |
751 | 0 | SHALLOW_DUPLICATE_ATTRIB(sy, sb); |
752 | 0 | } |
753 | 0 | UNPROTECT(3); |
754 | 0 | return sy; |
755 | 0 | } |
756 | | |
757 | | attribute_hidden SEXP do_complex(SEXP call, SEXP op, SEXP args, SEXP rho) |
758 | 0 | { |
759 | | /* complex(length, real, imaginary) */ |
760 | 0 | SEXP ans, re, im; |
761 | 0 | R_xlen_t i, na, nr, ni; |
762 | |
|
763 | 0 | checkArity(op, args); |
764 | 0 | na = asInteger(CAR(args)); |
765 | 0 | if(na == NA_INTEGER || na < 0) |
766 | 0 | error(_("invalid length")); |
767 | 0 | PROTECT(re = coerceVector(CADR(args), REALSXP)); |
768 | 0 | PROTECT(im = coerceVector(CADDR(args), REALSXP)); |
769 | 0 | nr = XLENGTH(re); |
770 | 0 | ni = XLENGTH(im); |
771 | | /* is always true: if (na >= 0) {*/ |
772 | 0 | na = (nr > na) ? nr : na; |
773 | 0 | na = (ni > na) ? ni : na; |
774 | | /* }*/ |
775 | 0 | ans = allocVector(CPLXSXP, na); |
776 | 0 | Rcomplex *pans = COMPLEX(ans); |
777 | 0 | for(i=0 ; i<na ; i++) { |
778 | 0 | pans[i].r = 0; |
779 | 0 | pans[i].i = 0; |
780 | 0 | } |
781 | 0 | UNPROTECT(2); |
782 | 0 | if(na > 0 && nr > 0) { |
783 | 0 | const double *p_re = REAL_RO(re); |
784 | 0 | for(i=0 ; i<na ; i++) |
785 | 0 | pans[i].r = p_re[i%nr]; |
786 | 0 | } |
787 | 0 | if(na > 0 && ni > 0) { |
788 | 0 | const double *p_im = REAL_RO(im); |
789 | 0 | for(i=0 ; i<na ; i++) |
790 | 0 | pans[i].i = p_im[i%ni]; |
791 | 0 | } |
792 | 0 | return ans; |
793 | 0 | } |
794 | | |
795 | | static void R_cpolyroot(double *opr, double *opi, int *degree, |
796 | | double *zeror, double *zeroi, bool *fail); |
797 | | |
798 | | attribute_hidden SEXP do_polyroot(SEXP call, SEXP op, SEXP args, SEXP rho) |
799 | 0 | { |
800 | 0 | checkArity(op, args); |
801 | 0 | SEXP z = CAR(args); |
802 | 0 | switch(TYPEOF(z)) { |
803 | 0 | case CPLXSXP: |
804 | 0 | PROTECT(z); |
805 | 0 | break; |
806 | 0 | case REALSXP: |
807 | 0 | case INTSXP: |
808 | 0 | case LGLSXP: |
809 | 0 | PROTECT(z = coerceVector(z, CPLXSXP)); |
810 | 0 | break; |
811 | 0 | default: |
812 | 0 | UNIMPLEMENTED_TYPE("polyroot", z); |
813 | 0 | } |
814 | | |
815 | 0 | int i, n; |
816 | 0 | #ifdef LONG_VECTOR_SUPPORT |
817 | 0 | R_xlen_t nn = XLENGTH(z); |
818 | 0 | if (nn > R_SHORT_LEN_MAX) error("long vectors are not supported"); |
819 | 0 | n = (int) nn; |
820 | | #else |
821 | | n = LENGTH(z); |
822 | | #endif |
823 | 0 | const Rcomplex *pz = COMPLEX_RO(z); |
824 | 0 | int degree = 0; // := max{i; z[i] != 0} |
825 | 0 | for(i = 0; i < n; i++) { |
826 | 0 | if(pz[i].r!= 0.0 || pz[i].i != 0.0) degree = i; |
827 | 0 | } |
828 | 0 | n = degree + 1; /* omit trailing zeroes */ |
829 | 0 | SEXP r; |
830 | 0 | if(degree >= 1) { |
831 | 0 | SEXP zr, zi, rr, ri; |
832 | 0 | PROTECT(rr = allocVector(REALSXP, n)); |
833 | 0 | PROTECT(ri = allocVector(REALSXP, n)); |
834 | 0 | PROTECT(zr = allocVector(REALSXP, n)); |
835 | 0 | PROTECT(zi = allocVector(REALSXP, n)); |
836 | |
|
837 | 0 | double *p_rr = REAL(rr); |
838 | 0 | double *p_ri = REAL(ri); |
839 | 0 | double *p_zr = REAL(zr); |
840 | 0 | double *p_zi = REAL(zi); |
841 | |
|
842 | 0 | for(i = 0 ; i < n ; i++) { |
843 | 0 | if(!R_FINITE(pz[i].r) || !R_FINITE(pz[i].i)) |
844 | 0 | error(_("invalid polynomial coefficient")); |
845 | 0 | p_zr[degree-i] = pz[i].r; |
846 | 0 | p_zi[degree-i] = pz[i].i; |
847 | 0 | } |
848 | 0 | bool fail; |
849 | 0 | R_cpolyroot(p_zr, p_zi, °ree, p_rr, p_ri, &fail); |
850 | 0 | if(fail) error(_("root finding code failed")); |
851 | 0 | UNPROTECT(2); |
852 | 0 | r = allocVector(CPLXSXP, degree); |
853 | 0 | Rcomplex *pr = COMPLEX(r); |
854 | 0 | for(i = 0 ; i < degree ; i++) { |
855 | 0 | pr[i].r = p_rr[i]; |
856 | 0 | pr[i].i = p_ri[i]; |
857 | 0 | } |
858 | 0 | UNPROTECT(3); |
859 | 0 | } |
860 | 0 | else { |
861 | 0 | UNPROTECT(1); |
862 | 0 | r = allocVector(CPLXSXP, 0); |
863 | 0 | } |
864 | 0 | return r; |
865 | 0 | } |
866 | | |
867 | | /* Formerly src/appl/cpoly.c: |
868 | | * |
869 | | * Copyright (C) 1997-1998 Ross Ihaka |
870 | | * Copyright (C) 1999-2001 R Core Team |
871 | | * |
872 | | * cpoly finds the zeros of a complex polynomial. |
873 | | * |
874 | | * On Entry |
875 | | * |
876 | | * opr, opi - double precision vectors of real and |
877 | | * imaginary parts of the coefficients in |
878 | | * order of decreasing powers. |
879 | | * |
880 | | * degree - int degree of polynomial. |
881 | | * |
882 | | * |
883 | | * On Return |
884 | | * |
885 | | * zeror, zeroi - output double precision vectors of |
886 | | * real and imaginary parts of the zeros. |
887 | | * |
888 | | * fail - output int parameter, true only if |
889 | | * leading coefficient is zero or if cpoly |
890 | | * has found fewer than degree zeros. |
891 | | * |
892 | | * The program has been written to reduce the chance of overflow |
893 | | * occurring. If it does occur, there is still a possibility that |
894 | | * the zerofinder will work provided the overflowed quantity is |
895 | | * replaced by a large number. |
896 | | * |
897 | | * This is a C translation of the following. |
898 | | * |
899 | | * TOMS Algorithm 419 |
900 | | * Jenkins and Traub. |
901 | | * Comm. ACM 15 (1972) 97-99. |
902 | | * |
903 | | * Ross Ihaka |
904 | | * February 1997 |
905 | | */ |
906 | | |
907 | | #include <R_ext/Arith.h> /* for declaration of hypot */ |
908 | | #include <R_ext/Memory.h> /* for declaration of R_alloc */ |
909 | | |
910 | | #include <float.h> /* for FLT_RADIX */ |
911 | | |
912 | | #include <Rmath.h> /* for R_pow_di */ |
913 | | |
914 | | static void calct(bool *); |
915 | | static bool fxshft(int, double *, double *); |
916 | | static bool vrshft(int, double *, double *); |
917 | | static void nexth(bool); |
918 | | static void noshft(int); |
919 | | |
920 | | static void polyev(int, double, double, |
921 | | double *, double *, double *, double *, double *, double *); |
922 | | static double errev(int, double *, double *, double, double, double, double); |
923 | | static double cpoly_cauchy(int, double *, double *); |
924 | | static double cpoly_scale(int, double *, double, double, double, double); |
925 | | static void cdivid(double, double, double, double, double *, double *); |
926 | | |
927 | | /* Global Variables (too many!) */ |
928 | | |
929 | | static int nn; |
930 | | static double *pr, *pi, *hr, *hi, *qpr, *qpi, *qhr, *qhi, *shr, *shi; |
931 | | static double sr, si; |
932 | | static double tr, ti; |
933 | | static double pvr, pvi; |
934 | | |
935 | | static const double eta = DBL_EPSILON; |
936 | | static const double are = /* eta = */DBL_EPSILON; |
937 | | static const double mre = 2. * M_SQRT2 * /* eta, i.e. */DBL_EPSILON; |
938 | | static const double infin = DBL_MAX; |
939 | | |
940 | | static void R_cpolyroot(double *opr, double *opi, int *degree, |
941 | | double *zeror, double *zeroi, bool *fail) |
942 | 0 | { |
943 | 0 | static const double smalno = DBL_MIN; |
944 | 0 | static const double base = (double)FLT_RADIX; |
945 | 0 | static int d_n, i, i1, i2; |
946 | 0 | static double zi, zr, xx, yy; |
947 | 0 | static double bnd, xxx; |
948 | 0 | bool conv; |
949 | 0 | int d1; |
950 | 0 | double *tmp; |
951 | 0 | static const double cosr =/* cos 94 */ -0.06975647374412529990; |
952 | 0 | static const double sinr =/* sin 94 */ 0.99756405025982424767; |
953 | 0 | xx = M_SQRT1_2;/* 1/sqrt(2) = 0.707.... */ |
954 | |
|
955 | 0 | yy = -xx; |
956 | 0 | *fail = false; |
957 | |
|
958 | 0 | nn = *degree; |
959 | 0 | d1 = nn - 1; |
960 | | |
961 | | /* algorithm fails if the leading coefficient is zero. */ |
962 | |
|
963 | 0 | if (opr[0] == 0. && opi[0] == 0.) { |
964 | 0 | *fail = true; |
965 | 0 | return; |
966 | 0 | } |
967 | | |
968 | | /* remove the zeros at the origin if any. */ |
969 | | |
970 | 0 | while (opr[nn] == 0. && opi[nn] == 0.) { |
971 | 0 | d_n = d1-nn+1; |
972 | 0 | zeror[d_n] = 0.; |
973 | 0 | zeroi[d_n] = 0.; |
974 | 0 | nn--; |
975 | 0 | } |
976 | 0 | nn++; |
977 | | /*-- Now, global var. nn := #{coefficients} = (relevant degree)+1 */ |
978 | |
|
979 | 0 | if (nn == 1) return; |
980 | | |
981 | | /* Use a single allocation as these as small */ |
982 | 0 | const void *vmax = vmaxget(); |
983 | 0 | tmp = (double *) R_alloc((size_t) (10*nn), sizeof(double)); |
984 | 0 | pr = tmp; pi = tmp + nn; hr = tmp + 2*nn; hi = tmp + 3*nn; |
985 | 0 | qpr = tmp + 4*nn; qpi = tmp + 5*nn; qhr = tmp + 6*nn; qhi = tmp + 7*nn; |
986 | 0 | shr = tmp + 8*nn; shi = tmp + 9*nn; |
987 | | |
988 | | /* make a copy of the coefficients and shr[] = | p[] | */ |
989 | 0 | for (i = 0; i < nn; i++) { |
990 | 0 | pr[i] = opr[i]; |
991 | 0 | pi[i] = opi[i]; |
992 | 0 | shr[i] = hypot(pr[i], pi[i]); |
993 | 0 | } |
994 | | |
995 | | /* scale the polynomial with factor 'bnd'. */ |
996 | 0 | bnd = cpoly_scale(nn, shr, eta, infin, smalno, base); |
997 | 0 | if (bnd != 1.) { |
998 | 0 | for (i=0; i < nn; i++) { |
999 | 0 | pr[i] *= bnd; |
1000 | 0 | pi[i] *= bnd; |
1001 | 0 | } |
1002 | 0 | } |
1003 | | |
1004 | | /* start the algorithm for one zero */ |
1005 | |
|
1006 | 0 | while (nn > 2) { |
1007 | | |
1008 | | /* calculate bnd, a lower bound on the modulus of the zeros. */ |
1009 | |
|
1010 | 0 | for (i=0 ; i < nn ; i++) |
1011 | 0 | shr[i] = hypot(pr[i], pi[i]); |
1012 | 0 | bnd = cpoly_cauchy(nn, shr, shi); |
1013 | | |
1014 | | /* outer loop to control 2 major passes */ |
1015 | | /* with different sequences of shifts */ |
1016 | |
|
1017 | 0 | for (i1 = 1; i1 <= 2; i1++) { |
1018 | | |
1019 | | /* first stage calculation, no shift */ |
1020 | |
|
1021 | 0 | noshft(5); |
1022 | | |
1023 | | /* inner loop to select a shift */ |
1024 | 0 | for (i2 = 1; i2 <= 9; i2++) { |
1025 | | |
1026 | | /* shift is chosen with modulus bnd */ |
1027 | | /* and amplitude rotated by 94 degrees */ |
1028 | | /* from the previous shift */ |
1029 | |
|
1030 | 0 | xxx= cosr * xx - sinr * yy; |
1031 | 0 | yy = sinr * xx + cosr * yy; |
1032 | 0 | xx = xxx; |
1033 | 0 | sr = bnd * xx; |
1034 | 0 | si = bnd * yy; |
1035 | | |
1036 | | /* second stage calculation, fixed shift */ |
1037 | |
|
1038 | 0 | conv = fxshft(i2 * 10, &zr, &zi); |
1039 | 0 | if (conv) |
1040 | 0 | goto L10; |
1041 | 0 | } |
1042 | 0 | } |
1043 | | |
1044 | | /* the zerofinder has failed on two major passes */ |
1045 | | /* return empty handed */ |
1046 | | |
1047 | 0 | *fail = true; |
1048 | 0 | vmaxset(vmax); |
1049 | 0 | return; |
1050 | | |
1051 | | /* the second stage jumps directly to the third stage iteration. |
1052 | | * if successful, the zero is stored and the polynomial deflated. |
1053 | | */ |
1054 | 0 | L10: |
1055 | 0 | d_n = d1+2 - nn; |
1056 | 0 | zeror[d_n] = zr; |
1057 | 0 | zeroi[d_n] = zi; |
1058 | 0 | --nn; |
1059 | 0 | for (i=0; i < nn ; i++) { |
1060 | 0 | pr[i] = qpr[i]; |
1061 | 0 | pi[i] = qpi[i]; |
1062 | 0 | } |
1063 | 0 | }/*while*/ |
1064 | | |
1065 | | /* calculate the final zero and return */ |
1066 | 0 | cdivid(-pr[1], -pi[1], pr[0], pi[0], &zeror[d1], &zeroi[d1]); |
1067 | |
|
1068 | 0 | vmaxset(vmax); |
1069 | 0 | return; |
1070 | 0 | } |
1071 | | |
1072 | | |
1073 | | /* Computes the derivative polynomial as the initial |
1074 | | * polynomial and computes l1 no-shift h polynomials. */ |
1075 | | |
1076 | | static void noshft(int l1) |
1077 | 0 | { |
1078 | 0 | int i, j, jj, n = nn - 1, nm1 = n - 1; |
1079 | |
|
1080 | 0 | double t1, t2, xni; |
1081 | |
|
1082 | 0 | for (i=0; i < n; i++) { |
1083 | 0 | xni = (double)(nn - i - 1); |
1084 | 0 | hr[i] = xni * pr[i] / n; |
1085 | 0 | hi[i] = xni * pi[i] / n; |
1086 | 0 | } |
1087 | |
|
1088 | 0 | for (jj = 1; jj <= l1; jj++) { |
1089 | |
|
1090 | 0 | if (hypot(hr[n-1], hi[n-1]) <= |
1091 | 0 | eta * 10.0 * hypot(pr[n-1], pi[n-1])) { |
1092 | | /* If the constant term is essentially zero, */ |
1093 | | /* shift h coefficients. */ |
1094 | |
|
1095 | 0 | for (i = 1; i <= nm1; i++) { |
1096 | 0 | j = nn - i; |
1097 | 0 | hr[j-1] = hr[j-2]; |
1098 | 0 | hi[j-1] = hi[j-2]; |
1099 | 0 | } |
1100 | 0 | hr[0] = 0.; |
1101 | 0 | hi[0] = 0.; |
1102 | 0 | } |
1103 | 0 | else { |
1104 | 0 | cdivid(-pr[nn-1], -pi[nn-1], hr[n-1], hi[n-1], &tr, &ti); |
1105 | 0 | for (i = 1; i <= nm1; i++) { |
1106 | 0 | j = nn - i; |
1107 | 0 | t1 = hr[j-2]; |
1108 | 0 | t2 = hi[j-2]; |
1109 | 0 | hr[j-1] = tr * t1 - ti * t2 + pr[j-1]; |
1110 | 0 | hi[j-1] = tr * t2 + ti * t1 + pi[j-1]; |
1111 | 0 | } |
1112 | 0 | hr[0] = pr[0]; |
1113 | 0 | hi[0] = pi[0]; |
1114 | 0 | } |
1115 | 0 | } |
1116 | 0 | } |
1117 | | |
1118 | | |
1119 | | /* Computes l2 fixed-shift h polynomials and tests for convergence. |
1120 | | * initiates a variable-shift iteration and returns with the |
1121 | | * approximate zero if successful. |
1122 | | */ |
1123 | | static bool fxshft(int l2, double *zr, double *zi) |
1124 | 0 | { |
1125 | | /* l2 - limit of fixed shift steps |
1126 | | * zr,zi - approximate zero if convergence (result TRUE) |
1127 | | * |
1128 | | * Return value indicates convergence of stage 3 iteration |
1129 | | * |
1130 | | * Uses global (sr,si), nn, pr[], pi[], .. (all args of polyev() !) |
1131 | | */ |
1132 | |
|
1133 | 0 | bool pasd, h_s_0, test; |
1134 | 0 | static double svsi, svsr; |
1135 | 0 | static int i, j, n; |
1136 | 0 | static double oti, otr; |
1137 | |
|
1138 | 0 | n = nn - 1; |
1139 | | |
1140 | | /* evaluate p at s. */ |
1141 | |
|
1142 | 0 | polyev(nn, sr, si, pr, pi, qpr, qpi, &pvr, &pvi); |
1143 | |
|
1144 | 0 | test = true; |
1145 | 0 | pasd = false; |
1146 | | |
1147 | | /* calculate first t = -p(s)/h(s). */ |
1148 | |
|
1149 | 0 | calct(&h_s_0); |
1150 | | |
1151 | | /* main loop for one second stage step. */ |
1152 | |
|
1153 | 0 | for (j=1; j<=l2; j++) { |
1154 | |
|
1155 | 0 | otr = tr; |
1156 | 0 | oti = ti; |
1157 | | |
1158 | | /* compute next h polynomial and new t. */ |
1159 | |
|
1160 | 0 | nexth(h_s_0); |
1161 | 0 | calct(&h_s_0); |
1162 | 0 | *zr = sr + tr; |
1163 | 0 | *zi = si + ti; |
1164 | | |
1165 | | /* test for convergence unless stage 3 has */ |
1166 | | /* failed once or this is the last h polynomial. */ |
1167 | |
|
1168 | 0 | if (!h_s_0 && test && j != l2) { |
1169 | 0 | if (hypot(tr - otr, ti - oti) >= hypot(*zr, *zi) * 0.5) { |
1170 | 0 | pasd = false; |
1171 | 0 | } |
1172 | 0 | else if (! pasd) { |
1173 | 0 | pasd = true; |
1174 | 0 | } |
1175 | 0 | else { |
1176 | | |
1177 | | /* the weak convergence test has been */ |
1178 | | /* passed twice, start the third stage */ |
1179 | | /* iteration, after saving the current */ |
1180 | | /* h polynomial and shift. */ |
1181 | |
|
1182 | 0 | for (i = 0; i < n; i++) { |
1183 | 0 | shr[i] = hr[i]; |
1184 | 0 | shi[i] = hi[i]; |
1185 | 0 | } |
1186 | 0 | svsr = sr; |
1187 | 0 | svsi = si; |
1188 | 0 | if (vrshft(10, zr, zi)) { |
1189 | 0 | return true; |
1190 | 0 | } |
1191 | | |
1192 | | /* the iteration failed to converge. */ |
1193 | | /* turn off testing and restore */ |
1194 | | /* h, s, pv and t. */ |
1195 | | |
1196 | 0 | test = false; |
1197 | 0 | for (i=1 ; i<=n ; i++) { |
1198 | 0 | hr[i-1] = shr[i-1]; |
1199 | 0 | hi[i-1] = shi[i-1]; |
1200 | 0 | } |
1201 | 0 | sr = svsr; |
1202 | 0 | si = svsi; |
1203 | 0 | polyev(nn, sr, si, pr, pi, qpr, qpi, &pvr, &pvi); |
1204 | 0 | calct(&h_s_0); |
1205 | 0 | } |
1206 | 0 | } |
1207 | 0 | } |
1208 | | |
1209 | | /* attempt an iteration with final h polynomial */ |
1210 | | /* from second stage. */ |
1211 | | |
1212 | 0 | return(vrshft(10, zr, zi)); |
1213 | 0 | } |
1214 | | |
1215 | | |
1216 | | /* carries out the third stage iteration. |
1217 | | */ |
1218 | | static bool vrshft(int l3, double *zr, double *zi) |
1219 | 0 | { |
1220 | | /* l3 - limit of steps in stage 3. |
1221 | | * zr,zi - on entry contains the initial iterate; |
1222 | | * if the iteration converges it contains |
1223 | | * the final iterate on exit. |
1224 | | * Returns TRUE if iteration converges |
1225 | | * |
1226 | | * Assign and uses GLOBAL sr, si |
1227 | | */ |
1228 | 0 | bool h_s_0, b; |
1229 | 0 | static int i, j; |
1230 | 0 | static double r1, r2, mp, ms, tp, relstp; |
1231 | 0 | static double omp; |
1232 | |
|
1233 | 0 | b = false; |
1234 | 0 | sr = *zr; |
1235 | 0 | si = *zi; |
1236 | | |
1237 | | /* main loop for stage three */ |
1238 | |
|
1239 | 0 | for (i = 1; i <= l3; i++) { |
1240 | | |
1241 | | /* evaluate p at s and test for convergence. */ |
1242 | 0 | polyev(nn, sr, si, pr, pi, qpr, qpi, &pvr, &pvi); |
1243 | |
|
1244 | 0 | mp = hypot(pvr, pvi); |
1245 | 0 | ms = hypot(sr, si); |
1246 | 0 | if (mp <= 20. * errev(nn, qpr, qpi, ms, mp, /*are=*/eta, mre)) { |
1247 | 0 | goto L_conv; |
1248 | 0 | } |
1249 | | |
1250 | | /* polynomial value is smaller in value than */ |
1251 | | /* a bound on the error in evaluating p, */ |
1252 | | /* terminate the iteration. */ |
1253 | | |
1254 | 0 | if (i != 1) { |
1255 | |
|
1256 | 0 | if (!b && mp >= omp && relstp < .05) { |
1257 | | |
1258 | | /* iteration has stalled. probably a */ |
1259 | | /* cluster of zeros. do 5 fixed shift */ |
1260 | | /* steps into the cluster to force */ |
1261 | | /* one zero to dominate. */ |
1262 | |
|
1263 | 0 | tp = relstp; |
1264 | 0 | b = true; |
1265 | 0 | if (relstp < eta) |
1266 | 0 | tp = eta; |
1267 | 0 | r1 = sqrt(tp); |
1268 | 0 | r2 = sr * (r1 + 1.) - si * r1; |
1269 | 0 | si = sr * r1 + si * (r1 + 1.); |
1270 | 0 | sr = r2; |
1271 | 0 | polyev(nn, sr, si, pr, pi, qpr, qpi, &pvr, &pvi); |
1272 | 0 | for (j = 1; j <= 5; ++j) { |
1273 | 0 | calct(&h_s_0); |
1274 | 0 | nexth(h_s_0); |
1275 | 0 | } |
1276 | 0 | omp = infin; |
1277 | 0 | goto L10; |
1278 | 0 | } |
1279 | 0 | else { |
1280 | | |
1281 | | /* exit if polynomial value */ |
1282 | | /* increases significantly. */ |
1283 | |
|
1284 | 0 | if (mp * .1 > omp) |
1285 | 0 | return false; |
1286 | 0 | } |
1287 | 0 | } |
1288 | 0 | omp = mp; |
1289 | | |
1290 | | /* calculate next iterate. */ |
1291 | |
|
1292 | 0 | L10: |
1293 | 0 | calct(&h_s_0); |
1294 | 0 | nexth(h_s_0); |
1295 | 0 | calct(&h_s_0); |
1296 | 0 | if (!h_s_0) { |
1297 | 0 | relstp = hypot(tr, ti) / hypot(sr, si); |
1298 | 0 | sr += tr; |
1299 | 0 | si += ti; |
1300 | 0 | } |
1301 | 0 | } |
1302 | 0 | return false; |
1303 | | |
1304 | 0 | L_conv: |
1305 | 0 | *zr = sr; |
1306 | 0 | *zi = si; |
1307 | 0 | return true; |
1308 | 0 | } |
1309 | | |
1310 | | static void calct(bool *h_s_0) |
1311 | 0 | { |
1312 | | /* computes t = -p(s)/h(s). |
1313 | | * h_s_0 - logical, set true if h(s) is essentially zero. */ |
1314 | |
|
1315 | 0 | int n = nn - 1; |
1316 | 0 | double hvi, hvr; |
1317 | | |
1318 | | /* evaluate h(s). */ |
1319 | 0 | polyev(n, sr, si, hr, hi, |
1320 | 0 | qhr, qhi, &hvr, &hvi); |
1321 | |
|
1322 | 0 | *h_s_0 = hypot(hvr, hvi) <= are * 10. * hypot(hr[n-1], hi[n-1]); |
1323 | 0 | if (!*h_s_0) { |
1324 | 0 | cdivid(-pvr, -pvi, hvr, hvi, &tr, &ti); |
1325 | 0 | } |
1326 | 0 | else { |
1327 | 0 | tr = 0.; |
1328 | 0 | ti = 0.; |
1329 | 0 | } |
1330 | 0 | } |
1331 | | |
1332 | | static void nexth(bool h_s_0) |
1333 | 0 | { |
1334 | | /* calculates the next shifted h polynomial. |
1335 | | * h_s_0 : if TRUE h(s) is essentially zero |
1336 | | */ |
1337 | 0 | int j, n = nn - 1; |
1338 | 0 | double t1, t2; |
1339 | |
|
1340 | 0 | if (!h_s_0) { |
1341 | 0 | for (j=1; j < n; j++) { |
1342 | 0 | t1 = qhr[j - 1]; |
1343 | 0 | t2 = qhi[j - 1]; |
1344 | 0 | hr[j] = tr * t1 - ti * t2 + qpr[j]; |
1345 | 0 | hi[j] = tr * t2 + ti * t1 + qpi[j]; |
1346 | 0 | } |
1347 | 0 | hr[0] = qpr[0]; |
1348 | 0 | hi[0] = qpi[0]; |
1349 | 0 | } |
1350 | 0 | else { |
1351 | | /* if h(s) is zero replace h with qh. */ |
1352 | |
|
1353 | 0 | for (j=1; j < n; j++) { |
1354 | 0 | hr[j] = qhr[j-1]; |
1355 | 0 | hi[j] = qhi[j-1]; |
1356 | 0 | } |
1357 | 0 | hr[0] = 0.; |
1358 | 0 | hi[0] = 0.; |
1359 | 0 | } |
1360 | 0 | } |
1361 | | |
1362 | | /*--------------------- Independent Complex Polynomial Utilities ----------*/ |
1363 | | |
1364 | | static |
1365 | | void polyev(int n, |
1366 | | double s_r, double s_i, |
1367 | | double *p_r, double *p_i, |
1368 | | double *q_r, double *q_i, |
1369 | | double *v_r, double *v_i) |
1370 | 0 | { |
1371 | | /* evaluates a polynomial p at s by the horner recurrence |
1372 | | * placing the partial sums in q and the computed value in v_. |
1373 | | */ |
1374 | 0 | int i; |
1375 | 0 | double t; |
1376 | |
|
1377 | 0 | q_r[0] = p_r[0]; |
1378 | 0 | q_i[0] = p_i[0]; |
1379 | 0 | *v_r = q_r[0]; |
1380 | 0 | *v_i = q_i[0]; |
1381 | 0 | for (i = 1; i < n; i++) { |
1382 | 0 | t = *v_r * s_r - *v_i * s_i + p_r[i]; |
1383 | 0 | q_i[i] = *v_i = *v_r * s_i + *v_i * s_r + p_i[i]; |
1384 | 0 | q_r[i] = *v_r = t; |
1385 | 0 | } |
1386 | 0 | } |
1387 | | |
1388 | | static |
1389 | | double errev(int n, double *qr, double *qi, |
1390 | | double ms, double mp, double a_re, double m_re) |
1391 | 0 | { |
1392 | | /* bounds the error in evaluating the polynomial by the horner |
1393 | | * recurrence. |
1394 | | * |
1395 | | * qr,qi - the partial sum vectors |
1396 | | * ms - modulus of the point |
1397 | | * mp - modulus of polynomial value |
1398 | | * a_re,m_re - error bounds on complex addition and multiplication |
1399 | | */ |
1400 | 0 | double e; |
1401 | 0 | int i; |
1402 | |
|
1403 | 0 | e = hypot(qr[0], qi[0]) * m_re / (a_re + m_re); |
1404 | 0 | for (i=0; i < n; i++) |
1405 | 0 | e = e*ms + hypot(qr[i], qi[i]); |
1406 | |
|
1407 | 0 | return e * (a_re + m_re) - mp * m_re; |
1408 | 0 | } |
1409 | | |
1410 | | |
1411 | | static |
1412 | | double cpoly_cauchy(int n, double *pot, double *q) |
1413 | 0 | { |
1414 | | /* Computes a lower bound on the moduli of the zeros of a polynomial |
1415 | | * pot[1:nn] is the modulus of the coefficients. |
1416 | | */ |
1417 | 0 | double f, x, delf, dx, xm; |
1418 | 0 | int i, n1 = n - 1; |
1419 | |
|
1420 | 0 | pot[n1] = -pot[n1]; |
1421 | | |
1422 | | /* compute upper estimate of bound. */ |
1423 | |
|
1424 | 0 | x = exp((log(-pot[n1]) - log(pot[0])) / (double) n1); |
1425 | | |
1426 | | /* if newton step at the origin is better, use it. */ |
1427 | |
|
1428 | 0 | if (pot[n1-1] != 0.) { |
1429 | 0 | xm = -pot[n1] / pot[n1-1]; |
1430 | 0 | if (xm < x) |
1431 | 0 | x = xm; |
1432 | 0 | } |
1433 | | |
1434 | | /* chop the interval (0,x) unitl f le 0. */ |
1435 | |
|
1436 | 0 | for(;;) { |
1437 | 0 | xm = x * 0.1; |
1438 | 0 | f = pot[0]; |
1439 | 0 | for (i = 1; i < n; i++) |
1440 | 0 | f = f * xm + pot[i]; |
1441 | 0 | if (f <= 0.0) { |
1442 | 0 | break; |
1443 | 0 | } |
1444 | 0 | x = xm; |
1445 | 0 | } |
1446 | |
|
1447 | 0 | dx = x; |
1448 | | |
1449 | | /* do Newton iteration until x converges to two decimal places. */ |
1450 | |
|
1451 | 0 | while (fabs(dx / x) > 0.005) { |
1452 | 0 | q[0] = pot[0]; |
1453 | 0 | for(i = 1; i < n; i++) |
1454 | 0 | q[i] = q[i-1] * x + pot[i]; |
1455 | 0 | f = q[n1]; |
1456 | 0 | delf = q[0]; |
1457 | 0 | for(i = 1; i < n1; i++) |
1458 | 0 | delf = delf * x + q[i]; |
1459 | 0 | dx = f / delf; |
1460 | 0 | x -= dx; |
1461 | 0 | } |
1462 | 0 | return x; |
1463 | 0 | } |
1464 | | |
1465 | | static |
1466 | | double cpoly_scale(int n, double *pot, |
1467 | | double eps, double BIG, double small, double base) |
1468 | 0 | { |
1469 | | /* Returns a scale factor to multiply the coefficients of the polynomial. |
1470 | | * The scaling is done to avoid overflow and to avoid |
1471 | | * undetected underflow interfering with the convergence criterion. |
1472 | | * The factor is a power of the base. |
1473 | | |
1474 | | * pot[1:n] : modulus of coefficients of p |
1475 | | * eps,BIG, |
1476 | | * small,base - constants describing the floating point arithmetic. |
1477 | | */ |
1478 | |
|
1479 | 0 | int i, ell; |
1480 | 0 | double x, high, sc, lo, min_, max_; |
1481 | | |
1482 | | /* find largest and smallest moduli of coefficients. */ |
1483 | 0 | high = sqrt(BIG); |
1484 | 0 | lo = small / eps; |
1485 | 0 | max_ = 0.; |
1486 | 0 | min_ = BIG; |
1487 | 0 | for (i = 0; i < n; i++) { |
1488 | 0 | x = pot[i]; |
1489 | 0 | if (x > max_) max_ = x; |
1490 | 0 | if (x != 0. && x < min_) |
1491 | 0 | min_ = x; |
1492 | 0 | } |
1493 | | |
1494 | | /* scale only if there are very large or very small components. */ |
1495 | |
|
1496 | 0 | if (min_ < lo || max_ > high) { |
1497 | 0 | x = lo / min_; |
1498 | 0 | if (x <= 1.) |
1499 | 0 | sc = 1. / (sqrt(max_) * sqrt(min_)); |
1500 | 0 | else { |
1501 | 0 | sc = x; |
1502 | 0 | if (BIG / sc > max_) |
1503 | 0 | sc = 1.0; |
1504 | 0 | } |
1505 | 0 | ell = (int) (log(sc) / log(base) + 0.5); |
1506 | 0 | return R_pow_di(base, ell); |
1507 | 0 | } |
1508 | 0 | else return 1.0; |
1509 | 0 | } |
1510 | | |
1511 | | |
1512 | | static |
1513 | | void cdivid(double ar, double ai, double br, double bi, |
1514 | | double *cr, double *ci) |
1515 | 0 | { |
1516 | | /* complex division c = a/b, i.e., (cr +i*ci) = (ar +i*ai) / (br +i*bi), |
1517 | | avoiding overflow. */ |
1518 | |
|
1519 | 0 | double d, r; |
1520 | |
|
1521 | 0 | if (br == 0. && bi == 0.) { |
1522 | | /* division by zero, c = infinity. */ |
1523 | 0 | *cr = *ci = R_PosInf; |
1524 | 0 | } |
1525 | 0 | else if (fabs(br) >= fabs(bi)) { |
1526 | 0 | r = bi / br; |
1527 | 0 | d = br + r * bi; |
1528 | 0 | *cr = (ar + ai * r) / d; |
1529 | 0 | *ci = (ai - ar * r) / d; |
1530 | 0 | } |
1531 | 0 | else { |
1532 | 0 | r = br / bi; |
1533 | 0 | d = bi + r * br; |
1534 | 0 | *cr = (ar * r + ai) / d; |
1535 | 0 | *ci = (ai * r - ar) / d; |
1536 | 0 | } |
1537 | 0 | } |
1538 | | |
1539 | | /* static double cpoly_cmod(double *r, double *i) |
1540 | | * --> replaced by hypot() everywhere |
1541 | | */ |