#
#--> ExponentVector(x:list(name))
# Exponent vector category
# Author MBM: 1989
#
ExponentVector := proc(x) local P,n,r,env;

	if not type(x,list(name)) then ERROR(`invalid arguments`) fi;
	n := nops(x);
	if nargs = 1 then P := newCategory() else P := args[2] fi;

	P := OrderedAbelianMonoid( op(P) );
	addCategory( P, ExponentVector );

	defOperation( `-`, [P,P] &-> P, P);
	defOperation( Div, [P,P] &-> Union(P,FAIL), P );
	defOperation( `<>=`, [P,P] &-> Union(-1,0,1), P );
	defOperation( List2Vect, List(Integer) &-> P, P );
	defOperation( Vect2List, P &-> List(Integer), P );
	defOperation( Degree, [P,Integer] &-> Integer, P );
	defOperation( TotalDegree, P &-> Integer, P );
	defOperation( Variables, List(Name), P );
	defOperation( Dim, Integer, P );
	defOperation( Gcd, [P,P] &-> P, P );
	defOperation( Lcm, [P,P] &-> P, P );

	env := ['D' = P, 'R' = r, 'N' = n];

	P[Variables] := x; 
	P[Dim] := n;

	P[`=`] := subs(env, proc(a,b) evalb(D[`<>=`](a,b) = 0) end);
	P[`<`] := subs(env, proc(a,b) evalb(D[`<>=`](a,b) = -1) end);
	P[`+`] := subs(env, proc(a,b) local i,r,u,v;
		u := D[Vect2List](a);
		v := D[Vect2List](b);
		r := [ seq(u[i]+v[i], i=1..N) ];
		D[List2Vect](r)
	    end);
	P[`-`] := subs(env, proc(a,b) local i,r,u,v;
		u := D[Vect2List](a);
		v := D[Vect2List](b);
		r := [ seq(u[i]-v[i], i=1..N) ];
		D[List2Vect](r)
	    end);
	P[Div] := subs(env, proc(a,b) local q,x;
		q := D[Vect2List](D[`-`](a,b));
		for x in q do if x < 0 then RETURN(FAIL) fi od;
		D[List2Vect]( q )
	    end);

	r := rand(4);
	P[Random] := subs(env, proc()
		D[List2Vect]( [ 'R()' $ N ] )
	    end);
	P[Degree] := subs(env, proc(a,i)
		if i < 1 or i > N then ERROR(`index out of range`) fi;
		D[Vect2List](a)[i]
	    end);
	P[TotalDegree] := subs(env, proc(a)
		convert( D[Vect2List](a), `+` )
	    end);
	P[Gcd] := subs(env, proc(a,b)
		D[List2Vect](zip(min, D[Vect2List](a), D[Vect2List](b)))
	    end);
	P[Lcm] := subs(min=max, eval(P[Gcd]));
	P[Input] := subs(env, proc(t) local c,i,x,v;
		c := traperror( lcoeff(t,D[Variables],x) );
		if c = lasterror or t <> x then RETURN(FAIL) fi;
		v := [seq( degree(t,x), x=D[Variables] )];
		D[List2Vect]( v )
	    end);
	P[Output] := subs(env, proc(a) local i,v,x;
		x := D[Variables];
		v := D[Vect2List](a);
		convert( [ seq(x[i]^v[i], i=1..N) ], `*` )
	    end);
	op(P)
end:

save `EV.m`;
quit
