コード例 #1
0
        /// <summary>
        /// Adaptive integration on semi-infinite interval (a,+Infinity).
        /// </summary>
        /// <param name="f">Function to integrate.</param>
        /// <param name="a">Lower integration limit.</param>
        /// <param name="epsabs">Specifies the expected absolute error of integration. Should be set to zero (0) if you specify a relative error.</param>
        /// <param name="epsrel">Specifies the expected relative error of integration. Should be set to zero (0) if you specify an absolute error.</param>
        /// <param name="limit">Maximum number of subintervals used for integration.</param>
        /// <param name="integrationRule">Integration rule used for integration (only for this function call).</param>
        /// <param name="debug">Setting of the debug flag (only for this function call). If the integration fails or the specified accuracy
        /// is not reached, an exception is thrown if the debug flag is set to true. If set to false, the return value of the integration
        /// function will be set to the appropriate error code (an exception will be thrown then only for serious errors).</param>
        /// <param name="result">On return, contains the integration result.</param>
        /// <param name="abserr">On return, contains the absolute error of integration.</param>
        /// <param name="tempStorage">Provides a temporary storage object that you can reuse for repeating function calls.</param>
        /// <returns>Null if successfull, otherwise the appropriate error code.</returns>
        public static GSL_ERROR Integration(Func <double, double> f,
                                            double a,
                                            double epsabs, double epsrel,
                                            int limit,
                                            gsl_integration_rule integrationRule, bool debug,
                                            out double result, out double abserr,
                                            ref object tempStorage)
        {
            var algo = tempStorage as QagiuIntegration;

            if (null == algo)
            {
                tempStorage = algo = new QagiuIntegration(integrationRule, debug);
            }
            return(algo.Integrate(f, a, epsabs, epsrel, limit, integrationRule, debug, out result, out abserr));
        }
コード例 #2
0
        Integration(Func <double, double> f,
                    double a,
                    double epsabs, double epsrel,
                    int limit,
                    out double result, out double abserr,
                    ref object tempStorage
                    )
        {
            var algo = tempStorage as QagiuIntegration;

            if (null == algo)
            {
                tempStorage = algo = new QagiuIntegration();
            }
            return(algo.Integrate(f, a, epsabs, epsrel, limit, out result, out abserr));
        }
コード例 #3
0
ファイル: QagiuIntegration.cs プロジェクト: Altaxo/Altaxo
		Integration(Func<double, double> f,
					double a,
					double epsabs, double epsrel,
					int limit,
					out double result, out double abserr,
					ref object tempStorage
					)
		{
			QagiuIntegration algo = tempStorage as QagiuIntegration;
			if (null == algo)
				tempStorage = algo = new QagiuIntegration();
			return algo.Integrate(f, a, epsabs, epsrel, limit, out result, out abserr);
		}
コード例 #4
0
ファイル: QagiuIntegration.cs プロジェクト: Altaxo/Altaxo
		/// <summary>
		/// Adaptive integration on semi-infinite interval (a,+Infinity).
		/// </summary>
		/// <param name="f">Function to integrate.</param>
		/// <param name="a">Lower integration limit.</param>
		/// <param name="epsabs">Specifies the expected absolute error of integration. Should be set to zero (0) if you specify a relative error.</param>
		/// <param name="epsrel">Specifies the expected relative error of integration. Should be set to zero (0) if you specify an absolute error.</param>
		/// <param name="limit">Maximum number of subintervals used for integration.</param>
		/// <param name="integrationRule">Integration rule used for integration (only for this function call).</param>
		/// <param name="debug">Setting of the debug flag (only for this function call). If the integration fails or the specified accuracy
		/// is not reached, an exception is thrown if the debug flag is set to true. If set to false, the return value of the integration
		/// function will be set to the appropriate error code (an exception will be thrown then only for serious errors).</param>
		/// <param name="result">On return, contains the integration result.</param>
		/// <param name="abserr">On return, contains the absolute error of integration.</param>
		/// <param name="tempStorage">Provides a temporary storage object that you can reuse for repeating function calls.</param>
		/// <returns>Null if successfull, otherwise the appropriate error code.</returns>
		public static GSL_ERROR Integration(Func<double, double> f,
					double a,
					double epsabs, double epsrel,
					int limit,
					gsl_integration_rule integrationRule, bool debug,
					out double result, out double abserr,
					ref object tempStorage)
		{
			QagiuIntegration algo = tempStorage as QagiuIntegration;
			if (null == algo)
				tempStorage = algo = new QagiuIntegration(integrationRule, debug);
			return algo.Integrate(f, a, epsabs, epsrel, limit, integrationRule, debug, out result, out abserr);
		}
コード例 #5
0
        gsl_integration_qawf(Func <double, double> f,
                             double a,
                             double epsabs,
                             int limit,
                             gsl_integration_workspace workspace,
                             gsl_integration_workspace cycle_workspace,
                             gsl_integration_qawo_table wf,
                             out double result, out double abserr,
                             bool bDebug)
        {
            double area, errsum;
            double res_ext, err_ext;
            double correc, total_error = 0.0, truncation_error = 0;

            int ktmin     = 0;
            int iteration = 0;

            var table = new extrapolation_table();

            double cycle;
            double omega = wf.omega;

            double p = 0.9;
            double factor = 1;
            double initial_eps, eps;
            int    error_type = 0;

            /* Initialize results */

            workspace.initialise(a, a);

            result = 0;
            abserr = 0;

            if (limit > workspace.limit)
            {
                return(new GSL_ERROR("iteration limit exceeds available workspace", GSL_ERR.GSL_EINVAL, bDebug));
            }

            /* Test on accuracy */

            if (epsabs <= 0)
            {
                return(new GSL_ERROR("absolute tolerance epsabs must be positive", GSL_ERR.GSL_EBADTOL, bDebug));
            }

            if (omega == 0.0)
            {
                if (wf.sine == gsl_integration_qawo_enum.GSL_INTEG_SINE)
                {
                    /* The function sin(w x) f(x) is always zero for w = 0 */

                    result = 0;
                    abserr = 0;

                    return(null); // GSL_SUCCESS;
                }
                else
                {
                    /* The function cos(w x) f(x) is always f(x) for w = 0 */

                    GSL_ERROR status = QagiuIntegration.gsl_integration_qagiu(f, a, epsabs, 0.0,
                                                                              cycle_workspace.limit,
                                                                              cycle_workspace,
                                                                              out result, out abserr,
                                                                              QagiuIntegration.DefaultIntegrationRule, QagiuIntegration.DefaultDebugFlag);
                    return(status);
                }
            }

            if (epsabs > GSL_CONST.GSL_DBL_MIN / (1 - p))
            {
                eps = epsabs * (1 - p);
            }
            else
            {
                eps = epsabs;
            }

            initial_eps = eps;

            area   = 0;
            errsum = 0;

            res_ext = 0;
            err_ext = GSL_CONST.GSL_DBL_MAX;
            correc  = 0;

            cycle = (2 * Math.Floor(Math.Abs(omega)) + 1) * Math.PI / Math.Abs(omega);

            wf.set_length(cycle);

            table.initialise_table();

            for (iteration = 0; iteration < limit; iteration++)
            {
                double a1 = a + iteration * cycle;
                double b1 = a1 + cycle;

                double epsabs1 = eps * factor;

                GSL_ERROR status = gsl_integration_qawo(f, a1, epsabs1, 0.0, limit,
                                                        cycle_workspace, wf,
                                                        out var area1, out var error1, false);

                workspace.append_interval(a1, b1, area1, error1);

                factor *= p;

                area   = area + area1;
                errsum = errsum + error1;

                /* estimate the truncation error as 50 times the final term */

                truncation_error = 50 * Math.Abs(area1);

                total_error = errsum + truncation_error;

                if (total_error < epsabs && iteration > 4)
                {
                    goto compute_result;
                }

                if (error1 > correc)
                {
                    correc = error1;
                }

                if (null != status)
                {
                    eps = Math.Max(initial_eps, correc * (1.0 - p));
                }

                if (null != status && total_error < 10 * correc && iteration > 3)
                {
                    goto compute_result;
                }

                table.append_table(area);

                if (table.n < 2)
                {
                    continue;
                }

                table.qelg(out var reseps, out var erreps);

                ktmin++;

                if (ktmin >= 15 && err_ext < 0.001 * total_error)
                {
                    error_type = 4;
                }

                if (erreps < err_ext)
                {
                    ktmin   = 0;
                    err_ext = erreps;
                    res_ext = reseps;

                    if (err_ext + 10 * correc <= epsabs)
                    {
                        break;
                    }
                    if (err_ext <= epsabs && 10 * correc >= epsabs)
                    {
                        break;
                    }
                }
            }

            if (iteration == limit)
            {
                error_type = 1;
            }

            if (err_ext == GSL_CONST.GSL_DBL_MAX)
            {
                goto compute_result;
            }

            err_ext = err_ext + 10 * correc;

            result = res_ext;
            abserr = err_ext;

            if (error_type == 0)
            {
                return(null); // GSL_SUCCESS;
            }

            if (res_ext != 0.0 && area != 0.0)
            {
                if (err_ext / Math.Abs(res_ext) > errsum / Math.Abs(area))
                {
                    goto compute_result;
                }
            }
            else if (err_ext > errsum)
            {
                goto compute_result;
            }
            else if (area == 0.0)
            {
                goto return_error;
            }

            if (error_type == 4)
            {
                err_ext = err_ext + truncation_error;
            }

            goto return_error;

compute_result:

            result = area;
            abserr = total_error;

return_error:

            if (error_type > 2)
            {
                error_type--;
            }

            if (error_type == 0)
            {
                return(null); // GSL_SUCCESS;
            }
            else if (error_type == 1)
            {
                return(new GSL_ERROR("number of iterations was insufficient", GSL_ERR.GSL_EMAXITER, bDebug));
            }
            else if (error_type == 2)
            {
                return(new GSL_ERROR("cannot reach tolerance because of roundoff error",
                                     GSL_ERR.GSL_EROUND, bDebug));
            }
            else if (error_type == 3)
            {
                return(new GSL_ERROR("bad integrand behavior found in the integration interval",
                                     GSL_ERR.GSL_ESING, bDebug));
            }
            else if (error_type == 4)
            {
                return(new GSL_ERROR("roundoff error detected in the extrapolation table",
                                     GSL_ERR.GSL_EROUND, bDebug));
            }
            else if (error_type == 5)
            {
                return(new GSL_ERROR("integral is divergent, or slowly convergent",
                                     GSL_ERR.GSL_EDIVERGE, bDebug));
            }
            else
            {
                return(new GSL_ERROR("could not integrate function", GSL_ERR.GSL_EFAILED, bDebug));
            }
        }