############################################################################# ## ## This file is part of GAP, a system for computational discrete algebra. ## This file's authors include Frank Celler, Andrew Solomon, Alexander Hulpke. ## ## Copyright of GAP belongs to its developers, whose names are too numerous ## to list here. Please refer to the COPYRIGHT file for details. ## ## SPDX-License-Identifier: GPL-2.0-or-later ## ## This file contains the methods for rational functions that know that they ## are univariate. ##
lc:=Length(cofs); if lc>0 and not IsIdenticalObj(ElementsFamily(FamilyObj(cofs)),fam) then # try to fix
Info(InfoWarning,1, "Convert coefficient list to get compatibility with family");
cofs:=cofs*One(fam); if not IsIdenticalObj(ElementsFamily(FamilyObj(cofs)),fam) then # did not work
TryNextMethod(); fi; fi;
fam:=RationalFunctionsFamily(fam); if lc>0 and (IsZero(cofs[1]) or IsZero(cofs[lc])) then
cofs:=ShallowCopy(cofs); # always copy to avoid destroying list
val:=val+RemoveOuterCoeffs(cofs,fam!.zeroCoefficient); fi;
InstallMethod( LaurentPolynomialByCoefficients, "warn about iterated polynomials", true,
[ IsFamily and HasCoefficientsFamily, IsList, IsInt, IsInt ], 0, function( fam, cofs, val, ind ) # catch algebraic extensions if ITER_POLY_WARN=true and not IsBound(fam!.primitiveElm) # also sc rings are fine.
and not IsBound(fam!.moduli) then
Info(InfoWarning,1, "You are creating a polynomial *over* a polynomial ring (i.e. in an");
Info(InfoWarning,1, "iterated polynomial ring). Are you sure you want to do this?");
Info(InfoWarning,1, "If not, the first argument should be the base ring, not a polynomial ring"
);
Info(InfoWarning,1, "Set ITER_POLY_WARN:=false; to remove this warning."
); fi;
TryNextMethod(); end);
cofs := CoefficientsOfLaurentPolynomial(obj); if IsEmpty(cofs[1]) then
return DEGREE_ZERO_LAURPOL; else
return cofs[2] + Length(cofs[1]) - 1; fi; end );
############################################################################# ## #M DegreeIndeterminate( pol, ind ) ##
InstallOtherMethod(DegreeIndeterminate,"laurent,indetnr",true,
[IsLaurentPolynomial,IsPosInt],0, function(pol,ind)
local d;
d:=DegreeOfLaurentPolynomial(pol); # unless constant: return 0 as we are in the wrong game if d>0 and IndeterminateNumberOfUnivariateRationalFunction(pol)<>ind then
return 0; fi;
return d; end);
############################################################################# ## #F CIUnivPols( <upol>, <upol> ) test for common base ring and for ## common indeterminate of UnivariatePolynomials
InstallGlobalFunction( CIUnivPols, function(f,g)
local d,x;
#if HasIndeterminateNumberOfLaurentPolynomial(f) and # HasIndeterminateNumberOfLaurentPolynomial(g) then # x:=IndeterminateNumberOfLaurentPolynomial(f); # if x<>IndeterminateNumberOfLaurentPolynomial(g) then # return fail; # else # return x; # fi; #fi;
if IsLaurentPolynomial(f) and IsLaurentPolynomial(g) then # is either polynomial constant? if yes we must permit different # indeterminate numbers
d:=DegreeOfLaurentPolynomial(f); if d=0 or d=DEGREE_ZERO_LAURPOL then
return IndeterminateNumberOfLaurentPolynomial(g); fi;
x:=IndeterminateNumberOfLaurentPolynomial(f);
d:=DegreeOfLaurentPolynomial(g); if d<>0 and d<>DEGREE_ZERO_LAURPOL and
x<>IndeterminateNumberOfLaurentPolynomial(g) then
return fail; fi; # all OK
return x; fi;
return fail; end );
############################################################################# ## #M ExtRepNumeratorRatFun(<ulaurent>) ##
InstallMethod(ExtRepNumeratorRatFun,"laurent polynomial rep.",true,
[IsLaurentPolynomialDefaultRep],0, function(f)
local c;
c:=CoefficientsOfLaurentPolynomial(f);
return EXTREP_COEFFS_LAURENT(c[1],
Maximum(0,c[2]), # negative will go into denominator
IndeterminateNumberOfLaurentPolynomial(f),
FamilyObj(f)!.zeroCoefficient); end);
############################################################################# ## #M ExtRepDenominatorRatFun(<ulaurent>) ##
InstallMethod(ExtRepDenominatorRatFun,"laurent polynomial rep.",true,
[IsLaurentPolynomialDefaultRep and IsRationalFunction],0, function(obj)
local cofs, val, ind, quo;
cofs := CoefficientsOfLaurentPolynomial(obj); if Length(cofs) = 0then
return [[], FamilyObj(obj)!.oneCoefficient]; fi;
val := cofs[2];
cofs := cofs[1];
ind := IndeterminateNumberOfUnivariateRationalFunction(obj);
# This is to compute the denominator
if val < 0then
quo := [ [ ind, -val ], FamilyObj(obj)!.oneCoefficient ]; else
quo := [ [], FamilyObj(obj)!.oneCoefficient ]; fi;
return quo;
end);
############################################################################# ## #M One(<laurent>) ##
InstallMethod(OneOp,"univariate",true,
[ IsPolynomialFunction and IsUnivariateRationalFunction ], 0, function(p)
local indn,fam;
fam:=FamilyObj(p);
indn := IndeterminateNumberOfUnivariateRationalFunction(p); if not IsBound(fam!.univariateOnePolynomials[indn]) then
fam!.univariateOnePolynomials[indn]:=
LaurentPolynomialByExtRepNC(fam,fam!.oneCoefflist,0,indn); fi;
return fam!.univariateOnePolynomials[indn]; end);
# avoid the one of the family (which is not univariate!)
InstallMethod(One,"univariate",true,
[ IsPolynomialFunction and IsUnivariateRationalFunction ], 0, OneOp);
############################################################################# ## #M Zero(<laurent>) ##
InstallMethod(ZeroOp,"univariate",true,
[ IsPolynomialFunction and IsUnivariateRationalFunction ], 0, function(p)
local indn,fam;
fam:=FamilyObj(p);
indn := IndeterminateNumberOfUnivariateRationalFunction(p); if not IsBound(fam!.univariateZeroPolynomials[indn]) then
fam!.univariateZeroPolynomials[indn]:=
LaurentPolynomialByExtRepNC(fam,[],0,indn); fi;
return fam!.univariateZeroPolynomials[indn];
end);
# avoid the one of the family (which is not univariate!)
InstallMethod(Zero,"univariate",true,
[ IsPolynomialFunction and IsUnivariateRationalFunction ], 0, ZeroOp);
############################################################################# ## #M <laurent> - <laurent> ## ## This is almost the same as `+'. However calling `AdditiveInverse' would ## wrap up an intermediate polynomial which gets a bit expensive. So we do ## almost the same here.
InstallMethod( \-, "laurent - laurent", IsIdenticalObj,
[ IsPolynomialFunction and IsLaurentPolynomial,
IsPolynomialFunction and IsLaurentPolynomial ], 0, DIFF_LAURPOLS);
# multiply by zero gives the zero polynomial if IsZero(coef) then return Zero(laur); elif IsOne(coef) then return laur;fi;
fam:=FamilyObj(laur);
# construct the product and check the valuation in case zero divisors
tmp := CoefficientsOfLaurentPolynomial(laur);
return LaurentPolynomialByExtRepNC(fam,coef*tmp[1], tmp[2],
IndeterminateNumberOfUnivariateRationalFunction(laur)); end );
############################################################################# ## #M <coeff> + <laurent> ## ## This method is installed for all rational functions because it does not ## matter if one is in a 'RationalFunctionsFamily', a 'LaurentPolynomials- ## Family', or a 'UnivariatePolynomialsFamily'. The sum is defined in all ## three cases. ##
BindGlobal("SumCoeffLaurpol", function( coef, laur )
local fam,zero, tmp, indn, val, sum, i;
fam:=FamilyObj(laur);
zero := fam!.zeroCoefficient;
tmp := CoefficientsOfLaurentPolynomial(laur);
val := tmp[2];
# if coef is trivial return laur if coef = zero then
return laur;
# the polynomial is trivial elif0 = Length(tmp[1]) then # we create, no problem occurs
return LaurentPolynomialByExtRepNC(fam, [coef], 0, indn );
# the constant is present elif val <= 0 and 0 < val + Length(tmp[1]) then
sum := ShallowCopy(tmp[1]);
i:=1-val; if (i=1 or i=Length(sum)) and sum[i]+coef=fam!.zeroCoefficient then # be careful if cancellation happens at an end
sum[i]:=fam!.zeroCoefficient;
val:=val+RemoveOuterCoeffs(sum,fam!.zeroCoefficient); else # no cancellation in first place
sum[i] := coef + sum[i]; fi;
return LaurentPolynomialByExtRepNC(fam, sum, val, indn );
# every coefficients has a negative exponent elif val + Length(tmp[1]) <= 0then
sum := ShallowCopy(tmp[1]); for i in [ Length(sum)+1 .. -val ] do
sum[i] := zero;
od;
sum[1-val] := coef; # we add at the end, no problem occurs
return LaurentPolynomialByExtRepNC(fam, sum, val, indn );
# every coefficients has a positive exponent else
sum := [coef]; for i in [ 2 .. val ] do
sum[i] := zero;
od;
Append( sum, tmp[1] ); # we add in the first position, no problem occurs
return LaurentPolynomialByExtRepNC(fam, sum, 0, indn );
fi; end );
# test whether family b occurs anywhere as a coefficients family of a.
BindGlobal("CoefficientsFamilyEmbedded",function(a,b) while HasCoefficientsFamily(a) do
a:=CoefficientsFamily(a); if a=b then
return true; fi;
od;
return false; end);
InstallMethod( \+, "coeff(embed) + laurent", true,
[ IsRingElement, IsUnivariateRationalFunction and IsLaurentPolynomial ], 0, function(c,l) if IsRat(c) #natural map from rationals into arbitrary rings
or # Adding elements of a smaller coefficient ring that is naturally embedded
CoefficientsFamilyEmbedded(FamilyObj(l),FamilyObj(c)) then
return SumCoeffLaurpol(c*FamilyObj(l)!.oneCoefficient,l); else
TryNextMethod(); fi; end);
InstallMethod( \+, "laurent + coeff(embed)", true,
[ IsUnivariateRationalFunction and IsLaurentPolynomial, IsRingElement ], 0, function(l,c) if IsRat(c) #natural map from rationals into arbitrary rings
or # Adding elements of a smaller coefficient ring that is naturally embedded
CoefficientsFamilyEmbedded(CoefficientsFamily(FamilyObj(l)),FamilyObj(c)) then
return SumCoeffLaurpol(c*FamilyObj(l)!.oneCoefficient,l); else
TryNextMethod(); fi; end);
# these should be ranked higher than the previous two
InstallMethod( \+, "coeff + laurent", IsCoeffsElms,
[ IsRingElement, IsUnivariateRationalFunction and IsLaurentPolynomial ], 0,
SumCoeffLaurpol);
############################################################################# ## #F QuotRemLaurpols(left,right,mode) ##
InstallGlobalFunction(QuotRemLaurpols,function(f,g,mode)
local fam,indn,val,q,fc,gc;
fam:=FamilyObj(f);
indn := CIUnivPols(f,g); # use to get the indeterminate if indn=fail then
return fail; # can't do anything fi;
f:=CoefficientsOfLaurentPolynomial(f);
g:=CoefficientsOfLaurentPolynomial(g); if Length(g[1])=0then
return fail; # cannot divide by 0 fi; if f[2]>0then
fc:=ShiftedCoeffs(f[1],f[2]); else
fc:=ShallowCopy(f[1]); fi; if g[2]>0then
gc:=ShiftedCoeffs(g[1],g[2]); else
gc:=ShallowCopy(g[1]); fi;
if mode=1 or mode=4then if mode=4 and ForAny(fc,i->not IsZero(i)) then
return fail; fi;
val:=RemoveOuterCoeffs(q,fam!.zeroCoefficient);
q:=LaurentPolynomialByExtRepNC(fam,q,val,indn);
return q; elif mode=2then
val:=RemoveOuterCoeffs(fc,fam!.zeroCoefficient);
f:=LaurentPolynomialByExtRepNC(fam,fc,val,indn);
return f; elif mode=3then
val:=RemoveOuterCoeffs(q,fam!.zeroCoefficient);
q:=LaurentPolynomialByExtRepNC(fam,q,val,indn);
val:=RemoveOuterCoeffs(fc,fam!.zeroCoefficient);
f:=LaurentPolynomialByExtRepNC(fam,fc,val,indn);
return [q,f]; fi;
end);
############################################################################# ## #M <unilau> / <unilau> (if possible) ## ## While w rely for ordinary rat. fun. on a*Inverse(b) we do not want this ## for laurent polynomials, as the inverse would have to be represented as ## a rational function, not a laurent polynomial.
InstallMethod(\/,"upol/upol",true,
[IsUnivariatePolynomial,IsUnivariatePolynomial],2, function(a,b)
local q;
q:=QuotRemLaurpols(a,b,4); if q=fail then
TryNextMethod(); fi;
return q; end);
############################################################################# ## #M QuotientRemainder( [<pring>,] <upol>, <upol> ) ##
InstallMethod(QuotientRemainder,"laurent, ring",IsCollsElmsElms,
[IsPolynomialRing,IsUnivariatePolynomial,
IsUnivariatePolynomial],0, function (R,f,g)
local q;
q:=QuotRemLaurpols(f,g,3); if q=fail then
TryNextMethod(); fi;
return q; end);
InstallOtherMethod(QuotientRemainder,"laurent",IsIdenticalObj,
[IsUnivariatePolynomial,IsUnivariatePolynomial],0, function (f,g)
local q;
q:=QuotRemLaurpols(f,g,3); if q=fail then
TryNextMethod(); fi;
return q; end);
############################################################################# ## #M QuotientMod( <pring>, <upol>, <upol>, <upol> ) ##
BIND_GLOBAL("QUOMOD_UPOLY",function (r,s,m)
local f,g,h,fs,gs,hs,q,t;
f := s; fs := 1;
g := m; gs := 0; while not IsZero(g) do
t := QuotientRemainder(f,g);
h := g; hs := gs;
g := t[2]; gs := fs - t[1]*gs;
f := h; fs := hs;
od;
q:=QuotRemLaurpols(r,f,4); if q = fail then
return fail; else
return (fs*q) mod m; fi; end);
InstallMethod(QuotientMod,"laurent,ring",IsCollsElmsElmsElms,
[IsRing,IsUnivariatePolynomial,IsUnivariatePolynomial,IsUnivariatePolynomial],0, function (R,r,s,m)
return QUOMOD_UPOLY(r,s,m); end);
g:=PowerModCoeffs(g,Length(g),e,m,Length(m)); if Length(g)>0 and (g[1]=fam!.zeroCoefficient or
Last(g)=fam!.zeroCoefficient) then
g:=ShallowCopy(g);
val:=RemoveOuterCoeffs(g,fam!.zeroCoefficient); else
val := 0; fi;
g:=LaurentPolynomialByExtRepNC(fam,g,val,brci);
return g; end);
############################################################################# ## #M \=( <upol>, <upol> ) comparison ##
InstallMethod(\=,"laurent",IsIdenticalObj,
[IsLaurentPolynomial,IsLaurentPolynomial],0, function(a,b)
local ac,bc;
ac:=CoefficientsOfLaurentPolynomial(a);
bc:=CoefficientsOfLaurentPolynomial(b); if ac<>bc then
return false; fi; # is the indeterminate important? if (Length(ac[1])>1 or (Length(ac[1])>0 and ac[2]<>0))
and IndeterminateNumberOfLaurentPolynomial(a)<>
IndeterminateNumberOfLaurentPolynomial(b) then
return false; fi;
return true; end);
# we have problems if they have (truly) different indeterminate numbers # (i.e.: both are not constant and the indnums differ if (ac[2]<>0 or Length(ac[1])>1) and (bc[2]<>0 or Length(bc[1])>1) and
IndeterminateNumberOfLaurentPolynomial(a)<>
IndeterminateNumberOfLaurentPolynomial(b) then
TryNextMethod(); fi;
da:=Length(ac[1])+ac[2];
db:=Length(bc[1])+bc[2];
if da=db then # the total length is the same. We do not need to care about shift # factors!
a:=ac[1];b:=bc[1];
l:=Length(a);
m:=Length(b); while l>0 and m>0do if a[l]<b[m] then
return true; elif a[l]>b[m] then
return false; fi;
l:=l-1;m:=m-1;
od; # all the coefficients were the same. So we have to compare with a zero # that would have been shifted in if l>0then
z:=Zero(a[l]); # we don't need a `l>0' condition, because ending zeroes were shifted # out initially while a[l]=z do
l:=l-1;
od;
return a[l]<z; elif m>0then
z:=Zero(b[m]); # we don't need a `m>0' condition, because ending zeroes were shifted # out initially while b[m]=z do
m:=m-1;
od;
return b[m]>z; else # they are the same
return false; fi; else # compare the degrees
return da<db; fi; end);
############################################################################# ## #F RandomPol( <fam>, <deg> [,<inum>] ) ##
InstallGlobalFunction(RandomPol,function(arg)
local dom,deg,inum,i,c;
dom:=arg[1];
deg:=arg[2]; if Length(arg)=3then
inum:=arg[3]; else
inum:=1; fi;
c:=[]; for i in [0..deg] do
Add(c,Random(dom));
od; while IsZero(c[deg+1]) do
c[deg+1]:=Random(dom);
od;
return LaurentPolynomialByCoefficients(FamilyObj(c[1]),c,0,inum); end);
############################################################################# ## #M StandardAssociateUnit( <pring>, <lpol> ) ##
InstallMethod(StandardAssociateUnit,"laurent",
IsCollsElms,[IsPolynomialRing, IsLaurentPolynomial],0, function(R,f) # get standard associate of leading term
return StandardAssociateUnit(CoefficientsRing(R), LeadingCoefficient(f)) * One(R); end);
ind := [CoefficientsFamily(FamilyObj(f)),
IndeterminateNumberOfUnivariateRationalFunction(f)];
one:=FamilyObj(f)!.oneCoefficient;
d:=CoefficientsOfLaurentPolynomial(f); if Length(d[1])=0then # special case: Derivative of 0-Polynomial
return f; fi;
f:=d;
d:=[]; iF:=Zero(one); if f[2]>0then for i in [1..f[2]] doiF:=iF+one; od; elif f[2]<0then for i in [1..-f[2]] doiF:=iF+one; od; fi; for i in [1..Length(f[1])] do
d[i] := iF*f[1][i]; iF:=iF+one;
od;
return LaurentPolynomialByCoefficients(ind[1],d,f[2]-1,ind[2]); end);
InstallOtherMethod(Derivative,"uratfun",true,
[IsUnivariateRationalFunction],0, function(ratfun)
local num,den,R,cf,pow,dr; # try to be good for the case of iterated derivatives by using if the # denominator is a power
num:=NumeratorOfRationalFunction(ratfun);
den:=DenominatorOfRationalFunction(ratfun);
R:=CoefficientsRing(DefaultRing([den]));
cf:=Collected(Factors(den));
pow:=Gcd(List(cf,x->x[2])); if pow>1then
dr:=Product(List(cf,x->x[1]^(x[2]/pow))); # root else
dr:=den; fi; #cf:=(Derivative(num)*dr-num*pow*Derivative(dr))/dr^(pow+1);
num:=Derivative(num)*dr-num*pow*Derivative(dr);
den:=dr^(pow+1); if IsOne(Gcd(num,dr)) then # avoid cancellation
num:=CoefficientsOfUnivariateLaurentPolynomial(num);
den:=CoefficientsOfUnivariateLaurentPolynomial(den);
cf:=UnivariateRationalFunctionByExtRepNC(FamilyObj(ratfun),
num[1],den[1],num[2]-den[2],
IndeterminateNumberOfUnivariateRationalFunction(ratfun)); # maintain factorization of denominator
StoreFactorsPol(R,DenominatorOfRationalFunction(cf),
ListWithIdenticalEntries(pow+1,dr)); else
cf:=num/den; # cancellation fi;
return cf; #return (Derivative(num)*den-num*Derivative(den))/(den^2); end);
InstallGlobalFunction(TaylorSeriesRationalFunction,function(f,at,deg)
local t,i,x; if not (IsUnivariateRationalFunction(f) and deg>=0) then
Error("function is not univariate pol, or degree negative"); fi;
x:=IndeterminateOfUnivariateRationalFunction(f);
t:=Zero(f); for i in [0..deg] do if i>0then
f:=Derivative(f); fi;
t:=t+Value(f,at)*(x-at)^i/Factorial(i);
od;
return t; end);
############################################################################# ## #F Discriminant( <f> ) . . . . . . . . . . . . discriminant of polynomial f ##
InstallMethod( Discriminant, "univariate", true, [IsUnivariatePolynomial], 0, function(f)
local d; # the discriminant is \prod_i\prod_{j\not= i}(\alpha_i-\alpha_j), but # to avoid chaos with symmetric polynomials, we better compute it as # the resultant of f and f'
d:=DegreeOfLaurentPolynomial(f);
d:=(-1)^(d*(d-1)/2)*Resultant(f,Derivative(f),
IndeterminateNumberOfLaurentPolynomial(f))/LeadingCoefficient(f);
return ConstantInBaseRingPol(d,IndeterminateNumberOfLaurentPolynomial(f)); end);
############################################################################# ## #M Value( <upol>, <elm>, <one> ) ##
InstallOtherMethod( Value,"Laurent, ring element, and mult. neutral element",
true, [ IsLaurentPolynomial, IsRingElement, IsRingElement ], 0, function( f, x, one )
local val, i,e;
val:= Zero( one );
f:= CoefficientsOfLaurentPolynomial( f );
i:= Length( f[1] ); while0 < i do
e:=1; while0<i and IsZero(f[1][i]) do
e:=e+1;
i:=i-1;
od; if e>1then
val:= val * x^e + one * f[1][i]; else
val:= val * x + one * f[1][i]; fi;
i:=i-1;
od; if0 <> f[2] then
val:= val * x^f[2]; fi;
return val; end );
InstallOtherMethod( Value,"univariate rational function",
true, [ IsUnivariateRationalFunction, IsRingElement, IsRingElement ], 0, function( f, x, one )
local val, i,j;
val:= [Zero( one ),Zero(one)];
f:= CoefficientsOfUnivariateRationalFunction( f ); for j in [1,2] do
i:= Length( f[j] ); while0 < i do
val[j]:= val[j] * x + one * f[j][i];
i:= i-1;
od;
od; if IsZero(val[2]) then
Error("Denominator evaluates as zero"); fi;
val:=val[1]/val[2]; if0 <> f[3] then
val:= val * x^f[3]; fi;
return val; end );
# print coeff list f.
BindGlobal("StringUnivariateLaurent",function(fam,cofs,val,name)
local str,zero,one,mone,i,c,lc,s;
str:="";
zero := fam!.zeroCoefficient;
one := fam!.oneCoefficient;
mone := -one;
if IsInt(name) then# passed as indeterminate number if HasIndeterminateName(fam,name) then
name:=IndeterminateName(fam,name); else
name:=Concatenation("x_",String(name)); fi; fi;
if Length(cofs)=0then
return String(zero); fi;
lc:=Length(cofs); if cofs[lc] = zero then # assume that there is at least one non-zero coefficient
repeat
lc:=lc-1;
until cofs[lc]<>zero; fi; for i in [ lc,lc-1..1 ] do if cofs[i] <> zero then
# print a '+' if necessary
c := "*"; if i <lc then if IsRat(cofs[i]) then if cofs[i] = one then
Append(str,"+" );
c:=""; elif cofs[i]>0then
Append(str,"+");
Append(str,String(cofs[i])); elif cofs[i]=mone then
Append(str,"-");
c:=""; else
Append(str,String(cofs[i])); fi; elif cofs[i]=one then
Append(str,"+");
c:=""; elif cofs[i]=mone then
Append(str,"-");
c:=""; else
Append(str,"+");
s:=String(cofs[i]); if'+' in s or '-' in s then
s:=Concatenation("(",s,")"); fi;
Append(str,s); fi; elif cofs[i]=one then
c:=""; elif cofs[i]=mone then
Append(str,"-");
c:=""; else
s:=String(cofs[i]); if not IsRat(cofs[i]) and ('+' in s or '-' in s) then
s:=Concatenation("(",s,")"); fi;
Append(str,s); fi; if i+val <> 1then
Append(str,c);
Append(str,name); if i+val <> 2then
Append(str,"^");
Append(str,String( i+val-1 )); fi; elif cofs[i] = one then
Append(str,String(one)); elif cofs[i] = mone then
Append(str,String(one)); fi; fi;
od;
return str; end);
############################################################################# ## #M PrintObj( <uni-laurent> ) ## ## This method is installed for all rational functions because it does not ## matter if one is in a 'RationalFunctionsFamily', a 'LaurentPolynomials- ## Family', or a 'UnivariatePolynomialsFamily'. ##
InstallMethod( PrintObj,"laurent polynomial",true,[IsLaurentPolynomial],0, function( f )
local c;
c:=CoefficientsOfLaurentPolynomial(f);
Print(StringUnivariateLaurent(FamilyObj(f),
c[1],c[2],
IndeterminateNumberOfLaurentPolynomial(f))); end);
InstallMethod( String,"laurent polynomial",true,[IsLaurentPolynomial],0, function( f )
local c;
c:=CoefficientsOfLaurentPolynomial(f);
return StringUnivariateLaurent(FamilyObj(f),
c[1],c[2],
IndeterminateNumberOfLaurentPolynomial(f)); end);
fam:=RationalFunctionsFamily(fam); if Length(cofs)>0 and (IsZero(cofs[1]) or IsZero(Last(cofs))) then if not IsMutable(cofs) then
cofs:=ShallowCopy(cofs); fi;
val:=val+RemoveOuterCoeffs(cofs,fam!.zeroCoefficient); fi; if Length(dc)>0 and (IsZero(dc[1]) or IsZero(Last(dc))) then if not IsMutable(dc) then
dc:=ShallowCopy(dc); fi;
val:=val-RemoveOuterCoeffs(dc,fam!.zeroCoefficient); fi;
InstallMethod( PrintObj,"univar",true,[IsUnivariateRationalFunction],0, function( f )
local fam,ind,nv,dv;
fam := FamilyObj(f);
ind := IndeterminateNumberOfLaurentPolynomial(f);
f := CoefficientsOfUnivariateRationalFunction(f); if f[3]>=0then
nv:=f[3];
dv:=0; else
nv:=0;
dv:=-f[3]; fi;
Print("(",StringUnivariateLaurent(fam,f[1],nv,ind),")/(",StringUnivariateLaurent(fam,f[2],dv,ind),")"); end);
InstallMethod( String,"univar",true,[IsUnivariateRationalFunction],0, function( f )
local fam,ind,nv,dv;
fam := FamilyObj(f);
ind := IndeterminateNumberOfLaurentPolynomial(f);
f := CoefficientsOfUnivariateRationalFunction(f); if f[3]>=0then
nv:=f[3];
dv:=0; else
nv:=0;
dv:=-f[3]; fi;
return Concatenation("(",StringUnivariateLaurent(fam,f[1],nv,ind),")/(",StringUnivariateLaurent(fam,f[2],dv,ind),")"); end);
# Conversion:
# laurent to univariate ratfun
InstallMethod(CoefficientsOfUnivariateRationalFunction,"laurent polynomial",
true,[IsLaurentPolynomial],0, function(f)
local c;
c:=CoefficientsOfLaurentPolynomial(f);
return [c[1],FamilyObj(f)!.oneCoefflist,c[2]]; end);
# it is unlikely that there is a laurent polynomial in univariate ratfun # extrep. The following routines therefore are for safety only.
InstallMethod(IsLaurentPolynomial,"univariate",true,
[IsUnivariateRationalFunction],0, function(f)
local c;
c:=CoefficientsOfUnivariateRationalFunction(f); if Length(c[2])=1then
c:=[c[1]/c[2][1],c[3]];
SetCoefficientsOfLaurentPolynomial(f,c);
return true; fi;
return false; end);
# when testing a univariate rational function for polynomiality, we check # whether it is a laurent polynomial and then use the laurent polynomial # routines.
InstallMethod(IsPolynomial,"univariate",true,[IsUnivariateRationalFunction],0, function(f) if not IsLaurentPolynomial(f) then
return false; fi;
return CoefficientsOfLaurentPolynomial(f)[2]>=0; # test valuation end);
InstallOtherMethod(ExtRepPolynomialRatFun,"univariate",true,
[IsUnivariateRationalFunction],0, function(f) if not IsPolynomial(f) then
return false; fi;
return EXTREP_POLYNOMIAL_LAURENT(f); end);
if Length(cofs[1])=0then
return fail; elif Length(cofs[1])=1then # if the numerator is a power of x, we can return a laurent polynomial
return LaurentPolynomialByExtRepNC(FamilyObj(obj),
cofs[2]*Inverse(cofs[1][1]), -cofs[3], indn ); else # swap numerator and denominator and invert the valuation
return UnivariateRationalFunctionByExtRepNC(FamilyObj(obj),
cofs[2],cofs[1],-cofs[3],indn ); fi;
############################################################################# ## #M <univariate> - <univariate> ## ## This is almost the same as `+'. However calling `AdditiveInverse' would ## wrap up an intermediate polynomial which gets a bit expensive. So we do ## almost the same here.
InstallMethod( \-, "univariate - univariate", IsIdenticalObj,
[ IsPolynomialFunction and IsUnivariateRationalFunction,
IsPolynomialFunction and IsUnivariateRationalFunction ], 0,
DIFF_UNIVFUNCS);
############################################################################# ## #M <univariate> = <univariate> ##
InstallMethod( \=, "univariate = univariate", IsIdenticalObj,
[ IsPolynomialFunction and IsUnivariateRationalFunction,
IsPolynomialFunction and IsUnivariateRationalFunction ], 0, function(l,r)
local lc,rc;
lc:=CoefficientsOfUnivariateRationalFunction(l);
rc:=CoefficientsOfUnivariateRationalFunction(r); # is the indeterminate important? if (Length(lc[1])>1 or (Length(lc[1])>0 and lc[3]<>0))
and IndeterminateNumberOfUnivariateRationalFunction(l)<>
IndeterminateNumberOfUnivariateRationalFunction(r) then
return false; fi;
return ProductCoeffs(lc[1],rc[2])=ProductCoeffs(lc[2],rc[1]) and lc[3]=rc[3]; end);
# multiply by zero gives the zero polynomial if IsZero(coef) then return Zero(univ); elif IsOne(coef) then return univ;fi;
fam:=FamilyObj(univ);
# construct the product and check the valuation in case zero divisors
tmp := CoefficientsOfUnivariateRationalFunction(univ); if Length(tmp[1])=0then
return UnivariateRationalFunctionByExtRepNC(fam,[], tmp[2],tmp[3],
IndeterminateNumberOfUnivariateRationalFunction(univ)); else # Here we use ShallowCopy to avoid access errors later when CLONE_OBJ # will be called from coef*tmp[1] and will try to modify tmp
return UnivariateRationalFunctionByExtRepNC(fam,coef*ShallowCopy(tmp[1]), tmp[2],tmp[3],
IndeterminateNumberOfUnivariateRationalFunction(univ)); fi; end );
InstallMethod( \*, "coeff * univariate", IsCoeffsElms,
[ IsRingElement, IsPolynomialFunction and IsUnivariateRationalFunction ], 3, # The method for rational functions is higher ranked
ProdCoeffUnivfunc);
InstallMethod( \*, "univariate * coeff", IsElmsCoeffs,
[ IsPolynomialFunction and IsUnivariateRationalFunction,IsRingElement ], 3, # The method for rational functions is higher ranked function(l,c) return ProdCoeffUnivfunc(c,l);end);
# special convenience: permit to multiply by rationals
InstallMethod( \*, "rat * univariate", true,
[ IsRat, IsPolynomialFunction and IsUnivariateRationalFunction ],
-RankFilter(IsRat),#fallback method is low ranked function(c,r) return ProdCoeffUnivfunc(c*FamilyObj(r)!.oneCoefficient,r); end);
fam:=FamilyObj(univ); # make the constant a polynomial
tmp:=UnivariateRationalFunctionByExtRepNC(fam,
coef*fam!.oneCoefflist,fam!.oneCoefflist,0,
IndeterminateNumberOfUnivariateRationalFunction(univ));
return univ+tmp; end );
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.9Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-10-12)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.