/* ----------------------------------------------- sort a list in ascending order using merge sort created -- 95sep22, cca ----------------------------------------------- */ IP * IP_mergeSortUp ( IP *ip0 ) { int i, m, m1 ; IP *ip, *ip1, *ip2, *prev ; /* ---------------------------------------- count the number of elements in the list ---------------------------------------- */ #if MYDEBUG > 0 fprintf(stdout, "\n inside IP_mergeSortUp :") ; IP_fp80(stdout, ip0, 25) ; fflush(stdout) ; #endif for ( ip = ip0, m = 0 ; ip != NULL ; ip = ip->next ) { m++ ; } if ( m <= 1 ) { return(ip0) ; } else { m1 = m / 2 ; #if MYDEBUG > 0 fprintf(stdout, "\n m = %d, m1 = %d, m2 = %d", m, m1, m-m1) ; fflush(stdout) ; #endif for ( i = 1, ip = ip0, prev = NULL ; i < m1 ; i++ ) { prev = ip ; ip = ip->next ; } ip2 = ip->next ; ip->next = NULL ; ip1 = ip0 ; #if MYDEBUG > 0 fprintf(stdout, "\n calling IP_mergeSortUp :") ; IP_fp80(stdout, ip1, 13) ; fflush(stdout) ; #endif ip1 = IP_mergeSortUp(ip1) ; #if MYDEBUG > 0 fprintf(stdout, "\n return from IP_mergeSortUp :") ; IP_fp80(stdout, ip1, 13) ; fprintf(stdout, "\n calling IPmergeSortUp :") ; IP_fp80(stdout, ip2, 13) ; #endif ip2 = IP_mergeSortUp(ip2) ; #if MYDEBUG > 0 fprintf(stdout, "\n return from IP_mergeSortUp :") ; IP_fp80(stdout, ip2, 13) ; fprintf(stdout, "\n calling IP_mergeUp :") ; fprintf(stdout, "\n first list") ; IP_fp80(stdout, ip1, 13) ; fprintf(stdout, "\n second list") ; IP_fp80(stdout, ip2, 13) ; #endif ip = IP_mergeUp(ip1, ip2) ; #if MYDEBUG > 0 fprintf(stdout, "\n return from IP_mergeUp, sorted list : ") ; IP_fp80(stdout, ip, 40) ; fflush(stdout) ; #endif return(ip) ; } }
/* ----------------------------------------- purpose -- eliminate vertex v 1) create v's boundary list 2) merge boundary list onto reach list 3) for each vertex in the boundary 3.1) add v to the subtree list created -- 96feb25, cca ----------------------------------------- */ void MSMD_eliminateVtx ( MSMD *msmd, MSMDvtx *v, MSMDinfo *info ) { int i, ierr, j, nadj, nbnd, nedge, uid, wid, wght ; int *adj, *bnd, *edges ; IP *ip, *ip2, *prev ; IV *reachIV ; MSMDvtx *u, *w ; /* --------------- check the input --------------- */ if ( msmd == NULL || v == NULL || info == NULL ) { fprintf(stderr, "\n fatal error in MSMD_eliminateVtx(%p,%p,%p)" "\n bad input\n", msmd, v, info) ; exit(-1) ; } adj = IV_entries(&msmd->ivtmpIV) ; reachIV = &msmd->reachIV ; /* ----------------------------- create the boundary set for v ----------------------------- */ v->mark = 'X' ; if ( v->subtrees == NULL ) { /* -------------------------------------------------------- v is a leaf, look at its uncovered edge list, move v and any indistinguishable vertices to the end of the list -------------------------------------------------------- */ if ( info->msglvl > 3 ) { fprintf(info->msgFile, "\n vertex %d is a leaf", v->id) ; fflush(info->msgFile) ; } v->status = 'L' ; nedge = v->nadj ; edges = v->adj ; i = 0 ; j = nedge - 1 ; while ( i <= j ) { wid = edges[i] ; w = msmd->vertices + wid ; if ( w == v || w->status == 'I' ) { edges[i] = edges[j] ; edges[j] = wid ; j-- ; } else { w->mark = 'X' ; i++ ; } } v->nadj = j + 1 ; } else { /* ---------------------------------------------------- v is not a leaf, merge its subtrees' boundaries with its uncovered edge list to get the new boundary ---------------------------------------------------- */ if ( info->msglvl > 3 ) { fprintf(info->msgFile, "\n vertex %d is not a leaf", v->id) ; fprintf(info->msgFile, "\n vertex %d, subtrees :", v->id) ; IP_fp80(info->msgFile, v->subtrees, 20) ; fflush(info->msgFile) ; } v->status = 'E' ; nadj = 0 ; while ( (ip = v->subtrees) != NULL ) { if ( info->msglvl > 3 ) { fprintf(info->msgFile, "\n subtree %d, ip(%p)<%d,%p>", ip->val, ip, ip->val, ip->next) ; fflush(info->msgFile) ; } uid = ip->val ; u = msmd->vertices + uid ; u->par = v ; nbnd = u->nadj ; bnd = u->adj ; if ( info->msglvl > 3 ) { fprintf(info->msgFile, "\n bnd of adj subtree %d :", u->id) ; IVfp80(info->msgFile, nbnd, bnd, 25, &ierr) ; fflush(info->msgFile) ; } for ( i = 0 ; i < nbnd ; i++ ) { wid = bnd[i] ; w = msmd->vertices + wid ; if ( w->mark == 'O' && w->status != 'I' ) { w->mark = 'X' ; adj[nadj++] = wid ; } } if ( u->status == 'E' ) { /* ------------------------------------------ u is not a leaf, free its boundary storage ------------------------------------------ */ IVfree(u->adj) ; info->nbytes -= u->nadj * sizeof(int) ; } u->adj = NULL ; u->nadj = 0 ; /* -------------------------------------- put this IP structure on the free list -------------------------------------- */ v->subtrees = ip->next ; ip->val = -1 ; ip->next = msmd->freeIP ; msmd->freeIP = ip ; if ( info->msglvl > 3 ) { fprintf(info->msgFile, "\n v->subtrees = %p, msmd->freeIP = %p", v->subtrees, msmd->freeIP) ; fflush(info->msgFile) ; } } /* ------------------------------------------------ merge all uncovered edges into the boundary list ------------------------------------------------ */ nedge = v->nadj ; edges = v->adj ; for ( i = 0 ; i < nedge ; i++ ) { wid = edges[i] ; w = msmd->vertices + wid ; if ( w->mark == 'O' && w->status != 'I' ) { w->mark = 'X' ; adj[nadj++] = wid ; } } /* ---------------------------------------------------------- if boundary is not empty, allocate new storage for entries ---------------------------------------------------------- */ v->nadj = nadj ; if ( nadj > 0 ) { v->adj = IVinit(nadj, -1) ; IVcopy(nadj, v->adj, adj) ; info->nbytes += nadj*sizeof(int) ; if ( info->maxnbytes < info->nbytes ) { info->maxnbytes = info->nbytes ; } } else { v->adj = NULL ; } } if ( info->msglvl > 3 ) { fprintf(info->msgFile, "\n bnd(%d) :", v->id) ; if ( v->nadj > 0 ) { IVfp80(info->msgFile, v->nadj, v->adj, 17, &ierr) ; } fflush(info->msgFile) ; } /* ---------------------------------------------- for each boundary vertex 1. add v to subtree list 2. put v on reach set if not already there 3. unmark and add weight to boundary weight ---------------------------------------------- */ nbnd = v->nadj ; bnd = v->adj ; if ( info->msglvl > 3 ) { fprintf(info->msgFile, "\n %d's bnd :", v->id) ; IVfp80(info->msgFile, nbnd, bnd, 12, &ierr) ; fflush(info->msgFile) ; } wght = 0 ; for ( i = 0 ; i < nbnd ; i++ ) { wid = bnd[i] ; w = msmd->vertices + wid ; if ( info->msglvl > 4 ) { fprintf(info->msgFile, "\n adjacent vertex %d", w->id) ; fflush(info->msgFile) ; } /* ------------------------------- add v to the subtree list for w ------------------------------- */ if ( (ip = msmd->freeIP) == NULL ) { if ( info->msglvl > 2 ) { fprintf(info->msgFile, "\n need to get more IP objects") ; fflush(info->msgFile) ; } /* ------------------------------------------------- no more free IP structures, allocate more storage ------------------------------------------------- */ if ( (ip = IP_init(msmd->incrIP, IP_FORWARD)) == NULL ) { fprintf(stderr, "\n fatal error in MSMD_eliminateVtx%p,%p,%p)" "\n unable to allocate more IP objects", msmd, v, info) ; exit(-1) ; } if ( info->msglvl > 4 ) { fprintf(info->msgFile, "\n old baseIP = %p", msmd->baseIP) ; fprintf(info->msgFile, "\n new baseIP = %p", ip) ; fflush(info->msgFile) ; } ip->next = msmd->baseIP ; msmd->baseIP = ip ; info->nbytes += msmd->incrIP*sizeof(struct _IP) ; if ( info->maxnbytes < info->nbytes ) { info->maxnbytes = info->nbytes ; } ip = msmd->freeIP = msmd->baseIP + 1 ; if ( info->msglvl > 2 ) { fprintf(info->msgFile, "\n all set") ; fflush(info->msgFile) ; } } msmd->freeIP = ip->next ; ip->val = v->id ; ip->next = NULL ; for ( ip2 = w->subtrees, prev = NULL ; ip2 != NULL && ip2->val > ip->val ; ip2 = ip2->next ) { prev = ip2 ; } if ( prev == NULL ) { w->subtrees = ip ; } else { prev->next = ip ; } ip->next = ip2 ; if ( info->msglvl > 3 ) { fprintf(info->msgFile, "\n %d's subtrees :", w->id) ; IP_fp80(info->msgFile, w->subtrees, 15) ; fflush(info->msgFile) ; } /* -------------------------------- add w to reach list if necessary -------------------------------- */ if ( info->msglvl > 4 ) { fprintf(info->msgFile, "\n status[%d] = %c", wid, w->status) ; fflush(info->msgFile) ; } switch ( w->status ) { case 'D' : if ( info->msglvl > 4 ) { fprintf(info->msgFile, ", remove from heap") ; fflush(info->msgFile) ; } IIheap_remove(msmd->heap, wid) ; case 'O' : case 'B' : if ( info->msglvl > 4 ) { fprintf(info->msgFile, ", add to reach set, nreach = %d", IV_size(reachIV) + 1) ; fflush(info->msgFile) ; } IV_push(reachIV, wid) ; w->status = 'R' ; case 'R' : break ; case 'I' : break ; default : fprintf(stderr, "\n error in MSMD_eliminateVtx(%p,%p,%p)" "\n status[%d] = '%c'\n", msmd, v, info, wid, w->status) ; fprintf(stderr, "\n msmd->nvtx = %d", msmd->nvtx) ; exit(-1) ; } /* -------------------------------- unmark the boundary vertices and store the weight of the boundary -------------------------------- */ w->mark = 'O' ; wght += w->wght ; } /* ------------------------------------ unmark v and set its boundary weight ------------------------------------ */ v->mark = 'O' ; v->bndwght = wght ; return ; }
/* --------------------------------------------- purpose -- to sort a singly linked list in ascending order using a radix sort created -- 95sep22, cca --------------------------------------------- */ IP * IP_radixSortUp ( IP *ip ) { int b1, b2, d, dneg, dpos, i, j, negmin, posmax ; IP *head, *next, *tail ; IP *poshead, *neghead, *zerohead ; IP *postail, *negtail, *zerotail ; #define BASE 10 IP *heads[BASE], *tails[BASE] ; /* -------------------------------------------------------- split the list into negative, zero and positive sublists -------------------------------------------------------- */ poshead = postail = neghead = negtail = zerohead = NULL ; zerotail = NULL ; posmax = negmin = 0 ; while ( ip != NULL ) { next = ip->next ; if ( ip->val > 0 ) { ip->next = poshead, poshead = ip ; if ( posmax < ip->val ) { posmax = ip->val ; } } else if ( ip->val < 0 ) { ip->next = neghead, neghead = ip ; if ( negmin > ip->val ) { negmin = ip->val ; } } else { if ( zerohead == NULL ) { zerotail = ip ; } ip->next = zerohead, zerohead = ip ; } ip = next ; } #if MYDEBUG > 0 fprintf(stdout, "\n positive list :") ; IP_fp80(stdout, poshead, 16) ; fprintf(stdout, "\n zero list :") ; IP_fp80(stdout, zerohead, 16) ; fprintf(stdout, "\n negative list :") ; IP_fp80(stdout, neghead, 16) ; fflush(stdout) ; #endif /* --------------- find the limits --------------- */ dpos = 0 ; while ( posmax > 0 ) { dpos++ ; posmax /= 10 ; } negmin = - negmin ; dneg = 0 ; while ( negmin > 0 ) { dneg++ ; negmin /= 10 ; } if ( dpos > dneg ) { d = dpos ; } else { d = dneg ; } #if MYDEBUG > 0 fprintf(stdout, "\n dneg %d, dpos %d, d %d", dneg, dpos, d) ; fflush(stdout) ; #endif /* ---------------------- sort the positive list ---------------------- */ #if MYDEBUG > 0 fprintf(stdout, "\n sorting the positive list") ; #endif for ( i = 0 ; i < BASE ; i++ ) { heads[i] = tails[i] = NULL ; } b1 = 1 ; for ( i = 0 ; i < dpos ; i++ ) { b2 = BASE * b1 ; ip = poshead ; poshead = NULL ; #if MYDEBUG > 0 fprintf(stdout, "\n b1 %d, b2 %d", b1, b2) ; #endif while ( ip != NULL ) { next = ip->next ; j = (ip->val % b2) / b1 ; #if MYDEBUG > 0 fprintf(stdout, "\n ip->val %d, j %d", ip->val, j) ; #endif if ( heads[j] == NULL ) { heads[j] = ip ; } else { tails[j]->next = ip ; } tails[j] = ip ; ip = next ; } for ( j = 0 ; j < BASE ; j++ ) { if ( heads[j] != NULL ) { if ( poshead == NULL ) { poshead = heads[j] ; } else { postail->next = heads[j] ; } postail = tails[j] ; heads[j] = tails[j] = NULL ; } } postail->next = NULL ; b1 = b2 ; } #if MYDEBUG > 0 fprintf(stdout, "\n positive list") ; IP_fprintf(stdout, poshead) ; #endif /* ---------------------- sort the negative list ---------------------- */ #if MYDEBUG > 0 fprintf(stdout, "\n sorting the negative list") ; #endif b1 = 1 ; for ( i = 0 ; i < dneg ; i++ ) { b2 = BASE * b1 ; #if MYDEBUG > 0 fprintf(stdout, "\n b1 %d, b2 %d", b1, b2) ; #endif ip = neghead ; neghead = NULL ; while ( ip != NULL ) { next = ip->next ; j = ((-ip->val) % b2) / b1 ; #if MYDEBUG > 0 fprintf(stdout, "\n ip->val %d, j %d", ip->val, j) ; #endif if ( heads[j] == NULL ) { heads[j] = ip ; } else { tails[j]->next = ip ; } tails[j] = ip ; ip = next ; } for ( j = 0 ; j < BASE ; j++ ) { if ( heads[j] != NULL ) { if ( neghead == NULL ) { neghead = heads[j] ; } else { negtail->next = heads[j] ; } negtail = tails[j] ; heads[j] = tails[j] = NULL ; } } negtail->next = NULL ; b1 = b2 ; } #if MYDEBUG > 0 fprintf(stdout, "\n negative list") ; IP_fprintf(stdout, neghead) ; #endif /* --------------------------- concatenate the three lists --------------------------- */ head = tail = ip = neghead ; while ( ip != NULL ) { next = ip->next ; ip->next = head ; head = ip ; ip = next ; } if ( tail != NULL ) { tail->next = NULL ; } #if MYDEBUG > 0 fprintf(stdout, "\n 1. head = %p, tail = %p", head, tail) ; #endif if ( zerohead != NULL ) { if ( tail != NULL ) { tail->next = zerohead ; } else { head = zerohead ; } tail = zerotail ; } if ( tail != NULL ) { tail->next = NULL ; } #if MYDEBUG > 0 fprintf(stdout, "\n 2. head = %p, tail = %p", head, tail) ; #endif if ( poshead != NULL ) { if ( tail != NULL ) { tail->next = poshead ; } else { head = poshead ; } tail = postail ; } if ( tail != NULL ) { tail->next = NULL ; } #if MYDEBUG > 0 fprintf(stdout, "\n 3. head = %p, tail = %p", head, tail) ; IP_fprintf(stdout, head) ; #endif return(head) ; }
/* ---------------------------------------------- for each uncovered (v,w) if v->subtrees \cap w->subtrees != emptyset remove (v,w) from uncovered edges end if end for created -- 95nov08, cca ---------------------------------------------- */ void MSMD_cleanEdgeList ( MSMD *msmd, MSMDvtx *v, MSMDinfo *info ) { int i, ierr, j, nedge, wid ; int *edges ; IP *ip1, *ip2 ; MSMDvtx *w ; /* --------------- check the input --------------- */ if ( msmd == NULL || v == NULL || info == NULL ) { fprintf(stderr, "\n inside MSMD_cleanEdgeList(%p,%p,%p)" "\n bad input\n", msmd, v, info) ; exit(-1) ; } /* -------------------------------------------- remove covered edges from the uncovered list -------------------------------------------- */ nedge = v->nadj ; edges = v->adj ; if ( info->msglvl > 5 ) { fprintf(info->msgFile, "\n inside MSMD_cleanEdgeList(%p,%p)" "\n %d's edges :", msmd, v, v->id) ; IVfp80(info->msgFile, nedge, edges, 12, &ierr) ; fflush(info->msgFile) ; } i = 0 ; j = nedge - 1 ; while ( i <= j ) { wid = edges[i] ; w = msmd->vertices + wid ; if ( info->msglvl > 5 ) { fprintf(info->msgFile, "\n <%d,%c>", wid, w->status) ; fflush(info->msgFile) ; } if ( w == v ) { /* -------------------------------- purge v from uncovered edge list -------------------------------- */ edges[i] = edges[j] ; edges[j] = wid ; j-- ; } else { switch ( w->status ) { case 'I' : case 'L' : case 'E' : /* -------------------------------- purge w from uncovered edge list -------------------------------- */ edges[i] = edges[j] ; edges[j] = wid ; j-- ; break ; default : ip1 = v->subtrees ; ip2 = w->subtrees ; if ( info->msglvl > 5 ) { fprintf(info->msgFile, "\n subtree list for %d :", v->id) ; IP_fp80(info->msgFile, ip1, 30) ; fprintf(info->msgFile, "\n subtree list for %d :", w->id) ; IP_fp80(info->msgFile, ip2, 30) ; } while ( ip1 != NULL && ip2 != NULL ) { if ( ip1->val > ip2->val ) { ip1 = ip1->next ; } else if ( ip1->val < ip2->val ) { ip2 = ip2->next ; } else { /* --------------------------------- this edge has been covered, break --------------------------------- */ edges[i] = edges[j] ; edges[j] = wid ; j-- ; break ; } } if ( ip1 == NULL || ip2 == NULL ) { /* ------------------------------- this edge was not covered, keep ------------------------------- */ i++ ; } } } } v->nadj = j + 1 ; if ( info->msglvl > 5 ) { fprintf(info->msgFile, "\n leaving MSMD_cleanEdgeList(%p,%p)" "\n %d's edges :", msmd, v, v->id) ; IVfp80(info->msgFile, v->nadj, edges, 12, &ierr) ; fflush(info->msgFile) ; } return ; }