#include "lu_internal.h"
#include "lu_list.h"
#include "lu_file.h"
#include "lu_timer.h"
#define MAXROW_SMALL 64
static lu_int lu_pivot_any(struct lu *this);
static lu_int lu_pivot_small(struct lu *this);
static lu_int lu_pivot_singleton_row(struct lu *this);
static lu_int lu_pivot_singleton_col(struct lu *this);
static lu_int lu_pivot_doubleton_col(struct lu *this);
static void lu_remove_col(struct lu *this, lu_int j);
lu_int lu_pivot(struct lu *this)
{
const lu_int m = this->m;
const lu_int rank = this->rank;
const lu_int Lmem = this->Lmem;
const lu_int Umem = this->Umem;
const lu_int pivot_col = this->pivot_col;
const lu_int pivot_row = this->pivot_row;
const double *colmax = this->col_pivot;
const lu_int *Lbegin_p = this->Lbegin_p;
const lu_int *Ubegin = this->Ubegin;
const lu_int *Wbegin = this->Wbegin;
const lu_int *Wend = this->Wend;
const lu_int *Uindex = this->Uindex;
const lu_int nz_col = Wend[pivot_col] - Wbegin[pivot_col];
const lu_int nz_row = Wend[m+pivot_row] - Wbegin[m+pivot_row];
lu_int room, need, pos, j;
lu_int status = BASICLU_OK;
double tic[2];
lu_tic(tic);
assert(nz_row >= 1);
assert(nz_col >= 1);
room = Lmem - Lbegin_p[rank];
need = nz_col;
if (room < need)
{
this->addmemL = need-room;
status = BASICLU_REALLOCATE;
}
room = Umem - Ubegin[rank];
need = nz_row-1;
if (room < need)
{
this->addmemU = need-room;
status = BASICLU_REALLOCATE;
}
if (status != BASICLU_OK)
return status;
if (nz_row == 1)
{
status = lu_pivot_singleton_row(this);
}
else if (nz_col == 1)
{
status = lu_pivot_singleton_col(this);
}
else if (nz_col == 2)
{
status = lu_pivot_doubleton_col(this);
}
else if (nz_col-1 <= MAXROW_SMALL)
{
status = lu_pivot_small(this);
}
else
{
status = lu_pivot_any(this);
}
if (status == BASICLU_OK)
{
for (pos = Ubegin[rank]; pos < Ubegin[rank+1]; pos++)
{
j = Uindex[pos];
assert(j != pivot_col);
if (colmax[j] == 0.0 || colmax[j] < this->abstol)
lu_remove_col(this, j);
}
}
this->factor_flops += (nz_col-1) * (nz_row-1);
this->time_elim_pivot += lu_toc(tic);
return status;
}
static lu_int lu_pivot_any(struct lu *this)
{
const lu_int m = this->m;
const lu_int rank = this->rank;
const double droptol = this->droptol;
const lu_int pad = this->pad;
const double stretch = this->stretch;
const lu_int pivot_col = this->pivot_col;
const lu_int pivot_row = this->pivot_row;
lu_int *colcount_flink = this->colcount_flink;
lu_int *colcount_blink = this->colcount_blink;
lu_int *rowcount_flink = this->rowcount_flink;
lu_int *rowcount_blink = this->rowcount_blink;
double *colmax = this->col_pivot;
lu_int *Lbegin_p = this->Lbegin_p;
lu_int *Ubegin = this->Ubegin;
lu_int *Wbegin = this->Wbegin;
lu_int *Wend = this->Wend;
lu_int *Wflink = this->Wflink;
lu_int *Wblink = this->Wblink;
lu_int *Lindex = this->Lindex;
double *Lvalue = this->Lvalue;
lu_int *Uindex = this->Uindex;
double *Uvalue = this->Uvalue;
lu_int *Windex = this->Windex;
double *Wvalue = this->Wvalue;
lu_int *marked = this->iwork0;
double *work = this->work0;
lu_int cbeg = Wbegin[pivot_col];
lu_int cend = Wend[pivot_col];
lu_int rbeg = Wbegin[m+pivot_row];
lu_int rend = Wend[m+pivot_row];
const lu_int cnz1 = cend-cbeg-1;
const lu_int rnz1 = rend-rbeg-1;
lu_int i, j, pos, pos1, rpos, put, Uput, where, nz, *wi;
lu_int grow, room, found, position;
double pivot, a, x, cmx, xrj, *wx;
grow = 0;
where = -1;
for (pos = cbeg; pos < cend; pos++)
{
if ((i = Windex[pos]) == pivot_row)
where = pos;
else
{
nz = Wend[m+i] - Wbegin[m+i];
grow += nz+rnz1 + stretch*(nz+rnz1) + pad;
}
}
assert(where >= 0);
lu_iswap(Windex, cbeg, where);
lu_fswap(Wvalue, cbeg, where);
pivot = Wvalue[cbeg];
assert(pivot);
where = -1;
for (rpos = rbeg; rpos < rend; rpos++)
{
if ((j = Windex[rpos]) == pivot_col)
where = rpos;
else
{
nz = Wend[j] - Wbegin[j];
grow += nz+cnz1 + stretch*(nz+cnz1) + pad;
}
}
assert(where >= 0);
lu_iswap(Windex, rbeg, where);
room = Wend[2*m] - Wbegin[2*m];
if (grow > room)
{
lu_file_compress(2*m,Wbegin,Wend,Wflink,Windex,Wvalue,stretch,pad);
cbeg = Wbegin[pivot_col];
cend = Wend[pivot_col];
rbeg = Wbegin[m+pivot_row];
rend = Wend[m+pivot_row];
room = Wend[2*m] - Wbegin[2*m];
this->ngarbage++;
}
if (grow > room)
{
this->addmemW = grow-room;
return BASICLU_REALLOCATE;
}
Uput = Ubegin[rank];
assert(Uput >= 0);
assert(Uput < this->Umem);
position = 1;
for (pos = cbeg+1; pos < cend; pos++)
{
i = Windex[pos];
marked[i] = position++;
}
wi = Windex + cbeg;
wx = Wvalue + cbeg;
for (rpos = rbeg+1; rpos < rend; rpos++)
{
j = Windex[rpos];
assert(j != pivot_col);
cmx = 0.0;
where = -1;
put = pos1 = Wbegin[j];
for (pos = pos1; pos < Wend[j]; pos++)
{
i = Windex[pos];
if ((position = marked[i]) > 0)
{
assert(i != pivot_row);
work[position] = Wvalue[pos];
}
else
{
assert(position == 0);
if (i == pivot_row)
where = put;
else if ((x = fabs(Wvalue[pos])) > cmx)
cmx = x;
Windex[put] = Windex[pos];
Wvalue[put++] = Wvalue[pos];
}
}
assert(where >= 0);
Wend[j] = put;
lu_iswap(Windex, pos1, where);
lu_fswap(Wvalue, pos1, where);
xrj = Wvalue[pos1];
room = Wbegin[Wflink[j]] - put;
if (room < cnz1)
{
nz = Wend[j] - Wbegin[j];
room = cnz1 + stretch*(nz+cnz1) + pad;
lu_file_reappend(j, 2*m, Wbegin, Wend, Wflink, Wblink, Windex,
Wvalue, room);
put = Wend[j];
assert(Wbegin[Wflink[j]] - put == room);
this->nexpand++;
}
a = xrj/pivot;
for (pos = 1; pos <= cnz1; pos++)
work[pos] -= a * wx[pos];
for (pos = 1; pos <= cnz1; pos++)
{
Windex[put] = wi[pos];
Wvalue[put++] = work[pos];
if ((x = fabs(work[pos])) > cmx)
cmx = x;
work[pos] = 0.0;
}
Wend[j] = put;
if (fabs(xrj) > droptol)
{
assert(Uput < this->Umem);
Uindex[Uput] = j;
Uvalue[Uput++] = xrj;
}
assert(Windex[Wbegin[j]] == pivot_row);
Wbegin[j]++;
nz = Wend[j] - Wbegin[j];
lu_list_move(j, nz, colcount_flink, colcount_blink, m,
&this->min_colnz);
colmax[j] = cmx;
}
for (pos = cbeg+1; pos < cend; pos++)
marked[Windex[pos]] = 0;
for (rpos = rbeg; rpos < rend; rpos++)
marked[Windex[rpos]] = 1;
assert(marked[pivot_col] == 1);
for (pos = cbeg+1; pos < cend; pos++)
{
i = Windex[pos];
assert(i != pivot_row);
found = 0;
put = Wbegin[m+i];
for (rpos = Wbegin[m+i]; rpos < Wend[m+i]; rpos++)
{
if ((j = Windex[rpos]) == pivot_col)
found = 1;
if (!marked[j])
Windex[put++] = j;
}
assert(found);
Wend[m+i] = put;
room = Wbegin[Wflink[m+i]] - put;
if (room < rnz1)
{
nz = Wend[m+i] - Wbegin[m+i];
room = rnz1 + stretch*(nz+rnz1) + pad;
lu_file_reappend(m+i, 2*m, Wbegin, Wend, Wflink, Wblink, Windex,
Wvalue, room);
put = Wend[m+i];
assert(Wbegin[Wflink[m+i]] - put == room);
this->nexpand++;
}
for (rpos = rbeg+1; rpos < rend; rpos++)
Windex[put++] = Windex[rpos];
Wend[m+i] = put;
nz = Wend[m+i] - Wbegin[m+i];
lu_list_move(i, nz, rowcount_flink, rowcount_blink, m,
&this->min_rownz);
}
for (rpos = rbeg; rpos < rend; rpos++)
marked[Windex[rpos]] = 0;
put = Lbegin_p[rank];
for (pos = cbeg+1; pos < cend; pos++)
{
x = Wvalue[pos] / pivot;
if (fabs(x) > droptol)
{
Lindex[put] = Windex[pos];
Lvalue[put++] = x;
}
}
Lindex[put++] = -1;
Lbegin_p[rank+1] = put;
Ubegin[rank+1] = Uput;
colmax[pivot_col] = pivot;
Wend[pivot_col] = cbeg;
Wend[m+pivot_row] = rbeg;
lu_list_remove(colcount_flink, colcount_blink, pivot_col);
lu_list_remove(rowcount_flink, rowcount_blink, pivot_row);
#ifdef DEBUG_EXTRA
assert(lu_file_diff(m, Wbegin+m, Wend+m, Wbegin, Wend, Windex, NULL) == 0);
assert(lu_file_diff(m, Wbegin, Wend, Wbegin+m, Wend+m, Windex, NULL) == 0);
#endif
return BASICLU_OK;
}
static lu_int lu_pivot_small(struct lu *this)
{
const lu_int m = this->m;
const lu_int rank = this->rank;
const double droptol = this->droptol;
const lu_int pad = this->pad;
const double stretch = this->stretch;
const lu_int pivot_col = this->pivot_col;
const lu_int pivot_row = this->pivot_row;
lu_int *colcount_flink = this->colcount_flink;
lu_int *colcount_blink = this->colcount_blink;
lu_int *rowcount_flink = this->rowcount_flink;
lu_int *rowcount_blink = this->rowcount_blink;
double *colmax = this->col_pivot;
lu_int *Lbegin_p = this->Lbegin_p;
lu_int *Ubegin = this->Ubegin;
lu_int *Wbegin = this->Wbegin;
lu_int *Wend = this->Wend;
lu_int *Wflink = this->Wflink;
lu_int *Wblink = this->Wblink;
lu_int *Lindex = this->Lindex;
double *Lvalue = this->Lvalue;
lu_int *Uindex = this->Uindex;
double *Uvalue = this->Uvalue;
lu_int *Windex = this->Windex;
double *Wvalue = this->Wvalue;
lu_int *marked = this->iwork0;
double *work = this->work0;
int64_t *cancelled = (void *) this->row_pivot;
lu_int cbeg = Wbegin[pivot_col];
lu_int cend = Wend[pivot_col];
lu_int rbeg = Wbegin[m+pivot_row];
lu_int rend = Wend[m+pivot_row];
const lu_int cnz1 = cend-cbeg-1;
const lu_int rnz1 = rend-rbeg-1;
lu_int i, j, pos, pos1, rpos, put, Uput, where, nz, *wi;
lu_int grow, room, found, position, col_number;
double pivot, a, x, cmx, xrj, *wx;
int64_t mask;
assert(cnz1 <= MAXROW_SMALL);
grow = 0;
where = -1;
for (pos = cbeg; pos < cend; pos++)
{
if ((i = Windex[pos]) == pivot_row)
where = pos;
else
{
nz = Wend[m+i] - Wbegin[m+i];
grow += nz+rnz1 + stretch*(nz+rnz1) + pad;
}
}
assert(where >= 0);
lu_iswap(Windex, cbeg, where);
lu_fswap(Wvalue, cbeg, where);
pivot = Wvalue[cbeg];
assert(pivot);
where = -1;
for (rpos = rbeg; rpos < rend; rpos++)
{
if ((j = Windex[rpos]) == pivot_col)
where = rpos;
else
{
nz = Wend[j] - Wbegin[j];
grow += nz+cnz1 + stretch*(nz+cnz1) + pad;
}
}
assert(where >= 0);
lu_iswap(Windex, rbeg, where);
room = Wend[2*m] - Wbegin[2*m];
if (grow > room)
{
lu_file_compress(2*m,Wbegin,Wend,Wflink,Windex,Wvalue,stretch,pad);
cbeg = Wbegin[pivot_col];
cend = Wend[pivot_col];
rbeg = Wbegin[m+pivot_row];
rend = Wend[m+pivot_row];
room = Wend[2*m] - Wbegin[2*m];
this->ngarbage++;
}
if (grow > room)
{
this->addmemW = grow-room;
return BASICLU_REALLOCATE;
}
Uput = Ubegin[rank];
assert(Uput >= 0);
assert(Uput < this->Umem);
position = 1;
for (pos = cbeg+1; pos < cend; pos++)
{
i = Windex[pos];
marked[i] = position++;
}
wi = Windex + cbeg;
wx = Wvalue + cbeg;
col_number = 0;
for (rpos = rbeg+1; rpos < rend; rpos++, col_number++)
{
j = Windex[rpos];
assert(j != pivot_col);
cmx = 0.0;
where = -1;
put = pos1 = Wbegin[j];
for (pos = pos1; pos < Wend[j]; pos++)
{
i = Windex[pos];
if ((position = marked[i]) > 0)
{
assert(i != pivot_row);
work[position] = Wvalue[pos];
}
else
{
assert(position == 0);
if (i == pivot_row)
where = put;
else if ((x = fabs(Wvalue[pos])) > cmx)
cmx = x;
Windex[put] = Windex[pos];
Wvalue[put++] = Wvalue[pos];
}
}
assert(where >= 0);
Wend[j] = put;
lu_iswap(Windex, pos1, where);
lu_fswap(Wvalue, pos1, where);
xrj = Wvalue[pos1];
room = Wbegin[Wflink[j]] - put;
if (room < cnz1)
{
nz = Wend[j] - Wbegin[j];
room = cnz1 + stretch*(nz+cnz1) + pad;
lu_file_reappend(j, 2*m, Wbegin, Wend, Wflink, Wblink, Windex,
Wvalue, room);
put = Wend[j];
assert(Wbegin[Wflink[j]] - put == room);
this->nexpand++;
}
a = xrj/pivot;
for (pos = 1; pos <= cnz1; pos++)
work[pos] -= a * wx[pos];
mask = 0;
for (pos = 1; pos <= cnz1; pos++)
{
x = fabs(work[pos]);
if (x > droptol)
{
Windex[put] = wi[pos];
Wvalue[put++] = work[pos];
if (x > cmx)
cmx = x;
}
else
{
mask |= (int64_t) 1 << (pos-1);
}
work[pos] = 0.0;
}
Wend[j] = put;
cancelled[col_number] = mask;
if (fabs(xrj) > droptol)
{
assert(Uput < this->Umem);
Uindex[Uput] = j;
Uvalue[Uput++] = xrj;
}
assert(Windex[Wbegin[j]] == pivot_row);
Wbegin[j]++;
nz = Wend[j] - Wbegin[j];
lu_list_move(j, nz, colcount_flink, colcount_blink, m,
&this->min_colnz);
colmax[j] = cmx;
}
for (pos = cbeg+1; pos < cend; pos++)
marked[Windex[pos]] = 0;
for (rpos = rbeg; rpos < rend; rpos++)
marked[Windex[rpos]] = 1;
assert(marked[pivot_col] == 1);
mask = 1;
for (pos = cbeg+1; pos < cend; pos++, mask <<= 1)
{
assert(mask);
i = Windex[pos];
assert(i != pivot_row);
found = 0;
put = Wbegin[m+i];
for (rpos = Wbegin[m+i]; rpos < Wend[m+i]; rpos++)
{
if ((j = Windex[rpos]) == pivot_col)
found = 1;
if (!marked[j])
Windex[put++] = j;
}
assert(found);
Wend[m+i] = put;
room = Wbegin[Wflink[m+i]] - put;
if (room < rnz1)
{
nz = Wend[m+i] - Wbegin[m+i];
room = rnz1 + stretch*(nz+rnz1) + pad;
lu_file_reappend(m+i, 2*m, Wbegin, Wend, Wflink, Wblink, Windex,
Wvalue, room);
put = Wend[m+i];
assert(Wbegin[Wflink[m+i]] - put == room);
this->nexpand++;
}
col_number = 0;
for (rpos = rbeg+1; rpos < rend; rpos++, col_number++)
{
if (! (cancelled[col_number] & mask))
{
Windex[put++] = Windex[rpos];
}
}
Wend[m+i] = put;
nz = Wend[m+i] - Wbegin[m+i];
lu_list_move(i, nz, rowcount_flink, rowcount_blink, m,
&this->min_rownz);
}
for (rpos = rbeg; rpos < rend; rpos++)
marked[Windex[rpos]] = 0;
put = Lbegin_p[rank];
for (pos = cbeg+1; pos < cend; pos++)
{
x = Wvalue[pos] / pivot;
if (fabs(x) > droptol)
{
Lindex[put] = Windex[pos];
Lvalue[put++] = x;
}
}
Lindex[put++] = -1;
Lbegin_p[rank+1] = put;
Ubegin[rank+1] = Uput;
colmax[pivot_col] = pivot;
Wend[pivot_col] = cbeg;
Wend[m+pivot_row] = rbeg;
lu_list_remove(colcount_flink, colcount_blink, pivot_col);
lu_list_remove(rowcount_flink, rowcount_blink, pivot_row);
#ifdef DEBUG_EXTRA
assert(lu_file_diff(m, Wbegin+m, Wend+m, Wbegin, Wend, Windex, NULL) == 0);
assert(lu_file_diff(m, Wbegin, Wend, Wbegin+m, Wend+m, Windex, NULL) == 0);
#endif
return BASICLU_OK;
}
static lu_int lu_pivot_singleton_row(struct lu *this)
{
const lu_int m = this->m;
const lu_int rank = this->rank;
const double droptol = this->droptol;
const lu_int pivot_col = this->pivot_col;
const lu_int pivot_row = this->pivot_row;
lu_int *colcount_flink = this->colcount_flink;
lu_int *colcount_blink = this->colcount_blink;
lu_int *rowcount_flink = this->rowcount_flink;
lu_int *rowcount_blink = this->rowcount_blink;
double *colmax = this->col_pivot;
lu_int *Lbegin_p = this->Lbegin_p;
lu_int *Ubegin = this->Ubegin;
lu_int *Wbegin = this->Wbegin;
lu_int *Wend = this->Wend;
lu_int *Lindex = this->Lindex;
double *Lvalue = this->Lvalue;
lu_int *Windex = this->Windex;
double *Wvalue = this->Wvalue;
const lu_int cbeg = Wbegin[pivot_col];
const lu_int cend = Wend[pivot_col];
const lu_int rbeg = Wbegin[m+pivot_row];
const lu_int rend = Wend[m+pivot_row];
const lu_int rnz1 = rend-rbeg-1;
lu_int i, pos, put, nz, where;
double pivot, x;
assert(rnz1 == 0);
for (where = cbeg; Windex[where] != pivot_row; where++)
assert(where < cend-1);
pivot = Wvalue[where];
assert(pivot);
put = Lbegin_p[rank];
for (pos = cbeg; pos < cend; pos++)
{
x = Wvalue[pos] / pivot;
if (pos != where && fabs(x) > droptol)
{
Lindex[put] = Windex[pos];
Lvalue[put++] = x;
}
}
Lindex[put++] = -1;
Lbegin_p[rank+1] = put;
Ubegin[rank+1] = Ubegin[rank];
for (pos = cbeg; pos < cend; pos++)
{
i = Windex[pos];
if (i == pivot_row)
continue;
for (where = Wbegin[m+i]; Windex[where] != pivot_col; where++)
assert(where < Wend[m+i]-1);
Windex[where] = Windex[--Wend[m+i]];
nz = Wend[m+i] - Wbegin[m+i];
lu_list_move(i, nz, rowcount_flink, rowcount_blink, m,
&this->min_rownz);
}
colmax[pivot_col] = pivot;
Wend[pivot_col] = cbeg;
Wend[m+pivot_row] = rbeg;
lu_list_remove(colcount_flink, colcount_blink, pivot_col);
lu_list_remove(rowcount_flink, rowcount_blink, pivot_row);
return BASICLU_OK;
}
static lu_int lu_pivot_singleton_col(struct lu *this)
{
const lu_int m = this->m;
const lu_int rank = this->rank;
const double droptol = this->droptol;
const lu_int pivot_col = this->pivot_col;
const lu_int pivot_row = this->pivot_row;
lu_int *colcount_flink = this->colcount_flink;
lu_int *colcount_blink = this->colcount_blink;
lu_int *rowcount_flink = this->rowcount_flink;
lu_int *rowcount_blink = this->rowcount_blink;
double *colmax = this->col_pivot;
lu_int *Lbegin_p = this->Lbegin_p;
lu_int *Ubegin = this->Ubegin;
lu_int *Wbegin = this->Wbegin;
lu_int *Wend = this->Wend;
lu_int *Lindex = this->Lindex;
lu_int *Uindex = this->Uindex;
double *Uvalue = this->Uvalue;
lu_int *Windex = this->Windex;
double *Wvalue = this->Wvalue;
const lu_int cbeg = Wbegin[pivot_col];
const lu_int cend = Wend[pivot_col];
const lu_int rbeg = Wbegin[m+pivot_row];
const lu_int rend = Wend[m+pivot_row];
const lu_int cnz1 = cend-cbeg-1;
lu_int j, pos, rpos, put, nz, where, found;
double pivot, cmx, x, xrj;
assert(cnz1 == 0);
put = Ubegin[rank];
pivot = Wvalue[cbeg];
assert(pivot);
found = 0;
xrj = 0.0;
for (rpos = rbeg; rpos < rend; rpos++)
{
j = Windex[rpos];
if (j == pivot_col)
{
found = 1;
continue;
}
where = -1;
cmx = 0.0;
for (pos = Wbegin[j]; pos < Wend[j]; pos++)
{
if (Windex[pos] == pivot_row)
{
where = pos;
xrj = Wvalue[pos];
}
else if ((x = fabs(Wvalue[pos])) > cmx)
cmx = x;
}
assert(where >= 0);
if (fabs(xrj) > droptol)
{
Uindex[put] = j;
Uvalue[put++] = xrj;
}
Windex[where] = Windex[--Wend [j]];
Wvalue[where] = Wvalue[Wend [j]];
nz = Wend[j] - Wbegin[j];
lu_list_move(j, nz, colcount_flink, colcount_blink, m,
&this->min_colnz);
colmax[j] = cmx;
}
assert(found);
Ubegin[rank+1] = put;
put = Lbegin_p[rank];
Lindex[put++] = -1;
Lbegin_p[rank+1] = put;
colmax[pivot_col] = pivot;
Wend[pivot_col] = cbeg;
Wend[m+pivot_row] = rbeg;
lu_list_remove(colcount_flink, colcount_blink, pivot_col);
lu_list_remove(rowcount_flink, rowcount_blink, pivot_row);
return BASICLU_OK;
}
static lu_int lu_pivot_doubleton_col(struct lu *this)
{
const lu_int m = this->m;
const lu_int rank = this->rank;
const double droptol = this->droptol;
const lu_int pad = this->pad;
const double stretch = this->stretch;
const lu_int pivot_col = this->pivot_col;
const lu_int pivot_row = this->pivot_row;
lu_int *colcount_flink = this->colcount_flink;
lu_int *colcount_blink = this->colcount_blink;
lu_int *rowcount_flink = this->rowcount_flink;
lu_int *rowcount_blink = this->rowcount_blink;
double *colmax = this->col_pivot;
lu_int *Lbegin_p = this->Lbegin_p;
lu_int *Ubegin = this->Ubegin;
lu_int *Wbegin = this->Wbegin;
lu_int *Wend = this->Wend;
lu_int *Wflink = this->Wflink;
lu_int *Wblink = this->Wblink;
lu_int *Lindex = this->Lindex;
double *Lvalue = this->Lvalue;
lu_int *Uindex = this->Uindex;
double *Uvalue = this->Uvalue;
lu_int *Windex = this->Windex;
double *Wvalue = this->Wvalue;
lu_int *marked = this->iwork0;
lu_int cbeg = Wbegin[pivot_col];
lu_int cend = Wend[pivot_col];
lu_int rbeg = Wbegin[m+pivot_row];
lu_int rend = Wend[m+pivot_row];
const lu_int cnz1 = cend-cbeg-1;
const lu_int rnz1 = rend-rbeg-1;
lu_int j, pos, rpos, put, Uput, nz, nfill, where, where_pivot, where_other;
lu_int other_row, grow, room, space, end, ncancelled;
double pivot, other_value, xrj, cmx, x, xabs;
assert(cnz1 == 1);
if (Windex[cbeg] != pivot_row)
{
lu_iswap(Windex, cbeg, cbeg+1);
lu_fswap(Wvalue, cbeg, cbeg+1);
}
assert(Windex[cbeg] == pivot_row);
pivot = Wvalue[cbeg];
assert(pivot);
other_row = Windex[cbeg+1];
other_value = Wvalue[cbeg+1];
for (where = rbeg; Windex[where] != pivot_col; where++)
assert(where < rend-1);
lu_iswap(Windex, rbeg, where);
nz = Wend[m+other_row] - Wbegin[m+other_row];
grow = nz+rnz1 + stretch*(nz+rnz1) + pad;
room = Wend[2*m] - Wbegin[2*m];
if (grow > room)
{
lu_file_compress(2*m,Wbegin,Wend,Wflink,Windex,Wvalue,stretch,pad);
cbeg = Wbegin[pivot_col];
cend = Wend[pivot_col];
rbeg = Wbegin[m+pivot_row];
rend = Wend[m+pivot_row];
room = Wend[2*m] - Wbegin[2*m];
this->ngarbage++;
}
if (grow > room)
{
this->addmemW = grow-room;
return BASICLU_REALLOCATE;
}
Uput = Ubegin[rank];
put = rbeg+1;
ncancelled = 0;
for (rpos = rbeg+1; rpos < rend; rpos++)
{
j = Windex[rpos];
assert(j != pivot_col);
cmx = 0.0;
where_pivot = -1;
where_other = -1;
end = Wend[j];
for (pos = Wbegin[j]; pos < end; pos++)
{
if (Windex[pos] == pivot_row)
where_pivot = pos;
else if (Windex[pos] == other_row)
where_other = pos;
else if ((x = fabs(Wvalue[pos])) > cmx)
cmx = x;
}
assert(where_pivot >= 0);
xrj = Wvalue[where_pivot];
if (fabs(Wvalue[where_pivot]) > droptol)
{
Uindex[Uput] = j;
Uvalue[Uput++] = Wvalue[where_pivot];
}
if (where_other == -1)
{
x = -xrj * (other_value / pivot);
xabs = fabs(x);
if (xabs > droptol)
{
Windex[where_pivot] = other_row;
Wvalue[where_pivot] = x;
Windex[put++] = j;
if (xabs > cmx)
cmx = xabs;
}
else
{
end = --Wend[j];
Windex[where_pivot] = Windex[end];
Wvalue[where_pivot] = Wvalue[end];
nz = end - Wbegin[j];
lu_list_move(j, nz, colcount_flink, colcount_blink, m,
&this->min_colnz);
}
}
else
{
end = --Wend[j];
Windex[where_pivot] = Windex[end];
Wvalue[where_pivot] = Wvalue[end];
if (where_other == end)
where_other = where_pivot;
Wvalue[where_other] -= xrj * (other_value/pivot);
x = fabs(Wvalue[where_other]);
if (x <= droptol)
{
end = --Wend[j];
Windex[where_other] = Windex[end];
Wvalue[where_other] = Wvalue[end];
marked[j] = 1;
ncancelled++;
}
else if (x > cmx)
cmx = x;
nz = Wend[j] - Wbegin[j];
lu_list_move(j, nz, colcount_flink, colcount_blink, m,
&this->min_colnz);
}
colmax[j] = cmx;
}
rend = put;
Ubegin[rank+1] = Uput;
if (ncancelled)
{
assert(marked[pivot_col] == 0);
marked[pivot_col] = 1;
put = Wbegin[m+other_row];
end = Wend[m+other_row];
for (pos = put; pos < end; pos++)
{
j = Windex[pos];
if (marked[j])
marked[j] = 0;
else
Windex[put++] = j;
}
assert(end-put == ncancelled+1);
Wend[m+other_row] = put;
}
else
{
for (where = Wbegin[m+other_row]; Windex[where] != pivot_col; where++)
assert (where < Wend[m+other_row]-1);
end = --Wend[m+other_row];
Windex[where] = Windex[end];
}
nfill = rend - (rbeg+1);
room = Wbegin[Wflink [m+other_row]] - Wend[m+other_row];
if (nfill > room)
{
nz = Wend[m+other_row] - Wbegin[m+other_row];
space = nfill + stretch*(nz+nfill) + pad;
lu_file_reappend(m+other_row, 2*m, Wbegin, Wend, Wflink, Wblink,
Windex, Wvalue, space);
this->nexpand++;
}
put = Wend[m+other_row];
for (pos = rbeg+1; pos < rend; pos++)
Windex[put++] = Windex[pos];
Wend[m+other_row] = put;
nz = Wend[m+other_row] - Wbegin[m+other_row];
lu_list_move(other_row, nz, rowcount_flink, rowcount_blink, m,
&this->min_rownz);
put = Lbegin_p[rank];
x = other_value / pivot;
if (fabs(x) > droptol)
{
Lindex[put] = other_row;
Lvalue[put++] = x;
}
Lindex[put++] = -1;
Lbegin_p[rank+1] = put;
colmax[pivot_col] = pivot;
Wend[pivot_col] = cbeg;
Wend[m+pivot_row] = rbeg;
lu_list_remove(colcount_flink, colcount_blink, pivot_col);
lu_list_remove(rowcount_flink, rowcount_blink, pivot_row);
#ifdef DEBUG_EXTRA
assert(lu_file_diff(m, Wbegin+m, Wend+m, Wbegin, Wend, Windex, NULL) == 0);
assert(lu_file_diff(m, Wbegin, Wend, Wbegin+m, Wend+m, Windex, NULL) == 0);
#endif
return BASICLU_OK;
}
static void lu_remove_col(struct lu *this, lu_int j)
{
const lu_int m = this->m;
lu_int *colcount_flink = this->colcount_flink;
lu_int *colcount_blink = this->colcount_blink;
lu_int *rowcount_flink = this->rowcount_flink;
lu_int *rowcount_blink = this->rowcount_blink;
double *colmax = this->col_pivot;
lu_int *Wbegin = this->Wbegin;
lu_int *Wend = this->Wend;
lu_int *Windex = this->Windex;
const lu_int cbeg = Wbegin[j];
const lu_int cend = Wend[j];
lu_int i, pos, nz, where;
for (pos = cbeg; pos < cend; pos++)
{
i = Windex[pos];
for (where = Wbegin[m+i]; Windex[where] != j; where++)
assert(where < Wend[m+i]-1);
Windex[where] = Windex[--Wend[m+i]];
nz = Wend[m+i] - Wbegin[m+i];
lu_list_move(i, nz, rowcount_flink, rowcount_blink, m,
&this->min_rownz);
}
colmax[j] = 0.0;
Wend[j] = cbeg;
lu_list_move(j, 0, colcount_flink, colcount_blink, m, &this->min_colnz);
}