123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398 |
- /* LIBDGL -- a Directed Graph Library implementation
- * Copyright (C) 2002 Roberto Micarelli
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
- /*
- * best view with tabstop=4
- */
- /*
- * Add edge can be performed on TREE state graph. If the state is FLAT
- * return BadOnFlatGraph error.
- */
- int DGL_ADD_EDGE_FUNC(dglGraph_s * pgraph,
- dglInt32_t nHead,
- dglInt32_t nTail,
- dglInt32_t nCost,
- dglInt32_t nEdge,
- void *pvHeadAttr,
- void *pvTailAttr, void *pvEdgeAttr, dglInt32_t nFlags)
- {
- dglInt32_t *pHead;
- dglInt32_t *pTail;
- dglInt32_t *pEdgeset;
- dglInt32_t *pEdge;
- DGL_T_NODEITEM_TYPE *pHeadNodeItem;
- DGL_T_NODEITEM_TYPE *pTailNodeItem;
- #if defined(_DGL_V2)
- dglInt32_t *pinEdgeset;
- dglTreeEdge_s *pEdgeItem;
- dglTreeEdge_s findEdge;
- #endif
- if (pgraph->Flags & DGL_GS_FLAT) {
- pgraph->iErrno = DGL_ERR_BadOnFlatGraph;
- return -pgraph->iErrno;
- }
- #ifdef DGL_STATS
- {
- clock_t clk = clock();
- #endif
- if ((pHeadNodeItem =
- DGL_T_NODEITEM_Add(pgraph->pNodeTree, nHead)) == NULL ||
- (pTailNodeItem =
- DGL_T_NODEITEM_Add(pgraph->pNodeTree, nTail)) == NULL) {
- pgraph->iErrno = DGL_ERR_MemoryExhausted;
- return -pgraph->iErrno;
- }
- #ifdef DGL_STATS
- pgraph->clkNodeTree += clock() - clk;
- pgraph->cNodeTree++;
- pgraph->cNodeTree++;
- }
- #endif
- if (DGL_T_NODEITEM_NodePTR(pHeadNodeItem) == NULL) {
- if ((pHead = DGL_NODE_ALLOC(pgraph->NodeAttrSize)) == NULL) {
- pgraph->iErrno = DGL_ERR_MemoryExhausted;
- return -1;
- }
- DGL_NODE_STATUS(pHead) = 0;
- DGL_T_NODEITEM_Set_NodePTR(pHeadNodeItem, pHead);
- pgraph->cNode++;
- pgraph->cHead++;
- }
- else {
- pHead = DGL_T_NODEITEM_NodePTR(pHeadNodeItem);
- if (!(DGL_NODE_STATUS(pHead) & DGL_NS_HEAD))
- pgraph->cHead++;
- }
- if (DGL_T_NODEITEM_NodePTR(pTailNodeItem) == NULL) {
- if ((pTail = DGL_NODE_ALLOC(pgraph->NodeAttrSize)) == NULL) {
- pgraph->iErrno = DGL_ERR_MemoryExhausted;
- return -pgraph->iErrno;
- }
- DGL_NODE_STATUS(pTail) = 0;
- DGL_T_NODEITEM_Set_NodePTR(pTailNodeItem, pTail);
- pgraph->cNode++;
- pgraph->cTail++;
- }
- else {
- pTail = DGL_T_NODEITEM_NodePTR(pTailNodeItem);
- if (!(DGL_NODE_STATUS(pTail) & DGL_NS_TAIL))
- pgraph->cTail++;
- }
- DGL_NODE_STATUS(pHead) |= DGL_NS_HEAD;
- DGL_NODE_STATUS(pTail) |= DGL_NS_TAIL;
- if (DGL_NODE_STATUS(pHead) & DGL_NS_ALONE) {
- DGL_NODE_STATUS(pHead) &= ~DGL_NS_ALONE;
- pgraph->cAlone--;
- }
- if (DGL_NODE_STATUS(pTail) & DGL_NS_ALONE) {
- DGL_NODE_STATUS(pTail) &= ~DGL_NS_ALONE;
- pgraph->cAlone--;
- }
- DGL_NODE_ID(pHead) = nHead;
- DGL_NODE_ID(pTail) = nTail;
- DGL_NODE_EDGESET_OFFSET(pHead) = -1;
- DGL_NODE_EDGESET_OFFSET(pTail) = -1;
- if (pvHeadAttr && pgraph->NodeAttrSize) {
- memcpy(DGL_NODE_ATTR_PTR(pHead), pvHeadAttr, pgraph->NodeAttrSize);
- }
- if (pvTailAttr && pgraph->NodeAttrSize) {
- memcpy(DGL_NODE_ATTR_PTR(pTail), pvTailAttr, pgraph->NodeAttrSize);
- }
- /*
- if ( DGL_T_NODEITEM_OutEdgesetPTR(pTailNodeItem) == NULL )
- {
- pEdgeset = DGL_EDGESET_ALLOC( 0 , pgraph->EdgeAttrSize );
- if ( pEdgeset == NULL ) {
- pgraph->iErrno = DGL_ERR_MemoryExhausted;
- return -pgraph->iErrno;
- }
- DGL_EDGESET_EDGECOUNT(pEdgeset) = 0;
- DGL_T_NODEITEM_Set_OutEdgesetPTR(pTailNodeItem,pEdgeset);
- }
- */
- if ((pEdgeset = DGL_T_NODEITEM_OutEdgesetPTR(pHeadNodeItem)) == NULL) {
- pEdgeset = DGL_EDGESET_ALLOC(1, pgraph->EdgeAttrSize);
- if (pEdgeset == NULL) {
- pgraph->iErrno = DGL_ERR_MemoryExhausted;
- return -pgraph->iErrno;
- }
- DGL_EDGESET_EDGECOUNT(pEdgeset) = 0;
- DGL_T_NODEITEM_Set_OutEdgesetPTR(pHeadNodeItem, pEdgeset);
- }
- else {
- pEdgeset = DGL_EDGESET_REALLOC(pEdgeset,
- DGL_EDGESET_EDGECOUNT(pEdgeset) + 1,
- pgraph->EdgeAttrSize);
- if (pEdgeset == NULL) {
- pgraph->iErrno = DGL_ERR_MemoryExhausted;
- return -pgraph->iErrno;
- }
- DGL_T_NODEITEM_Set_OutEdgesetPTR(pHeadNodeItem, pEdgeset);
- }
- #if defined(_DGL_V2)
- /*
- if ( DGL_T_NODEITEM_InEdgesetPTR(pHeadNodeItem) == NULL )
- {
- pinEdgeset = DGL_EDGESET_ALLOC( 0 , pgraph->EdgeAttrSize );
- if ( pinEdgeset == NULL ) {
- pgraph->iErrno = DGL_ERR_MemoryExhausted;
- return -pgraph->iErrno;
- }
- DGL_EDGESET_EDGECOUNT(pinEdgeset) = 0;
- DGL_T_NODEITEM_Set_InEdgesetPTR(pHeadNodeItem,pinEdgeset);
- }
- */
- if ((pinEdgeset = DGL_T_NODEITEM_InEdgesetPTR(pTailNodeItem)) == NULL) {
- pinEdgeset = DGL_EDGESET_ALLOC(1, pgraph->EdgeAttrSize);
- if (pinEdgeset == NULL) {
- pgraph->iErrno = DGL_ERR_MemoryExhausted;
- return -pgraph->iErrno;
- }
- DGL_EDGESET_EDGECOUNT(pinEdgeset) = 0;
- DGL_T_NODEITEM_Set_InEdgesetPTR(pTailNodeItem, pinEdgeset);
- }
- else {
- pinEdgeset = DGL_EDGESET_REALLOC(pinEdgeset,
- DGL_EDGESET_EDGECOUNT(pinEdgeset) +
- 1, pgraph->EdgeAttrSize);
- if (pinEdgeset == NULL) {
- pgraph->iErrno = DGL_ERR_MemoryExhausted;
- return -pgraph->iErrno;
- }
- DGL_T_NODEITEM_Set_InEdgesetPTR(pTailNodeItem, pinEdgeset);
- }
- /*
- * Set the edge-tree
- */
- findEdge.nKey = nEdge;
- if ((pEdgeItem = dglTreeEdgeAdd(pgraph->pEdgeTree, nEdge)) == NULL) {
- pgraph->iErrno = DGL_ERR_MemoryExhausted;
- return -pgraph->iErrno;
- }
- if (pEdgeItem->pv) {
- pgraph->iErrno = DGL_ERR_EdgeAlreadyExist;
- return -pgraph->iErrno;
- }
- if ((pEdgeItem->pv = DGL_EDGE_ALLOC(pgraph->EdgeAttrSize)) == NULL) {
- pgraph->iErrno = DGL_ERR_MemoryExhausted;
- return -pgraph->iErrno;
- }
- /*
- * assign edge id
- */
- pEdgeset[DGL_EDGESET_EDGECOUNT(pEdgeset) + 1] = nEdge;
- pinEdgeset[DGL_EDGESET_EDGECOUNT(pinEdgeset) + 1] = nEdge;
- ++DGL_EDGESET_EDGECOUNT(pEdgeset);
- ++DGL_EDGESET_EDGECOUNT(pinEdgeset);
- /*
- printf( "add edge: node %ld(%ld,%ld) -> %ld(%ld,%ld)\n",
- DGL_NODE_ID(pHead), DGL_EDGESET_EDGECOUNT(pEdgeset),0,
- DGL_NODE_ID(pTail), 0,DGL_EDGESET_EDGECOUNT(pinEdgeset));
- */
- pEdge = pEdgeItem->pv;
- #endif
- #if defined(_DGL_V1)
- pEdge =
- DGL_EDGESET_EDGE_PTR(pEdgeset, DGL_EDGESET_EDGECOUNT(pEdgeset),
- pgraph->EdgeAttrSize);
- DGL_EDGESET_EDGECOUNT(pEdgeset)++;
- #endif
- DGL_EDGE_HEADNODE_OFFSET(pEdge) = nHead; /* will be an offset after flattening */
- DGL_EDGE_TAILNODE_OFFSET(pEdge) = nTail; /* will be an offset after flattening */
- DGL_EDGE_COST(pEdge) = nCost;
- DGL_EDGE_ID(pEdge) = nEdge;
- #if !defined(_DGL_V1)
- if (nFlags & DGL_ES_DIRECTED)
- DGL_EDGE_STATUS(pEdge) = DGL_ES_DIRECTED;
- else
- DGL_EDGE_STATUS(pEdge) = 0;
- #endif
- pgraph->cEdge++;
- pgraph->nnCost += (dglInt64_t) nCost;
- if (pvEdgeAttr && pgraph->EdgeAttrSize) {
- memcpy(DGL_EDGE_ATTR_PTR(pEdge), pvEdgeAttr, pgraph->EdgeAttrSize);
- }
- /*
- * If requested add a cost-weighted entry into the edge prioritizer
- */
- #if !defined(_DGL_V1)
- if (pgraph->nOptions & DGL_GO_EdgePrioritize_COST) {
- if (dgl_edge_prioritizer_add
- (pgraph, DGL_EDGE_ID(pEdge), DGL_EDGE_COST(pEdge)) < 0) {
- return -pgraph->iErrno;
- }
- }
- #endif
- if (nFlags & DGL_STRONGCONNECT) {
- return DGL_ADD_EDGE_FUNC(pgraph, nTail, nHead, nCost, nEdge,
- pvHeadAttr, pvTailAttr, pvEdgeAttr,
- nFlags & ~DGL_STRONGCONNECT);
- }
- return 0;
- }
- int DGL_DEL_EDGE_FUNC(dglGraph_s * pgraph, dglInt32_t nEdge)
- {
- #if defined(_DGL_V1)
- pgraph->iErrno = DGL_ERR_NotSupported;
- return -pgraph->iErrno;
- #else
- dglTreeEdge_s *pEdgeItem, findEdgeItem;
- dglInt32_t *pEdge;
- if (pgraph->Flags & DGL_GS_FLAT) {
- pgraph->iErrno = DGL_ERR_BadOnFlatGraph;
- return -pgraph->iErrno;
- }
- if (pgraph->pEdgeTree == NULL) {
- pgraph->iErrno = DGL_ERR_UnexpectedNullPointer;
- return -pgraph->iErrno;
- }
- findEdgeItem.nKey = nEdge;
- if ((pEdgeItem = avl_find(pgraph->pEdgeTree, &findEdgeItem)) == NULL) {
- pgraph->iErrno = DGL_ERR_EdgeNotFound;
- return -pgraph->iErrno;
- }
- pEdge = pEdgeItem->pv;
- if (DGL_DEL_NODE_INEDGE_FUNC
- (pgraph, DGL_EDGE_TAILNODE_OFFSET(pEdge), DGL_EDGE_ID(pEdge)) < 0) {
- return -pgraph->iErrno;
- }
- if (DGL_DEL_NODE_OUTEDGE_FUNC
- (pgraph, DGL_EDGE_HEADNODE_OFFSET(pEdge), DGL_EDGE_ID(pEdge)) < 0) {
- return -pgraph->iErrno;
- }
- /* prioritizer sync
- */
- if (pgraph->nOptions & DGL_GO_EdgePrioritize_COST) {
- if (dgl_edge_prioritizer_del
- (pgraph, DGL_EDGE_ID(pEdge), DGL_EDGE_COST(pEdge)) < 0) {
- return -pgraph->iErrno;
- }
- }
- /*
- */
- pgraph->cEdge--;
- pgraph->nnCost -= (dglInt64_t) DGL_EDGE_COST(pEdge);
- avl_delete(pgraph->pEdgeTree, pEdgeItem);
- dglTreeEdgeCancel(pEdgeItem, NULL);
- return 0;
- #endif
- }
- dglInt32_t *DGL_GET_EDGE_FUNC(dglGraph_s * pgraph, dglInt32_t nEdge)
- {
- #if defined(_DGL_V1)
- pgraph->iErrno = DGL_ERR_NotSupported;
- return NULL;
- #else
- register dglInt32_t top; /* top of table */
- register dglInt32_t pos; /* current position to compare */
- register dglInt32_t bot; /* bottom of table */
- register dglInt32_t *pref;
- register int cwords; /* size of a edge in words of 32 bit */
- register dglTreeEdge_s *ptreeEdge;
- dglTreeEdge_s findEdge;
- dglInt32_t id;
- pgraph->iErrno = 0;
- if (pgraph->Flags & DGL_GS_FLAT) {
- cwords = DGL_EDGE_WSIZE(pgraph->EdgeAttrSize);
- /*bot = pgraph->iEdgeBuffer / DGL_EDGE_SIZEOF(pgraph->EdgeAttrSize); */
- bot = pgraph->cEdge;
- top = 0;
- pos = 0;
- pref = (dglInt32_t *) pgraph->pEdgeBuffer;
- /* perform a binary search
- */
- while (top != bot) {
- pos = top + (bot - top) / 2;
- id = DGL_EDGE_ID(&pref[pos * cwords]);
- if (id == nEdge) {
- break;
- }
- else if (nEdge < id) {
- bot = pos;
- }
- else if (nEdge > id) {
- top = pos + 1;
- }
- }
- if (top == bot) {
- return NULL;
- }
- return &pref[pos * cwords];
- }
- else {
- findEdge.nKey = nEdge;
- ptreeEdge = avl_find(pgraph->pEdgeTree, &findEdge);
- if (ptreeEdge && ptreeEdge->pv) {
- return ptreeEdge->pv;
- }
- return NULL;
- }
- #endif
- }
|