Blender V2.61 - r43446

scolumn_dfs.c

Go to the documentation of this file.
00001 
00006 /*
00007  * -- SuperLU routine (version 3.0) --
00008  * Univ. of California Berkeley, Xerox Palo Alto Research Center,
00009  * and Lawrence Berkeley National Lab.
00010  * October 15, 2003
00011  *
00012  */
00013 /*
00014   Copyright (c) 1994 by Xerox Corporation.  All rights reserved.
00015  
00016   THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY
00017   EXPRESSED OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
00018  
00019   Permission is hereby granted to use or copy this program for any
00020   purpose, provided the above notices are retained on all copies.
00021   Permission to modify the code and to distribute modified code is
00022   granted, provided the above notices are retained, and a notice that
00023   the code was modified is included with the above copyright notice.
00024 */
00025 
00026 #include "ssp_defs.h"
00027 
00028 /* What type of supernodes we want */
00029 #define T2_SUPER
00030 
00031 int
00032 scolumn_dfs(
00033        const int  m,         /* in - number of rows in the matrix */
00034        const int  jcol,      /* in */
00035        int        *perm_r,   /* in */
00036        int        *nseg,     /* modified - with new segments appended */
00037        int        *lsub_col, /* in - defines the RHS vector to start the dfs */
00038        int        *segrep,   /* modified - with new segments appended */
00039        int        *repfnz,   /* modified */
00040        int        *xprune,   /* modified */
00041        int        *marker,   /* modified */
00042        int        *parent,   /* working array */
00043        int        *xplore,   /* working array */
00044        GlobalLU_t *Glu       /* modified */
00045        )
00046 {
00047 /* 
00048  * Purpose
00049  * =======
00050  *   "column_dfs" performs a symbolic factorization on column jcol, and
00051  *   decide the supernode boundary.
00052  *
00053  *   This routine does not use numeric values, but only use the RHS 
00054  *   row indices to start the dfs.
00055  *
00056  *   A supernode representative is the last column of a supernode.
00057  *   The nonzeros in U[*,j] are segments that end at supernodal
00058  *   representatives. The routine returns a list of such supernodal 
00059  *   representatives in topological order of the dfs that generates them.
00060  *   The location of the first nonzero in each such supernodal segment
00061  *   (supernodal entry location) is also returned.
00062  *
00063  * Local parameters
00064  * ================
00065  *   nseg: no of segments in current U[*,j]
00066  *   jsuper: jsuper=EMPTY if column j does not belong to the same
00067  *  supernode as j-1. Otherwise, jsuper=nsuper.
00068  *
00069  *   marker2: A-row --> A-row/col (0/1)
00070  *   repfnz: SuperA-col --> PA-row
00071  *   parent: SuperA-col --> SuperA-col
00072  *   xplore: SuperA-col --> index to L-structure
00073  *
00074  * Return value
00075  * ============
00076  *     0  success;
00077  *   > 0  number of bytes allocated when run out of space.
00078  *
00079  */
00080     int     jcolp1, jcolm1, jsuper, nsuper, nextl;
00081     int     k, krep, krow, kmark, kperm;
00082     int     *marker2;           /* Used for small panel LU */
00083     int     fsupc;      /* First column of a snode */
00084     int     myfnz;      /* First nonz column of a U-segment */
00085     int     chperm, chmark, chrep, kchild;
00086     int     xdfs, maxdfs, kpar, oldrep;
00087     int     jptr, jm1ptr;
00088     int     ito, ifrom, istop;  /* Used to compress row subscripts */
00089     int     mem_error;
00090     int     *xsup, *supno, *lsub, *xlsub;
00091     int     nzlmax;
00092     static  int  first = 1, maxsuper;
00093     
00094     xsup    = Glu->xsup;
00095     supno   = Glu->supno;
00096     lsub    = Glu->lsub;
00097     xlsub   = Glu->xlsub;
00098     nzlmax  = Glu->nzlmax;
00099 
00100     if ( first ) {
00101     maxsuper = sp_ienv(3);
00102     first = 0;
00103     }
00104     jcolp1  = jcol + 1;
00105     jcolm1  = jcol - 1;
00106     nsuper  = supno[jcol];
00107     jsuper  = nsuper;
00108     nextl   = xlsub[jcol];
00109     marker2 = &marker[2*m];
00110 
00111 
00112     /* For each nonzero in A[*,jcol] do dfs */
00113     for (k = 0; lsub_col[k] != EMPTY; k++) {
00114 
00115     krow = lsub_col[k];
00116         lsub_col[k] = EMPTY;
00117     kmark = marker2[krow];      
00118 
00119     /* krow was visited before, go to the next nonz */
00120         if ( kmark == jcol ) continue; 
00121 
00122     /* For each unmarked nbr krow of jcol
00123      *  krow is in L: place it in structure of L[*,jcol]
00124      */
00125     marker2[krow] = jcol;
00126     kperm = perm_r[krow];
00127 
00128     if ( kperm == EMPTY ) {
00129         lsub[nextl++] = krow;   /* krow is indexed into A */
00130         if ( nextl >= nzlmax ) {
00131         if ((mem_error = sLUMemXpand(jcol, nextl, LSUB, &nzlmax, Glu)))
00132             return (mem_error);
00133         lsub = Glu->lsub;
00134         }
00135             if ( kmark != jcolm1 ) jsuper = EMPTY;/* Row index subset testing */
00136     } else {
00137         /*  krow is in U: if its supernode-rep krep
00138          *  has been explored, update repfnz[*]
00139          */
00140         krep = xsup[supno[kperm]+1] - 1;
00141         myfnz = repfnz[krep];
00142 
00143         if ( myfnz != EMPTY ) { /* Visited before */
00144             if ( myfnz > kperm ) repfnz[krep] = kperm;
00145         /* continue; */
00146         }
00147         else {
00148         /* Otherwise, perform dfs starting at krep */
00149         oldrep = EMPTY;
00150         parent[krep] = oldrep;
00151         repfnz[krep] = kperm;
00152         xdfs = xlsub[krep];
00153         maxdfs = xprune[krep];
00154 
00155         do {
00156             /* 
00157              * For each unmarked kchild of krep 
00158              */
00159             while ( xdfs < maxdfs ) {
00160 
00161             kchild = lsub[xdfs];
00162             xdfs++;
00163             chmark = marker2[kchild];
00164 
00165             if ( chmark != jcol ) { /* Not reached yet */
00166                 marker2[kchild] = jcol;
00167                 chperm = perm_r[kchild];
00168 
00169                 /* Case kchild is in L: place it in L[*,k] */
00170                 if ( chperm == EMPTY ) {
00171                     lsub[nextl++] = kchild;
00172                 if ( nextl >= nzlmax ) {
00173                     if ((mem_error =
00174                      sLUMemXpand(jcol,nextl,LSUB,&nzlmax,Glu)))
00175                     return (mem_error);
00176                     lsub = Glu->lsub;
00177                 }
00178                 if ( chmark != jcolm1 ) jsuper = EMPTY;
00179                 } else {
00180                         /* Case kchild is in U: 
00181                  *   chrep = its supernode-rep. If its rep has 
00182                      *   been explored, update its repfnz[*]
00183                      */
00184                     chrep = xsup[supno[chperm]+1] - 1;
00185                 myfnz = repfnz[chrep];
00186                 if ( myfnz != EMPTY ) { /* Visited before */
00187                     if ( myfnz > chperm )
00188                         repfnz[chrep] = chperm;
00189                 } else {
00190                         /* Continue dfs at super-rep of kchild */
00191                     xplore[krep] = xdfs;    
00192                     oldrep = krep;
00193                     krep = chrep; /* Go deeper down G(L^t) */
00194                     parent[krep] = oldrep;
00195                         repfnz[krep] = chperm;
00196                     xdfs = xlsub[krep];     
00197                     maxdfs = xprune[krep];
00198                 } /* else */
00199 
00200                } /* else */
00201 
00202             } /* if */
00203 
00204             } /* while */
00205 
00206             /* krow has no more unexplored nbrs;
00207              *    place supernode-rep krep in postorder DFS.
00208              *    backtrack dfs to its parent
00209              */
00210             segrep[*nseg] = krep;
00211             ++(*nseg);
00212             kpar = parent[krep]; /* Pop from stack, mimic recursion */
00213             if ( kpar == EMPTY ) break; /* dfs done */
00214             krep = kpar;
00215             xdfs = xplore[krep];
00216             maxdfs = xprune[krep];
00217 
00218         } while ( kpar != EMPTY );  /* Until empty stack */
00219 
00220         } /* else */
00221 
00222     } /* else */
00223 
00224     } /* for each nonzero ... */
00225 
00226     /* Check to see if j belongs in the same supernode as j-1 */
00227     if ( jcol == 0 ) { /* Do nothing for column 0 */
00228     nsuper = supno[0] = 0;
00229     } else {
00230     fsupc = xsup[nsuper];
00231     jptr = xlsub[jcol]; /* Not compressed yet */
00232     jm1ptr = xlsub[jcolm1];
00233 
00234 #ifdef T2_SUPER
00235     if ( (nextl-jptr != jptr-jm1ptr-1) ) jsuper = EMPTY;
00236 #endif
00237     /* Make sure the number of columns in a supernode doesn't
00238        exceed threshold. */
00239     if ( jcol - fsupc >= maxsuper ) jsuper = EMPTY;
00240 
00241     /* If jcol starts a new supernode, reclaim storage space in
00242      * lsub from the previous supernode. Note we only store
00243      * the subscript set of the first and last columns of
00244      * a supernode. (first for num values, last for pruning)
00245      */
00246     if ( jsuper == EMPTY ) {    /* starts a new supernode */
00247         if ( (fsupc < jcolm1-1) ) { /* >= 3 columns in nsuper */
00248 #ifdef CHK_COMPRESS
00249         printf("  Compress lsub[] at super %d-%d\n", fsupc, jcolm1);
00250 #endif
00251             ito = xlsub[fsupc+1];
00252         xlsub[jcolm1] = ito;
00253         istop = ito + jptr - jm1ptr;
00254         xprune[jcolm1] = istop; /* Initialize xprune[jcol-1] */
00255         xlsub[jcol] = istop;
00256         for (ifrom = jm1ptr; ifrom < nextl; ++ifrom, ++ito)
00257             lsub[ito] = lsub[ifrom];
00258         nextl = ito;            /* = istop + length(jcol) */
00259         }
00260         nsuper++;
00261         supno[jcol] = nsuper;
00262     } /* if a new supernode */
00263 
00264     }   /* else: jcol > 0 */ 
00265     
00266     /* Tidy up the pointers before exit */
00267     xsup[nsuper+1] = jcolp1;
00268     supno[jcolp1]  = nsuper;
00269     xprune[jcol]   = nextl; /* Initialize upper bound for pruning */
00270     xlsub[jcolp1]  = nextl;
00271 
00272     return 0;
00273 }