void print_int_list(int_list * list, int items_line) { /*int i,k;*/ int_node* p = list->next; printf("Totally %d vectors in list\n", list->ll); int i; for(i = 0; i < list->ll; i++){ printf("[[%d]]:\n", i); int k; print_int_vec(p->value,items_line); p = p->next; } }
int qrnzcnt(int neqns, int adjlen, int *xadj, int *adjncy, int *zfdperm, int *perm, int *invp, int *etpar, int *colcnt_h, int *nlnz, int *part_super_ata, int *part_super_h) { /* o 5/20/95 Xiaoye S. Li: Translated from fcnthn.f using f2c; Modified to use 0-based indexing in C; Initialize xsup = 0 as suggested by B. Peyton to handle singletons. o 5/24/95 Xiaoye S. Li: Modified to compute row/column counts of R in QR factorization 1. Compute row counts of A, and f(i) in a separate pass def 2. Re-define hadj[k] === U { j | j in Struct(A_i*), j>k} i:f(i)==k Record supernode partition in part_super_ata[*] of size neqns: part_super_ata[k] = size of the supernode beginning at column k; = 0, elsewhere. o 1/16/96 Xiaoye S. Li: Modified to incorporate row/column counts of the Householder Matrix H in the QR factorization A --> H , R. Record supernode partition in part_super_h[*] of size neqns: part_super_h[k] = size of the supernode beginning at column k; = 0, elsewhere. *********************************************************************** Version: 0.3 Last modified: January 12, 1995 Authors: Esmond G. Ng and Barry W. Peyton Mathematical Sciences Section, Oak Ridge National Laboratoy *********************************************************************** ************** FCNTHN ..... FIND NONZERO COUNTS *************** *********************************************************************** PURPOSE: THIS SUBROUTINE DETERMINES THE ROW COUNTS AND COLUMN COUNTS IN THE CHOLESKY FACTOR. IT USES A DISJOINT SET UNION ALGORITHM. TECHNIQUES: 1) SUPERNODE DETECTION. 2) PATH HALVING. 3) NO UNION BY RANK. NOTES: 1) ASSUMES A POSTORDERING OF THE ELIMINATION TREE. INPUT PARAMETERS: (I) NEQNS - NUMBER OF EQUATIONS. (I) ADJLEN - LENGTH OF ADJACENCY STRUCTURE. (I) XADJ(*) - ARRAY OF LENGTH NEQNS+1, CONTAINING POINTERS TO THE ADJACENCY STRUCTURE. (I) ADJNCY(*) - ARRAY OF LENGTH ADJLEN, CONTAINING THE ADJACENCY STRUCTURE. (I) ZFDPERM(*) - THE ROW PERMUTATION VECTOR THAT PERMUTES THE MATRIX TO HAVE ZERO-FREE DIAGONAL. ZFDPERM(I) = J MEANS ROW I OF THE ORIGINAL MATRIX IS IN ROW J OF THE PERMUTED MATRIX. (I) PERM(*) - ARRAY OF LENGTH NEQNS, CONTAINING THE POSTORDERING. (I) INVP(*) - ARRAY OF LENGTH NEQNS, CONTAINING THE INVERSE OF THE POSTORDERING. (I) ETPAR(*) - ARRAY OF LENGTH NEQNS, CONTAINING THE ELIMINATION TREE OF THE POSTORDERED MATRIX. OUTPUT PARAMETERS: (I) ROWCNT(*) - ARRAY OF LENGTH NEQNS, CONTAINING THE NUMBER OF NONZEROS IN EACH ROW OF THE FACTOR, INCLUDING THE DIAGONAL ENTRY. (I) COLCNT(*) - ARRAY OF LENGTH NEQNS, CONTAINING THE NUMBER OF NONZEROS IN EACH COLUMN OF THE FACTOR, INCLUDING THE DIAGONAL ENTRY. (I) NLNZ - NUMBER OF NONZEROS IN THE FACTOR, INCLUDING THE DIAGONAL ENTRIES. (I) PART_SUPER_ATA SUPERNODE PARTITION IN THE CHOLESKY FACTOR OF A'A. (I) PART_SUPER_H SUPERNODE PARTITION IN THE HOUSEHOLDER MATRIX H. WORK PARAMETERS: (I) SET(*) - ARRAY OF LENGTH NEQNS USED TO MAINTAIN THE DISJOINT SETS (I.E., SUBTREES). (I) PRVLF(*) - ARRAY OF LENGTH NEQNS USED TO RECORD THE PREVIOUS LEAF OF EACH ROW SUBTREE. (I) LEVEL(*) - ARRAY OF LENGTH NEQNS+1 CONTAINING THE LEVEL (DISTANCE FROM THE ROOT). (I) WEIGHT(*) - ARRAY OF LENGTH NEQNS+1 CONTAINING WEIGHTS USED TO COMPUTE COLUMN COUNTS. (I) FDESC(*) - ARRAY OF LENGTH NEQNS+1 CONTAINING THE FIRST (I.E., LOWEST-NUMBERED) DESCENDANT. (I) NCHILD(*) - ARRAY OF LENGTH NEQNS+1 CONTAINING THE NUMBER OF CHILDREN. (I) PRVNBR(*) - ARRAY OF LENGTH NEQNS USED TO RECORD THE PREVIOUS ``LOWER NEIGHBOR'' OF EACH NODE. FIRST CREATED ON APRIL 12, 1990. LAST UPDATED ON JANUARY 12, 1995. *********************************************************************** */ /* Local variables */ int temp, last1, last2, i, j, k, lflag, pleaf, hinbr, jstop, jstrt, ifdesc, oldnbr, parent, lownbr, lca; int xsup; /* the ongoing supernode */ int *set, *prvlf, *level, *weight, *fdesc, *nchild, *prvnbr; int *fnz; /* first nonzero column subscript in each row */ int *marker; /* used to remove duplicate indices */ int *fnz_hadj; /* higher-numbered neighbors of the first nonzero (higher adjacency set of A'A) */ int *hadj_begin; /* pointers to the fnz_hadj[] structure */ int *hadj_end; /* pointers to the fnz_hadj[] structure */ /* Locally malloc'd room for QR purpose */ /* ---------------------------------------------------------- FIRST set is defined as first[j] := { i : f[i] = j } , which is a collection of disjoint sets of integers between 0 and n-1. ---------------------------------------------------------- */ int *first; /* header pointing to FIRST set */ int *firstset; /* linked list to describe FIRST set */ int *weight_h; /* weights for H */ int *rowcnt; /* row colunts for Lc */ int *colcnt; /* column colunts for Lc */ int *rowcnt_h; /* row colunts for H */ int nsuper; /* total number of fundamental supernodes in Lc */ int nhnz; set = intMalloc(neqns); prvlf = intMalloc(neqns); level = intMalloc(neqns + 1); /* length n+1 */ weight = intMalloc(neqns + 1); /* length n+1 */ fdesc = intMalloc(neqns + 1); /* length n+1 */ nchild = intMalloc(neqns + 1); /* length n+1 */ prvnbr = intMalloc(neqns); fnz_hadj = intMalloc(adjlen + 2*neqns + 1); hadj_begin = fnz_hadj + adjlen; /* neqns+1 */ hadj_end = hadj_begin + neqns + 1; /* neqns */ fnz = set; /* aliasing for the time being */ marker = prvlf; /* " " " */ first = intMalloc(neqns); firstset = intMalloc(neqns); weight_h = intCalloc(neqns + 1); /* length n+1 */ rowcnt_h = intMalloc(neqns); rowcnt = intMalloc(neqns); colcnt = intMalloc(neqns); /* ------------------------------------------------------- * Compute fnz[*], first[*], nchild[*] and row counts of A. * Also find supernodes in H. * * Note that the structure of each row of H forms a simple path in * the etree between fnz[i] and i (George, Liu & Ng (1988)). * The "first vertices" of the supernodes in H are characterized * by the following conditions: * 1) first nonzero in each row of A, i.e., fnz(i); * or 2) nchild >= 2; * ------------------------------------------------------- */ for (k = 0; k < neqns; ++k) { fnz[k] = first[k] = marker[k] = EMPTY; rowcnt[k] = part_super_ata[k] = 0; part_super_h[k] = 0; nchild[k] = 0; } nchild[ROOT] = 0; xsup = 0; for (k = 0; k < neqns; ++k) { parent = etpar[k]; ++nchild[parent]; if ( k != 0 && nchild[k] >= 2 ) { part_super_h[xsup] = k - xsup; xsup = k; } oldnbr = perm[k]; for (j = xadj[oldnbr]; j < xadj[oldnbr+1]; ++j) { /* * Renumber vertices of G(A) by postorder */ /* i = invp[zfdperm[adjncy[j]]];*/ i = zfdperm[adjncy[j]]; ++rowcnt[i]; if (fnz[i] == EMPTY) { /* * Build linked list to describe FIRST sets */ fnz[i] = k; firstset[i] = first[k]; first[k] = i; if ( k != 0 && xsup != k ) { part_super_h[xsup] = k - xsup; xsup = k; } } } } part_super_h[xsup] = neqns - xsup; #ifdef CHK_NZCNT printf("%8s%8s%8s\n", "k", "fnz", "first"); for (k = 0; k < neqns; ++k) printf("%8d%8d%8d\n", k, fnz[k], first[k]); #endif /* Set up fnz_hadj[*] structure. */ hadj_begin[0] = 0; for (k = 0; k < neqns; ++k) { temp = 0; oldnbr = perm[k]; hadj_end[k] = hadj_begin[k]; for (j = xadj[oldnbr]; j < xadj[oldnbr+1]; ++j) { /* hinbr = invp[zfdperm[adjncy[j]]];*/ hinbr = zfdperm[adjncy[j]]; jstrt = fnz[hinbr]; /* first nonzero must be <= k */ if ( jstrt != k && marker[jstrt] < k ) { /* ---------------------------------- filtering k itself and duplicates ---------------------------------- */ fnz_hadj[hadj_end[jstrt]] = k; ++hadj_end[jstrt]; marker[jstrt] = k; } if ( jstrt == k ) temp += rowcnt[hinbr]; } hadj_begin[k+1] = hadj_begin[k] + temp; } #ifdef CHK_NZCNT printf("%8s%8s\n", "k", "hadj"); for (k = 0; k < neqns; ++k) { printf("%8d", k); for (j = hadj_begin[k]; j < hadj_end[k]; ++j) printf("%8d", fnz_hadj[j]); printf("\n"); } #endif /* -------------------------------------------------- COMPUTE LEVEL(*), FDESC(*), NCHILD(*). INITIALIZE ROWCNT(*), COLCNT(*), SET(*), PRVLF(*), WEIGHT(*), PRVNBR(*). -------------------------------------------------- */ level[ROOT] = 0; for (k = neqns-1; k >= 0; --k) { rowcnt[k] = 1; colcnt[k] = 0; set[k] = k; prvlf[k] = EMPTY; level[k] = level[etpar[k]] + 1; weight[k] = 1; fdesc[k] = k; prvnbr[k] = EMPTY; } fdesc[ROOT] = EMPTY; for (k = 0; k < neqns; ++k) { parent = etpar[k]; weight[parent] = 0; colcnt_h[k] = 0; ifdesc = fdesc[k]; if (ifdesc < fdesc[parent]) { fdesc[parent] = ifdesc; } } xsup = 0; /* BUG FIX */ nsuper = 0; /* ------------------------------------ FOR EACH ``LOW NEIGHBOR'' LOWNBR ... ------------------------------------ */ for (lownbr = 0; lownbr < neqns; ++lownbr) { for (i = first[lownbr]; i != EMPTY; i = firstset[i]) { rowcnt_h[i] = 1 + ( level[lownbr] - level[i] ); ++weight_h[lownbr]; parent = etpar[i]; --weight_h[parent]; } lflag = 0; ifdesc = fdesc[lownbr]; jstrt = hadj_begin[lownbr]; jstop = hadj_end[lownbr]; /* ----------------------------------------------- FOR EACH ``HIGH NEIGHBOR'', HINBR OF LOWNBR ... ----------------------------------------------- */ for (j = jstrt; j < jstop; ++j) { hinbr = fnz_hadj[j]; if (hinbr > lownbr) { if (ifdesc > prvnbr[hinbr]) { /* ------------------------- INCREMENT WEIGHT(LOWNBR). ------------------------- */ ++weight[lownbr]; pleaf = prvlf[hinbr]; /* ----------------------------------------- IF HINBR HAS NO PREVIOUS ``LOW NEIGHBOR'' THEN ... ----------------------------------------- */ if (pleaf == EMPTY) { /* ----------------------------------------- ... ACCUMULATE LOWNBR-->HINBR PATH LENGTH IN ROWCNT(HINBR). ----------------------------------------- */ rowcnt[hinbr] = rowcnt[hinbr] + level[lownbr] - level[hinbr]; } else { /* ----------------------------------------- ... OTHERWISE, LCA <-- FIND(PLEAF), WHICH IS THE LEAST COMMON ANCESTOR OF PLEAF AND LOWNBR. (PATH HALVING.) ----------------------------------------- */ last1 = pleaf; last2 = set[last1]; lca = set[last2]; while ( lca != last2 ) { set[last1] = lca; last1 = lca; last2 = set[last1]; lca = set[last2]; } /* ------------------------------------- ACCUMULATE PLEAF-->LCA PATH LENGTH IN ROWCNT(HINBR). DECREMENT WEIGHT(LCA). ------------------------------------- */ rowcnt[hinbr] = rowcnt[hinbr] + level[lownbr] - level[lca]; --weight[lca]; } /* ---------------------------------------------- LOWNBR NOW BECOMES ``PREVIOUS LEAF'' OF HINBR. ---------------------------------------------- */ prvlf[hinbr] = lownbr; lflag = 1; } /* -------------------------------------------------- LOWNBR NOW BECOMES ``PREVIOUS NEIGHBOR'' OF HINBR. -------------------------------------------------- */ prvnbr[hinbr] = lownbr; } } /* for j ... */ /* ---------------------------------------------------- DECREMENT WEIGHT ( PARENT(LOWNBR) ). SET ( P(LOWNBR) ) <-- SET ( P(LOWNBR) ) + SET(XSUP). ---------------------------------------------------- */ parent = etpar[lownbr]; --weight[parent]; if (lflag == 1 || nchild[lownbr] >= 2) { /* lownbr is detected as the beginning of the new supernode */ if ( lownbr != 0 ) part_super_ata[xsup] = lownbr - xsup; ++nsuper; xsup = lownbr; } else { if ( parent == ROOT && ifdesc == lownbr ) { /* lownbr is a singleton, and begins a new supernode but is not detected as doing so -- BUG FIX */ part_super_ata[lownbr] = 1; ++nsuper; xsup = lownbr; } } set[xsup] = parent; } /* for lownbr ... */ /* --------------------------------------------------------- USE WEIGHTS TO COMPUTE COLUMN (AND TOTAL) NONZERO COUNTS. --------------------------------------------------------- */ *nlnz = nhnz = 0; for (k = 0; k < neqns; ++k) { /* for R */ temp = colcnt[k] + weight[k]; colcnt[k] = temp; *nlnz += temp; parent = etpar[k]; if (parent != ROOT) { colcnt[parent] += temp; } /* for H */ temp = colcnt_h[k] + weight_h[k]; colcnt_h[k] = temp; nhnz += temp; if (parent != ROOT) { colcnt_h[parent] += temp; } } part_super_ata[xsup] = neqns - xsup; /* Fix the supernode partition in H. */ free (set); free (prvlf); free (level); free (weight); free (fdesc); free (nchild); free (prvnbr); free (fnz_hadj); free (first); free (firstset); free (weight_h); free (rowcnt_h); free (rowcnt); free (colcnt); #if ( PRNTlevel==1 ) printf(".. qrnzcnt() nlnz %d, nhnz %d, nlnz/nhnz %.2f\n", *nlnz, nhnz, (float) *nlnz/nhnz); #endif #if ( DEBUGlevel>=2 ) print_int_vec("part_super_h", neqns, part_super_h); #endif return 0; } /* qrnzcnt_ */
int main ( int argc, char *argv[] ) /**********************************************************************/ /* Purpose: SUPER_LU_D0 runs a small 5 by 5 example of the use of SUPER_LU. Modified: 23 April 2004 Reference: James Demmel, John Gilbert, Xiaoye Li, SuperLU Users's Guide, Sections 1 and 2. */ { double *a; SuperMatrix A; int *asub; SuperMatrix B; int i; int info; SuperMatrix L; int m; int n; int nnz; int nrhs; superlu_options_t options; int *perm_c; int *perm_r; int permc_spec; double *rhs; double sol[5]; SuperLUStat_t stat; SuperMatrix U; int *xa; /* Say hello. */ printf ( "\n" ); printf ( "SUPER_LU_D0:\n" ); printf ( " Simple 5 by 5 example of SUPER_LU solver.\n" ); /* Initialize parameters. */ m = 5; n = 5; nnz = 12; /* Set aside space for the arrays. */ a = doubleMalloc ( nnz ); if ( !a ) { ABORT ( "Malloc fails for a[]." ); } asub = intMalloc ( nnz ); if ( !asub ) { ABORT ( "Malloc fails for asub[]." ); } xa = intMalloc ( n+1 ); if ( !xa ) { ABORT ( "Malloc fails for xa[]." ); } /* Initialize matrix A. */ a[0] = 19.0; a[1] = 12.0; a[2] = 12.0; a[3] = 21.0; a[4] = 12.0; a[5] = 12.0; a[6] = 21.0; a[7] = 16.0; a[8] = 21.0; a[9] = 5.0; a[10]= 21.0; a[11]= 18.0; asub[0] = 0; asub[1] = 1; asub[2] = 4; asub[3] = 1; asub[4] = 2; asub[5] = 4; asub[6] = 0; asub[7] = 2; asub[8] = 0; asub[9] = 3; asub[10]= 3; asub[11]= 4; xa[0] = 0; xa[1] = 3; xa[2] = 6; xa[3] = 8; xa[4] = 10; xa[5] = 12; sol[0] = -0.031250000; sol[1] = 0.065476190; sol[2] = 0.013392857; sol[3] = 0.062500000; sol[4] = 0.032738095; /* Create matrix A in the format expected by SuperLU. */ dCreate_CompCol_Matrix ( &A, m, n, nnz, a, asub, xa, SLU_NC, SLU_D, SLU_GE ); /* Create the right-hand side matrix B. */ nrhs = 1; rhs = doubleMalloc ( m * nrhs ); if ( !rhs ) { ABORT("Malloc fails for rhs[]."); } for ( i = 0; i < m; i++ ) { rhs[i] = 1.0; } dCreate_Dense_Matrix ( &B, m, nrhs, rhs, m, SLU_DN, SLU_D, SLU_GE ); /* Set up the arrays for the permutations. */ perm_r = intMalloc ( m ); if ( !perm_r ) { ABORT ( "Malloc fails for perm_r[]." ); } perm_c = intMalloc ( n ); if ( !perm_c ) { ABORT ( "Malloc fails for perm_c[]." ); } /* Set the default input options, and then adjust some of them. */ set_default_options ( &options ); options.ColPerm = NATURAL; /* Initialize the statistics variables. */ StatInit ( &stat ); /* Factor the matrix and solve the linear system. */ dgssv ( &options, &A, perm_c, perm_r, &L, &U, &B, &stat, &info ); /* Print some of the results. */ dPrint_CompCol_Matrix ( "Matrix A", &A ); dPrint_SuperNode_Matrix ( "Factor L", &L ); dPrint_CompCol_Matrix ( "Factor U", &U ); dPrint_Dense_Matrix ( "Solution X", &B ); printf ( "\n" ); printf ( " The exact solution:\n" ); printf ( "\n" ); for ( i = 0; i < n; i++ ) { printf ( "%d %f\n", i, sol[i] ); } printf ( "\n" ); print_int_vec ( "perm_r", m, perm_r ); /* De-allocate storage. */ SUPERLU_FREE ( rhs ); SUPERLU_FREE ( perm_r ); SUPERLU_FREE ( perm_c ); Destroy_CompCol_Matrix ( &A ); Destroy_SuperMatrix_Store ( &B ); Destroy_SuperNode_Matrix ( &L ); Destroy_CompCol_Matrix ( &U ); StatFree ( &stat ); printf ( "\n" ); printf ( "SUPER_LU_D0:\n" ); printf ( " Normal end of execution.\n" ); return 0; }
/*! \brief * * <pre> * Purpose * ======= * * sp_preorder() permutes the columns of the original matrix. It performs * the following steps: * * 1. Apply column permutation perm_c[] to A's column pointers to form AC; * * 2. If options->Fact = DOFACT, then * (1) Compute column elimination tree etree[] of AC'AC; * (2) Post order etree[] to get a postordered elimination tree etree[], * and a postorder permutation post[]; * (3) Apply post[] permutation to columns of AC; * (4) Overwrite perm_c[] with the product perm_c * post. * * Arguments * ========= * * options (input) superlu_options_t* * Specifies whether or not the elimination tree will be re-used. * If options->Fact == DOFACT, this means first time factor A, * etree is computed, postered, and output. * Otherwise, re-factor A, etree is input, unchanged on exit. * * A (input) SuperMatrix* * Matrix A in A*X=B, of dimension (A->nrow, A->ncol). The number * of the linear equations is A->nrow. Currently, the type of A can be: * Stype = NC or SLU_NCP; Mtype = SLU_GE. * In the future, more general A may be handled. * * perm_c (input/output) int* * Column permutation vector of size A->ncol, which defines the * permutation matrix Pc; perm_c[i] = j means column i of A is * in position j in A*Pc. * If options->Fact == DOFACT, perm_c is both input and output. * On output, it is changed according to a postorder of etree. * Otherwise, perm_c is input. * * etree (input/output) int* * Elimination tree of Pc'*A'*A*Pc, dimension A->ncol. * If options->Fact == DOFACT, etree is an output argument, * otherwise it is an input argument. * Note: etree is a vector of parent pointers for a forest whose * vertices are the integers 0 to A->ncol-1; etree[root]==A->ncol. * * AC (output) SuperMatrix* * The resulting matrix after applied the column permutation * perm_c[] to matrix A. The type of AC can be: * Stype = SLU_NCP; Dtype = A->Dtype; Mtype = SLU_GE. * </pre> */ void sp_preorder(superlu_options_t *options, SuperMatrix *A, int *perm_c, int *etree, SuperMatrix *AC) { NCformat *Astore; NCPformat *ACstore; int *iwork, *post; register int n, i; n = A->ncol; /* Apply column permutation perm_c to A's column pointers so to obtain NCP format in AC = A*Pc. */ AC->Stype = SLU_NCP; AC->Dtype = A->Dtype; AC->Mtype = A->Mtype; AC->nrow = A->nrow; AC->ncol = A->ncol; Astore = A->Store; ACstore = AC->Store = (void *) SUPERLU_MALLOC( sizeof(NCPformat) ); if ( !ACstore ) ABORT("SUPERLU_MALLOC fails for ACstore"); ACstore->nnz = Astore->nnz; ACstore->nzval = Astore->nzval; ACstore->rowind = Astore->rowind; ACstore->colbeg = (int*) SUPERLU_MALLOC(n*sizeof(int)); if ( !(ACstore->colbeg) ) ABORT("SUPERLU_MALLOC fails for ACstore->colbeg"); ACstore->colend = (int*) SUPERLU_MALLOC(n*sizeof(int)); if ( !(ACstore->colend) ) ABORT("SUPERLU_MALLOC fails for ACstore->colend"); #ifdef DEBUG print_int_vec("pre_order:", n, perm_c); check_perm("Initial perm_c", n, perm_c); #endif for (i = 0; i < n; i++) { ACstore->colbeg[perm_c[i]] = Astore->colptr[i]; ACstore->colend[perm_c[i]] = Astore->colptr[i+1]; } if ( options->Fact == DOFACT ) { #undef ETREE_ATplusA #ifdef ETREE_ATplusA /*-------------------------------------------- COMPUTE THE ETREE OF Pc*(A'+A)*Pc'. --------------------------------------------*/ int *b_colptr, *b_rowind, bnz, j; int *c_colbeg, *c_colend; /*printf("Use etree(A'+A)\n");*/ /* Form B = A + A'. */ at_plus_a(n, Astore->nnz, Astore->colptr, Astore->rowind, &bnz, &b_colptr, &b_rowind); /* Form C = Pc*B*Pc'. */ c_colbeg = (int*) SUPERLU_MALLOC(2*n*sizeof(int)); c_colend = c_colbeg + n; if (!c_colbeg ) ABORT("SUPERLU_MALLOC fails for c_colbeg/c_colend"); for (i = 0; i < n; i++) { c_colbeg[perm_c[i]] = b_colptr[i]; c_colend[perm_c[i]] = b_colptr[i+1]; } for (j = 0; j < n; ++j) { for (i = c_colbeg[j]; i < c_colend[j]; ++i) { b_rowind[i] = perm_c[b_rowind[i]]; } } /* Compute etree of C. */ sp_symetree(c_colbeg, c_colend, b_rowind, n, etree); SUPERLU_FREE(b_colptr); if ( bnz ) SUPERLU_FREE(b_rowind); SUPERLU_FREE(c_colbeg); #else /*-------------------------------------------- COMPUTE THE COLUMN ELIMINATION TREE. --------------------------------------------*/ sp_coletree(ACstore->colbeg, ACstore->colend, ACstore->rowind, A->nrow, A->ncol, etree); #endif #ifdef DEBUG print_int_vec("etree:", n, etree); #endif /* In symmetric mode, do not do postorder here. */ if ( options->SymmetricMode == NO ) { /* Post order etree */ post = (int *) TreePostorder(n, etree); /* for (i = 0; i < n+1; ++i) inv_post[post[i]] = i; iwork = post; */ #ifdef DEBUG print_int_vec("post:", n+1, post); check_perm("post", n, post); #endif iwork = (int*) SUPERLU_MALLOC((n+1)*sizeof(int)); if ( !iwork ) ABORT("SUPERLU_MALLOC fails for iwork[]"); /* Renumber etree in postorder */ for (i = 0; i < n; ++i) iwork[post[i]] = post[etree[i]]; for (i = 0; i < n; ++i) etree[i] = iwork[i]; #ifdef DEBUG print_int_vec("postorder etree:", n, etree); #endif /* Postmultiply A*Pc by post[] */ for (i = 0; i < n; ++i) iwork[post[i]] = ACstore->colbeg[i]; for (i = 0; i < n; ++i) ACstore->colbeg[i] = iwork[i]; for (i = 0; i < n; ++i) iwork[post[i]] = ACstore->colend[i]; for (i = 0; i < n; ++i) ACstore->colend[i] = iwork[i]; for (i = 0; i < n; ++i) iwork[i] = post[perm_c[i]]; /* product of perm_c and post */ for (i = 0; i < n; ++i) perm_c[i] = iwork[i]; #ifdef DEBUG print_int_vec("Pc*post:", n, perm_c); check_perm("final perm_c", n, perm_c); #endif SUPERLU_FREE (post); SUPERLU_FREE (iwork); } /* end postordering */ } /* if options->Fact == DOFACT ... */ }
static void OyInit_color_options(SANE_Handle device) { const SANE_Option_Descriptor *opt = NULL; SANE_Int num_options = 0; SANE_Status status; unsigned int opt_num = 0, i = 0, chars = 0; char buf[BUFSIZE]; /* We got a device, find out how many options it has */ status = sane_control_option(device, 0, SANE_ACTION_GET_VALUE, &num_options, 0); if (status != SANE_STATUS_GOOD) { fprintf(stderr, "unable to determine option count\n"); exit(1); } color_option_names = (char **)malloc(sizeof(char *) * num_options); color_option_values = (char **)malloc(sizeof(char *) * num_options); memset(color_option_names, 0, sizeof(char *) * num_options); memset(color_option_values, 0, sizeof(char *) * num_options); for (opt_num = 1; opt_num < num_options; opt_num++) { opt = sane_get_option_descriptor(device, opt_num); if (opt->cap & SANE_CAP_COLOUR) { void *val = malloc(opt->size); color_option_names[i] = (char *)malloc(strlen(opt->name) + 1); strcpy(color_option_names[i], opt->name); sane_control_option(device, opt_num, SANE_ACTION_GET_VALUE, val, 0); switch (opt->type) { case SANE_TYPE_BOOL: color_option_values[i] = *(SANE_Bool *) val ? "true" : "false"; break; case SANE_TYPE_INT: if (opt->size == (SANE_Int) sizeof(SANE_Word)) chars = sprintf(buf, "%d", *(SANE_Int *) val); /* use snprintf( ..,128,.. ) */ else chars = print_int_vec((SANE_Int *) val, opt->size, buf, BUFSIZE); color_option_values[i] = (char *)malloc(chars + 1); strcpy(color_option_values[i], buf); break; case SANE_TYPE_FIXED: chars = sprintf(buf, "%f", SANE_UNFIX(*(SANE_Fixed *) val)); color_option_values[i] = (char *)malloc(chars + 1); strcpy(color_option_values[i], buf); break; case SANE_TYPE_STRING: color_option_values[i] = (char *)malloc(strlen((char *)val) + 1); strcpy(color_option_values[i], (char *)val); break; case SANE_TYPE_BUTTON: color_option_values[i] = "button"; break; default: fprintf(stderr, "Do not know what to do with option %d\n", opt->type); exit(0); break; } i++; } } }
int main ( ) /******************************************************************************/ /* Purpose: D_SAMPLE_ST tests the SUPERLU solver with a 5x5 double precision real matrix. Discussion: The general (GE) representation of the matrix is: [ 19 0 21 21 0 12 21 0 0 0 0 12 16 0 0 0 0 0 5 21 12 12 0 0 18 ] The (0-based) compressed column (CC) representation of this matrix is: I CC A -- -- -- 0 0 19 1 12 4 12 1 3 21 2 12 4 12 0 6 21 2 16 0 8 21 3 5 3 10 21 4 18 * 12 * The right hand side B and solution X are # B X -- -- ---------- 0 1 -0.03125 1 1 0.0654762 2 1 0.0133929 3 1 0.0625 4 1 0.0327381 Licensing: This code is distributed under the GNU LGPL license. Modified: 18 July 2014 Author: John Burkardt Reference: James Demmel, John Gilbert, Xiaoye Li, SuperLU Users's Guide. */ { SuperMatrix A; double *acc; double *b; double *b2; SuperMatrix B; int *ccc; int i; int *icc; int info; int j; SuperMatrix L; int m; int n; int nrhs = 1; int ncc; superlu_options_t options; int *perm_c; int permc_spec; int *perm_r; SuperLUStat_t stat; SuperMatrix U; timestamp ( ); printf ( "\n" ); printf ( "D_SAMPLE_ST:\n" ); printf ( " C version\n" ); printf ( " SUPERLU solves a double precision real linear system.\n" ); printf ( " The matrix is read from a Sparse Triplet (ST) file.\n" ); /* Read the matrix from a file associated with standard input, in sparse triplet (ST) format, into compressed column (CC) format. */ dreadtriple ( &m, &n, &ncc, &acc, &icc, &ccc ); /* Print the matrix. */ cc_print ( m, n, ncc, icc, ccc, acc, " CC Matrix:" ); /* Convert the compressed column (CC) matrix into a SuperMatrix A. */ dCreate_CompCol_Matrix ( &A, m, n, ncc, acc, icc, ccc, SLU_NC, SLU_D, SLU_GE ); /* Create the right-hand side matrix. */ b = ( double * ) malloc ( m * sizeof ( double ) ); for ( i = 0; i < m; i++ ) { b[i] = 1.0; } printf ( "\n" ); printf ( " Right hand side:\n" ); printf ( "\n" ); for ( i = 0; i < m; i++ ) { printf ( "%g\n", b[i] ); } /* Create Super Right Hand Side. */ dCreate_Dense_Matrix ( &B, m, nrhs, b, m, SLU_DN, SLU_D, SLU_GE ); /* Set space for the permutations. */ perm_r = ( int * ) malloc ( m * sizeof ( int ) ); perm_c = ( int * ) malloc ( n * sizeof ( int ) ); /* Set the input options. */ set_default_options ( &options ); options.ColPerm = NATURAL; /* Initialize the statistics variables. */ StatInit ( &stat ); /* Solve the linear system. */ dgssv ( &options, &A, perm_c, perm_r, &L, &U, &B, &stat, &info ); dPrint_CompCol_Matrix ( ( char * ) "A", &A ); dPrint_CompCol_Matrix ( ( char * ) "U", &U ); dPrint_SuperNode_Matrix ( ( char * ) "L", &L ); print_int_vec ( ( char * ) "\nperm_r", m, perm_r ); /* By some miracle involving addresses, the solution has been put into the B vector. */ printf ( "\n" ); printf ( " Computed solution:\n" ); printf ( "\n" ); for ( i = 0; i < m; i++ ) { printf ( "%g\n", b[i] ); } /* Demonstrate that RHS is really the solution now. Multiply it by the matrix. */ b2 = cc_mv ( m, n, ncc, icc, ccc, acc, b ); printf ( "\n" ); printf ( " Product A*X:\n" ); printf ( "\n" ); for ( i = 0; i < m; i++ ) { printf ( "%g\n", b2[i] ); } /* Free memory. */ free ( b ); free ( b2 ); free ( perm_c ); free ( perm_r ); Destroy_SuperMatrix_Store ( &A ); Destroy_SuperMatrix_Store ( &B ); Destroy_SuperNode_Matrix ( &L ); Destroy_CompCol_Matrix ( &U ); StatFree ( &stat ); /* Terminate. */ printf ( "\n" ); printf ( "D_SAMPLE_ST:\n" ); printf ( " Normal end of execution.\n" ); printf ( "\n" ); timestamp ( ); return 0; }
void sp_colorder(SuperMatrix *A, int *perm_c, superlumt_options_t *options, SuperMatrix *AC) { /* * -- SuperLU MT routine (version 2.0) -- * Lawrence Berkeley National Lab, Univ. of California Berkeley, * and Xerox Palo Alto Research Center. * September 10, 2007 * * * Purpose * ======= * * sp_colorder() permutes the columns of the original matrix A into AC. * It performs the following steps: * * 1. Apply column permutation perm_c[] to A's column pointers to form AC; * * 2. If options->refact = NO, then * (1) Allocate etree[], and compute column etree etree[] of AC'AC; * (2) Post order etree[] to get a postordered elimination tree etree[], * and a postorder permutation post[]; * (3) Apply post[] permutation to columns of AC; * (4) Overwrite perm_c[] with the product perm_c * post. * (5) Allocate storage, and compute the column count (colcnt_h) and the * supernode partition (part_super_h) for the Householder matrix H. * * Arguments * ========= * * A (input) SuperMatrix* * Matrix A in A*X=B, of dimension (A->nrow, A->ncol). The number * of the linear equations is A->nrow. Currently, the type of A can be: * Stype = NC or NCP; Dtype = _D; Mtype = GE. * * perm_c (input/output) int* * Column permutation vector of size A->ncol, which defines the * permutation matrix Pc; perm_c[i] = j means column i of A is * in position j in A*Pc. * * options (input/output) superlumt_options_t* * If options->refact = YES, then options is an * input argument. The arrays etree[], colcnt_h[] and part_super_h[] * are available from a previous factor and will be re-used. * If options->refact = NO, then options is an output argument. * * AC (output) SuperMatrix* * The resulting matrix after applied the column permutation * perm_c[] to matrix A. The type of AC can be: * Stype = NCP; Dtype = _D; Mtype = GE. * */ NCformat *Astore; NCPformat *ACstore; int i, n, nnz, nlnz; yes_no_t refact = options->refact; int *etree; int *colcnt_h; int *part_super_h; int *iwork, *post, *iperm; int *invp; int *part_super_ata; extern void at_plus_a(const int, const int, int *, int *, int *, int **, int **, int); n = A->ncol; iwork = intMalloc(n+1); part_super_ata = intMalloc(n); /* Apply column permutation perm_c to A's column pointers so to obtain NCP format in AC = A*Pc. */ AC->Stype = SLU_NCP; AC->Dtype = A->Dtype; AC->Mtype = A->Mtype; AC->nrow = A->nrow; AC->ncol = A->ncol; Astore = A->Store; ACstore = AC->Store = (void *) malloc( sizeof(NCPformat) ); ACstore->nnz = Astore->nnz; ACstore->nzval = Astore->nzval; ACstore->rowind = Astore->rowind; ACstore->colbeg = intMalloc(n); ACstore->colend = intMalloc(n); nnz = Astore->nnz; #ifdef CHK_COLORDER print_int_vec("pre_order:", n, perm_c); dcheck_perm("Initial perm_c", n, perm_c); #endif for (i = 0; i < n; i++) { ACstore->colbeg[perm_c[i]] = Astore->colptr[i]; ACstore->colend[perm_c[i]] = Astore->colptr[i+1]; } if ( refact == NO ) { int *b_colptr, *b_rowind, bnz, j; options->etree = etree = intMalloc(n); options->colcnt_h = colcnt_h = intMalloc(n); options->part_super_h = part_super_h = intMalloc(n); if ( options->SymmetricMode ) { /* Compute the etree of C = Pc*(A'+A)*Pc'. */ int *c_colbeg, *c_colend; /* Form B = A + A'. */ at_plus_a(n, Astore->nnz, Astore->colptr, Astore->rowind, &bnz, &b_colptr, &b_rowind, 1); /* Form C = Pc*B*Pc'. */ c_colbeg = (int_t*) intMalloc(n); c_colend = (int_t*) intMalloc(n); if (!(c_colbeg) || !(c_colend) ) SUPERLU_ABORT("SUPERLU_MALLOC fails for c_colbeg/c_colend"); for (i = 0; i < n; i++) { c_colbeg[perm_c[i]] = b_colptr[i]; c_colend[perm_c[i]] = b_colptr[i+1]; } for (j = 0; j < n; ++j) { for (i = c_colbeg[j]; i < c_colend[j]; ++i) { b_rowind[i] = perm_c[b_rowind[i]]; } iwork[perm_c[j]] = j; /* inverse perm_c */ } /* Compute etree of C. */ sp_symetree(c_colbeg, c_colend, b_rowind, n, etree); /* Restore B to be A+A', without column permutation */ for (i = 0; i < bnz; ++i) b_rowind[i] = iwork[b_rowind[i]]; SUPERLU_FREE(c_colbeg); SUPERLU_FREE(c_colend); } else { /* Compute the column elimination tree. */ sp_coletree(ACstore->colbeg, ACstore->colend, ACstore->rowind, A->nrow, A->ncol, etree); } #ifdef CHK_COLORDER print_int_vec("etree:", n, etree); #endif /* Post order etree. */ post = (int *) TreePostorder(n, etree); invp = intMalloc(n); for (i = 0; i < n; ++i) invp[post[i]] = i; #ifdef CHK_COLORDER print_int_vec("post:", n+1, post); dcheck_perm("post", n, post); #endif /* Renumber etree in postorder. */ for (i = 0; i < n; ++i) iwork[post[i]] = post[etree[i]]; for (i = 0; i < n; ++i) etree[i] = iwork[i]; #ifdef CHK_COLORDER print_int_vec("postorder etree:", n, etree); #endif /* Postmultiply A*Pc by post[]. */ for (i = 0; i < n; ++i) iwork[post[i]] = ACstore->colbeg[i]; for (i = 0; i < n; ++i) ACstore->colbeg[i] = iwork[i]; for (i = 0; i < n; ++i) iwork[post[i]] = ACstore->colend[i]; for (i = 0; i < n; ++i) ACstore->colend[i] = iwork[i]; for (i = 0; i < n; ++i) iwork[i] = post[perm_c[i]]; /* product of perm_c and post */ for (i = 0; i < n; ++i) perm_c[i] = iwork[i]; for (i = 0; i < n; ++i) invp[perm_c[i]] = i; /* inverse of perm_c */ iperm = post; /* alias to the same address */ #ifdef ZFD_PERM /* Permute the rows of AC to have zero-free diagonal. */ printf("** Permute the rows to have zero-free diagonal....\n"); for (i = 0; i < n; ++i) iwork[i] = ACstore->colend[i] - ACstore->colbeg[i]; zfdperm(n, nnz, ACstore->rowind, ACstore->colbeg, iwork, iperm); #else for (i = 0; i < n; ++i) iperm[i] = i; #endif /* NOTE: iperm is returned as column permutation so that * the diagonal is nonzero. Since a symmetric permutation * preserves the diagonal, we can do the following: * P'(AP')P = P'A * That is, we apply the inverse of iperm to rows of A * to get zero-free diagonal. But since iperm is defined * in MC21A inversely as our definition of permutation, * so it is indeed an inverse for our purpose. We can * apply it directly. */ if ( options->SymmetricMode ) { /* Determine column count in the Cholesky factor of B = A+A' */ #if 0 cholnzcnt(n, Astore->colptr, Astore->rowind, invp, perm_c, etree, colcnt_h, &nlnz, part_super_h); #else cholnzcnt(n, b_colptr, b_rowind, invp, perm_c, etree, colcnt_h, &nlnz, part_super_h); #endif #if ( PRNTlevel>=1 ) printf(".. bnz %d\n", bnz); #endif SUPERLU_FREE(b_colptr); if ( bnz ) SUPERLU_FREE(b_rowind); } else { /* Determine the row and column counts in the QR factor. */ qrnzcnt(n, nnz, Astore->colptr, Astore->rowind, iperm, invp, perm_c, etree, colcnt_h, &nlnz, part_super_ata, part_super_h); } #if ( PRNTlevel>=2 ) dCheckZeroDiagonal(n, ACstore->rowind, ACstore->colbeg, ACstore->colend, perm_c); print_int_vec("colcnt", n, colcnt_h); dPrintSuperPart("Hpart", n, part_super_h); print_int_vec("iperm", n, iperm); #endif #ifdef CHK_COLORDER print_int_vec("Pc*post:", n, perm_c); dcheck_perm("final perm_c", n, perm_c); #endif SUPERLU_FREE (post); SUPERLU_FREE (invp); } /* if refact == NO */ SUPERLU_FREE (iwork); SUPERLU_FREE (part_super_ata); }