polym_mat.sa
Generated by gen_html_sa_files from ICSI. Contact gomes@icsi.berkeley.edu for details
class MAT_POLYM_INTI
class MAT_POLYM_INTI is
include MAT_RING{POLYM_INTI};
include DET_PRIMITIVE_ALG{POLYM_INTI};
create(r,c:CARD):SAME is
return create(r,c,POLYM_INTI::one);
end;
end;
class MAT_POLYM_INTI_REDUCTION
class MAT_POLYM_INTI_REDUCTION is
------------------- matrix reduction -----------
shared Pivot_lc:INTI; -- coefficient of highest term
shared ip,jp:CARD;
shared cv0:ARRAY{POLYM_INTI};
shared Mat:MAT_POLYM_INTI;
shared jPivot:ARRAY{CARD}; -- [1..ALEXMATmaxC]
shared p0:CARD;
shared polydeg,polydegM:MONOMIAL{INTI};
CheckZeroI(p0:CARD):BOOL is
loop j::=(p0+1).upto!(Mat.nc-1);
if Mat[p0][jPivot[j]].is_zero.not then return false; end;
end;
return true;
end;
CheckZeroJ(p0:CARD):BOOL is
j0::=jPivot[p0];
loop i::=(p0+1).upto!(Mat.nr-1);
if Mat[i][j0].is_zero.not then return false; end;
end;
return true;
end;
CheckZero(p0:CARD):BOOL is
res::=CheckZeroI(p0) and CheckZeroJ(p0);
return res;
end;
maxDeg(p0:CARD):MONOMIAL{INTI} is
-- maximal degree in [p0..iDeg][p0..jDeg]
d:MONOMIAL{INTI}:=#;
loop i::=p0.upto!(Mat.nr-1);
loop j::=p0.upto!(Mat.nc-1);
d:=d.lcm(Mat[i][jPivot[j]].lp);
end;
end;
return d;
end;
shared unit:BOOL; -- true if pivot be a unit.
shared deg:MONOMIAL{INTI};
Sp(i,j:CARD) is
ip:=i; jp:=j; cv0:=Mat[ip];
deg:=cv0[jPivot[j]].lp; Pivot_lc:=cv0[jPivot[j]].lc;
end;
SetPivotSearch(p0:CARD) is
APivot,wPivot:INTI;
j1::=p0;
count::=0;
Sp(p0,p0);
cv0:=Mat[ip];
cv1::=cv0;
-- search arleady reduced
loop i::=p0.upto!(Mat.nr-1);
cv1:=Mat[i]; count:=0;
loop j::=p0.upto!(Mat.nc-1);
if cv1[jPivot[j]].is_zero.not then count:=count+1; jp:=j; end;
end;
if count=1 then
j1:=jPivot[jp]; count:=0;
loop i1::=p0.upto!(Mat.nr-1);
if Mat[i1][j1].is_zero.not then count:=count+1; end;
end;
if count=1 then Sp(i,jp); return; end;
end;
end;
-- Search unit
wPivot:=0.inti; unit:=false; deg:=#;
loop i::=p0.upto!(Mat.nr-1);
cv1:=Mat[i];
loop j::=p0.upto!(Mat.nc-1); j1:=jPivot[j];
if cv1[j1].is_zero.not then
wPivot:=cv1[j1].lc.abs;
if ((wPivot=1.inti)and(cv1[j1]=#POLYM_INTI(cv1[j1].lt)) and
((~unit)or(cv1[j1].lp<deg))
)
then Sp(i,j); unit:=true;
if (deg=#MONOMIAL{INTI}) then return; end;
end;
end;
end;
end;
if unit then return; end;
-- Search a polynomial with least coefficient of degree "polydeg"
APivot:=(-1).inti;
wPivot:=0.inti;
deg:=polydeg;
loop i::=p0.upto!(Mat.nr-1);
cv1:=Mat[i];
loop j::=p0.upto!(Mat.nc-1); j1:=jPivot[j];
wPivot:=cv1[j1].lc.abs;
if (cv1[j1].is_zero.not)and(APivot<0.inti) then
Sp(i,j); APivot:=Pivot_lc.abs;
end;
if (cv1[j1].is_zero.not)and((i/=p0)or(j/=p0))and(APivot>wPivot) then
if (deg>cv1[j1].lp)or(APivot>wPivot) then
Sp(i,j); APivot:=Pivot_lc.abs;
end;
end;
end;
end;
return;
end; -- SetPivotSearch
SetPivot(p0:CARD, inout polydeg:MONOMIAL{INTI}):BOOL is
-- Set Pivot_lc,jPivot: ip:=p0,jp:=jPivot[p0],cv0:=Mat[ip];
SetPivotSearch(p0); -- ip,jp,Pivot_lc
cv0:=Mat[ip]; Mat[ip]:=Mat[p0]; Mat[p0]:=cv0; ip:=p0;
tmp::=jPivot[jp]; jPivot[jp]:=jPivot[p0]; jPivot[p0]:=tmp; jp:=tmp;
if Pivot_lc/=0.inti then polydeg:=deg; end;
return Pivot_lc/=0.inti;
end;
shiftC(i:CARD) is
-- shift degree of i-th row to standard position
d:MONOMIAL{INTI}; cv1::=Mat[i];
loop j::=p0.upto!(Mat.nc-1); j1::=jPivot[j]; -- set degree
if (cv1[j1].is_zero.not) then
if void(d) then d:=cv1[j1].gcd_term;
else d:=d.gcd(cv1[j1].gcd_term);
end;
end;
end;
if void(d) then d:=#; end;
d.coeff:=POLYM_INTI::r_1;
if (~void(d))and(d>#MONOMIAL{INTI}) then --shift degree
loop j::=p0.upto!(Mat.nc-1); j1::=jPivot[j];
if (cv1[j1].is_zero.not) then
cv1[j1]:=cv1[j1]/#POLYM_INTI(d);
end;
end;
end;
end;
shiftL(j:CARD) is
-- shift degree to standard position
d:MONOMIAL{INTI}; j1::=jPivot[j];
-- set degree
loop i::=p0.upto!(Mat.nr-1);
if (Mat[i][j1].is_zero.not) then
if void(d) then d:=Mat[i][j1].gcd_term;
else d:=d.gcd(Mat[i][j1].gcd_term);
end;
end;
end;
if void(d) then d:=#; end;
d.coeff:=POLYM_INTI::r_1;
if d>#MONOMIAL{INTI} then --shift
loop i::=p0.upto!(Mat.nr-1);
if (Mat[i][j1].is_zero.not) then
Mat[i][j1]:=Mat[i][j1]/#POLYM_INTI(d);
end;
end;
end;
end;
SubC(i:CARD, inout polydegM:MONOMIAL{INTI}):BOOL is
j1 :CARD;
s:INTI:=0.inti; spoly, wpoly:POLYM_INTI;
d,mw:MONOMIAL{INTI};
cv1::=Mat[i]; flg:BOOL:=false;
-- #OUT+"subC"+"\n";
if unit then flg:=true;
loop
-- if cv0[jp].degree/=0 then #OUT+"!"; end;
--#OUT+"subC:1"+"\n";
-- check equivalence with Alexander poly.
-- #LOGOUT+WriteMatrix(Mat,Mat.nr-1,Mat.nc-1,1);
-- APolyOut(p0,maxR,false);
-- #LOGOUT+"\n";
if (cv1[jp].is_zero) then break!; end;
mw:=cv1[jp].lp.lcm(cv0[jp].lp);
d:=mw/cv1[jp].lp; d.coeff:=POLYM_INTI::r_1;
wpoly:=#POLYM_INTI(d);
--d:=mw/cv0[jp].lp; d.coeff:=cv1[jp].lc/Pivot_lc;
--spoly:=#POLYM_INTI(d);
spoly:=cv1[jp]*wpoly/cv0[jp];
loop j::=p0.upto!(Mat.nc-1); j1:=jPivot[j];
if cv0[j1].is_zero.not then
cv1[j1]:=cv1[j1]*wpoly-cv0[j1]*spoly;
end;
end;
-- #LOGOUT+WriteMatrix(Mat,Mat.nr-1,Mat.nc-1,1);
-- APolyOut(p0,maxR,false);
-- #LOGOUT+"\n";
end;
else
loop
--#OUT+"subC:2"+"\n";
if (cv1[jp].is_zero)or(cv1[jp].lt<cv0[jp].lt) then break!; end;
if cv1[jp].lp.is_divisible(cv0[jp].lp,false,false).not then break!; end;
s:=cv1[jp].lc/Pivot_lc;
if s=0.inti then break!; end;
flg:=true;
mw:=cv1[jp].lp.lcm(cv0[jp].lp);
d:=mw/cv1[jp].lp; d.coeff:=POLYM_INTI::r_1;
wpoly:=#POLYM_INTI(d);
--d:=mw/cv0[jp].lp; d.coeff:=s;
--spoly:=#POLYM_INTI(d);
spoly:=cv1[jp]*wpoly/cv0[jp];
loop j::=p0.upto!(Mat.nc-1); j1:=jPivot[j];
if cv0[j1].is_zero.not then
cv1[j1]:=cv1[j1]*wpoly-cv0[j1]*spoly;
end;
end;
end;
end;
--#OUT+"subC:2"+"\n";
if ~ flg then return false; end;
loop j::=p0.upto!(Mat.nc-1); shiftL(j); end;
shiftC(i);
-- set polydegM
--#OUT+"subC:4"+"\n";
loop j::=p0.upto!(Mat.nc-1); j1:=jPivot[j];
if (cv1[j1].is_zero.not)and(polydegM<cv1[j1].lp) then
polydegM:=cv1[j1].lp;
end;
end;
return true;
end;
SubL(j:CARD, inout polydegM:MONOMIAL{INTI}):BOOL is
s:INTI:=0.inti; spoly, wpoly:POLYM_INTI;
j1::=jPivot[j]; flg:BOOL:=false;
cv1:ARRAY{POLYM_INTI};
d,dw:MONOMIAL{INTI};
--#OUT+"subL"+"\n";
loop
--#OUT+"subL:1"+"\n";
if (cv0[j1].is_zero)or(cv0[j1].lp<cv0[jp].lp) then break!; end;
if cv0[j1].lp.is_divisible(cv0[jp].lp,false,false).not then break!; end;
s:=(cv0[j1].lc/Pivot_lc);
if s=0.inti then break!; end;
dw:=cv0[j1].lp.lcm(cv0[jp].lp);
d:=dw/cv0[j1].lp; d.coeff:=POLYM_INTI::r_1;
wpoly:=#POLYM_INTI(d);
--d:=mw/cv0[jp].lp; d.coeff:=s;
--spoly:=#POLYM_INTI(d);
spoly:=cv0[j1]*wpoly/cv0[jp];
flg:=true;
loop i::=p0.upto!(Mat.nr-1); cv1:=Mat[i];
if cv1[jp].is_zero.not then cv1[j1]:=cv1[j1]*wpoly-spoly*cv1[jp]; end;
end;
end;
--#OUT+"subL:2"+"\n";
if ~ flg then return false; end;
loop i::=p0.upto!(Mat.nr-1); shiftC(i); end;
shiftL(j);
-- set polydegM
--#OUT+"subL:3"+"\n";
loop i::=p0.upto!(Mat.nr-1); cv1:=Mat[i];
if (cv1[j1].is_zero.not)and(polydegM<cv1[j1].lp) then
polydegM:=cv1[j1].lp;
end;
end;
return true;
end;
reduce(inout mat:MAT_POLYM_INTI,out jpivot:ARRAY{CARD},out rDeg:CARD) is
--#OUT+"reduce\n";
i1:CARD;
subFlg:BOOL;
count:CARD;
Mat:=mat;
jPivot:=#(mat.nc); loop i::=jPivot.ind!; jPivot[i]:=i; end;
jpivot:=jPivot;
dim:CARD:=(Mat.nr).min(Mat.nc);
if dim<=0 then rDeg:=0;mat:=Mat; jpivot:=jPivot; return; end;
--#OUT+"reduce1\n";
loop p0:=0.upto!(dim-1);
--#OUT+"reduce2: p0="+p0.str+"\n";
if (p0+1=dim)and(Mat.nr=Mat.nc) then
rDeg:=p0+1; mat:=Mat; jpivot:=jPivot; return;
end;
rDeg:=p0;
polydegM:=maxDeg(p0); subFlg:=true;
count:=0;
loop
count:=count+1;
--#OUT+"reduce3: count="+count.str+"\n";
-- I don't know how to check the matrix is minimal.
-- (dim-p0+1)
if count>(dim-p0).square then
mat:=Mat; jpivot:=jPivot; return;
end;
--if ~ subFlg then polydegM:=polydegM-1;
--else -- polydegMax:=polydegM;
polydegM:=maxDeg(p0);
-- polydegMax:=maxDeg(p0,iDeg0,jDeg0);
--end;
subFlg:=false;
polydeg:=polydegM;
--#OUT+"reduce4: setpivot"+"\n";
if SetPivot(p0,inout polydeg) then end;
--if polydeg<0 then -- minimal?
-- mat:=Mat; jpivot:=jPivot; return;
--end;
if CheckZero(p0) then break!; end;
polydegM:=polydeg;
-- #OUT+"set pivot:\n"; WriteMatrix(Mat,p0);
--#OUT+"reduce5: subC"+"\n";
loop i::=(p0+1).upto!(Mat.nr-1) ;
if Mat[i][jp].is_zero.not then
subFlg:=SubC(i,inout polydegM) or subFlg;
-- if (Pivot_lc.abs/=1)or(polydeg>0) then
-- WriteMatrix(p0);
--end;
end;
end;
if unit then cv0[jp]:=POLYM_INTI::one;
polydeg:=#MONOMIAL{INTI};
loop j::=(p0+1).upto!(Mat.nc-1) ;
cv0[jPivot[j]]:=POLYM_INTI::zero;
end;
break!;
elsif CheckZero(p0) then
break!;
end;
--#OUT+"reduce6: subL"+"\n";
loop j::=(p0+1).upto!(Mat.nc-1);
if cv0[jPivot[j]].is_zero.not then
subFlg:=SubL(j,inout polydegM) or subFlg;
-- if (Pivot_lc.abs/=1)or(polydeg>0) then
--WriteMatrix(AlexMat,p0);
--end;
end;
end;
if CheckZero(p0) then break!; end;
end;
end;
--if Mat.nr-1=Mat.nc-1 then rDeg:=dim+1; end;
--PrintRelation;
mat:=Mat; jpivot:=jPivot;
end;
end;