static void taucs_ccs_genmmd(taucs_ccs_matrix * m, int **perm, int **invperm, char *which) { #ifndef TAUCS_CONFIG_GENMMD taucs_printf("taucs_ccs_genmmd: GENMMD routines not linked.\n"); *perm = NULL; *invperm = NULL; return; #else int n, maxint, delta, nofsub; int *xadj; int *adjncy; int *invp; int *prm; int *dhead; int *qsize; int *llist; int *marker; int *len; int *next; int nnz, i, j, ip; /* * taucs_printf("taucs_ccs_genmmd: starting (%s)\n",which); */ if (!(m->flags & TAUCS_SYMMETRIC) && !(m->flags & TAUCS_HERMITIAN)) { taucs_printf("taucs_ccs_genmmd: GENMMD ordering only works on symmetric matrices.\n"); *perm = NULL; *invperm = NULL; return; } /* * this routine may actually work on UPPER as well */ if (!(m->flags & TAUCS_LOWER)) { taucs_printf("taucs_ccs_genmmd: the lower part of the matrix must be represented.\n"); *perm = NULL; *invperm = NULL; return; } *perm = NULL; *invperm = NULL; n = m->n; nnz = (m->colptr)[n]; /* * I copied the value of delta and the size of */ /* * from SuperLU. Sivan */ delta = 1; /* DELTA is a parameter to allow the choice of nodes whose degree <= * min-degree + DELTA. */ delta = 1; /* DELTA is a parameter to allow the choice of nodes whose degree <= * min-degree + DELTA. */ /* * maxint = 2147483648; *//* * 2**31-1, for 32-bit only! */ maxint = 32000; assert(sizeof(int) == 4); maxint = 2147483647; /* 2**31-1, for 32-bit only! */ xadj = (int *) taucs_malloc((n + 1) * sizeof(int)); adjncy = (int *) taucs_malloc((2 * nnz - n) * sizeof(int)); invp = (int *) taucs_malloc((n + 1) * sizeof(int)); prm = (int *) taucs_malloc(n * sizeof(int)); dhead = (int *) taucs_malloc((n + 1) * sizeof(int)); qsize = (int *) taucs_malloc((n + 1) * sizeof(int)); llist = (int *) taucs_malloc(n * sizeof(int)); marker = (int *) taucs_malloc(n * sizeof(int)); if (!xadj || !adjncy || !invp || !prm || !dhead || !qsize || !llist || !marker) { taucs_free(xadj); taucs_free(adjncy); taucs_free(invp); taucs_free(prm); taucs_free(dhead); taucs_free(qsize); taucs_free(llist); taucs_free(marker); return; } len = dhead; /* we reuse space */ next = qsize; /* we reuse space */ for (i = 0; i < n; i++) len[i] = 0; for (j = 0; j < n; j++) { for (ip = (m->colptr)[j]; ip < (m->colptr)[j + 1]; ip++) { /* * i = (m->rowind)[ip] - (m->indshift); */ i = (m->rowind)[ip]; if (i != j) { len[i]++; len[j]++; } else { /* * len[i] ++; */ } } } xadj[0] = 1; for (i = 1; i <= n; i++) xadj[i] = xadj[i - 1] + len[i - 1]; /* * for (i=0; i<=n; i++) printf("xadj[%d]=%d\n",i,xadj[i]); */ /* * use degree as a temporary */ for (i = 0; i < n; i++) next[i] = xadj[i] - 1; for (j = 0; j < n; j++) { for (ip = (m->colptr)[j]; ip < (m->colptr)[j + 1]; ip++) { /* * i = (m->rowind)[ip] - (m->indshift); */ i = (m->rowind)[ip]; assert(next[i] < 2 * nnz - n); assert(next[j] < 2 * nnz - n); if (i != j) { adjncy[next[i]] = j + 1; adjncy[next[j]] = i + 1; next[i]++; next[j]++; } else { /* * adjncy[ next[i] ] = j+1; next[i] ++; */ } } } /* * for (j=0; j<n; j++) { qsort(adjncy + (xadj[j] - 1), xadj[j+1] - xadj[j], sizeof(int), compare_ints); printf("+++ %d: * ",j+1); for (ip=xadj[j]-1; ip<xadj[j+1]-1;ip++) printf("%d ",adjncy[ip]); printf("\n"); } */ /* * taucs_printf("taucs_ccs_genmmd: calling genmmd, matrix is %dx%d, nnz=%d\n", n,n,nnz); */ genmmd_(&n, xadj, adjncy, invp, prm, &delta, dhead, qsize, llist, marker, &maxint, &nofsub); /* * taucs_printf("taucs_ccs_genmmd: genmmd returned.\n"); */ /* * { FILE* f; f=fopen("p.ijv","w"); for (i=0; i<n; i++) fprintf(f,"%d %d\n",prm[i],invp[i]); fclose(f); } */ taucs_free(marker); taucs_free(llist); taucs_free(qsize); taucs_free(dhead); taucs_free(xadj); taucs_free(adjncy); for (i = 0; i < n; i++) prm[i]--; for (i = 0; i < n; i++) invp[prm[i]] = i; *perm = prm; *invperm = invp; #endif }
void get_perm_c(int ispec, SuperMatrix *A, int *perm_c) /* * Purpose * ======= * * GET_PERM_C obtains a permutation matrix Pc, by applying the multiple * minimum degree ordering code by Joseph Liu to matrix A'*A or A+A'. * or using approximate minimum degree column ordering by Davis et. al. * The LU factorization of A*Pc tends to have less fill than the LU * factorization of A. * * Arguments * ========= * * ispec (input) int * Specifies the type of column ordering to reduce fill: * = 1: minimum degree on the structure of A^T * A * = 2: minimum degree on the structure of A^T + A * = 3: approximate minimum degree for unsymmetric matrices * If ispec == 0, the natural ordering (i.e., Pc = I) is returned. * * 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; Dtype = _D; Mtype = GE. In the future, * more general A can be handled. * * perm_c (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. * */ { NCformat *Astore = A->Store; int m, n, bnz = 0, *b_colptr, i; int delta, maxint, nofsub, *invp; int *b_rowind, *dhead, *qsize, *llist, *marker; double t, SuperLU_timer_(); m = A->nrow; n = A->ncol; t = SuperLU_timer_(); switch ( ispec ) { case 0: /* Natural ordering */ for (i = 0; i < n; ++i) perm_c[i] = i; #if ( PRNTlevel>=1 ) printf("Use natural column ordering.\n"); #endif return; case 1: /* Minimum degree ordering on A'*A */ getata(m, n, Astore->nnz, Astore->colptr, Astore->rowind, &bnz, &b_colptr, &b_rowind); #if ( PRNTlevel>=1 ) printf("Use minimum degree ordering on A'*A.\n"); #endif t = SuperLU_timer_() - t; /*printf("Form A'*A time = %8.3f\n", t);*/ break; case 2: /* Minimum degree ordering on A'+A */ if ( m != n ) ABORT("Matrix is not square"); at_plus_a(n, Astore->nnz, Astore->colptr, Astore->rowind, &bnz, &b_colptr, &b_rowind); #if ( PRNTlevel>=1 ) printf("Use minimum degree ordering on A'+A.\n"); #endif t = SuperLU_timer_() - t; /*printf("Form A'+A time = %8.3f\n", t);*/ break; case 3: /* Approximate minimum degree column ordering. */ get_colamd(m, n, Astore->nnz, Astore->colptr, Astore->rowind, perm_c); #if ( PRNTlevel>=1 ) printf(".. Use approximate minimum degree column ordering.\n"); #endif return; default: ABORT("Invalid ISPEC"); } if ( bnz != 0 ) { t = SuperLU_timer_(); /* Initialize and allocate storage for GENMMD. */ delta = 1; /* DELTA is a parameter to allow the choice of nodes whose degree <= min-degree + DELTA. */ maxint = 2147483647; /* 2**31 - 1 */ invp = (int *) SUPERLU_MALLOC((n+delta)*sizeof(int)); if ( !invp ) ABORT("SUPERLU_MALLOC fails for invp."); dhead = (int *) SUPERLU_MALLOC((n+delta)*sizeof(int)); if ( !dhead ) ABORT("SUPERLU_MALLOC fails for dhead."); qsize = (int *) SUPERLU_MALLOC((n+delta)*sizeof(int)); if ( !qsize ) ABORT("SUPERLU_MALLOC fails for qsize."); llist = (int *) SUPERLU_MALLOC(n*sizeof(int)); if ( !llist ) ABORT("SUPERLU_MALLOC fails for llist."); marker = (int *) SUPERLU_MALLOC(n*sizeof(int)); if ( !marker ) ABORT("SUPERLU_MALLOC fails for marker."); /* Transform adjacency list into 1-based indexing required by GENMMD.*/ for (i = 0; i <= n; ++i) ++b_colptr[i]; for (i = 0; i < bnz; ++i) ++b_rowind[i]; genmmd_(&n, b_colptr, b_rowind, perm_c, invp, &delta, dhead, qsize, llist, marker, &maxint, &nofsub); /* Transform perm_c into 0-based indexing. */ for (i = 0; i < n; ++i) --perm_c[i]; SUPERLU_FREE(invp); SUPERLU_FREE(dhead); SUPERLU_FREE(qsize); SUPERLU_FREE(llist); SUPERLU_FREE(marker); SUPERLU_FREE(b_rowind); t = SuperLU_timer_() - t; /* printf("call GENMMD time = %8.3f\n", t);*/ } else { /* Empty adjacency structure */ for (i = 0; i < n; ++i) perm_c[i] = i; } SUPERLU_FREE(b_colptr); }