#include <omega.h>

#pragma hdrstop

#ifdef _WIN32
#define export extern "C" __declspec(dllexport)
#endif

typedef int handle;

export handle Relation_Union (handle h1, handle h2)
{
	Relation *r1 = (Relation *)h1;
	Relation *r2 = (Relation *)h2;

	Relation *r = new Relation();

	*r = Union(copy(*r1), copy(*r2));

	return (handle)r;
}

export handle Relation_Intersection (handle h1, handle h2)
{
	Relation *r1 = (Relation *)h1;
	Relation *r2 = (Relation *)h2;

	Relation *r = new Relation();

	*r = Intersection(copy(*r1), copy(*r2));

	return (handle)r;
}

export handle Relation_Composition (handle h1, handle h2)
{
	Relation *r1 = (Relation *)h1;
	Relation *r2 = (Relation *)h2;

	Relation *r = new Relation();

	*r = Composition(copy(*r1), copy(*r2));

	return (handle)r;
}

export handle *Relation_GetConjuncts (handle h)
{
	DNF *dnf = ((Relation *)h)->query_DNF(2, 4);

	handle *c = new handle[dnf->length() + 1];

	c[0] = dnf->length();

	int p = 1;

	for (DNF_Iterator i(dnf); i; i++)
		c[p++] = (handle)*i;

	return c;
}

export int Conjunct_QueryVariableLowerBound (handle h, handle v)
{
	int lower, upper;

	((Conjunct *)h)->query_variable_bounds((Variable_ID)v, lower, upper);

	return lower;
}

export int Conjunct_QueryVariableUpperBound (handle h, handle v)
{
	int lower, upper;

	((Conjunct *)h)->query_variable_bounds((Variable_ID)v, lower, upper);

	return upper;
}

export handle Relation_GetLocal (handle h, handle g)
{
	return (handle)((Relation *)h)->get_local((Free_Var_Decl *)g);
}

export handle Relation_Create1 (int s)
{
	Relation *r = new Relation(s);

	return (handle)r;	
}

export handle Relation_Create2 (int i, int o)
{
	Relation *r = new Relation(i, o);

	return (handle)r;	
}

export void Relation_Delete (handle h)
{
	delete (Relation *)h;
}

export void Relation_Print (handle h)
{
	((Relation *)h)->print();
}

export void Relation_Finalize (handle h)
{
	((Relation *)h)->finalize();
}

export void Relation_Simplify (handle h, int p1, int p2)
{
	((Relation *)h)->simplify(p1, p2);
}

export void Relation_NameInputVariable (handle h, int i, char *n)
{
	((Relation *)h)->name_input_var(i, n);
}

export void Relation_NameOutputVariable (handle h, int i, char *n)
{
	((Relation *)h)->name_output_var(i, n);
}

export void Relation_NameSetVariable (handle h, int i, char *n)
{
	((Relation *)h)->name_set_var(i, n);
}

export handle Relation_GetInputVariable (handle h, int i)
{
	return (handle)((Relation *)h)->input_var(i);
}

export handle Relation_GetOutputVariable (handle h, int i)
{
	return (handle)((Relation *)h)->output_var(i);
}

export handle Relation_GetSetVariable (handle h, int i)
{
	return (handle)((Relation *)h)->set_var(i);
}

export int Relation_GetInputCount (handle h)
{
	return ((Relation *)h)->n_inp();
}

export int Relation_GetOutputCount (handle h)
{
	return ((Relation *)h)->n_out();
}

export int Relation_GetSetCount (handle h)
{
	return ((Relation *)h)->n_set();
}

export handle Relation_AddAnd (handle h)
{
	return (handle)((Relation *)h)->add_and();
}

export handle Formula_AddAnd (handle h)
{
	return (handle)((Formula *)h)->add_and();
}

export handle Formula_AddOr (handle h)
{
	return (handle)((Formula *)h)->add_or();
}

export handle Formula_AddNot (handle h)
{
	return (handle)((Formula *)h)->add_not();
}

export handle FAnd_AddEQ (handle h)
{
	Constraint_Handle *t = new EQ_Handle();
	
	*t = ((F_And *)h)->add_EQ();

	return (handle)t;
}

export handle FAnd_AddGEQ (handle h)
{
	Constraint_Handle *t = new GEQ_Handle();
	
	*t = ((F_And *)h)->add_GEQ();

	return (handle)t;
}

export void Constraint_DeleteHandle (handle h)
{
	delete (Constraint_Handle *)h;
}

export void Constraint_UpdateCoefficient (handle h, handle v, int c)
{
	((Constraint_Handle *)h)->update_coef((Variable_ID)v, c);
}

export void Constraint_UpdateConstant (handle h, int c)
{
	((Constraint_Handle *)h)->update_const(c);
}

export const char *Variable_GetName (handle h)
{
	static char b[128] = "";

	return strcpy(b, ((Variable_ID)h)->base_name);
}

export handle Global_Create (char *n)
{
	Free_Var_Decl *d = new Free_Var_Decl(n);

	return (handle)d;
}

export void Global_Delete (handle h)
{
	delete (Free_Var_Decl *)h;
}