#include "lu_internal.h"
#include "lu_list.h"
#include "lu_timer.h"
lu_int lu_markowitz(struct lu *this)
{
const lu_int m = this->m;
const lu_int *Wbegin = this->Wbegin;
const lu_int *Wend = this->Wend;
const lu_int *Windex = this->Windex;
const double *Wvalue = this->Wvalue;
const lu_int *colcount_flink = this->colcount_flink;
lu_int *rowcount_flink = this->rowcount_flink;
lu_int *rowcount_blink = this->rowcount_blink;
const double *colmax = this->col_pivot;
const double abstol = this->abstol;
const double reltol = this->reltol;
const lu_int maxsearch = this->maxsearch;
const lu_int search_rows = this->search_rows;
const lu_int nz_start = search_rows ?
MIN(this->min_colnz, this->min_rownz) : this->min_colnz;
lu_int i, j, pos, where, inext, nz, pivot_row, pivot_col;
lu_int nsearch, cheap, found, min_colnz, min_rownz;
double cmx, x, tol, tic[2];
const int_least64_t M = m;
int_least64_t nz1, nz2, mc, MC;
lu_tic(tic);
pivot_row = -1;
pivot_col = -1;
MC = M*M;
nsearch = 0;
min_colnz = -1;
min_rownz = -1;
assert(nz_start >= 1);
if (colcount_flink[m] != m)
{
pivot_col = colcount_flink[m];
assert(pivot_col >= 0 && pivot_col < m);
assert(Wend[pivot_col] == Wbegin[pivot_col]);
goto done;
}
for (nz = nz_start; nz <= m; nz++)
{
for (j = colcount_flink[m+nz]; j < m; j = colcount_flink[j])
{
if (min_colnz == -1)
min_colnz = nz;
assert(Wend[j] - Wbegin[j] == nz);
cmx = colmax[j];
assert(cmx >= 0);
if (!cmx || cmx < abstol)
continue;
tol = fmax(abstol, reltol*cmx);
for (pos = Wbegin[j]; pos < Wend[j]; pos++)
{
x = fabs(Wvalue[pos]);
if (!x || x < tol)
continue;
i = Windex[pos];
assert(i >= 0 && i < m);
nz1 = nz;
nz2 = Wend[m+i] - Wbegin[m+i];
assert(nz2 >= 1);
mc = (nz1-1) * (nz2-1);
if (mc < MC)
{
MC = mc;
pivot_row = i;
pivot_col = j;
if (search_rows && MC <= (nz1-1)*(nz1-1))
goto done;
}
}
assert(MC < M*M);
if (++nsearch >= maxsearch)
goto done;
}
assert(j == m+nz);
if (!search_rows)
continue;
for (i = rowcount_flink[m+nz]; i < m; i = inext)
{
if (min_rownz == -1)
min_rownz = nz;
inext = rowcount_flink[i];
assert(Wend[m+i] - Wbegin[m+i] == nz);
cheap = 0;
found = 0;
for (pos = Wbegin[m+i]; pos < Wend[m+i]; pos++)
{
j = Windex[pos];
assert(j >= 0 && j < m);
nz1 = nz;
nz2 = Wend[j] - Wbegin[j];
assert(nz2 >= 1);
mc = (nz1-1) * (nz2-1);
if (mc >= MC)
continue;
cheap = 1;
cmx = colmax[j];
assert(cmx >= 0);
if (!cmx || cmx < abstol)
continue;
for (where = Wbegin[j]; Windex[where] != i; where++)
assert(where < Wend[j] - 1);
x = fabs(Wvalue[where]);
if (x >= abstol && x >= reltol*cmx)
{
found = 1;
MC = mc;
pivot_row = i;
pivot_col = j;
if (MC <= nz1*(nz1-1))
goto done;
}
}
if (cheap && !found)
{
lu_list_move(i, m+1, rowcount_flink, rowcount_blink, m, NULL);
}
else
{
assert(MC < M*M);
if (++nsearch >= maxsearch)
goto done;
}
}
assert(i == m+nz);
}
done:
this->pivot_row = pivot_row;
this->pivot_col = pivot_col;
this->nsearch_pivot += nsearch;
if (min_colnz >= 0)
this->min_colnz = min_colnz;
if (min_rownz >= 0)
this->min_rownz = min_rownz;
this->time_search_pivot += lu_toc(tic);
return BASICLU_OK;
}