/*61:*/
#line 1584 "./MorseExtract.w"

struct grad12_struct
{
long links[3];
long count;
int flags;
};


/*:61*//*83:*/
#line 2195 "./MorseExtract.w"

typedef struct
{
long*body;
unsigned int size;
unsigned int padded_size;
unsigned long body_length;
unsigned long length;
unsigned long read_index;
unsigned long read_delete_index;
}list;
#define list_count(l) ((l)->length)
#define list_is_empty(l) ((l)->length == 0)
#define list_clear(l)  ((l)->length =  0)
#define list_entry(l,n) ((l)->body + (n)*((l)->padded_size))

/*:83*//*88:*/
#line 2311 "./MorseExtract.w"

#define list_read_init(l) ((l)->read_index =  (l)->read_delete_index =  0)
#define list_read_delete(l) ((l)->read_delete_index--)

/*:88*//*92:*/
#line 2377 "./MorseExtract.w"

struct olist_key
{
long high;
long low;
long eq;
long k;
};

typedef struct
{
list*keys;
list*entries;
long top;
long free;
int sz;
}olist;
#define olist_is_empty(l) ((l)->top < 0)
#define olist_entry(l,n) list_entry((l)->entries,n)
#define olist_get_key(l,n)  (((struct olist_key *)list_entry((l)->keys,n))->k)
#define olist_count(l) list_count((l)->entries)

/*:92*//*101:*/
#line 2620 "./MorseExtract.w"


typedef struct vertexstruct
{
short type;
short h;

void*links[1];
}vertex;

typedef struct edgestruct
{
short type;
short h;

void*links[3];
}edge;

typedef struct trianglestruct
{
short type;
short h;

void*links[5];
}triangle;

typedef struct tetrahedronstruct
{
short type;
short h;

void*links[4];
}tetrahedron;

#define get_vertex(e,i) (vertex *)((e)->links[i])
#define get_edge_vertices(e,vl) ((vl)[0]= get_vertex(e,0), (vl)[1]= get_vertex(e,1))
#define dimension(s) ((s)->type&3)
#define is_critical(t) ((t)->type&8)
#define other_vertex_in_edge(u,e) ((get_vertex(e,0) == u)?get_vertex(e,1):get_vertex(e,0))
#define coface(t,i) (tetrahedron *)((t)->links[3+i])
#define get_edge(t,i) (edge *)((t)->links[i])
#define get_face(t,i) (triangle *)((t)->links[i])
#define is_in_K(v) ((v)->type&4)
#define value(t) (int)((((t)->type&0x80)!=0)?(t)->h:max_value(t,dimension(t)))
#define other_coface(s,t)  (tetrahedron *)(((t) == (s)->links[3])? (s)->links[4]: (s)->links[3])
#define is_deadend(s) ((s)->type & 0x100)
#define make_deadend(s) ((s)->type |=  0x100)



/*:101*//*107:*/
#line 2783 "./MorseExtract.w"

#define vertex_in_edge(v,e) (((v) == get_vertex(e,0))?0:(((v) == get_vertex(e,1))?1:-1))
#define edge_in_triangle(e,t) (((e) == get_edge(t,0))?0:(((e) == get_edge(t,1))?1: \
(((e) == get_edge(t,2))?2:-1)))


/*:107*//*111:*/
#line 2903 "./MorseExtract.w"

#define is_paired_up(t) (((t)->type&0x1C)==4)
#define is_paired_down(t) (((t)->type&0x1C)==0x14)
#define r32(t) get_face(t,((t)->type&0x60)>>5)
#define r21(t) get_edge(t,((t)->type&0x60)>>5)
#define r10(t) get_vertex(t,((t)->type&0x20)>>5)
#define r23(t) coface(t,((t)->type&0x20)>>5)
#define r12(t) (triangle *)((t)->links[2])
#define r01(t) (edge *)((t)->links[0])

/*:111*//*116:*/
#line 3039 "./MorseExtract.w"

#define vertex_id(v) ((v)-vertexlist)
#define edge_id(e) ((e)-elist)
#define triangle_id(f) ((f)-flist)
#define tetrahedron_id(t) ((t)-tlist)
#define id2vertex(id) (vertexlist+(id))
#define id2edge(id) (elist +(id))
#define id2triangle(id) (flist +(id))
#define id2tetrahedron(id) (tlist +(id))

/*:116*//*128:*/
#line 3386 "./MorseExtract.w"

#ifndef in_MorseExtract
extern list*crit[4];
extern long num_simp[4];
extern vertex*vertexlist;
extern edge*elist;
extern triangle*flist;
extern tetrahedron*tlist;
#endif


void Extract(int p);
void ExtractCancel1(int p);
void ExtractCancel2(int p);
void ExtractCancel3(int p);
void read_in_complex(FILE*df);
void*plist_read(list*l);
void get_triangle_vertices(triangle*t,vertex*vlist[3]);
void get_tetrahedron_vertices(tetrahedron*t,vertex*vlist[4]);
vertex*FindGrad01(vertex*u,int m);
tetrahedron*FindGrad23(tetrahedron*tau,int m);
long find_all_grad12_paths(triangle*sigma,olist*edges,int flags);
void list_initialize(list**l,unsigned int sz);
void list_abandon(list**l);
void*list_push(list*l,void*q);
void list_pop(list*l,void*q);
void*list_read(list*l);
void plist_push(list*l,void*q);
void*plist_pop(list*l);
void*plist_read(list*l);
void olist_initialize(olist**l,int sz);
void olist_abandon(olist**l);
void olist_clear(olist*l);
long olist_min(olist*l,void*p);
long olist_add(olist*l,long m,void*p);
long olist_find_add(olist*l,long m,void*p,int*flag);
void abort_message(char*s);

/*:128*/
