Ejemplo n.º 1
0
        gsl_integration_qagil(Func <double, double> f,
                              double b,
                              double epsabs, double epsrel, int limit,
                              gsl_integration_workspace workspace,
                              out double result, out double abserr, gsl_integration_rule q, bool bDebug)
        {
            //int status;

            // gsl_function f_transform;
            var transform_params = new il_params
            {
                b = b,
                f = f
            };

            //  f_transform.function = &il_transform;
            //  f_transform.params = &transform_params;

            Func <double, double> f_transform = delegate(double t)
            { return(il_transform(t, transform_params)); };

            GSL_ERROR status = qags(f_transform, 0.0, 1.0,
                                    epsabs, epsrel, limit,
                                    workspace,
                                    out result, out abserr,
                                    q, bDebug);

            return(status);
        }
Ejemplo n.º 2
0
        Integrate(Func <double, double> f,
                  double a,
                  OscillatoryTerm oscTerm,
                  double omega,
                  double epsabs, int limit,
                  bool debug,
                  out double result, out double abserr)
        {
            if (null == _workSpace || limit > _workSpace.limit)
            {
                _workSpace = new gsl_integration_workspace(limit);
            }

            if (null == _cycleWorkspace || limit > _cycleWorkspace.limit)
            {
                _cycleWorkspace = new gsl_integration_workspace(limit);
            }

            if (null == _qawoTable)
            {
                _qawoTable = new gsl_integration_qawo_table(omega, 1, oscTerm == OscillatoryTerm.Cosine ? gsl_integration_qawo_enum.GSL_INTEG_COSINE : gsl_integration_qawo_enum.GSL_INTEG_SINE, _defaultOscTableLength);
            }
            else
            {
                _qawoTable.set(omega, 1, oscTerm == OscillatoryTerm.Cosine ? gsl_integration_qawo_enum.GSL_INTEG_COSINE : gsl_integration_qawo_enum.GSL_INTEG_SINE);
            }
            return(gsl_integration_qawf(f, a, epsabs, limit, _workSpace, _cycleWorkspace, _qawoTable, out result, out abserr, debug));
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Adaptive integration on infinite interval (-Infinity,+Infinity).
        /// </summary>
        /// <param name="f">Function to integrate.</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>
        /// <returns>Null if successfull, otherwise the appropriate error code.</returns>
        public GSL_ERROR Integrate(Func <double, double> f,
                                   double epsabs, double epsrel, int limit,
                                   gsl_integration_rule integrationRule, bool debug,
                                   out double result, out double abserr)
        {
            if (null == _workSpace || limit > _workSpace.limit)
            {
                _workSpace = new gsl_integration_workspace(limit);
            }

            return(gsl_integration_qagi(f, epsabs, epsrel, limit, _workSpace, out result, out abserr, integrationRule, debug));
        }
Ejemplo n.º 4
0
		qags(Func<double, double> f,
					double a, double b,
					double epsabs, double epsrel,
					int limit,
					gsl_integration_workspace workspace,
					out double result, out double abserr,
					gsl_integration_rule q, bool bDebug)
		{
			double area, errsum;
			double res_ext, err_ext;
			double result0, abserr0, resabs0, resasc0;
			double tolerance;

			double ertest = 0;
			double error_over_large_intervals = 0;
			double reseps = 0, abseps = 0, correc = 0;
			int ktmin = 0;
			int roundoff_type1 = 0, roundoff_type2 = 0, roundoff_type3 = 0;
			int error_type = 0;
			bool error_type2 = false;

			int iteration = 0;

			bool positive_integrand = false;
			bool extrapolate = false;
			bool disallow_extrapolation = false;

			extrapolation_table table = new extrapolation_table();

			/* Initialize results */

			workspace.initialise(a, b);

			result = double.NaN;
			abserr = double.NaN;

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

			/* Test on accuracy */

			if (epsabs <= 0 && (epsrel < 50 * GSL_CONST.GSL_DBL_EPSILON || epsrel < 0.5e-28))
			{
				return new GSL_ERROR("tolerance cannot be acheived with given epsabs and epsrel",
									 GSL_ERR.GSL_EBADTOL, bDebug);
			}

			/* Perform the first integration */

			q(f, a, b, out result0, out abserr0, out resabs0, out resasc0);

			workspace.set_initial_result(result0, abserr0);

			tolerance = Math.Max(epsabs, epsrel * Math.Abs(result0));

			if (abserr0 <= 100 * GSL_CONST.GSL_DBL_EPSILON * resabs0 && abserr0 > tolerance)
			{
				result = result0;
				abserr = abserr0;

				return new GSL_ERROR("cannot reach tolerance because of roundoff error on first attempt", GSL_ERR.GSL_EROUND, bDebug);
			}
			else if ((abserr0 <= tolerance && abserr0 != resasc0) || abserr0 == 0.0)
			{
				result = result0;
				abserr = abserr0;

				return null; // GSL_SUCCESS;
			}
			else if (limit == 1)
			{
				result = result0;
				abserr = abserr0;

				return new GSL_ERROR("a maximum of one iteration was insufficient", GSL_ERR.GSL_EMAXITER, bDebug);
			}

			/* Initialization */

			table.initialise_table();
			table.append_table(result0);

			area = result0;
			errsum = abserr0;

			res_ext = result0;
			err_ext = GSL_CONST.GSL_DBL_MAX;

			positive_integrand = test_positivity(result0, resabs0);

			iteration = 1;

			do
			{
				int current_level;
				double a1, b1, a2, b2;
				double a_i, b_i, r_i, e_i;
				double area1 = 0, area2 = 0, area12 = 0;
				double error1 = 0, error2 = 0, error12 = 0;
				double resasc1, resasc2;
				double resabs1, resabs2;
				double last_e_i;

				/* Bisect the subinterval with the largest error estimate */

				workspace.retrieve(out a_i, out b_i, out r_i, out e_i);

				current_level = workspace.level[workspace.i] + 1;

				a1 = a_i;
				b1 = 0.5 * (a_i + b_i);
				a2 = b1;
				b2 = b_i;

				iteration++;

				q(f, a1, b1, out area1, out error1, out resabs1, out resasc1);
				q(f, a2, b2, out area2, out error2, out resabs2, out resasc2);

				area12 = area1 + area2;
				error12 = error1 + error2;
				last_e_i = e_i;

				/* Improve previous approximations to the integral and test for
					 accuracy.

					 We write these expressions in the same way as the original
					 QUADPACK code so that the rounding errors are the same, which
					 makes testing easier. */

				errsum = errsum + error12 - e_i;
				area = area + area12 - r_i;

				tolerance = Math.Max(epsabs, epsrel * Math.Abs(area));

				if (resasc1 != error1 && resasc2 != error2)
				{
					double delta = r_i - area12;

					if (Math.Abs(delta) <= 1.0e-5 * Math.Abs(area12) && error12 >= 0.99 * e_i)
					{
						if (!extrapolate)
						{
							roundoff_type1++;
						}
						else
						{
							roundoff_type2++;
						}
					}
					if (iteration > 10 && error12 > e_i)
					{
						roundoff_type3++;
					}
				}

				/* Test for roundoff and eventually set error flag */

				if (roundoff_type1 + roundoff_type2 >= 10 || roundoff_type3 >= 20)
				{
					error_type = 2;       /* round off error */
				}

				if (roundoff_type2 >= 5)
				{
					error_type2 = true;
				}

				/* set error flag in the case of bad integrand behaviour at
					 a point of the integration range */

				if (subinterval_too_small(a1, a2, b2))
				{
					error_type = 4;
				}

				/* append the newly-created intervals to the list */

				workspace.update(a1, b1, area1, error1, a2, b2, area2, error2);

				if (errsum <= tolerance)
				{
					goto compute_result;
				}

				if (0 != error_type)
				{
					break;
				}

				if (iteration >= limit - 1)
				{
					error_type = 1;
					break;
				}

				if (iteration == 2)       /* set up variables on first iteration */
				{
					error_over_large_intervals = errsum;
					ertest = tolerance;
					table.append_table(area);
					continue;
				}

				if (disallow_extrapolation)
				{
					continue;
				}

				error_over_large_intervals += -last_e_i;

				if (current_level < workspace.maximum_level)
				{
					error_over_large_intervals += error12;
				}

				if (!extrapolate)
				{
					/* test whether the interval to be bisected next is the
						 smallest interval. */

					if (workspace.large_interval())
						continue;

					extrapolate = true;
					workspace.nrmax = 1;
				}

				if (!error_type2 && error_over_large_intervals > ertest)
				{
					if (workspace.increase_nrmax())
						continue;
				}

				/* Perform extrapolation */

				table.append_table(area);

				table.qelg(out reseps, out abseps);

				ktmin++;

				if (ktmin > 5 && err_ext < 0.001 * errsum)
				{
					error_type = 5;
				}

				if (abseps < err_ext)
				{
					ktmin = 0;
					err_ext = abseps;
					res_ext = reseps;
					correc = error_over_large_intervals;
					ertest = Math.Max(epsabs, epsrel * Math.Abs(reseps));
					if (err_ext <= ertest)
						break;
				}

				/* Prepare bisection of the smallest interval. */

				if (table.n == 1)
				{
					disallow_extrapolation = true;
				}

				if (error_type == 5)
				{
					break;
				}

				/* work on interval with largest error */

				workspace.reset_nrmax();
				extrapolate = false;
				error_over_large_intervals = errsum;
			}
			while (iteration < limit);

			result = res_ext;
			abserr = err_ext;

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

			if (0 != error_type || error_type2)
			{
				if (error_type2)
				{
					err_ext += correc;
				}

				if (error_type == 0)
					error_type = 3;

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

			/*  Test on divergence. */

			{
				double max_area = Math.Max(Math.Abs(res_ext), Math.Abs(area));

				if (!positive_integrand && max_area < 0.01 * resabs0)
					goto return_error;
			}

			{
				double ratio = res_ext / area;

				if (ratio < 0.01 || ratio > 100.0 || errsum > Math.Abs(area))
					error_type = 6;
			}

			goto return_error;

		compute_result:

			result = workspace.sum_results();
			abserr = errsum;

		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);
			}
		}
Ejemplo n.º 5
0
        gsl_integration_qawc(Func <double, double> f,
                             double a, double b, double c,
                             double epsabs, double epsrel,
                             int limit,
                             gsl_integration_workspace workspace,
                             out double result, out double abserr,
                             bool bDebug)
        {
            double area, errsum;
            double tolerance;
            int    iteration = 0;
            int    roundoff_type1 = 0, roundoff_type2 = 0, error_type = 0;
            int    sign = 1;
            double lower, higher;

            /* Initialize results */

            result = 0;
            abserr = 0;

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

            if (b < a)
            {
                lower  = b;
                higher = a;
                sign   = -1;
            }
            else
            {
                lower  = a;
                higher = b;
            }

            workspace.initialise(lower, higher);

            if (epsabs <= 0 && (epsrel < 50 * GSL_CONST.GSL_DBL_EPSILON || epsrel < 0.5e-28))
            {
                return(new GSL_ERROR("tolerance cannot be acheived with given epsabs and epsrel", GSL_ERR.GSL_EBADTOL, bDebug));
            }

            if (c == a || c == b)
            {
                return(new GSL_ERROR("cannot integrate with singularity on endpoint", GSL_ERR.GSL_EINVAL, bDebug));
            }

            /* perform the first integration */

            qc25c(f, lower, higher, c, out var result0, out var abserr0, out var err_reliable);

            workspace.set_initial_result(result0, abserr0);

            /* Test on accuracy, use 0.01 relative error as an extra safety
             *                         margin on the first iteration (ignored for subsequent iterations) */

            tolerance = Math.Max(epsabs, epsrel * Math.Abs(result0));

            if (abserr0 < tolerance && abserr0 < 0.01 * Math.Abs(result0))
            {
                result = sign * result0;
                abserr = abserr0;

                return(null); // GSL_SUCCESS;
            }
            else if (limit == 1)
            {
                result = sign * result0;
                abserr = abserr0;

                return(new GSL_ERROR("a maximum of one iteration was insufficient", GSL_ERR.GSL_EMAXITER, bDebug));
            }

            area   = result0;
            errsum = abserr0;

            iteration = 1;

            do
            {
                double a1, b1, a2, b2;
                double area12  = 0;
                double error12 = 0;

                /* Bisect the subinterval with the largest error estimate */

                workspace.retrieve(out var a_i, out var b_i, out var r_i, out var e_i);

                a1 = a_i;
                b1 = 0.5 * (a_i + b_i);
                a2 = b1;
                b2 = b_i;

                if (c > a1 && c <= b1)
                {
                    b1 = 0.5 * (c + b2);
                    a2 = b1;
                }
                else if (c > b1 && c < b2)
                {
                    b1 = 0.5 * (a1 + c);
                    a2 = b1;
                }

                qc25c(f, a1, b1, c, out var area1, out var error1, out var err_reliable1);
                qc25c(f, a2, b2, c, out var area2, out var error2, out var err_reliable2);

                area12  = area1 + area2;
                error12 = error1 + error2;

                errsum += (error12 - e_i);
                area   += area12 - r_i;

                if (err_reliable1 && err_reliable2)
                {
                    double delta = r_i - area12;

                    if (Math.Abs(delta) <= 1.0e-5 * Math.Abs(area12) && error12 >= 0.99 * e_i)
                    {
                        roundoff_type1++;
                    }
                    if (iteration >= 10 && error12 > e_i)
                    {
                        roundoff_type2++;
                    }
                }

                tolerance = Math.Max(epsabs, epsrel * Math.Abs(area));

                if (errsum > tolerance)
                {
                    if (roundoff_type1 >= 6 || roundoff_type2 >= 20)
                    {
                        error_type = 2; /* round off error */
                    }

                    /* set error flag in the case of bad integrand behaviour at
                     *                                     a point of the integration range */

                    if (subinterval_too_small(a1, a2, b2))
                    {
                        error_type = 3;
                    }
                }

                workspace.update(a1, b1, area1, error1, a2, b2, area2, error2);

                workspace.retrieve(out a_i, out b_i, out r_i, out e_i);

                iteration++;
            }while (iteration < limit && 0 == error_type && errsum > tolerance);

            result = sign * workspace.sum_results();
            abserr = errsum;

            if (errsum <= tolerance)
            {
                return(null); // GSL_SUCCESS;
            }
            else if (error_type == 2)
            {
                return(new GSL_ERROR("roundoff error prevents tolerance from being achieved", 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 (iteration == limit)
            {
                return(new GSL_ERROR("maximum number of subdivisions reached", GSL_ERR.GSL_EMAXITER, bDebug));
            }
            else
            {
                return(new GSL_ERROR("could not integrate function", GSL_ERR.GSL_EFAILED, bDebug));
            }
        }
Ejemplo n.º 6
0
        qags(Func <double, double> f,
             double a, double b,
             double epsabs, double epsrel,
             int limit,
             gsl_integration_workspace workspace,
             out double result, out double abserr,
             gsl_integration_rule q, bool bDebug)
        {
            double area, errsum;
            double res_ext, err_ext;
            double tolerance;

            double ertest = 0;
            double error_over_large_intervals = 0;
            double reseps = 0, abseps = 0, correc = 0;
            int    ktmin = 0;
            int    roundoff_type1 = 0, roundoff_type2 = 0, roundoff_type3 = 0;
            int    error_type           = 0;
            bool   error_type2          = false;

            int iteration               = 0;

            bool positive_integrand = false;
            bool extrapolate            = false;
            bool disallow_extrapolation = false;

            var table = new extrapolation_table();

            /* Initialize results */

            workspace.initialise(a, b);

            result = double.NaN;
            abserr = double.NaN;

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

            /* Test on accuracy */

            if (epsabs <= 0 && (epsrel < 50 * GSL_CONST.GSL_DBL_EPSILON || epsrel < 0.5e-28))
            {
                return(new GSL_ERROR("tolerance cannot be acheived with given epsabs and epsrel",
                                     GSL_ERR.GSL_EBADTOL, bDebug));
            }

            /* Perform the first integration */

            q(f, a, b, out var result0, out var abserr0, out var resabs0, out var resasc0);

            workspace.set_initial_result(result0, abserr0);

            tolerance = Math.Max(epsabs, epsrel * Math.Abs(result0));

            if (abserr0 <= 100 * GSL_CONST.GSL_DBL_EPSILON * resabs0 && abserr0 > tolerance)
            {
                result = result0;
                abserr = abserr0;

                return(new GSL_ERROR("cannot reach tolerance because of roundoff error on first attempt", GSL_ERR.GSL_EROUND, bDebug));
            }
            else if ((abserr0 <= tolerance && abserr0 != resasc0) || abserr0 == 0.0)
            {
                result = result0;
                abserr = abserr0;

                return(null); // GSL_SUCCESS;
            }
            else if (limit == 1)
            {
                result = result0;
                abserr = abserr0;

                return(new GSL_ERROR("a maximum of one iteration was insufficient", GSL_ERR.GSL_EMAXITER, bDebug));
            }

            /* Initialization */

            table.initialise_table();
            table.append_table(result0);

            area   = result0;
            errsum = abserr0;

            res_ext = result0;
            err_ext = GSL_CONST.GSL_DBL_MAX;

            positive_integrand = test_positivity(result0, resabs0);

            iteration = 1;

            do
            {
                int    current_level;
                double a1, b1, a2, b2;
                double area12  = 0;
                double error12 = 0;
                double last_e_i;

                /* Bisect the subinterval with the largest error estimate */

                workspace.retrieve(out var a_i, out var b_i, out var r_i, out var e_i);

                current_level = workspace.level[workspace.i] + 1;

                a1 = a_i;
                b1 = 0.5 * (a_i + b_i);
                a2 = b1;
                b2 = b_i;

                iteration++;

                q(f, a1, b1, out var area1, out var error1, out var resabs1, out var resasc1);
                q(f, a2, b2, out var area2, out var error2, out var resabs2, out var resasc2);

                area12   = area1 + area2;
                error12  = error1 + error2;
                last_e_i = e_i;

                /* Improve previous approximations to the integral and test for
                 *                               accuracy.
                 *
                 *                               We write these expressions in the same way as the original
                 *                               QUADPACK code so that the rounding errors are the same, which
                 *                               makes testing easier. */

                errsum = errsum + error12 - e_i;
                area   = area + area12 - r_i;

                tolerance = Math.Max(epsabs, epsrel * Math.Abs(area));

                if (resasc1 != error1 && resasc2 != error2)
                {
                    double delta = r_i - area12;

                    if (Math.Abs(delta) <= 1.0e-5 * Math.Abs(area12) && error12 >= 0.99 * e_i)
                    {
                        if (!extrapolate)
                        {
                            roundoff_type1++;
                        }
                        else
                        {
                            roundoff_type2++;
                        }
                    }
                    if (iteration > 10 && error12 > e_i)
                    {
                        roundoff_type3++;
                    }
                }

                /* Test for roundoff and eventually set error flag */

                if (roundoff_type1 + roundoff_type2 >= 10 || roundoff_type3 >= 20)
                {
                    error_type = 2; /* round off error */
                }

                if (roundoff_type2 >= 5)
                {
                    error_type2 = true;
                }

                /* set error flag in the case of bad integrand behaviour at
                 *                               a point of the integration range */

                if (subinterval_too_small(a1, a2, b2))
                {
                    error_type = 4;
                }

                /* append the newly-created intervals to the list */

                workspace.update(a1, b1, area1, error1, a2, b2, area2, error2);

                if (errsum <= tolerance)
                {
                    goto compute_result;
                }

                if (0 != error_type)
                {
                    break;
                }

                if (iteration >= limit - 1)
                {
                    error_type = 1;
                    break;
                }

                if (iteration == 2) /* set up variables on first iteration */
                {
                    error_over_large_intervals = errsum;
                    ertest = tolerance;
                    table.append_table(area);
                    continue;
                }

                if (disallow_extrapolation)
                {
                    continue;
                }

                error_over_large_intervals += -last_e_i;

                if (current_level < workspace.maximum_level)
                {
                    error_over_large_intervals += error12;
                }

                if (!extrapolate)
                {
                    /* test whether the interval to be bisected next is the
                     *                                     smallest interval. */

                    if (workspace.large_interval())
                    {
                        continue;
                    }

                    extrapolate     = true;
                    workspace.nrmax = 1;
                }

                if (!error_type2 && error_over_large_intervals > ertest)
                {
                    if (workspace.increase_nrmax())
                    {
                        continue;
                    }
                }

                /* Perform extrapolation */

                table.append_table(area);

                table.qelg(out reseps, out abseps);

                ktmin++;

                if (ktmin > 5 && err_ext < 0.001 * errsum)
                {
                    error_type = 5;
                }

                if (abseps < err_ext)
                {
                    ktmin   = 0;
                    err_ext = abseps;
                    res_ext = reseps;
                    correc  = error_over_large_intervals;
                    ertest  = Math.Max(epsabs, epsrel * Math.Abs(reseps));
                    if (err_ext <= ertest)
                    {
                        break;
                    }
                }

                /* Prepare bisection of the smallest interval. */

                if (table.n == 1)
                {
                    disallow_extrapolation = true;
                }

                if (error_type == 5)
                {
                    break;
                }

                /* work on interval with largest error */

                workspace.reset_nrmax();
                extrapolate = false;
                error_over_large_intervals = errsum;
            }while (iteration < limit);

            result = res_ext;
            abserr = err_ext;

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

            if (0 != error_type || error_type2)
            {
                if (error_type2)
                {
                    err_ext += correc;
                }

                if (error_type == 0)
                {
                    error_type = 3;
                }

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

            /*  Test on divergence. */

            {
                double max_area = Math.Max(Math.Abs(res_ext), Math.Abs(area));

                if (!positive_integrand && max_area < 0.01 * resabs0)
                {
                    goto return_error;
                }
            }

            {
                double ratio = res_ext / area;

                if (ratio < 0.01 || ratio > 100.0 || errsum > Math.Abs(area))
                {
                    error_type = 6;
                }
            }

            goto return_error;

compute_result:

            result = workspace.sum_results();
            abserr = errsum;

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));
            }
        }
Ejemplo n.º 7
0
		gsl_integration_qagi(Func<double, double> f,
													double epsabs, double epsrel, int limit,
													gsl_integration_workspace workspace,
													out double result, out double abserr,
													gsl_integration_rule q, bool bDebug
			)
		{
			//int status;

			//  gsl_function f_transform;
			//  f_transform.function = &i_transform;
			//  f_transform.params = f;

			Func<double, double> f_transform = delegate(double t) { return i_transform(t, f); };

			GSL_ERROR status = qags(f_transform, 0.0, 1.0,
										 epsabs, epsrel, limit,
										 workspace,
										 out result, out abserr,
										 q, bDebug);

			return status;
		}
Ejemplo n.º 8
0
		/// <summary>
		/// Adaptive integration on infinite interval (-Infinity,+Infinity).
		/// </summary>
		/// <param name="f">Function to integrate.</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>
		/// <returns>Null if successfull, otherwise the appropriate error code.</returns>
		public GSL_ERROR Integrate(Func<double, double> f,
				double epsabs, double epsrel, int limit,
			 gsl_integration_rule integrationRule, bool debug,
			 out double result, out double abserr)
		{
			if (null == _workSpace || limit > _workSpace.limit)
				_workSpace = new gsl_integration_workspace(limit);

			return gsl_integration_qagi(f, epsabs, epsrel, limit, _workSpace, out result, out abserr, integrationRule, debug);
		}
Ejemplo n.º 9
0
		qag(Func<double, double> f,
				 double a, double b,
				 double epsabs, double epsrel,
				 int limit,
				 gsl_integration_workspace workspace,
				 out double result, out double abserr,
				 gsl_integration_rule q,
				 bool bDebug)
		{
			double area, errsum;
			double result0, abserr0, resabs0, resasc0;
			double tolerance;
			int iteration = 0;
			int roundoff_type1 = 0, roundoff_type2 = 0, error_type = 0;

			double round_off;

			/* Initialize results */

			workspace.initialise(a, b);

			result = 0;
			abserr = 0;

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

			if (epsabs <= 0 && (epsrel < 50 * GSL_CONST.GSL_DBL_EPSILON || epsrel < 0.5e-28))
			{
				return new GSL_ERROR("tolerance cannot be acheived with given epsabs and epsrel",
									 GSL_ERR.GSL_EBADTOL, true);
			}

			/* perform the first integration */

			q(f, a, b, out result0, out abserr0, out resabs0, out resasc0);

			workspace.set_initial_result(result0, abserr0);

			/* Test on accuracy */

			tolerance = Math.Max(epsabs, epsrel * Math.Abs(result0));

			/* need IEEE rounding here to match original quadpack behavior */

			round_off = GSL_COERCE_DBL(50 * GSL_CONST.GSL_DBL_EPSILON * resabs0);

			if (abserr0 <= round_off && abserr0 > tolerance)
			{
				result = result0;
				abserr = abserr0;

				return new GSL_ERROR("cannot reach tolerance because of roundoff error on first attempt", GSL_ERR.GSL_EROUND, bDebug);
			}
			else if ((abserr0 <= tolerance && abserr0 != resasc0) || abserr0 == 0.0)
			{
				result = result0;
				abserr = abserr0;

				return null; //GSL_SUCCESS;
			}
			else if (limit == 1)
			{
				result = result0;
				abserr = abserr0;

				return new GSL_ERROR("a maximum of one iteration was insufficient", GSL_ERR.GSL_EMAXITER, bDebug);
			}

			area = result0;
			errsum = abserr0;

			iteration = 1;

			do
			{
				double a1, b1, a2, b2;
				double a_i, b_i, r_i, e_i;
				double area1 = 0, area2 = 0, area12 = 0;
				double error1 = 0, error2 = 0, error12 = 0;
				double resasc1, resasc2;
				double resabs1, resabs2;

				/* Bisect the subinterval with the largest error estimate */

				workspace.retrieve(out a_i, out b_i, out r_i, out e_i);

				a1 = a_i;
				b1 = 0.5 * (a_i + b_i);
				a2 = b1;
				b2 = b_i;

				q(f, a1, b1, out area1, out error1, out resabs1, out resasc1);
				q(f, a2, b2, out area2, out error2, out resabs2, out resasc2);

				area12 = area1 + area2;
				error12 = error1 + error2;

				errsum += (error12 - e_i);
				area += area12 - r_i;

				if (resasc1 != error1 && resasc2 != error2)
				{
					double delta = r_i - area12;

					if (Math.Abs(delta) <= 1.0e-5 * Math.Abs(area12) && error12 >= 0.99 * e_i)
					{
						roundoff_type1++;
					}
					if (iteration >= 10 && error12 > e_i)
					{
						roundoff_type2++;
					}
				}

				tolerance = Math.Max(epsabs, epsrel * Math.Abs(area));

				if (errsum > tolerance)
				{
					if (roundoff_type1 >= 6 || roundoff_type2 >= 20)
					{
						error_type = 2;   /* round off error */
					}

					/* set error flag in the case of bad integrand behaviour at
						 a point of the integration range */

					if (subinterval_too_small(a1, a2, b2))
					{
						error_type = 3;
					}
				}

				workspace.update(a1, b1, area1, error1, a2, b2, area2, error2);

				workspace.retrieve(out a_i, out b_i, out r_i, out e_i);

				iteration++;
			}
			while (iteration < limit && 0 == error_type && errsum > tolerance);

			result = workspace.sum_results();
			abserr = errsum;

			if (errsum <= tolerance)
			{
				return null; //GSL_SUCCESS;
			}
			else if (error_type == 2)
			{
				return new GSL_ERROR("roundoff error prevents tolerance from being achieved",
									 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 (iteration == limit)
			{
				return new GSL_ERROR("maximum number of subdivisions reached", GSL_ERR.GSL_EMAXITER, bDebug);
			}
			else
			{
				return new GSL_ERROR("could not integrate function", GSL_ERR.GSL_EFAILED, bDebug);
			}
		}
Ejemplo n.º 10
0
			Integrate(Func<double, double> f,
			double a, double b,
			OscillatoryTerm oscTerm,
			double omega,
			double epsabs, double epsrel, int limit,
			bool debug,
			out double result, out double abserr)
		{
			if (null == _workSpace || limit > _workSpace.limit)
				_workSpace = new gsl_integration_workspace(limit);
			if (null == _qawoTable)
			{
				_qawoTable = new gsl_integration_qawo_table(omega, b - a, oscTerm == OscillatoryTerm.Cosine ? gsl_integration_qawo_enum.GSL_INTEG_COSINE : gsl_integration_qawo_enum.GSL_INTEG_SINE, _defaultOscTableLength);
			}
			else
			{
				_qawoTable.set(omega, b - a, oscTerm == OscillatoryTerm.Cosine ? gsl_integration_qawo_enum.GSL_INTEG_COSINE : gsl_integration_qawo_enum.GSL_INTEG_SINE);
			}

			return gsl_integration_qawo(f, a, epsabs, epsrel, limit, _workSpace, _qawoTable, out result, out abserr, debug);
		}
Ejemplo n.º 11
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;

			extrapolation_table 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 area1, error1, reseps, erreps;

				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 area1, out 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 reseps, out 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);
			}
		}
Ejemplo n.º 12
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));
            }
        }
Ejemplo n.º 13
0
        qag(Func <double, double> f,
            double a, double b,
            double epsabs, double epsrel,
            int limit,
            gsl_integration_workspace workspace,
            out double result, out double abserr,
            gsl_integration_rule q,
            bool bDebug)
        {
            double area, errsum;
            double tolerance;
            int    iteration = 0;
            int    roundoff_type1 = 0, roundoff_type2 = 0, error_type = 0;

            double round_off;

            /* Initialize results */

            workspace.initialise(a, b);

            result = 0;
            abserr = 0;

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

            if (epsabs <= 0 && (epsrel < 50 * GSL_CONST.GSL_DBL_EPSILON || epsrel < 0.5e-28))
            {
                return(new GSL_ERROR("tolerance cannot be acheived with given epsabs and epsrel",
                                     GSL_ERR.GSL_EBADTOL, true));
            }

            /* perform the first integration */

            q(f, a, b, out var result0, out var abserr0, out var resabs0, out var resasc0);

            workspace.set_initial_result(result0, abserr0);

            /* Test on accuracy */

            tolerance = Math.Max(epsabs, epsrel * Math.Abs(result0));

            /* need IEEE rounding here to match original quadpack behavior */

            round_off = GSL_COERCE_DBL(50 * GSL_CONST.GSL_DBL_EPSILON * resabs0);

            if (abserr0 <= round_off && abserr0 > tolerance)
            {
                result = result0;
                abserr = abserr0;

                return(new GSL_ERROR("cannot reach tolerance because of roundoff error on first attempt", GSL_ERR.GSL_EROUND, bDebug));
            }
            else if ((abserr0 <= tolerance && abserr0 != resasc0) || abserr0 == 0.0)
            {
                result = result0;
                abserr = abserr0;

                return(null); //GSL_SUCCESS;
            }
            else if (limit == 1)
            {
                result = result0;
                abserr = abserr0;

                return(new GSL_ERROR("a maximum of one iteration was insufficient", GSL_ERR.GSL_EMAXITER, bDebug));
            }

            area   = result0;
            errsum = abserr0;

            iteration = 1;

            do
            {
                double a1, b1, a2, b2;
                double area12  = 0;
                double error12 = 0;

                /* Bisect the subinterval with the largest error estimate */

                workspace.retrieve(out var a_i, out var b_i, out var r_i, out var e_i);

                a1 = a_i;
                b1 = 0.5 * (a_i + b_i);
                a2 = b1;
                b2 = b_i;

                q(f, a1, b1, out var area1, out var error1, out var resabs1, out var resasc1);
                q(f, a2, b2, out var area2, out var error2, out var resabs2, out var resasc2);

                area12  = area1 + area2;
                error12 = error1 + error2;

                errsum += (error12 - e_i);
                area   += area12 - r_i;

                if (resasc1 != error1 && resasc2 != error2)
                {
                    double delta = r_i - area12;

                    if (Math.Abs(delta) <= 1.0e-5 * Math.Abs(area12) && error12 >= 0.99 * e_i)
                    {
                        roundoff_type1++;
                    }
                    if (iteration >= 10 && error12 > e_i)
                    {
                        roundoff_type2++;
                    }
                }

                tolerance = Math.Max(epsabs, epsrel * Math.Abs(area));

                if (errsum > tolerance)
                {
                    if (roundoff_type1 >= 6 || roundoff_type2 >= 20)
                    {
                        error_type = 2; /* round off error */
                    }

                    /* set error flag in the case of bad integrand behaviour at
                     *                                     a point of the integration range */

                    if (subinterval_too_small(a1, a2, b2))
                    {
                        error_type = 3;
                    }
                }

                workspace.update(a1, b1, area1, error1, a2, b2, area2, error2);

                workspace.retrieve(out a_i, out b_i, out r_i, out e_i);

                iteration++;
            }while (iteration < limit && 0 == error_type && errsum > tolerance);

            result = workspace.sum_results();
            abserr = errsum;

            if (errsum <= tolerance)
            {
                return(null); //GSL_SUCCESS;
            }
            else if (error_type == 2)
            {
                return(new GSL_ERROR("roundoff error prevents tolerance from being achieved",
                                     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 (iteration == limit)
            {
                return(new GSL_ERROR("maximum number of subdivisions reached", GSL_ERR.GSL_EMAXITER, bDebug));
            }
            else
            {
                return(new GSL_ERROR("could not integrate function", GSL_ERR.GSL_EFAILED, bDebug));
            }
        }