//genMethods "-g" "-t" "Graph*" "-I" "LINK/graph/Graph.h" "-d" "graph" "-y" "display_graphptr" "-m" "mark_graphptr" "-w" "free_graphptr" 

#include <iostream.h>
#include <stk.h>
#include <LINK/stkWrapper/LINK_STk.h>

#include <LINK/graph/Graph.h>

#include <LINK/stkWrapper/Wrapper.h>
#include <LINK/stkWrapper/Register.h>

void display_graphptr(SCM, SCM, int);
void mark_graphptr(SCM);
void free_graphptr(SCM);

typedef Graph* _Graph_;

#define _Graph_DATA(x) ((Graph**) (EXTDATA(x)))
#define _Graph_IS_DATA(x) (TYPEP(x, tc_CXXwrapper) && \
		TYPEP(STk_slot_ref(x,val_scm), tc_CXXwrapper) && \
		(EXTID(STk_slot_ref(x,val_scm)) == Wrapper<Graph* >::type))
#define _Graph_ISNT_DATA(x) (!IS_DATA(x))

#define _Graph_CXX_DATA(x) (*(Graph**) (EXTDATA(VAL(x))))
#define _Graph_CXX_IS_DATA(x) (INSTANCEP(x) && \
		TYPEP(STk_slot_ref(x,val_scm), tc_CXXwrapper) && \
		(EXTID(STk_slot_ref(x,val_scm)) == Wrapper<Graph* >::type))
#define _Graph_CXX_ISNT_DATA(x) (!CXX_IS_DATA(x))

//----------------------------------------------------------------------
#include <LINK/basic/Iterator.h>
#include <LINK/basic/Set.h>
#include <strstream.h>
#include <LINK/graph/Vertex.h>
#include <LINK/graph/Edge.h>
#include <LINK/graph/Graph.h>
#include <LINK/graph/UBinGraph.h>
#include <LINK/graph/DBinGraph.h>
#include <LINK/graph/UHyperGraph.h>
#include <LINK/graph/DHyperGraph.h>
#include <LINK/graph/Attribute.h>
#include <LINK/stkWrapper/CollectionWrapper.h>

#define CXX_DATA(x, type_check) (*((type_check)**) (EXTDATA(VAL(x))))
#define CXX_IS_DATA(x, type_check) (INSTANCEP(x) && \
		TYPEP(STk_slot_ref(x,val_scm), tc_CXXwrapper) && \
		(EXTID(STk_slot_ref(x,val_scm)) == type_check))


void display_graphptr(SCM c, SCM port, int mode)
{
        ostrstream oss;
	if (*_Graph_DATA(c))
        	oss << **_Graph_DATA(c);
        oss << ends;
        char *buffer = oss.str();
        Puts(buffer, FILEPTR(port));
        delete buffer;
}

void mark_graphptr(SCM p)
{
        Register<Graph>::markEntry(*_Graph_DATA(p));
}

void free_graphptr(SCM p)
{
        if (!EXTSTATICP(p)) {
                delete _Graph_DATA(p);
        }
}

static SCM wrapGraph(Graph *g)
{
    Graph **gp;

    if (!g)
	return Ntruth;

    switch (g->type()) {
	case MIXEDHYPERGRAPH:
        	Register<Graph>::createEntry(Wrapper<HyperGraph>::type, 
				     Wrapper<HyperGraph>::name, 
				     g);
        	gp = new Graph *(g);
        	return STk_make_CXXwrapper(Wrapper<HyperGraph*>::type,
                     Wrapper<HyperGraph*>::name, (void *) gp, LINK_DYNAMIC);
	case UNDHYPERGRAPH:
        	Register<Graph>::createEntry(Wrapper<UHyperGraph>::type, 
				     Wrapper<UHyperGraph>::name, 
				     g);
        	gp = new Graph *(g);
        	return STk_make_CXXwrapper(Wrapper<UHyperGraph*>::type,
                     Wrapper<UHyperGraph*>::name, (void *) gp, LINK_DYNAMIC);
	case DIRHYPERGRAPH:
        	Register<Graph>::createEntry(Wrapper<DHyperGraph>::type, 
				     Wrapper<DHyperGraph>::name, 
				     g);
        	gp = new Graph *(g);
        	return STk_make_CXXwrapper(Wrapper<DHyperGraph*>::type,
                     Wrapper<DHyperGraph*>::name, (void *) gp, LINK_DYNAMIC);
	case MIXEDBINARYGRAPH:
        	Register<Graph>::createEntry(Wrapper<BinGraph>::type, 
				     Wrapper<BinGraph>::name, 
				     g);
        	gp = new Graph *(g);
		//{
		//	Vertex *v = (*gp)->vertex(0);
		//	double d;
		//	getAttribute((GraphObject*) v, "tmp-x-coord", d);
		//	cout << "in wrapGraph v is: " << v << endl;
		//	cout << "in wrapGraph it is: " << d << endl;
		//}
        	return STk_make_CXXwrapper(Wrapper<BinGraph*>::type,
                     Wrapper<BinGraph*>::name, (void *) gp, LINK_DYNAMIC);
	case UNDBINARYGRAPH:
        	Register<Graph>::createEntry(Wrapper<UBinGraph>::type, 
				     Wrapper<UBinGraph>::name, 
				     g);
        	gp = new Graph *(g);
        	return STk_make_CXXwrapper(Wrapper<UBinGraph*>::type,
                     Wrapper<UBinGraph*>::name, (void *) gp, LINK_DYNAMIC);
	case DIRBINARYGRAPH:
        	Register<Graph>::createEntry(Wrapper<DBinGraph>::type, 
				     Wrapper<DBinGraph>::name, 
				     g);
        	gp = new Graph *(g);
        	return STk_make_CXXwrapper(Wrapper<DBinGraph*>::type,
                     Wrapper<DBinGraph*>::name, (void *) gp, LINK_DYNAMIC);
	case M_MIXEDHYPERGRAPH:
        	Register<Graph>::createEntry(Wrapper<MHyperGraph>::type, 
				     Wrapper<MHyperGraph>::name, 
				     g);
        	gp = new Graph *(g);
        	return STk_make_CXXwrapper(Wrapper<MHyperGraph*>::type,
                     Wrapper<MHyperGraph*>::name, (void *) gp, LINK_DYNAMIC);
	case M_UNDHYPERGRAPH:
        	Register<Graph>::createEntry(Wrapper<MUHyperGraph>::type,
				     Wrapper<MUHyperGraph>::name, 
				     g);
        	gp = new Graph *(g);
        	return STk_make_CXXwrapper(Wrapper<MUHyperGraph*>::type,
                     Wrapper<MUHyperGraph*>::name, (void *) gp, LINK_DYNAMIC);
	case M_DIRHYPERGRAPH:
        	Register<Graph>::createEntry(Wrapper<MDHyperGraph>::type,
				     Wrapper<MDHyperGraph>::name, 
				     g);
        	gp = new Graph *(g);
        	return STk_make_CXXwrapper(Wrapper<MDHyperGraph*>::type,
                     Wrapper<MDHyperGraph*>::name, (void *) gp, LINK_DYNAMIC);
	case M_MIXEDBINARYGRAPH:
        	Register<Graph>::createEntry(Wrapper<MBinGraph>::type, 
				     Wrapper<MBinGraph>::name, 
				     g);
        	gp = new Graph *(g);
        	return STk_make_CXXwrapper(Wrapper<MBinGraph*>::type,
                     Wrapper<MBinGraph*>::name, (void *) gp, LINK_DYNAMIC);
	case M_UNDBINARYGRAPH:
        	Register<Graph>::createEntry(Wrapper<MUBinGraph>::type, 
				     Wrapper<MUBinGraph>::name, 
				     g);
        	gp = new Graph *(g);
        	return STk_make_CXXwrapper(Wrapper<MUBinGraph*>::type,
                     Wrapper<MUBinGraph*>::name, (void *) gp, LINK_DYNAMIC);
	case M_DIRBINARYGRAPH:
        	Register<Graph>::createEntry(Wrapper<MDBinGraph>::type, 
				     Wrapper<MDBinGraph>::name, 
				     g);
        	gp = new Graph *(g);
        	return STk_make_CXXwrapper(Wrapper<MDBinGraph*>::type,
                     Wrapper<MDBinGraph*>::name, (void *) gp, LINK_DYNAMIC);
	default:
		Err("illegal graph type", NIL);
   }
   return NIL;
}

static PRIMITIVE AddSubgraphCmd(SCM g, SCM vs)
{
	Graph *gr, *g2;
        if (!(gr = getGraph(g)))
          Err("add-subgraph: bad arg 1, <graph*> expected", g);

        int& vset_type = Wrapper<Set<Vertex*> >::type;
        if (!CXX_TYPEP(vs, vset_type))
          Err("add-subgraph: bad arg 2, <set<vertex*>> expected", vs);

        Set<Vertex*> s = *(Set<Vertex*>*) CLASSDATA(vs);
	List<Vertex*> l; 
	Iterator<Vertex*> get_vert(&s);
	Vertex *v;
	while (get_vert(v))
		l.append(v);

	Vertex *sv = gr->addSubgraph(l);
	if (!sv) 
		return Ntruth;
        Vertex **w = new Vertex *(sv);
        return STk_make_CXXwrapper(Wrapper<Vertex*>::type,
                        Wrapper<Vertex*>::name, (void *) w, LINK_DYNAMIC);
}

static PRIMITIVE DissolveSubgraphCmd(SCM graph, SCM v1)
{
	Graph *g;
        int& v_type = Wrapper<Vertex*>::type;

        if (!(g = getGraph(graph)))
               Err("dissolve-subgraph: bad arg 1, <graph*> expected", graph);
        if (!CXX_TYPEP(v1, v_type))
               Err("dissolve-subgraph: bad arg 2, <vertex*> expected", v1);

	Vertex *vert1 = *(Vertex**) CLASSDATA(v1);
        Set<Vertex*>* s = new Set<Vertex*>(g->dissolveSubgraph(vert1));
	if (!s)
		return Ntruth;
        return STk_make_CXXwrapper(Wrapper<Set<Vertex*> >::type,
                Wrapper<Set<Vertex*> >::name, (void *) s, LINK_DYNAMIC);
}

static PRIMITIVE InducedSubgraphCmd(SCM g, SCM vs, SCM clone_flag)
{
	Graph *gr, *g2;
        if (!(gr = getGraph(g)))
          Err("induced-subgraph: bad arg 1, <graph*> expected", g);

        int& vset_type = Wrapper<Set<Vertex*> >::type;
        if (!CXX_TYPEP(vs, vset_type))
          Err("induced-subgraph: bad arg 2, <set<vertex*>> expected", vs);

        Set<Vertex*> s = *(Set<Vertex*>*) CLASSDATA(vs);

	if (!INTEGERP(clone_flag))
          Err("induced-subgraph: bad arg 3, (0|1) (1->copy attributes)",
						clone_flag);
	
	g2 = gr->inducedSubgraph(s, INTEGER(clone_flag));
	return wrapGraph(g2);
}

static PRIMITIVE CopyGraphCmd(SCM g, SCM clone_flag)
{
	Graph *gr, *g2;
        if (!(gr = getGraph(g)))
          Err("copy-graph: bad arg 1, <graph*> expected", g);
	if (!INTEGERP(clone_flag))
          Err("copy-graph: bad arg 2, (0|1) (1->copy attributes)",clone_flag);
	
	g2 = gr->copyGraph(INTEGER(clone_flag));
	return wrapGraph(g2);
}

static PRIMITIVE MultiGraphCmd(SCM g, SCM clone_flag)
{
	Graph *gr, *g2;
        if (!(gr = getGraph(g)))
          Err("multi-graph: bad arg 1, <graph*> expected", g);
	if (!INTEGERP(clone_flag))
          Err("multi-graph: bad arg 2, (0|1) (1->copy attributes)",clone_flag);
	
	g2 = multiGraph(gr, INTEGER(clone_flag));
	return wrapGraph(g2);
}

static PRIMITIVE SimpleGraphCmd(SCM g, SCM clone_flag)
{
	Graph *gr, *g2;
        if (!(gr = getGraph(g)))
          Err("simple-graph: bad arg 1, <graph*> expected", g);
	if (!INTEGERP(clone_flag))
          Err("simple-graph: bad arg 2, (0|1) (1->copy attributes)",clone_flag);
	
	g2 = simpleGraph(gr, INTEGER(clone_flag));
	return wrapGraph(g2);
}

static PRIMITIVE NameGraphObjectCmd(SCM go)
{
       GraphObject *gr;
       if (!(gr = getGraphObject(go)))
          Err("graph-object-label: bad arg 1, <graph*>, <vertex*>, or <edge*> " 
				" expected", go);

       return STk_makestring(gr->name());
}


static PRIMITIVE AddVertexGraphCmd(SCM v, SCM g)
{
	Graph *gr;
	char *name;
        if (!(name = getName(v)))
                Err("add-vertex!: bad arg 1, <vertex*> expected", v);
        if (!(gr = getGraph(g)))
                Err("add-vertex!: bad arg 2, <graph*> was expected", g);

        Vertex *x = gr->addVertex(name);
        delete name;
	if (!x) 
		return Ntruth;
        Vertex **w = new Vertex *(x);
        return STk_make_CXXwrapper(Wrapper<Vertex*>::type,
                        Wrapper<Vertex*>::name, (void *) w, LINK_DYNAMIC);
}

static PRIMITIVE DeleteVertexGraphCmd(SCM v, SCM g)
{
	Graph *gr;
	char *name;
        if (!(name = getName(v)))
                Err("remove-vertex!: bad arg 1, <vertex*> expected", v);
        if (!(gr = getGraph(g)))
                Err("remove-vertex!: bad arg 2, <graph*> expected", g);

        Vertex *x = gr->findVertexByName(name);
        delete name;
	if (!x) 
		return Ntruth;
        gr->deleteVertex(x);
        return UNDEFINED;
              
}

static PRIMITIVE DeleteVertex2GraphCmd(SCM v, SCM g)
{
	Graph *gr;
	int& v_type = Wrapper<Vertex*>::type;

	if (!CXX_TYPEP(v, v_type))
                Err("remove-vertex!: bad arg 1, <vertex*> expected", v);
        if (!(gr = getGraph(g)))
                Err("remove-vertex!: bad arg 2, <graph*> expected", g);

	
        Vertex *x = *(Vertex**) CLASSDATA(v);
	if (!x) 
		return Ntruth;
        gr->deleteVertex(x);
        return UNDEFINED;
}


static PRIMITIVE AddVerticesGraphCmd(SCM lower, SCM upper, SCM g)
{
        Graph *gr;

        if (!INTEGERP(lower))
                Err("add-vertices!: bad arg 1, <integer> expected", lower);
        if (!INTEGERP(upper))
                Err("add-vertices!: bad arg 2, <integer> expected", upper);
        if (!(gr = getGraph(g)))
                Err("add-vertices!: bad arg 3, <graph*> expected", g);

        char *name;

        int i, low = INTEGER(lower), high = INTEGER(upper);
        if (low >= high)
                Err("add-vertex!: arg_1 < arg_2 must hold", NIL);

        for (i=low; i<=high; i++) {
                ostrstream oss;
                oss << i << ends;
                name = oss.str();
                gr->addVertex(name);
                delete name;
        }
        Set<Vertex*>* s = new Set<Vertex*>(gr->vertices());
	if (!s)
		return Ntruth;
        return STk_make_CXXwrapper(Wrapper<Set<Vertex*> >::type,
                Wrapper<Set<Vertex*> >::name, (void *) s, LINK_DYNAMIC);
}

static PRIMITIVE DeleteVerticesGraphCmd(SCM lower, SCM upper, SCM g)
{
        Graph *gr;

        if (!INTEGERP(lower))
                Err("remove-vertices!: bad arg 1, <integer> expected", lower);
        if (!INTEGERP(upper))
                Err("remove-vertices!: bad arg 2, <integer> expected", upper);
        if (!(gr = getGraph(g)))
                Err("remove-vertices!: bad arg 3, <graph*> expected", g);

        char *name;

        int i, low = INTEGER(lower), high = INTEGER(upper);
        if (low >= high)
                Err("add-vertex!: arg_1 < arg_2 must hold", NIL);

        for (i=low; i<=high; i++) {
                ostrstream oss;
                oss << i << ends;
                name = oss.str();
                gr->deleteVertex(name);
                delete name;
        }
        return UNDEFINED;
}

static PRIMITIVE AddEdgeGraphCmd(SCM vset, SCM g)
{
	Graph *gr;
        int& vset_type = Wrapper<Collection<Vertex*> >::type;


	Collection<Vertex*>* vc = 
			CollectionWrapper<Vertex*>::getCollection(vset);
	if (!vc) {
               Err("add-edge!: bad arg 1, <collection<vertex*>> expected",vset);
	}
        if (!(gr = getGraph(g)))
                Err("add-edge!: bad arg 2, <graph*> expected", g);

	Edge *e;
	if (vc->sortedQ()) {
        	e = gr->addEdge(*vc);
	} else {
        	e = gr->addEdge(*(Sequence<Vertex*>*) vc);
	}
        if (!e)
		return Ntruth;
        Edge **w = new Edge *(e);

        return STk_make_CXXwrapper(Wrapper<Edge*>::type,
                Wrapper<Edge*>::name, (void *) w, LINK_DYNAMIC);
}

static PRIMITIVE DeleteEdgeGraphCmd(SCM vset, SCM g)
{
	Graph *gr;
        int& edge_type = Wrapper<Edge*>::type;

	Collection<Vertex*>* s = 
			CollectionWrapper<Vertex*>::getCollection(vset);

        if (!(gr = getGraph(g)))
                Err("remove-edge!: bad arg 2, <graph*> expected", g);
        if (s)
        	gr->deleteEdge(*s);
	else if (!CXX_TYPEP(vset, edge_type)) {
               		Err("remove-edge!: bad arg 1, <edge*> or "
			    "<collection<vertex*>> expected", vset);
	} 
	Edge *e = *(Edge**) CLASSDATA(vset);
        gr->deleteEdge(e);

        return UNDEFINED;
}

static PRIMITIVE VertexSetGraphCmd(SCM g)
{
        Graph *gr;
        if (!(gr = getGraph(g)))
                Err("vertex-set: bad arg 1, <graph*> expected", g);
        SortedArray<Vertex*> a = gr->vertices();
        Set<Vertex*>* s = new Set<Vertex*>(a);

        //Set<Vertex*>* s = new Set<Vertex*>(gr->vertices());  SEGFAULT (WHY?)
	if (!s)
		return Ntruth;

        return STk_make_CXXwrapper(Wrapper<Set<Vertex*> >::type,
                Wrapper<Set<Vertex*> >::name, (void *) s, LINK_DYNAMIC);
}

static PRIMITIVE EdgeSetGraphCmd(SCM g)
{
        Graph *gr;
        if (!(gr = getGraph(g)))
                Err("edge-set: bad arg 1, <graph*> expected", g);
        MSet<Edge*> a = gr->edges();
        MSet<Edge*>* s = new MSet<Edge*>(a);
	if (!s)
		return Ntruth;

        return STk_make_CXXwrapper(Wrapper<MSet<Edge*> >::type,
                Wrapper<MSet<Edge*> >::name, (void *) s, LINK_DYNAMIC);
}

static PRIMITIVE VertexVectorGraphCmd(SCM g)
{
        Graph *gr;
        if (!(gr = getGraph(g)))
                Err("vertex-vector: bad arg 1, <graph*> expected", g);
        SortedArray<Vertex*> a = gr->vertices();
        SortedArray<Vertex*>* s = new SortedArray<Vertex*>(a);

        //SortedArray<Vertex*>* s = new SortedArray<Vertex*>(gr->vertices());SF
	if (!s)
		return Ntruth;

        return STk_make_CXXwrapper(Wrapper<Array<Vertex*> >::type,
                Wrapper<Array<Vertex*> >::name, (void *) s, LINK_DYNAMIC);
}

static PRIMITIVE MBinGraphCmd(SCM g)
{
        Tcl_HashEntry *p;
        Graph *ap, *gr;

	if (g == UNBOUND)
        	ap = new MBinGraph;
	else if (!(gr = getGraph(g)))
                	Err("mbingraph: bad arg 1, <graph*> expected", g);
	else 
		ap = new MBinGraph(*gr, CLONE);
        return wrapGraph(ap);
}

static PRIMITIVE MUBinGraphCmd(SCM g)
{
        Tcl_HashEntry *p;
        Graph *ap, *gr;

	if (g == UNBOUND)
        	ap = new MUBinGraph;
	else if (!(gr = getGraph(g)))
                	Err("mbingraph: bad arg 1, <graph*> expected", g);
	else 
		ap = new MUBinGraph(*gr, CLONE);
        return wrapGraph(ap);
}

static PRIMITIVE MDBinGraphCmd(SCM g)
{
        Tcl_HashEntry *p;
        Graph *ap, *gr;

	if (g == UNBOUND)
        	ap = new MDBinGraph;
	else if (!(gr = getGraph(g)))
                	Err("mbingraph: bad arg 1, <graph*> expected", g);
	else 
		ap = new MDBinGraph(*gr, CLONE);
        return wrapGraph(ap);
}

static PRIMITIVE BinGraphCmd(SCM g)
{
        Tcl_HashEntry *p;
        Graph *ap, *gr;

	if (g == UNBOUND)
        	ap = new BinGraph;
	else if (!(gr = getGraph(g)))
                	Err("mbingraph: bad arg 1, <graph*> expected", g);
	else 
		ap = new BinGraph(*gr, CLONE);
        return wrapGraph(ap);
}

static PRIMITIVE UBinGraphCmd(SCM g)
{
        Tcl_HashEntry *p;
        Graph *ap, *gr;

	if (g == UNBOUND)
        	ap = new UBinGraph;
	else if (!(gr = getGraph(g)))
                	Err("mbingraph: bad arg 1, <graph*> expected", g);
	else 
		ap = new UBinGraph(*gr, CLONE);
        return wrapGraph(ap);
}

static PRIMITIVE DBinGraphCmd(SCM g)
{
        Tcl_HashEntry *p;
        Graph *ap, *gr;

	if (g == UNBOUND)
        	ap = new DBinGraph;
	else if (!(gr = getGraph(g)))
                	Err("mbingraph: bad arg 1, <graph*> expected", g);
	else 
		ap = new DBinGraph(*gr, CLONE);
        return wrapGraph(ap);
}

static PRIMITIVE MHyperGraphCmd(SCM g)
{
        Tcl_HashEntry *p;
        Graph *ap, *gr;

	if (g == UNBOUND)
        	ap = new MHyperGraph;
	else if (!(gr = getGraph(g)))
                	Err("mbingraph: bad arg 1, <graph*> expected", g);
	else 
		ap = new MHyperGraph(*gr, CLONE);
        return wrapGraph(ap);
}

static PRIMITIVE MUHyperGraphCmd(SCM g)
{
        Tcl_HashEntry *p;
        Graph *ap, *gr;

	if (g == UNBOUND)
        	ap = new MUHyperGraph;
	else if (!(gr = getGraph(g)))
                	Err("mbingraph: bad arg 1, <graph*> expected", g);
	else 
		ap = new MUHyperGraph(*gr, CLONE);
        return wrapGraph(ap);
}

static PRIMITIVE MDHyperGraphCmd(SCM g)
{
        Tcl_HashEntry *p;
        Graph *ap, *gr;

	if (g == UNBOUND)
        	ap = new MDHyperGraph;
	else if (!(gr = getGraph(g)))
                	Err("mbingraph: bad arg 1, <graph*> expected", g);
	else 
		ap = new MDHyperGraph(*gr, CLONE);
        return wrapGraph(ap);
}

static PRIMITIVE HyperGraphCmd(SCM g)
{
        Tcl_HashEntry *p;
        Graph *ap, *gr;

	if (g == UNBOUND)
        	ap = new HyperGraph;
	else if (!(gr = getGraph(g)))
                	Err("mbingraph: bad arg 1, <graph*> expected", g);
	else 
		ap = new HyperGraph(*gr, CLONE);
        return wrapGraph(ap);
}

static PRIMITIVE UHyperGraphCmd(SCM g)
{
        Tcl_HashEntry *p;
        Graph *ap, *gr;

	if (g == UNBOUND)
        	ap = new UHyperGraph;
	else if (!(gr = getGraph(g)))
                	Err("mbingraph: bad arg 1, <graph*> expected", g);
	else 
		ap = new UHyperGraph(*gr, CLONE);
        return wrapGraph(ap);
}

static PRIMITIVE DHyperGraphCmd(SCM g)
{
        Tcl_HashEntry *p;
        Graph *ap, *gr;

	if (g == UNBOUND)
        	ap = new DHyperGraph;
	else if (!(gr = getGraph(g)))
                	Err("mbingraph: bad arg 1, <graph*> expected", g);
	else 
		ap = new DHyperGraph(*gr, CLONE);
        return wrapGraph(ap);
}

static PRIMITIVE MakeGraphExistingCmd(SCM vset, SCM eset)
{
        Tcl_HashEntry *p;
        Graph *g, **gp;
        int *e;
	char vname[10];

	Collection<Vertex*>* vc = 
			CollectionWrapper<Vertex*>::getCollection(vset);
	Collection<Set<Vertex*> >* ec = 
			CollectionWrapper<Set<Vertex*> >::getCollection(eset);

        //int& vset_type = Wrapper<Set<Vertex*> >::type;
        //int& eset_type = Wrapper<Set<Set<Vertex*> > >::type;
        //if (!CXX_TYPEP(vset, vset_type))
        //       Err("graph: bad arg 1, <set<vertex*>> expected", vset);
        //if (!CXX_TYPEP(eset, eset_type))
        //       Err("graph: bad arg 2, <set<set<vertex*>> expected", eset);
	//Set<Vertex*>* vertices = (Set<Vertex*>*) CLASSDATA(vset);
	//Set<Set<Vertex*> >* edges = (Set<Set<Vertex*> >*) CLASSDATA(eset);
        //g = makeGraph(*vertices, *edges);

        g = makeGraph(*vc, *ec);
	if (!g)
		return Ntruth;
        return wrapGraph(g);
}

static PRIMITIVE MakeGraphVertsEdgesCmd(SCM vset, SCM eset)
{
        Tcl_HashEntry *p;
        Graph *g, **gp;
        int *e;
	char vname[10];
	MSet<Vertex*> vrts;
	Set<Vertex*> verts;
	MSet<Edge*> edges;

	if (CollectionWrapper<Vertex*>::isMSet(vset) ||
	    CollectionWrapper<Vertex*>::isSet(vset)) {
		vrts = *(MSet<Vertex*>*) CLASSDATA(vset);
		verts = vrts;
	} else {
               Err("graph: bad arg 1, <set<vertex*>> expected", vset);
	}
	if (CollectionWrapper<Edge*>::isMSet(eset) ||
	    CollectionWrapper<Edge*>::isSet(eset)) {
		edges = *(Set<Edge*>*) CLASSDATA(eset);
	} else {
               Err("graph: bad arg 2, <set<edge*>> expected", eset);
	}

        g = makeGraph(verts, edges);
	return wrapGraph(g);
}

static PRIMITIVE MakeGraphEdgesIntCmd(SCM eset);

static PRIMITIVE MakeGraphFromScratchCmd(SCM gparms, int len)
{
	SCM vlist, elist;
        Tcl_HashEntry *p;
        Graph *g, **gp;
        int *e;
	char vname[10];
	Set<char*> verts;
	MSet<Set<char*> > edges;

	if (len == 0)
		return UBinGraphCmd(UNBOUND);
	else if (len == 1)
		return MakeGraphEdgesIntCmd(CAR(gparms));
	else {
		vlist = CAR(gparms);
		elist = CAR(CDR(gparms));
	}
	if (NCONSP(vlist)) {
               Err("graph: bad arg 1, list expected", vlist);
	}
	if (NCONSP(elist)) {
               Err("graph: bad arg 2, list of lists expected", elist);
	}
	
	SCM l=vlist, l2;
	for (;;) {
		if (NULLP(l))
			break;
		char *vname = getName(CAR(l));
		verts.insert(vname);
		l = CDR(l);
	}
	l = elist;
	for (;;) {
		if (NULLP(l))
			break;
		if (NCONSP(CAR(l)))
			Err("graph: bad arg 2.ill-formed edge list",elist);
		l2 = CAR(l);
		Set<char*> edge_verts;
		for (;;) {
			if (NULLP(l2))
				break;
			char *vname = getName(CAR(l2));
			edge_verts.insert(vname);
			l2 = CDR(l2);
		}
                edges.insert(edge_verts);
		l = CDR(l);
	}
        g = makeGraph(verts, edges);

	Iterator<char*> get_vname(&verts);
	char* v;
	while (get_vname(v)) delete v;
	Iterator<Set<char*> > get_ename(&edges);
	Set<char*> edge;
	while (get_ename(edge)) {
		Iterator<char*> get_vname(&edge);
		while (get_vname(v)) delete v;
	}

	return wrapGraph(g);
}

static PRIMITIVE MakeDigraphCmd()
{
        Tcl_HashEntry *p;
        Graph *ap, **app;

        ap = new DBinGraph;         
	if (!ap)
		return Ntruth;
        Register<Graph>::createEntry(Wrapper<DBinGraph>::type, 
				     Wrapper<DBinGraph>::name, ap);
        app = new Graph *(ap);
	if (!app)
		return Ntruth;

        return STk_make_CXXwrapper(Wrapper<DBinGraph*>::type,
                        Wrapper<DBinGraph*>::name, (void *) app, LINK_DYNAMIC);
}

static PRIMITIVE MakeDigraphExistingCmd(SCM vset, SCM eset)
{
        Tcl_HashEntry *p;
        Graph *g, **gp;
        int *e;
	char vname[10];

        int& vset_type = Wrapper<Set<Vertex*> >::type;
        int& eset_type = Wrapper<Set<Sequence<Vertex*> > >::type;
        if (!CXX_TYPEP(vset, vset_type))
               Err("digraph: bad arg 1, <set<vertex*>> expected", vset);
        if (!CXX_TYPEP(eset, eset_type))
               Err("digraph: bad arg 2, <set<sequece<vertex*>> expected", eset);

	Set<Vertex*>* vertices = (Set<Vertex*>*) CLASSDATA(vset);
	Set<Sequence<Vertex*> >* edges=
				(Set<Sequence<Vertex*> >*)CLASSDATA(eset);
        g = makeGraph(*vertices, *edges);
        return wrapGraph(g);
}

static PRIMITIVE MakeDigraphFromScratchCmd(SCM gparms, int len)
{
	SCM vlist, elist;
        Tcl_HashEntry *p;
        Graph *g, **gp;
        int *e;
	char vname[10];
	Set<char*> verts;
	MSet<Sequence<char*> > edges;

	if (len == 0)
		return MakeDigraphCmd();
	else if (len == 1)
		Err("MakeDigraphFromScratchCmd: one arg method not defined",
						gparms);
	else {
		vlist = CAR(gparms);
		elist = CAR(CDR(gparms));
	}
	if (NCONSP(vlist)) {
               Err("digraph: bad arg 1, list expected", vlist);
	}
	if (NCONSP(elist)) {
               Err("digraph: bad arg 2, list of lists expected", elist);
	}
	
	SCM l=vlist, l2;
	for (;;) {
		if (NULLP(l))
			break;
		char *vname = getName(CAR(l));
		verts.insert(vname);
		l = CDR(l);
	}
	l = elist;
	for (;;) {
		if (NULLP(l))
			break;
		if (NCONSP(CAR(l)))
			Err("graph: bad arg 2.ill-formed edge list",elist);
		l2 = CAR(l);
		Sequence<char*> edge_verts;
		for (;;) {
			if (NULLP(l2))
				break;
			char *vname = getName(CAR(l2));
			edge_verts.append(vname);
			l2 = CDR(l2);
		}
		edges.insert(edge_verts);
		l = CDR(l);
	}
        g = makeGraph(verts, edges);

	Iterator<char*> get_vname(&verts);
	char* v;
	while (get_vname(v)) delete v;
	Iterator<Sequence<char*> > get_ename(&edges);
	Sequence<char*> edge;
	while (get_ename(edge)) {
		Iterator<char*> get_vname(&edge);
		while (get_vname(v)) delete v;
	}

	return wrapGraph(g);
}

static PRIMITIVE LoadGraphCmd(SCM fname)
{
	char *fn = getName(fname);
	Graph *g = LoadGraph(fn);
	return wrapGraph(g);
}

static PRIMITIVE LoadDimacsGraphCmd(SCM fname)
{
	char *fn = getName(fname);
	Graph *g = LoadDimacsGraph(fn);
	return wrapGraph(g);
}

static PRIMITIVE SaveGraphCmd(SCM graph, SCM fname)
{
	char *fn = getName(fname);
	Graph *g = getGraph(graph);
	//cout << "ok.." << endl;
	int i = SaveGraph(g, fn);
	//cout << "done.." << i <<  endl;
	if (i)
		return Ntruth;
	else
		return Truth;
}

static PRIMITIVE SaveDimacsGraphCmd(SCM graph, SCM fname)
{
	char *fn = getName(fname);
	Graph *g = getGraph(graph);
	int i = SaveDimacsGraph(g, fn);
	if (i)	
		return Ntruth;
	else
		return Truth;
}


static PRIMITIVE AddEdgesFromScratchCmd(SCM elist, SCM graph)
{
        Tcl_HashEntry *p;
        int *e;
	char *vname;
	SCM l, l2;

	Graph* g;
        if (!(g = getGraph(graph)))
               Err("add-edges!: bad arg 2, <graph*> expected", graph);

	if (NCONSP(elist)) {
               Err("add-edges!: bad arg 1, list of lists expected", elist);
	}
	
	l = elist;
	for (;;) {
		if (NULLP(l))
			break;
		if (NCONSP(CAR(l)))
			Err("add-edges: bad arg 1,ill-formed edge list",elist);
		l2 = CAR(l);
		Sequence<Vertex*> edge_verts;
		for (;;) {
			if (NULLP(l2))
				break;
			vname = getName(CAR(l2));
			Vertex *v = g->findVertexByName(vname);
			if (v)
				edge_verts.insert(v);
			l2 = CDR(l2);
		}
		g->addEdge(edge_verts);
		l = CDR(l);
	}
	return UNDEFINED;
}

static PRIMITIVE DeleteEdgesFromScratchCmd(SCM elist, SCM graph)
{
        Tcl_HashEntry *p;
        int *e;
	char *vname;
	SCM l, l2;
	Graph* g;

	if (NCONSP(elist)) {
               Err("remove-edges!: bad arg 1, list of lists expected", elist);
	}

        if (!(g = getGraph(graph)))
               Err("remove-edges!: bad arg 2, <graph*> expected", graph);
	
	l = elist;
	for (;;) {
		if (NULLP(l))
			break;
		if (NCONSP(CAR(l)))
			Err("remove-edges!:bad arg 1,ill-formed list",elist);
		l2 = CAR(l);
		Sequence<Vertex*> edge_verts;
		for (;;) {
			if (NULLP(l2))
				break;
			vname = getName(CAR(l2));
			Vertex *v = g->findVertexByName(vname);
			if (v)
				edge_verts.append(v);
			l2 = CDR(l2);
		}
		g->deleteEdge(edge_verts);
		l = CDR(l);
	}
	return UNDEFINED;
}

static PRIMITIVE addGraphEdgesCmd(SCM eset, SCM graph)
{
        Tcl_HashEntry *p;
        int *e;
	char vname[10];
	MSet<Edge*> es;

	Graph* g;
        if (!(g = getGraph(graph)))
               Err("add-edges!: bad arg 2, graph expected", graph);

        if (CollectionWrapper<Sequence<Vertex*> >::isMSet(eset)) {
		MSet<Sequence<Vertex*> >* mms = (MSet<Sequence<Vertex*> >*) 
							CLASSDATA(eset);
		es = g->addEdges(*mms);
	} else if (CollectionWrapper<Sequence<Vertex*> >::isSet(eset)) {
		Set<Sequence<Vertex*> >* mms = (Set<Sequence<Vertex*> >*) 
							CLASSDATA(eset);
		es = g->addEdges(*mms);
	} else if (CollectionWrapper<Set<Vertex*> >::isMSet(eset)) {
		MSet<Set<Vertex*> >* mms = (MSet<Set<Vertex*> >*) 
							CLASSDATA(eset);
		es = g->addEdges(*mms);
	} else if (CollectionWrapper<Set<Vertex*> >::isSet(eset)) {
		Set<Set<Vertex*> >* mms = (Set<Set<Vertex*> >*) 
							CLASSDATA(eset);
		es = g->addEdges(*mms);
	} else
               Err("add-edges!: bad arg 1, set or mset of "
			" set or sequence of <vertex*>> expected", eset);

	MSet<Edge*>* ep = new MSet<Edge*>(es);
	if (!ep)
		return Ntruth;

        return STk_make_CXXwrapper(Wrapper<MSet<Edge*> >::type,
                        Wrapper<MSet<Edge*> >::name, (void *) ep, LINK_DYNAMIC);
}

static PRIMITIVE deleteGraphEdgesCmd(SCM eset, SCM graph)
{
        Tcl_HashEntry *p;
        int *e;
	char vname[10];

	Graph* g;
        if (!(g = getGraph(graph)))
               Err("remove-edges!: bad arg 2, graph expected", graph);

        if (CollectionWrapper<Sequence<Vertex*> >::isMSet(eset)) {
		MSet<Sequence<Vertex*> >* mms = (MSet<Sequence<Vertex*> >*) 
							CLASSDATA(eset);
		if (!mms) return Ntruth;
		g->deleteEdges(*mms);
	} else if (CollectionWrapper<Sequence<Vertex*> >::isSet(eset)) {
		Set<Sequence<Vertex*> >* mms = (Set<Sequence<Vertex*> >*) 
							CLASSDATA(eset);
		if (!mms) return Ntruth;
		g->deleteEdges(*mms);
	} else if (CollectionWrapper<Set<Vertex*> >::isMSet(eset)) {
		MSet<Set<Vertex*> >* mms = (MSet<Set<Vertex*> >*) 
							CLASSDATA(eset);
		if (!mms) return Ntruth;
		g->deleteEdges(*mms);
	} else if (CollectionWrapper<Set<Vertex*> >::isSet(eset)) {
		Set<Set<Vertex*> >* mms = (Set<Set<Vertex*> >*) 
							CLASSDATA(eset);
		if (!mms) return Ntruth;
		g->deleteEdges(*mms);
	} else
               Err("remove-edges!: bad arg 1, set or mset of "
			" set or sequence of <vertex*>> expected", eset);
        return UNDEFINED;
}

static PRIMITIVE MakeGraphEdgesIntCmd(SCM eset)
{
        Tcl_HashEntry *p;
        Graph *g, **gp;
        int *e;
	char vname[10];

        int& eset_type = Wrapper<MSet<Set<int*> > >::type;
        if (!CXX_TYPEP(eset, eset_type))
               Err("graph: bad arg 1, <mset<set<int*>> expected", eset);

	MSet<Set<int*> >* mms = (MSet<Set<int*> >*) CLASSDATA(eset);
        g = new MHyperGraph;
	if (!g) return Ntruth;
	Iterator<Set<int*> > get_set(mms);
	Set<int*> ms;
	while (get_set(ms)) {
		Iterator<int*> get_element(&ms);
		while (get_element(e)) {
			sprintf(vname, "%d", *e);
			g->addVertex((char*) vname);
		}
	}
	get_set.reset();
	/*while (get_set(ms)) {
		Set<int*> s = ms;
		g->addEdge(s);
	}*/
        Register<Graph>::createEntry(Wrapper<Graph>::type, 
				     Wrapper<Graph>::name, g);
        gp = new Graph *(g);
	if (!gp) return Ntruth;

        return STk_make_CXXwrapper(Wrapper<Graph*>::type,
                        Wrapper<Graph*>::name, (void *) gp, LINK_DYNAMIC);
}

static PRIMITIVE IsomorphicQCmd(SCM graph1, SCM graph2)
{
	Graph *g, *g2;

        if (!(g = getGraph(graph1)))
               Err("adjacent?: bad arg 1, <graph*> expected", graph1);
        if (!(g2 = getGraph(graph2)))
               Err("adjacent?: bad arg 2, <graph*> expected", graph2);

	if (g->isomorphicQ(g2))
		return Truth;
	else
		return Ntruth;
}

static PRIMITIVE AdjacentQCmd(SCM v1, SCM v2, SCM graph)
{
	Graph *g;
        int& v_type = Wrapper<Vertex*>::type;

        if (!CXX_TYPEP(v1, v_type))
               Err("adjacent?: bad arg 1, <vertex*> expected", v1);
        if (!CXX_TYPEP(v2, v_type))
               Err("adjacent?: bad arg 2, <vertex*> expected", v2);
        if (!(g = getGraph(graph)))
               Err("adjacent?: bad arg 3, <graph*> expected", graph);

	Vertex *vert1 = *(Vertex**) CLASSDATA(v1);
	Vertex *vert2 = *(Vertex**) CLASSDATA(v2);

	SCM result;

	if (g->adjacentQ(vert1, vert2))
		result = Truth;
	else
		result = Ntruth;

	return result;
}


static PRIMITIVE IsEdgeCmd2(SCM vset, SCM graph)
{
        int& vset_type = Wrapper<Set<Vertex*> >::type;
	Graph *g;
        if (!CXX_TYPEP(vset, vset_type))
               Err("edge?: bad arg 1, <set<vertex*>> expected", vset);
        if (!(g = getGraph(graph)))
               Err("adjacent?: bad arg 2, <graph*> expected", graph);

        Set<Vertex*>* s = (Set<Vertex*>*) CLASSDATA(vset);

	Edge* e = g->isEdge(*s);
	if (e) {
		Edge** ep = new Edge*(e);
        	return STk_make_CXXwrapper(Wrapper<Edge*>::type,
                        Wrapper<Edge*>::name, (void *) ep, LINK_DYNAMIC);
	} else
		return Ntruth;
}

static PRIMITIVE IsEdgeCmd(SCM v1, SCM v2, SCM graph)
{
	Graph *g;
        int& v_type = Wrapper<Vertex*>::type;
        if (!CXX_TYPEP(v1, v_type))
               Err("edge?: bad arg 1, <vertex*> expected", v1);
        if (!CXX_TYPEP(v2, v_type))
               Err("edge?: bad arg 2, <vertex*> expected", v2);
        if (!(g = getGraph(graph)))
               Err("adjacent?: bad arg 3, <graph*> expected", graph);

        Vertex* vert1 = *(Vertex**) CLASSDATA(v1);
        Vertex* vert2 = *(Vertex**) CLASSDATA(v2);

	Edge* e = g->isEdge(vert1, vert2);
	if (e) {
		Edge** ep = new Edge*(e);
        	return STk_make_CXXwrapper(Wrapper<Edge*>::type,
                        Wrapper<Edge*>::name, (void *) ep, LINK_DYNAMIC);
	} else
		return Ntruth;
}

static PRIMITIVE IncidentEdgesCmd(SCM v)
{
        int& v_type = Wrapper<Vertex*>::type;

        if (!CXX_TYPEP(v, v_type))
               Err("incident-edges: bad arg 1, <vertex*> expected", v);

	Vertex *vert1 = *(Vertex**) CLASSDATA(v);
	Graph *g = vert1->owner();

	MSet<Edge*> inc_edges = g->incidentEdges(vert1);
	MSet<Edge*>* ep = new MSet<Edge*>(inc_edges);

        return STk_make_CXXwrapper(Wrapper<MSet<Edge*> >::type,
                        Wrapper<MSet<Edge*> >::name, (void *) ep, LINK_DYNAMIC);
}

static PRIMITIVE InIncidentEdgesCmd(SCM v)
{
        int& v_type = Wrapper<Vertex*>::type;

        if (!CXX_TYPEP(v, v_type))
               Err("in-incident-edges: bad arg 1, <vertex*> expected", v);

	Vertex *vert1 = *(Vertex**) CLASSDATA(v);
	Graph *g = vert1->owner();

	MSet<Edge*> inc_edges = g->inIncidentEdges(vert1);
	MSet<Edge*>* ep = new MSet<Edge*>(inc_edges);

        return STk_make_CXXwrapper(Wrapper<MSet<Edge*> >::type,
                        Wrapper<MSet<Edge*> >::name, (void *) ep, LINK_DYNAMIC);
}

static PRIMITIVE OutIncidentEdgesCmd(SCM v)
{
        int& v_type = Wrapper<Vertex*>::type;

        if (!CXX_TYPEP(v, v_type))
               Err("out-incident-edges: bad arg 1, <vertex*> expected", v);

	Vertex *vert1 = *(Vertex**) CLASSDATA(v);
	Graph *g = vert1->owner();

	MSet<Edge*> inc_edges = g->outIncidentEdges(vert1);
	MSet<Edge*>* ep = new MSet<Edge*>(inc_edges);

        return STk_make_CXXwrapper(Wrapper<MSet<Edge*> >::type,
                        Wrapper<MSet<Edge*> >::name, (void *) ep, LINK_DYNAMIC);
}

static PRIMITIVE DegreeCmd(SCM v)
{
        int& v_type = Wrapper<Vertex*>::type;

        if (!CXX_TYPEP(v, v_type))
               Err("degree: bad arg 1, <vertex*> expected", v);

	Vertex *vert1 = *(Vertex**) CLASSDATA(v);
	Graph *g = vert1->owner();

	SCM result;

	int degree = g->degree(vert1);

	result = STk_makeinteger(degree);
	return result;
}

static PRIMITIVE InDegreeCmd(SCM v, SCM graph)
{
        int& v_type = Wrapper<Vertex*>::type;

        if (!CXX_TYPEP(v, v_type))
               Err("in-degree: bad arg 1, <vertex*> expected", v);

	Vertex *vert1 = *(Vertex**) CLASSDATA(v);
	Graph *g = vert1->owner();

	SCM result;

	int degree = g->inDegree(vert1);

	result = STk_makeinteger(degree);
	return result;
}

static PRIMITIVE OutDegreeCmd(SCM v, SCM graph)
{
        int& v_type = Wrapper<Vertex*>::type;

        if (!CXX_TYPEP(v, v_type))
               Err("out-degree: bad arg 1, <vertex*> expected", v);

	Vertex *vert1 = *(Vertex**) CLASSDATA(v);
	Graph *g = vert1->owner();

	SCM result;

	int degree = g->outDegree(vert1);

	result = STk_makeinteger(degree);
	return result;
}

static PRIMITIVE OrderCmd(SCM graph)
{
	Graph *g;

        if (!(g = getGraph(graph)))
               Err("order: bad arg 1, graph expected", graph);

	SCM result;

	int order = g->order();

	result = STk_makeinteger(order);
	return result;
}

static PRIMITIVE SizeCmd(SCM graph)
{
	Graph *g;

        if (!(g = getGraph(graph)))
               Err("size: bad arg 1, graph expected", graph);

	SCM result;

	int size = g->size();

	result = STk_makeinteger(size);
	return result;
}

static PRIMITIVE VertexRefCmd(SCM graph, SCM rank)
{
	Graph *g;

	if (!INTEGERP(rank))
               Err("vertex-ref: bad arg 2, <integer> expected", rank);
        if (!(g = getGraph(graph)))
               Err("vertex-ref: bad arg 1, graph expected", graph);

	SCM result;

	int i = INTEGER(rank);
	Vertex *v = g->vertex(i);
	if (!v)
		return Ntruth;
        Vertex **w = new Vertex *(v);

        return STk_make_CXXwrapper(Wrapper<Vertex*>::type,
                        Wrapper<Vertex*>::name, (void *) w, LINK_DYNAMIC);
}

static PRIMITIVE FindVertexByNameCmd(SCM nm, SCM graph)
{
	Graph *g;

	char *name;
        if (!(name = getName(nm)))
                Err("find-vertex: bad arg 1, symbol or string expected", nm);
        if (!(g = getGraph(graph)))
               Err("find-vertex: bad arg 2, graph expected", graph);

	SCM result;

	Vertex *v = g->findVertexByName(name);
        Vertex **w = new Vertex *(v);

        return STk_make_CXXwrapper(Wrapper<Vertex*>::type,
                        Wrapper<Vertex*>::name, (void *) w, LINK_DYNAMIC);
}

static PRIMITIVE FindEdgeByNameCmd(SCM nm, SCM graph)
{
	Graph *g;

	char *name;
        if (!(name = getName(nm)))
                Err("find-edge: bad arg 1, symbol or string expected", nm);
        if (!(g = getGraph(graph)))
               Err("fin-edge: bad arg 2, graph expected", graph);

	SCM result;

	Edge *e = g->findEdgeByName(name);
        Edge **ep = new Edge *(e);

        return STk_make_CXXwrapper(Wrapper<Edge*>::type,
                        Wrapper<Edge*>::name, (void *) ep, LINK_DYNAMIC);
}

static PRIMITIVE EdgeRefCmd(SCM graph, SCM rank)
{
	Graph *g;

	if (!INTEGERP(rank))
               Err("edge-ref: bad arg 2, <integer> expected", rank);
        if (!(g = getGraph(graph)))
               Err("edge-ref: bad arg 1, graph expected", graph);

	SCM result;

	int i = INTEGER(rank);
	Edge *v = g->edge(i);
	if (!v)
		return Ntruth;
        Edge **w = new Edge *(v);

        return STk_make_CXXwrapper(Wrapper<Edge*>::type,
                        Wrapper<Edge*>::name, (void *) w, LINK_DYNAMIC);
}

static PRIMITIVE VertexRankCmd(SCM vertex, SCM graph)
{
	Graph *g;

        int& v_type = Wrapper<Vertex*>::type;

        if (!CXX_TYPEP(vertex, v_type))
               Err("rank: bad arg 1, <vertex*> expected", vertex);
        if (!(g = getGraph(graph)))
               Err("rank: bad arg 2, graph expected", graph);

	SCM result;

	Vertex *v = *(Vertex**) CLASSDATA(vertex);
	int rank = g->rank(v);

	result = STk_makeinteger(rank);
	return result;
}

static PRIMITIVE EdgeRankCmd(SCM edge, SCM graph)
{
	Graph *g;

        int& e_type = Wrapper<Edge*>::type;

        if (!CXX_TYPEP(edge, e_type))
               Err("rank: bad arg 1, <edge*> expected", edge);
        if (!(g = getGraph(graph)))
               Err("rank: bad arg 2, graph expected", graph);

	SCM result;

	Edge *e = *(Edge**) CLASSDATA(edge);
	int rank = g->rank(e);

	result = STk_makeinteger(rank);
	return result;
}

static PRIMITIVE LineGraphCmd(SCM graph)
{
	Graph *g;
        if (!(g = getGraph(graph)))
               Err("line graph: bad arg 1, graph expected", graph);
	MBinGraph *mhg = (MBinGraph*) g;
        Graph *res = new MBinGraph(mhg->lineGraph());
	return wrapGraph(res);
}

static PRIMITIVE GraphComplementCmd(SCM graph)
{
	Graph *g;
        if (!(g = getGraph(graph)))
               Err("graph complement: bad arg 1, graph expected", graph);
	MBinGraph *mhg = (MBinGraph*) g;
        Graph *res = new MBinGraph(mhg->complement());
	return wrapGraph(res);
}

static PRIMITIVE GraphSumCmd(SCM graph1, SCM graph2)
{
	Graph *g1, *g2;
        if (!(g1 = getGraph(graph1)))
               Err("graph sum: bad arg 1, graph expected", graph1);
        if (!(g2 = getGraph(graph2)))
	       return graph1;
        Graph * res = new MBinGraph( (*(MBinGraph*)g1) + 
				         (*(MBinGraph*)g2));
	return wrapGraph(res);
}

static PRIMITIVE GraphProductCmd(SCM graph1, SCM graph2)
{
	Graph *g1, *g2;
        if (!(g1 = getGraph(graph1)))
               Err("graph product: bad arg 1, graph expected", graph1);
        if (!(g2 = getGraph(graph2)))
	       return graph1;
        Graph * res = new MBinGraph( (*(MBinGraph*)g1) * 
				         (*(MBinGraph*)g2));
	return wrapGraph(res);
}

// define your new methods above 
// and register them using STk_add_new_cpp_primitive() below

void genExtra_Graph_Methods() 
{
        STk_add_new_cpp_primitive("mbingraph", tc_subr_0_or_1,
                                    (PRIMITIVE (*)(...))MBinGraphCmd);
        STk_add_new_cpp_primitive("mubingraph", tc_subr_0_or_1,
                                    (PRIMITIVE (*)(...))MUBinGraphCmd);
        STk_add_new_cpp_primitive("mdbingraph", tc_subr_0_or_1,
                                    (PRIMITIVE (*)(...))MDBinGraphCmd);
        STk_add_new_cpp_primitive("bingraph", tc_subr_0_or_1,
                                    (PRIMITIVE (*)(...))BinGraphCmd);
        STk_add_new_cpp_primitive("ubingraph", tc_subr_0_or_1,
                                    (PRIMITIVE (*)(...))UBinGraphCmd);
        STk_add_new_cpp_primitive("dbingraph", tc_subr_0_or_1,
                                    (PRIMITIVE (*)(...))DBinGraphCmd);
        STk_add_new_cpp_primitive("mhypergraph", tc_subr_0_or_1,
                                    (PRIMITIVE (*)(...))MHyperGraphCmd);
        STk_add_new_cpp_primitive("muhypergraph", tc_subr_0_or_1,
                                    (PRIMITIVE (*)(...))MUHyperGraphCmd);
        STk_add_new_cpp_primitive("mdhypergraph", tc_subr_0_or_1,
                                    (PRIMITIVE (*)(...))MDHyperGraphCmd);
        STk_add_new_cpp_primitive("hypergraph", tc_subr_0_or_1,
                                    (PRIMITIVE (*)(...))HyperGraphCmd);
        STk_add_new_cpp_primitive("uhypergraph", tc_subr_0_or_1,
                                    (PRIMITIVE (*)(...))UHyperGraphCmd);
        STk_add_new_cpp_primitive("dhypergraph", tc_subr_0_or_1,
                                    (PRIMITIVE (*)(...))DHyperGraphCmd);

        STk_add_new_cpp_primitive("add-subgraph", tc_subr_2,
                                    (PRIMITIVE (*)(...))AddSubgraphCmd);
        STk_add_new_cpp_primitive("dissolve-subgraph", tc_subr_2,
                                    (PRIMITIVE (*)(...))DissolveSubgraphCmd);
        STk_add_new_cpp_primitive("induced-subgraph", tc_subr_3,
                                    (PRIMITIVE (*)(...))InducedSubgraphCmd);
        STk_add_new_cpp_primitive("copy-graph", tc_subr_2,
                                    (PRIMITIVE (*)(...))CopyGraphCmd);
        STk_add_new_cpp_primitive("multi-graph", tc_subr_2,
                                    (PRIMITIVE (*)(...))MultiGraphCmd);
        STk_add_new_cpp_primitive("simple-graph", tc_subr_2,
                                    (PRIMITIVE (*)(...))SimpleGraphCmd);
        STk_add_new_cpp_primitive("make-graph-existing", tc_subr_2,
                                    (PRIMITIVE (*)(...))MakeGraphExistingCmd);
        STk_add_new_cpp_primitive("make-graph-verts-edges", tc_subr_2,
                                    (PRIMITIVE (*)(...))MakeGraphVertsEdgesCmd);
        STk_add_new_cpp_primitive("make-graph-from-scratch", tc_lsubr,
                                    (PRIMITIVE(*)(...))MakeGraphFromScratchCmd);
        STk_add_new_cpp_primitive("make-digraph", tc_subr_0,
                                  (PRIMITIVE (*)(...))MakeDigraphCmd);
        STk_add_new_cpp_primitive("make-digraph-existing", tc_subr_2,
                                  (PRIMITIVE (*)(...))MakeDigraphExistingCmd);
        STk_add_new_cpp_primitive("make-digraph-from-scratch", tc_lsubr,
                                  (PRIMITIVE(*)(...))MakeDigraphFromScratchCmd);
        STk_add_new_cpp_primitive("load-graph", tc_subr_1,
                                  (PRIMITIVE(*)(...))LoadGraphCmd);
        STk_add_new_cpp_primitive("load-dimacs-graph", tc_subr_1,
                                  (PRIMITIVE(*)(...))LoadDimacsGraphCmd);
        STk_add_new_cpp_primitive("save-graph", tc_subr_2,
                                  (PRIMITIVE(*)(...))SaveGraphCmd);
        STk_add_new_cpp_primitive("save-dimacs-graph", tc_subr_2,
                                  (PRIMITIVE(*)(...))SaveDimacsGraphCmd);
        STk_add_new_cpp_primitive("add-graph-edges!", tc_subr_2,
                                    (PRIMITIVE (*)(...))addGraphEdgesCmd);
        STk_add_new_cpp_primitive("add-graph-edge-list!", tc_subr_2,
                                    (PRIMITIVE (*)(...))AddEdgesFromScratchCmd);
        STk_add_new_cpp_primitive("remove-graph-edges!", tc_subr_2,
                                    (PRIMITIVE (*)(...))deleteGraphEdgesCmd);
        STk_add_new_cpp_primitive("remove-graph-edge-list!", tc_subr_2,
                                 (PRIMITIVE (*)(...))DeleteEdgesFromScratchCmd);
        STk_add_new_cpp_primitive("find-vertex-by-name", tc_subr_2,
                                    (PRIMITIVE (*)(...))FindVertexByNameCmd);
        STk_add_new_cpp_primitive("find-edge-by-name", tc_subr_2,
                                    (PRIMITIVE (*)(...))FindEdgeByNameCmd);
        STk_add_new_cpp_primitive("vertex-label", tc_subr_1,
                                    (PRIMITIVE (*)(...))NameGraphObjectCmd);
        STk_add_new_cpp_primitive("edge-label", tc_subr_1,
                                    (PRIMITIVE (*)(...))NameGraphObjectCmd);
        STk_add_new_cpp_primitive("graph-label", tc_subr_1,
                                    (PRIMITIVE (*)(...))NameGraphObjectCmd);
        STk_add_new_cpp_primitive("make-graph-edges", tc_subr_1,
                                    (PRIMITIVE (*)(...))MakeGraphEdgesIntCmd);
        STk_add_new_cpp_primitive("edge-set", tc_subr_1,
                                    (PRIMITIVE (*)(...))EdgeSetGraphCmd);
        STk_add_new_cpp_primitive("vertex-set", tc_subr_1,
                                    (PRIMITIVE (*)(...))VertexSetGraphCmd);
        STk_add_new_cpp_primitive("vertex-vector", tc_subr_1,
                                    (PRIMITIVE (*)(...))VertexVectorGraphCmd);
        STk_add_new_cpp_primitive("add-vertex!", tc_subr_2,
                                    (PRIMITIVE (*)(...))AddVertexGraphCmd);
        STk_add_new_cpp_primitive("remove-vertex!", tc_subr_2,
                                    (PRIMITIVE (*)(...))DeleteVertexGraphCmd);
        STk_add_new_cpp_primitive("remove-vertex2!", tc_subr_2,
                                    (PRIMITIVE (*)(...))DeleteVertex2GraphCmd);
        STk_add_new_cpp_primitive("add-vertices!", tc_subr_3,
                                    (PRIMITIVE (*)(...))AddVerticesGraphCmd);
        STk_add_new_cpp_primitive("remove-vertices!", tc_subr_3,
                                    (PRIMITIVE (*)(...))DeleteVerticesGraphCmd);
        STk_add_new_cpp_primitive("add-edge!", tc_subr_2,
                                    (PRIMITIVE (*)(...))AddEdgeGraphCmd);
        STk_add_new_cpp_primitive("remove-edge!", tc_subr_2,
                                    (PRIMITIVE (*)(...))DeleteEdgeGraphCmd);
        STk_add_new_cpp_primitive("adjacent?", tc_subr_3,
                                    (PRIMITIVE (*)(...))AdjacentQCmd);
        STk_add_new_cpp_primitive("isomorphic?", tc_subr_2,
                                    (PRIMITIVE (*)(...))IsomorphicQCmd);
        STk_add_new_cpp_primitive("is-edge", tc_subr_3,
                                    (PRIMITIVE (*)(...))IsEdgeCmd);
        STk_add_new_cpp_primitive("is-edge2", tc_subr_2,
                                    (PRIMITIVE (*)(...))IsEdgeCmd2);
        STk_add_new_cpp_primitive("incident-edges", tc_subr_1,
                                    (PRIMITIVE (*)(...))IncidentEdgesCmd);
        STk_add_new_cpp_primitive("in-incident-edges", tc_subr_1,
                                    (PRIMITIVE (*)(...))InIncidentEdgesCmd);
        STk_add_new_cpp_primitive("out-incident-edges", tc_subr_1,
                                    (PRIMITIVE (*)(...))OutIncidentEdgesCmd);
        STk_add_new_cpp_primitive("vertex-degree", tc_subr_1,
                                    (PRIMITIVE (*)(...))DegreeCmd);
        STk_add_new_cpp_primitive("vertex-in-degree", tc_subr_1,
                                    (PRIMITIVE (*)(...))InDegreeCmd);
        STk_add_new_cpp_primitive("vertex-out-degree", tc_subr_1,
                                    (PRIMITIVE (*)(...))OutDegreeCmd);
        STk_add_new_cpp_primitive("order", tc_subr_1,
                                    (PRIMITIVE (*)(...))OrderCmd);
        STk_add_new_cpp_primitive("graph-size", tc_subr_1,
                                    (PRIMITIVE (*)(...))SizeCmd);
        STk_add_new_cpp_primitive("vertex-ref", tc_subr_2,
                                    (PRIMITIVE (*)(...))VertexRefCmd);
        STk_add_new_cpp_primitive("vertex-rank", tc_subr_2,
                                    (PRIMITIVE (*)(...))VertexRankCmd);
        STk_add_new_cpp_primitive("edge-ref", tc_subr_2,
                                    (PRIMITIVE (*)(...))EdgeRefCmd);
        STk_add_new_cpp_primitive("edge-rank", tc_subr_2,
                                    (PRIMITIVE (*)(...))EdgeRankCmd);
        STk_add_new_cpp_primitive("complement", tc_subr_1,
                                    (PRIMITIVE (*)(...))GraphComplementCmd);
        STk_add_new_cpp_primitive("line-graph", tc_subr_1,
                                    (PRIMITIVE (*)(...))LineGraphCmd);
        STk_add_new_cpp_primitive("sum", tc_subr_1_or_2,
                                    (PRIMITIVE (*)(...))GraphSumCmd);
        STk_add_new_cpp_primitive("product", tc_subr_1_or_2,
                                    (PRIMITIVE (*)(...))GraphProductCmd);


        addZeroArgMethod("graph", "make-graph", LINK_NEW);

        addOneArgMethod("graph", Wrapper<MSet<Set<int*> > >::name,
                                "make-graph-edges", LINK_OVL);
        addTwoArgMethod("graph", 
				Wrapper<MSet<Vertex*> >::name,
				Wrapper<MSet<Set<Vertex*> > >::name,
                                "make-graph-existing", LINK_OVL);
        addTwoArgMethod("graph", 
				Wrapper<MSet<Vertex*> >::name,
				Wrapper<MSet<Edge*> >::name,
                                "make-graph-verts-edges", LINK_OVL);
        addTwoArgMethod("graph", 
				"<pair>",
				"<pair>",
                                "make-graph-from-scratch", LINK_OVL);

        addZeroArgMethod("digraph", "make-digraph", LINK_NEW);

        addTwoArgMethod("digraph", 
				Wrapper<MSet<Vertex*> >::name,
				Wrapper<MSet<Sequence<Vertex*> > >::name,
                                "make-digraph-existing", LINK_OVL);
        addTwoArgMethod("digraph", 
				"<pair>",
				"<pair>",
                                "make-digraph-from-scratch", LINK_OVL);

        addOneArgMethod("size", Wrapper<Graph*>::name,
                                "graph-size", LINK_NEW);

        addOneArgMethod("degree", Wrapper<Vertex*>::name,
                                "vertex-degree", LINK_NEW);

        addOneArgMethod("in-degree", Wrapper<Vertex*>::name,
                                "vertex-in-degree", LINK_NEW);

        addOneArgMethod("out-degree", Wrapper<Vertex*>::name,
                                "vertex-out-degree", LINK_NEW);

        addTwoArgMethod("find-vertex", 
				"<string>",
				Wrapper<Graph*>::name,
				"find-vertex-by-name", LINK_NEW);

        addTwoArgMethod("find-vertex", 
				"<symbol>",
				Wrapper<Graph*>::name,
				"find-vertex-by-name", LINK_NEW);

        addTwoArgMethod("find-edge", 
				"<string>",
				Wrapper<Graph*>::name,
				"find-edge-by-name", LINK_NEW);

        addTwoArgMethod("find-edge", 
				"<symbol>",
				Wrapper<Graph*>::name,
				"find-edge-by-name", LINK_NEW);
        addTwoArgMethod("add-edges!", 
				"<pair>",
				Wrapper<Graph*>::name,
                                "add-graph-edge-list!", LINK_NEW);
        addTwoArgMethod("add-edges!", 
				Wrapper<MSet<Set<Vertex*> > >::name,
				Wrapper<Graph*>::name,
                                "add-graph-edges!", LINK_OVL);
        addTwoArgMethod("add-edges!", 
				Wrapper<MSet<Sequence<Vertex*> > >::name,
				Wrapper<Graph*>::name,
                                "add-graph-edges!", LINK_OVL);
        addTwoArgMethod("remove-edges!", 
				"<pair>",
				Wrapper<Graph*>::name,
                                "remove-graph-edge-list!", LINK_NEW);
        addTwoArgMethod("remove-edges!", 
				Wrapper<MSet<Set<Vertex*> > >::name,
				Wrapper<Graph*>::name,
                                "remove-graph-edges!", LINK_OVL);
        addTwoArgMethod("remove-edges!", 
				Wrapper<MSet<Sequence<Vertex*> > >::name,
				Wrapper<Graph*>::name,
                                "remove-graph-edges!", LINK_OVL);
        addTwoArgMethod("remove-vertex!", 
				Wrapper<Vertex*>::name,
				Wrapper<Graph*>::name,
                                "remove-vertex2!", LINK_OVL);
        addOneArgMethod("vertices", Wrapper<Graph*>::name,
                                "vertex-set", LINK_NEW);
        addOneArgMethod("edges", Wrapper<Graph*>::name,
                                "edge-set", LINK_NEW);
        addArbMethod("+", Wrapper<Graph*>::name,
                                "sum", LINK_OVL);
        addArbMethod("*", Wrapper<Graph*>::name,
                                "product", LINK_OVL);
}
