#include "lu_internal.h"
double lu_condest(
lu_int m, const lu_int *Ubegin, const lu_int *Ui, const double *Ux,
const double *pivot, const lu_int *perm, int upper, double *work,
double *norm, double *norminv)
{
lu_int j, p;
double Unorm, Uinvnorm;
Unorm = 0;
for (j = 0; j < m; j++)
{
double colsum = pivot ? fabs(pivot[j]) : 1;
for (p = Ubegin[j]; Ui[p] >= 0; p++)
colsum += fabs(Ux[p]);
Unorm = fmax(Unorm, colsum);
}
Uinvnorm = lu_normest(m, Ubegin, Ui, Ux, pivot, perm, upper, work);
if (norm) *norm = Unorm;
if (norminv) *norminv = Uinvnorm;
return Unorm * Uinvnorm;
}
double lu_normest(
lu_int m, const lu_int *Ubegin, const lu_int *Ui, const double *Ux,
const double *pivot, const lu_int *perm, int upper, double *work)
{
lu_int i, j, k, kbeg, kend, kinc, p;
double x1norm, xinfnorm, y1norm, temp;
x1norm = 0;
xinfnorm = 0;
if (upper)
{
kbeg = 0; kend = m; kinc = 1;
}
else
{
kbeg = m-1; kend = -1; kinc = -1;
}
for (k = kbeg; k != kend; k += kinc)
{
j = perm ? perm[k] : k;
temp = 0;
for (p = Ubegin[j]; (i = Ui[p]) >= 0; p++)
temp -= work[i] * Ux[p];
temp += temp >= 0 ? 1 : -1;
if (pivot) temp /= pivot[j];
work[j] = temp;
x1norm += fabs(temp);
xinfnorm = fmax(xinfnorm, fabs(temp));
}
y1norm = 0;
if (upper)
{
kbeg = m-1; kend = -1; kinc = -1;
}
else
{
kbeg = 0; kend = m; kinc = 1;
}
for (k = kbeg; k != kend; k += kinc)
{
j = perm ? perm[k] : k;
if (pivot) work[j] /= pivot[j];
temp = work[j];
for (p = Ubegin[j]; (i = Ui[p]) >= 0; p++)
work[i] -= temp * Ux[p];
y1norm += fabs(temp);
}
return fmax(y1norm/x1norm, xinfnorm);
}