/// <summary>Gets the value of the integral \int_a^b w(x) * f(x) dx.
            /// </summary>
            /// <returns>An approximation of the specific integral.
            /// </returns>
            public double GetValue()
            {
                double benchmarkValue;
                double value = OneStepIntegration(m_LowerBound, m_UpperBound, out benchmarkValue);

                if (m_IntegratorFactory.ExitCondition.IsFulfilled(value, benchmarkValue) == true)
                {
                    return(value);
                }

                /* use a stack which contains 'intervals/integrals' which have to divide into sub-integrals: */
                Stack <SubIntegral> stack = new Stack <SubIntegral>();

                stack.Push(new SubIntegral(value, benchmarkValue, m_LowerBound, m_UpperBound, 1));
                value = benchmarkValue = 0.0;

                while (stack.Count > 0)
                {
                    SubIntegral integral = stack.Pop();

                    if ((integral.Depth <= m_IntegratorFactory.ExitCondition.MaxIterations) || (Math.Abs(integral.UpperBound - integral.LowerBound) < MachineConsts.Epsilon))
                    {
                        double b = integral.LowerBound + (integral.UpperBound - integral.LowerBound) / 2.0;

                        /* consider the integrals \int_a^b and \int_b^c where a is the lowerBound and c the upper bound of the given integral: */
                        double subLeftBenchmarkValue;
                        double subLeftValue = OneStepIntegration(integral.LowerBound, b, out subLeftBenchmarkValue);

                        ulong factor = (2ul << integral.Depth);  // = 2^n

                        if (m_IntegratorFactory.ExitCondition.CheckConvergenceCriterion(subLeftValue, subLeftBenchmarkValue, factor) == false)
                        {
                            stack.Push(new SubIntegral(subLeftValue, subLeftBenchmarkValue, integral.LowerBound, b, integral.Depth + 1));
                        }
                        else
                        {
                            value          += subLeftValue;
                            benchmarkValue += subLeftBenchmarkValue;
                        }

                        double subRightBenchmarkValue;
                        double subRightValue = OneStepIntegration(b, integral.UpperBound, out subRightBenchmarkValue);

                        if (m_IntegratorFactory.ExitCondition.CheckConvergenceCriterion(subRightValue, subRightBenchmarkValue, factor) == false)
                        {
                            stack.Push(new SubIntegral(subRightValue, subRightBenchmarkValue, b, integral.UpperBound, integral.Depth + 1));
                        }
                        else
                        {
                            value          += subRightValue;
                            benchmarkValue += subRightBenchmarkValue;
                        }
                    }
                    else  // number of iteration exceeded or the integration range, i.e. b-a, is almost zero.
                    {
                        value          += integral.Value;
                        benchmarkValue += integral.BenchmarkValue;

                        /* the deepness of the binary tree is to high. Now get all the subintervals which are on the stack an cummulate the values: */
                        while (stack.Count > 0)
                        {
                            integral = stack.Pop();

                            value          += integral.Value;
                            benchmarkValue += integral.BenchmarkValue;
                        }
                        return(value);
                    }
                }
                return(value);
            }
        public static double Integral(SubIntegral func, double min, double max, int count)
        {
            double res = GaussLegendreRule.Integrate(x => { return(func(x)); }, min, max, count);

            return(res);
        }
            /// <summary>Gets the value of the integral \int_a^b w(x) * f(x) dx.
            /// </summary>
            /// <param name="value">An approximation of the specific integral.</param>
            /// <returns>The state of the algorithm, i.e. an indicating whether <paramref name="value"/> contains valid data.
            /// </returns>
            public State GetValue(out double value)
            {
                int oneStepFunctionEvaluationsNeeded = (int)m_IntegratorFactory.IntegrationRule;

                double benchmarkValue;

                value = OneStepIntegration(m_LowerBound, m_UpperBound, out benchmarkValue);
                int functionEvaluationsNeeded = oneStepFunctionEvaluationsNeeded;
                int numberOfIterations        = 0;

                if (m_IntegratorFactory.ExitCondition.IsFulfilled(value, benchmarkValue) == true)
                {
                    return(State.Create(NumericalIntegratorErrorClassification.ProperResult, iterationsNeeded: 1, evaluationsNeeded: functionEvaluationsNeeded));
                }

                /* use a stack which contains 'intervals/integrals' which have to divide into sub-integrals: */
                var stack = new Stack <SubIntegral>();

                stack.Push(new SubIntegral(value, benchmarkValue, m_LowerBound, m_UpperBound, 1));
                value = benchmarkValue = 0.0;

                while (stack.Count > 0)
                {
                    SubIntegral integral = stack.Pop();

                    if ((integral.Depth <= m_IntegratorFactory.ExitCondition.MaxIterations) || (Math.Abs(integral.UpperBound - integral.LowerBound) < MachineConsts.Epsilon))
                    {
                        numberOfIterations++;
                        functionEvaluationsNeeded += oneStepFunctionEvaluationsNeeded;

                        double b = integral.LowerBound + (integral.UpperBound - integral.LowerBound) / 2.0;

                        /* consider the integrals \int_a^b and \int_b^c where a is the lowerBound and c the upper bound of the given integral: */
                        double subLeftBenchmarkValue;
                        double subLeftValue = OneStepIntegration(integral.LowerBound, b, out subLeftBenchmarkValue);

                        ulong factor = (2ul << integral.Depth);  // = 2^n

                        if (m_IntegratorFactory.ExitCondition.CheckConvergenceCriterion(subLeftValue, subLeftBenchmarkValue, factor) == false)
                        {
                            stack.Push(new SubIntegral(subLeftValue, subLeftBenchmarkValue, integral.LowerBound, b, integral.Depth + 1));
                        }
                        else
                        {
                            value          += subLeftValue;
                            benchmarkValue += subLeftBenchmarkValue;
                        }

                        double subRightBenchmarkValue;
                        double subRightValue = OneStepIntegration(b, integral.UpperBound, out subRightBenchmarkValue);
                        functionEvaluationsNeeded += oneStepFunctionEvaluationsNeeded;

                        if (m_IntegratorFactory.ExitCondition.CheckConvergenceCriterion(subRightValue, subRightBenchmarkValue, factor) == false)
                        {
                            stack.Push(new SubIntegral(subRightValue, subRightBenchmarkValue, b, integral.UpperBound, integral.Depth + 1));
                        }
                        else
                        {
                            value          += subRightValue;
                            benchmarkValue += subRightBenchmarkValue;
                        }
                    }
                    else  // number of iteration exceeded or the integration range, i.e. b-a, is almost zero.
                    {
                        value          += integral.Value;
                        benchmarkValue += integral.BenchmarkValue;

                        /* the deepness of the binary tree is to high. Now get all the subintervals which are on the stack an cummulate the values: */
                        while (stack.Count > 0)
                        {
                            integral = stack.Pop();

                            value          += integral.Value;
                            benchmarkValue += integral.BenchmarkValue;
                        }

                        if (integral.Depth > m_IntegratorFactory.ExitCondition.MaxIterations)
                        {
                            return(State.Create(NumericalIntegratorErrorClassification.IterationLimitExceeded, benchmarkValue, value, numberOfIterations, functionEvaluationsNeeded));
                        }
                        else
                        {
                            return(State.Create(NumericalIntegratorErrorClassification.RoundOffError, benchmarkValue, value, numberOfIterations, functionEvaluationsNeeded));
                        }
                    }
                }
                return(State.Create(NumericalIntegratorErrorClassification.ProperResult, benchmarkValue, value, numberOfIterations));
            }