void Project_Recur(int oldid, int n, double *a, int *bmap, int lev, Bsystem *Bsys){ register int i,j; int alen,clen,ptchid,cstart,*map,cnt; int *linka, *linkc; double *A,*B,*C; Recur *rdata = Bsys->rslv->rdata+lev; if(!n) return; linka = ivector(0,n-1); linkc = ivector(0,n-1); ifill(n,-1,linka,1); ifill(n,-1,linkc,1); cstart = rdata->cstart; ptchid = rdata->pmap[oldid]; A = Bsys->rslv->A.a[ptchid]; B = rdata->binvc[ptchid]; C = rdata->invc [ptchid]; map = rdata->map[ptchid]; alen = rdata->patchlen_a[ptchid]; clen = rdata->patchlen_c[ptchid]; cnt = cstart + isum(ptchid,rdata->patchlen_c,1); /* set up local mappings for matrix a to next system */ for(i = 0; i < n; ++i){ if(bmap[i] < Bsys->nsolve){ if(bmap[i] < cstart){ for(j = 0; j < alen; ++j) if(bmap[i] == map[j]) linka[i] = j; } else linkc[i] = bmap[i] - cnt; } } /* project a to new local storage */ for(i = 0; i < n; ++i) for(j = 0; j < n; ++j) if((linka[i]+1)&&(linka[j]+1)) A[alen*linka[i] + linka[j]] += a[i*n + j]; else if((linka[i]+1)&&(linkc[j]+1)) B[clen*linka[i] + linkc[j]] += a[i*n + j]; else if((linkc[i]+1)&&(linkc[j]+1)) C[clen*linkc[i] + linkc[j]] += a[i*n + j]; free(linka); free(linkc); }
/* * Set up pointers for integer working arrays. */ void SetIWork(int m, int n, int panel_size, int *iworkptr, int **segrep, int **parent, int **xplore, int **repfnz, int **panel_lsub, int **xprune, int **marker) { *segrep = iworkptr; *parent = iworkptr + m; *xplore = *parent + m; *repfnz = *xplore + m; *panel_lsub = *repfnz + panel_size * m; *xprune = *panel_lsub + panel_size * m; *marker = *xprune + n; ifill (*repfnz, m * panel_size, EMPTY); ifill (*panel_lsub, m * panel_size, EMPTY); }
/*! \brief * * <pre> * Purpose * ======= * ilu_relax_snode() - Identify the initial relaxed supernodes, assuming * that the matrix has been reordered according to the postorder of the * etree. * </pre> */ void ilu_relax_snode ( const int n, int *et, /* column elimination tree */ const int relax_columns, /* max no of columns allowed in a relaxed snode */ int *descendants, /* no of descendants of each node in the etree */ int *relax_end, /* last column in a supernode * if j-th column starts a relaxed * supernode, relax_end[j] represents * the last column of this supernode */ int *relax_fsupc /* first column in a supernode * relax_fsupc[j] represents the first * column of j-th supernode */ ) { register int j, f, parent; register int snode_start; /* beginning of a snode */ ifill (relax_end, n, EMPTY); ifill (relax_fsupc, n, EMPTY); for (j = 0; j < n; j++) descendants[j] = 0; /* Compute the number of descendants of each node in the etree */ for (j = 0; j < n; j++) { parent = et[j]; if ( parent != n ) /* not the dummy root */ descendants[parent] += descendants[j] + 1; } /* Identify the relaxed supernodes by postorder traversal of the etree. */ for (j = f = 0; j < n; ) { parent = et[j]; snode_start = j; while ( parent != n && descendants[parent] < relax_columns ) { j = parent; parent = et[j]; } /* Found a supernode with j being the last column. */ relax_end[snode_start] = j; /* Last column is recorded */ j++; relax_fsupc[f++] = snode_start; /* Search for a new leaf */ while ( descendants[j] != 0 && j < n ) j++; } }
void super_stats(int nsuper, int *xsup, int *xsup_end) { register int nsup1 = 0; int i, isize, whichb, bl, bh; int bucket[NBUCKS]; max_sup_size = 0; /* Histogram of the supernode sizes */ ifill (bucket, NBUCKS, 0); for (i = 0; i <= nsuper; i++) { isize = xsup_end[i] - xsup[i]; if ( isize == 1 ) nsup1++; if ( max_sup_size < isize ) max_sup_size = isize; whichb = (float) isize / max_sup_size * NBUCKS; if (whichb >= NBUCKS) whichb = NBUCKS - 1; bucket[whichb]++; } printf("** Supernode statistics:\n\tno of supernodes = %d\n", nsuper+1); printf("\tmax supernode size = %d\n", max_sup_size); printf("\tno of size 1 supernodes = %d\n", nsup1); printf("\tHistogram of supernode size:\n"); for (i = 0; i < NBUCKS; i++) { bl = (float) i * max_sup_size / NBUCKS; bh = (float) (i+1) * max_sup_size / NBUCKS; printf("\t%3d-%3d\t\t%d\n", bl+1, bh, bucket[i]); } }
int cbayes_markov_init(bvar *var) { int i, j; bvar *c; if (var->observed) return 0; ifill(var->state_count, var->dist->len, 0); if (var->mb_child_base != NULL) free(var->mb_child_base); if (var->mb_child_idx != NULL) free(var->mb_child_idx); var->mb_child_base = (int*) malloc(sizeof(int) * var->nchildren); var->mb_child_idx = (int*) malloc(sizeof(int) * var->nchildren); for (i=0; i<var->nchildren; i++) { c = var->children[i]; var->mb_child_base[i] = 1; for (j=c->nparents-1; j>=0; j--) if (c->parents[j] == var) break; else var->mb_child_base[i] *= c->parents[j]->dist->len; } }
/* * Set up pointers for integer working arrays. */ void pxgstrf_SetIWork(int n, int panel_size, int *iworkptr, int **segrep, int **parent, int **xplore, int **repfnz, int **panel_lsub, int **marker, int **lbusy) { *segrep = iworkptr; /* n */ *parent = iworkptr + n; /* n */ *xplore = iworkptr + 2*n; /* 2*n */ *repfnz = iworkptr + 4*n; /* w*n */ *panel_lsub = iworkptr + 4*n + panel_size*n; /* w*n */ *marker = iworkptr + 4*n + 2*panel_size*n; /* 3*n */ *lbusy = iworkptr + (4+NO_MARKER)*n + 2*panel_size*n; /* n */ ifill (*repfnz, n * panel_size, EMPTY); }
void relax_snode ( const int n, int *et, /* column elimination tree */ const int relax_columns, /* max no of columns allowed in a relaxed snode */ int *descendants, /* no of descendants of each node in the etree */ int *relax_end /* last column in a supernode */ ) { /* * Purpose * ======= * relax_snode() - Identify the initial relaxed supernodes, assuming that * the matrix has been reordered according to the postorder of the etree. * */ register int j, parent; register int snode_start; /* beginning of a snode */ ifill (relax_end, n, EMPTY); for (j = 0; j < n; j++) descendants[j] = 0; /* Compute the number of descendants of each node in the etree */ for (j = 0; j < n; j++) { parent = et[j]; if ( parent != n ) /* not the dummy root */ descendants[parent] += descendants[j] + 1; } /* Identify the relaxed supernodes by postorder traversal of the etree. */ for (j = 0; j < n; ) { parent = et[j]; snode_start = j; while ( parent != n && descendants[parent] < relax_columns ) { j = parent; parent = et[j]; } /* Found a supernode with j being the last column. */ relax_end[snode_start] = j; /* Last column is recorded */ j++; /* Search for a new leaf */ while ( descendants[j] != 0 && j < n ) j++; } /*printf("No of relaxed snodes: %d; relaxed columns: %d\n", nsuper, no_relaxed_col); */ }
/* * Calculate conditional probability distribution given probability function * and conditioning distributions. * * RUNNING TIME: mul = O(dist->len*SIGMA(dist[i]->len)) * * @param func * probability function * @param dist * array of probability distributions * @param cond * target probability distribution * @return * 0 on success, or error code */ int cbayes_conditional(pfunc *func, pdist **dist, pdist *cond) { // cache pointers, precompute int i, j, b; int clen = func->condlen; int nvars = func->nvars; int nvn1 = nvars - 1; int *idx = func->idx; int *len = func->len; double *val = func->val; double *fdist = func->dist; double **cdist = func->cdist; double *tdist = cond->dist; for (i=0; i<func->nvars; i++) cdist[i] = dist[i]->dist; // initialize to zeros ifill(idx, nvars, 0); ffill(tdist, clen, 0.0); // loop every conditional combination for (i=0; i<clen; i++) { // increment recursive index j = nvn1; while (j >= 0 && (++idx[j] == len[j+1])) idx[j--] = 0; // multiple conditional probabilities together for (; j<nvars; j++) val[j+1] = val[j] * cdist[j][idx[j]]; // multiply by function into target for (j=0, b=i; j<len[0]; j++, b+=cond->len) tdist[j] += cdist[b] * val[nvars]; } // correct within normal tolerance correct(cond->dist, cond->len); return 0; }
void zgstrf (char *refact, SuperMatrix *A, double diag_pivot_thresh, double drop_tol, int relax, int panel_size, int *etree, void *work, int lwork, int *perm_r, int *perm_c, SuperMatrix *L, SuperMatrix *U, int *info) { /* * Purpose * ======= * * ZGSTRF computes an LU factorization of a general sparse m-by-n * matrix A using partial pivoting with row interchanges. * The factorization has the form * Pr * A = L * U * where Pr is a row permutation matrix, L is lower triangular with unit * diagonal elements (lower trapezoidal if A->nrow > A->ncol), and U is upper * triangular (upper trapezoidal if A->nrow < A->ncol). * * See supermatrix.h for the definition of 'SuperMatrix' structure. * * Arguments * ========= * * refact (input) char* * Specifies whether we want to use perm_r from a previous factor. * = 'Y': re-use perm_r; perm_r is input, and may be modified due to * different pivoting determined by diagonal threshold. * = 'N': perm_r is determined by partial pivoting, and output. * * A (input) SuperMatrix* * Original matrix A, permuted by columns, of dimension * (A->nrow, A->ncol). The type of A can be: * Stype = SLU_NCP; Dtype = SLU_Z; Mtype = SLU_GE. * * diag_pivot_thresh (input) double * Diagonal pivoting threshold. At step j of the Gaussian elimination, * if abs(A_jj) >= thresh * (max_(i>=j) abs(A_ij)), use A_jj as pivot. * 0 <= thresh <= 1. The default value of thresh is 1, corresponding * to partial pivoting. * * drop_tol (input) double (NOT IMPLEMENTED) * Drop tolerance parameter. At step j of the Gaussian elimination, * if abs(A_ij)/(max_i abs(A_ij)) < drop_tol, drop entry A_ij. * 0 <= drop_tol <= 1. The default value of drop_tol is 0. * * relax (input) int * To control degree of relaxing supernodes. If the number * of nodes (columns) in a subtree of the elimination tree is less * than relax, this subtree is considered as one supernode, * regardless of the row structures of those columns. * * panel_size (input) int * A panel consists of at most panel_size consecutive columns. * * etree (input) int*, dimension (A->ncol) * Elimination tree of A'*A. * 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. * On input, the columns of A should be permuted so that the * etree is in a certain postorder. * * work (input/output) void*, size (lwork) (in bytes) * User-supplied work space and space for the output data structures. * Not referenced if lwork = 0; * * lwork (input) int * Specifies the size of work array in bytes. * = 0: allocate space internally by system malloc; * > 0: use user-supplied work array of length lwork in bytes, * returns error if space runs out. * = -1: the routine guesses the amount of space needed without * performing the factorization, and returns it in * *info; no other side effects. * * perm_r (input/output) int*, dimension (A->nrow) * Row permutation vector which defines the permutation matrix Pr, * perm_r[i] = j means row i of A is in position j in Pr*A. * If refact is not 'Y', perm_r is output argument; * If refact = 'Y', the pivoting routine will try to use the input * perm_r, unless a certain threshold criterion is violated. * In that case, perm_r is overwritten by a new permutation * determined by partial pivoting or diagonal threshold pivoting. * * perm_c (input) int*, dimension (A->ncol) * Column permutation vector, which defines the * permutation matrix Pc; perm_c[i] = j means column i of A is * in position j in A*Pc. * When searching for diagonal, perm_c[*] is applied to the * row subscripts of A, so that diagonal threshold pivoting * can find the diagonal of A, rather than that of A*Pc. * * L (output) SuperMatrix* * The factor L from the factorization Pr*A=L*U; use compressed row * subscripts storage for supernodes, i.e., L has type: * Stype = SLU_SC, Dtype = SLU_Z, Mtype = SLU_TRLU. * * U (output) SuperMatrix* * The factor U from the factorization Pr*A*Pc=L*U. Use column-wise * storage scheme, i.e., U has types: Stype = SLU_NC, * Dtype = SLU_Z, Mtype = SLU_TRU. * * info (output) int* * = 0: successful exit * < 0: if info = -i, the i-th argument had an illegal value * > 0: if info = i, and i is * <= A->ncol: U(i,i) is exactly zero. The factorization has * been completed, but the factor U is exactly singular, * and division by zero will occur if it is used to solve a * system of equations. * > A->ncol: number of bytes allocated when memory allocation * failure occurred, plus A->ncol. If lwork = -1, it is * the estimated amount of space needed, plus A->ncol. * * ====================================================================== * * Local Working Arrays: * ====================== * m = number of rows in the matrix * n = number of columns in the matrix * * xprune[0:n-1]: xprune[*] points to locations in subscript * vector lsub[*]. For column i, xprune[i] denotes the point where * structural pruning begins. I.e. only xlsub[i],..,xprune[i]-1 need * to be traversed for symbolic factorization. * * marker[0:3*m-1]: marker[i] = j means that node i has been * reached when working on column j. * Storage: relative to original row subscripts * NOTE: There are 3 of them: marker/marker1 are used for panel dfs, * see zpanel_dfs.c; marker2 is used for inner-factorization, * see zcolumn_dfs.c. * * parent[0:m-1]: parent vector used during dfs * Storage: relative to new row subscripts * * xplore[0:m-1]: xplore[i] gives the location of the next (dfs) * unexplored neighbor of i in lsub[*] * * segrep[0:nseg-1]: contains the list of supernodal representatives * in topological order of the dfs. A supernode representative is the * last column of a supernode. * The maximum size of segrep[] is n. * * repfnz[0:W*m-1]: for a nonzero segment U[*,j] that ends at a * supernodal representative r, repfnz[r] is the location of the first * nonzero in this segment. It is also used during the dfs: repfnz[r]>0 * indicates the supernode r has been explored. * NOTE: There are W of them, each used for one column of a panel. * * panel_lsub[0:W*m-1]: temporary for the nonzeros row indices below * the panel diagonal. These are filled in during zpanel_dfs(), and are * used later in the inner LU factorization within the panel. * panel_lsub[]/dense[] pair forms the SPA data structure. * NOTE: There are W of them. * * dense[0:W*m-1]: sparse accumulating (SPA) vector for intermediate values; * NOTE: there are W of them. * * tempv[0:*]: real temporary used for dense numeric kernels; * The size of this array is defined by NUM_TEMPV() in zsp_defs.h. * */ /* Local working arrays */ NCPformat *Astore; int *iperm_r; /* inverse of perm_r; not used if refact = 'N' */ int *iperm_c; /* inverse of perm_c */ int *iwork; doublecomplex *zwork; int *segrep, *repfnz, *parent, *xplore; int *panel_lsub; /* dense[]/panel_lsub[] pair forms a w-wide SPA */ int *xprune; int *marker; doublecomplex *dense, *tempv; int *relax_end; doublecomplex *a; int *asub; int *xa_begin, *xa_end; int *xsup, *supno; int *xlsub, *xlusup, *xusub; int nzlumax; static GlobalLU_t Glu; /* persistent to facilitate multiple factors. */ /* Local scalars */ int pivrow; /* pivotal row number in the original matrix A */ int nseg1; /* no of segments in U-column above panel row jcol */ int nseg; /* no of segments in each U-column */ register int jcol; register int kcol; /* end column of a relaxed snode */ register int icol; register int i, k, jj, new_next, iinfo; int m, n, min_mn, jsupno, fsupc, nextlu, nextu; int w_def; /* upper bound on panel width */ int usepr, iperm_r_allocated = 0; int nnzL, nnzU; extern SuperLUStat_t SuperLUStat; int *panel_histo = SuperLUStat.panel_histo; flops_t *ops = SuperLUStat.ops; iinfo = 0; m = A->nrow; n = A->ncol; min_mn = SUPERLU_MIN(m, n); Astore = A->Store; a = Astore->nzval; asub = Astore->rowind; xa_begin = Astore->colbeg; xa_end = Astore->colend; /* Allocate storage common to the factor routines */ *info = zLUMemInit(refact, work, lwork, m, n, Astore->nnz, panel_size, L, U, &Glu, &iwork, &zwork); if ( *info ) return; xsup = Glu.xsup; supno = Glu.supno; xlsub = Glu.xlsub; xlusup = Glu.xlusup; xusub = Glu.xusub; SetIWork(m, n, panel_size, iwork, &segrep, &parent, &xplore, &repfnz, &panel_lsub, &xprune, &marker); zSetRWork(m, panel_size, zwork, &dense, &tempv); usepr = lsame_(refact, "Y"); if ( usepr ) { /* Compute the inverse of perm_r */ iperm_r = (int *) intMalloc(m); for (k = 0; k < m; ++k) iperm_r[perm_r[k]] = k; iperm_r_allocated = 1; } iperm_c = (int *) intMalloc(n); for (k = 0; k < n; ++k) iperm_c[perm_c[k]] = k; /* Identify relaxed snodes */ relax_end = (int *) intMalloc(n); relax_snode(n, etree, relax, marker, relax_end); ifill (perm_r, m, EMPTY); ifill (marker, m * NO_MARKER, EMPTY); supno[0] = -1; xsup[0] = xlsub[0] = xusub[0] = xlusup[0] = 0; w_def = panel_size; /* * Work on one "panel" at a time. A panel is one of the following: * (a) a relaxed supernode at the bottom of the etree, or * (b) panel_size contiguous columns, defined by the user */ for (jcol = 0; jcol < min_mn; ) { if ( relax_end[jcol] != EMPTY ) { /* start of a relaxed snode */ kcol = relax_end[jcol]; /* end of the relaxed snode */ panel_histo[kcol-jcol+1]++; /* -------------------------------------- * Factorize the relaxed supernode(jcol:kcol) * -------------------------------------- */ /* Determine the union of the row structure of the snode */ if ( (*info = zsnode_dfs(jcol, kcol, asub, xa_begin, xa_end, xprune, marker, &Glu)) != 0 ) return; nextu = xusub[jcol]; nextlu = xlusup[jcol]; jsupno = supno[jcol]; fsupc = xsup[jsupno]; new_next = nextlu + (xlsub[fsupc+1]-xlsub[fsupc])*(kcol-jcol+1); nzlumax = Glu.nzlumax; while ( new_next > nzlumax ) { if ( *info = zLUMemXpand(jcol, nextlu, LUSUP, &nzlumax, &Glu) ) return; } for (icol = jcol; icol<= kcol; icol++) { xusub[icol+1] = nextu; /* Scatter into SPA dense[*] */ for (k = xa_begin[icol]; k < xa_end[icol]; k++) dense[asub[k]] = a[k]; /* Numeric update within the snode */ zsnode_bmod(icol, jsupno, fsupc, dense, tempv, &Glu); if ( *info = zpivotL(icol, diag_pivot_thresh, &usepr, perm_r, iperm_r, iperm_c, &pivrow, &Glu) ) if ( iinfo == 0 ) iinfo = *info; #ifdef DEBUG zprint_lu_col("[1]: ", icol, pivrow, xprune, &Glu); #endif } jcol = icol; } else { /* Work on one panel of panel_size columns */ /* Adjust panel_size so that a panel won't overlap with the next * relaxed snode. */ panel_size = w_def; for (k = jcol + 1; k < SUPERLU_MIN(jcol+panel_size, min_mn); k++) if ( relax_end[k] != EMPTY ) { panel_size = k - jcol; break; } if ( k == min_mn ) panel_size = min_mn - jcol; panel_histo[panel_size]++; /* symbolic factor on a panel of columns */ zpanel_dfs(m, panel_size, jcol, A, perm_r, &nseg1, dense, panel_lsub, segrep, repfnz, xprune, marker, parent, xplore, &Glu); /* numeric sup-panel updates in topological order */ zpanel_bmod(m, panel_size, jcol, nseg1, dense, tempv, segrep, repfnz, &Glu); /* Sparse LU within the panel, and below panel diagonal */ for ( jj = jcol; jj < jcol + panel_size; jj++) { k = (jj - jcol) * m; /* column index for w-wide arrays */ nseg = nseg1; /* Begin after all the panel segments */ if ((*info = zcolumn_dfs(m, jj, perm_r, &nseg, &panel_lsub[k], segrep, &repfnz[k], xprune, marker, parent, xplore, &Glu)) != 0) return; /* Numeric updates */ if ((*info = zcolumn_bmod(jj, (nseg - nseg1), &dense[k], tempv, &segrep[nseg1], &repfnz[k], jcol, &Glu)) != 0) return; /* Copy the U-segments to ucol[*] */ if ((*info = zcopy_to_ucol(jj, nseg, segrep, &repfnz[k], perm_r, &dense[k], &Glu)) != 0) return; if ( *info = zpivotL(jj, diag_pivot_thresh, &usepr, perm_r, iperm_r, iperm_c, &pivrow, &Glu) ) if ( iinfo == 0 ) iinfo = *info; /* Prune columns (0:jj-1) using column jj */ zpruneL(jj, perm_r, pivrow, nseg, segrep, &repfnz[k], xprune, &Glu); /* Reset repfnz[] for this column */ resetrep_col (nseg, segrep, &repfnz[k]); #ifdef DEBUG zprint_lu_col("[2]: ", jj, pivrow, xprune, &Glu); #endif } jcol += panel_size; /* Move to the next panel */ } /* else */ } /* for */ *info = iinfo; if ( m > n ) { k = 0; for (i = 0; i < m; ++i) if ( perm_r[i] == EMPTY ) { perm_r[i] = n + k; ++k; } } countnz(min_mn, xprune, &nnzL, &nnzU, &Glu); fixupL(min_mn, perm_r, &Glu); zLUWorkFree(iwork, zwork, &Glu); /* Free work space and compress storage */ if ( lsame_(refact, "Y") ) { /* L and U structures may have changed due to possibly different pivoting, although the storage is available. There could also be memory expansions, so the array locations may have changed, */ ((SCformat *)L->Store)->nnz = nnzL; ((SCformat *)L->Store)->nsuper = Glu.supno[n]; ((SCformat *)L->Store)->nzval = Glu.lusup; ((SCformat *)L->Store)->nzval_colptr = Glu.xlusup; ((SCformat *)L->Store)->rowind = Glu.lsub; ((SCformat *)L->Store)->rowind_colptr = Glu.xlsub; ((NCformat *)U->Store)->nnz = nnzU; ((NCformat *)U->Store)->nzval = Glu.ucol; ((NCformat *)U->Store)->rowind = Glu.usub; ((NCformat *)U->Store)->colptr = Glu.xusub; } else { zCreate_SuperNode_Matrix(L, A->nrow, A->ncol, nnzL, Glu.lusup, Glu.xlusup, Glu.lsub, Glu.xlsub, Glu.supno, Glu.xsup, SLU_SC, SLU_Z, SLU_TRLU); zCreate_CompCol_Matrix(U, min_mn, min_mn, nnzU, Glu.ucol, Glu.usub, Glu.xusub, SLU_NC, SLU_Z, SLU_TRU); } ops[FACT] += ops[TRSV] + ops[GEMV]; if ( iperm_r_allocated ) SUPERLU_FREE (iperm_r); SUPERLU_FREE (iperm_c); SUPERLU_FREE (relax_end); }