#include "lu_internal.h"
#include "lu_timer.h"
static lu_int singleton_cols
(
const lu_int m,
const lu_int *Bbegin,
const lu_int *Bend,
const lu_int *Bi,
const double *Bx,
const lu_int *Btp,
const lu_int *Bti,
const double *Btx,
lu_int *Up,
lu_int *Ui,
double *Ux,
lu_int *Lp,
lu_int *Li,
double *Lx,
double *col_pivot,
lu_int *pinv,
lu_int *qinv,
lu_int *iset,
lu_int *queue,
lu_int rank,
double abstol
);
static lu_int singleton_rows
(
const lu_int m,
const lu_int *Bbegin,
const lu_int *Bend,
const lu_int *Bi,
const double *Bx,
const lu_int *Btp,
const lu_int *Bti,
const double *Btx,
lu_int *Up,
lu_int *Ui,
double *Ux,
lu_int *Lp,
lu_int *Li,
double *Lx,
double *col_pivot,
lu_int *pinv,
lu_int *qinv,
lu_int *iset,
lu_int *queue,
lu_int rank,
double abstol
);
lu_int lu_singletons(
struct lu *this, const lu_int *Bbegin, const lu_int *Bend, const lu_int *Bi,
const double *Bx)
{
const lu_int m = this->m;
const lu_int Lmem = this->Lmem;
const lu_int Umem = this->Umem;
const lu_int Wmem = this->Wmem;
const double abstol = this->abstol;
const lu_int nzbias = this->nzbias;
lu_int *pinv = this->pinv;
lu_int *qinv = this->qinv;
lu_int *Lbegin_p = this->Lbegin_p;
lu_int *Ubegin = this->Ubegin;
double *col_pivot = this->col_pivot;
lu_int *Lindex = this->Lindex;
double *Lvalue = this->Lvalue;
lu_int *Uindex = this->Uindex;
double *Uvalue = this->Uvalue;
lu_int *iwork1 = this->iwork1;
lu_int *iwork2 = iwork1 + m;
lu_int *Btp = this->Wbegin;
lu_int *Bti = this->Windex;
double *Btx = this->Wvalue;
lu_int i, j, pos, put, rank, Bnz, ok;
double tic[2];
lu_tic(tic);
Bnz = 0;
ok = 1;
for (j = 0; j < m && ok; j++)
{
if (Bend[j] < Bbegin[j])
ok = 0;
else
Bnz += Bend[j] - Bbegin[j];
}
if (!ok)
return BASICLU_ERROR_invalid_argument;
ok = 1;
if (Lmem < Bnz) { this->addmemL = Bnz-Lmem; ok = 0; }
if (Umem < Bnz) { this->addmemU = Bnz-Umem; ok = 0; }
if (Wmem < Bnz) { this->addmemW = Bnz-Wmem; ok = 0; }
if (!ok)
return BASICLU_REALLOCATE;
memset(iwork1, 0, m*sizeof(lu_int));
ok = 1;
for (j = 0; j < m && ok; j++)
{
for (pos = Bbegin[j]; pos < Bend[j] && ok; pos++)
{
i = Bi[pos];
if (i < 0 || i >= m)
ok = 0;
else
iwork1[i]++;
}
}
if (!ok)
return BASICLU_ERROR_invalid_argument;
put = 0;
for (i = 0; i < m; i++)
{
Btp[i] = put;
put += iwork1[i];
iwork1[i] = Btp[i];
}
Btp[m] = put;
assert(put == Bnz);
ok = 1;
for (j = 0; j < m; j++)
{
for (pos = Bbegin[j]; pos < Bend[j]; pos++)
{
i = Bi[pos];
put = iwork1[i]++;
Bti[put] = j;
Btx[put] = Bx [pos];
if (put > Btp[i] && Bti[put-1] == j)
ok = 0;
}
}
if (!ok)
return BASICLU_ERROR_invalid_argument;
for (i = 0; i < m; i++)
pinv[i] = -1;
for (j = 0; j < m; j++)
qinv[j] = -1;
if (nzbias >= 0)
{
Lbegin_p[0] = Ubegin[0] = rank = 0;
rank = singleton_cols(m, Bbegin, Bend, Bi, Bx, Btp, Bti, Btx,
Ubegin, Uindex, Uvalue, Lbegin_p, Lindex, Lvalue,
col_pivot, pinv, qinv, iwork1, iwork2, rank,
abstol);
rank = singleton_rows(m, Bbegin, Bend, Bi, Bx, Btp, Bti, Btx,
Ubegin, Uindex, Uvalue, Lbegin_p, Lindex, Lvalue,
col_pivot, pinv, qinv, iwork1, iwork2, rank,
abstol);
}
else
{
Lbegin_p[0] = Ubegin[0] = rank = 0;
rank = singleton_rows(m, Bbegin, Bend, Bi, Bx, Btp, Bti, Btx,
Ubegin, Uindex, Uvalue, Lbegin_p, Lindex, Lvalue,
col_pivot, pinv, qinv, iwork1, iwork2, rank,
abstol);
rank = singleton_cols(m, Bbegin, Bend, Bi, Bx, Btp, Bti, Btx,
Ubegin, Uindex, Uvalue, Lbegin_p, Lindex, Lvalue,
col_pivot, pinv, qinv, iwork1, iwork2, rank,
abstol);
}
for (i = 0; i < m; i++)
if (pinv[i] < 0)
pinv[i] = -1;
for (j = 0; j < m; j++)
if (qinv[j] < 0)
qinv[j] = -1;
this->matrix_nz = Bnz;
this->rank = rank;
this->time_singletons = lu_toc(tic);
return BASICLU_OK;
}
static lu_int singleton_cols
(
const lu_int m,
const lu_int *Bbegin,
const lu_int *Bend,
const lu_int *Bi,
const double *Bx,
const lu_int *Btp,
const lu_int *Bti,
const double *Btx,
lu_int *Up,
lu_int *Ui,
double *Ux,
lu_int *Lp,
lu_int *Li,
double *Lx,
double *col_pivot,
lu_int *pinv,
lu_int *qinv,
lu_int *iset,
lu_int *queue,
lu_int rank,
double abstol
)
{
lu_int i, j, j2, nz, pos, put, end, front, tail, rk = rank;
double piv;
tail = 0;
for (j = 0; j < m; j++)
{
if (qinv[j] < 0)
{
nz = Bend[j] - Bbegin[j];
i = 0;
for (pos = Bbegin[j]; pos < Bend[j]; pos++)
i ^= Bi[pos];
iset[j] = i;
qinv[j] = -nz-1;
if (nz == 1)
queue[tail++] = j;
}
}
put = Up [rank];
for (front = 0; front < tail; front++)
{
j = queue[front];
assert(qinv[j] == -2 || qinv[j] == -1);
if (qinv[j] == -1)
continue;
i = iset[j];
assert(i >= 0 && i < m);
assert(pinv[i] < 0);
end = Btp[i+1];
for (pos = Btp[i]; Bti[pos] != j; pos++)
assert(pos < end-1);
piv = Btx[pos];
if (!piv || fabs(piv) < abstol)
continue;
qinv[j] = rank;
pinv[i] = rank;
for (pos = Btp[i]; pos < end; pos++)
{
j2 = Bti[pos];
if (qinv[j2] < 0)
{
Ui[put] = j2;
Ux[put++] = Btx[pos];
iset[j2] ^= i;
if (++qinv[j2] == -2)
queue[tail++] = j2;
}
}
Up[rank+1] = put;
col_pivot[j] = piv;
rank++;
}
pos = Lp[rk];
for ( ; rk < rank; rk++)
{
Li[pos++] = -1;
Lp[rk+1] = pos;
}
return rank;
}
static lu_int singleton_rows
(
const lu_int m,
const lu_int *Bbegin,
const lu_int *Bend,
const lu_int *Bi,
const double *Bx,
const lu_int *Btp,
const lu_int *Bti,
const double *Btx,
lu_int *Up,
lu_int *Ui,
double *Ux,
lu_int *Lp,
lu_int *Li,
double *Lx,
double *col_pivot,
lu_int *pinv,
lu_int *qinv,
lu_int *iset,
lu_int *queue,
lu_int rank,
double abstol
)
{
lu_int i, j, i2, nz, pos, put, end, front, tail, rk = rank;
double piv;
tail = 0;
for (i = 0; i < m; i++)
{
if (pinv[i] < 0)
{
nz = Btp[i+1] - Btp[i];
j = 0;
for (pos = Btp[i]; pos < Btp[i+1]; pos++)
j ^= Bti[pos];
iset[i] = j;
pinv[i] = -nz-1;
if (nz == 1)
queue[tail++] = i;
}
}
put = Lp[rank];
for (front = 0; front < tail; front++)
{
i = queue[front];
assert(pinv[i] == -2 || pinv[i] == -1);
if (pinv[i] == -1)
continue;
j = iset [i];
assert(j >= 0 && j < m);
assert(qinv[j] < 0);
end = Bend[j];
for (pos = Bbegin[j]; Bi[pos] != i; pos++)
assert(pos < end-1);
piv = Bx[pos];
if (!piv || fabs(piv) < abstol)
continue;
qinv[j] = rank;
pinv[i] = rank;
for (pos = Bbegin[j]; pos < end; pos++)
{
i2 = Bi[pos];
if (pinv[i2] < 0)
{
Li[put] = i2;
Lx[put++] = Bx[pos] / piv;
iset[i2] ^= j;
if (++pinv[i2] == -2)
queue[tail++] = i2;
}
}
Li[put++] = -1;
Lp[rank+1] = put;
col_pivot[j] = piv;
rank++;
}
pos = Up[rk];
for ( ; rk < rank; rk++)
Up[rk+1] = pos;
return rank;
}