Esempio n. 1
0
        private static void CentralDeriv(PZMath_f f, double x, double h, out double result, out double abserr_round, out double abserr_trunc)
        {
            /* Compute the derivative using the 5-point rule (x-h, x-h/2, x,
            x+h/2, x+h). Note that the central point is not used.

            Compute the error using the difference between the 5-point and
            the 3-point rule (x-h,x,x+h). Again the central point is not
            used. */
            double fm1 = f.FN_EVAL(x - h);
            double fp1 = f.FN_EVAL(x + h);

            double fmh = f.FN_EVAL (x - h / 2);
            double fph = f.FN_EVAL (x + h / 2);

            double r3 = 0.5 * (fp1 - fm1);
            double r5 = (4.0 / 3.0) * (fph - fmh) - (1.0 / 3.0) * r3;

            double e3 = (System.Math.Abs(fp1) + System.Math.Abs(fm1)) * PZMath_machine.PZMath_DBL_EPSILON;
            double e5 = 2.0 * (System.Math.Abs(fph) + System.Math.Abs(fmh)) * PZMath_machine.PZMath_DBL_EPSILON + e3;

            double dy = System.Math.Max(System.Math.Abs(r3), System.Math.Abs(r5)) * System.Math.Abs(x) * PZMath_machine.PZMath_DBL_EPSILON;

            /* The truncation error in the r5 approximation itself is O(h^4).
            However, for safety, we estimate the error from r5-r3, which is
            O(h^2).  By scaling h we will minimise this estimated error, not
            the actual truncation error in r5. */

            result = r5 / h;
            abserr_trunc = System.Math.Abs((r5 - r3) / h); /* Estimated truncation error O(h^2) */
            abserr_round = System.Math.Abs(e5 / h) + dy;   /* Rounding error (cancellations) */
        }
Esempio n. 2
0
        static void QK(int n, double [] xgk, double [] wg, double [] wgk, 
            double [] fv1, double [] fv2,
            PZMath_f f, double a, double b,
            ref double result, ref double abserr, ref double resabs, ref double resasc)
        {
            double center = 0.5 * (a + b);
            double half_length = 0.5 * (b - a);
            double abs_half_length = System.Math.Abs (half_length);
            double f_center = f.FN_EVAL(center);

            double result_gauss = 0;
            double result_kronrod = f_center * wgk[n - 1];

            double result_abs = System.Math.Abs (result_kronrod);
            double result_asc = 0;
            double mean = 0, err = 0;

            int j;

            if (n % 2 == 0)
                result_gauss = f_center * wg[n / 2 - 1];

            for (j = 0; j < (n - 1) / 2; j++)
            {
                int jtw = j * 2 + 1;        /* j=1,2,3 jtw=2,4,6 */
                double abscissa = half_length * xgk[jtw];
                double fval1 = f.FN_EVAL (center - abscissa);
                double fval2 = f.FN_EVAL (center + abscissa);
                double fsum = fval1 + fval2;
                fv1[jtw] = fval1;
                fv2[jtw] = fval2;
                result_gauss += wg[j] * fsum;
                result_kronrod += wgk[jtw] * fsum;
                result_abs += wgk[jtw] * (System.Math.Abs (fval1) + System.Math.Abs (fval2));
            }

            for (j = 0; j < n / 2; j++)
            {
                int jtwm1 = j * 2;
                double abscissa = half_length * xgk[jtwm1];
                double fval1 = f.FN_EVAL (center - abscissa);
                double fval2 = f.FN_EVAL (center + abscissa);
                fv1[jtwm1] = fval1;
                fv2[jtwm1] = fval2;
                result_kronrod += wgk[jtwm1] * (fval1 + fval2);
                result_abs += wgk[jtwm1] * (System.Math.Abs (fval1) + System.Math.Abs (fval2));
            }

            mean = result_kronrod * 0.5;

            result_asc = wgk[n - 1] * System.Math.Abs (f_center - mean);

            for (j = 0; j < n - 1; j++)
                result_asc += wgk[j] * (System.Math.Abs (fv1[j] - mean) + System.Math.Abs (fv2[j] - mean));

            /* scale by the width of the integration region */

            err = (result_kronrod - result_gauss) * half_length;

            result_kronrod *= half_length;
            result_abs *= abs_half_length;
            result_asc *= abs_half_length;

            result = result_kronrod;
            resabs = result_abs;
            resasc = result_asc;
            abserr = RescaleError (err, result_abs, result_asc);
        }