Blender V2.61 - r43446

spanel_dfs.c

Go to the documentation of this file.
00001 
00006 /*
00007  * -- SuperLU routine (version 2.0) --
00008  * Univ. of California Berkeley, Xerox Palo Alto Research Center,
00009  * and Lawrence Berkeley National Lab.
00010  * November 15, 1997
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 #include "util.h"
00028 
00029 void
00030 spanel_dfs (
00031        const int  m,           /* in - number of rows in the matrix */
00032        const int  w,           /* in */
00033        const int  jcol,        /* in */
00034        SuperMatrix *A,       /* in - original matrix */
00035        int        *perm_r,     /* in */
00036        int        *nseg,       /* out */
00037        float     *dense,      /* out */
00038        int        *panel_lsub, /* out */
00039        int        *segrep,     /* out */
00040        int        *repfnz,     /* out */
00041        int        *xprune,     /* out */
00042        int        *marker,     /* out */     
00043        int        *parent,     /* working array */
00044        int        *xplore,     /* working array */
00045        GlobalLU_t *Glu         /* modified */
00046        )
00047 {
00048 /*
00049  * Purpose
00050  * =======
00051  *
00052  *   Performs a symbolic factorization on a panel of columns [jcol, jcol+w).
00053  *
00054  *   A supernode representative is the last column of a supernode.
00055  *   The nonzeros in U[*,j] are segments that end at supernodal
00056  *   representatives.
00057  *
00058  *   The routine returns one list of the supernodal representatives
00059  *   in topological order of the dfs that generates them. This list is
00060  *   a superset of the topological order of each individual column within
00061  *   the panel. 
00062  *   The location of the first nonzero in each supernodal segment
00063  *   (supernodal entry location) is also returned. Each column has a 
00064  *   separate list for this purpose.
00065  *
00066  *   Two marker arrays are used for dfs:
00067  *     marker[i] == jj, if i was visited during dfs of current column jj;
00068  *     marker1[i] >= jcol, if i was visited by earlier columns in this panel;
00069  *
00070  *   marker: A-row --> A-row/col (0/1)
00071  *   repfnz: SuperA-col --> PA-row
00072  *   parent: SuperA-col --> SuperA-col
00073  *   xplore: SuperA-col --> index to L-structure
00074  *
00075  */
00076     NCPformat *Astore;
00077     float    *a;
00078     int       *asub;
00079     int       *xa_begin, *xa_end;
00080     int       krep, chperm, chmark, chrep, oldrep, kchild, myfnz;
00081     int       k, krow, kmark, kperm;
00082     int       xdfs, maxdfs, kpar;
00083     int       jj;      /* index through each column in the panel */
00084     int       *marker1;    /* marker1[jj] >= jcol if vertex jj was visited 
00085                   by a previous column within this panel.   */
00086     int       *repfnz_col; /* start of each column in the panel */
00087     float    *dense_col;  /* start of each column in the panel */
00088     int       nextl_col;   /* next available position in panel_lsub[*,jj] */
00089     int       *xsup, *supno;
00090     int       *lsub, *xlsub;
00091 
00092     /* Initialize pointers */
00093     Astore     = A->Store;
00094     a          = Astore->nzval;
00095     asub       = Astore->rowind;
00096     xa_begin   = Astore->colbeg;
00097     xa_end     = Astore->colend;
00098     marker1    = marker + m;
00099     repfnz_col = repfnz;
00100     dense_col  = dense;
00101     *nseg      = 0;
00102     xsup       = Glu->xsup;
00103     supno      = Glu->supno;
00104     lsub       = Glu->lsub;
00105     xlsub      = Glu->xlsub;
00106 
00107     /* For each column in the panel */
00108     for (jj = jcol; jj < jcol + w; jj++) {
00109     nextl_col = (jj - jcol) * m;
00110 
00111 #ifdef CHK_DFS
00112     printf("\npanel col %d: ", jj);
00113 #endif
00114 
00115     /* For each nonz in A[*,jj] do dfs */
00116     for (k = xa_begin[jj]; k < xa_end[jj]; k++) {
00117         krow = asub[k];
00118             dense_col[krow] = a[k];
00119         kmark = marker[krow];       
00120         if ( kmark == jj ) 
00121         continue;     /* krow visited before, go to the next nonzero */
00122 
00123         /* For each unmarked nbr krow of jj
00124          * krow is in L: place it in structure of L[*,jj]
00125          */
00126         marker[krow] = jj;
00127         kperm = perm_r[krow];
00128         
00129         if ( kperm == EMPTY ) {
00130         panel_lsub[nextl_col++] = krow; /* krow is indexed into A */
00131         }
00132         /* 
00133          * krow is in U: if its supernode-rep krep
00134          * has been explored, update repfnz[*]
00135          */
00136         else {
00137         
00138         krep = xsup[supno[kperm]+1] - 1;
00139         myfnz = repfnz_col[krep];
00140         
00141 #ifdef CHK_DFS
00142         printf("krep %d, myfnz %d, perm_r[%d] %d\n", krep, myfnz, krow, kperm);
00143 #endif
00144         if ( myfnz != EMPTY ) { /* Representative visited before */
00145             if ( myfnz > kperm ) repfnz_col[krep] = kperm;
00146             /* continue; */
00147         }
00148         else {
00149             /* Otherwise, perform dfs starting at krep */
00150             oldrep = EMPTY;
00151             parent[krep] = oldrep;
00152             repfnz_col[krep] = kperm;
00153             xdfs = xlsub[krep];
00154             maxdfs = xprune[krep];
00155             
00156 #ifdef CHK_DFS 
00157             printf("  xdfs %d, maxdfs %d: ", xdfs, maxdfs);
00158             for (i = xdfs; i < maxdfs; i++) printf(" %d", lsub[i]);
00159             printf("\n");
00160 #endif
00161             do {
00162             /* 
00163              * For each unmarked kchild of krep 
00164              */
00165             while ( xdfs < maxdfs ) {
00166                 
00167                 kchild = lsub[xdfs];
00168                 xdfs++;
00169                 chmark = marker[kchild];
00170                 
00171                 if ( chmark != jj ) { /* Not reached yet */
00172                 marker[kchild] = jj;
00173                 chperm = perm_r[kchild];
00174                   
00175                 /* Case kchild is in L: place it in L[*,j] */
00176                 if ( chperm == EMPTY ) {
00177                     panel_lsub[nextl_col++] = kchild;
00178                 } 
00179                 /* Case kchild is in U: 
00180                  *   chrep = its supernode-rep. If its rep has 
00181                  *   been explored, update its repfnz[*]
00182                  */
00183                 else {
00184                     
00185                     chrep = xsup[supno[chperm]+1] - 1;
00186                     myfnz = repfnz_col[chrep];
00187 #ifdef CHK_DFS
00188                     printf("chrep %d,myfnz %d,perm_r[%d] %d\n",chrep,myfnz,kchild,chperm);
00189 #endif
00190                     if ( myfnz != EMPTY ) { /* Visited before */
00191                     if ( myfnz > chperm )
00192                         repfnz_col[chrep] = chperm;
00193                     }
00194                     else {
00195                     /* Cont. dfs at snode-rep of kchild */
00196                     xplore[krep] = xdfs;    
00197                     oldrep = krep;
00198                     krep = chrep; /* Go deeper down G(L) */
00199                     parent[krep] = oldrep;
00200                     repfnz_col[krep] = chperm;
00201                     xdfs = xlsub[krep];     
00202                     maxdfs = xprune[krep];
00203 #ifdef CHK_DFS 
00204                     printf("  xdfs %d, maxdfs %d: ", xdfs, maxdfs);
00205                     for (i = xdfs; i < maxdfs; i++) printf(" %d", lsub[i]); 
00206                     printf("\n");
00207 #endif
00208                     } /* else */
00209                   
00210                 } /* else */
00211                   
00212                 } /* if... */
00213                 
00214             } /* while xdfs < maxdfs */
00215             
00216             /* krow has no more unexplored nbrs:
00217              *    Place snode-rep krep in postorder DFS, if this 
00218              *    segment is seen for the first time. (Note that
00219              *    "repfnz[krep]" may change later.)
00220              *    Backtrack dfs to its parent.
00221              */
00222             if ( marker1[krep] < jcol ) {
00223                 segrep[*nseg] = krep;
00224                 ++(*nseg);
00225                 marker1[krep] = jj;
00226             }
00227             
00228             kpar = parent[krep]; /* Pop stack, mimic recursion */
00229             if ( kpar == EMPTY ) break; /* dfs done */
00230             krep = kpar;
00231             xdfs = xplore[krep];
00232             maxdfs = xprune[krep];
00233             
00234 #ifdef CHK_DFS 
00235             printf("  pop stack: krep %d,xdfs %d,maxdfs %d: ", krep,xdfs,maxdfs);
00236             for (i = xdfs; i < maxdfs; i++) printf(" %d", lsub[i]);
00237             printf("\n");
00238 #endif
00239             } while ( kpar != EMPTY ); /* do-while - until empty stack */
00240             
00241         } /* else */
00242         
00243         } /* else */
00244         
00245     } /* for each nonz in A[*,jj] */
00246     
00247     repfnz_col += m;    /* Move to next column */
00248         dense_col += m;
00249     
00250     } /* for jj ... */
00251     
00252 }