C中高阶复杂多项式方程的根

问题描述 投票:-1回答:1

我有一个具有复数系数的第五多项式。我有一个用C编写的工作程序,我想在其中包含一个寻根算法。例如等式:

x ^ 5 + i x ^ 4 +(2 + i)x ^ 3 +(5 + i)x ^ 2 +(2 + 4i)x + 6 i = 0。

我一直在使用GSL库。例如:

#include <stdio.h>
#include <gsl/gsl_poly.h>

int
main (void)
{
  int i;
  /* coefficients of P(x) =  -1 + x^5  */
  double a[6] = { -1, 0, 0, 0, 0, 1 };
  double z[10];

  gsl_poly_complex_workspace * w
      = gsl_poly_complex_workspace_alloc (6);

  gsl_poly_complex_solve (a, 6, w, z);

  gsl_poly_complex_workspace_free (w);

  for (i = 0; i < 5; i++)
    {
      printf ("z%d = %+.18f %+.18f\n",
              i, z[2*i], z[2*i+1]);
    }

  return 0;
}

但是,它只能用于实系数。我如何才能通过它进行复杂系数的计算。甚至可以用C来做到这一点。

谢谢。

c polynomials gsl
1个回答
0
投票

[这是我所做的。 https://wp.csiro.au/alanmiller/toms.html

FORTRAN f77和f90中有一个代码

https://mathblog.com/polynomial-root-finding-with-the-jenkins-traub-algorithm/

能够使用f2c库将f77代码转换为c。 cpoly.c的代码如下

/* cpoly.f -- translated by f2c (version 20100827).
   You must link the resulting object file with libf2c:
    on Microsoft Windows system, link with libf2c.lib;
    on Linux or Unix systems, link with .../path/to/libf2c.a -lm
    or, if you install libf2c.a in a standard place, with -lf2c -lm
    -- in that order, at the end of the command line, as in
        cc *.o -lf2c -lm
    Source for libf2c is in /netlib/f2c/libf2c.zip, e.g.,

        http://www.netlib.org/f2c/libf2c.zip
*/

#include "f2c.h"

/* Common Block Declarations */

struct {
    doublereal pr[50], pi[50], hr[50], hi[50], qpr[50], qpi[50], qhr[50], qhi[
        50], shr[50], shi[50], sr, si, tr, ti, pvr, pvi, are, mre, eta, 
        infin;
    integer nn;
} global_;

#define global_1 global_

/* Table of constant values */

static integer c__5 = 5;
static integer c__10 = 10;

/* Subroutine */ int cpoly_(doublereal *opr, doublereal *opi, integer *degree,
     doublereal *zeror, doublereal *zeroi, logical *fail)
{
    /* System generated locals */
    integer i__1;
    doublereal d__1, d__2;

    /* Builtin functions */
    double sqrt(doublereal);

    /* Local variables */
    static integer i__;
    static doublereal zi, zr, xx, yy, bnd, xxx;
    static integer cnt1, cnt2;
    static doublereal base;
    extern doublereal cmod_(doublereal *, doublereal *);
    extern /* Subroutine */ int mcon_(doublereal *, doublereal *, doublereal *
        , doublereal *);
    static logical conv;
    static doublereal cosr, sinr;
    static integer idnn2;
    extern doublereal scale_(integer *, doublereal *, doublereal *, 
        doublereal *, doublereal *, doublereal *);
    extern /* Subroutine */ int cdivid_(doublereal *, doublereal *, 
        doublereal *, doublereal *, doublereal *, doublereal *);
    extern doublereal cauchy_(integer *, doublereal *, doublereal *);
    static doublereal smalno;
    extern /* Subroutine */ int noshft_(integer *), fxshft_(integer *, 
        doublereal *, doublereal *, logical *);


/* Added changes from Remark on Algorithm 419 by David H. Withers */
/* CACM (March 1974) Vol 17 No 3 p. 157 */

/* FINDS THE ZEROS OF A COMPLEX POLYNOMIAL. */
/* OPR, OPI  -  DOUBLE PRECISION VECTORS OF REAL AND */
/* IMAGINARY PARTS OF THE COEFFICIENTS IN */
/* ORDER OF DECREASING POWERS. */
/* DEGREE    -  INTEGER DEGREE OF POLYNOMIAL. */
/* ZEROR, ZEROI  -  OUTPUT DOUBLE PRECISION VECTORS OF */
/* REAL AND IMAGINARY PARTS OF THE ZEROS. */
/* FAIL      -  OUTPUT LOGICAL PARAMETER,  TRUE  ONLY IF */
/* LEADING COEFFICIENT IS ZERO OR IF CPOLY */
/* HAS FOUND FEWER THAN DEGREE ZEROS. */
/* THE PROGRAM HAS BEEN WRITTEN TO REDUCE THE CHANCE OF OVERFLOW */
/* OCCURRING. IF IT DOES OCCUR, THERE IS STILL A POSSIBILITY THAT */
/* THE ZEROFINDER WILL WORK PROVIDED THE OVERFLOWED QUANTITY IS */
/* REPLACED BY A LARGE NUMBER. */
/* COMMON AREA */
/* TO CHANGE THE SIZE OF POLYNOMIALS WHICH CAN BE SOLVED, REPLACE */
/* THE DIMENSION OF THE ARRAYS IN THE COMMON AREA. */
/* INITIALIZATION OF CONSTANTS */
    /* Parameter adjustments */
    --zeroi;
    --zeror;
    --opi;
    --opr;

    /* Function Body */
    mcon_(&global_1.eta, &global_1.infin, &smalno, &base);
    global_1.are = global_1.eta;
    global_1.mre = sqrt(2.) * 2. * global_1.eta;
    xx = .70710678f;
    yy = -xx;
    cosr = -.069756474f;
    sinr = .99756405f;
    *fail = FALSE_;
    global_1.nn = *degree + 1;
/* ALGORITHM FAILS IF THE LEADING COEFFICIENT IS ZERO. */
    if (opr[1] != 0. || opi[1] != 0.) {
    goto L10;
    }
    *fail = TRUE_;
    return 0;
/* REMOVE THE ZEROS AT THE ORIGIN IF ANY. */
L10:
    if (opr[global_1.nn] != 0. || opi[global_1.nn] != 0.) {
    goto L20;
    }
    idnn2 = *degree - global_1.nn + 2;
    zeror[idnn2] = 0.;
    zeroi[idnn2] = 0.;
    --global_1.nn;
    goto L10;
/* MAKE A COPY OF THE COEFFICIENTS. */
L20:
    i__1 = global_1.nn;
    for (i__ = 1; i__ <= i__1; ++i__) {
    global_1.pr[i__ - 1] = opr[i__];
    global_1.pi[i__ - 1] = opi[i__];
    global_1.shr[i__ - 1] = cmod_(&global_1.pr[i__ - 1], &global_1.pi[i__ 
        - 1]);
/* L30: */
    }
/* SCALE THE POLYNOMIAL. */
    bnd = scale_(&global_1.nn, global_1.shr, &global_1.eta, &global_1.infin, &
        smalno, &base);
    if (bnd == 1.) {
    goto L40;
    }
    i__1 = global_1.nn;
    for (i__ = 1; i__ <= i__1; ++i__) {
    global_1.pr[i__ - 1] = bnd * global_1.pr[i__ - 1];
    global_1.pi[i__ - 1] = bnd * global_1.pi[i__ - 1];
/* L35: */
    }
/* START THE ALGORITHM FOR ONE ZERO . */
L40:
    if (global_1.nn > 2) {
    goto L50;
    }
/* CALCULATE THE FINAL ZERO AND RETURN. */
    d__1 = -global_1.pr[1];
    d__2 = -global_1.pi[1];
    cdivid_(&d__1, &d__2, global_1.pr, global_1.pi, &zeror[*degree], &zeroi[*
        degree]);
    return 0;
/* CALCULATE BND, A LOWER BOUND ON THE MODULUS OF THE ZEROS. */
L50:
    i__1 = global_1.nn;
    for (i__ = 1; i__ <= i__1; ++i__) {
    global_1.shr[i__ - 1] = cmod_(&global_1.pr[i__ - 1], &global_1.pi[i__ 
        - 1]);
/* L60: */
    }
    bnd = cauchy_(&global_1.nn, global_1.shr, global_1.shi);
/* OUTER LOOP TO CONTROL 2 MAJOR PASSES WITH DIFFERENT SEQUENCES */
/* OF SHIFTS. */
    for (cnt1 = 1; cnt1 <= 2; ++cnt1) {
/* FIRST STAGE CALCULATION, NO SHIFT. */
    noshft_(&c__5);
/* INNER LOOP TO SELECT A SHIFT. */
    for (cnt2 = 1; cnt2 <= 9; ++cnt2) {
/* SHIFT IS CHOSEN WITH MODULUS BND AND AMPLITUDE ROTATED BY */
/* 94 DEGREES FROM THE PREVIOUS SHIFT */
        xxx = cosr * xx - sinr * yy;
        yy = sinr * xx + cosr * yy;
        xx = xxx;
        global_1.sr = bnd * xx;
        global_1.si = bnd * yy;
/* SECOND STAGE CALCULATION, FIXED SHIFT. */
        i__1 = cnt2 * 10;
        fxshft_(&i__1, &zr, &zi, &conv);
        if (! conv) {
        goto L80;
        }
/* THE SECOND STAGE JUMPS DIRECTLY TO THE THIRD STAGE ITERATION. */
/* IF SUCCESSFUL THE ZERO IS STORED AND THE POLYNOMIAL DEFLATED. */
        idnn2 = *degree - global_1.nn + 2;
        zeror[idnn2] = zr;
        zeroi[idnn2] = zi;
        --global_1.nn;
        i__1 = global_1.nn;
        for (i__ = 1; i__ <= i__1; ++i__) {
        global_1.pr[i__ - 1] = global_1.qpr[i__ - 1];
        global_1.pi[i__ - 1] = global_1.qpi[i__ - 1];
/* L70: */
        }
        goto L40;
L80:
/* IF THE ITERATION IS UNSUCCESSFUL ANOTHER SHIFT IS CHOSEN. */
/* L90: */
        ;
    }
/* IF 9 SHIFTS FAIL, THE OUTER LOOP IS REPEATED WITH ANOTHER */
/* SEQUENCE OF SHIFTS. */
/* L100: */
    }
/* THE ZEROFINDER HAS FAILED ON TWO MAJOR PASSES. */
/* RETURN EMPTY HANDED. */
    *fail = TRUE_;
    return 0;
} /* cpoly_ */

/* Subroutine */ int noshft_(integer *l1)
{
    /* System generated locals */
    integer i__1, i__2;
    doublereal d__1, d__2;

    /* Local variables */
    static integer i__, j, n;
    static doublereal t1, t2;
    static integer jj, nm1;
    static doublereal xni;
    extern doublereal cmod_(doublereal *, doublereal *);
    extern /* Subroutine */ int cdivid_(doublereal *, doublereal *, 
        doublereal *, doublereal *, doublereal *, doublereal *);

/* COMPUTES  THE DERIVATIVE  POLYNOMIAL AS THE INITIAL H */
/* POLYNOMIAL AND COMPUTES L1 NO-SHIFT H POLYNOMIALS. */
/* COMMON AREA */
    n = global_1.nn - 1;
    nm1 = n - 1;
    i__1 = n;
    for (i__ = 1; i__ <= i__1; ++i__) {
    xni = (doublereal) (global_1.nn - i__);
    global_1.hr[i__ - 1] = xni * global_1.pr[i__ - 1] / (real) n;
    global_1.hi[i__ - 1] = xni * global_1.pi[i__ - 1] / (real) n;
/* L10: */
    }
    i__1 = *l1;
    for (jj = 1; jj <= i__1; ++jj) {
    if (cmod_(&global_1.hr[n - 1], &global_1.hi[n - 1]) <= global_1.eta * 
        10. * cmod_(&global_1.pr[n - 1], &global_1.pi[n - 1])) {
        goto L30;
    }
    d__1 = -global_1.pr[global_1.nn - 1];
    d__2 = -global_1.pi[global_1.nn - 1];
    cdivid_(&d__1, &d__2, &global_1.hr[n - 1], &global_1.hi[n - 1], &
        global_1.tr, &global_1.ti);
    i__2 = nm1;
    for (i__ = 1; i__ <= i__2; ++i__) {
        j = global_1.nn - i__;
        t1 = global_1.hr[j - 2];
        t2 = global_1.hi[j - 2];
        global_1.hr[j - 1] = global_1.tr * t1 - global_1.ti * t2 + 
            global_1.pr[j - 1];
        global_1.hi[j - 1] = global_1.tr * t2 + global_1.ti * t1 + 
            global_1.pi[j - 1];
/* L20: */
    }
    global_1.hr[0] = global_1.pr[0];
    global_1.hi[0] = global_1.pi[0];
    goto L50;
/* IF THE CONSTANT TERM IS ESSENTIALLY ZERO, SHIFT H COEFFICIENTS. */
L30:
    i__2 = nm1;
    for (i__ = 1; i__ <= i__2; ++i__) {
        j = global_1.nn - i__;
        global_1.hr[j - 1] = global_1.hr[j - 2];
        global_1.hi[j - 1] = global_1.hi[j - 2];
/* L40: */
    }
    global_1.hr[0] = 0.;
    global_1.hi[0] = 0.;
L50:
    ;
    }
    return 0;
} /* noshft_ */

/* Subroutine */ int fxshft_(integer *l2, doublereal *zr, doublereal *zi, 
    logical *conv)
{
    /* System generated locals */
    integer i__1, i__2;
    doublereal d__1, d__2;

    /* Local variables */
    static integer i__, j, n;
    static doublereal oti, otr;
    extern doublereal cmod_(doublereal *, doublereal *);
    static logical pasd, bool, test;
    static doublereal svsi, svsr;
    extern /* Subroutine */ int calct_(logical *), nexth_(logical *), vrshft_(
        integer *, doublereal *, doublereal *, logical *), polyev_(
        integer *, doublereal *, doublereal *, doublereal *, doublereal *,
         doublereal *, doublereal *, doublereal *, doublereal *);

/* COMPUTES L2 FIXED-SHIFT H POLYNOMIALS AND TESTS FOR */
/* CONVERGENCE. */
/* INITIATES A VARIABLE-SHIFT ITERATION AND RETURNS WITH THE */
/* APPROXIMATE ZERO IF SUCCESSFUL. */
/* L2 - LIMIT OF FIXED SHIFT STEPS */
/* ZR,ZI - APPROXIMATE ZERO IF CONV IS .TRUE. */
/* CONV  - LOGICAL INDICATING CONVERGENCE OF STAGE 3 ITERATION */
/* COMMON AREA */
    n = global_1.nn - 1;
/* EVALUATE P AT S. */
    polyev_(&global_1.nn, &global_1.sr, &global_1.si, global_1.pr, 
        global_1.pi, global_1.qpr, global_1.qpi, &global_1.pvr, &
        global_1.pvi);
    test = TRUE_;
    pasd = FALSE_;
/* CALCULATE FIRST T = -P(S)/H(S). */
    calct_(&bool);
/* MAIN LOOP FOR ONE SECOND STAGE STEP. */
    i__1 = *l2;
    for (j = 1; j <= i__1; ++j) {
    otr = global_1.tr;
    oti = global_1.ti;
/* COMPUTE NEXT H POLYNOMIAL AND NEW T. */
    nexth_(&bool);
    calct_(&bool);
    *zr = global_1.sr + global_1.tr;
    *zi = global_1.si + global_1.ti;
/* TEST FOR CONVERGENCE UNLESS STAGE 3 HAS FAILED ONCE OR THIS */
/* IS THE LAST H POLYNOMIAL . */
    if (bool || ! test || j == *l2) {
        goto L50;
    }
    d__1 = global_1.tr - otr;
    d__2 = global_1.ti - oti;
    if (cmod_(&d__1, &d__2) >= cmod_(zr, zi) * .5) {
        goto L40;
    }
    if (! pasd) {
        goto L30;
    }
/* THE WEAK CONVERGENCE TEST HAS BEEN PASSED TWICE, START THE */
/* THIRD STAGE ITERATION, AFTER SAVING THE CURRENT H POLYNOMIAL */
/* AND SHIFT. */
    i__2 = n;
    for (i__ = 1; i__ <= i__2; ++i__) {
        global_1.shr[i__ - 1] = global_1.hr[i__ - 1];
        global_1.shi[i__ - 1] = global_1.hi[i__ - 1];
/* L10: */
    }
    svsr = global_1.sr;
    svsi = global_1.si;
    vrshft_(&c__10, zr, zi, conv);
    if (*conv) {
        return 0;
    }
/* THE ITERATION FAILED TO CONVERGE. TURN OFF TESTING AND RESTORE */
/* H,S,PV AND T. */
    test = FALSE_;
    i__2 = n;
    for (i__ = 1; i__ <= i__2; ++i__) {
        global_1.hr[i__ - 1] = global_1.shr[i__ - 1];
        global_1.hi[i__ - 1] = global_1.shi[i__ - 1];
/* L20: */
    }
    global_1.sr = svsr;
    global_1.si = svsi;
    polyev_(&global_1.nn, &global_1.sr, &global_1.si, global_1.pr, 
        global_1.pi, global_1.qpr, global_1.qpi, &global_1.pvr, &
        global_1.pvi);
    calct_(&bool);
    goto L50;
L30:
    pasd = TRUE_;
    goto L50;
L40:
    pasd = FALSE_;
L50:
    ;
    }
/* ATTEMPT AN ITERATION WITH FINAL H POLYNOMIAL FROM SECOND STAGE. */
    vrshft_(&c__10, zr, zi, conv);
    return 0;
} /* fxshft_ */

/* Subroutine */ int vrshft_(integer *l3, doublereal *zr, doublereal *zi, 
    logical *conv)
{
    /* System generated locals */
    integer i__1;

    /* Builtin functions */
    double sqrt(doublereal);

    /* Local variables */
    static logical b;
    static integer i__, j;
    static doublereal r1, r2, mp, ms, tp, omp;
    extern doublereal cmod_(doublereal *, doublereal *);
    static logical bool;
    extern /* Subroutine */ int calct_(logical *);
    extern doublereal errev_(integer *, doublereal *, doublereal *, 
        doublereal *, doublereal *, doublereal *, doublereal *);
    extern /* Subroutine */ int nexth_(logical *);
    static doublereal relstp;
    extern /* Subroutine */ int polyev_(integer *, doublereal *, doublereal *,
         doublereal *, doublereal *, doublereal *, doublereal *, 
        doublereal *, doublereal *);

/* CARRIES OUT THE THIRD STAGE ITERATION. */
/* L3 - LIMIT OF STEPS IN STAGE 3. */
/* ZR,ZI   - ON ENTRY CONTAINS THE INITIAL ITERATE, IF THE */
/* ITERATION CONVERGES IT CONTAINS THE FINAL ITERATE */
/* ON EXIT. */
/* CONV    -  .TRUE. IF ITERATION CONVERGES */
/* COMMON AREA */
    *conv = FALSE_;
    b = FALSE_;
    global_1.sr = *zr;
    global_1.si = *zi;
/* MAIN LOOP FOR STAGE THREE */
    i__1 = *l3;
    for (i__ = 1; i__ <= i__1; ++i__) {
/* EVALUATE P AT S AND TEST FOR CONVERGENCE. */
    polyev_(&global_1.nn, &global_1.sr, &global_1.si, global_1.pr, 
        global_1.pi, global_1.qpr, global_1.qpi, &global_1.pvr, &
        global_1.pvi);
    mp = cmod_(&global_1.pvr, &global_1.pvi);
    ms = cmod_(&global_1.sr, &global_1.si);
    if (mp > errev_(&global_1.nn, global_1.qpr, global_1.qpi, &ms, &mp, &
        global_1.are, &global_1.mre) * 20.) {
        goto L10;
    }
/* POLYNOMIAL VALUE IS SMALLER IN VALUE THAN A BOUND ON THE ERROR */
/* IN EVALUATING P, TERMINATE THE ITERATION. */
    *conv = TRUE_;
    *zr = global_1.sr;
    *zi = global_1.si;
    return 0;
L10:
    if (i__ == 1) {
        goto L40;
    }
    if (b || mp < omp || relstp >= .05) {
        goto L30;
    }
/* ITERATION HAS STALLED. PROBABLY A CLUSTER OF ZEROS. DO 5 FIXED */
/* SHIFT STEPS INTO THE CLUSTER TO FORCE ONE ZERO TO DOMINATE. */
    tp = relstp;
    b = TRUE_;
    if (relstp < global_1.eta) {
        tp = global_1.eta;
    }
    r1 = sqrt(tp);
    r2 = global_1.sr * (r1 + 1.) - global_1.si * r1;
    global_1.si = global_1.sr * r1 + global_1.si * (r1 + 1.);
    global_1.sr = r2;
    polyev_(&global_1.nn, &global_1.sr, &global_1.si, global_1.pr, 
        global_1.pi, global_1.qpr, global_1.qpi, &global_1.pvr, &
        global_1.pvi);
    for (j = 1; j <= 5; ++j) {
        calct_(&bool);
        nexth_(&bool);
/* L20: */
    }
    omp = global_1.infin;
    goto L50;
/* EXIT IF POLYNOMIAL VALUE INCREASES SIGNIFICANTLY. */
L30:
    if (mp * .1 > omp) {
        return 0;
    }
L40:
    omp = mp;
/* CALCULATE NEXT ITERATE. */
L50:
    calct_(&bool);
    nexth_(&bool);
    calct_(&bool);
    if (bool) {
        goto L60;
    }
    relstp = cmod_(&global_1.tr, &global_1.ti) / cmod_(&global_1.sr, &
        global_1.si);
    global_1.sr += global_1.tr;
    global_1.si += global_1.ti;
L60:
    ;
    }
    return 0;
} /* vrshft_ */

/* Subroutine */ int calct_(logical *bool)
{
    /* System generated locals */
    doublereal d__1, d__2;

    /* Local variables */
    static integer n;
    static doublereal hvi, hvr;
    extern doublereal cmod_(doublereal *, doublereal *);
    extern /* Subroutine */ int cdivid_(doublereal *, doublereal *, 
        doublereal *, doublereal *, doublereal *, doublereal *), polyev_(
        integer *, doublereal *, doublereal *, doublereal *, doublereal *,
         doublereal *, doublereal *, doublereal *, doublereal *);

/* COMPUTES  T = -P(S)/H(S). */
/* BOOL   - LOGICAL, SET TRUE IF H(S) IS ESSENTIALLY ZERO. */
/* COMMON AREA */
    n = global_1.nn - 1;
/* EVALUATE H(S). */
    polyev_(&n, &global_1.sr, &global_1.si, global_1.hr, global_1.hi, 
        global_1.qhr, global_1.qhi, &hvr, &hvi);
    *bool = cmod_(&hvr, &hvi) <= global_1.are * 10. * cmod_(&global_1.hr[n - 
        1], &global_1.hi[n - 1]);
    if (*bool) {
    goto L10;
    }
    d__1 = -global_1.pvr;
    d__2 = -global_1.pvi;
    cdivid_(&d__1, &d__2, &hvr, &hvi, &global_1.tr, &global_1.ti);
    return 0;
L10:
    global_1.tr = 0.;
    global_1.ti = 0.;
    return 0;
} /* calct_ */

/* Subroutine */ int nexth_(logical *bool)
{
    /* System generated locals */
    integer i__1;

    /* Local variables */
    static integer j, n;
    static doublereal t1, t2;
    static integer nm1;

/* CALCULATES THE NEXT SHIFTED H POLYNOMIAL. */
/* BOOL   -  LOGICAL, IF .TRUE. H(S) IS ESSENTIALLY ZERO */
/* COMMON AREA */
    n = global_1.nn - 1;
    nm1 = n - 1;
    if (*bool) {
    goto L20;
    }
    i__1 = n;
    for (j = 2; j <= i__1; ++j) {
    t1 = global_1.qhr[j - 2];
    t2 = global_1.qhi[j - 2];
    global_1.hr[j - 1] = global_1.tr * t1 - global_1.ti * t2 + 
        global_1.qpr[j - 1];
    global_1.hi[j - 1] = global_1.tr * t2 + global_1.ti * t1 + 
        global_1.qpi[j - 1];
/* L10: */
    }
    global_1.hr[0] = global_1.qpr[0];
    global_1.hi[0] = global_1.qpi[0];
    return 0;
/* IF H(S) IS ZERO REPLACE H WITH QH. */
L20:
    i__1 = n;
    for (j = 2; j <= i__1; ++j) {
    global_1.hr[j - 1] = global_1.qhr[j - 2];
    global_1.hi[j - 1] = global_1.qhi[j - 2];
/* L30: */
    }
    global_1.hr[0] = 0.;
    global_1.hi[0] = 0.;
    return 0;
} /* nexth_ */

/* Subroutine */ int polyev_(integer *nn, doublereal *sr, doublereal *si, 
    doublereal *pr, doublereal *pi, doublereal *qr, doublereal *qi, 
    doublereal *pvr, doublereal *pvi)
{
    /* System generated locals */
    integer i__1;

    /* Local variables */
    static integer i__;
    static doublereal t;

/* EVALUATES A POLYNOMIAL  P  AT  S  BY THE HORNER RECURRENCE */
/* PLACING THE PARTIAL SUMS IN Q AND THE COMPUTED VALUE IN PV. */
    /* Parameter adjustments */
    --qi;
    --qr;
    --pi;
    --pr;

    /* Function Body */
    qr[1] = pr[1];
    qi[1] = pi[1];
    *pvr = qr[1];
    *pvi = qi[1];
    i__1 = *nn;
    for (i__ = 2; i__ <= i__1; ++i__) {
    t = *pvr * *sr - *pvi * *si + pr[i__];
    *pvi = *pvr * *si + *pvi * *sr + pi[i__];
    *pvr = t;
    qr[i__] = *pvr;
    qi[i__] = *pvi;
/* L10: */
    }
    return 0;
} /* polyev_ */

doublereal errev_(integer *nn, doublereal *qr, doublereal *qi, doublereal *ms,
     doublereal *mp, doublereal *are, doublereal *mre)
{
    /* System generated locals */
    integer i__1;
    doublereal ret_val;

    /* Local variables */
    static doublereal e;
    static integer i__;
    extern doublereal cmod_(doublereal *, doublereal *);

/* BOUNDS THE ERROR IN EVALUATING THE POLYNOMIAL BY THE HORNER */
/* RECURRENCE. */
/* QR,QI - THE PARTIAL SUMS */
/* MS    -MODULUS OF THE POINT */
/* MP    -MODULUS OF POLYNOMIAL VALUE */
/* ARE, MRE -ERROR BOUNDS ON COMPLEX ADDITION AND MULTIPLICATION */
    /* Parameter adjustments */
    --qi;
    --qr;

    /* Function Body */
    e = cmod_(&qr[1], &qi[1]) * *mre / (*are + *mre);
    i__1 = *nn;
    for (i__ = 1; i__ <= i__1; ++i__) {
    e = e * *ms + cmod_(&qr[i__], &qi[i__]);
/* L10: */
    }
    ret_val = e * (*are + *mre) - *mp * *mre;
    return ret_val;
} /* errev_ */

doublereal cauchy_(integer *nn, doublereal *pt, doublereal *q)
{
    /* System generated locals */
    integer i__1;
    doublereal ret_val, d__1;

    /* Builtin functions */
    double log(doublereal), exp(doublereal);

    /* Local variables */
    static doublereal f;
    static integer i__, n;
    static doublereal x, df, dx, xm;

/* CAUCHY COMPUTES A LOWER BOUND ON THE MODULI OF THE ZEROS OF A */
/* POLYNOMIAL - PT IS THE MODULUS OF THE COEFFICIENTS. */
    /* Parameter adjustments */
    --q;
    --pt;

    /* Function Body */
    pt[*nn] = -pt[*nn];
/* COMPUTE UPPER ESTIMATE OF BOUND. */
    n = *nn - 1;
    x = exp((log(-pt[*nn]) - log(pt[1])) / (real) n);
    if (pt[n] == 0.) {
    goto L20;
    }
/* IF NEWTON STEP AT THE ORIGIN IS BETTER, USE IT. */
    xm = -pt[*nn] / pt[n];
    if (xm < x) {
    x = xm;
    }
/* CHOP THE INTERVAL (0,X) UNITL F LE 0. */
L20:
    xm = x * .1;
    f = pt[1];
    i__1 = *nn;
    for (i__ = 2; i__ <= i__1; ++i__) {
    f = f * xm + pt[i__];
/* L30: */
    }
    if (f <= 0.) {
    goto L40;
    }
    x = xm;
    goto L20;
L40:
    dx = x;
/* DO NEWTON ITERATION UNTIL X CONVERGES TO TWO DECIMAL PLACES. */
L50:
    if ((d__1 = dx / x, abs(d__1)) <= .005) {
    goto L70;
    }
    q[1] = pt[1];
    i__1 = *nn;
    for (i__ = 2; i__ <= i__1; ++i__) {
    q[i__] = q[i__ - 1] * x + pt[i__];
/* L60: */
    }
    f = q[*nn];
    df = q[1];
    i__1 = n;
    for (i__ = 2; i__ <= i__1; ++i__) {
    df = df * x + q[i__];
/* L65: */
    }
    dx = f / df;
    x -= dx;
    goto L50;
L70:
    ret_val = x;
    return ret_val;
} /* cauchy_ */

doublereal scale_(integer *nn, doublereal *pt, doublereal *eta, doublereal *
    infin, doublereal *smalno, doublereal *base)
{
    /* System generated locals */
    integer i__1;
    doublereal ret_val;

    /* Builtin functions */
    double sqrt(doublereal), log(doublereal), pow_di(doublereal *, integer *);

    /* Local variables */
    static integer i__, l;
    static doublereal x, hi, sc, lo, min__, max__;

/* RETURNS A SCALE FACTOR TO MULTIPLY THE COEFFICIENTS OF THE */
/* POLYNOMIAL. THE SCALING IS DONE TO AVOID OVERFLOW AND TO AVOID */
/* UNDETECTED UNDERFLOW INTERFERING WITH THE CONVERGENCE */
/* CRITERION.  THE FACTOR IS A POWER OF THE BASE. */
/* PT - MODULUS OF COEFFICIENTS OF P */
/* ETA,INFIN,SMALNO,BASE - CONSTANTS DESCRIBING THE */
/* FLOATING POINT ARITHMETIC. */
/* FIND LARGEST AND SMALLEST MODULI OF COEFFICIENTS. */
    /* Parameter adjustments */
    --pt;

    /* Function Body */
    hi = sqrt(*infin);
    lo = *smalno / *eta;
    max__ = 0.;
    min__ = *infin;
    i__1 = *nn;
    for (i__ = 1; i__ <= i__1; ++i__) {
    x = pt[i__];
    if (x > max__) {
        max__ = x;
    }
    if (x != 0. && x < min__) {
        min__ = x;
    }
/* L10: */
    }
/* SCALE ONLY IF THERE ARE VERY LARGE OR VERY SMALL COMPONENTS. */
    ret_val = 1.;
    if (min__ >= lo && max__ <= hi) {
    return ret_val;
    }
    x = lo / min__;
    if (x > 1.) {
    goto L20;
    }
    sc = 1. / (sqrt(max__) * sqrt(min__));
    goto L30;
L20:
    sc = x;
    if (*infin / sc > max__) {
    sc = 1.;
    }
L30:
    l = (integer) (log(sc) / log(*base) + .5f);
    ret_val = pow_di(base, &l);
    return ret_val;
} /* scale_ */

/* Subroutine */ int cdivid_(doublereal *ar, doublereal *ai, doublereal *br, 
    doublereal *bi, doublereal *cr, doublereal *ci)
{
    static doublereal d__, r__, t;
    extern /* Subroutine */ int mcon_(doublereal *, doublereal *, doublereal *
        , doublereal *);
    static doublereal infin;

/* COMPLEX DIVISION C = A/B, AVOIDING OVERFLOW. */
    if (*br != 0. || *bi != 0.) {
    goto L10;
    }
/* DIVISION BY ZERO, C = INFINITY. */
    mcon_(&t, &infin, &t, &t);
    *cr = infin;
    *ci = infin;
    return 0;
L10:
    if (abs(*br) >= abs(*bi)) {
    goto L20;
    }
    r__ = *br / *bi;
    d__ = *bi + r__ * *br;
    *cr = (*ar * r__ + *ai) / d__;
    *ci = (*ai * r__ - *ar) / d__;
    return 0;
L20:
    r__ = *bi / *br;
    d__ = *br + r__ * *bi;
    *cr = (*ar + *ai * r__) / d__;
    *ci = (*ai - *ar * r__) / d__;
    return 0;
} /* cdivid_ */

doublereal cmod_(doublereal *r__, doublereal *i__)
{
    /* System generated locals */
    doublereal ret_val, d__1;

    /* Builtin functions */
    double sqrt(doublereal);

    /* Local variables */
    static doublereal ai, ar;

/* MODULUS OF A COMPLEX NUMBER AVOIDING OVERFLOW. */
    ar = abs(*r__);
    ai = abs(*i__);
    if (ar >= ai) {
    goto L10;
    }
/* Computing 2nd power */
    d__1 = ar / ai;
    ret_val = ai * sqrt(d__1 * d__1 + 1.);
    return ret_val;
L10:
    if (ar <= ai) {
    goto L20;
    }
/* Computing 2nd power */
    d__1 = ai / ar;
    ret_val = ar * sqrt(d__1 * d__1 + 1.);
    return ret_val;
L20:
    ret_val = ar * sqrt(2.);
    return ret_val;
} /* cmod_ */

/* Subroutine */ int mcon_(doublereal *eta, doublereal *infiny, doublereal *
    smalno, doublereal *base)
{
    /* System generated locals */
    integer i__1, i__2;
    doublereal d__1;

    /* Builtin functions */
    double pow_di(doublereal *, integer *);

    /* Local variables */
    static integer m, n, t;

/* MCON PROVIDES MACHINE CONSTANTS USED IN VARIOUS PARTS OF THE */
/* PROGRAM. THE USER MAY EITHER SET THEM DIRECTLY OR USE THE */
/* STATEMENTS BELOW TO COMPUTE THEM. THE MEANING OF THE FOUR */
/* CONSTANTS ARE - */
/* ETA       THE MAXIMUM RELATIVE REPRESENTATION ERROR */
/* WHICH CAN BE DESCRIBED AS THE SMALLEST POSITIVE */
/* FLOATING-POINT NUMBER SUCH THAT 1.0D0 + ETA IS */
/* GREATER THAN 1.0D0. */
/* INFINY    THE LARGEST FLOATING-POINT NUMBER */
/* SMALNO    THE SMALLEST POSITIVE FLOATING-POINT NUMBER */
/* BASE      THE BASE OF THE FLOATING-POINT NUMBER SYSTEM USED */
/* LET T BE THE NUMBER OF BASE-DIGITS IN EACH FLOATING-POINT */
/* NUMBER(DOUBLE PRECISION). THEN ETA IS EITHER .5*B**(1-T) */
/* OR B**(1-T) DEPENDING ON WHETHER ROUNDING OR TRUNCATION */
/* IS USED. */
/* LET M BE THE LARGEST EXPONENT AND N THE SMALLEST EXPONENT */
/* IN THE NUMBER SYSTEM. THEN INFINY IS (1-BASE**(-T))*BASE**M */
/* AND SMALNO IS BASE**N. */
/* THE VALUES FOR BASE,T,M,N BELOW CORRESPOND TO THE IBM/360. */
    *base = 16.;
    t = 14;
    m = 63;
    n = -65;
    i__1 = 1 - t;
    *eta = pow_di(base, &i__1);
    i__1 = -t;
    i__2 = m - 1;
    *infiny = *base * (1. - pow_di(base, &i__1)) * pow_di(base, &i__2);
    i__1 = n + 3;
/* Computing 3rd power */
    d__1 = *base;
    *smalno = pow_di(base, &i__1) / (d__1 * (d__1 * d__1));
    return 0;
} /* mcon_ */

/*
int main(){
  doublereal opr[11] = {1, -55, 1320, -18150, 157773, -902055, 3416930, -8409500, 12753576, -10628640, 3628800};
  doublereal opi[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  integer degree = 10;
  doublereal zr[11]; 
  doublereal zi[11];
  logical fail;
  cpoly_(opr, opi, &degree, zr, zi, &fail);
}
*/

下面是测试代码

#include<stdio.h>
#include "f2c.h"

extern int cpoly_(doublereal *opr, doublereal *opi, integer *degree, doublereal *zeror, doublereal *zeroi, logical *fail);

int main(){
  doublereal opr[11] = {1, -55, 1320, -18150, 157773, -902055, 3416930, -8409500, 12753576, -10628640, 3628800};
  doublereal opi[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  integer degree = 10;
  doublereal zr[11];
  doublereal zi[11];
  logical fail;
  int res = cpoly_(opr, opi, &degree, zr, zi, &fail);
  printf("%d %d\n", res, fail);
  for(int i=0; i<11; i++){
    printf("%e %e\n", zr[i], zi[i]);
  }
}

编译和链接可以通过以下方式完成

gcc -c cpoly.c
gcc -c cpoly_test.c
gcc cpoly_test.o cpoly.o -lm -lf2c -o test

但是,需要安装f2c库。这是链接:

https://askubuntu.com/questions/1077151/how-to-run-a-csh-script-to-install-f2c

© www.soinside.com 2019 - 2024. All rights reserved.