示例#1
0
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);
}
示例#2
0
文件: memory.c 项目: Narrat/eispice
/*
 * 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);
}
示例#3
0
/*! \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++;
    }
}
示例#4
0
文件: util.c 项目: aceskpark/osfeo
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]);
    }

}
示例#5
0
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;
	}
}
示例#6
0
文件: pmemory.c 项目: ivanBobrov/Xeon
/*
 * 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);
}
示例#7
0
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); */
}
示例#8
0
/*
 * 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);

}