static void Dao_ParseTarget( DString *target, DList *parts, DaoValue *sval ) { DString *tmp = sval->xString.value; DaoInteger ival = {DAO_INTEGER,0,0,0,0,0}; daoint i, n = DString_Size( target ); int ch, ch2; DString_Clear( tmp ); for(i=0; i<n; i++){ ch = target->chars[i]; ch2 = target->chars[i+1]; if( ch == '%' && isdigit( ch2 ) ){ DList_PushBack( parts, sval ); DString_Clear( tmp ); ival.value = ch2 - '0'; DList_PushBack( parts, (DaoValue*) & ival ); i ++; }else if( ch == '%' ){ if( i+1 < n ){ DString_AppendChar( tmp, (char)ch2 ); } i ++; }else{ DString_AppendChar( tmp, (char)ch ); } } DList_PushBack( parts, sval ); }
static void NODE_Search( DaoProcess *proc, DaoValue *p[], int N ) { DList *nodes; DaoList *list = DaoProcess_PutList( proc ); DaoxNode *self = (DaoxNode*) p[0]; DaoVmCode *sect = DaoProcess_InitCodeSection( proc, 1 ); daoint method = p[1]->xEnum.value; daoint which = p[2]->xEnum.value; daoint i, j, entry; if( sect == NULL ) return; for(i=0; i<self->graph->nodes->size; i++){ DaoxNode *node = (DaoxNode*) self->graph->nodes->items.pVoid[i]; node->state = 0; } nodes = DList_New(0); DList_PushBack( nodes, self ); entry = proc->topFrame->entry; while( nodes->size ){ DaoxNode *node = NULL; if( method ){ node = (DaoxNode*) DList_Front( nodes ); DList_PopFront( nodes ); }else{ node = (DaoxNode*) DList_Back( nodes ); DList_PopBack( nodes ); } if( node->state ) continue; node->state = 1; if( sect->b >0 ) DaoProcess_SetValue( proc, sect->a, (DaoValue*) node ); proc->topFrame->entry = entry; DaoProcess_Execute( proc ); if( proc->status == DAO_PROCESS_ABORTED ) break; if( proc->stackValues[0]->xInteger.value ){ DaoList_PushBack( list, (DaoValue*) node ); if( which == 0 ) break; } for(j=0; j<node->outs->size; j++){ DaoxEdge *edge = (DaoxEdge*) node->outs->items.pVoid[j]; DaoxNode *node2 = node == edge->first ? edge->second : edge->first; DList_PushBack( nodes, node2 ); } } DaoProcess_PopFrame( proc ); DList_Delete( nodes ); }
DaoxEdge* DaoxGraph_AddEdge( DaoxGraph *self, DaoxNode *first, DaoxNode *second ) { DaoxEdge *edge = DaoxEdge_New( self ); DList_PushFront( first->outs, edge ); if( self->directed ){ if( second->ins == NULL ) second->ins = DList_New(DAO_DATA_VALUE); DList_PushBack( second->ins, edge ); }else{ DList_PushBack( second->outs, edge ); } DList_Append( self->edges, edge ); edge->first = first; edge->second = second; return edge; }
void DList_Insert( DList *self, void *val, daoint id ) { void **buf = self->items.pVoid - self->offset; daoint i; if( id == 0 ){ DList_PushFront( self, val ); return; }else if( id >= self->size ){ DList_PushBack( self, val ); return; } if( self->type == DAO_DATA_VALUE ) DaoGC_LockData(); if( (daoint)(self->offset + self->size + 1) >= self->bufsize ){ if( self->offset > 0 ) memmove( buf, self->items.pVoid, self->size*sizeof(void*) ); self->bufsize += self->bufsize/5 + 5; self->items.pVoid = (void**) dao_realloc( buf, (self->bufsize+1)*sizeof(void*) ); self->offset = 0; } if( self->type && val != NULL ){ for( i=self->size; i>id; i-- ) self->items.pVoid[i] = self->items.pVoid[i-1]; self->items.pVoid[ id ] = NULL; }else{ for( i=self->size; i>id; i-- ) self->items.pVoid[i] = self->items.pVoid[i-1]; self->items.pVoid[id] = val; } if( self->type == DAO_DATA_VALUE ) DaoGC_UnlockData(); if( self->type && val != NULL ){ self->items.pVoid[ id ] = DList_CopyItem( self, val ); } self->size++; }
void DaoxNode_BreadthFirstSearch( DaoxNode *self, DList *nodes ) { daoint i, j; DList_Clear( nodes ); DList_PushBack( nodes, self ); self->state = 1; for(i=0; i<nodes->size; i++){ DaoxNode *node = (DaoxNode*) nodes->items.pVoid[i]; for(j=0; j<node->outs->size; j++){ DaoxEdge *edge = (DaoxEdge*) node->outs->items.pVoid[j]; DaoxNode *node2 = node == edge->first ? edge->second : edge->first; if( node2->state ) continue; node2->state = 1; DList_PushBack( nodes, node2 ); } } }
void DaoxNode_DepthFirstSearch( DaoxNode *self, DList *nodes ) { DList *stack = DList_New(0); daoint j; DList_Clear( nodes ); DList_PushBack( stack, self ); while( stack->size ){ DaoxNode *node = (DaoxNode*) DList_Back( stack ); DList_PopBack( stack ); if( node->state ) continue; node->state = 1; DList_PushBack( nodes, node ); for(j=0; j<node->outs->size; j++){ DaoxEdge *edge = (DaoxEdge*) node->outs->items.pVoid[j]; DaoxNode *node2 = node == edge->first ? edge->second : edge->first; DList_PushBack( stack, node2 ); } } DList_Delete( stack ); }
static double DaoxGraph_MaxFlow_PRTF_Float( DaoxGraph *self, DaoxNode *source, DaoxNode *sink ) { daoint i, n; double inf = 1.0; DList *list = DList_New(0); for(i=0,n=source->outs->size; i<n; i++){ DaoxEdge *edge = source->outs->items.pgEdge[i]; if( source == edge->first ) inf += edge->X.MF->capacity; } for(i=0,n=self->nodes->size; i<n; i++){ DaoxNode *node = self->nodes->items.pgNode[i]; node->X.MF->nextpush = 0; node->X.MF->height = 0; node->X.MF->excess = 0.0; if( node != source && node != sink ) DList_PushBack( list, node ); } source->X.MF->nextpush = 0; source->X.MF->height = n; source->X.MF->excess = inf; for(i=0,n=self->edges->size; i<n; i++){ DaoxEdge *edge = self->edges->items.pgEdge[i]; edge->X.MF->flow_fw = 0.0; edge->X.MF->flow_bw = 0.0; } for(i=0,n=source->outs->size; i<n; i++){ DaoxEdge *edge = source->outs->items.pgEdge[i]; if( source == edge->first ) MaxFlow_PushFloat( source, edge ); } i = 0; while( i < list->size ){ DaoxNode *U = list->items.pgNode[i]; daoint old_height = U->X.MF->height; MaxFlow_DischargeFloat( U ); if( U->X.MF->height > old_height ){ DList_Erase( list, i, 1 ); DList_PushFront( list, U ); i = 0; }else{ i += 1; } } DList_Delete( list ); inf = 0.0; for(i=0,n=source->outs->size; i<n; i++){ DaoxEdge *edge = source->outs->items.pgEdge[i]; if( source == edge->first ) inf += edge->X.MF->flow_fw; } return inf; }
void DCondVar_Wait( DCondVar *self, DMutex *mtx ) { DThreadData *p = (DThreadData*)TlsGetValue( thdSpecKey ); DMutex_Lock( & self->thdMutex ); DList_PushBack( self->thdWaiting, (void*) p->thdObject ); DMutex_Unlock( & self->thdMutex ); if( mtx ) DMutex_Unlock( mtx ); WaitForSingleObject( p->thdObject->condv.myCondVar, INFINITE ); ResetEvent( p->thdObject->condv.myCondVar ); if( mtx ) DMutex_Lock( mtx ); if( p->state & DTHREAD_CANCELED ) DThread_Exit( p->thdObject ); }
int DCondVar_TimedWait( DCondVar *self, DMutex *mtx, double seconds ) { DWORD retc; DThreadData *p = (DThreadData*)TlsGetValue( thdSpecKey ); DMutex_Lock( & self->thdMutex ); DList_PushBack( self->thdWaiting, (void*) p->thdObject ); DMutex_Unlock( & self->thdMutex ); if( mtx ) DMutex_Unlock( mtx ); retc = WaitForSingleObject( p->thdObject->condv.myCondVar, (DWORD)( seconds * 1000 ) ); ResetEvent( p->thdObject->condv.myCondVar ); if( mtx ) DMutex_Lock( mtx ); if( p->state & DTHREAD_CANCELED ) DThread_Exit( p->thdObject ); return ( retc == WAIT_TIMEOUT ); }
void DaoxTriangulator_PushPoint( DaoxTriangulator *self, float x, float y ) { DaoxVertexData *prev = NULL, *vertex = DaoxTriangulator_GetVertex( self, self->points->size ); if( self->vertices->size ){ prev = (DaoxVertexData*) self->vertices->items.pVoid[self->vertices->size-1]; if( prev->next ){ vertex->contour = prev->contour + 1; }else{ vertex->contour = prev->contour; prev->next = vertex; vertex->prev = prev; } } DArray_PushVectorXY( self->points, x, y ); DList_PushBack( self->vertices, vertex ); if( self->start == NULL ) self->start = vertex; }
/* Lock daoCallServer::mutex before calling this function: */ static void DaoCallServer_CacheEvent( DaoTaskEvent *event ) { DaoCallServer *server = daoCallServer; DaoTaskEvent_Reset( event ); DList_PushBack( server->caches, event ); }
/* Lock self::mutex before calling this function: */ static void DaoTaskletServer_CacheEvent( DaoTaskletServer *self, DaoTaskletEvent *event ) { DaoTaskletEvent_Reset( event ); DList_PushBack( self->caches, event ); }
void DaoxGraph_ConnectedComponents( DaoxGraph *self, DList *cclist ) { DList *nodes; DaoxGraph *subgraph; daoint i, j, k, n; if( self->nodes->size == 0 ){ DList_PushBack( cclist, self ); return; } for(i=0; i<self->nodes->size; i++){ DaoxNode *node = (DaoxNode*) self->nodes->items.pVoid[i]; node->state = 0; } nodes = DList_New(0); while( self->nodes->size ){ DaoxNode_BreadthFirstSearch( (DaoxNode*) self->nodes->items.pVoid[0], nodes ); #if 0 printf( "self->nodes->size = %i, %i\n", self->nodes->size, nodes->size ); #endif if( nodes->size == self->nodes->size ){ DList_PushBack( cclist, self ); break; } subgraph = DaoxGraph_New( self->ctype, self->directed ); DList_PushBack( cclist, subgraph ); for(i=0,n=nodes->size; i<n; i++){ DaoxNode *node = (DaoxNode*) nodes->items.pVoid[i]; GC_Assign( & node->graph, subgraph ); DList_PushBack( subgraph->nodes, node ); for(j=0; j<node->outs->size; j++){ DaoxEdge *edge = (DaoxEdge*) node->outs->items.pVoid[j]; if( edge->graph == subgraph ) continue; GC_Assign( & edge->graph, subgraph ); DList_PushBack( subgraph->edges, edge ); } } for(i=0,k=0,n=self->nodes->size; i<n; i++){ DaoxNode *node = (DaoxNode*) self->nodes->items.pVoid[i]; /* Ensure no duplication of the reference (for the Concurrent GC): */ self->nodes->items.pVoid[i] = NULL; if( node->graph != self ){ GC_DecRC( node ); continue; } self->nodes->items.pVoid[k++] = node; } self->nodes->size = k; for(i=0,k=0,n=self->edges->size; i<n; i++){ DaoxNode *edge = (DaoxNode*) self->edges->items.pVoid[i]; /* Ensure no duplication of the reference (for the Concurrent GC): */ self->edges->items.pVoid[i] = NULL; if( edge->graph != self ){ GC_DecRC( edge ); continue; } self->edges->items.pVoid[k++] = edge; } self->edges->size = k; } DList_Delete( nodes ); }
void DaoxTriangulator_Triangulate( DaoxTriangulator *self ) { DaoxVertexData *V, *A, *B, *C, *inside; DaoxVector2D PA, PB, PC, P, *points = self->points->data.vectors2d; int i, imin, imax, contours, K = 0, N = self->vertices->size; double dist, area, ymin, ymax, dmax, dmin; double AB, BC, CA, min_area = 1E-16; if( self->vertices->size == 0 ) return; DaoxTriangulator_InitContourOrientation( self ); V = (DaoxVertexData*) self->vertices->items.pVoid[N-1]; contours = V->contour; DList_Assign( self->worklist, self->vertices ); while( self->worklist->size && (++K) < 10*N ){ A = (DaoxVertexData*) self->worklist->items.pVoid[self->worklist->size-1]; if( A->done ){ DList_PopBack( self->worklist ); continue; } B = A->next; C = A->prev; PA = points[A->index]; PB = points[B->index]; PC = points[C->index]; area = DaoxTriangle_Area( PA, PB, PC ); if( B->next == C ){ /* already a triangle: */ if( fabs( area ) > min_area ) DaoxTriangulator_MakeTriangle( self, A ); A->next->prev = A->prev; A->prev->next = A->next; A->done = B->done = C->done = 1; DList_PopBack( self->worklist ); continue; } ymin = ymax = PA.y; if( PB.y < ymin ) ymin = PB.y; else if( PB.y > ymax ) ymax = PB.y; if( PC.y < ymin ) ymin = PC.y; else if( PC.y > ymax ) ymax = PC.y; imin = B->sorting < C->sorting ? B->sorting : C->sorting; imax = A->sorting; inside = NULL; dmax = - 1.0; dmin = 1E9; /* // find the closest point to the triangle: // // Note: no need to distinguish duplicated vertices, because: // 1. if they are outside of the trianlge, they cause no problem; // 2. they cannot be the "closest" vertex to "A" or another vertex again, // so no problem for joining inner contour or splitting outer contour. // // The reason that they cannot be the "closest" vertex is that, // only a concave vertex from the outer contour or a convex // vertex from an inner contour for a hole can be chosen as the // the "closest" vertex. // // And when its original vertex was choose as the "closest" vertex, // the associated "A" will always be processed until it is removed // from the polygon(s), which will leave the duplicated vertices // as convex vertices on the outer contour! */ for(i=imin+1; i<imax; ++i){ V = (DaoxVertexData*) self->vertices->items.pVoid[i]; P = points[V->index]; if( V->done ) continue; //printf( "%3i: %12f %12f %9p, %3i %3i %3i %3i\n", i, P.x, P.y, V, V->contour, A->contour, V->direction, A->direction ); /* Ingore vertex from other contour with the same direction: */ if( V->contour != A->contour && V->direction == A->direction ) continue; if( V->sorting == A->sorting || V->sorting == B->sorting || V->sorting == C->sorting ) continue; if( P.y > ymax ) continue; if( P.y < ymin ) continue; //printf( "%3i: %12f %12f %9p, %3i %3i %3i %3i\n", i, P.x, P.y, V, V->contour, A->contour, V->direction, A->direction ); BC = DaoxTriangle_Area( P, PB, PC ); AB = DaoxTriangle_Area( P, PA, PB ); CA = DaoxTriangle_Area( P, PC, PA ); if( area < 0.0 ){ AB = -AB; BC = -BC; CA = -CA; } //printf( "%3i: %12f %12f %12f\n", i, AB, BC, CA ); if( BC >= 0.0 && AB >= 0.0 && CA >= 0.0 ){ float d = DaoxVector2D_Dist( P, PA ); if( d < dmin ){ dmin = d; inside = V; } } } #if 0 printf( "A: %15f %15f %9p\n", PA.x, PA.y, A ); printf( "B: %15f %15f %9p\n", PB.x, PB.y, B ); printf( "C: %15f %15f %9p\n", PC.x, PC.y, C ); if( inside ) printf( "I: %15f %15f\n", points[inside->index].x, points[inside->index].y ); printf( "%p\n", inside ); printf( "area: %15f\n", area ); #endif if( inside == NULL ){ A->done = 1; //printf( "area: %15f\n", DaoxTriangle_Area( PA, PB, PC ) ); if( fabs( area ) > min_area ) DaoxTriangulator_MakeTriangle( self, A ); A->next->prev = A->prev; A->prev->next = A->next; DList_PopBack( self->worklist ); //if( self->triangles->size >= 3*111 ) break; }else{ /* point inside the triangle: */ DaoxVertexData *A2, *N2; int breaking = inside->contour == A->contour; if( inside->contour != A->contour ){ /* joining contour: */ /* the "inside" vertex is from a hole: */ DaoxVertexData *V2 = inside; //printf( "joining\n" ); /* update contour: */ do { V2->contour = A->contour; V2->direction = A->direction; V2 = V2->next; } while( V2 != inside ); } /* // connect "inside" to "A" with duplicated vertices, this will either: // 1. connect the inner contour with the outer contour; // 2. or break the outer contour. */ N2 = DaoxTriangulator_GetVertex( self, inside->index ); A2 = DaoxTriangulator_GetVertex( self, A->index ); N2->sorting = inside->sorting; A2->sorting = A->sorting; A2->contour = N2->contour = A->contour; A2->direction = N2->direction = A->direction; A2->prev = A->prev; A->prev->next = A2; A2->next = N2; N2->prev = A2; N2->next = inside->next; inside->next->prev = N2; inside->next = A; A->prev = inside; //printf( "dup: %9p %9p\n", A2, N2 ); if( breaking ){ contours += 1; //printf( "contours = %3i\n", contours ); DaoxVertexData *V2 = inside; /* update contour: */ do { V2->contour = contours; V2 = V2->next; } while( V2 != inside ); } DList_PushBack( self->vertices, N2 ); DList_PushBack( self->vertices, A2 ); DList_PopBack( self->worklist ); DList_PushBack( self->worklist, N2 ); DList_PushBack( self->worklist, A2 ); DList_PushBack( self->worklist, A ); } } }