public override void update()
{
TridiagonalOperator L = new TridiagonalOperator(cH_.n_);
Array<double> tmp = new Array<double>(cH_.n_);
var dx = new Array<double>(cH_.n_ - 1);
var S = new Array<double>(cH_.n_ - 1);
int i=0;
dx[i] = this.xBegin_[i+1] - this.xBegin_[i];
S[i] = (this.yBegin_[i+1] - this.yBegin_[i])/dx[i];
for (i=1; i<cH_.n_-1; ++i) {
dx[i] = this.xBegin_[i+1] - this.xBegin_[i];
S[i] = (this.yBegin_[i+1] - this.yBegin_[i])/dx[i];
L.setMidRow(i, dx[i], 2.0*(dx[i]+dx[i-1]), dx[i-1]);
tmp[i] = 3.0*(dx[i]*S[i-1] + dx[i-1]*S[i]);
}
/**** BOUNDARY CONDITIONS ****/
// left condition
switch (leftType_)
{
case CubicSplineInterpolation.BoundaryCondition.NotAKnot:
// ignoring end condition value
L.setFirstRow(dx[1]*(dx[1]+dx[0]),
(dx[0]+dx[1])*(dx[0]+dx[1]));
tmp[0] = S[0]*dx[1]*(2.0*dx[1]+3.0*dx[0]) +
S[1]*dx[0]*dx[0];
break;
case CubicSplineInterpolation.BoundaryCondition.FirstDerivative:
L.setFirstRow(1.0, 0.0);
tmp[0] = leftValue_;
break;
case CubicSplineInterpolation.BoundaryCondition.SecondDerivative:
L.setFirstRow(2.0, 1.0);
tmp[0] = 3.0*S[0] - leftValue_*dx[0]/2.0;
break;
case CubicSplineInterpolation.BoundaryCondition.Periodic:
case CubicSplineInterpolation.BoundaryCondition.Lagrange:
// ignoring end condition value
throw new ApplicationException("this end condition is not implemented yet");
default:
throw new ApplicationException("unknown end condition");
}
// right condition
switch (rightType_)
{
case CubicSplineInterpolation.BoundaryCondition.NotAKnot:
// ignoring end condition value
L.setLastRow(-(dx[cH_.n_-2]+dx[cH_.n_-3])*(dx[cH_.n_-2]+dx[cH_.n_-3]),
-dx[cH_.n_-3]*(dx[cH_.n_-3]+dx[cH_.n_-2]));
tmp[cH_.n_-1] = -S[cH_.n_-3]*dx[cH_.n_-2]*dx[cH_.n_-2] -
S[cH_.n_-2]*dx[cH_.n_-3]*(3.0*dx[cH_.n_-2]+2.0*dx[cH_.n_-3]);
break;
case CubicSplineInterpolation.BoundaryCondition.FirstDerivative:
L.setLastRow(0.0, 1.0);
tmp[cH_.n_-1] = rightValue_;
break;
case CubicSplineInterpolation.BoundaryCondition.SecondDerivative:
L.setLastRow(1.0, 2.0);
tmp[cH_.n_-1] = 3.0*S[cH_.n_-2] + rightValue_*dx[cH_.n_-2]/2.0;
break;
case CubicSplineInterpolation.BoundaryCondition.Periodic:
case CubicSplineInterpolation.BoundaryCondition.Lagrange:
// ignoring end condition value
throw new ApplicationException("this end condition is not implemented yet");
default:
throw new ApplicationException("unknown end condition");
}
// solve the system
tmp = L.solveFor(tmp);
for (int j = 0; i < cH_.monotonicityAdjustments_.Count; j++ )
cH_.monotonicityAdjustments_[j] = false;
if (constrained_)
{
double correction;
double pm, pu, pd, M;
for (i=0; i<cH_.n_; ++i) {
if (i==0) {
if (tmp[i]*S[0]>0.0)
{
correction = tmp[i]/Math.Abs(tmp[i]) *
Math.Min(Math.Abs(tmp[i]),
Math.Abs(3.0*S[0]));
}
else
{
correction = 0.0;
}
if (correction!=tmp[i])
{
tmp[i] = correction;
cH_.monotonicityAdjustments_[i] = true;
}
}
else if (i==cH_.n_-1)
{
if (tmp[i]*S[cH_.n_-2]>0.0)
{
correction = tmp[i]/Math.Abs(tmp[i]) *
Math.Min(Math.Abs(tmp[i]),
Math.Abs(3.0*S[cH_.n_-2]));
}
else
{
correction = 0.0;
}
if (correction!=tmp[i])
{
tmp[i] = correction;
cH_.monotonicityAdjustments_[i] = true;
}
}
else
{
pm=(S[i-1]*dx[i]+S[i]*dx[i-1])/
(dx[i-1]+dx[i]);
M = 3.0 * Math.Min(Math.Min(Math.Abs(S[i-1]),
Math.Abs(S[i])),
Math.Abs(pm));
if (i>1)
{
if ((S[i-1]-S[i-2])*(S[i]-S[i-1])>0.0)
{
pd=(S[i-1]*(2.0*dx[i-1]+dx[i-2])
-S[i-2]*dx[i-1])/
(dx[i-2]+dx[i-1]);
if (pm*pd>0.0 && pm*(S[i-1]-S[i-2])>0.0)
{
M = Math.Max(M, 1.5*Math.Min(
Math.Abs(pm),Math.Abs(pd)));
}
}
}
if (i<cH_.n_-2)
{
if ((S[i]-S[i-1])*(S[i+1]-S[i])>0.0)
{
pu=(S[i]*(2.0*dx[i]+dx[i+1])-S[i+1]*dx[i])/
(dx[i]+dx[i+1]);
if (pm*pu>0.0 && -pm*(S[i]-S[i-1])>0.0)
{
M = Math.Max(M, 1.5*Math.Min(
Math.Abs(pm),Math.Abs(pu)));
}
}
}
if (tmp[i]*pm>0.0)
{
correction = tmp[i]/Math.Abs(tmp[i]) *
Math.Min(Math.Abs(tmp[i]), M);
}
else
{
correction = 0.0;
}
if (correction!=tmp[i])
{
tmp[i] = correction;
cH_.monotonicityAdjustments_[i] = true;
}
}
}
}
for (i=0; i<cH_.n_-1; ++i)
{
cH_.a_[i] = tmp[i];
cH_.b_[i] = (3.0*S[i] - tmp[i+1] - 2.0*tmp[i])/dx[i];
cH_.c_[i] = (tmp[i+1] + tmp[i] - 2.0*S[i])/(dx[i]*dx[i]);
}
cH_.primitiveConst_[0] = 0.0;
for (i=1; i<cH_.n_-1; ++i)
{
cH_.primitiveConst_[i] = cH_.primitiveConst_[i-1]
+ dx[i-1] *
(this.yBegin_[i-1] + dx[i-1] *
(cH_.a_[i-1]/2.0 + dx[i-1] *
(cH_.b_[i-1]/3.0 + dx[i-1] * cH_.c_[i-1]/4.0)));
}
}