Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add systematic tests for euclidean ring properties; fix/implement those for Integers mod n #3604

Merged
merged 5 commits into from
Aug 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/field.gi
Original file line number Diff line number Diff line change
Expand Up @@ -1114,7 +1114,7 @@ InstallMethod( QuotientRemainder,
if not r in F then
TryNextMethod(); # FIXME: or error?
fi;
return [ r/s, 0 ];
return [ r/s, Zero(F) ];
end );

#############################################################################
Expand Down
9 changes: 8 additions & 1 deletion lib/zmodnz.gd
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,13 @@ InstallTrueMethod( IsFinite,
IsZmodnZObjNonprimeCollection and IsDuplicateFree );


#############################################################################
##
#M IsEuclideanRing( <R> ) . . . . . . . . . . . . method for full ring Z/nZ
##
InstallTrueMethod(IsEuclideanRing, IsZmodnZObjNonprimeCollection and
IsWholeFamily and IsRing);

#############################################################################
##
#V Z_MOD_NZ
Expand Down Expand Up @@ -241,7 +248,7 @@ DeclareSynonym( "ZmodpZObj", ZmodnZObj );
##
## <Description>
## For an element <A>obj</A> in a residue class ring of integers modulo
## <M>n</M> (see&nbsp;<Ref Func="IsZmodnZObj"/>),
## <M>n</M> (see&nbsp;<Ref Filt="IsZmodnZObj"/>),
## <Ref Attr="ModulusOfZmodnZObj"/> returns the positive integer <M>n</M>.
##
## Deprecated, use <Ref Attr="Characteristic"/> instead.
Expand Down
37 changes: 37 additions & 0 deletions lib/zmodnz.gi
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,43 @@ InstallMethod(ZOp,
end);


#############################################################################
##
#M EuclideanDegree( <R>, <n> )
##
## For an overview on the theory of euclidean rings which are not domains,
## see Pierre Samuel, "About Euclidean rings", J. Algebra, 1971 vol. 19 pp. 282-301.
## http://dx.doi.org/10.1016/0021-8693(71)90110-4

InstallMethod( EuclideanDegree,
"for Z/nZ and an element in Z/nZ",
IsCollsElms,
[ IsZmodnZObjNonprimeCollection and IsWholeFamily and IsRing, IsZmodnZObj and IsModulusRep ],
function ( R, n )
return GcdInt( n![1], Characteristic( n ) );
end );


#############################################################################
##
#M QuotientRemainder( <R>, <n>, <m> )
##
InstallMethod( QuotientRemainder,
"for Z/nZ and two elements in Z/nZ",
IsCollsElmsElms,
[ IsZmodnZObjNonprimeCollection and IsWholeFamily and IsRing,
IsZmodnZObj and IsModulusRep, IsZmodnZObj and IsModulusRep ],
function ( R, n, m )
local u, s, q, r;
u := StandardAssociateUnit(R, m);
s := u * m; # the standard associate of m
q := QuoInt(n![1], s![1]);
r := n![1] - q * s![1];
return [ ZmodnZObj( FamilyObj( n ), (q * u![1]) mod Characteristic(R) ),
ZmodnZObj( FamilyObj( n ), r ) ];
end );


#############################################################################
##
#M StandardAssociate( <r> )
Expand Down
60 changes: 60 additions & 0 deletions tst/testinstall/euclidean.tst
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#@local checkEuclideanRing
gap> START_TEST("euclidean.tst");

# test consistency of EuclideanDegree, EuclideanQuotient, EuclideanRemainder,
# and QuotientRemainder for some ring and elements of it
gap> checkEuclideanRing :=
> function(R, colls...)
> local coll1, coll2, a, b, deg_b, deg_r, q, r, qr;
> if Length(colls) >= 1 then coll1:=colls[1];
> elif Size(R) <= 100 then coll1 := R;
> else coll1 := List([1..100],i->Random(R));
> fi;
> if Length(colls) >= 2 then coll2:=colls[2];
> elif Size(R) <= 100 then coll2 := R;
> else coll2 := List([1..100],i->Random(R));
> fi;
> for b in coll1 do
> if IsZero(b) then continue; fi;
> deg_b := EuclideanDegree(R, b);
> for a in coll2 do
> q := EuclideanQuotient(R, a, b); Assert(0, q in R);
> r := EuclideanRemainder(R, a, b); Assert(0, r in R);
> if a <> q*b + r then Error("a <> q*b + r for ", [R,a,b]); fi;
> deg_r := EuclideanDegree(R, r);
> if not IsZero(r) and deg_r >= deg_b then Error("Euclidean degree did not decrease for ",[R,a,b]); fi;
> qr := QuotientRemainder(R, a, b);
> if qr <> [q, r] then Error("QuotientRemainder inconsistent for ", [R,a,b]); fi;
> od;
> od;
> return true;
> end;;

# rings in characteristic 0
gap> checkEuclideanRing(Integers,[-100..100],[-100..100]);
true
gap> checkEuclideanRing(Rationals);
true
gap> checkEuclideanRing(GaussianIntegers);
true
gap> checkEuclideanRing(GaussianRationals);
true

# finite fields
gap> ForAll(Filtered([2..50], IsPrimePowerInt), q->checkEuclideanRing(GF(q)));
true

# ZmodnZ
gap> ForAll([1..50], m -> checkEuclideanRing(Integers mod m));
true
gap> checkEuclideanRing(Integers mod ((2*3*5)^2));
true
gap> checkEuclideanRing(Integers mod ((2*3*5)^3));
true
gap> checkEuclideanRing(Integers mod ((2*3*5*7)^2));
true
gap> checkEuclideanRing(Integers mod ((2*3*5*7)^3));
true

#
gap> STOP_TEST( "euclidean.tst", 1);