#define eps(t) (((signe(t)*(t[lgefint(t)-1]))&3)==3)

intrinsic HilbertSymbol(x::RngIntElt, y::RngIntElt, p::RngIntElt)
{}
   require Sign(p) gt 0 and IsPrime(p) : "Argument 3 must be a prime.";
   if x eq 0 or y eq 0 then 
      return 0;
   end if;
   
   if IsOdd(p) then
      alpha, xprime := Valuation(x, p);
      beta,  yprime  := Valuation(y, p);
      
   else
  // etc. See Serre, "Local Fields", pg 212.

   end if;
end intrinsic;


hil(GEN x, GEN y, GEN p)
{
  long a,b,av,tx,ty,z;
  GEN p1,p2,u,v;

  if (gcmp0(x) || gcmp0(y)) return 0;
  av=avma; tx=typ(x); ty=typ(y);
  if (tx>ty) { p1=x; x=y; y=p1; a=tx,tx=ty; ty=a; }
  switch(tx)
  {
    case t_INT:
      switch(ty)
      {
	case t_INT:
	  if (signe(p)<=0)
	    return (signe(x)<0 && signe(y)<0)? -1: 1;
	  a = odd(pvaluation(x,p,&u));
          b = odd(pvaluation(y,p,&v));
	  if (egalii(p,gdeux))
          {
	    z = (eps(u) && eps(v))? -1: 1;
	    if (a && ome(v)) z= -z;
	    if (b && ome(u)) z= -z;
          }
          else
	  {
	    z = (a && b && eps(p))? -1: 1;
	    if (a && kronecker(v,p)<0) z= -z;
	    if (b && kronecker(u,p)<0) z= -z;
	  }
	  avma=av; return z;
#undef eps
#undef ome
