public override Vector evolve(double t0, Vector x0, double dt, Vector dw)
{
/* predictor-corrector step to reduce discretization errors.
*
* Short - but slow - solution would be
*
* Array rnd_0 = stdDeviation(t0, x0, dt)*dw;
* Array drift_0 = discretization_->drift(*this, t0, x0, dt);
*
* return apply(x0, ( drift_0 + discretization_
* ->drift(*this,t0,apply(x0, drift_0 + rnd_0),dt) )*0.5 + rnd_0);
*
* The following implementation does the same but is faster.
*/
int m = nextIndexReset(t0);
double sdt = Math.Sqrt(dt);
Vector f = new Vector(x0);
Matrix diff = lfmParam_.diffusion(t0, x0);
Matrix covariance = lfmParam_.covariance(t0, x0);
for (int k = m; k < size_; ++k)
{
double y = accrualPeriod_[k] * x0[k];
m1[k] = y / (1 + y);
double d = 0;
m1.GetRange(m, k + 1 - m).ForEach(
(ii, vv) => d += vv *
covariance.column(k).GetRange(m, covariance.rows() - m)[ii]);
d = (d - 0.5 * covariance[k, k]) * dt;
double r = 0;
diff.row(k).ForEach((kk, vv) => r += vv * dw[kk]);
r *= sdt;
double x = y * Math.Exp(d + r);
m2[k] = x / (1 + x);
double inner_product = 0;
m2.GetRange(m, k + 1 - m).ForEach(
(ii, vv) => inner_product += vv *
covariance.column(k).GetRange(m, covariance.rows() - m)[ii]);
f[k] = x0[k] * Math.Exp(0.5 * (d + (inner_product - 0.5 * covariance[k, k]) * dt) + r);
}
return(f);
}