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