|
kusano |
7d535a |
/*! @file sp_preorder.c
|
|
kusano |
7d535a |
* \brief Permute and performs functions on columns of orginal matrix
|
|
kusano |
7d535a |
*/
|
|
kusano |
7d535a |
#include "slu_ddefs.h"
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/*! \brief
|
|
kusano |
7d535a |
*
|
|
kusano |
7d535a |
*
|
|
kusano |
7d535a |
* Purpose
|
|
kusano |
7d535a |
* =======
|
|
kusano |
7d535a |
*
|
|
kusano |
7d535a |
* sp_preorder() permutes the columns of the original matrix. It performs
|
|
kusano |
7d535a |
* the following steps:
|
|
kusano |
7d535a |
*
|
|
kusano |
7d535a |
* 1. Apply column permutation perm_c[] to A's column pointers to form AC;
|
|
kusano |
7d535a |
*
|
|
kusano |
7d535a |
* 2. If options->Fact = DOFACT, then
|
|
kusano |
7d535a |
* (1) Compute column elimination tree etree[] of AC'AC;
|
|
kusano |
7d535a |
* (2) Post order etree[] to get a postordered elimination tree etree[],
|
|
kusano |
7d535a |
* and a postorder permutation post[];
|
|
kusano |
7d535a |
* (3) Apply post[] permutation to columns of AC;
|
|
kusano |
7d535a |
* (4) Overwrite perm_c[] with the product perm_c * post.
|
|
kusano |
7d535a |
*
|
|
kusano |
7d535a |
* Arguments
|
|
kusano |
7d535a |
* =========
|
|
kusano |
7d535a |
*
|
|
kusano |
7d535a |
* options (input) superlu_options_t*
|
|
kusano |
7d535a |
* Specifies whether or not the elimination tree will be re-used.
|
|
kusano |
7d535a |
* If options->Fact == DOFACT, this means first time factor A,
|
|
kusano |
7d535a |
* etree is computed, postered, and output.
|
|
kusano |
7d535a |
* Otherwise, re-factor A, etree is input, unchanged on exit.
|
|
kusano |
7d535a |
*
|
|
kusano |
7d535a |
* A (input) SuperMatrix*
|
|
kusano |
7d535a |
* Matrix A in A*X=B, of dimension (A->nrow, A->ncol). The number
|
|
kusano |
7d535a |
* of the linear equations is A->nrow. Currently, the type of A can be:
|
|
kusano |
7d535a |
* Stype = NC or SLU_NCP; Mtype = SLU_GE.
|
|
kusano |
7d535a |
* In the future, more general A may be handled.
|
|
kusano |
7d535a |
*
|
|
kusano |
7d535a |
* perm_c (input/output) int*
|
|
kusano |
7d535a |
* Column permutation vector of size A->ncol, which defines the
|
|
kusano |
7d535a |
* permutation matrix Pc; perm_c[i] = j means column i of A is
|
|
kusano |
7d535a |
* in position j in A*Pc.
|
|
kusano |
7d535a |
* If options->Fact == DOFACT, perm_c is both input and output.
|
|
kusano |
7d535a |
* On output, it is changed according to a postorder of etree.
|
|
kusano |
7d535a |
* Otherwise, perm_c is input.
|
|
kusano |
7d535a |
*
|
|
kusano |
7d535a |
* etree (input/output) int*
|
|
kusano |
7d535a |
* Elimination tree of Pc'*A'*A*Pc, dimension A->ncol.
|
|
kusano |
7d535a |
* If options->Fact == DOFACT, etree is an output argument,
|
|
kusano |
7d535a |
* otherwise it is an input argument.
|
|
kusano |
7d535a |
* Note: etree is a vector of parent pointers for a forest whose
|
|
kusano |
7d535a |
* vertices are the integers 0 to A->ncol-1; etree[root]==A->ncol.
|
|
kusano |
7d535a |
*
|
|
kusano |
7d535a |
* AC (output) SuperMatrix*
|
|
kusano |
7d535a |
* The resulting matrix after applied the column permutation
|
|
kusano |
7d535a |
* perm_c[] to matrix A. The type of AC can be:
|
|
kusano |
7d535a |
* Stype = SLU_NCP; Dtype = A->Dtype; Mtype = SLU_GE.
|
|
kusano |
7d535a |
*
|
|
kusano |
7d535a |
*/
|
|
kusano |
7d535a |
void
|
|
kusano |
7d535a |
sp_preorder(superlu_options_t *options, SuperMatrix *A, int *perm_c,
|
|
kusano |
7d535a |
int *etree, SuperMatrix *AC)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
NCformat *Astore;
|
|
kusano |
7d535a |
NCPformat *ACstore;
|
|
kusano |
7d535a |
int *iwork, *post;
|
|
kusano |
7d535a |
register int n, i;
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
n = A->ncol;
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/* Apply column permutation perm_c to A's column pointers so to
|
|
kusano |
7d535a |
obtain NCP format in AC = A*Pc. */
|
|
kusano |
7d535a |
AC->Stype = SLU_NCP;
|
|
kusano |
7d535a |
AC->Dtype = A->Dtype;
|
|
kusano |
7d535a |
AC->Mtype = A->Mtype;
|
|
kusano |
7d535a |
AC->nrow = A->nrow;
|
|
kusano |
7d535a |
AC->ncol = A->ncol;
|
|
kusano |
7d535a |
Astore = A->Store;
|
|
kusano |
7d535a |
ACstore = AC->Store = (void *) SUPERLU_MALLOC( sizeof(NCPformat) );
|
|
kusano |
7d535a |
if ( !ACstore ) ABORT("SUPERLU_MALLOC fails for ACstore");
|
|
kusano |
7d535a |
ACstore->nnz = Astore->nnz;
|
|
kusano |
7d535a |
ACstore->nzval = Astore->nzval;
|
|
kusano |
7d535a |
ACstore->rowind = Astore->rowind;
|
|
kusano |
7d535a |
ACstore->colbeg = (int*) SUPERLU_MALLOC(n*sizeof(int));
|
|
kusano |
7d535a |
if ( !(ACstore->colbeg) ) ABORT("SUPERLU_MALLOC fails for ACstore->colbeg");
|
|
kusano |
7d535a |
ACstore->colend = (int*) SUPERLU_MALLOC(n*sizeof(int));
|
|
kusano |
7d535a |
if ( !(ACstore->colend) ) ABORT("SUPERLU_MALLOC fails for ACstore->colend");
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
#ifdef DEBUG
|
|
kusano |
7d535a |
print_int_vec("pre_order:", n, perm_c);
|
|
kusano |
7d535a |
check_perm("Initial perm_c", n, perm_c);
|
|
kusano |
7d535a |
#endif
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
for (i = 0; i < n; i++) {
|
|
kusano |
7d535a |
ACstore->colbeg[perm_c[i]] = Astore->colptr[i];
|
|
kusano |
7d535a |
ACstore->colend[perm_c[i]] = Astore->colptr[i+1];
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
if ( options->Fact == DOFACT ) {
|
|
kusano |
7d535a |
#undef ETREE_ATplusA
|
|
kusano |
7d535a |
#ifdef ETREE_ATplusA
|
|
kusano |
7d535a |
/*--------------------------------------------
|
|
kusano |
7d535a |
COMPUTE THE ETREE OF Pc*(A'+A)*Pc'.
|
|
kusano |
7d535a |
--------------------------------------------*/
|
|
kusano |
7d535a |
int *b_colptr, *b_rowind, bnz, j;
|
|
kusano |
7d535a |
int *c_colbeg, *c_colend;
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/*printf("Use etree(A'+A)\n");*/
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/* Form B = A + A'. */
|
|
kusano |
7d535a |
at_plus_a(n, Astore->nnz, Astore->colptr, Astore->rowind,
|
|
kusano |
7d535a |
&bnz, &b_colptr, &b_rowind);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/* Form C = Pc*B*Pc'. */
|
|
kusano |
7d535a |
c_colbeg = (int*) SUPERLU_MALLOC(2*n*sizeof(int));
|
|
kusano |
7d535a |
c_colend = c_colbeg + n;
|
|
kusano |
7d535a |
if (!c_colbeg ) ABORT("SUPERLU_MALLOC fails for c_colbeg/c_colend");
|
|
kusano |
7d535a |
for (i = 0; i < n; i++) {
|
|
kusano |
7d535a |
c_colbeg[perm_c[i]] = b_colptr[i];
|
|
kusano |
7d535a |
c_colend[perm_c[i]] = b_colptr[i+1];
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
for (j = 0; j < n; ++j) {
|
|
kusano |
7d535a |
for (i = c_colbeg[j]; i < c_colend[j]; ++i) {
|
|
kusano |
7d535a |
b_rowind[i] = perm_c[b_rowind[i]];
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/* Compute etree of C. */
|
|
kusano |
7d535a |
sp_symetree(c_colbeg, c_colend, b_rowind, n, etree);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
SUPERLU_FREE(b_colptr);
|
|
kusano |
7d535a |
if ( bnz ) SUPERLU_FREE(b_rowind);
|
|
kusano |
7d535a |
SUPERLU_FREE(c_colbeg);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
#else
|
|
kusano |
7d535a |
/*--------------------------------------------
|
|
kusano |
7d535a |
COMPUTE THE COLUMN ELIMINATION TREE.
|
|
kusano |
7d535a |
--------------------------------------------*/
|
|
kusano |
7d535a |
sp_coletree(ACstore->colbeg, ACstore->colend, ACstore->rowind,
|
|
kusano |
7d535a |
A->nrow, A->ncol, etree);
|
|
kusano |
7d535a |
#endif
|
|
kusano |
7d535a |
#ifdef DEBUG
|
|
kusano |
7d535a |
print_int_vec("etree:", n, etree);
|
|
kusano |
7d535a |
#endif
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/* In symmetric mode, do not do postorder here. */
|
|
kusano |
7d535a |
if ( options->SymmetricMode == NO ) {
|
|
kusano |
7d535a |
/* Post order etree */
|
|
kusano |
7d535a |
post = (int *) TreePostorder(n, etree);
|
|
kusano |
7d535a |
/* for (i = 0; i < n+1; ++i) inv_post[post[i]] = i;
|
|
kusano |
7d535a |
iwork = post; */
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
#ifdef DEBUG
|
|
kusano |
7d535a |
print_int_vec("post:", n+1, post);
|
|
kusano |
7d535a |
check_perm("post", n, post);
|
|
kusano |
7d535a |
#endif
|
|
kusano |
7d535a |
iwork = (int*) SUPERLU_MALLOC((n+1)*sizeof(int));
|
|
kusano |
7d535a |
if ( !iwork ) ABORT("SUPERLU_MALLOC fails for iwork[]");
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/* Renumber etree in postorder */
|
|
kusano |
7d535a |
for (i = 0; i < n; ++i) iwork[post[i]] = post[etree[i]];
|
|
kusano |
7d535a |
for (i = 0; i < n; ++i) etree[i] = iwork[i];
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
#ifdef DEBUG
|
|
kusano |
7d535a |
print_int_vec("postorder etree:", n, etree);
|
|
kusano |
7d535a |
#endif
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/* Postmultiply A*Pc by post[] */
|
|
kusano |
7d535a |
for (i = 0; i < n; ++i) iwork[post[i]] = ACstore->colbeg[i];
|
|
kusano |
7d535a |
for (i = 0; i < n; ++i) ACstore->colbeg[i] = iwork[i];
|
|
kusano |
7d535a |
for (i = 0; i < n; ++i) iwork[post[i]] = ACstore->colend[i];
|
|
kusano |
7d535a |
for (i = 0; i < n; ++i) ACstore->colend[i] = iwork[i];
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
for (i = 0; i < n; ++i)
|
|
kusano |
7d535a |
iwork[i] = post[perm_c[i]]; /* product of perm_c and post */
|
|
kusano |
7d535a |
for (i = 0; i < n; ++i) perm_c[i] = iwork[i];
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
#ifdef DEBUG
|
|
kusano |
7d535a |
print_int_vec("Pc*post:", n, perm_c);
|
|
kusano |
7d535a |
check_perm("final perm_c", n, perm_c);
|
|
kusano |
7d535a |
#endif
|
|
kusano |
7d535a |
SUPERLU_FREE (post);
|
|
kusano |
7d535a |
SUPERLU_FREE (iwork);
|
|
kusano |
7d535a |
} /* end postordering */
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
} /* if options->Fact == DOFACT ... */
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
int check_perm(char *what, int n, int *perm)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
register int i;
|
|
kusano |
7d535a |
int *marker;
|
|
kusano |
7d535a |
marker = (int *) calloc(n, sizeof(int));
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
for (i = 0; i < n; ++i) {
|
|
kusano |
7d535a |
if ( marker[perm[i]] == 1 || perm[i] >= n ) {
|
|
kusano |
7d535a |
printf("%s: Not a valid PERM[%d] = %d\n", what, i, perm[i]);
|
|
kusano |
7d535a |
ABORT("check_perm");
|
|
kusano |
7d535a |
} else {
|
|
kusano |
7d535a |
marker[perm[i]] = 1;
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
SUPERLU_FREE(marker);
|
|
kusano |
7d535a |
return 0;
|
|
kusano |
7d535a |
}
|