/* XXL: The eXtensible and fleXible Library for data processing
Copyright (C) 2000-2011 Prof. Dr. Bernhard Seeger
Head of the Database Research Group
Department of Mathematics and Computer Science
University of Marburg
Germany
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; If not, see <http://www.gnu.org/licenses/>.
http://code.google.com/p/xxl/
*/
package xxl.core.math.numerics.splines;
import xxl.core.util.DoubleArrays;
/**
* This class implements a <tt>cubic Bezier-Spline</tt> with the second boundary condition.
* Thus, the abstract class {@link CubicBezierSpline} is implemented. Since there are most
* of the variables precomputed, this class only implements the method <code>solveLGS</code>.
* This method solves a linear equation system whose solution uniquely determines the Bezier-coefficients.
* For solving the linear equation system, a modified version of the
* {@link xxl.core.math.Maths#triDiagonalGaussianLGS(double[],double[],double[],double[]) Gauss algorithm}
* is used because the system contains a tridiagonal matrix and this permits an efficient computation.
*
* @see xxl.core.math.numerics.splines.CubicBezierSpline
* @see xxl.core.math.numerics.splines.RB1CubicBezierSpline
* @see xxl.core.math.Maths#triDiagonalGaussianLGS(double[],double[],double[],double[])
*/
public class RB2CubicBezierSpline extends CubicBezierSpline {
/**
* Constructs a cubic Bezier-Spline with the second boundary condition
* based upon a grid and the corresponding function
* values. Also the values of the second derivative at the borders are given.
* A flag cdfMode indicates whether the spline is in cdf mode or not,
* i.e., evaluating the spline at x > maximum causes the spline
* to return 1.0 instead of 0.0.
*
* @param grid given grid points
* @param fvalues function values at the grid points
* @param deviation_0 value of the first derivative of f at the left border of the grid
* @param deviation_dim value of the first derivative of f at the right border of the grid
* @param cdfMode indicates spline is in cdf mode
*/
public RB2CubicBezierSpline(
double[] grid,
double[] fvalues,
double deviation_0,
double deviation_dim,
boolean cdfMode) {
super(grid, fvalues, deviation_0, deviation_dim, cdfMode);
}
/**
* Constructs a cubic Bezier-Spline with the second boundary condition
* based upon an equidistant grid and the corresponding function
* values. Also the values of the second derivative at the borders are given.
* A flag cdfMode indicates whether the spline is in cdf Mode or not,
* i.e., evaluating the spline at x > maximum causes the spline
* to return 1.0 instead of 0.0.
*
* @param a left border of the grid
* @param b right border of the grid
* @param n number of grid points
* @param fvalues function values at the grid points
* @param deviation_0 value of the first derivative of f at the left border of the grid
* @param deviation_dim value of the first derivative of f at the right border of the grid
* @param cdfMode indicates spline is in cdf mode
*/
public RB2CubicBezierSpline(
double a,
double b,
int n,
double[] fvalues,
double deviation_0,
double deviation_dim,
boolean cdfMode) {
super(DoubleArrays.equiGrid(a, b, n), fvalues, deviation_0, deviation_dim, cdfMode);
}
/**
* Constructs a cubic Bezier-Spline with the second boundary condition
* based upon a grid and the corresponding function
* values. Also the values of the second derivative at the borders are given.
* Initially, the cdf mode is set to false.
*
* @param grid given grid points
* @param fvalues function values at the grid points
* @param deviation_0 value of the first derivative of f at the left border of the grid
* @param deviation_dim value of the first derivative of f at the right border of the grid
*/
public RB2CubicBezierSpline(double[] grid, double[] fvalues, double deviation_0, double deviation_dim) {
super(grid, fvalues, deviation_0, deviation_dim, false);
}
/**
* Constructs a cubic Bezier-Spline with the second boundary condition
* based upon an equidistant grid and the corresponding function
* values. Also the values of the second derivative at the borders are given.
* Initially, the cdf mode is set to false.
*
* @param a left border of the grid
* @param b right border of the grid
* @param n number of grid points
* @param fvalues function values at the grid points
* @param deviation_0 value of the first derivative of f at the left border of the grid
* @param deviation_dim value of the first derivative of f at the right border of the grid
*/
public RB2CubicBezierSpline(
double a,
double b,
int n,
double[] fvalues,
double deviation_0,
double deviation_dim) {
super(DoubleArrays.equiGrid(a, b, n), fvalues, deviation_0, deviation_dim, false);
}
/**
* Solves the linear system of equations for the second boundary condition with a
* modified algorithm of Gauss.
*
* @return solution of the linear equation system
*/
protected double[] solveLGS() {
double[] a1 = new double[a.length + 1];
double[] b1 = new double[b.length + 1];
for (int i = 0; i < a.length; i++) {
a1[i] = a[i];
b1[i + 1] = b[i];
}
b1[0] = a1[a1.length - 1] = 1; // 2nd border
double[] twoTmp = new double[a1.length + 1];
double[] right = new double[a1.length + 1]; // 2nd border
for (int i = 0; i < twoTmp.length; i++) {
twoTmp[i] = 2;
}
for (int i = 0; i < rightSide.length; i++) {
right[i + 1] = rightSide[i];
}
right[0] =
(fvalues[1] - fvalues[0]) * Math.pow(distance[0] * distance[0], -1)
- deviation[0] * Math.pow(distance[0], -1);
// 2nd border
right[right.length - 1] =
(fvalues[dim - 2] - fvalues[dim - 1]) * Math.pow(distance[dim - 2] * distance[dim - 2], -1)
+ deviation[1] * Math.pow(distance[dim - 2], -1);
// 2nd border
double[] res = xxl.core.math.Maths.triDiagonalGaussianLGS(a1, twoTmp, b1, right);
return res;
}
}