/// <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)); }
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)); }
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); }
/// <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); }
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)); } }