poly_mat.sa
Generated by gen_html_sa_files from ICSI. Contact gomes@icsi.berkeley.edu for details
class MAT_POLYS_INTI
class MAT_POLYS_INTI is
include MAT_RING{POLYS_INTI};
include DET_PRIMITIVE_ALG{POLYS_INTI};
include MAT_POLYS{POLYS_INTI};
det_mod_unit:POLYS_INTI is
return MAT_POLYS_DET::det_mod_unit(self);
end;
end;
class MAT_POLYS_FP
class MAT_POLYS_FP is
include MAT_RING{POLYS_FP};
include DET_PRIMITIVE_ALG{POLYS_FP} det->det_prm;
include MAT_PID{POLYS_FP};
include MAT_PID_DET{POLYS_FP} det->det_pid;
include MAT_POLYS{POLYS_FP};
det:POLYS_FP is return det_pid; end;
row_mod(i:CARD, n:POLYS_FP) is
-- (i-th row) mod n
if nc>0 then
loop j:CARD:=0.upto!(nc-1); m[i][j]:=m[i][j]%n; end;
end;
end;
col_mod(j:CARD, n:POLYS_FP) is
-- (j-th col) mod n
if nr>0 then
loop i:CARD:=0.upto!(nr-1); m[i][j]:=m[i][j]%n; end;
end;
end;
end;
partial class MAT_POLYS{ET}
partial class MAT_POLYS{ET} is
create(r,c:CARD):SAME is
return create(r,c,ET::one);
end;
str_pmatrix(var_name:STR):STR is
-- TeX \pmatrix{ }. v:var name
if nc=0 or nr=0 then return "()"; end;
s:STR:="\\pmatrix{\n"; newln:STR:="";
loop i::=0.upto!(nr-1);
s:=s+newln; newln:="\\cr\n"; sep:STR:="";
loop j::=0.upto!(nc-1);
s:=s+sep+m[i][j].str("tex",var_name,true); sep:=" & ";
end;
end;
s:=s+"\\cr\n}\n";
return s;
end;
str_array(var_name:STR):STR is
-- LaTeX array. v:var name
if nc=0 or nr=0 then return "()"; end;
s:STR:="\\left( \\begin{array}{"+("c".repeat(nc))+"}\n"; newln:STR:="";
loop i::=0.upto!(nr-1);
s:=s+newln; newln:="\\\\\n"; sep:STR:="";
loop j::=0.upto!(nc-1);
s:=s+sep+m[i][j].str("tex",var_name,true); sep:=" & ";
end;
end;
s:=s+"\n\\end{array} \\right)\n";
return s;
end;
strTeX(var_name:STR):STR is
return str_pmatrix(var_name);
end;
end;
class MAT_POLYS_DET
class MAT_POLYS_DET is
det_mod_unit(M:MAT_POLYS_INTI):POLYS_INTI is
if M.nr/=M.nc then return POLYS_INTI::zero; end;
Mw::=M.copy;
jPivot:ARRAY{CARD};
p0:CARD;
MAT_POLYS_INTI_REDUCTION::reduce(inout Mw,out jPivot,out p0);
poly::=POLYS_INTI::one;
pw:POLYS_INTI; -- work
-- diagonal part
if p0>0 then
loop i::=0.upto!(p0-1); pw:=Mw[i,jPivot[i]];
if pw.is_zero then return pw; else poly:=poly*pw; end;
end;
end;
-- non-diagonal part
if p0<Mw.nr then
mat::=Mw.copy; jPivotm::=jPivot.copy;
loop i::=0.upto!(p0-1); mat:=mat.minor_matrix(0,jPivotm[i]);
loop j::=i.upto!(jPivotm.size-1);
if jPivotm[j]>jPivotm[i] then jPivotm[j]:=jPivotm[j]-1; end;
end;
end;
poly:=poly*mat.det;
end;
return poly;
end;
end;
class MAT_POLYS_INTI_REDUCTION
class MAT_POLYS_INTI_REDUCTION is
------------------- matrix reduction -----------
shared Pivot_lc:INTI; -- coefficient of highest term
shared ip,jp:CARD;
shared cv0:ARRAY{POLYS_INTI};
shared Mat:MAT_POLYS_INTI;
shared jPivot:ARRAY{CARD}; -- [1..ALEXMATmaxC]
shared p0:CARD;
shared polydegM:CARD;
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):CARD is
-- maximal degree in [p0..iDeg][p0..jDeg]
d:CARD:=0;
loop i::=p0.upto!(Mat.nr-1);
loop j::=p0.upto!(Mat.nc-1);
d:=d.max(Mat[i][jPivot[j]].degree.card);
end;
end;
return d;
end;
Sp(i,j:CARD, out deg:CARD,out Pivot_lc:INTI) is
ip:=i; jp:=j; cv0:=Mat[ip];
deg:=cv0[jPivot[j]].degree.card; Pivot_lc:=cv0[jPivot[j]].lc;
end;
SetPivotSearch(p0:CARD, polydeg:CARD, out deg:CARD, out Pivot_is_unit:BOOL) is
APivot,wPivot:INTI;
j1:CARD;
count:CARD:=0;
Sp(p0,p0, out deg,out Pivot_lc); Pivot_is_unit:=false;
cv0:=Mat[ip];
cv1:ARRAY{POLYS_INTI}:=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, out deg,out Pivot_lc); return; end;
end;
end;
-- Search unit
wPivot:=0.inti; Pivot_is_unit:=false; deg:=0;
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]=cv1[j1].lt) and
((~Pivot_is_unit)or(cv1[j1].degree<deg.int))
)
then Sp(i,j,out deg,out Pivot_lc); Pivot_is_unit:=true;
if (deg=0) then return; end;
end;
end;
end;
end;
if Pivot_is_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,out deg,out Pivot_lc); APivot:=Pivot_lc.abs;
end;
if (cv1[j1].is_zero.not)
and((i/=p0)or(j/=p0))
and (APivot>wPivot) then
if (deg.int>cv1[j1].degree)or(APivot>wPivot) then
Sp(i,j,out deg,out Pivot_lc); APivot:=Pivot_lc.abs;
end;
end;
end;
end;
return;
end; -- SetPivotSearch
SetPivot(p0:CARD, inout polydeg:CARD, out piv_is_unit:BOOL):BOOL is
-- Set Pivot_lc,jPivot: ip:=p0,jp:=jPivot[p0],cv0:=Mat[ip];
deg:CARD;
SetPivotSearch(p0,polydeg,out deg, out piv_is_unit); -- 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
j1:CARD;
-- set degree
d:INT:=-1; cv1::=Mat[i];
loop j::=p0.upto!(Mat.nc-1); j1:=jPivot[j];
if (cv1[j1].is_zero.not) then
if d.is_non_neg then d:=d.min(cv1[j1].low_deg);
else d:=cv1[j1].low_deg;
end;
end;
end;
if d.is_pos then --shift
loop j::=p0.upto!(Mat.nc-1); j1:=jPivot[j];
if (cv1[j1].is_zero.not) then
cv1[j1]:=cv1[j1].shift_deg(-d);
end;
end;
end;
end;
shiftL(j:CARD) is
-- shift degree to standard position
d:INT:=-1; j1:CARD:=jPivot[j];
-- set degree
loop i::=p0.upto!(Mat.nr-1);
if (Mat[i][j1].is_zero.not) then
if d.is_non_neg then d:=d.min(Mat[i][j1].low_deg);
else d:=Mat[i][j1].low_deg;
end;
end;
end;
if d.is_pos then --shift
loop i::=p0.upto!(Mat.nr-1);
if (Mat[i][j1].is_zero.not) then
Mat[i][j1]:=Mat[i][j1].shift_deg(-d);
end;
end;
end;
end;
SubC(i:CARD, inout polydegM:CARD, piv_is_unit:BOOL):BOOL is
j1:CARD;
d:INT;
s:INTI:=0.inti; spoly:POLYS_INTI;
cv1::=Mat[i]; flg:BOOL:=false;
if piv_is_unit then flg:=true;
loop
-- if cv0[jp].degree/=0 then #OUT+"!"; end;
if (cv1[jp].is_zero) then break!; end;
d:=cv1[jp].degree-cv0[jp].degree;
if d.is_neg then
loop j::=p0.upto!(Mat.nc-1);
cv1[jPivot[j]]:=cv1[jPivot[j]].shift_deg(-d);
end;
d:=0;
end;
s:=cv1[jp].lc/Pivot_lc;
spoly:=#POLYS_INTI(s,d.card);
loop j::=p0.upto!(Mat.nc-1); j1:=jPivot[j];
if cv0[j1].is_zero.not then
cv1[j1]:=cv1[j1]-(spoly*cv0[j1]);
end;
end;
end;
else
loop
if (cv1[jp].is_zero)or(cv1[jp].degree<cv0[jp].degree) then
break!;
end;
s:=cv1[jp].lc/Pivot_lc;
if s=0.inti then break!; end;
flg:=true;
d:=cv1[jp].degree-cv0[jp].degree;
spoly:=#POLYS_INTI(s,d.card);
loop j::=p0.upto!(Mat.nc-1); j1:=jPivot[j];
if cv0[j1].is_zero.not then
cv1[j1]:=cv1[j1]-(spoly*cv0[j1]);
end;
end;
end;
end;
if ~ flg then return false; end;
loop j::=p0.upto!(Mat.nc-1); shiftL(j); end;
shiftC(i);
-- set polydegM
loop j::=p0.upto!(Mat.nc-1); j1:=jPivot[j];
if (cv1[j1].is_zero.not)and(polydegM.int<cv1[j1].degree) then
polydegM:=cv1[j1].degree.card;
end;
end;
return true;
end;
SubL(j:CARD, inout polydegM:CARD):BOOL is
s:INTI:=0.inti; spoly:POLYS_INTI;
j1:CARD:=jPivot[j]; flg:BOOL:=false;
cv1:ARRAY{POLYS_INTI};
loop
--#OUT+"subL:1"+"\n";
if (cv0[j1].is_zero)or(cv0[j1].degree<cv0[jp].degree) then break!; end;
s:=(cv0[j1].lc/Pivot_lc);
if s=0.inti then break!; end;
d:CARD:=(cv0[j1].degree-cv0[jp].degree).card;
spoly:=#POLYS_INTI(s,d);
flg:=true;
loop i::=p0.upto!(Mat.nr-1); cv1:=Mat[i];
if cv1[jp].is_zero.not then
cv1[j1]:=cv1[j1]-(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].degree.card) then
polydegM:=cv1[j1].degree.card;
end;
end;
return true;
end;
reduce(inout mat:MAT_POLYS_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;
piv_is_unit:BOOL;
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_tmp::=polydegM;
--#OUT+"reduce4: setpivot"+"\n";
loop while!((polydeg_tmp>=0) and (~ SetPivot(p0,inout polydeg_tmp, out piv_is_unit)) );
if polydeg_tmp=0 then -- minimal?
mat:=Mat; jpivot:=jPivot; return;
end;
polydeg_tmp:=polydeg_tmp-1;
end;
if CheckZero(p0) then break!; end;
polydegM:=polydeg_tmp;
-- #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,piv_is_unit) or subFlg;
-- if (Pivot_lc.abs/=1)or(polydeg_tmp>0) then
-- WriteMatrix(p0);
--end;
end;
end;
if piv_is_unit then cv0[jp]:=POLYS_INTI::one; polydeg_tmp:=0;
loop j::=(p0+1).upto!(Mat.nc-1) ;
cv0[jPivot[j]]:=POLYS_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_tmp>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;