/// <summary>Updates the current curve interpolator. /// </summary> /// <param name="gridPointCount">The number of grid points, i.e. the number of relevant elements of <paramref name="gridPointArguments" /> and <paramref name="gridPointValues" /> to take into account.</param> /// <param name="gridPointArguments">The arguments of the grid points, thus labels of the curve in its <see cref="System.Double" /> representation in ascending order.</param> /// <param name="gridPointValues">The values of the grid points corresponding to <paramref name="gridPointArguments" />.</param> /// <param name="state">The state of the grid points, i.e. <paramref name="gridPointArguments" /> and <paramref name="gridPointValues" />, with respect to the previous function call.</param> /// <param name="gridPointArgumentStartIndex">The null-based start index of <paramref name="gridPointArguments" /> to take into account.</param> /// <param name="gridPointValueStartIndex">The null-based start index of <paramref name="gridPointValues" /> to take into account.</param> /// <param name="gridPointArgumentIncrement">The increment for <paramref name="gridPointArguments" />.</param> /// <param name="gridPointValueIncrement">The increment for <paramref name="gridPointValues" />.</param> /// <remarks> /// This method should be called if grid points have been changed, added, removed etc. and before evaluating the grid point curve at a specified point. /// <para>If no problem occurred, the flag <see cref="IOperable.IsOperable" /> will be set to <c>true</c>.</para> /// </remarks> public void Update(int gridPointCount, IList <double> gridPointArguments, IList <double> gridPointValues, GridPointCurve.State state, int gridPointArgumentStartIndex = 0, int gridPointValueStartIndex = 0, int gridPointArgumentIncrement = 1, int gridPointValueIncrement = 1) { m_BoundaryCondition.Update(gridPointCount, gridPointArguments, gridPointValues, state, gridPointArgumentStartIndex, gridPointValueStartIndex, gridPointArgumentIncrement, gridPointValueIncrement); double[] coefficientsB, coefficientsC, coefficientsD; m_SplineEvaluator.Update(gridPointCount, gridPointArguments, gridPointValues, state, out coefficientsB, out coefficientsC, out coefficientsD, gridPointArgumentStartIndex, gridPointValueStartIndex, gridPointArgumentIncrement, gridPointValueIncrement); int n = gridPointCount; int nMinusOne = n - 1; double deltaT; // LU decomposition is necessary if and only if the labels have been changed, too: if (state.HasFlag(GridPointCurve.State.GridPointArgumentChanged) == true) { ArrayMemory.Reallocate(ref m_DiagonalElements, n, Math.Max(10, n / 5)); ArrayMemory.Reallocate(ref m_SubDiagonalElements, nMinusOne, Math.Max(10, n / 5)); ArrayMemory.Reallocate(ref m_SuperDiagonalElements, nMinusOne, Math.Max(10, n / 5)); ArrayMemory.Reallocate(ref m_SecondSuperDiagonalElements, nMinusOne - 1, Math.Max(10, n / 5)); ArrayMemory.Reallocate(ref m_PivotIndices, n, Math.Max(10, n / 5)); deltaT = m_SplineEvaluator.GridPointArguments[1] - m_SplineEvaluator.GridPointArguments[0]; for (int j = 1; j < nMinusOne; j++) { double nextDeltaT = m_SplineEvaluator.GridPointArguments[j + 1] - m_SplineEvaluator.GridPointArguments[j]; m_SubDiagonalElements[j - 1] = deltaT; m_DiagonalElements[j] = 2.0 * (deltaT + nextDeltaT); m_SuperDiagonalElements[j] = nextDeltaT; deltaT = nextDeltaT; } m_BoundaryCondition.GetRemainingMatrixElements(out m_DiagonalElements[0], out m_SuperDiagonalElements[0], out m_SubDiagonalElements[n - 2], out m_DiagonalElements[nMinusOne]); LAPACK.LinearEquations.MatrixFactorization.dgttrf(n, m_SubDiagonalElements, m_DiagonalElements, m_SuperDiagonalElements, m_SecondSuperDiagonalElements, m_PivotIndices); } /* Compute the right hand side of Ax=b, where A is the tri-diagonal matrix already calculated and * b depends on the second derivatives and the boundary condition only. We store the value of b in *coefficientsC*: */ deltaT = m_SplineEvaluator.GridPointArguments[1] - m_SplineEvaluator.GridPointArguments[0]; for (int j = 1; j < nMinusOne; j++) { double nextDeltaT = m_SplineEvaluator.GridPointArguments[j + 1] - m_SplineEvaluator.GridPointArguments[j]; coefficientsC[j] = 3.0 * ((m_SplineEvaluator.GridPointValues[j + 1] - m_SplineEvaluator.GridPointValues[j]) / nextDeltaT - (m_SplineEvaluator.GridPointValues[j] - m_SplineEvaluator.GridPointValues[j - 1]) / deltaT); deltaT = nextDeltaT; } m_BoundaryCondition.GetRemainingRightHandSideElements(out coefficientsC[0], out coefficientsC[nMinusOne]); /* Calculate the solution x of Ax=b. The solution is the coefficient 'c' and 'dttrs' stores the result in 'coefficientsC': */ LAPACK.LinearEquations.Solver.dgttrs(n, m_SubDiagonalElements, m_DiagonalElements, m_SuperDiagonalElements, m_SecondSuperDiagonalElements, m_PivotIndices, coefficientsC, 1); /* Calculate the coefficients b_j and d_j: */ for (int k = 0; k < nMinusOne; k++) { deltaT = m_SplineEvaluator.GridPointArguments[k + 1] - m_SplineEvaluator.GridPointArguments[k]; coefficientsD[k] = (coefficientsC[k + 1] - coefficientsC[k]) / (3.0 * deltaT); coefficientsB[k] = (m_SplineEvaluator.GridPointValues[k + 1] - m_SplineEvaluator.GridPointValues[k]) / deltaT - deltaT * (2 * coefficientsC[k] + coefficientsC[k + 1]) / 3.0; } }
/// <summary>Updates the current curve interpolator. /// </summary> /// <param name="gridPointCount">The number of grid points, i.e. the number of relevant elements of <paramref name="gridPointArguments" /> and <paramref name="gridPointValues" /> to take into account.</param> /// <param name="gridPointArguments">The arguments of the grid points, thus labels of the curve in its <see cref="System.Double" /> representation in ascending order.</param> /// <param name="gridPointValues">The values of the grid points corresponding to <paramref name="gridPointArguments" />.</param> /// <param name="state">The state of the grid points, i.e. <paramref name="gridPointArguments" /> and <paramref name="gridPointValues" />, with respect to the previous function call.</param> /// <param name="gridPointArgumentStartIndex">The null-based start index of <paramref name="gridPointArguments" /> to take into account.</param> /// <param name="gridPointValueStartIndex">The null-based start index of <paramref name="gridPointValues" /> to take into account.</param> /// <param name="gridPointArgumentIncrement">The increment for <paramref name="gridPointArguments" />.</param> /// <param name="gridPointValueIncrement">The increment for <paramref name="gridPointValues" />.</param> /// <remarks> /// This method should be called if grid points have been changed, added, removed etc. and before evaluating the grid point curve at a specified point. /// <para>If no problem occurred, the flag <see cref="IOperable.IsOperable" /> will be set to <c>true</c>.</para> /// </remarks> public void Update(int gridPointCount, IList <double> gridPointArguments, IList <double> gridPointValues, GridPointCurve.State state, int gridPointArgumentStartIndex = 0, int gridPointValueStartIndex = 0, int gridPointArgumentIncrement = 1, int gridPointValueIncrement = 1) { double[] coefficientsB, coefficientsC, coefficientsD; m_SplineEvaluator.Update(gridPointCount, gridPointArguments, gridPointValues, state, out coefficientsB, out coefficientsC, out coefficientsD, gridPointArgumentStartIndex, gridPointValueStartIndex, gridPointArgumentIncrement, gridPointValueIncrement); double deltaT = m_SplineEvaluator.GridPointArguments[1] - m_SplineEvaluator.GridPointArguments[0]; // = t_{j+1} - t_j double nextDeltaT = m_SplineEvaluator.GridPointArguments[2] - m_SplineEvaluator.GridPointArguments[1]; // = t_{j+2} - t_{j+1} double b = ((m_SplineEvaluator.GridPointArguments[2] + m_SplineEvaluator.GridPointArguments[1] - 2 * m_SplineEvaluator.GridPointArguments[0]) * (m_SplineEvaluator.GridPointValues[1] - m_SplineEvaluator.GridPointValues[0]) / deltaT - deltaT * (m_SplineEvaluator.GridPointValues[2] - m_SplineEvaluator.GridPointValues[1]) / nextDeltaT) / (m_SplineEvaluator.GridPointArguments[2] - m_SplineEvaluator.GridPointArguments[0]); int k = 0; // k is the shortcut for j-1, i.e. k = j-1 double valueAtk = m_SplineEvaluator.GridPointValues[k]; for (int j = 1; j < gridPointCount - 1; j++) { double valueAtj = m_SplineEvaluator.GridPointValues[j]; nextDeltaT = m_SplineEvaluator.GridPointArguments[j + 1] - m_SplineEvaluator.GridPointArguments[j]; double nextB = (nextDeltaT * (valueAtj - valueAtk) / deltaT + deltaT * (m_SplineEvaluator.GridPointValues[j + 1] - valueAtj) / nextDeltaT) / (m_SplineEvaluator.GridPointArguments[j + 1] - m_SplineEvaluator.GridPointArguments[k]); double m = (valueAtj - valueAtk) / deltaT; coefficientsB[k] = b; coefficientsC[k] = (3 * m - nextB - 2 * b) / deltaT; coefficientsD[k] = (nextB + b - 2 * m) / (deltaT * deltaT); b = nextB; deltaT = nextDeltaT; valueAtk = valueAtj; k++; } // Special case for the last coefficients: (k=n-1) int n = gridPointCount - 1; double b_n = -(nextDeltaT * (m_SplineEvaluator.GridPointValues[n - 1] - m_SplineEvaluator.GridPointValues[n - 2]) / deltaT - (2 * m_SplineEvaluator.GridPointArguments[n] - m_SplineEvaluator.GridPointArguments[n - 1] - m_SplineEvaluator.GridPointArguments[n - 2]) * (m_SplineEvaluator.GridPointValues[n] - m_SplineEvaluator.GridPointValues[n - 1]) / nextDeltaT) / (m_SplineEvaluator.GridPointArguments[n] - m_SplineEvaluator.GridPointArguments[n - 2]); double m_n = (m_SplineEvaluator.GridPointValues[n] - m_SplineEvaluator.GridPointValues[n - 1]) / nextDeltaT; coefficientsB[k] = b; coefficientsC[k] = (3 * m_n - b_n - 2 * b) / deltaT; coefficientsD[k] = (b_n + b - 2 * m_n) / (deltaT * deltaT); }
/// <summary>Updates the current curve fitting object. /// </summary> /// <param name="gridPointCount">The number of grid points, i.e. the number of relevant elements of gridPointArguments and gridPointValues to take into account.</param> /// <param name="gridPointArguments">The arguments of the grid points, thus labels of the curve in its <see cref="System.Double"/> representation in ascending order.</param> /// <param name="gridPointValues">The values of the grid points corresponding to gridPointArguments.</param> /// <param name="state">The state of the grid points, i.e. gridPointArguments and gridPointValues, with respect to the previous function call.</param> /// <param name="gridPointArgumentStartIndex">The null-based start index of gridPointArguments to take into account.</param> /// <param name="gridPointValueStartIndex">The null-based start index of gridPointValues to take into account.</param> /// <param name="gridPointArgumentIncrement">The increment for <paramref name="gridPointArguments"/>.</param> /// <param name="gridPointValueIncrement">The increment for <paramref name="gridPointValues"/>.</param> /// <remarks>This method should be called if grid points have been changed, added, removed etc. and before evaluating the grid point curve at a specified point. /// <para>If no problem occurred, the flag <see cref="IOperable.IsOperable"/> will be set to <c>true</c>.</para> /// </remarks> public void Update(int gridPointCount, IList <double> gridPointArguments, IList <double> gridPointValues, GridPointCurve.State state = GridPointCurve.State.GridPointChanged, int gridPointArgumentStartIndex = 0, int gridPointValueStartIndex = 0, int gridPointArgumentIncrement = 1, int gridPointValueIncrement = 1) { int n = gridPointCount - 1; if (n >= 3) { m_BoundaryCondition.Update(gridPointCount, gridPointArguments, gridPointValues, state, gridPointArgumentStartIndex, gridPointValueStartIndex, gridPointArgumentIncrement, gridPointValueIncrement); m_SplineEvaluator.Update(gridPointCount, gridPointArguments, gridPointValues, state, out double[] coefficientsB, out double[] coefficientsC, out double[] coefficientsD, gridPointArgumentStartIndex, gridPointValueStartIndex, gridPointArgumentIncrement, gridPointValueIncrement); double b = m_BoundaryCondition.GetFirstBoundaryCoefficient(); int gridPointValueIndex = gridPointValueStartIndex; int gridPointArgumentIndex = gridPointArgumentStartIndex; double deltaT = m_SplineEvaluator.GridPointArguments[gridPointArgumentIndex + gridPointArgumentIncrement] - m_SplineEvaluator.GridPointArguments[gridPointArgumentIndex]; // = t_{j+1} - t_j double nextDeltaT; // = t_{j+2} - t_{j+1} double m = (m_SplineEvaluator.GridPointValues[gridPointValueIndex + gridPointValueIncrement] - m_SplineEvaluator.GridPointValues[gridPointValueIndex]) / deltaT; int k = 0; // k is just the shortcut for j-1, i.e. k = j-1 double next_m = 0.0; // assiment is needed for the compiler only. for (int j = 1; j < n; j++) { gridPointValueIndex += gridPointValueIncrement; gridPointArgumentIndex += gridPointArgumentIncrement; nextDeltaT = m_SplineEvaluator.GridPointArguments[gridPointArgumentIndex + gridPointArgumentIncrement] - m_SplineEvaluator.GridPointArguments[gridPointArgumentIndex]; next_m = (m_SplineEvaluator.GridPointValues[gridPointValueIndex + gridPointValueIncrement] - m_SplineEvaluator.GridPointValues[gridPointValueIndex]) / nextDeltaT; double nextB = 0.0; if (m * next_m > 0.0) // locally monotone { double max = Math.Max(m, next_m); double min = Math.Min(m, next_m); nextB = 3.0 * m * next_m / (max + min + min); if (min > 0.0) // locally increasing { nextB = Math.Min(Math.Max(0.0, nextB), 3.0 * min); } else if (max < 0.0) { nextB = Math.Max(Math.Min(0.0, nextB), 3.0 * max); } } coefficientsB[k] = b; coefficientsC[k] = (3.0 * m - nextB - b - b) / deltaT; coefficientsD[k] = (nextB + b - m - m) / (deltaT * deltaT); b = nextB; deltaT = nextDeltaT; m = next_m; k++; } // Special case for the last coefficients, i.e. 'b_n': b = m_BoundaryCondition.GetLastBoundaryCoefficient(); coefficientsB[k] = b; coefficientsC[k] = (3.0 * next_m - b - b) / deltaT; coefficientsD[k] = (b - next_m - next_m) / (deltaT * deltaT); } }