static void taucs_ccs_randomperm(int n, int **perm, int **invperm) { int i; *perm = (int *) taucs_malloc(n * sizeof(int)); *invperm = (int *) taucs_malloc(n * sizeof(int)); if (!(*perm) || !(*invperm)) { taucs_free(*perm); taucs_free(*invperm); *perm = *invperm = NULL; taucs_printf("taucs_ccs_randomperm: out of memory for permutation\n"); return; } for (i = 0; i < n; i++) (*perm)[i] = i; for (i = 0; i < n; i++) { int i1, i2; int t; i1 = rand() % (n - i); i2 = n - i - 1; t = (*perm)[i1]; (*perm)[i1] = (*perm)[i2]; (*perm)[i2] = t; } for (i = 0; i < n; i++) (*invperm)[(*perm)[i]] = i; return; }
void taucs_dtl(ccs_free) (taucs_ccs_matrix * matrix) { if (!matrix) return; taucs_free(matrix->rowind); taucs_free(matrix->colptr); taucs_free(matrix->taucs_values); taucs_free(matrix); }
double taucs_available_memory_size() { double m_sys; double m,m_low,m_high,m_tol; char* p; m_sys = taucs_system_memory_size(); /* malloc test */ m = 1048576.0; while ( (p=(char*) taucs_malloc( (size_t) (m*2.0) )) != NULL ) { taucs_free(p); m = m*2.0; } m_low = m; m_high = 2.0*m; m_tol = m / 128.0; while ( m_high - m_low > m_tol ) { m = m_low + ( (m_high-m_low)/2.0 ); taucs_printf("taucs_avail_memory_size: [%.0lf %.0lf %.0lf]\n", m_low / 1048576.0, m / 1048576.0, m_high / 1048576.0); if ( (p=(char*) taucs_malloc( (size_t) m )) != NULL ) m_low = m; else m_high = m; taucs_free(p); } m = m_low; taucs_printf("taucs_avail_memory_size: malloc test=%.0lf MB sys test=%.0lf MB\n", m / 1048576.0, m_sys / 1048576.0 ); /* if m_sys is meaningful, then we limit m by 0.75*m_sys */ if (m_sys > 0) { m_sys = floor(0.75 * m_sys); if (m_sys < m) m = m_sys; } return m; }
taucs_ccs_matrix *taucs_dtl(ccs_create) (int m, int n, int nnz) { taucs_ccs_matrix *matrix; matrix = (taucs_ccs_matrix *) taucs_malloc(sizeof(taucs_ccs_matrix)); if (!matrix) { taucs_printf("taucs_ccs_create: out of memory\n"); return NULL; } #ifdef TAUCS_CORE_DOUBLE matrix->flags = TAUCS_DOUBLE; #endif #ifdef TAUCS_CORE_SINGLE matrix->flags = TAUCS_SINGLE; #endif #ifdef TAUCS_CORE_DCOMPLEX matrix->flags = TAUCS_DCOMPLEX; #endif #ifdef TAUCS_CORE_SINGLE matrix->flags = TAUCS_SINGLE; #endif matrix->n = n; matrix->m = m; matrix->colptr = (int *) taucs_malloc((n + 1) * sizeof(int)); matrix->rowind = (int *) taucs_malloc(nnz * sizeof(int)); matrix->taucs_values = (taucs_datatype *) taucs_malloc(nnz * sizeof(taucs_datatype)); if (!(matrix->colptr) || !(matrix->rowind) || !(matrix->taucs_values)) { taucs_printf("taucs_ccs_create: out of memory (n=%d, nnz=%d)\n", n, nnz); taucs_free(matrix->colptr); taucs_free(matrix->rowind); taucs_free(matrix->taucs_values); taucs_free(matrix); return NULL; } return matrix; }
void taucs_ccs_order(taucs_ccs_matrix* m, int** perm, int** invperm, char* which) { if (!strcmp(which,"mmd") || !strcmp(which,"amd") || !strcmp(which,"md")) taucs_ccs_amd(m,perm,invperm,which); else if (!strcmp(which,"metis")) taucs_ccs_metis(m,perm,invperm,which); else if (!strcmp(which,"genmmd")) taucs_ccs_genmmd(m,perm,invperm,which); else if (!strcmp(which,"colamd")) taucs_ccs_colamd(m,perm,invperm,which); else if (!strcmp(which,"random")) taucs_ccs_randomperm(m->n,perm,invperm); else if (!strcmp(which,"tree")) { taucs_ccs_treeorder(m,perm,invperm); if (*perm == NULL) /* perhaps the graph of the matrix is not a tree */ taucs_ccs_metis(m,perm,invperm,"metis"); } else if (!strcmp(which,"identity")) { int i; *perm = (int*) taucs_malloc((m->n) * sizeof(int)); *invperm = (int*) taucs_malloc((m->n) * sizeof(int)); if (!(*perm) || !(*invperm)) { taucs_free(*perm); taucs_free(*invperm); *perm = *invperm = NULL; taucs_printf("taucs_ccs_order: out of memory for identity permutation\n"); return; } for (i=0; i<m->n; i++) (*perm)[i] = (*invperm)[i] = i; return; } else { taucs_printf("taucs_ccs_order: invalid ordering requested (%s)\n",which); *perm = *invperm = NULL; } }
void taucs_sccs_times_vec_dacc(taucs_ccs_matrix * m, taucs_single * X, taucs_single * B) { int i, ip, j, n; taucs_single Aij; taucs_double *Bd; assert(m->flags & TAUCS_SYMMETRIC); assert(m->flags & TAUCS_LOWER); assert(m->flags & TAUCS_SINGLE); n = m->n; Bd = (taucs_double *) taucs_malloc(n * sizeof(taucs_double)); if (Bd == NULL) { taucs_sccs_times_vec(m, X, B); return; } for (i = 0; i < n; i++) Bd[i] = 0.0; for (j = 0; j < n; j++) { for (ip = (m->colptr)[j]; ip < (m->colptr[j + 1]); ip++) { i = (m->rowind)[ip]; Aij = (m->taucs_values)[ip]; Bd[i] += X[j] * Aij; if (i != j) Bd[j] += X[i] * Aij; } } for (i = 0; i < n; i++) B[i] = (taucs_single) Bd[i]; taucs_free(Bd); }
taucs_ccs_matrix* taucs_dtl(ccs_read_ijv)(char* ijvfilename,int flags,int base) { /* omer - base is 0 when the ijv file is 1-based and 1 when the ijv file is 0-based. we add base to the i's and j's found.*/ FILE* f; taucs_ccs_matrix* m; int* clen; int* is; int* js; taucs_datatype* vs; int ncols, nrows, nnz; int i,j,k,n; double di,dj; taucs_datatype dv; f = fopen (ijvfilename , "r"); if (f == NULL) { taucs_printf("taucs_ccs_read_ijv: could not open ijv file %s\n",ijvfilename); return NULL; } n = 10000; is = (int*) taucs_malloc(n*sizeof(int)); js = (int*) taucs_malloc(n*sizeof(int)); vs = (taucs_datatype*) taucs_malloc(n*sizeof(taucs_datatype)); if (!is || !js || !vs) { taucs_printf("symccs_read_ijv: out of memory\n"); taucs_free(is); taucs_free(js); taucs_free(vs); return NULL; } nnz = 0; nrows = ncols = 0; while (!feof(f)) { if (nnz == n) { n = (int) ( 1.25 * (double) n); taucs_printf("taucs_ccs_read_ijv: allocating %d ijv's\n",n); is = (int*) taucs_realloc(is,n*sizeof(int)); js = (int*) taucs_realloc(js,n*sizeof(int)); vs = (taucs_datatype*) taucs_realloc(vs,n*sizeof(taucs_datatype)); if (!is || !js || !vs) { taucs_printf("taucs_ccs_read_ijv: out of memory\n"); taucs_free(is); taucs_free(js); taucs_free(vs); return NULL; } } #ifdef TAUCS_CORE_DOUBLE if (fscanf(f, "%lg %lg %lg", &di, &dj, &dv) != 3) break; #endif #ifdef TAUCS_CORE_SINGLE if (fscanf(f, "%lg %lg %g", &di, &dj, &dv) != 3) break; #endif #ifdef TAUCS_CORE_COMPLEX { taucs_real_datatype dv_i; taucs_real_datatype dv_r; #ifdef TAUCS_CORE_DCOMPLEX if (fscanf(f, "%lg %lg %lg+%lgi", &di, &dj, &dv_r,&dv_i) != 4) break; #endif #ifdef TAUCS_CORE_SCOMPLEX if (fscanf(f, "%lg %lg %g+%gi", &di, &dj, &dv_r, &dv_i) != 4) break; #endif dv = taucs_complex_create(dv_r,dv_i); } #endif is[nnz] = (int)di+base; js[nnz] = (int)dj+base; vs[nnz] = dv;/*omer*/ /* we read the lower part */ if ((flags & TAUCS_SYMMETRIC) && is[nnz] < js[nnz]) continue; if ((flags & TAUCS_HERMITIAN) && is[nnz] < js[nnz]) continue; nrows = max(is[nnz],nrows); ncols = max(js[nnz],ncols); nnz++; } fclose ( f ); m = (taucs_ccs_matrix*) taucs_malloc(sizeof(taucs_ccs_matrix)); if (!m) { taucs_printf("taucs_ccs_read_ijv: out of memory\n"); taucs_free(is); taucs_free(js); taucs_free(vs); return NULL; } m->n = ncols; m->m = nrows; m->flags = 0; if (flags & TAUCS_SYMMETRIC) m->flags = TAUCS_SYMMETRIC | TAUCS_LOWER; if (flags & TAUCS_HERMITIAN) m->flags = TAUCS_HERMITIAN | TAUCS_LOWER; #ifdef TAUCS_CORE_DOUBLE m->flags |= TAUCS_DOUBLE; #endif #ifdef TAUCS_CORE_SINGLE m->flags |= TAUCS_SINGLE; #endif #ifdef TAUCS_CORE_DCOMPLEX m->flags |= TAUCS_DCOMPLEX; #endif #ifdef TAUCS_CORE_SCOMPLEX m->flags |= TAUCS_SCOMPLEX; #endif clen = (int*) taucs_malloc((ncols+1) * sizeof(int)); m->colptr = (int*) taucs_malloc((ncols+1) * sizeof(int)); m->rowind = (int*) taucs_malloc(nnz * sizeof(int)); m->taucs_values = (taucs_datatype*) taucs_malloc(nnz * sizeof(taucs_datatype)); if (!clen || !(m->colptr) || !(m->rowind) || !(m->rowind)) { taucs_printf("taucs_ccs_read_ijv: out of memory: ncols=%d nnz=%d\n",ncols,nnz); taucs_free(clen); taucs_free(m->colptr); taucs_free(m->rowind); taucs_free(m->taucs_values); taucs_free (m); taucs_free(is); taucs_free(js); taucs_free(vs); return NULL; } for (j=0; j<ncols; j++) clen[j] = 0; for (k=0; k<nnz; k++) { i = is[k] - 1; /* make it 1-based */ j = js[k] - 1; /* make it 1-based */ if ( j<0 || j>ncols ) taucs_printf("j=%d k=%d\n",j,k); ( clen[j] )++; } /* just check */ k = 0; for (j=0; j<ncols; j++) k += clen[j]; if (k!=nnz) taucs_printf("k=%d, nnz=%d\n",k,nnz); assert(k == nnz); /* now compute column pointers */ k = 0; for (j=0; j<ncols; j++) { int tmp; tmp = clen[j]; clen[j] = (m->colptr[j]) = k; k += tmp; } clen[ncols] = (m->colptr[ncols]) = k; assert(clen[ncols] == nnz); /* now read matrix into data structure */ for (k=0; k<nnz; k++) { i = is[k] - 1; /* make it 1-based */ j = js[k] - 1; /* make it 1-based */ assert(i < nrows); assert(j < ncols); (m->taucs_values)[ clen[j] ] = vs[k]; (m->rowind)[ clen[j] ] = i; clen[j] ++; } taucs_free(clen); taucs_free(vs); taucs_free(js); taucs_free(is); taucs_printf("taucs_ccs_read_ijv: read %s, n=%d\n",ijvfilename,m->n); return m; }
static void taucs_ccs_metis(taucs_ccs_matrix * m, int **perm, int **invperm, char *which) { #ifndef TAUCS_CONFIG_METIS taucs_printf("taucs_ccs_metis: METIS routines not linked.\n"); *perm = NULL; *invperm = NULL; return; #else int n, nnz, i, j, ip; int *xadj; int *adj; int num_flag = 0; int options_flag[8]; int *len; int *ptr; /* * taucs_printf("taucs_ccs_metis: starting (%s)\n",which); */ if (!(m->flags & TAUCS_SYMMETRIC) && !(m->flags & TAUCS_HERMITIAN)) { taucs_printf("taucs_ccs_treeorder: METIS 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_metis: the lower part of the matrix must be represented.\n"); *perm = NULL; *invperm = NULL; return; } n = m->n; nnz = (m->colptr)[n]; *perm = (int *) taucs_malloc(n * sizeof(int)); *invperm = (int *) taucs_malloc(n * sizeof(int)); xadj = (int *) taucs_malloc((n + 1) * sizeof(int)); adj = (int *) taucs_malloc(2 * nnz * sizeof(int)); if (!(*perm) || !(*invperm) || !xadj || !adj) { taucs_free(*perm); taucs_free(*invperm); taucs_free(xadj); taucs_free(adj); *perm = *invperm = NULL; return; } ptr = len = *perm; 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]++; } } } xadj[0] = 0; for (i = 1; i <= n; i++) xadj[i] = xadj[i - 1] + len[i - 1]; for (i = 0; i < n; i++) ptr[i] = xadj[i]; 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) { adj[ptr[i]] = j; adj[ptr[j]] = i; ptr[i]++; ptr[j]++; } } } options_flag[0] = 1; /* use these options */ options_flag[1] = 3; /* default */ options_flag[2] = 1; /* default */ options_flag[3] = 1; /* two-side refinement */ options_flag[4] = 0; /* no debug */ options_flag[5] = 1; /* default */ options_flag[6] = 0; /* THIS IS SLOW if non-zero. global nodes */ options_flag[7] = 3; /* number of separators */ METIS_NodeND(&n, xadj, adj, &num_flag, options_flag, *perm, *invperm); taucs_free(xadj); taucs_free(adj); #endif }
static void taucs_ccs_treeorder(taucs_ccs_matrix * m, int **perm, int **invperm) { int n, nnz, i, j, ip, k, p, nleaves; int *adjptr; int *adj; int *len; int *ptr; int *degree; int *leaves; if (!(m->flags & TAUCS_SYMMETRIC) && !(m->flags & TAUCS_HERMITIAN)) { taucs_printf("taucs_ccs_treeorder: tree 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_treeorder: the lower part of the matrix must be represented.\n"); *perm = NULL; *invperm = NULL; return; } n = m->n; nnz = (m->colptr)[n]; taucs_printf("taucs_ccs_treeorder: starting, matrix is %dx%d, # edges=%d\n", n, n, nnz - n); *perm = (int *) taucs_malloc(n * sizeof(int)); *invperm = (int *) taucs_malloc(n * sizeof(int)); /* * we can reuse buffers: don't need invperm until the end */ /* * also, we can reuse perm for leaves but it's messy. */ len = (int *) taucs_malloc(n * sizeof(int)); degree = (int *) taucs_malloc(n * sizeof(int)); leaves = (int *) taucs_malloc(n * sizeof(int)); adjptr = (int *) taucs_malloc(n * sizeof(int)); adj = (int *) taucs_malloc(2 * (nnz - n) * sizeof(int)); if (!(*perm) || !(*invperm) || !adjptr || !adj || !len || !degree || !leaves) { taucs_free(adj); taucs_free(adjptr); taucs_free(len); taucs_free(leaves); taucs_free(degree); taucs_free(*perm); taucs_free(*invperm); *perm = *invperm = NULL; } 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]++; } } } nleaves = 0; for (i = 0; i < n; i++) { degree[i] = len[i]; if (degree[i] <= 1) { leaves[nleaves] = i; nleaves++; } } adjptr[0] = 0; for (i = 1; i < n; i++) adjptr[i] = adjptr[i - 1] + len[i - 1]; ptr = *perm; for (i = 0; i < n; i++) ptr[i] = adjptr[i]; 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) { adj[ptr[i]] = j; adj[ptr[j]] = i; ptr[i]++; ptr[j]++; } } } /* * taucs_printf("taucs_ccs_treeorder: %d initial leaves: ",nleaves); for (i=0; i<nleaves; i++) taucs_printf("%d * ",leaves[i]); taucs_printf("\n"); */ for (i = 0; i < n; i++) { nleaves--; if (nleaves <= 0) { /* * not a tree */ taucs_free(adj); taucs_free(adjptr); taucs_free(len); taucs_free(leaves); taucs_free(degree); taucs_free(*perm); taucs_free(*invperm); *perm = *invperm = NULL; } j = leaves[nleaves]; /* * taucs_printf("taucs_ccs_treeorder: next leaf is %d, degree=%d\n",j,len[j]); */ (*perm)[i] = j; (*invperm)[j] = i; if (len[j] > 0) { if (len[j] != 1) { /* * not a tree */ taucs_free(adj); taucs_free(adjptr); taucs_free(len); taucs_free(leaves); taucs_free(degree); taucs_free(*perm); taucs_free(*invperm); *perm = *invperm = NULL; } p = adj[adjptr[j]]; /* * taucs_printf("taucs_ccs_treeorder: parent of %d is %d\n",j,p); */ for (k = 0; k < len[p]; k++) if (adj[adjptr[p] + k] == j) break; if (k >= len[p]) { /* otherwise j does not show up in p's adjacency list */ /* * not a tree */ taucs_free(adj); taucs_free(adjptr); taucs_free(len); taucs_free(leaves); taucs_free(degree); taucs_free(*perm); taucs_free(*invperm); *perm = *invperm = NULL; } /* * now delete j from p's adjacency list and compress */ len[p]--; for (; k < len[p]; k++) adj[adjptr[p] + k] = adj[adjptr[p] + k + 1]; if (len[p] == 1) { /* degree was higher and now is 1 */ leaves[nleaves] = p; nleaves++; } } } taucs_free(adj); taucs_free(adjptr); taucs_free(len); taucs_free(leaves); taucs_free(degree); /* * taucs_printf("taucs_ccs_treeorder: ordering: "); for (i=0; i<n; i++) taucs_printf("%d ",(*perm)[i]); * taucs_printf("\n"); */ taucs_printf("taucs_ccs_treeorder: done\n"); }
static void taucs_ccs_colamd(taucs_ccs_matrix * m, int **perm, int **invperm, char *which) { #ifndef TAUCS_CONFIG_COLAMD taucs_printf("taucs_ccs_colamd: COLAMD routines not linked.\n"); *perm = NULL; *invperm = NULL; return; #else double knobs[COLAMD_KNOBS]; int Alen; int *A; int *p; int *ip; int k, nnz; int i; if (m->flags & TAUCS_SYMMETRIC || m->flags & TAUCS_HERMITIAN) { taucs_printf("taucs_ccs_colamd: not applicable for symmetric or hermitian matrices\n"); return; } taucs_printf("taucs_ccs_colamd: starting\n"); *perm = NULL; *invperm = NULL; nnz = (m->colptr)[m->n]; p = (int *) taucs_malloc((m->n + 1) * sizeof(int)); ip = (int *) taucs_malloc((m->n + 1) * sizeof(int)); assert(p && ip); Alen = colamd_recommended(nnz, m->m, m->n); A = taucs_malloc(Alen * sizeof(int)); assert(A); assert(A); colamd_set_defaults(knobs); for (i = 0; i <= m->n; i++) p[i] = (m->colptr)[i]; for (k = 0; k < nnz; k++) A[k] = (m->rowind)[k]; taucs_printf("oocsp_ccs_colamd: calling colamd matrix is %dx%d, nnz=%d\n", m->m, m->n, nnz); if (!colamd(m->m, m->n, Alen, A, p, knobs)) { taucs_printf("oocsp_ccs_colamd: colamd failed\n"); taucs_free(A); taucs_free(p); return; } taucs_printf("oocsp_ccs_colamd: colamd returned\n"); taucs_free(A); *perm = p; *invperm = ip; for (i = 0; i < m->n; i++) (*invperm)[(*perm)[i]] = i; #endif }
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 }
static void taucs_ccs_amd(taucs_ccs_matrix * m, int **perm, int **invperm, char *which) { #ifndef TAUCS_CONFIG_AMD taucs_printf("taucs_ccs_amd: AMD routines not linked.\n"); *perm = NULL; *invperm = NULL; return; #else int n, iwlen, pfree, ncmpa, iovflo; int *iw; int *pe; int *degree; int *nv; int *next; int *last; int *head; int *elen; int *w; int *len; int nnz, i, j, ip; taucs_printf("taucs_ccs_amd: starting (%s)\n", which); if (!(m->flags & TAUCS_SYMMETRIC) && !(m->flags & TAUCS_HERMITIAN)) { taucs_printf("taucs_ccs_amd: AMD 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_amd: 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]; pe = (int *) taucs_malloc((n+1) * sizeof(int)); degree = (int *) taucs_malloc(n * sizeof(int)); nv = (int *) taucs_malloc(n * sizeof(int)); next = (int *) taucs_malloc(n * sizeof(int)); last = (int *) taucs_malloc(n * sizeof(int)); head = (int *) taucs_malloc(n * sizeof(int)); elen = (int *) taucs_malloc(n * sizeof(int)); w = (int *) taucs_malloc(n * sizeof(int)); len = (int *) taucs_malloc(n * sizeof(int)); /* * AMD docs recommend iwlen >= 1.2 nnz, but this leads to compressions */ iwlen = n + (int) (10.0 * (nnz - n)); taucs_printf("taucs_ccs_amd: allocating %d ints for iw\n", iwlen); iw = (int *) taucs_malloc(iwlen * sizeof(int)); if (!pe || !degree || !nv || !next || !last || !head || !elen || !w || !len || !iw) { taucs_printf("taucs_ccs_amd: out of memory\n"); taucs_free(pe); taucs_free(degree); taucs_free(nv); taucs_free(next); taucs_free(last); taucs_free(head); taucs_free(elen); taucs_free(w); taucs_free(len); taucs_free(iw); return; } /* * assert(iw && pe && degree && nv && next && last && head && elen && w && len); */ int offset; if (!strcmp(which, "amdc") || !strcmp(which, "amdbarc")){ offset = 0; /* C */ } else { offset = 1; /* Fortran */ } iovflo = INT_MAX; /* for 32-bit only! */ 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]; if (i != j) { len[i]++; len[j]++; } } } pe[0] = offset; for (i = 1; i < n; i++) pe[i] = pe[i - 1] + len[i - 1]; pfree = pe[n - 1] + len[n - 1]; if (offset == 0) { pe[n] = pfree; } /* * use degree as a temporary */ for (i = 0; i < n; i++) degree[i] = pe[i] - offset; for (j = 0; j < n; j++) { for (ip = (m->colptr)[j]; ip < (m->colptr)[j + 1]; ip++) { i = (m->rowind)[ip]; if (i != j) { iw[degree[i]] = j + offset; iw[degree[j]] = i + offset; degree[i]++; degree[j]++; } } } taucs_printf("taucs_ccs_amd: calling amd matrix is %dx%d, nnz=%d\n", n, n, nnz); if (!strcmp(which, "mmd")) amdexa_(&n, pe, iw, len, &iwlen, &pfree, nv, next, last, head, elen, degree, &ncmpa, w, &iovflo); else if (!strcmp(which, "md")) amdtru_(&n, pe, iw, len, &iwlen, &pfree, nv, next, last, head, elen, degree, &ncmpa, w, &iovflo); else if (!strcmp(which, "amdbar")) amdbarnew_(&n, pe, iw, len, &iwlen, &pfree, nv, next, last, head, elen, degree, &ncmpa, w); else if (!strcmp(which, "amd")) amdnew_(&n, pe, iw, len, &iwlen, &pfree, nv, next, last, head, elen, degree, &ncmpa, w); else if (!strcmp(which, "amdc")) GMRFLib_amdc(n, pe, iw, len, iwlen, pfree, nv, next, last, head, elen, degree, ncmpa, w); else if (!strcmp(which, "amdbarc")) GMRFLib_amdbarc(n, pe, iw, len, iwlen, pfree, nv, next, last, head, elen, degree, ncmpa, w); else { taucs_printf("taucs_ccs_amd: WARNING - invalid ordering requested (%s)\n", which); return; } taucs_printf("taucs_ccs_amd: amd returned. optimal iwlen=%d (in this run was %d), %d compressions\n", pfree, iwlen, ncmpa); /* * { FILE* f; f=fopen("p.ijv","w"); for (i=0; i<n; i++) fprintf(f,"%d\n",last[i]); fclose(f); } */ taucs_free(pe); taucs_free(degree); taucs_free(nv); taucs_free(next); /* * free(last ); */ taucs_free(head); taucs_free(elen); taucs_free(w); /* * free(len ); */ taucs_free(iw); for (i = 0; i < n; i++) last[i]--; for (i = 0; i < n; i++) len[last[i]] = i; *perm = last; *invperm = len; #endif }
taucs_ccs_matrix* taucs_dtl(ccs_read_ccs)(char* filename,int flags) { FILE* f; taucs_ccs_matrix* m; /* int* clen; int* is; int* js; taucs_datatype* vs; int ncols, nrows, nnz; int i,ip,j,k,n; */ /* taucs_datatype dv;*/ /* double di,dj;*/ int i,ip,j,N,*pointers; f = fopen(filename ,"r"); if (f == NULL) { taucs_printf("taucs_ccs_read_ccs: could not open ccs file %s\n",filename); return NULL; } fscanf(f,"%d",&N); pointers = (int*) taucs_malloc((N+1)*sizeof(int)); for(i=0; i<N+1; ++i) { fscanf(f,"%d",&pointers[i]); } m = taucs_dtl(ccs_create)(N, N, pointers[N]); for (i=0; i<=N; i++) (m->colptr)[i] = pointers[i]; for(i=0; i<pointers[N]; ++i) fscanf(f,"%d",(m->rowind)+i); #ifdef TAUCS_CORE_DOUBLE for(i=0; i<pointers[N]; ++i) fscanf(f,"%lg",(m->taucs_values)+i); #endif #ifdef TAUCS_CORE_SINGLE for(i=0; i<pointers[N]; ++i) fscanf(f,"%g",(m->taucs_values)+i); #endif #ifdef TAUCS_CORE_DCOMPLEX for(i=0; i<pointers[N]; ++i) { taucs_real_datatype dv_r; taucs_real_datatype dv_i; fscanf(f,"%lg+%lgi",&dv_r,&dv_i); (m->taucs_values)[i] = taucs_complex_create(dv_r,dv_i); } #endif #ifdef TAUCS_CORE_SCOMPLEX for(i=0; i<pointers[N]; ++i) { taucs_real_datatype dv_r; taucs_real_datatype dv_i; fscanf(f,"%g+%gi",&dv_r,&dv_i); (m->taucs_values)[i] = taucs_complex_create(dv_r,dv_i); } #endif if (flags & TAUCS_SYMMETRIC) { m->flags = TAUCS_SYMMETRIC | TAUCS_LOWER; for (j=0; j<N; j++) { for (ip=(m->colptr)[j]; ip<(m->colptr)[j+1]; ip++) { i = (m->rowind)[ip]; assert(i >= j); } } } else m->flags = 0; #ifdef TAUCS_CORE_DOUBLE m->flags |= TAUCS_DOUBLE; #endif #ifdef TAUCS_CORE_SINGLE m->flags |= TAUCS_SINGLE; #endif #ifdef TAUCS_CORE_DCOMPLEX m->flags |= TAUCS_DCOMPLEX; #endif #ifdef TAUCS_CORE_SCOMPLEX m->flags |= TAUCS_SCOMPLEX; #endif taucs_free(pointers); taucs_printf("taucs_ccs_read_ccs: read %s, n=%d\n",filename,m->n); return m; }
taucs_ccs_matrix *taucs_dtl(ccs_permute_symmetrically) (taucs_ccs_matrix * A, int *perm, int *invperm) { taucs_ccs_matrix *PAPT; int n; int nnz; /* * int* colptr; */ int *len; int i, j, ip, I, J; taucs_datatype AIJ; assert(A->flags & TAUCS_SYMMETRIC || A->flags & TAUCS_HERMITIAN); assert(A->flags & TAUCS_LOWER); n = A->n; nnz = (A->colptr)[n]; PAPT = taucs_dtl(ccs_create) (n, n, nnz); if (!PAPT) return NULL; /* * PAPT->flags = TAUCS_SYMMETRIC | TAUCS_LOWER; */ PAPT->flags = A->flags; len = (int *) taucs_malloc(n * sizeof(int)); /* * colptr = (int*) taucs_malloc(n * sizeof(int)); */ if (!len) { taucs_printf("taucs_ccs_permute_symmetrically: out of memory\n"); taucs_ccs_free(PAPT); return NULL; } for (j = 0; j < n; j++) len[j] = 0; for (j = 0; j < n; j++) { for (ip = (A->colptr)[j]; ip < (A->colptr)[j + 1]; ip++) { /* * i = (A->rowind)[ip] - (A->indshift); */ i = (A->rowind)[ip]; I = invperm[i]; J = invperm[j]; if (I < J) { int T = I; I = J; J = T; } len[J]++; } } (PAPT->colptr)[0] = 0; for (j = 1; j <= n; j++) (PAPT->colptr)[j] = (PAPT->colptr)[j - 1] + len[j - 1]; for (j = 0; j < n; j++) len[j] = (PAPT->colptr)[j]; for (j = 0; j < n; j++) { for (ip = (A->colptr)[j]; ip < (A->colptr)[j + 1]; ip++) { /* * i = (A->rowind)[ip] - (A->indshift); */ i = (A->rowind)[ip]; AIJ = (A->taucs_values)[ip]; I = invperm[i]; J = invperm[j]; if (I < J) { int T = I; I = J; J = T; if (A->flags & TAUCS_HERMITIAN) AIJ = taucs_conj(AIJ); } /* * (PAPT->rowind)[ len[J] ] = I + (PAPT->indshift); */ (PAPT->rowind)[len[J]] = I; (PAPT->taucs_values)[len[J]] = AIJ; len[J]++; } } taucs_free(len); return PAPT; }
taucs_ccs_matrix* taucs_ccs_read_binary(char* filename) { taucs_ccs_matrix* A = NULL; /* warning*/ int nrows,ncols,flags,j;/*nnz, omer*/ int f; ssize_t bytes_read; int* colptr; taucs_printf("taucs_ccs_binary: reading binary matrix %s\n",filename); #ifdef OSTYPE_win32 f = open(filename,_O_RDONLY |_O_BINARY); #else f = open(filename,O_RDONLY); #endif /*f = open(filename,O_RDONLY);*/ bytes_read = read(f,&nrows,sizeof(int)); bytes_read = read(f,&ncols,sizeof(int)); bytes_read = read(f,&flags,sizeof(int)); taucs_printf("\t%d-by-%d, flags = %08x\n",nrows,ncols,flags); taucs_printf("\t%d-by-%d, flags = %d \n",nrows,ncols,flags); colptr = (int*) taucs_malloc((ncols+1) * sizeof(int)); assert(colptr); bytes_read = read(f,colptr,(ncols+1)*sizeof(int)); taucs_printf("colptr = ["); for(j=0; j<min(ncols-1,10); j++) taucs_printf("%d,",colptr[j]); taucs_printf("...,%d]\n",colptr[ncols]); if ( 0 ) /* we need this so that we have 'else if' in each type */ {} #ifdef TAUCS_DOUBLE_IN_BUILD else if (flags & TAUCS_DOUBLE) { A = taucs_dccs_create(nrows,ncols,colptr[ncols]); if (!A) return NULL; bytes_read = read(f,A->rowind,colptr[ncols]*sizeof(int)); bytes_read = read(f,A->values.d,colptr[ncols]*sizeof(taucs_double)); } #endif #ifdef TAUCS_SINGLE_IN_BUILD else if (flags & TAUCS_SINGLE) { A = taucs_sccs_create(nrows,ncols,colptr[ncols]); if (!A) return NULL; bytes_read = read(f,A->rowind,colptr[ncols]*sizeof(int)); bytes_read = read(f,A->values.s,colptr[ncols]*sizeof(taucs_single)); } #endif #ifdef TAUCS_DCOMPLEX_IN_BUILD else if (flags & TAUCS_DCOMPLEX) { A = taucs_zccs_create(nrows,ncols,colptr[ncols]); if (!A) return NULL; bytes_read = read(f,A->rowind,colptr[ncols]*sizeof(int)); bytes_read = read(f,A->values.z,colptr[ncols]*sizeof(taucs_dcomplex)); } #endif #ifdef TAUCS_SCOMPLEX_IN_BUILD else if (flags & TAUCS_SCOMPLEX) { A = taucs_cccs_create(nrows,ncols,colptr[ncols]); if (!A) return NULL; bytes_read = read(f,A->rowind,colptr[ncols]*sizeof(int)); bytes_read = read(f,A->values.c,colptr[ncols]*sizeof(taucs_scomplex)); } #endif else { assert(0); } A->flags = flags; for (j=0; j<=ncols; j++) (A->colptr)[j] = colptr[j]; taucs_free(colptr); close(f); taucs_printf("taucs_ccs_read_binary: done reading\n"); return A; }
/* split into left p columns, right p columns */ void taucs_dtl(ccs_split) (taucs_ccs_matrix * A, taucs_ccs_matrix ** L, taucs_ccs_matrix ** R, int p) { int i, n; int Lnnz, Rnnz; assert((A->flags & TAUCS_SYMMETRIC) || (A->flags & TAUCS_TRIANGULAR)); assert(A->flags & TAUCS_LOWER); n = A->n; *L = (taucs_ccs_matrix *) taucs_malloc(sizeof(taucs_ccs_matrix)); *R = (taucs_ccs_matrix *) taucs_malloc(sizeof(taucs_ccs_matrix)); if (!(*L) || !(*R)) { taucs_printf("taucs_ccs_split: out of memory\n"); taucs_free(*L); taucs_free(*R); *L = *R = NULL; return; } Lnnz = 0; for (i = 0; i < p; i++) Lnnz += ((A->colptr)[i + 1] - (A->colptr)[i]); (*L)->flags |= TAUCS_SYMMETRIC | TAUCS_LOWER; (*L)->n = n; (*L)->m = n; (*L)->colptr = (int *) taucs_malloc((n + 1) * sizeof(int)); (*L)->rowind = (int *) taucs_malloc(Lnnz * sizeof(int)); (*L)->taucs_values = (void *) taucs_malloc(Lnnz * sizeof(taucs_datatype)); if (!((*L)->colptr) || !((*L)->rowind) || !((*L)->rowind)) { taucs_printf("taucs_ccs_split: out of memory: n=%d nnz=%d\n", n, Lnnz); taucs_free((*L)->colptr); taucs_free((*L)->rowind); taucs_free((*L)->taucs_values); taucs_free((*L)); return; } for (i = 0; i <= p; i++) ((*L)->colptr)[i] = (A->colptr)[i]; for (i = p + 1; i < n + 1; i++) ((*L)->colptr)[i] = ((*L)->colptr)[p]; /* other columns are empty */ for (i = 0; i < Lnnz; i++) { ((*L)->rowind)[i] = (A->rowind)[i]; ((*L)->taucs_values)[i] = (A->taucs_values)[i]; } /* * now copy right part of matrix into a p-by-p matrix */ Rnnz = 0; for (i = p; i < n; i++) Rnnz += ((A->colptr)[i + 1] - (A->colptr)[i]); (*R)->flags = TAUCS_SYMMETRIC | TAUCS_LOWER; (*R)->n = n - p; (*R)->m = n - p; (*R)->colptr = (int *) taucs_malloc((n - p + 1) * sizeof(int)); (*R)->rowind = (int *) taucs_malloc(Rnnz * sizeof(int)); (*R)->taucs_values = (void *) taucs_malloc(Rnnz * sizeof(taucs_datatype)); if (!((*R)->colptr) || !((*R)->rowind) || !((*R)->rowind)) { taucs_printf("taucs_ccs_split: out of memory (3): p=%d nnz=%d\n", p, Rnnz); taucs_free((*R)->colptr); taucs_free((*R)->rowind); taucs_free((*R)->taucs_values); taucs_free((*L)->colptr); taucs_free((*L)->rowind); taucs_free((*L)->taucs_values); taucs_free((*R)); taucs_free((*L)); return; } for (i = 0; i <= (n - p); i++) ((*R)->colptr)[i] = (A->colptr)[i + p] - Lnnz; for (i = 0; i < Rnnz; i++) { ((*R)->rowind)[i] = (A->rowind)[i + Lnnz] - p; ((*R)->taucs_values)[i] = (A->taucs_values)[i + Lnnz]; } }
taucs_ccs_matrix *taucs_dtl(ccs_augment_nonpositive_offdiagonals) (taucs_ccs_matrix * A) { #ifdef TAUCS_CORE_COMPLEX assert(0); #else int n, i, j; int *tmp; taucs_ccs_matrix *A_tmp; if (!(A->flags & TAUCS_SYMMETRIC) || !(A->flags & TAUCS_LOWER)) { taucs_printf("taucs_ccs_augment_nonpositive_offdiagonal: matrix not symmetric or not lower\n"); return NULL; } n = A->n; tmp = (int *) taucs_calloc((2 * n + 1), sizeof(int)); if (!tmp) { taucs_printf("taucs_ccs_augment_nonpositive_offdiagonal: out of memory\n"); return NULL; } A_tmp = taucs_dtl(ccs_create) (2 * n, 2 * n, 2 * (A->colptr[n])); if (A_tmp == NULL) { taucs_free(tmp); return NULL; } A_tmp->flags |= TAUCS_SYMMETRIC | TAUCS_LOWER; for (i = 0; i < n; i++) { for (j = A->colptr[i]; j < A->colptr[i + 1]; j++) { if ((i == A->rowind[j]) || (A->taucs_values[j] < 0)) { tmp[i]++; tmp[i + n]++; } else { tmp[i]++; tmp[A->rowind[j]]++; } } } A_tmp->colptr[0] = 0; for (i = 0; i < 2 * n; i++) A_tmp->colptr[i + 1] = A_tmp->colptr[i] + tmp[i]; for (i = 0; i < 2 * n; i++) tmp[i] = A_tmp->colptr[i]; for (i = 0; i < n; i++) { for (j = A->colptr[i]; j < A->colptr[i + 1]; j++) { if ((i == A->rowind[j]) || (A->taucs_values[j] < 0)) { A_tmp->rowind[tmp[i]] = A->rowind[j]; A_tmp->taucs_values[tmp[i]++] = A->taucs_values[j]; A_tmp->rowind[tmp[i + n]] = A->rowind[j] + n; A_tmp->taucs_values[tmp[i + n]++] = A->taucs_values[j]; } else { A_tmp->rowind[tmp[i]] = A->rowind[j] + n; A_tmp->taucs_values[tmp[i]++] = -A->taucs_values[j]; A_tmp->rowind[tmp[A->rowind[j]]] = i + n; A_tmp->taucs_values[tmp[A->rowind[j]]++] = -A->taucs_values[j]; } } } taucs_free(tmp); return A_tmp; #endif /* * added omer */ return NULL; }
taucs_ccs_matrix* taucs_dtl(ccs_read_mtx)(char* filename,int flags) { FILE* f; taucs_ccs_matrix* m; int* clen; int* is; int* js; taucs_datatype* vs; int ncols, nrows, nnz; int i,j,k,n; double di,dj; taucs_datatype dv; f = fopen (filename , "r"); if (f == NULL) { taucs_printf("taucs_ccs_read_mtx: could not open mtx file %s\n",filename); return NULL; } if (fscanf(f, "%d %d %d", &nrows, &ncols, &nnz) != 3) { taucs_printf("taucs_ccs_read_mtx: wrong header\n"); return NULL; } n = 10000; is = (int*) taucs_malloc(n*sizeof(int)); js = (int*) taucs_malloc(n*sizeof(int)); vs = (taucs_datatype*) taucs_malloc(n*sizeof(taucs_datatype)); if (!is || !js || !vs) { taucs_printf("taucs_ccs_read_mtx: out of memory\n"); taucs_free(is); taucs_free(js); taucs_free(vs); return NULL; } nnz = 0; nrows = ncols = 0; while (!feof(f)) { if (nnz == n) { n = (int) ( 1.25 * (double) n); taucs_printf("taucs_ccs_read_mtx: allocating %d ijv's\n",n); is = (int*) taucs_realloc(is,n*sizeof(int)); js = (int*) taucs_realloc(js,n*sizeof(int)); vs = (taucs_datatype*) taucs_realloc(vs,n*sizeof(taucs_datatype)); if (!is || !js || !vs) { taucs_printf("taucs_ccs_read_mtx: out of memory\n"); taucs_free(is); taucs_free(js); taucs_free(vs); return NULL; } } #ifdef TAUCS_CORE_DOUBLE if (fscanf(f, "%lg %lg %lg", &di, &dj, &dv) != 3) break; #endif #ifdef TAUCS_CORE_SINGLE if (fscanf(f, "%lg %lg %g", &di, &dj, &dv) != 3) break; #endif #ifdef TAUCS_CORE_COMPLEX { taucs_real_datatype dv_i; taucs_real_datatype dv_r; #ifdef TAUCS_CORE_DCOMPLEX if (fscanf(f, "%lg %lg %lg+%lgi", &di, &dj, &dv_r,&dv_i) != 4) break; #endif #ifdef TAUCS_CORE_SCOMPLEX if (fscanf(f, "%lg %lg %g+%gi", &di, &dj, &dv_r,&dv_i) != 4) break; #endif dv = taucs_complex_create(dv_r,dv_i); } #endif is[nnz] = (int)di; js[nnz] = (int)dj; vs[nnz] = dv;/*omer*/ /* upper or lower might be stored, we use lower */ if ((flags & TAUCS_SYMMETRIC) && is[nnz] < js[nnz]) { int t = is[nnz]; is[nnz] = js[nnz]; js[nnz] = t; } if (flags & TAUCS_PATTERN) { #ifdef TAUCS_CORE_DOUBLE if (is[nnz] == js[nnz]) vs[nnz] = (double) (nrows+1); else vs[nnz] = -1.0; #endif #ifdef TAUCS_CORE_SINGLE if (is[nnz] == js[nnz]) vs[nnz] = (float) (nrows+1); else vs[nnz] = -1.0; #endif #ifdef TAUCS_CORE_DCOMPEX assert(0); #endif #ifdef TAUCS_CORE_SCOMPLEX assert(0); #endif } nrows = max(is[nnz],nrows); ncols = max(js[nnz],ncols); nnz++; } fclose ( f ); m = (taucs_ccs_matrix*) taucs_malloc(sizeof(taucs_ccs_matrix)); if (!m) { taucs_printf("taucs_ccs_read_mtx: out of memory\n"); taucs_free(is); taucs_free(js); taucs_free(vs); return NULL; } m->n = nrows; m->m = ncols; if (flags & TAUCS_SYMMETRIC) m->flags = TAUCS_SYMMETRIC | TAUCS_LOWER; else m->flags = 0; #ifdef TAUCS_CORE_DOUBLE m->flags |= TAUCS_DOUBLE; #endif #ifdef TAUCS_CORE_SINGLE m->flags |= TAUCS_SINGLE; #endif #ifdef TAUCS_CORE_DCOMPLEX m->flags |= TAUCS_DCOMPLEX; #endif #ifdef TAUCS_CORE_SCOMPLEX m->flags |= TAUCS_SCOMPLEX; #endif clen = (int*) taucs_malloc((ncols+1) * sizeof(int)); m->colptr = (int*) taucs_malloc((ncols+1) * sizeof(int)); m->rowind = (int*) taucs_malloc(nnz * sizeof(int)); m->taucs_values = (taucs_datatype*) taucs_malloc(nnz * sizeof(taucs_datatype)); if (!clen || !(m->colptr) || !(m->rowind) || !(m->rowind)) { taucs_printf("taucs_ccs_read_mtx: out of memory: ncols=%d nnz=%d\n",ncols,nnz); taucs_free(clen); taucs_free(m->colptr); taucs_free(m->rowind); taucs_free(m->taucs_values); taucs_free (m); taucs_free(is); taucs_free(js); taucs_free(vs); return NULL; } for (j=0; j<ncols; j++) clen[j] = 0; for (k=0; k<nnz; k++) { i = is[k] - 1; /* make it 1-based */ j = js[k] - 1; /* make it 1-based */ ( clen[j] )++; } /* just check */ k = 0; for (j=0; j<ncols; j++) k += clen[j]; assert(k == nnz); /* now compute column pointers */ k = 0; for (j=0; j<ncols; j++) { int tmp; tmp = clen[j]; clen[j] = (m->colptr[j]) = k; k += tmp; } clen[ncols] = (m->colptr[ncols]) = k; assert(clen[ncols] == nnz); /* now read matrix into data structure */ for (k=0; k<nnz; k++) { i = is[k] - 1; /* make it 1-based */ j = js[k] - 1; /* make it 1-based */ assert(i < nrows); assert(j < ncols); (m->taucs_values)[ clen[j] ] = vs[k]; (m->rowind)[ clen[j] ] = i; clen[j] ++; } taucs_free(clen); taucs_free(vs); taucs_free(js); taucs_free(is); taucs_printf("taucs_ccs_read_mtx: read %s, n=%d\n",filename,m->n); return m; }
static void taucs_ccs_metis(taucs_ccs_matrix* m, int** perm, int** invperm, char* which) { #ifndef TAUCS_CONFIG_METIS taucs_printf("taucs_ccs_metis: METIS routines not linked.\n"); *perm = NULL; *invperm = NULL; return; #else int n,nnz,i,j,ip; int* xadj; int* adj; int num_flag = 0; int options_flag = 0; int* len; int* ptr; /* taucs_printf("taucs_ccs_metis: starting (%s)\n",which); */ if (!(m->flags & TAUCS_SYMMETRIC) && !(m->flags & TAUCS_HERMITIAN)) { taucs_printf("taucs_ccs_treeorder: METIS 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_metis: the lower part of the matrix must be represented.\n"); *perm = NULL; *invperm = NULL; return; } n = m->n; nnz = (m->colptr)[n]; *perm = (int*) taucs_malloc(n * sizeof(int)); *invperm = (int*) taucs_malloc(n * sizeof(int)); xadj = (int*) taucs_malloc((n+1) * sizeof(int)); /* Change suggested by Yifan Hu for diagonal matrices */ /* and for matrices with no diagonal */ /* adj = (int*) taucs_malloc(2*(nnz-n) * sizeof(int));*/ adj = (int*) taucs_malloc(2* nnz * sizeof(int)); if (!(*perm) || !(*invperm) || !xadj || !adj) { taucs_free(*perm); taucs_free(*invperm); taucs_free(xadj); taucs_free(adj); *perm = *invperm = NULL; return; } /* assert(*perm && *invperm && xadj && adj);*/ ptr = len = *perm; 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] ++; } } } xadj[0] = 0; for (i=1; i<=n; i++) xadj[i] = xadj[i-1] + len[i-1]; for (i=0; i<n; i++) ptr[i] = xadj[i]; 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) { adj[ ptr[i] ] = j; adj[ ptr[j] ] = i; ptr[i] ++; ptr[j] ++; } } } /* taucs_printf("taucs_ccs_metis: calling metis matrix is %dx%d, nnz=%d\n", */ /* n,n,nnz); */ METIS_NodeND(&n, xadj,adj, &num_flag, &options_flag, *perm,*invperm); /* taucs_printf("taucs_ccs_metis: metis returned\n"); */ /* { FILE* f; f=fopen("p.ijv","w"); for (i=0; i<n; i++) fprintf(f,"%d\n",last[i]); fclose(f); } */ taucs_free(xadj); taucs_free(adj); #endif }