#define mark_edge_done(v,e) ((e) ->type|= (((v) ==get_vertex(e,0) ) ?0x200:0x400) ) #define edge_marked_done(v,e) ((e) ->type&(((v) ==get_vertex(e,0) ) ?0x200:0x400) ) \ \ #define slower_and_finer 1 \ #define min(x,y) (((x) > (y) ) ?y:x) #define max(x,y) (((x) > (y) ) ?x:y) #define in_MorseExtract 1 \ #define is_xdeadend(s) ((s) ->type&0x1000) #define make_xdeadend(s) ((s) ->type|= 0x1000) \ #define olist_next_free(l) ((l) ->free>=0) ?(l) ->free:list_count((l) ->entries) #define set_value(t,f) ((t) ->type|= 0x80,(t) ->h= f) #define smallest_vertex_in_edge(e) (vertex_compare(get_vertex(e,0) ,get_vertex(e,1) ) <0? \ get_vertex(e,0) :get_vertex(e,1) ) #define largest_vertex_in_edge(e) (vertex_compare(get_vertex(e,0) ,get_vertex(e,1) ) <0? \ get_vertex(e,1) :get_vertex(e,0) ) #define unmake_critical(s) (s) ->type&= 0xff87 #define make_critical(s) ((s) ->type&= 0xff87,(s) ->type|= 8,plist_push(crit[dimension(s) ],s) ) #define is_persistent(t) ((t) ->type&0x20) #define make_persistent(t) ((t) ->type|= 0x20) #define unmake_persistent(t) ((t) ->type&= 0xffdf) /*1:*/ /*18:*/ #include #include "MorseExtract.h" /*:18*/ /*19:*/ void abort_message(char*s); /*:19*/ /*2:*/ list*crit[4]; long num_simp[4]; vertex*vertexlist; edge*elist; triangle*flist; tetrahedron*tlist; /*:2*/ /*84:*/ void list_initialize(list**l,unsigned int sz) { *l= (list*)malloc(sizeof(list)); if((*l)==NULL)abort_message("Out of memory"); (*l)->size= sz; (*l)->padded_size= (sz+sizeof(long)-1)/sizeof(long); (*l)->length= 0; (*l)->body= NULL; (*l)->body_length= 0; } /*:84*//*85:*/ void list_abandon(list**l) { if((*l)->body_length> 0)free((*l)->body); free(*l); *l= NULL; } /*:85*//*86:*/ void*list_push(list*l,void*q) { long*p; if(l->body_length<=l->length) { l->body_length= l->length+1000; l->body= (long*)realloc(l->body,l->body_length*l->padded_size*sizeof(long)); if(l->body==NULL)abort_message("out of memory"); } p= list_entry(l,l->length); memcpy(p,q,l->size); l->length++; return p; } void plist_push(list*l,void*q) { void*p= q; list_push(l,&p); } /*:86*//*87:*/ void list_pop(list*l,void*q) { long*p; if(l->length==0)abort_message("pop from empty list"); l->length--; p= list_entry(l,l->length); memcpy(q,p,l->size); } void*plist_pop(list*l) { void*p; list_pop(l,&p); return p; } /*:87*//*89:*/ void*list_read(list*l) { void*p,*pp; if(l->read_index>=l->length) { l->length= l->read_index= l->read_delete_index; return(NULL); } pp= list_entry(l,l->read_delete_index); if(l->read_index!=l->read_delete_index) { p= list_entry(l,l->read_index); memcpy(pp,p,l->size); } l->read_delete_index++; l->read_index++; return pp; } void*plist_read(list*l) { void**r; r= list_read(l); if(r!=NULL)return*r; else return NULL; } /*:89*//*90:*/ void*list_read_insert(list*l,void*p) { if(l->read_index==l->read_delete_index) list_push(l,p); else { memcpy(list_entry(l,l->read_delete_index),p,l->size); l->read_delete_index++; } } /*:90*//*93:*/ void olist_initialize(olist**l,int sz) { *l= (olist*)malloc(sizeof(olist)); if((*l)==NULL)abort_message("Out of memory"); list_initialize(&((*l)->keys),sizeof(struct olist_key)); list_initialize(&((*l)->entries),sz); (*l)->top= -1; (*l)->free= -1; (*l)->sz= sz; } /*:93*//*94:*/ void olist_abandon(olist**l) { list_abandon(&((*l)->keys)); list_abandon(&((*l)->entries)); free(*l); *l= NULL; } /*:94*//*95:*/ void olist_clear(olist*l) { list_clear(l->keys); list_clear(l->entries); l->top= -1; l->free= -1; } /*:95*//*96:*/ long olist_min(olist*l,void*p) { struct olist_key*q,*r; long min_index; min_index= l->top; if(min_index<0)abort_message("min of empty list"); q= (struct olist_key*)list_entry(l->keys,min_index); if(q->low>=0) { while(q->low>=0) { r= q; min_index= q->low; q= (struct olist_key*)list_entry(l->keys,min_index); } if(q->eq>=0) { r= q; min_index= q->eq; q= (struct olist_key*)list_entry(l->keys,min_index); r->eq= q->eq; } else r->low= q->high; } else if(q->eq>=0) { r= q; min_index= q->eq; q= (struct olist_key*)list_entry(l->keys,min_index); r->eq= q->eq; } else l->top= q->high; memcpy(p,list_entry(l->entries,min_index),l->sz); q->low= l->free; l->free= min_index; return q->k; } /*:96*//*97:*/ long olist_add(olist*l,long m,void*p) { struct olist_key*q,*r; long b,*last; b= olist_next_free(l); /*99:*/ { struct olist_key rr; rr.high= rr.low= rr.eq= -1; rr.k= m; if(l->free>=0) { memcpy(list_entry(l->entries,b),p,l->sz); r= (struct olist_key*)list_entry(l->keys,b); l->free= r->low; memcpy(r,&rr,sizeof(struct olist_key)); } else { list_push(l->entries,p); r= (struct olist_key*)list_push(l->keys,&rr); } } /*:99*/ last= &(l->top); while((*last)>=0) { q= (struct olist_key*)list_entry(l->keys,*last); if(mk)last= &(q->low); else if(m> q->k)last= &(q->high); else { r->eq= *last; r->low= q->low; r->high= q->high; q->low= -1; q->high= -1; break; } } *last= b; return b; } /*:97*//*98:*/ long olist_find_add(olist*l,long m,void*p,int*flag) { struct olist_key*q,*r; long b,*last; last= &(l->top); while((*last)>=0) { q= (struct olist_key*)list_entry(l->keys,*last); if(mk)last= &(q->low); else if(m> q->k)last= &(q->high); else { if(flag!=NULL)*flag= 1; return*last; } } if(p!=NULL) { b= *last= olist_next_free(l); /*99:*/ { struct olist_key rr; rr.high= rr.low= rr.eq= -1; rr.k= m; if(l->free>=0) { memcpy(list_entry(l->entries,b),p,l->sz); r= (struct olist_key*)list_entry(l->keys,b); l->free= r->low; memcpy(r,&rr,sizeof(struct olist_key)); } else { list_push(l->entries,p); r= (struct olist_key*)list_push(l->keys,&rr); } } /*:99*/ } else b= -1; if(flag!=NULL)*flag= 0; return b; } /*:98*/ /*102:*/ void get_triangle_vertices(triangle*t,vertex*vlist[3]) { vertex*v; edge*e; e= get_edge(t,0); get_edge_vertices(e,vlist); e= get_edge(t,1); v= get_vertex(e,1); if(v!=vlist[0]&&v!=vlist[1])vlist[2]= v; else vlist[2]= get_vertex(e,0); } void get_tetrahedron_vertices(tetrahedron*t,vertex*vlist[4]) { vertex*vlistp[3]; int i; get_triangle_vertices(get_face(t,0),vlist); get_triangle_vertices(get_face(t,1),vlistp); for(i= 0;i<3;i++) { if(vlistp[i]!=vlist[0]&&vlistp[i]!=vlist[1]&&vlistp[i]!=vlist[2]) { vlist[3]= vlistp[i]; break; } } } /*:102*//*103:*/ int edge_orient(triangle*t,int i) { vertex*vl[2],*vlp[2]; if(i==0)return 1; get_edge_vertices(get_edge(t,0),vl); get_edge_vertices(get_edge(t,i),vlp); if(vlp[0]==vl[1]||vlp[1]==vl[0])return 1; return-1; } /*:103*//*104:*/ long vertex_compare(vertex*v,vertex*w) { if(value(v) value(w))return 1; else return(long)v-(long)w; } /*:104*//*105:*/ int smallest_vertex(vertex*v[2],int n) { int i,j; for(i= 0,j= 1;j 0)i= j; } return i; } /*:105*//*106:*/ int is_in_lower_Star(tetrahedron*t,vertex*v) { vertex*vlist[4]; get_tetrahedron_vertices(t,vlist); return v==vlist[largest_vertex(vlist,4)]; } /*:106*//*108:*/ int triangle_in_tetrahedron(triangle*s,tetrahedron*t) { int i; for(i= 0;i<4;i++) { if(s==get_face(t,i))return i; } return-1; } /*:108*//*109:*/ edge*other_edge(vertex*v,edge*f,triangle*t) { int i; edge*e; for(i= 0;i<3;i++) { e= get_edge(t,i); if(e==f)continue; if(get_vertex(e,0)==v||get_vertex(e,1)==v)return e; } return NULL; } triangle* other_face(edge*e,triangle*f,tetrahedron*t) { int i; triangle*s; for(i= 0;i<4;i++) { s= get_face(t,i); if(f!=s&&edge_in_triangle(e,s)>=0)return s; } return NULL; } /*:109*//*110:*/ void clean_crit(void) { tetrahedron*t; triangle*f; edge*e; vertex*v; list*l; l= crit[0]; list_read_init(l); while((v= (vertex*)plist_read(l))!=NULL) { if(!is_critical(v))list_read_delete(l); } l= crit[1]; list_read_init(l); while((e= (edge*)plist_read(l))!=NULL) { if(!is_critical(e))list_read_delete(l); } l= crit[2]; list_read_init(l); while((f= (triangle*)plist_read(l))!=NULL) { if(!is_critical(f))list_read_delete(l); } l= crit[3]; list_read_init(l); while((t= (tetrahedron*)plist_read(l))!=NULL) { if(!is_critical(t))list_read_delete(l); } } /*:110*//*112:*/ void pair01(vertex*s0,edge*s1) { int n; s0->type&= 0xFF87; s1->type&= 0xFF87; s0->links[0]= s1; n= vertex_in_edge(s0,s1); s1->type|= (16+(n<<5)); } void pair12(edge*s0,triangle*s1) { int n; s0->type&= 0xFF87; s1->type&= 0xFF87; s0->links[2]= s1; n= edge_in_triangle(s0,s1); s1->type|= (16+(n<<5)); } void pair23(triangle*s0,tetrahedron*s1) { int n; s0->type&= 0xFF87; s1->type&= 0xFF87; if(s0->links[4]==s1)s0->type|= 0x20; n= triangle_in_tetrahedron(s0,s1); s1->type|= (16+(n<<5)); } /*:112*//*113:*/ int max_value(void*s,int d) { tetrahedron*te; triangle*t; edge*e; int m0,m1; if(s==NULL)return-0x8000; switch(d) { case 3: te= (tetrahedron*)s; m0= value(get_face(te,0)); m1= value(get_face(te,1)); break; case 2: t= (triangle*)s; m0= value(get_edge(t,0)); m1= value(get_edge(t,1)); break; case 1: e= (edge*)s; m0= value(get_vertex(e,0)); m1= value(get_vertex(e,1)); break; default: abort_message("max value of simplex of unknown dimension"); break; } return max(m0,m1); } /*:113*//*114:*/ int min_value(void*s,int d) { tetrahedron*te; triangle*t; edge*e; int m0,m1; if(s==NULL)return 0x7fff; switch(d) { case 3: te= (tetrahedron*)s; m0= min_value(get_face(te,0),2); m1= min_value(get_face(te,1),2); break; case 2: t= (triangle*)s; m0= min_value(get_edge(t,0),1); m1= min_value(get_edge(t,1),1); break; case 1: e= (edge*)s; m0= value(get_vertex(e,0)); m1= value(get_vertex(e,1)); break; default: abort_message("min value of simplex of unknown dimension"); break; } return min(m0,m1); } /*:114*/ /*115:*/ void abort_message(char*s) { printf("Error: %s",s); exit(1); } /*:115*/ /*117:*/ vertex*new_vertex(long id,short val,short flag) { vertex*v; v= id2vertex(id); v->type= (flag)?0x84:0x80; v->links[0]= NULL; v->h= val; return v; } /*:117*//*118:*/ edge*new_edge(long id,long vids[2],short flag) { edge*e; short flagp; vertex*v0,*v1; e= id2edge(id); v0= id2vertex(vids[0]); v1= id2vertex(vids[1]); e->links[0]= v0; e->links[1]= v1; e->links[2]= NULL; e->h= max(v0->h,v1->h); flagp= (flag&&is_in_K(v0)&&is_in_K(v1)); e->type= (flagp)?5:1; if(flag> 0&&flagp==0) abort_message("vertices of edge in K must be in K"); if(v0->links[0]==NULL)v0->links[0]= e; if(v1->links[0]==NULL)v1->links[0]= e; return e; } /*:118*//*119:*/ triangle*new_triangle(long id,long eids[3],short flag) { triangle*t; vertex*vl[3],*v[2]; edge*e0,*e1,*e2; short flagp; e0= id2edge(eids[0]); e1= id2edge(eids[1]); e2= id2edge(eids[2]); get_edge_vertices(e0,vl); get_edge_vertices(e1,v); if(vertex_in_edge(v[0],e0)<0)vl[2]= v[0]; else if(vertex_in_edge(v[1],e0)<0)vl[2]= v[1]; else abort_message("new triangle has more than three vertices"); get_edge_vertices(e2,v); if(v[0]!=vl[0]&&v[0]!=vl[1]&&v[0]!=vl[2]) abort_message("new triangle has more than three vertices-1"); if(v[1]!=vl[0]&&v[1]!=vl[1]&&v[1]!=vl[2]) abort_message("new triangle has more than three vertices-2"); t= id2triangle(id); t->links[0]= e0; t->links[1]= e1; t->links[2]= e2; t->h= max(e0->h,e1->h); flagp= (flag&&is_in_K(e0)&&is_in_K(e1)&&is_in_K(e2)); t->type= (flagp)?6:2; t->links[3]= NULL; t->links[4]= NULL; if(e0->links[2]==NULL)e0->links[2]= t; if(e1->links[2]==NULL)e1->links[2]= t; if(e2->links[2]==NULL)e2->links[2]= t; if(flag> 0&&flagp==0) abort_message("edges of triangle in K must be in K"); return t; } /*:119*//*120:*/ tetrahedron*new_tetrahedron(long id,long fids[4],short flag) { tetrahedron*t; vertex*vl[4],*vlp[3]; int i; short flagp; triangle*f0,*f1,*f2,*f3; f0= id2triangle(fids[0]); f1= id2triangle(fids[1]); f2= id2triangle(fids[2]); f3= id2triangle(fids[3]); get_triangle_vertices(f0,vl); get_triangle_vertices(f1,vlp); for(i= 0;i<3;i++) { if(vlp[i]!=vl[0]&&vlp[i]!=vl[1]&&vlp[i]!=vl[2]) { vl[3]= vlp[i]; break; } } /*121:*/ for(i= 0;i<3;i++) { if(vlp[i]!=vl[0]&&vlp[i]!=vl[1]&&vlp[i]!=vl[2]&&vlp[i]!=vl[3]) abort_message("new tetrahedron has more than four vertices"); } /*:121*/ get_triangle_vertices(f2,vlp); /*121:*/ for(i= 0;i<3;i++) { if(vlp[i]!=vl[0]&&vlp[i]!=vl[1]&&vlp[i]!=vl[2]&&vlp[i]!=vl[3]) abort_message("new tetrahedron has more than four vertices"); } /*:121*/ get_triangle_vertices(f3,vlp); /*121:*/ for(i= 0;i<3;i++) { if(vlp[i]!=vl[0]&&vlp[i]!=vl[1]&&vlp[i]!=vl[2]&&vlp[i]!=vl[3]) abort_message("new tetrahedron has more than four vertices"); } /*:121*/ t= id2tetrahedron(id); t->links[0]= f0; t->links[1]= f1; t->links[2]= f2; t->links[3]= f3; t->h= max(f0->h,f1->h); flagp= (flag&&is_in_K(f0)&&is_in_K(f1)&&is_in_K(f2)&&is_in_K(f3)); t->type= (flagp)?7:3; if(f0->links[3]==NULL)f0->links[3]= t; else if(f0->links[4]==NULL)f0->links[4]= t; else abort_message("a triangle can be in only two tetrahedra"); if(f1->links[3]==NULL)f1->links[3]= t; else if(f1->links[4]==NULL)f1->links[4]= t; else abort_message("a triangle can be in only two tetrahedra-1"); if(f2->links[3]==NULL)f2->links[3]= t; else if(f2->links[4]==NULL)f2->links[4]= t; else abort_message("a triangle can be in only two tetrahedra-2"); if(f3->links[3]==NULL)f3->links[3]= t; else if(f3->links[4]==NULL)f3->links[4]= t; else abort_message("a triangle can be in only two tetrahedra-3"); if(flag> 0&&flagp==0) abort_message("faces of tetrahedron in K must be in K"); return t; } /*:120*//*123:*/ void read_in_complex(FILE*df) { long i,n[4]; int res; /*124:*/ { int val; int vertex_in_K,c; res= fscanf(df,"%ld\n",n); if(res!=1)abort_message("bad number of vertices"); num_simp[0]= n[0]; vertexlist= (vertex*)malloc(n[0]*sizeof(vertex)); if(vertexlist==NULL)abort_message("Out of memory"); for(i= 0;i m) { e= r01(v); v= other_vertex_in_edge(v,e); } if(value(v)<=m)return NULL; return v; } /*:51*//*52:*/ tetrahedron*FindGrad23(tetrahedron*tau,int m) { tetrahedron*t; triangle*s; if(tau==NULL)return NULL; t= tau; while(is_in_K(t)&&value(t)count++; if(!flag) { if(is_critical(ep))list_push(crits,&n); else list_push(to_do,&n); } } } if(livecount==0&&e!=NULL)make_deadend(e); } /*:55*/ while(!list_is_empty(to_do)) { list_pop(to_do,&m); e= (edge*)olist_get_key(graph,m); t= r12(e); /*55:*/ { int i; long n; int flag; edge*ep; int livecount; livecount= 0; for(i= 0;i<3;i++) { ep= get_edge(t,i); if(e!=ep&&((is_paired_up(ep)&&!is_deadend(ep))||is_critical(ep))) { livecount++; if(value(ep)<=value(sigma)-p)continue; r.up= m; r.count= 0; n= olist_find_add(graph,(long)ep,&r,&flag); q= (struct edge_graph*)olist_entry(graph,n); q->count++; if(!flag) { if(is_critical(ep))list_push(crits,&n); else list_push(to_do,&n); } } } if(livecount==0&&e!=NULL)make_deadend(e); } /*:55*/ } if(flags&1)/*82:*/ { edge*ee; e= NULL; while(!list_is_empty(crits)) { list_pop(crits,&m); ee= (edge*)olist_get_key(graph,m); if(is_persistent(ee)) { e= ee; break; } } } /*:82*/ else/*56:*/ { int best_value,val,bestm; bestm= -1; while(!list_is_empty(crits)) { list_pop(crits,&m); q= (struct edge_graph*)olist_entry(graph,m); val= value((edge*)olist_get_key(graph,m)); if(q->count==1&&(bestm<0||val> best_value)) /*57:*/ { while(q->up>=0) { q= (struct edge_graph*)olist_entry(graph,q->up); if(q->count> 1)break; } if(q->count==1) { best_value= val; bestm= m; } } /*:57*/ } if(bestm>=0)e= (edge*)olist_get_key(graph,bestm); else e= NULL; if(e!=NULL&&grad_path!=NULL)/*58:*/ { list_clear(grad_path); m= bestm; while(m>=0) { plist_push(grad_path,(edge*)olist_get_key(graph,m)); m= ((struct edge_graph*)olist_entry(graph,m))->up; } } /*:58*/ } /*:56*/ return e; } /*:53*//*59:*/ int splitrejoin(tetrahedron*t) { int i,j; edge*e,*ep; triangle*s; for(i= 0;i<4;i++) { s= get_face(t,i); if(is_paired_down(s)) { e= r21(s); for(j= 0;j<3;j++) { ep= get_edge(s,j); if(ep!=e &&(!is_paired_up(ep)||triangle_in_tetrahedron(r12(ep),t)<0))break; } if(j==3)return i; } } return-1; } /*:59*//*60:*/ triangle*unsplitrejoin(tetrahedron*t,int n) { triangle*s,*sp; edge*e; s= get_face(t,n); e= r21(s); sp= other_face(e,s,t); if(!is_in_K(t))return NULL; if(is_critical(sp))return NULL; if(is_paired_down(sp)) abort_message("tetrahedron surrounded by 2->1 triangles"); pair23(s,t); pair12(e,sp); return sp; } /*:60*//*62:*/ long find_all_grad12_paths(triangle*sigma,olist*edges,int options) { int kk= -1; edge*ep; long todo= -2; long this; long crit= -1; struct grad12_struct*p; triangle*f; olist_clear(edges); do { this= todo; if(this>=0) { p= (struct grad12_struct*)olist_entry(edges,this); ep= id2edge(olist_get_key(edges,this)); kk= p->flags&3; if(kk) { todo= p->links[0]; p->links[0]= -1; } else { todo= p->links[1]; p->links[1]= -1; } f= r12(ep); } else f= sigma; /*63:*/ { int k; edge*e; int livecount= 0; for(k= 0;k<3;k++) { if(k==kk)continue; e= get_edge(f,k); /*64:*/ { struct grad12_struct r,*q; triangle*t; int flag; int j; long id; if(is_paired_up(e)&&(!is_deadend(e)||(options&3)==0)) { livecount++; id= olist_find_add(edges,edge_id(e),&r,&flag); q= (struct grad12_struct*)olist_entry(edges,id); if(flag) { p->links[k]= q->links[q->flags&3]; q->links[q->flags&3]= this; } else { q->links[1]= q->links[2]= -1; t= r12(e); q->flags= edge_in_triangle(e,t); q->links[q->flags]= this; if(q->flags)q->links[0]= todo; else q->links[1]= todo; todo= id; } } else if(is_critical(e)) { livecount++; id= olist_find_add(edges,edge_id(e),&r,&flag); q= (struct grad12_struct*)olist_entry(edges,id); if(flag) { p->links[k]= q->links[0]; q->links[0]= this; } else { q->links[0]= this; q->links[1]= crit; q->flags= 3; crit= id; } } } /*:64*/ } if(livecount==0&&(options&3)&&this>=0) { make_deadend(f); make_deadend(ep); } } /*:63*/ }while(todo>=0); if((options&3)==2) /*65:*/ { long j; struct grad12_struct*p; edge*e; list*todo_list; list_initialize(&todo_list,sizeof(long)); todo= crit; while(todo>=0) { /*66:*/ { long next,id; struct grad12_struct*q; int i; list_clear(todo_list); list_push(todo_list,&todo); while(!list_is_empty(todo_list)) { list_pop(todo_list,&next); p= (struct grad12_struct*)olist_entry(edges,next); if(p->flags&4)continue; p->flags|= 4; i= p->flags&3; if(i==3)id= p->links[0]; else id= p->links[i]; e= id2edge(olist_get_key(edges,next)); while(id>=0) { q= (struct grad12_struct*)olist_entry(edges,id); ep= id2edge(olist_get_key(edges,id)); if((q->flags&4)==0) { list_push(todo_list,&id); } i= edge_in_triangle(e,r12(ep)); if(i<0)abort_message("error"); id= q->links[i]; } } } /*:66*/ p= (struct grad12_struct*)olist_entry(edges,todo); todo= p->links[1]; } list_abandon(&todo_list); for(j= 0;jflags&4)continue; e= id2edge(olist_get_key(edges,j)); make_deadend(e); make_deadend(r12(e)); } } /*:65*/ if(options&4) /*67:*/ { list*todo_list; long id= -1,*idp; struct grad12_struct*q; int error_check; list_initialize(&todo_list,sizeof(long)); list_push(todo_list,&id); while(!list_is_empty(todo_list)) { list_read_init(todo_list); error_check= 1; while((idp= (long*)list_read(todo_list))!=NULL) { if(*idp<0) { list_read_delete(todo_list); kk= -1; f= sigma; } else { p= (struct grad12_struct*)olist_entry(edges,*idp); if(p->flags&24)continue; /*68:*/ { edge*e; int i; ep= id2edge(olist_get_key(edges,*idp)); kk= p->flags&3; if(kk==3)id= p->links[0]; else id= p->links[kk]; while(id>=0) { q= (struct grad12_struct*)olist_entry(edges,id); if((q->flags&8)==0)break; e= id2edge(olist_get_key(edges,id)); i= edge_in_triangle(ep,r12(e)); id= q->links[i]; } if(id<0) /*71:*/ { edge*e; int i; long ct= 0; long orient; triangle*t; p->flags&= 0xffffffef; p->flags|= 8; list_read_delete(todo_list); kk= p->flags&3; if(kk==3)id= p->links[0]; else id= p->links[kk]; while(id>=0) { q= (struct grad12_struct*)olist_entry(edges,id); e= id2edge(olist_get_key(edges,id)); t= r12(e); i= edge_in_triangle(ep,t); id= q->links[i]; ct+= edge_orient(t,i)*q->count; } if(id==-2) { ct+= edge_orient(sigma,edge_in_triangle(ep,sigma)); } if(is_critical(ep))p->count= ct; else p->count= -ct*edge_orient(r12(ep),p->flags&3); } /*:71*/ else p->flags|= 16; if(id>=0||is_critical(ep))f= NULL; else f= r12(ep); } /*:68*/ } if(f!=NULL) { error_check= 0; /*69:*/ { int k; edge*e; for(k= 0;k<3;k++) { if(k==kk)continue; e= get_edge(f,k); /*70:*/ { int flag; long qid; if(is_critical(e)||(is_paired_up(e)&&(!is_deadend(e)||(options&3)==0))) { qid= olist_find_add(edges,edge_id(e),NULL,&flag); if(!flag)abort_message("count error 2"); q= (struct grad12_struct*)olist_entry(edges,qid); if((q->flags&32)==0) { list_read_insert(todo_list,&qid); q->flags|= 32; } else q->flags&= 0xffffffef; } } /*:70*/ } } /*:69*/ } } if(error_check&&!list_is_empty(todo_list))abort_message("count error"); } list_abandon(&todo_list); } /*:67*/ return crit; } /*:62*//*72:*/ long find_all_backward_grad12_paths(edge*tau,olist*triangles,list*crits,int options) { int kk= -1; triangle*f; edge*ep; long todo= -1; long this; struct grad12_struct*p; long start= -1; list*todo_list; olist_clear(triangles); if(crits!=NULL)list_clear(crits); if((options&3)==2)list_initialize(&todo_list,sizeof(long)); do { this= todo; if(this>=0) { p= (struct grad12_struct*)olist_entry(triangles,this); f= id2triangle(olist_get_key(triangles,this)); ep= r21(f); kk= p->flags&3; todo= p->links[kk]; p->links[kk]= -1; } else ep= tau; /*73:*/ { tetrahedron*t; int link_count= 0; f= ep->links[2]; t= coface(f,0); do { if(is_in_K(f)&&(is_critical(f)|| ((!is_xdeadend(f)||(options&3)==0)&& is_paired_down(f)&&ep!=r21(f)))) { link_count++; /*74:*/ { struct grad12_struct r,*q; long id; int flag; int k; id= olist_find_add(triangles,triangle_id(f),&r,&flag); q= (struct grad12_struct*)olist_entry(triangles,id); k= edge_in_triangle(ep,f); if(this>=0) p= (struct grad12_struct*)olist_entry(triangles,this); if(flag) { if(q->links[k]>=0)abort_message("backgrad error 1"); if(this<0)abort_message("backgrad error 2"); q->links[k]= p->links[kk]; p->links[kk]= id; } else { q->links[0]= q->links[1]= q->links[2]= -2; if(this>=0) { q->links[k]= p->links[kk]; p->links[kk]= id; } else { q->links[k]= start; start= id; } if(is_critical(f)) { q->flags= 3; if(crits!=NULL)list_push(crits,&id); if((options&3)==2)list_push(todo_list,&id); } else { q->flags= edge_in_triangle(r21(f),f); q->links[q->flags]= todo; todo= id; } } } /*:74*/ } t= other_coface(f,t); f= other_face(ep,f,t); }while(f!=ep->links[2]); if(link_count==0&&(options&3)&&this>=0) { make_xdeadend(ep); make_xdeadend(r12(ep)); } } /*:73*/ }while(todo>=0); if((options&3)==2) /*75:*/ { long id; int k; edge*e; struct grad12_struct r,*q; triangle*f; int flag; while(!list_is_empty(todo_list)) { list_pop(todo_list,&id); p= (struct grad12_struct*)olist_entry(triangles,id); if(p->flags&4)continue; p->flags|= 4; kk= p->flags&3; f= id2triangle(olist_get_key(triangles,id)); for(k= 0;k<3;k++) { if(k==kk||p->links[k]<-1)continue; e= get_edge(f,k); if(is_paired_up(e)&&!is_deadend(e)) { if(is_xdeadend(e))abort_message("back grad error 3"); id= olist_find_add(triangles,triangle_id(r12(e)),&r,&flag); q= (struct grad12_struct*)olist_entry(triangles,id); if(flag==0) { q->flags= edge_in_triangle(e,r12(e)); printf("back grad puzzle\n"); } if((q->flags&4)==0)list_push(todo_list,&id); } } } list_abandon(&todo_list); for(id= 0;idflags&4)continue; f= id2triangle(olist_get_key(triangles,id)); make_deadend(f); make_deadend(r21(f)); } } /*:75*/ return start; } /*:72*/ /*47:*/ void LocalCancel12(vertex*v,edge*sigma,edge*sigmap,triangle*tau) { edge*u; triangle*w,*wp; u= sigmap; w= tau; unmake_critical(tau); while(!is_critical(u)) { wp= r12(u); pair12(u,w); w= wp; u= other_edge(v,u,w); } unmake_critical(sigma); pair12(sigma,w); } /*:47*//*48:*/ void Cancel23(triangle*sigma,int n,tetrahedron*tau) { triangle*s,*sp; tetrahedron*t; s= sigma; t= coface(s,n); unmake_critical(sigma); while(!is_critical(t)) { sp= r32(t); pair23(s,t); s= sp; t= other_coface(s,t); } unmake_critical(tau); pair23(s,tau); } /*:48*//*49:*/ void Cancel01(vertex*v,int n,edge*kappa) { vertex*u; edge*e,*ep; u= get_vertex(kappa,n); e= kappa; unmake_critical(kappa); while(!is_critical(u)) { ep= r01(u); pair01(u,e); e= ep; u= other_vertex_in_edge(u,e); } unmake_critical(v); pair01(v,e); } /*:49*//*50:*/ void Cancel12(edge*sigma,triangle*kappa,list*grad_path,list*changed) { triangle*t,*nextt; edge*e; unmake_critical(kappa); unmake_critical(sigma); t= kappa; do { e= plist_pop(grad_path); if(e==sigma)break; nextt= r12(e); pair12(e,t); plist_push(changed,t); t= nextt; }while(1); pair12(e,t); plist_push(changed,t); } /*:50*/ /*21:*/ void LocalCancel(vertex*v,list*lcrit2) { triangle*t,*s; tetrahedron*te[2]; edge*e[2],*ep[2]; int j,i,in; while(!list_is_empty(lcrit2)) { t= plist_pop(lcrit2); /*22:*/ for(i= 0,j= 0;j<3;j++) { if(vertex_in_edge(v,get_edge(t,j))>=0) { e[i++]= get_edge(t,j); } } /*:22*/ ; /*23:*/ for(i= 0;i<2;i++) { ep[i]= e[i]; while(!is_critical(ep[i])) { if(is_paired_down(ep[i])) { ep[i]= NULL; break; } s= r12(ep[i]); ep[i]= other_edge(v,ep[i],s); } } /*:23*/ ; if(ep[0]!=ep[1]) { /*25:*/ if(ep[0]==NULL)LocalCancel12(v,ep[1],e[1],t); else if(ep[1]==NULL)LocalCancel12(v,ep[0],e[0],t); else if(min_value(ep[0],1)> min_value(ep[1],1)) LocalCancel12(v,ep[0],e[0],t); else LocalCancel12(v,ep[1],e[1],t); /*:25*/ ; } else { for(i= 0;i<2;i++) { /*24:*/ te[i]= coface(t,i); s= t; while(is_in_K(te[i])) { in= is_in_lower_Star(te[i],v); if(!in)break; if(is_critical(te[i]))break; s= r32(te[i]); te[i]= other_coface(s,te[i]); } if(!is_in_K(te[i])||!in) te[i]= NULL; /*:24*/ ; } if(te[0]!=te[1]) { /*26:*/ if(te[0]==NULL)Cancel23(t,1,te[1]); else if(te[1]==NULL)Cancel23(t,0,te[0]); else if(min_value(te[1],3)> min_value(te[0],3)) Cancel23(t,0,te[0]); else Cancel23(t,1,te[1]); /*:26*/ ; } } } } /*:21*//*27:*/ void ExtractCancel1(int p) { olist*c0; olist*c1; struct ccrit1 { edge*s; long c[2]; }s; int i; vertex*v[2]; int thisk; olist_initialize(&c0,sizeof(long)); olist_initialize(&c1,sizeof(struct ccrit1)); /*28:*/ { edge*e; list_read_init(crit[1]); while((e= (edge*)plist_read(crit[1]))!=NULL) { if(!is_critical(e))list_read_delete(crit[1]); else { v[0]= FindGrad01(get_vertex(e,0),value(e)-p); v[1]= FindGrad01(get_vertex(e,1),value(e)-p); if(v[0]!=v[1]) { /*29:*/ { long link; link= -1; s.s= e; s.c[0]= (v[0]==NULL)?-1:olist_find_add(c0,(long)v[0],&link,NULL); s.c[1]= (v[1]==NULL)?-1:olist_find_add(c0,(long)v[1],&link,NULL); i= /*34:*/ (v[0]==NULL)?1: (v[1]==NULL)?0: (value(v[0])> value(v[1]))?0: (value(v[0]) value(v[1]))?0: (value(v[0])=0;) { v[i]= (vertex*)olist_get_key(c0,a); if(is_critical(v[i]))break; a= *((long*)olist_entry(c0,a)); } *((long*)olist_entry(c0,s.c[i]))= a; if(value(v[i])<=value(s.s)-p) { v[i]= NULL; s.c[i]= -1; } else s.c[i]= a; } /*:33*/ } if(s.c[1]!=s.c[0]) { i= /*34:*/ (v[0]==NULL)?1: (v[1]==NULL)?0: (value(v[0])> value(v[1]))?0: (value(v[0]) value(t[1]))?1: (value(t[0]) value(t[1]))?1: (value(t[0])=0;) { t[i]= (tetrahedron*)olist_get_key(c3,a); if(is_critical(t[i]))break; a= *((long*)olist_entry(c3,a)); } *((long*)olist_entry(c3,r.c[i]))= a; if(value(t[i])>=value(r.s)+p) { t[i]= NULL; r.c[i]= -1; } else r.c[i]= a; } /*:41*/ } if(r.c[1]!=r.c[0]) { i= /*42:*/ (t[0]==NULL)?1: (t[1]==NULL)?0: (value(t[0])> value(t[1]))?1: (value(t[0])=0) { plist_push(changed,unsplitrejoin(te,j)); k++; } } } } if(!list_is_empty(changed))printf("May be infinite loop in split-rejoin"); } /*:46*/ ; #ifdef verbose if(thisp %d\n",lastp,thisp); #endif lastp= thisp; } else olist_add(goodpairs,thisp,&t); } } /*:45*/ }while(1); list_abandon(&changed); list_abandon(&grad_path); olist_abandon(&goodpairs); } /*:43*/ /*3:*/ void Extract(int p) { long i; long t1,t2,t3,t4,t5,t6; t1= clock(); for(i= 0;i<4;i++)list_initialize(crit+i,sizeof(void*)); /*4:*/ { edge*beste; vertex*v; int is_lower_Star_empty; long vid; list*lcrit2; list*edges_todo; list_initialize(&lcrit2,sizeof(triangle*)); list_initialize(&edges_todo,sizeof(edge*)); for(vid= 0;vidlinks[0]); is_lower_Star_empty= 1; while(!list_is_empty(edges_todo)) { /*6:*/ e= plist_pop(edges_todo); if(edge_marked_done(v,e))continue; mark_edge_done(v,e); /*:6*/ /*7:*/ flag= 0; if(is_in_K(e)) { w= smallest_vertex_in_edge(e); if(w!=v) { set_value(e,val); is_lower_Star_empty= 0; flag= 1; } } /*:7*/ /*8:*/ { triangle*s,*bests,*sp; tetrahedron*t; edge*ep; int state= 0; int bestsval; int first_in_lower_Star; vertex*min_vertex; #ifdef slower_and_finer triangle*bests_in_run,*first_bests_in_run; tetrahedron*bestt_in_run,*first_bestt_in_run; int bestsval_in_run,first_bestsval; #else vertex*first_min_vertex; #endif s= sp= e->links[2]; t= coface(s,0); do { ep= other_edge(v,e,s); if(!edge_marked_done(v,ep))plist_push(edges_todo,ep); #ifdef slower_and_finer if(flag)/*14:*/ { int in_lower_Star_of_e; /*10:*/ in_lower_Star_of_e= 0; if(is_in_K(s)) { vertex*vlist[3]; get_triangle_vertices(s,vlist); min_vertex= vlist[smallest_vertex(vlist,3)]; in_lower_Star_of_e= (vertex_in_edge(min_vertex,e)<0); if(in_lower_Star_of_e)set_value(s,val); } /*:10*/ ; switch(state) { case 0: if(in_lower_Star_of_e) { first_in_lower_Star= (s==sp&&is_in_K(t)); if(first_in_lower_Star)state= 1; else state= 3; bests= NULL; bests_in_run= s; bestt_in_run= t; bestsval_in_run= value(min_vertex); } break; case 1: case 3: if(!in_lower_Star_of_e||!is_in_K(t)) { /*15:*/ if(bests==NULL) { if(state==1) { first_bests_in_run= bests_in_run; first_bestt_in_run= bestt_in_run; first_bestsval= bestsval_in_run; } else { bests= bests_in_run; bestsval= bestsval_in_run; } } else if(bestsval_in_run bestsval_in_run) { sss= bests_in_run; bestt_in_run= other_coface(first_bests_in_run,first_bestt_in_run); bests_in_run= first_bests_in_run; } else sss= first_bests_in_run; /*16:*/ { triangle*ss; tetrahedron*tt; do { tt= other_coface(bests_in_run,bestt_in_run); ss= r32(tt); pair23(bests_in_run,tt); bests_in_run= ss; bestt_in_run= tt; }while(bestt_in_run!=t); bests_in_run= s; bestsval_in_run= value(min_vertex); } /*:16*/ bests_in_run= sss; } /*15:*/ if(bests==NULL) { if(state==1) { first_bests_in_run= bests_in_run; first_bestt_in_run= bestt_in_run; first_bestsval= bestsval_in_run; } else { bests= bests_in_run; bestsval= bestsval_in_run; } } else if(bestsval_in_run