Coverage Report

Created: 2026-09-14 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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, &degree, 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
*/