Blender  V2.59
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 }