#
#--> GaussianInteger(R)
# Creates the domain of Gaussian Integers using Maples representation
# Author MBM: 92
#
GaussianInteger := proc() local G,Z; option remember;

	G := EuclideanDomain();
	Z := Integer();

	defOperation( Conj,  G &-> G, G );
	defOperation( Make,  [Integer,Integer] &-> G, G );
	defOperations( {Re,Im}, G &-> Integer, G );

	# Rep is a Maple complex integer
	G[DomainName] := Gaussian;
	G[Characteristic] := 0;
	G['_i'] := I;
	G[Make] := proc(x,y) x+I*y end;
	G[Conj] := proc(x) Re(x)-I*Im(x) end;
	G[Re] := Re;
	G[Im] := Im;

	G[Output] := x -> x;
	G[Random] := subs('R' = Z, proc() R[Random]() + R[Random]() * I end);
	G[Input] := proc(x)
		if type(x,'complex(integer)') then x else FAIL fi
	    end;

	addProperty(G,CannonicallyUniquelyRepresented);
	G[`=`] := (x,y) -> evalb(x=y);

	G[0] := 0;
	G[1] := 1;
	G[`+`] := `+`;
	G[`-`] := `-`;
	G[`*`] := `*`;
	G[EuclideanNorm] := proc(x) Re(x)^2+Im(x)^2 end;
	G[Unit] := proc(x)
		if Im(x) > 0 and Re(x) <= 0 then I
		elif Re(x) < 0 and Im(x) <= 0 then -1
		elif Im(x) < 0 and Re(x) >= 0 then -I
		else 1
		fi
	    end;
	G[Inv] := proc(x)
		if x = 1 then 1
		elif x = -1 then -1
		elif x = I then -I
		elif x = -I then I
		elif x = 0 then ERROR(`division by zero`)
		else FAIL
		fi
	    end;
	G[Rem] := proc(a,b,q) local ar,ai,br,bi,nb,cr,ci,qr,qi,r;
		ar := Re(a); ai := Im(a); br := Re(b); bi := Im(b);
		nb := br^2+bi^2;
		cr := ar*br+ai*bi;
		ci := ai*br-ar*bi;
		qr := iquo(cr,nb,'r');
		if cr >= 0 then if r > iquo(cr,2) then qr := qr + 1 fi fi;
		if cr < 0 then if r < iquo(cr,2) then qr := qr - 1 fi fi;
		qi := iquo(ci,nb,'r');
		if ci >= 0 then if r > iquo(ci,2) then qi := qi + 1 fi fi;
		if ci < 0 then if r < iquo(ci,2) then qi := qi - 1 fi fi;
		if nargs = 3 then q := qr + I*qi fi;
		(ar-br*qr+bi*qi) + (ai-bi*qr-br*qi) * I
	    end;
	G[Prime] := subs('F' = G, proc(x) local y;
		y := F[Normal](x);
		if Im(y) = 0 then irem(Re(y),4) = 3 and isprime(Re(y))
		else isprime(F[EuclideanNorm](y))
		fi
	    end);
	op(G)
end:

save `GZ.m`;
quit
