Blender V2.61 - r43446

mmd.c

Go to the documentation of this file.
00001 
00005 typedef int shortint;
00006 
00007 
00008 /* prototypes -------------------- */
00009 int  genmmd_(int *, int *, int *, int *, int *, int *, int *, 
00010                     int *, int *, int *, int *, int *);
00011 int mmdint_(int *, int *, shortint *, shortint *, shortint *, shortint *, shortint *, 
00012             shortint *, shortint *);
00013 int mmdelm_(int *, int *, shortint *, shortint *, shortint *, shortint *, shortint *, 
00014             shortint *, shortint *, int *, int *);
00015 int mmdupd_(int *, int *, int *, shortint *, int *, int *, shortint *, 
00016             shortint *, shortint *, shortint *, shortint *, shortint *, int *, int *);
00017 int mmdnum_(int *, shortint *, shortint *, shortint *);
00018 
00019 
00020 /* *************************************************************** */
00021 /* *************************************************************** */
00022 /* ****     GENMMD ..... MULTIPLE MINIMUM EXTERNAL DEGREE     **** */
00023 /* *************************************************************** */
00024 /* *************************************************************** */
00025 
00026 /*     AUTHOR - JOSEPH W.H. LIU */
00027 /*              DEPT OF COMPUTER SCIENCE, YORK UNIVERSITY. */
00028 
00029 /*     PURPOSE - THIS ROUTINE IMPLEMENTS THE MINIMUM DEGREE */
00030 /*        ALGORITHM.  IT MAKES USE OF THE IMPLICIT REPRESENTATION */
00031 /*        OF ELIMINATION GRAPHS BY QUOTIENT GRAPHS, AND THE */
00032 /*        NOTION OF INDISTINGUISHABLE NODES.  IT ALSO IMPLEMENTS */
00033 /*        THE MODIFICATIONS BY MULTIPLE ELIMINATION AND MINIMUM */
00034 /*        EXTERNAL DEGREE. */
00035 /*        --------------------------------------------- */
00036 /*        CAUTION - THE ADJACENCY VECTOR ADJNCY WILL BE */
00037 /*        DESTROYED. */
00038 /*        --------------------------------------------- */
00039 
00040 /*     INPUT PARAMETERS - */
00041 /*        NEQNS  - NUMBER OF EQUATIONS. */
00042 /*        (XADJ,ADJNCY) - THE ADJACENCY STRUCTURE. */
00043 /*        DELTA  - TOLERANCE VALUE FOR MULTIPLE ELIMINATION. */
00044 /*        MAXINT - MAXIMUM MACHINE REPRESENTABLE (SHORT) INTEGER */
00045 /*                 (ANY SMALLER ESTIMATE WILL DO) FOR MARKING */
00046 /*                 NODES. */
00047 
00048 /*     OUTPUT PARAMETERS - */
00049 /*        PERM   - THE MINIMUM DEGREE ORDERING. */
00050 /*        INVP   - THE INVERSE OF PERM. */
00051 /*        NOFSUB - AN UPPER BOUND ON THE NUMBER OF NONZERO */
00052 /*                 SUBSCRIPTS FOR THE COMPRESSED STORAGE SCHEME. */
00053 
00054 /*     WORKING PARAMETERS - */
00055 /*        DHEAD  - VECTOR FOR HEAD OF DEGREE LISTS. */
00056 /*        INVP   - USED TEMPORARILY FOR DEGREE FORWARD LINK. */
00057 /*        PERM   - USED TEMPORARILY FOR DEGREE BACKWARD LINK. */
00058 /*        QSIZE  - VECTOR FOR SIZE OF SUPERNODES. */
00059 /*        LLIST  - VECTOR FOR TEMPORARY LINKED LISTS. */
00060 /*        MARKER - A TEMPORARY MARKER VECTOR. */
00061 
00062 /*     PROGRAM SUBROUTINES - */
00063 /*        MMDELM, MMDINT, MMDNUM, MMDUPD. */
00064 
00065 /* *************************************************************** */
00066 
00067 /* Subroutine */ int genmmd_(int *neqns, int *xadj, shortint *adjncy, 
00068     shortint *invp, shortint *perm, int *delta, shortint *dhead, 
00069     shortint *qsize, shortint *llist, shortint *marker, int *maxint, 
00070     int *nofsub)
00071 {
00072     /* System generated locals */
00073     int i__1;
00074 
00075     /* Local variables */
00076     static int mdeg, ehead, i, mdlmt, mdnode;
00077     extern /* Subroutine */ int mmdelm_(int *, int *, shortint *, 
00078         shortint *, shortint *, shortint *, shortint *, shortint *, 
00079         shortint *, int *, int *), mmdupd_(int *, int *, 
00080         int *, shortint *, int *, int *, shortint *, shortint 
00081         *, shortint *, shortint *, shortint *, shortint *, int *, 
00082         int *), mmdint_(int *, int *, shortint *, shortint *, 
00083         shortint *, shortint *, shortint *, shortint *, shortint *), 
00084         mmdnum_(int *, shortint *, shortint *, shortint *);
00085     static int nextmd, tag, num;
00086 
00087 
00088 /* *************************************************************** */
00089 
00090 
00091 /* *************************************************************** */
00092 
00093     /* Parameter adjustments */
00094     --marker;
00095     --llist;
00096     --qsize;
00097     --dhead;
00098     --perm;
00099     --invp;
00100     --adjncy;
00101     --xadj;
00102 
00103     /* Function Body */
00104     if (*neqns <= 0) {
00105     return 0;
00106     }
00107 
00108 /*        ------------------------------------------------ */
00109 /*        INITIALIZATION FOR THE MINIMUM DEGREE ALGORITHM. */
00110 /*        ------------------------------------------------ */
00111     *nofsub = 0;
00112     mmdint_(neqns, &xadj[1], &adjncy[1], &dhead[1], &invp[1], &perm[1], &
00113         qsize[1], &llist[1], &marker[1]);
00114 
00115 /*        ---------------------------------------------- */
00116 /*        NUM COUNTS THE NUMBER OF ORDERED NODES PLUS 1. */
00117 /*        ---------------------------------------------- */
00118     num = 1;
00119 
00120 /*        ----------------------------- */
00121 /*        ELIMINATE ALL ISOLATED NODES. */
00122 /*        ----------------------------- */
00123     nextmd = dhead[1];
00124 L100:
00125     if (nextmd <= 0) {
00126     goto L200;
00127     }
00128     mdnode = nextmd;
00129     nextmd = invp[mdnode];
00130     marker[mdnode] = *maxint;
00131     invp[mdnode] = -num;
00132     ++num;
00133     goto L100;
00134 
00135 L200:
00136 /*        ---------------------------------------- */
00137 /*        SEARCH FOR NODE OF THE MINIMUM DEGREE. */
00138 /*        MDEG IS THE CURRENT MINIMUM DEGREE; */
00139 /*        TAG IS USED TO FACILITATE MARKING NODES. */
00140 /*        ---------------------------------------- */
00141     if (num > *neqns) {
00142     goto L1000;
00143     }
00144     tag = 1;
00145     dhead[1] = 0;
00146     mdeg = 2;
00147 L300:
00148     if (dhead[mdeg] > 0) {
00149     goto L400;
00150     }
00151     ++mdeg;
00152     goto L300;
00153 L400:
00154 /*            ------------------------------------------------- */
00155 /*            USE VALUE OF DELTA TO SET UP MDLMT, WHICH GOVERNS */
00156 /*            WHEN A DEGREE UPDATE IS TO BE PERFORMED. */
00157 /*            ------------------------------------------------- */
00158     mdlmt = mdeg + *delta;
00159     ehead = 0;
00160 
00161 L500:
00162     mdnode = dhead[mdeg];
00163     if (mdnode > 0) {
00164     goto L600;
00165     }
00166     ++mdeg;
00167     if (mdeg > mdlmt) {
00168     goto L900;
00169     }
00170     goto L500;
00171 L600:
00172 /*                ---------------------------------------- */
00173 /*                REMOVE MDNODE FROM THE DEGREE STRUCTURE. */
00174 /*                ---------------------------------------- */
00175     nextmd = invp[mdnode];
00176     dhead[mdeg] = nextmd;
00177     if (nextmd > 0) {
00178     perm[nextmd] = -mdeg;
00179     }
00180     invp[mdnode] = -num;
00181     *nofsub = *nofsub + mdeg + qsize[mdnode] - 2;
00182     if (num + qsize[mdnode] > *neqns) {
00183     goto L1000;
00184     }
00185 /*                ---------------------------------------------- */
00186 /*                ELIMINATE MDNODE AND PERFORM QUOTIENT GRAPH */
00187 /*                TRANSFORMATION.  RESET TAG VALUE IF NECESSARY. */
00188 /*                ---------------------------------------------- */
00189     ++tag;
00190     if (tag < *maxint) {
00191     goto L800;
00192     }
00193     tag = 1;
00194     i__1 = *neqns;
00195     for (i = 1; i <= i__1; ++i) {
00196     if (marker[i] < *maxint) {
00197         marker[i] = 0;
00198     }
00199 /* L700: */
00200     }
00201 L800:
00202     mmdelm_(&mdnode, &xadj[1], &adjncy[1], &dhead[1], &invp[1], &perm[1], &
00203         qsize[1], &llist[1], &marker[1], maxint, &tag);
00204     num += qsize[mdnode];
00205     llist[mdnode] = ehead;
00206     ehead = mdnode;
00207     if (*delta >= 0) {
00208     goto L500;
00209     }
00210 L900:
00211 /*            ------------------------------------------- */
00212 /*            UPDATE DEGREES OF THE NODES INVOLVED IN THE */
00213 /*            MINIMUM DEGREE NODES ELIMINATION. */
00214 /*            ------------------------------------------- */
00215     if (num > *neqns) {
00216     goto L1000;
00217     }
00218     mmdupd_(&ehead, neqns, &xadj[1], &adjncy[1], delta, &mdeg, &dhead[1], &
00219         invp[1], &perm[1], &qsize[1], &llist[1], &marker[1], maxint, &tag)
00220         ;
00221     goto L300;
00222 
00223 L1000:
00224     mmdnum_(neqns, &perm[1], &invp[1], &qsize[1]);
00225     return 0;
00226 
00227 } /* genmmd_ */
00228 
00229 /* *************************************************************** */
00230 /* *************************************************************** */
00231 /* ***     MMDINT ..... MULT MINIMUM DEGREE INITIALIZATION     *** */
00232 /* *************************************************************** */
00233 /* *************************************************************** */
00234 
00235 /*     AUTHOR - JOSEPH W.H. LIU */
00236 /*              DEPT OF COMPUTER SCIENCE, YORK UNIVERSITY. */
00237 
00238 /*     PURPOSE - THIS ROUTINE PERFORMS INITIALIZATION FOR THE */
00239 /*        MULTIPLE ELIMINATION VERSION OF THE MINIMUM DEGREE */
00240 /*        ALGORITHM. */
00241 
00242 /*     INPUT PARAMETERS - */
00243 /*        NEQNS  - NUMBER OF EQUATIONS. */
00244 /*        (XADJ,ADJNCY) - ADJACENCY STRUCTURE. */
00245 
00246 /*     OUTPUT PARAMETERS - */
00247 /*        (DHEAD,DFORW,DBAKW) - DEGREE DOUBLY LINKED STRUCTURE. */
00248 /*        QSIZE  - SIZE OF SUPERNODE (INITIALIZED TO ONE). */
00249 /*        LLIST  - LINKED LIST. */
00250 /*        MARKER - MARKER VECTOR. */
00251 
00252 /* *************************************************************** */
00253 
00254 /* Subroutine */ int mmdint_(int *neqns, int *xadj, shortint *adjncy, 
00255     shortint *dhead, shortint *dforw, shortint *dbakw, shortint *qsize, 
00256     shortint *llist, shortint *marker)
00257 {
00258     /* System generated locals */
00259     int i__1;
00260 
00261     /* Local variables */
00262     static int ndeg, node, fnode;
00263 
00264 
00265 /* *************************************************************** */
00266 
00267 
00268 /* *************************************************************** */
00269 
00270     /* Parameter adjustments */
00271     --marker;
00272     --llist;
00273     --qsize;
00274     --dbakw;
00275     --dforw;
00276     --dhead;
00277     --adjncy;
00278     --xadj;
00279 
00280     /* Function Body */
00281     i__1 = *neqns;
00282     for (node = 1; node <= i__1; ++node) {
00283     dhead[node] = 0;
00284     qsize[node] = 1;
00285     marker[node] = 0;
00286     llist[node] = 0;
00287 /* L100: */
00288     }
00289 /*        ------------------------------------------ */
00290 /*        INITIALIZE THE DEGREE DOUBLY LINKED LISTS. */
00291 /*        ------------------------------------------ */
00292     i__1 = *neqns;
00293     for (node = 1; node <= i__1; ++node) {
00294     ndeg = xadj[node + 1] - xadj[node] + 1;
00295     fnode = dhead[ndeg];
00296     dforw[node] = fnode;
00297     dhead[ndeg] = node;
00298     if (fnode > 0) {
00299         dbakw[fnode] = node;
00300     }
00301     dbakw[node] = -ndeg;
00302 /* L200: */
00303     }
00304     return 0;
00305 
00306 } /* mmdint_ */
00307 
00308 /* *************************************************************** */
00309 /* *************************************************************** */
00310 /* **     MMDELM ..... MULTIPLE MINIMUM DEGREE ELIMINATION     *** */
00311 /* *************************************************************** */
00312 /* *************************************************************** */
00313 
00314 /*     AUTHOR - JOSEPH W.H. LIU */
00315 /*              DEPT OF COMPUTER SCIENCE, YORK UNIVERSITY. */
00316 
00317 /*     PURPOSE - THIS ROUTINE ELIMINATES THE NODE MDNODE OF */
00318 /*        MINIMUM DEGREE FROM THE ADJACENCY STRUCTURE, WHICH */
00319 /*        IS STORED IN THE QUOTIENT GRAPH FORMAT.  IT ALSO */
00320 /*        TRANSFORMS THE QUOTIENT GRAPH REPRESENTATION OF THE */
00321 /*        ELIMINATION GRAPH. */
00322 
00323 /*     INPUT PARAMETERS - */
00324 /*        MDNODE - NODE OF MINIMUM DEGREE. */
00325 /*        MAXINT - ESTIMATE OF MAXIMUM REPRESENTABLE (SHORT) */
00326 /*                 INT. */
00327 /*        TAG    - TAG VALUE. */
00328 
00329 /*     UPDATED PARAMETERS - */
00330 /*        (XADJ,ADJNCY) - UPDATED ADJACENCY STRUCTURE. */
00331 /*        (DHEAD,DFORW,DBAKW) - DEGREE DOUBLY LINKED STRUCTURE. */
00332 /*        QSIZE  - SIZE OF SUPERNODE. */
00333 /*        MARKER - MARKER VECTOR. */
00334 /*        LLIST  - TEMPORARY LINKED LIST OF ELIMINATED NABORS. */
00335 
00336 /* *************************************************************** */
00337 
00338 /* Subroutine */ int mmdelm_(int *mdnode, int *xadj, shortint *adjncy,
00339      shortint *dhead, shortint *dforw, shortint *dbakw, shortint *qsize, 
00340     shortint *llist, shortint *marker, int *maxint, int *tag)
00341 {
00342     /* System generated locals */
00343     int i__1, i__2;
00344 
00345     /* Local variables */
00346     static int node, link, rloc, rlmt, i, j, nabor, rnode, elmnt, xqnbr, 
00347         istop, jstop, istrt, jstrt, nxnode, pvnode, nqnbrs, npv;
00348 
00349 
00350 /* *************************************************************** */
00351 
00352 
00353 /* *************************************************************** */
00354 
00355 /*        ----------------------------------------------- */
00356 /*        FIND REACHABLE SET AND PLACE IN DATA STRUCTURE. */
00357 /*        ----------------------------------------------- */
00358     /* Parameter adjustments */
00359     --marker;
00360     --llist;
00361     --qsize;
00362     --dbakw;
00363     --dforw;
00364     --dhead;
00365     --adjncy;
00366     --xadj;
00367 
00368     /* Function Body */
00369     marker[*mdnode] = *tag;
00370     istrt = xadj[*mdnode];
00371     istop = xadj[*mdnode + 1] - 1;
00372 /*        ------------------------------------------------------- */
00373 /*        ELMNT POINTS TO THE BEGINNING OF THE LIST OF ELIMINATED */
00374 /*        NABORS OF MDNODE, AND RLOC GIVES THE STORAGE LOCATION */
00375 /*        FOR THE NEXT REACHABLE NODE. */
00376 /*        ------------------------------------------------------- */
00377     elmnt = 0;
00378     rloc = istrt;
00379     rlmt = istop;
00380     i__1 = istop;
00381     for (i = istrt; i <= i__1; ++i) {
00382     nabor = adjncy[i];
00383     if (nabor == 0) {
00384         goto L300;
00385     }
00386     if (marker[nabor] >= *tag) {
00387         goto L200;
00388     }
00389     marker[nabor] = *tag;
00390     if (dforw[nabor] < 0) {
00391         goto L100;
00392     }
00393     adjncy[rloc] = nabor;
00394     ++rloc;
00395     goto L200;
00396 L100:
00397     llist[nabor] = elmnt;
00398     elmnt = nabor;
00399 L200:
00400     ;
00401     }
00402 L300:
00403 /*            ----------------------------------------------------- */
00404 /*            MERGE WITH REACHABLE NODES FROM GENERALIZED ELEMENTS. */
00405 /*            ----------------------------------------------------- */
00406     if (elmnt <= 0) {
00407     goto L1000;
00408     }
00409     adjncy[rlmt] = -elmnt;
00410     link = elmnt;
00411 L400:
00412     jstrt = xadj[link];
00413     jstop = xadj[link + 1] - 1;
00414     i__1 = jstop;
00415     for (j = jstrt; j <= i__1; ++j) {
00416     node = adjncy[j];
00417     link = -node;
00418     if (node < 0) {
00419         goto L400;
00420     } else if (node == 0) {
00421         goto L900;
00422     } else {
00423         goto L500;
00424     }
00425 L500:
00426     if (marker[node] >= *tag || dforw[node] < 0) {
00427         goto L800;
00428     }
00429     marker[node] = *tag;
00430 /*                            --------------------------------- */
00431 /*                            USE STORAGE FROM ELIMINATED NODES */
00432 /*                            IF NECESSARY. */
00433 /*                            --------------------------------- */
00434 L600:
00435     if (rloc < rlmt) {
00436         goto L700;
00437     }
00438     link = -adjncy[rlmt];
00439     rloc = xadj[link];
00440     rlmt = xadj[link + 1] - 1;
00441     goto L600;
00442 L700:
00443     adjncy[rloc] = node;
00444     ++rloc;
00445 L800:
00446     ;
00447     }
00448 L900:
00449     elmnt = llist[elmnt];
00450     goto L300;
00451 L1000:
00452     if (rloc <= rlmt) {
00453     adjncy[rloc] = 0;
00454     }
00455 /*        -------------------------------------------------------- */
00456 /*        FOR EACH NODE IN THE REACHABLE SET, DO THE FOLLOWING ... */
00457 /*        -------------------------------------------------------- */
00458     link = *mdnode;
00459 L1100:
00460     istrt = xadj[link];
00461     istop = xadj[link + 1] - 1;
00462     i__1 = istop;
00463     for (i = istrt; i <= i__1; ++i) {
00464     rnode = adjncy[i];
00465     link = -rnode;
00466     if (rnode < 0) {
00467         goto L1100;
00468     } else if (rnode == 0) {
00469         goto L1800;
00470     } else {
00471         goto L1200;
00472     }
00473 L1200:
00474 /*                -------------------------------------------- */
00475 /*                IF RNODE IS IN THE DEGREE LIST STRUCTURE ... */
00476 /*                -------------------------------------------- */
00477     pvnode = dbakw[rnode];
00478     if (pvnode == 0 || pvnode == -(*maxint)) {
00479         goto L1300;
00480     }
00481 /*                    ------------------------------------- */
00482 /*                    THEN REMOVE RNODE FROM THE STRUCTURE. */
00483 /*                    ------------------------------------- */
00484     nxnode = dforw[rnode];
00485     if (nxnode > 0) {
00486         dbakw[nxnode] = pvnode;
00487     }
00488     if (pvnode > 0) {
00489         dforw[pvnode] = nxnode;
00490     }
00491     npv = -pvnode;
00492     if (pvnode < 0) {
00493         dhead[npv] = nxnode;
00494     }
00495 L1300:
00496 /*                ---------------------------------------- */
00497 /*                PURGE INACTIVE QUOTIENT NABORS OF RNODE. */
00498 /*                ---------------------------------------- */
00499     jstrt = xadj[rnode];
00500     jstop = xadj[rnode + 1] - 1;
00501     xqnbr = jstrt;
00502     i__2 = jstop;
00503     for (j = jstrt; j <= i__2; ++j) {
00504         nabor = adjncy[j];
00505         if (nabor == 0) {
00506         goto L1500;
00507         }
00508         if (marker[nabor] >= *tag) {
00509         goto L1400;
00510         }
00511         adjncy[xqnbr] = nabor;
00512         ++xqnbr;
00513 L1400:
00514         ;
00515     }
00516 L1500:
00517 /*                ---------------------------------------- */
00518 /*                IF NO ACTIVE NABOR AFTER THE PURGING ... */
00519 /*                ---------------------------------------- */
00520     nqnbrs = xqnbr - jstrt;
00521     if (nqnbrs > 0) {
00522         goto L1600;
00523     }
00524 /*                    ----------------------------- */
00525 /*                    THEN MERGE RNODE WITH MDNODE. */
00526 /*                    ----------------------------- */
00527     qsize[*mdnode] += qsize[rnode];
00528     qsize[rnode] = 0;
00529     marker[rnode] = *maxint;
00530     dforw[rnode] = -(*mdnode);
00531     dbakw[rnode] = -(*maxint);
00532     goto L1700;
00533 L1600:
00534 /*                -------------------------------------- */
00535 /*                ELSE FLAG RNODE FOR DEGREE UPDATE, AND */
00536 /*                ADD MDNODE AS A NABOR OF RNODE. */
00537 /*                -------------------------------------- */
00538     dforw[rnode] = nqnbrs + 1;
00539     dbakw[rnode] = 0;
00540     adjncy[xqnbr] = *mdnode;
00541     ++xqnbr;
00542     if (xqnbr <= jstop) {
00543         adjncy[xqnbr] = 0;
00544     }
00545 
00546 L1700:
00547     ;
00548     }
00549 L1800:
00550     return 0;
00551 
00552 } /* mmdelm_ */
00553 
00554 /* *************************************************************** */
00555 /* *************************************************************** */
00556 /* *****     MMDUPD ..... MULTIPLE MINIMUM DEGREE UPDATE     ***** */
00557 /* *************************************************************** */
00558 /* *************************************************************** */
00559 
00560 /*     AUTHOR - JOSEPH W.H. LIU */
00561 /*              DEPT OF COMPUTER SCIENCE, YORK UNIVERSITY. */
00562 
00563 /*     PURPOSE - THIS ROUTINE UPDATES THE DEGREES OF NODES */
00564 /*        AFTER A MULTIPLE ELIMINATION STEP. */
00565 
00566 /*     INPUT PARAMETERS - */
00567 /*        EHEAD  - THE BEGINNING OF THE LIST OF ELIMINATED */
00568 /*                 NODES (I.E., NEWLY FORMED ELEMENTS). */
00569 /*        NEQNS  - NUMBER OF EQUATIONS. */
00570 /*        (XADJ,ADJNCY) - ADJACENCY STRUCTURE. */
00571 /*        DELTA  - TOLERANCE VALUE FOR MULTIPLE ELIMINATION. */
00572 /*        MAXINT - MAXIMUM MACHINE REPRESENTABLE (SHORT) */
00573 /*                 INTEGER. */
00574 
00575 /*     UPDATED PARAMETERS - */
00576 /*        MDEG   - NEW MINIMUM DEGREE AFTER DEGREE UPDATE. */
00577 /*        (DHEAD,DFORW,DBAKW) - DEGREE DOUBLY LINKED STRUCTURE. */
00578 /*        QSIZE  - SIZE OF SUPERNODE. */
00579 /*        LLIST  - WORKING LINKED LIST. */
00580 /*        MARKER - MARKER VECTOR FOR DEGREE UPDATE. */
00581 /*        TAG    - TAG VALUE. */
00582 
00583 /* *************************************************************** */
00584 
00585 /* Subroutine */ int mmdupd_(int *ehead, int *neqns, int *xadj, 
00586     shortint *adjncy, int *delta, int *mdeg, shortint *dhead, 
00587     shortint *dforw, shortint *dbakw, shortint *qsize, shortint *llist, 
00588     shortint *marker, int *maxint, int *tag)
00589 {
00590     /* System generated locals */
00591     int i__1, i__2;
00592 
00593     /* Local variables */
00594     static int node, mtag, link, mdeg0, i, j, enode, fnode, nabor, elmnt, 
00595         istop, jstop, q2head, istrt, jstrt, qxhead, iq2, deg, deg0;
00596 
00597 
00598 /* *************************************************************** */
00599 
00600 
00601 /* *************************************************************** */
00602 
00603     /* Parameter adjustments */
00604     --marker;
00605     --llist;
00606     --qsize;
00607     --dbakw;
00608     --dforw;
00609     --dhead;
00610     --adjncy;
00611     --xadj;
00612 
00613     /* Function Body */
00614     mdeg0 = *mdeg + *delta;
00615     elmnt = *ehead;
00616 L100:
00617 /*            ------------------------------------------------------- */
00618 /*            FOR EACH OF THE NEWLY FORMED ELEMENT, DO THE FOLLOWING. */
00619 /*            (RESET TAG VALUE IF NECESSARY.) */
00620 /*            ------------------------------------------------------- */
00621     if (elmnt <= 0) {
00622     return 0;
00623     }
00624     mtag = *tag + mdeg0;
00625     if (mtag < *maxint) {
00626     goto L300;
00627     }
00628     *tag = 1;
00629     i__1 = *neqns;
00630     for (i = 1; i <= i__1; ++i) {
00631     if (marker[i] < *maxint) {
00632         marker[i] = 0;
00633     }
00634 /* L200: */
00635     }
00636     mtag = *tag + mdeg0;
00637 L300:
00638 /*            --------------------------------------------- */
00639 /*            CREATE TWO LINKED LISTS FROM NODES ASSOCIATED */
00640 /*            WITH ELMNT: ONE WITH TWO NABORS (Q2HEAD) IN */
00641 /*            ADJACENCY STRUCTURE, AND THE OTHER WITH MORE */
00642 /*            THAN TWO NABORS (QXHEAD).  ALSO COMPUTE DEG0, */
00643 /*            NUMBER OF NODES IN THIS ELEMENT. */
00644 /*            --------------------------------------------- */
00645     q2head = 0;
00646     qxhead = 0;
00647     deg0 = 0;
00648     link = elmnt;
00649 L400:
00650     istrt = xadj[link];
00651     istop = xadj[link + 1] - 1;
00652     i__1 = istop;
00653     for (i = istrt; i <= i__1; ++i) {
00654     enode = adjncy[i];
00655     link = -enode;
00656     if (enode < 0) {
00657         goto L400;
00658     } else if (enode == 0) {
00659         goto L800;
00660     } else {
00661         goto L500;
00662     }
00663 
00664 L500:
00665     if (qsize[enode] == 0) {
00666         goto L700;
00667     }
00668     deg0 += qsize[enode];
00669     marker[enode] = mtag;
00670 /*                        ---------------------------------- */
00671 /*                        IF ENODE REQUIRES A DEGREE UPDATE, */
00672 /*                        THEN DO THE FOLLOWING. */
00673 /*                        ---------------------------------- */
00674     if (dbakw[enode] != 0) {
00675         goto L700;
00676     }
00677 /*                            --------------------------------------- 
00678 */
00679 /*                            PLACE EITHER IN QXHEAD OR Q2HEAD LISTS. 
00680 */
00681 /*                            --------------------------------------- 
00682 */
00683     if (dforw[enode] == 2) {
00684         goto L600;
00685     }
00686     llist[enode] = qxhead;
00687     qxhead = enode;
00688     goto L700;
00689 L600:
00690     llist[enode] = q2head;
00691     q2head = enode;
00692 L700:
00693     ;
00694     }
00695 L800:
00696 /*            -------------------------------------------- */
00697 /*            FOR EACH ENODE IN Q2 LIST, DO THE FOLLOWING. */
00698 /*            -------------------------------------------- */
00699     enode = q2head;
00700     iq2 = 1;
00701 L900:
00702     if (enode <= 0) {
00703     goto L1500;
00704     }
00705     if (dbakw[enode] != 0) {
00706     goto L2200;
00707     }
00708     ++(*tag);
00709     deg = deg0;
00710 /*                    ------------------------------------------ */
00711 /*                    IDENTIFY THE OTHER ADJACENT ELEMENT NABOR. */
00712 /*                    ------------------------------------------ */
00713     istrt = xadj[enode];
00714     nabor = adjncy[istrt];
00715     if (nabor == elmnt) {
00716     nabor = adjncy[istrt + 1];
00717     }
00718 /*                    ------------------------------------------------ */
00719 /*                    IF NABOR IS UNELIMINATED, INCREASE DEGREE COUNT. */
00720 /*                    ------------------------------------------------ */
00721     link = nabor;
00722     if (dforw[nabor] < 0) {
00723     goto L1000;
00724     }
00725     deg += qsize[nabor];
00726     goto L2100;
00727 L1000:
00728 /*                        -------------------------------------------- */
00729 /*                        OTHERWISE, FOR EACH NODE IN THE 2ND ELEMENT, */
00730 /*                        DO THE FOLLOWING. */
00731 /*                        -------------------------------------------- */
00732     istrt = xadj[link];
00733     istop = xadj[link + 1] - 1;
00734     i__1 = istop;
00735     for (i = istrt; i <= i__1; ++i) {
00736     node = adjncy[i];
00737     link = -node;
00738     if (node == enode) {
00739         goto L1400;
00740     }
00741     if (node < 0) {
00742         goto L1000;
00743     } else if (node == 0) {
00744         goto L2100;
00745     } else {
00746         goto L1100;
00747     }
00748 
00749 L1100:
00750     if (qsize[node] == 0) {
00751         goto L1400;
00752     }
00753     if (marker[node] >= *tag) {
00754         goto L1200;
00755     }
00756 /*                                -----------------------------------
00757 -- */
00758 /*                                CASE WHEN NODE IS NOT YET CONSIDERED
00759 . */
00760 /*                                -----------------------------------
00761 -- */
00762     marker[node] = *tag;
00763     deg += qsize[node];
00764     goto L1400;
00765 L1200:
00766 /*                            ----------------------------------------
00767  */
00768 /*                            CASE WHEN NODE IS INDISTINGUISHABLE FROM
00769  */
00770 /*                            ENODE.  MERGE THEM INTO A NEW SUPERNODE.
00771  */
00772 /*                            ----------------------------------------
00773  */
00774     if (dbakw[node] != 0) {
00775         goto L1400;
00776     }
00777     if (dforw[node] != 2) {
00778         goto L1300;
00779     }
00780     qsize[enode] += qsize[node];
00781     qsize[node] = 0;
00782     marker[node] = *maxint;
00783     dforw[node] = -enode;
00784     dbakw[node] = -(*maxint);
00785     goto L1400;
00786 L1300:
00787 /*                            -------------------------------------- 
00788 */
00789 /*                            CASE WHEN NODE IS OUTMATCHED BY ENODE. 
00790 */
00791 /*                            -------------------------------------- 
00792 */
00793     if (dbakw[node] == 0) {
00794         dbakw[node] = -(*maxint);
00795     }
00796 L1400:
00797     ;
00798     }
00799     goto L2100;
00800 L1500:
00801 /*                ------------------------------------------------ */
00802 /*                FOR EACH ENODE IN THE QX LIST, DO THE FOLLOWING. */
00803 /*                ------------------------------------------------ */
00804     enode = qxhead;
00805     iq2 = 0;
00806 L1600:
00807     if (enode <= 0) {
00808     goto L2300;
00809     }
00810     if (dbakw[enode] != 0) {
00811     goto L2200;
00812     }
00813     ++(*tag);
00814     deg = deg0;
00815 /*                        --------------------------------- */
00816 /*                        FOR EACH UNMARKED NABOR OF ENODE, */
00817 /*                        DO THE FOLLOWING. */
00818 /*                        --------------------------------- */
00819     istrt = xadj[enode];
00820     istop = xadj[enode + 1] - 1;
00821     i__1 = istop;
00822     for (i = istrt; i <= i__1; ++i) {
00823     nabor = adjncy[i];
00824     if (nabor == 0) {
00825         goto L2100;
00826     }
00827     if (marker[nabor] >= *tag) {
00828         goto L2000;
00829     }
00830     marker[nabor] = *tag;
00831     link = nabor;
00832 /*                                ------------------------------ */
00833 /*                                IF UNELIMINATED, INCLUDE IT IN */
00834 /*                                DEG COUNT. */
00835 /*                                ------------------------------ */
00836     if (dforw[nabor] < 0) {
00837         goto L1700;
00838     }
00839     deg += qsize[nabor];
00840     goto L2000;
00841 L1700:
00842 /*                                    ------------------------------- 
00843 */
00844 /*                                    IF ELIMINATED, INCLUDE UNMARKED 
00845 */
00846 /*                                    NODES IN THIS ELEMENT INTO THE 
00847 */
00848 /*                                    DEGREE COUNT. */
00849 /*                                    ------------------------------- 
00850 */
00851     jstrt = xadj[link];
00852     jstop = xadj[link + 1] - 1;
00853     i__2 = jstop;
00854     for (j = jstrt; j <= i__2; ++j) {
00855         node = adjncy[j];
00856         link = -node;
00857         if (node < 0) {
00858         goto L1700;
00859         } else if (node == 0) {
00860         goto L2000;
00861         } else {
00862         goto L1800;
00863         }
00864 
00865 L1800:
00866         if (marker[node] >= *tag) {
00867         goto L1900;
00868         }
00869         marker[node] = *tag;
00870         deg += qsize[node];
00871 L1900:
00872         ;
00873     }
00874 L2000:
00875     ;
00876     }
00877 L2100:
00878 /*                    ------------------------------------------- */
00879 /*                    UPDATE EXTERNAL DEGREE OF ENODE IN DEGREE */
00880 /*                    STRUCTURE, AND MDEG (MIN DEG) IF NECESSARY. */
00881 /*                    ------------------------------------------- */
00882     deg = deg - qsize[enode] + 1;
00883     fnode = dhead[deg];
00884     dforw[enode] = fnode;
00885     dbakw[enode] = -deg;
00886     if (fnode > 0) {
00887     dbakw[fnode] = enode;
00888     }
00889     dhead[deg] = enode;
00890     if (deg < *mdeg) {
00891     *mdeg = deg;
00892     }
00893 L2200:
00894 /*                    ---------------------------------- */
00895 /*                    GET NEXT ENODE IN CURRENT ELEMENT. */
00896 /*                    ---------------------------------- */
00897     enode = llist[enode];
00898     if (iq2 == 1) {
00899     goto L900;
00900     }
00901     goto L1600;
00902 L2300:
00903 /*            ----------------------------- */
00904 /*            GET NEXT ELEMENT IN THE LIST. */
00905 /*            ----------------------------- */
00906     *tag = mtag;
00907     elmnt = llist[elmnt];
00908     goto L100;
00909 
00910 } /* mmdupd_ */
00911 
00912 /* *************************************************************** */
00913 /* *************************************************************** */
00914 /* *****     MMDNUM ..... MULTI MINIMUM DEGREE NUMBERING     ***** */
00915 /* *************************************************************** */
00916 /* *************************************************************** */
00917 
00918 /*     AUTHOR - JOSEPH W.H. LIU */
00919 /*              DEPT OF COMPUTER SCIENCE, YORK UNIVERSITY. */
00920 
00921 /*     PURPOSE - THIS ROUTINE PERFORMS THE FINAL STEP IN */
00922 /*        PRODUCING THE PERMUTATION AND INVERSE PERMUTATION */
00923 /*        VECTORS IN THE MULTIPLE ELIMINATION VERSION OF THE */
00924 /*        MINIMUM DEGREE ORDERING ALGORITHM. */
00925 
00926 /*     INPUT PARAMETERS - */
00927 /*        NEQNS  - NUMBER OF EQUATIONS. */
00928 /*        QSIZE  - SIZE OF SUPERNODES AT ELIMINATION. */
00929 
00930 /*     UPDATED PARAMETERS - */
00931 /*        INVP   - INVERSE PERMUTATION VECTOR.  ON INPUT, */
00932 /*                 IF QSIZE(NODE)=0, THEN NODE HAS BEEN MERGED */
00933 /*                 INTO THE NODE -INVP(NODE); OTHERWISE, */
00934 /*                 -INVP(NODE) IS ITS INVERSE LABELLING. */
00935 
00936 /*     OUTPUT PARAMETERS - */
00937 /*        PERM   - THE PERMUTATION VECTOR. */
00938 
00939 /* *************************************************************** */
00940 
00941 /* Subroutine */ int mmdnum_(int *neqns, shortint *perm, shortint *invp, 
00942     shortint *qsize)
00943 {
00944     /* System generated locals */
00945     int i__1;
00946 
00947     /* Local variables */
00948     static int node, root, nextf, father, nqsize, num;
00949 
00950 
00951 /* *************************************************************** */
00952 
00953 
00954 /* *************************************************************** */
00955 
00956     /* Parameter adjustments */
00957     --qsize;
00958     --invp;
00959     --perm;
00960 
00961     /* Function Body */
00962     i__1 = *neqns;
00963     for (node = 1; node <= i__1; ++node) {
00964     nqsize = qsize[node];
00965     if (nqsize <= 0) {
00966         perm[node] = invp[node];
00967     }
00968     if (nqsize > 0) {
00969         perm[node] = -invp[node];
00970     }
00971 /* L100: */
00972     }
00973 /*        ------------------------------------------------------ */
00974 /*        FOR EACH NODE WHICH HAS BEEN MERGED, DO THE FOLLOWING. */
00975 /*        ------------------------------------------------------ */
00976     i__1 = *neqns;
00977     for (node = 1; node <= i__1; ++node) {
00978     if (perm[node] > 0) {
00979         goto L500;
00980     }
00981 /*                ----------------------------------------- */
00982 /*                TRACE THE MERGED TREE UNTIL ONE WHICH HAS */
00983 /*                NOT BEEN MERGED, CALL IT ROOT. */
00984 /*                ----------------------------------------- */
00985     father = node;
00986 L200:
00987     if (perm[father] > 0) {
00988         goto L300;
00989     }
00990     father = -perm[father];
00991     goto L200;
00992 L300:
00993 /*                ----------------------- */
00994 /*                NUMBER NODE AFTER ROOT. */
00995 /*                ----------------------- */
00996     root = father;
00997     num = perm[root] + 1;
00998     invp[node] = -num;
00999     perm[root] = num;
01000 /*                ------------------------ */
01001 /*                SHORTEN THE MERGED TREE. */
01002 /*                ------------------------ */
01003     father = node;
01004 L400:
01005     nextf = -perm[father];
01006     if (nextf <= 0) {
01007         goto L500;
01008     }
01009     perm[father] = -root;
01010     father = nextf;
01011     goto L400;
01012 L500:
01013     ;
01014     }
01015 /*        ---------------------- */
01016 /*        READY TO COMPUTE PERM. */
01017 /*        ---------------------- */
01018     i__1 = *neqns;
01019     for (node = 1; node <= i__1; ++node) {
01020     num = -invp[node];
01021     invp[node] = num;
01022     perm[num] = node;
01023 /* L600: */
01024     }
01025     return 0;
01026 
01027 } /* mmdnum_ */
01028