📄 mmd.c
字号:
* (xadj, adjncy) -- adjacency structure.* output parameters --* (head, dfrow, backward) -- degree doubly linked structure.* qsize -- size of supernode ( initialized to one).* list -- linked list.* marker -- marker vector.****************************************************************************/int mmdint(int neqns, idxtype *xadj, idxtype *adjncy, idxtype *head, idxtype *forward, idxtype *backward, idxtype *qsize, idxtype *list, idxtype *marker){ int fnode, ndeg, node; for ( node = 1; node <= neqns; node++ ) { head[node] = 0; qsize[node] = 1; marker[node] = 0; list[node] = 0; }; /* initialize the degree doubly linked lists. */ for ( node = 1; node <= neqns; node++ ) { ndeg = xadj[node+1] - xadj[node]/* + 1*/; /* george */ if (ndeg == 0) ndeg = 1; fnode = head[ndeg]; forward[node] = fnode; head[ndeg] = node; if ( fnode > 0 ) backward[fnode] = node; backward[node] = -ndeg; }; return 0;}/***************************************************************************** mmdnum --- multi minimum degree numbering* purpose -- this routine performs the final step in producing* the permutation and inverse permutation vectors in the* multiple elimination version of the minimum degree* ordering algorithm.* input parameters --* neqns -- number of equations.* qsize -- size of supernodes at elimination.* updated parameters --* invp -- inverse permutation vector. on input,* if qsize[node] = 0, then node has been merged* into the node -invp[node]; otherwise,* -invp[node] is its inverse labelling.* output parameters --* perm -- the permutation vector.****************************************************************************/void mmdnum(int neqns, idxtype *perm, idxtype *invp, idxtype *qsize){ int father, nextf, node, nqsize, num, root; for ( node = 1; node <= neqns; node++ ) { nqsize = qsize[node]; if ( nqsize <= 0 ) perm[node] = invp[node]; if ( nqsize > 0 ) perm[node] = -invp[node]; }; /* for each node which has been merged, do the following. */ for ( node = 1; node <= neqns; node++ ) { if ( perm[node] <= 0 ) { /* trace the merged tree until one which has not */ /* been merged, call it root. */ father = node; while ( perm[father] <= 0 ) father = - perm[father]; /* number node after root. */ root = father; num = perm[root] + 1; invp[node] = -num; perm[root] = num; /* shorten the merged tree. */ father = node; nextf = - perm[father]; while ( nextf > 0 ) { perm[father] = -root; father = nextf; nextf = -perm[father]; }; }; /* end of -- if ( perm[node] <= 0 ) -- */ }; /* end of -- for ( node = 1; -- */ /* ready to compute perm. */ for ( node = 1; node <= neqns; node++ ) { num = -invp[node]; invp[node] = num; perm[num] = node; }; return;}/***************************************************************************** mmdupd ---- multiple minimum degree update* purpose -- this routine updates the degrees of nodes after a* multiple elimination step.* input parameters --* ehead -- the beginning of the list of eliminated nodes* (i.e., newly formed elements).* neqns -- number of equations.* (xadj, adjncy) -- adjacency structure.* delta -- tolerance value for multiple elimination.* maxint -- maximum machine representable (short) integer.* updated parameters --* mdeg -- new minimum degree after degree update.* (head, forward, backward) -- degree doubly linked structure.* qsize -- size of supernode.* list -- marker vector for degree update.* *tag -- tag value.****************************************************************************/void mmdupd(int ehead, int neqns, idxtype *xadj, idxtype *adjncy, int delta, int *mdeg, idxtype *head, idxtype *forward, idxtype *backward, idxtype *qsize, idxtype *list, idxtype *marker, int maxint,int *tag){ int deg, deg0, element, enode, fnode, i, iq2, istop, istart, j, jstop, jstart, link, mdeg0, mtag, nabor, node, q2head, qxhead; mdeg0 = *mdeg + delta; element = ehead;n100: if ( element <= 0 ) return; /* for each of the newly formed element, do the following. */ /* reset tag value if necessary. */ mtag = *tag + mdeg0; if ( mtag >= maxint ) { *tag = 1; for ( i = 1; i <= neqns; i++ ) if ( marker[i] < maxint ) marker[i] = 0; mtag = *tag + mdeg0; }; /* create two linked lists from nodes associated with 'element': */ /* one with two nabors (q2head) in the adjacency structure, and the*/ /* other with more than two nabors (qxhead). also compute 'deg0',*/ /* number of nodes in this element. */ q2head = 0; qxhead = 0; deg0 = 0; link =element;n400: istart = xadj[link]; istop = xadj[link+1] - 1; for ( i = istart; i <= istop; i++ ) { enode = adjncy[i]; link = -enode; if ( enode < 0 ) goto n400; if ( enode == 0 ) break; if ( qsize[enode] != 0 ) { deg0 += qsize[enode]; marker[enode] = mtag; /*'enode' requires a degree update*/ if ( backward[enode] == 0 ) { /* place either in qxhead or q2head list. */ if ( forward[enode] != 2 ) { list[enode] = qxhead; qxhead = enode; } else { list[enode] = q2head; q2head = enode; }; }; }; /* enf of -- if ( qsize[enode] != 0 ) -- */ }; /* end of -- for ( i = istart; -- */ /* for each node in q2 list, do the following. */ enode = q2head; iq2 = 1;n900: if ( enode <= 0 ) goto n1500; if ( backward[enode] != 0 ) goto n2200; (*tag)++; deg = deg0; /* identify the other adjacent element nabor. */ istart = xadj[enode]; nabor = adjncy[istart]; if ( nabor == element ) nabor = adjncy[istart+1]; link = nabor; if ( forward[nabor] >= 0 ) { /* nabor is uneliminated, increase degree count. */ deg += qsize[nabor]; goto n2100; }; /* the nabor is eliminated. for each node in the 2nd element */ /* do the following. */n1000: istart = xadj[link]; istop = xadj[link+1] - 1; for ( i = istart; i <= istop; i++ ) { node = adjncy[i]; link = -node; if ( node != enode ) { if ( node < 0 ) goto n1000; if ( node == 0 ) goto n2100; if ( qsize[node] != 0 ) { if ( marker[node] < *tag ) { /* 'node' is not yet considered. */ marker[node] = *tag; deg += qsize[node]; } else { if ( backward[node] == 0 ) { if ( forward[node] == 2 ) { /* 'node' is indistinguishable from 'enode'.*/ /* merge them into a new supernode. */ qsize[enode] += qsize[node]; qsize[node] = 0; marker[node] = maxint; forward[node] = -enode; backward[node] = -maxint; } else { /* 'node' is outmacthed by 'enode' */ if (backward[node]==0) backward[node] = -maxint; }; }; /* end of -- if ( backward[node] == 0 ) -- */ }; /* end of -- if ( marker[node] < *tag ) -- */ }; /* end of -- if ( qsize[node] != 0 ) -- */ }; /* end of -- if ( node != enode ) -- */ }; /* end of -- for ( i = istart; -- */ goto n2100;n1500: /* for each 'enode' in the 'qx' list, do the following. */ enode = qxhead; iq2 = 0;n1600: if ( enode <= 0 ) goto n2300; if ( backward[enode] != 0 ) goto n2200; (*tag)++; deg = deg0; /*for each unmarked nabor of 'enode', do the following.*/ istart = xadj[enode]; istop = xadj[enode+1] - 1; for ( i = istart; i <= istop; i++ ) { nabor = adjncy[i]; if ( nabor == 0 ) break; if ( marker[nabor] < *tag ) { marker[nabor] = *tag; link = nabor; if ( forward[nabor] >= 0 ) /*if uneliminated, include it in deg count.*/ deg += qsize[nabor]; else {n1700: /* if eliminated, include unmarked nodes in this*/ /* element into the degree count. */ jstart = xadj[link]; jstop = xadj[link+1] - 1; for ( j = jstart; j <= jstop; j++ ) { node = adjncy[j]; link = -node; if ( node < 0 ) goto n1700; if ( node == 0 ) break; if ( marker[node] < *tag ) { marker[node] = *tag; deg += qsize[node]; }; }; /* end of -- for ( j = jstart; -- */ }; /* end of -- if ( forward[nabor] >= 0 ) -- */ }; /* end of -- if ( marker[nabor] < *tag ) -- */ }; /* end of -- for ( i = istart; -- */n2100: /* update external degree of 'enode' in degree structure, */ /* and '*mdeg' if necessary. */ deg = deg - qsize[enode] + 1; fnode = head[deg]; forward[enode] = fnode; backward[enode] = -deg; if ( fnode > 0 ) backward[fnode] = enode; head[deg] = enode; if ( deg < *mdeg ) *mdeg = deg;n2200: /* get next enode in current element. */ enode = list[enode]; if ( iq2 == 1 ) goto n900; goto n1600;n2300: /* get next element in the list. */ *tag = mtag; element = list[element]; goto n100; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -