コード例 #1
0
        /*  Computes the derivative polynomial as the initial
         *  polynomial and computes l1 no-shift h polynomials.	*/
        void noshft(int l1)
        {
            int    i, j, jj, n = nn - 1, nm1 = n - 1;
            double t1, t2, xni;

            for (i = 0; i < n; i++)
            {
                xni        = (double)(nn - i - 1);
                this.hr[i] = xni * this.pr[i] / n;
                this.hi[i] = xni * this.pi[i] / n;
            }

            for (jj = 1; jj <= l1; jj++)
            {
                if (RVaria.hypot(this.hr[n - 1], this.hi[n - 1]) <= eta * 10.0 * RVaria.hypot(this.pr[n - 1], this.pi[n - 1]))
                {
                    /*	If the constant term is essentially zero, */
                    /*	shift h coefficients. */
                    for (i = 1; i <= nm1; i++)
                    {
                        j = this.nn - i;
                        this.hr[j - 1] = this.hr[j - 2];
                        this.hi[j - 1] = this.hi[j - 2];
                    }

                    this.hr[0] = 0.0;
                    this.hi[0] = 0.0;
                }
                else
                {
                    cdivid(-pr[nn - 1], -pi[nn - 1], hr[n - 1], hi[n - 1], out tr, out ti);
                    for (i = 1; i <= nm1; i++)
                    {
                        j         = nn - i;
                        t1        = hr[j - 2];
                        t2        = hi[j - 2];
                        hr[j - 1] = tr * t1 - ti * t2 + pr[j - 1];
                        hi[j - 1] = tr * t2 + ti * t1 + pi[j - 1];
                    }
                    hr[0] = pr[0];
                    hi[0] = pi[0];
                }
            }
        }
コード例 #2
0
        void calct(out bool bool_)
        {
            /*
             * computes	 t = -p(s)/h(s).
             * bool   - logical, set true if h(s) is essentially zero.
             *
             */
            int    n = nn - 1;
            double hvi, hvr;

            /* evaluate h(s). */
            polyev(n, sr, si, hr, hi, qhr, qhi, out hvr, out hvi);
            bool_ = RVaria.hypot(hvr, hvi) <= are * 10.0 * RVaria.hypot(hr[n - 1], hi[n - 1]);
            if (!bool_)
            {
                cdivid(-pvr, -pvi, hvr, hvi, out tr, out ti);
            }
            else
            {
                tr = 0.0;
                ti = 0.0;
            }
        }
コード例 #3
0
        double errev(int n, double[] qr, double[] qi, double ms, double mp, double a_re, double m_re)
        {
            /*
             *	bounds the error in evaluating the polynomial by the horner
             *	recurrence.
             *
             *	qr,qi	 - the partial sum vectors
             *	ms	 - modulus of the point
             *	mp	 - modulus of polynomial value
             *  a_re,m_re - error bounds on complex addition and multiplication
             *
             */

            double e;
            int    i;

            e = RVaria.hypot(qr[0], qi[0]) * m_re / (a_re + m_re);
            for (i = 0; i < n; i++)
            {
                e = e * ms + RVaria.hypot(qr[i], qi[i]);
            }

            return(e * (a_re + m_re) - mp * m_re);
        }
コード例 #4
0
        /*
         * carries out the third stage iteration.
         *
         */
        bool vrshft(int l3, ref double zr, ref double zi)
        {
            /*  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.
             * Returns TRUE if iteration converges
             *
             * Assign and uses  GLOBAL sr, si
             */
            bool   bool_, b;
            int    i, j;
            double r1, r2, mp, ms, tp, relstp = 0.0;
            double omp = 0.0;

            b  = false;
            sr = zr;
            si = zi;

            /* main loop for stage three */
            for (i = 1; i <= l3; i++)
            {
                /* evaluate p at s and test for convergence. */
                polyev(nn, sr, si, pr, pi, qpr, qpi, out pvr, out pvi);
                mp = RVaria.hypot(pvr, pvi);
                ms = RVaria.hypot(sr, si);
                if (mp <= 20.0 * errev(nn, qpr, qpi, ms, mp, /*are=*/ eta, mre))
                {
                    goto L_conv;
                }

                /*
                 * polynomial value is smaller in value than
                 * a bound on the error in evaluating p,
                 * terminate the iteration.
                 *
                 */
                if (i != 1)
                {
                    if (!b && (mp >= omp) && (relstp < .05))
                    {
                        /*
                         * 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 < eta)
                        {
                            tp = eta;
                        }

                        r1 = Math.Sqrt(tp);
                        r2 = sr * (r1 + 1.0) - si * r1;
                        si = sr * r1 + si * (r1 + 1.0);
                        sr = r2;
                        polyev(nn, sr, si, pr, pi, qpr, qpi, out pvr, out pvi);
                        for (j = 1; j <= 5; ++j)
                        {
                            calct(out bool_);
                            nexth(bool_);
                        }
                        omp = infin;
                        goto L10;
                    }
                    else
                    {
                        /* exit if polynomial value */
                        /* increases significantly. */
                        if (mp * .1 > omp)
                        {
                            return(false);
                        }
                    }
                }

                omp = mp;

                /* calculate next iterate. */
L10:
                calct(out bool_);
                nexth(bool_);
                calct(out bool_);
                if (!bool_)
                {
                    relstp = RVaria.hypot(tr, ti) / RVaria.hypot(sr, si);
                    sr    += tr;
                    si    += ti;
                }
            }

            return(false);

L_conv:
            zr = sr;
            zi = si;
            return(true);
        }
コード例 #5
0
        /*
         *  Computes l2 fixed-shift h polynomials and tests for convergence.
         *  initiates a variable-shift iteration and returns with the
         *  approximate zero if successful.
         *
         */
        bool fxshft(int l2, ref double zr, ref double zi)
        {
            /*
             *  l2	  - limit of fixed shift steps
             *  zr,zi - approximate zero if convergence (result TRUE)
             *
             * Return value indicates convergence of stage 3 iteration
             *
             * Uses global (sr,si), nn, pr[], pi[], .. (all args of polyev() !)
             *
             */
            bool   pasd, bool_, test;
            double svsi, svsr;
            int    i, j, n;
            double oti, otr;

            n = nn - 1;

            /* evaluate p at s. */
            polyev(nn, sr, si, pr, pi, qpr, qpi, out pvr, out pvi);
            test = true;
            pasd = false;

            /* calculate first t = -p(s)/h(s). */
            calct(out bool_);

            /* main loop for one second stage step. */
            for (j = 1; j <= l2; j++)
            {
                otr = tr;
                oti = ti;

                /* compute next h polynomial and new t. */
                nexth(bool_);
                calct(out bool_);
                zr = sr + tr;
                zi = si + ti;

                /* test for convergence unless stage 3 has */
                /* failed once or this is the last h polynomial. */
                if (!bool_ && test && (j != l2))
                {
                    if (RVaria.hypot(tr - otr, ti - oti) >= RVaria.hypot(zr, zi) * 0.5)
                    {
                        pasd = false;
                    }
                    else if (!pasd)
                    {
                        pasd = true;
                    }
                    else
                    {
                        /* the weak convergence test has been */
                        /* passed twice, start the third stage */
                        /* iteration, after saving the current */
                        /* h polynomial and shift. */
                        for (i = 0; i < n; i++)
                        {
                            shr[i] = hr[i];
                            shi[i] = hi[i];
                        }
                        svsr = sr;
                        svsi = si;
                        if (vrshft(10, ref zr, ref zi))
                        {
                            return(true);
                        }

                        /* the iteration failed to converge. */
                        /* turn off testing and restore */
                        /* h, s, pv and t. */

                        test = false;
                        for (i = 1; i <= n; i++)
                        {
                            hr[i - 1] = shr[i - 1];
                            hi[i - 1] = shi[i - 1];
                        }

                        sr = svsr;
                        si = svsi;
                        polyev(nn, sr, si, pr, pi, qpr, qpi, out pvr, out pvi);
                        calct(out bool_);
                    }
                }
            }

            /* attempt an iteration with final h polynomial */
            /* from second stage. */
            return(vrshft(10, ref zr, ref zi));
        }
コード例 #6
0
        private void R_cpolyroot(double[] opr, double[] opi, int degree, double[] zeror, double[] zeroi, out bool fail)
        {
            const double smalno = RVaria.DBL_MIN;
            const double base_  = (double)RVaria.FLT_RADIX;

            // R_cpolyroot variables ...
            int    d_n, i, i1, i2;
            double zr = 0, zi = 0, xx, yy;
            double bnd, xxx;

            bool         conv;
            int          d1;
            const double cosr = /* cos 94 */ -0.06975647374412529990;
            const double sinr = /* sin 94 */ 0.99756405025982424767;

            xx   = RVaria.M_SQRT1_2;/* 1/Math.Sqrt(2) = 0.707.... */
            yy   = -xx;
            fail = false;
            nn   = degree;
            d1   = nn - 1;

            /* algorithm fails if the leading coefficient is zero. */

            if ((opr[0] == 0) && (opi[0] == 0))
            {
                fail = true;
                return;
            }

            /* remove the zeros at the origin if any. */

            while ((opr[nn] == 0.0) && (opi[nn] == 0.0))
            {
                d_n        = d1 - nn + 1;
                zeror[d_n] = 0.0;
                zeroi[d_n] = 0.0;
                nn--;
            }

            nn++;
            /*-- Now, global var.  nn := #{coefficients} = (relevant degree)+1 */

            if (nn == 1)
            {
                return;
            }

            /* Use a single allocation as these as small */
            //const void* vmax = vmaxget();
            //tmp = new double[nn];
            pr = new double[nn];
            pi = new double[nn];

            hr = new double[nn];
            hi = new double[nn];

            qpr = new double[nn];
            qpi = new double[nn];

            qhr = new double[nn];
            qhi = new double[nn];

            shr = new double[nn];
            shi = new double[nn];

            /* make a copy of the coefficients and shr[] = | p[] | */
            for (i = 0; i < nn; i++)
            {
                pr[i]  = opr[i];
                pi[i]  = opi[i];
                shr[i] = RVaria.hypot(pr[i], pi[i]);
            }

            /* scale the polynomial with factor 'bnd'. */
            bnd = cpoly_scale(nn, shr, eta, infin, smalno, base_);
            if (bnd != 1.0)
            {
                for (i = 0; i < nn; i++)
                {
                    pr[i] *= bnd;
                    pi[i] *= bnd;
                }
            }

            /* start the algorithm for one zero */

            while (nn > 2)
            {
                /* calculate bnd, a lower bound on the modulus of the zeros. */
                for (i = 0; i < nn; i++)
                {
                    shr[i] = RVaria.hypot(pr[i], pi[i]);
                }

                bnd = cpoly_cauchy(nn, shr, shi);

                /* outer loop to control 2 major passes */
                /* with different sequences of shifts */

                for (i1 = 1; i1 <= 2; i1++)
                {
                    /* first stage calculation, no shift */
                    noshft(5);

                    /*	inner loop to select a shift */
                    for (i2 = 1; i2 <= 9; i2++)
                    {
                        /* 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;
                        this.sr = bnd * xx;
                        this.si = bnd * yy;

                        /*  second stage calculation, fixed shift */
                        conv = fxshft(i2 * 10, ref zr, ref zi);
                        if (conv)
                        {
                            goto L10;
                        }
                    }
                }

                /* the zerofinder has failed on two major passes */
                /* return empty handed */
                fail = true;
                return;

                /* the second stage jumps directly to the third stage iteration.
                 * if successful, the zero is stored and the polynomial deflated.
                 */
L10:
                d_n        = d1 + 2 - nn;
                zeror[d_n] = zr;
                zeroi[d_n] = zi;
                --nn;

                for (i = 0; i < nn; i++)
                {
                    pr[i] = qpr[i];
                    pi[i] = qpi[i];
                }
            }/*while*/

            /*	calculate the final zero and return */
            cdivid(-pr[1], -pi[1], pr[0], pi[0], out zeror[d1], out zeroi[d1]);
            return;
        }