int trcg(double delta, double[] g, double[] s, double[] r)
{
int n = NumberOfVariables;
double[] d = new double[n];
for (int i = 0; i < g.Length; i++)
{
s[i] = 0;
r[i] = -g[i];
d[i] = r[i];
}
double cgtol = 0; // cgtol = 0.1 * dnrm2_(&n, g, &inc);
for (int j = 0; j < g.Length; j++)
cgtol += g[j] * g[j];
cgtol = 0.1 * Math.Sqrt(cgtol);
int cg_iter = 0;
double rTr = 0; // rTr = ddot_(&n, r, &inc, r, &inc);
for (int j = 0; j < r.Length; j++)
rTr += r[j] * r[j];
while (true)
{
// rn = dnrm2_(&n, r, &inc)
double rn = 0;
for (int j = 0; j < r.Length; j++)
rn += r[j] * r[j];
rn = Math.Sqrt(rn);
if (rn <= cgtol)
break;
cg_iter++;
double[] Hd = Hessian(d);
double dHd = 0; // ddot_(&n, d, &inc, Hd, &inc)
for (int j = 0; j < d.Length; j++)
dHd += d[j] * Hd[j];
double alpha = rTr / dHd;
// daxpy_(&n, &alpha, d, &inc, s, &inc);
for (int j = 0; j < d.Length; j++)
s[j] += alpha * d[j];
double sn = 0; // dnrm2_(&n, s, &inc)
for (int j = 0; j < s.Length; j++)
sn += s[j] * s[j];
sn = Math.Sqrt(sn);
if (sn > delta)
{
Trace.WriteLine("cg reaches trust region boundary");
alpha = -alpha;
// daxpy_(&n, &alpha, d, &inc, s, &inc);
for (int j = 0; j < d.Length; j++)
s[j] += alpha * d[j];
double std = 0; // ddot_(&n, s, &inc, d, &inc);
for (int j = 0; j < s.Length; j++)
std += s[j] * d[j];
double sts = 0; // ddot_(&n, s, &inc, s, &inc);
for (int j = 0; j < s.Length; j++)
sts += s[j] * s[j];
double dtd = 0;// ddot_(&n, d, &inc, d, &inc);
for (int j = 0; j < d.Length; j++)
dtd += d[j] * d[j];
double dsq = delta * delta;
double rad = Math.Sqrt(std * std + dtd * (dsq - sts));
if (std >= 0)
alpha = (dsq - sts) / (std + rad);
else
alpha = (rad - std) / dtd;
// daxpy_(&n, &alpha, d, &inc, s, &inc);
for (int j = 0; j < d.Length; j++)
s[j] += alpha * d[j];
alpha = -alpha;
// daxpy_(&n, &alpha, Hd, &inc, r, &inc);
for (int j = 0; j < r.Length; j++)
r[j] += alpha * Hd[j];
break;
}
alpha = -alpha;
// daxpy_(&n, &alpha, Hd, &inc, r, &inc);
for (int j = 0; j < r.Length; j++)
r[j] += alpha * Hd[j];
// ddot_(&n, r, &inc, r, &inc);
double rnewTrnew = 0.0;
for (int j = 0; j < r.Length; j++)
rnewTrnew += r[j] * r[j];
double beta = rnewTrnew / rTr;
// dscal_(&n, &beta, d, &inc);
for (int j = 0; j < d.Length; j++)
d[j] *= beta;
// daxpy_(&n, &one, r, &inc, d, &inc);
for (int j = 0; j < d.Length; j++)
d[j] += r[j];
rTr = rnewTrnew;
}
return cg_iter;
}