/// <summary>Gets the value of the integral \int_a^b f(x) dx. /// </summary> /// <param name="lowerBound">The lower bound.</param> /// <param name="upperBound">The upper bound.</param> /// <returns>The value of \int_a^b f(x) dx.</returns> /// <remarks>The arguments must be elements of the domain of definition, represented by <see cref="IRealValuedCurve.LowerBound"/> and <see cref="IRealValuedCurve.UpperBound"/> of the encapsulated <see cref="ICurveDataFitting"/> object.</remarks> public double GetIntegral(double lowerBound, double upperBound) { if (UpdateRequested == true) { Update(); } int leftGridIndex = GridPointArguments.BinarySearch(0, GridPointCount, lowerBound); int rightGridIndex = GridPointArguments.BinarySearch(0, GridPointCount, upperBound); if ((leftGridIndex >= 0) && (rightGridIndex >= 0)) { return(m_Cache[rightGridIndex] - m_Cache[leftGridIndex]); // \int_{t_j}^{t_k} f(x) dx = \int_{t_0}^{t_k} f(x) dx - \int_{t_0}^{t_j} f(x) dx } else if (leftGridIndex < 0) { int previousLeftGridIndex = (~leftGridIndex) - 1; // previous grid point, i.e. smaller than the lower bound var value = CurveDataFitting.GetIntegral(lowerBound, Math.Min(upperBound, GridPointArguments[previousLeftGridIndex + 1]), previousLeftGridIndex); if (leftGridIndex != rightGridIndex) // lower and upper bound are not in the same interval [t_j, t_{j+1}] { if (rightGridIndex >= 0) { value += (m_Cache[rightGridIndex] - m_Cache[previousLeftGridIndex + 1]); } else { rightGridIndex = (~rightGridIndex) - 1; // previous grid point, i.e. smaller than the upper bound var stepValue = CurveDataFitting.GetIntegral(Math.Max(lowerBound, GridPointArguments[rightGridIndex]), upperBound, rightGridIndex); value += stepValue + (m_Cache[rightGridIndex] - m_Cache[previousLeftGridIndex + 1]); } } return(value); } else // lower bound is a grid point and the upper bound is not a grid point { rightGridIndex = (~rightGridIndex) - 1; // previous grid point, i.e. smaller than the upper bound var stepValue = CurveDataFitting.GetIntegral(Math.Max(lowerBound, GridPointArguments[rightGridIndex]), upperBound, rightGridIndex); return(stepValue + (m_Cache[rightGridIndex] - m_Cache[leftGridIndex])); } }
/// <summary>Updates the internal cache. /// </summary> private void Update() { ArrayMemory.Reallocate(ref m_Cache, GridPointCount, pufferSize: 5); var cumIntegralValue = m_Cache[0] = 0.0; var lowerBound = GridPointArguments[0]; for (int k = 1; k < GridPointCount; k++) { var upperBound = GridPointArguments[k]; var upperGridPointValue = GridPointValues[k]; cumIntegralValue += CurveDataFitting.GetIntegral(lowerBound, upperBound, k - 1); m_Cache[k] = cumIntegralValue; /* prepare for next loop: */ lowerBound = upperBound; } UpdateRequested = false; }