Skip to content

Commit

Permalink
Improve Is{Constant,Univariate}RationalFunction, add tests
Browse files Browse the repository at this point in the history
* Change IsConstantRationalFunction and IsUnivariateRationalFunction to
  return false for objects which are not even rational functions
* Improve UNIVARTEST_RATFUN to deal with some more "trivial" cases before
  giving up
* Add convenience helpers for multiplying rational numbers by rational
  functions over rings which don't contain the rational numbers,
  complementing the existing helpers doing this for addition
* Add tests
  • Loading branch information
fingolfin committed May 18, 2018
1 parent 832f48e commit fe11ed7
Show file tree
Hide file tree
Showing 6 changed files with 285 additions and 20 deletions.
33 changes: 33 additions & 0 deletions hpcgap/lib/ratfun.gi
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,26 @@ function(o)
fi;
end);

InstallOtherMethod(IsConstantRationalFunction,"fallback for non-ratfun",true,
[IsObject],0,
function(o)
if IsRationalFunction(o) then
TryNextMethod();
else
return false;
fi;
end);

InstallOtherMethod(IsUnivariateRationalFunction,"fallback for non-ratfun",true,
[IsObject],0,
function(o)
if IsRationalFunction(o) then
TryNextMethod();
else
return false;
fi;
end);

#############################################################################
##
#M ExtRepPolynomialRatFun(<ulaurent>)
Expand Down Expand Up @@ -1031,6 +1051,19 @@ function(r, c)
return ProdCoefRatfun(c,r);
end);

InstallMethod( \*, "ratfun * rat", true,
[ IsPolynomialFunction, IsRat ],-RankFilter(IsRat),
function( left, right )
return left * (right*FamilyObj(left)!.oneCoefficient);
end );

InstallMethod( \*, "rat * ratfun ", true,
[ IsRat, IsPolynomialFunction], -RankFilter(IsRat),
function( left, right )
return (left*FamilyObj(right)!.oneCoefficient) * right;
end);


#############################################################################
##
#M <polynomial> + <coeff>
Expand Down
2 changes: 1 addition & 1 deletion lib/ratfun.gd
Original file line number Diff line number Diff line change
Expand Up @@ -1576,7 +1576,7 @@ DeclareGlobalFunction("GcdCoeffs");
## gap> UnivariatenessTestRationalFunction( (-6*y^2+y^3) / (y+1) );
## [ true, 2, false, [ [ -6, 1 ], [ 1, 1 ], 2 ] ]
## gap> UnivariatenessTestRationalFunction( (-6*y^2+y^3) / (x+1));
## [ fail, fail, fail, fail ]
## [ false, fail, false, fail ]
## gap> UnivariatenessTestRationalFunction( ((y+2)*(x+1)) / ((y-1)*(x+1)) );
## [ fail, fail, fail, fail ]
## ]]></Example>
Expand Down
33 changes: 33 additions & 0 deletions lib/ratfun.gi
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,26 @@ function(o)
fi;
end);

InstallOtherMethod(IsConstantRationalFunction,"fallback for non-ratfun",true,
[IsObject],0,
function(o)
if IsRationalFunction(o) then
TryNextMethod();
else
return false;
fi;
end);

InstallOtherMethod(IsUnivariateRationalFunction,"fallback for non-ratfun",true,
[IsObject],0,
function(o)
if IsRationalFunction(o) then
TryNextMethod();
else
return false;
fi;
end);

#############################################################################
##
#M ExtRepPolynomialRatFun(<ulaurent>)
Expand Down Expand Up @@ -1025,6 +1045,19 @@ function(r, c)
return ProdCoefRatfun(c,r);
end);

InstallMethod( \*, "ratfun * rat", true,
[ IsPolynomialFunction, IsRat ],-RankFilter(IsRat),
function( left, right )
return left * (right*FamilyObj(left)!.oneCoefficient);
end );

InstallMethod( \*, "rat * ratfun ", true,
[ IsRat, IsPolynomialFunction], -RankFilter(IsRat),
function( left, right )
return (left*FamilyObj(right)!.oneCoefficient) * right;
end);


#############################################################################
##
#M <polynomial> + <coeff>
Expand Down
19 changes: 19 additions & 0 deletions lib/ratfun1.gi
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,17 @@ local coefs, ind, extrep, i, shift,fam;

end;

INDETS_POLY_EXTREP:=function(extrep)
local indets, i, j;
indets:=[];
for i in [1,3..Length(extrep)-1] do
for j in [1,3..Length(extrep[i])-1] do
AddSet(indets, extrep[i][j]);
od;
od;
return indets;
end;

UNIVARTEST_RATFUN:=function(f)
local fam,notuniv,cannot,num,den,hasden,indn,col,dcol,val,i,j,nud,pos;
fam:=FamilyObj(f);
Expand All @@ -104,6 +115,14 @@ local fam,notuniv,cannot,num,den,hasden,indn,col,dcol,val,i,j,nud,pos;
den := ExtRepDenominatorRatFun(f);
fi;

# if the symmetric difference of the indeterminates of the numerator and
# denominator contains more than one element, can't be univariate
i:=INDETS_POLY_EXTREP(num);
j:=INDETS_POLY_EXTREP(den);
if Size(Union(i,j)) > Size(Intersection(i,j))+1 then
return notuniv;
fi;

if Length(den[1])> 0 then
# try a GCD cancellation
i:=TryGcdCancelExtRepPolynomials(fam,num,den);
Expand Down
94 changes: 75 additions & 19 deletions tst/testinstall/ratfun.tst
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,84 @@ gap> u:=Indeterminate(Rationals,101);;
gap> SetName(u,"u");;

#
gap> p0:=0*t^0;;
gap> p1:=p0+0*t^0;;
gap> p2:=p0+1*t^0;;
gap> q0:=0;;
gap> q1:=q0+0*t^0;;
gap> q2:=q0+1*t^0;;
gap> List([p1,p2,q1,q2],x->IsPolynomial(x));
[ true, true, true, true ]
gap> List([p1,p2,q1,q2],x->IsRat(x));
[ false, false, false, false ]
gap> Value(p1,1);
# test basic properties
#
gap> data := [ 0*t, t^0, t, t+1, 1/t, 1/(t+1), t+u, t/u, t/(u+1), 0, 1/2 ];
[ 0, 1, t, t+1, t^-1, (1)/(t+1), t+u, t/u, t/(u+1), 0, 1/2 ]
gap> List(data, IsRat);
[ false, false, false, false, false, false, false, false, false, true, true ]
gap> List(data, IsRationalFunction);
[ true, true, true, true, true, true, true, true, true, false, false ]
gap> List(data, IsConstantRationalFunction);
[ true, true, false, false, false, false, false, false, false, false, false ]
gap> List(data, IsPolynomial);
[ true, true, true, true, false, false, true, false, false, false, false ]
gap> List(data, IsUnivariatePolynomial);
[ true, true, true, true, false, false, false, false, false, false, false ]
gap> List(data, IsUnivariateRationalFunction);
[ true, true, true, true, true, true, false, false, false, false, false ]
gap> List(data, IsLaurentPolynomial);
[ true, true, true, true, true, false, false, false, false, false, false ]

#
# arithmetics
#

# multiplication
gap> List(data, x -> x * Zero(t));
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
gap> ForAll(last,IsUnivariatePolynomial and IsZero);
true
gap> List(data, x -> Zero(t) * x);
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
gap> ForAll(last,IsUnivariatePolynomial and IsZero);
true
gap> List(data, x -> One(t) * x);
[ 0, 1, t, t+1, t^-1, (1)/(t+1), t+u, t/u, t/(u+1), 0, 1/2 ]
gap> last = data*t^0;
true
gap> List(data, x -> x * One(t));
[ 0, 1, t, t+1, t^-1, (1)/(t+1), t+u, t/u, t/(u+1), 0, 1/2 ]
gap> last = data*t^0;
true

# addition
gap> List(data, x -> x + Zero(t));
[ 0, 1, t, t+1, t^-1, (1)/(t+1), t+u, t/u, t/(u+1), 0, 1/2 ]
gap> last = data*t^0;
true
gap> List(data, x -> Zero(t) + x);
[ 0, 1, t, t+1, t^-1, (1)/(t+1), t+u, t/u, t/(u+1), 0, 1/2 ]
gap> last = data*t^0;
true

# commutative
gap> SetX(data, data, {x,y} -> x*y = y*x);
[ true ]
gap> SetX(data, data, {x,y} -> x+y = y+x);
[ true ]

# associative
gap> SetX(data, data, data, {x,y,z} -> (x*y)*z = x*(y*z));
[ true ]
gap> SetX(data, data, data, {x,y,z} -> (x+y)+z = x+(y+z));
[ true ]

# distributive
gap> SetX(data, data, data, {x,y,z} -> (x+y)*z = x*z+y*z);
[ true ]

#
gap> Value(0*t,1);
0
gap> Value(p2,1);
gap> Value(t^0,1);
1
gap> Value(q1,1);
0
gap> Value(q2,-1);
gap> Value(t^0,-1);
1
gap> Value(t,-1);
-1

#
gap> y1:=Indeterminate(Rationals,1);;
gap> y2:=Indeterminate(Rationals,2);;
gap> y3:=Indeterminate(Rationals,3);;
Expand Down Expand Up @@ -71,7 +131,3 @@ t^8*u-u

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

#############################################################################
##
#E
124 changes: 124 additions & 0 deletions tst/testinstall/ratfun_gf5.tst
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
#############################################################################
##
#W ratfun.tst GAP Tests Alexander Hulpke
##
##
#Y (C) 1998 School Math. and Comp. Sci., University of St Andrews, Scotland
##
gap> START_TEST("ratfun_gf5.tst");

#
gap> t:=Indeterminate(GF(5),100);;
gap> SetName(t,"t");;
gap> u:=Indeterminate(GF(5),101);;
gap> SetName(u,"u");;

#
# test basic properties
#
gap> data := [ 0*t, t^0, t, t+1, 1/t, 1/(t+1), t+u, t/u, t/(u+1), 0, 1/2 ];;
gap> List(data, IsRat);
[ false, false, false, false, false, false, false, false, false, true, true ]
gap> List(data, IsRationalFunction);
[ true, true, true, true, true, true, true, true, true, false, false ]
gap> List(data, IsConstantRationalFunction);
[ true, true, false, false, false, false, false, false, false, false, false ]
gap> List(data, IsPolynomial);
[ true, true, true, true, false, false, true, false, false, false, false ]
gap> List(data, IsUnivariatePolynomial);
[ true, true, true, true, false, false, false, false, false, false, false ]
gap> List(data, IsUnivariateRationalFunction);
[ true, true, true, true, true, true, false, false, false, false, false ]
gap> List(data, IsLaurentPolynomial);
[ true, true, true, true, true, false, false, false, false, false, false ]

#
# arithmetics
#

# multiplication
gap> ForAll(List(data, x -> x * Zero(t)), IsUnivariatePolynomial and IsZero);
true
gap> ForAll(List(data, x -> Zero(t) * x), IsUnivariatePolynomial and IsZero);
true
gap> ForAll(List(data, x -> One(t) * x) - data, IsUnivariatePolynomial and IsZero);
true
gap> ForAll(List(data, x -> x * One(t)) - data, IsUnivariatePolynomial and IsZero);
true

# addition
gap> ForAll(List(data, x -> Zero(t) + x) - data, IsUnivariatePolynomial and IsZero);
true
gap> ForAll(List(data, x -> x + Zero(t)) - data, IsUnivariatePolynomial and IsZero);
true

# commutative
gap> SetX(data, data, {x,y} -> x*y = y*x);
[ true ]
gap> SetX(data, data, {x,y} -> x+y = y+x);
[ true ]

# associative
gap> SetX(data, data, data, {x,y,z} -> (x*y)*z = x*(y*z));
[ true ]
gap> SetX(data, data, data, {x,y,z} -> (x+y)+z = x+(y+z));
[ true ]

# distributive
gap> SetX(data, data, data, {x,y,z} -> (x+y)*z = x*z+y*z);
[ true ]

#
gap> Value(0*t,1);
0
gap> Value(t^0,1);
Z(5)^0
gap> Value(t^0,-1);
Z(5)^0
gap> Value(t,-1);
Z(5)^2

#
gap> y1:=Indeterminate(Rationals,1);;
gap> y2:=Indeterminate(Rationals,2);;
gap> y3:=Indeterminate(Rationals,3);;
gap> mat:=[[y1,1,0],[y2,y1,1],[y3,y2,y1]];;
gap> det:=DeterminantMat(mat*y1^0);;
gap> Value(det,[y1,y2,y3],[1,-5,1]);
12
gap> 1/( y1*y2 );
1/(x_1*x_2)

#
gap> Factors(t^24-1);
[ t+Z(5)^0, t+Z(5), t-Z(5)^0, t+Z(5)^3, t^2+Z(5), t^2+Z(5)^3, t^2+t+Z(5)^0,
t^2+t+Z(5), t^2+Z(5)*t-Z(5)^0, t^2+Z(5)*t+Z(5)^3, t^2-t+Z(5)^0, t^2-t+Z(5),
t^2+Z(5)^3*t-Z(5)^0, t^2+Z(5)^3*t+Z(5)^3 ]
gap> (t^24-1)/(t^16-1);
(t^16+t^8+Z(5)^0)/(t^8+Z(5)^0)
gap> (t^24-1)/(t^-16-1);
(t^32+t^24+t^16)/(-t^8-Z(5)^0)

#
# multivariate
#
gap> (t^24-u^2)/(t^16-u^4);
(t^24-u^2)/(t^16-u^4)
gap> f:=u*(t^24-1);; g:=u^2*(t^16-1);;
gap> f/g;
(t^24*u-u)/(t^16*u^2-u^2)
gap> Factors(f);
[ u, t+Z(5)^0, t+Z(5), t-Z(5)^0, t+Z(5)^3, t^2+Z(5), t^2+Z(5)^3,
t^2+t+Z(5)^0, t^2+t+Z(5), t^2+Z(5)*t-Z(5)^0, t^2+Z(5)*t+Z(5)^3,
t^2-t+Z(5)^0, t^2-t+Z(5), t^2+Z(5)^3*t-Z(5)^0, t^2+Z(5)^3*t+Z(5)^3 ]
gap> Factors(t^4-u^4);
[ t+u, t+Z(5)*u, t-u, t+Z(5)^3*u ]

# multivariate gcd
gap> Gcd(DefaultRing(f),f,g);
t^8*u-u
gap> Gcd(f,g);
t^8*u-u

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

0 comments on commit fe11ed7

Please sign in to comment.