Blender  V2.59
sp_preorder.c
Go to the documentation of this file.
00001 
00004 #include "ssp_defs.h"
00005 
00006 int check_perm(char *, int , int *);
00007 
00008 
00009 void
00010 sp_preorder(superlu_options_t *options,  SuperMatrix *A, int *perm_c, 
00011             int *etree, SuperMatrix *AC)
00012 {
00013 /*
00014  * Purpose
00015  * =======
00016  *
00017  * sp_preorder() permutes the columns of the original matrix. It performs
00018  * the following steps:
00019  *
00020  *    1. Apply column permutation perm_c[] to A's column pointers to form AC;
00021  *
00022  *    2. If options->Fact = DOFACT, then
00023  *       (1) Compute column elimination tree etree[] of AC'AC;
00024  *       (2) Post order etree[] to get a postordered elimination tree etree[],
00025  *           and a postorder permutation post[];
00026  *       (3) Apply post[] permutation to columns of AC;
00027  *       (4) Overwrite perm_c[] with the product perm_c * post.
00028  *
00029  * Arguments
00030  * =========
00031  *
00032  * options (input) superlu_options_t*
00033  *         Specifies whether or not the elimination tree will be re-used.
00034  *         If options->Fact == DOFACT, this means first time factor A, 
00035  *         etree is computed, postered, and output.
00036  *         Otherwise, re-factor A, etree is input, unchanged on exit.
00037  *
00038  * A       (input) SuperMatrix*
00039  *         Matrix A in A*X=B, of dimension (A->nrow, A->ncol). The number
00040  *         of the linear equations is A->nrow. Currently, the type of A can be:
00041  *         Stype = NC or SLU_NCP; Mtype = SLU_GE.
00042  *         In the future, more general A may be handled.
00043  *
00044  * perm_c  (input/output) int*
00045  *         Column permutation vector of size A->ncol, which defines the 
00046  *         permutation matrix Pc; perm_c[i] = j means column i of A is 
00047  *         in position j in A*Pc.
00048  *         If options->Fact == DOFACT, perm_c is both input and output.
00049  *         On output, it is changed according to a postorder of etree.
00050  *         Otherwise, perm_c is input.
00051  *
00052  * etree   (input/output) int*
00053  *         Elimination tree of Pc'*A'*A*Pc, dimension A->ncol.
00054  *         If options->Fact == DOFACT, etree is an output argument,
00055  *         otherwise it is an input argument.
00056  *         Note: etree is a vector of parent pointers for a forest whose
00057  *         vertices are the integers 0 to A->ncol-1; etree[root]==A->ncol.
00058  *
00059  * AC      (output) SuperMatrix*
00060  *         The resulting matrix after applied the column permutation
00061  *         perm_c[] to matrix A. The type of AC can be:
00062  *         Stype = SLU_NCP; Dtype = A->Dtype; Mtype = SLU_GE.
00063  *
00064  */
00065 
00066     NCformat  *Astore;
00067     NCPformat *ACstore;
00068     int       *iwork, *post;
00069     register  int n, i;
00070 
00071     n = A->ncol;
00072     
00073     /* Apply column permutation perm_c to A's column pointers so to
00074        obtain NCP format in AC = A*Pc.  */
00075     AC->Stype       = SLU_NCP;
00076     AC->Dtype       = A->Dtype;
00077     AC->Mtype       = A->Mtype;
00078     AC->nrow        = A->nrow;
00079     AC->ncol        = A->ncol;
00080     Astore          = A->Store;
00081     ACstore = AC->Store = (void *) SUPERLU_MALLOC( sizeof(NCPformat) );
00082     if ( !ACstore ) ABORT("SUPERLU_MALLOC fails for ACstore");
00083     ACstore->nnz    = Astore->nnz;
00084     ACstore->nzval  = Astore->nzval;
00085     ACstore->rowind = Astore->rowind;
00086     ACstore->colbeg = (int*) SUPERLU_MALLOC(n*sizeof(int));
00087     if ( !(ACstore->colbeg) ) ABORT("SUPERLU_MALLOC fails for ACstore->colbeg");
00088     ACstore->colend = (int*) SUPERLU_MALLOC(n*sizeof(int));
00089     if ( !(ACstore->colend) ) ABORT("SUPERLU_MALLOC fails for ACstore->colend");
00090 
00091 #ifdef DEBUG
00092     print_int_vec("pre_order:", n, perm_c);
00093     check_perm("Initial perm_c", n, perm_c);
00094 #endif      
00095 
00096     for (i = 0; i < n; i++) {
00097         ACstore->colbeg[perm_c[i]] = Astore->colptr[i]; 
00098         ACstore->colend[perm_c[i]] = Astore->colptr[i+1];
00099     }
00100         
00101     if ( options->Fact == DOFACT ) {
00102 #undef ETREE_ATplusA
00103 #ifdef ETREE_ATplusA
00104         /*--------------------------------------------
00105           COMPUTE THE ETREE OF Pc*(A'+A)*Pc'.
00106           --------------------------------------------*/
00107         int *b_colptr, *b_rowind, bnz, j;
00108         int *c_colbeg, *c_colend;
00109 
00110         /*printf("Use etree(A'+A)\n");*/
00111 
00112         /* Form B = A + A'. */
00113         at_plus_a(n, Astore->nnz, Astore->colptr, Astore->rowind,
00114                   &bnz, &b_colptr, &b_rowind);
00115 
00116         /* Form C = Pc*B*Pc'. */
00117         c_colbeg = (int*) SUPERLU_MALLOC(2*n*sizeof(int));
00118         c_colend = c_colbeg + n;
00119         if (!c_colbeg ) ABORT("SUPERLU_MALLOC fails for c_colbeg/c_colend");
00120         for (i = 0; i < n; i++) {
00121             c_colbeg[perm_c[i]] = b_colptr[i]; 
00122             c_colend[perm_c[i]] = b_colptr[i+1];
00123         }
00124         for (j = 0; j < n; ++j) {
00125             for (i = c_colbeg[j]; i < c_colend[j]; ++i) {
00126                 b_rowind[i] = perm_c[b_rowind[i]];
00127             }
00128         }
00129 
00130         /* Compute etree of C. */
00131         sp_symetree(c_colbeg, c_colend, b_rowind, n, etree);
00132 
00133         SUPERLU_FREE(b_colptr);
00134         if ( bnz ) SUPERLU_FREE(b_rowind);
00135         SUPERLU_FREE(c_colbeg);
00136         
00137 #else
00138         /*--------------------------------------------
00139           COMPUTE THE COLUMN ELIMINATION TREE.
00140           --------------------------------------------*/
00141         sp_coletree(ACstore->colbeg, ACstore->colend, ACstore->rowind,
00142                     A->nrow, A->ncol, etree);
00143 #endif
00144 #ifdef DEBUG    
00145         print_int_vec("etree:", n, etree);
00146 #endif  
00147         
00148         /* In symmetric mode, do not do postorder here. */
00149         if ( options->SymmetricMode == NO ) {
00150             /* Post order etree */
00151             post = (int *) TreePostorder(n, etree);
00152             /* for (i = 0; i < n+1; ++i) inv_post[post[i]] = i;
00153                iwork = post; */
00154 
00155 #ifdef DEBUG
00156             print_int_vec("post:", n+1, post);
00157             check_perm("post", n, post);        
00158 #endif  
00159             iwork = (int*) SUPERLU_MALLOC((n+1)*sizeof(int)); 
00160             if ( !iwork ) ABORT("SUPERLU_MALLOC fails for iwork[]");
00161 
00162             /* Renumber etree in postorder */
00163             for (i = 0; i < n; ++i) iwork[post[i]] = post[etree[i]];
00164             for (i = 0; i < n; ++i) etree[i] = iwork[i];
00165 
00166 #ifdef DEBUG    
00167             print_int_vec("postorder etree:", n, etree);
00168 #endif
00169         
00170             /* Postmultiply A*Pc by post[] */
00171             for (i = 0; i < n; ++i) iwork[post[i]] = ACstore->colbeg[i];
00172             for (i = 0; i < n; ++i) ACstore->colbeg[i] = iwork[i];
00173             for (i = 0; i < n; ++i) iwork[post[i]] = ACstore->colend[i];
00174             for (i = 0; i < n; ++i) ACstore->colend[i] = iwork[i];
00175 
00176             for (i = 0; i < n; ++i)
00177                 iwork[i] = post[perm_c[i]];  /* product of perm_c and post */
00178             for (i = 0; i < n; ++i) perm_c[i] = iwork[i];
00179 
00180 #ifdef DEBUG
00181             print_int_vec("Pc*post:", n, perm_c);
00182             check_perm("final perm_c", n, perm_c);      
00183 #endif
00184             SUPERLU_FREE (post);
00185             SUPERLU_FREE (iwork);
00186         } /* end postordering */
00187 
00188     } /* if options->Fact == DOFACT ... */
00189 
00190 }
00191 
00192 int check_perm(char *what, int n, int *perm)
00193 {
00194     register int i;
00195     int          *marker;
00196     marker = (int *) calloc(n, sizeof(int));
00197 
00198     for (i = 0; i < n; ++i) {
00199         if ( marker[perm[i]] == 1 || perm[i] >= n ) {
00200             printf("%s: Not a valid PERM[%d] = %d\n", what, i, perm[i]);
00201             ABORT("check_perm");
00202         } else {
00203             marker[perm[i]] = 1;
00204         }
00205     }
00206 
00207     SUPERLU_FREE(marker);
00208     return 0;
00209 }