sl2p.sa


Generated by gen_html_sa_files from ICSI. Contact gomes@icsi.berkeley.edu for details
 


class SL2P < $IS_LT{SL2P},$STR,$HASH

class SL2P < $IS_LT{SL2P},$STR,$HASH is -- MAT2P with determinant=1. include COMPARABLE; include MAT2{FINITE_FIELD}; include MAT2_F2{FINITE_FIELD} inverse->inverse_mat; include MAT2_PSL{FINITE_FIELD}; include MAT2P_ALG{FINITE_FIELD}; include MAT2_DIA_ORDER{FINITE_FIELD}; get_list:ARRAY{SAME} is a:ARRAY{SAME}:=#; loop a:=a.append(|#SAME(0.int,1.int,-1,0.int).up_sl!|); end; return a; end; end;

class MAT2P < $IS_LT{MAT2P},$STR,$HASH

class MAT2P < $IS_LT{MAT2P},$STR,$HASH is include COMPARABLE; include MAT2{FINITE_FIELD}; include MAT2_F2{FINITE_FIELD}; include MAT2P_ALG{FINITE_FIELD}; end;

partial class MAT2P_ALG{ET}

partial class MAT2P_ALG{ET} is -- assume thet ET is finite field F(p). shared base:INT; -- prime set_base(p:INT) is base:=#(p); ET::set_base(base); end; create(a,b,c,d:INT):SAME is res:SAME:=#; res.m[0][0]:=#(a); res.m[0][1]:=#(b); res.m[1][0]:=#(c); res.m[1][1]:=#(d); return res; end; one:SAME is return #(1.int,0.int,0.int,1.int); end; zero:SAME is return #(0.int,0.int,0.int,0.int); end; hash:CARD is p::=m[0][0].p; return (((m[0][0].n*p+m[0][1].n)*p+m[1][0].n)*p+m[1][1].n).hash; end; is_one:BOOL is return m[0][0].is_one and m[0][1].is_zero and m[1][0].is_zero and m[1][1].is_one; end; times(i:INT):SAME is return self*(#ET(i)); end; div(i:INT):SAME is return div(#ET(i)); end; next_mat:SAME is -- consist with is_lt p00::=m[0][0]; p01::=m[0][1]; p10::=m[1][0]; p11::=m[1][1]+1.int; if p11.is_zero then p10:=p10+1.int; if p10.is_zero then p01:=p01+1.int; if p01.is_zero then p00:=p00+1.int; if p00.is_zero then return zero; end; end; end; end; return #(p00,p01,p10,p11); end; up_mat!:SAME is res::=self; loop yield res; res:=res.next_mat; if res.is_zero then break!; end; end; end; next_sl:SAME pre det.is_one is -- ireturn (0,0:0,0) when end. p00::=m[0][0]; p01::=m[0][1]; p10::=m[1][0]; p11::=m[1][1]; if p00.is_zero then p11:=p11+1.int; if p11.is_zero then p01:=p01+1.int; if p01.is_zero then return #(1.int,0.int,0.int,1.int); else return #(p00,p01,-p01.inverse,p11); end; else return #(p00,p01,p10,p11); end; else p10:=p10+1; if p10.is_zero then p01:=p01+1.int; if p01.is_zero then p00:=p00+1.int; if p00.is_zero then return zero; end; end; end; return #(p00,p01,p10,(p01*p10+1.int)/p00); end; end; up_sl!:SAME pre det.is_one post result.det.is_one is res::=self; loop yield res; res:=res.next_sl; if res.is_zero then break!; end; end; end; end;

class SL2P_CNJ_CLS

class SL2P_CNJ_CLS is -- list conjugate classes of SL2(p) in MAP2P. attr cls:ARRAY{ARRAY{SL2P}}; -- conjugate class --> list of matrix attr map:MAP{SL2P,CARD}; -- matrix --> conjugate class private is_lt_mat(s1,s2:SL2P):BOOL is return s1.is_lt_dia(s2); end; --return s1.is_lt(s2); private is_lt_cls(a1,a2:ARRAY{SL2P}):BOOL is return is_lt_mat(a1[0],a2[0]); end; create:SAME is res:SAME:=new; res.set_cnj_cls; return res; end; private set_cnj_cls is list::=SL2P::get_list; map:=#; loop map[list.elt!]:=0; end; cls:=#; map_work::=map.copy; loop k::=map.ind!; if k.det.is_one.not then #OUT+"set_cnj_cls: k="+k.str+"\n"; end; if map_work.has_ind(k) then cls:=cls.append(#ARRAY{SL2P}); ci::=cls.size-1; loop kl::=list.elt!; c::=k.conjugate(kl); if c.det.is_one.not then #OUT+"set_cnj_cls: c="+c.str+"="+kl.str+"*"+k.str+"*"+kl.inverse.str+"\n"; end; if map_work.has_ind(c) then cls[ci]:=cls[ci].append(|c|); map_work.delete(c); end; end; end; end; loop c::=cls.ind!; cls[c].insertion_sort_by(bind(is_lt_mat(_,_))); end; cls.insertion_sort_by(bind(is_lt_cls(_,_))); map:=#; loop c::=cls.ind!; loop map[cls[c].elt!]:=c; end; end; end; str:STR is s::=""; loop c::=cls.ind!; s:=s+"class# "+c.str+" : "; loop s:=s+" "+cls[c].elt!.str; end; s:=s+"\n"; end; return s; end; str(lib : LIBCHARS) : STR is return str; end; end;

partial class MAT2_PSL{ET}

partial class MAT2_PSL{ET} is -- assume that det=1.(Positive Special Linear) inverse:SAME --pre det.is_one post times(result).is_one is return cofactor_matrix; end; end;

partial class MAT2_F2{ET}

partial class MAT2_F2{ET} is -- ET is field div(i:ET):SAME is return #(m[0][0]/i,m[0][1]/i,m[1][0]/i,m[1][1]/i); end; inverse:SAME is return cofactor_matrix/det; end; div(o:SAME):SAME is return self*(o.inverse); end; conjugate(o:SAME):SAME is -- o * self * o~ return o*self/o; end; conjugateR(o:SAME):SAME is -- o~ * self * o res::=o.inverse*self*o; return o.inverse*self*o; end; end;

partial class MAT2_DIA_ORDER{ET}

partial class MAT2_DIA_ORDER{ET} is -- alternate ordering with diagonal part preference. -- Diagonal or Jordan form is less than others in the same conjugacy class. is_lt_dia(o:SAME):BOOL is return compare_dia(o)=-1; end; ET_compare_dia(e1,e2:ET):INT is -- e1<e2 means near with zero. e1a::=e1.abs; e2a::=e2.abs; if e1a<e2a then return -1; elsif e1a>e2a then return 1.int; elsif e1<e2 then return -1; elsif e1>e2 then return 1.int; else return 0.int; end; end; compare_dia(o:SAME):INT is -- lexicographical order of [1][0], [0][1], [0][0], [1][1] c::=ET_compare_dia(m[1][0],o.m[1][0]); if c.is_non_zero then return c; end; c:=ET_compare_dia(m[0][1],o.m[0][1]); if c.is_non_zero then return c; end; c:=ET_compare_dia(m[0][0],o.m[0][0]); if c.is_non_zero then return c; end; c:=ET_compare_dia(m[1][1],o.m[1][1]); return c; end; end;

partial class MAT2{ET}

partial class MAT2{ET} is attr m:ARRAY{ARRAY{ET}}; aset(i1,i2:CARD,val:ET) is m[i1][i2]:=val; end; aget(i1,i2:CARD):ET is return m[i1][i2]; end; create:SAME is res:SAME:=new; res.m:=#(2); res.m[0]:=#(2); res.m[1]:=#(2); return res; end; create(a,b,c,d:ET):SAME is res:SAME:=#; res.m[0][0]:=a; res.m[0][1]:=b; res.m[1][0]:=c; res.m[1][1]:=d; return res; end; copy:SAME is return #(m[0][0].copy,m[0][1].copy,m[1][0].copy,m[1][1].copy); end; is_eq(o:SAME):BOOL is return (m[0][0]=o.m[0][0])and(m[0][1]=o.m[0][1])and(m[1][0]=o.m[1][0])and(m[1][1]=o.m[1][1]); end; is_zero:BOOL is return m[0][0].is_zero and m[0][1].is_zero and m[1][0].is_zero and m[1][1].is_zero; end; is_lt(o:SAME):BOOL is -- lexicographical order of [0][0], [0][1], [1][0], [1][1] if m[0][0]<o.m[0][0] then return true; elsif m[0][0]>o.m[0][0] then return false; elsif m[0][1]<o.m[0][1] then return true; elsif m[0][1]>o.m[0][1] then return false; elsif m[1][0]<o.m[1][0] then return true; elsif m[1][0]>o.m[1][0] then return false; elsif m[1][1]<o.m[1][1] then return true; elsif m[1][1]>o.m[1][1] then return false; else return false; end; end; str:STR is s::="("+m[0][0].str+", "+m[0][1].str+" : "+m[1][0].str+", "+m[1][1].str+")"; return s; end; str(lib : LIBCHARS) : STR is return str; end; det:ET is return m[0][0]*m[1][1]-m[1][0]*m[0][1]; end; negate:SAME is return #(-m[0][0],-m[0][1],-m[1][0],-m[1][1]); end; plus(o:SAME):SAME is return #(m[0][0]+o.m[0][0],m[0][1]+o.m[0][1],m[1][0]+o.m[1][0],m[1][1]+o.m[1][1]); end; minus(o:SAME):SAME is return #(m[0][0]-o.m[0][0],m[0][1]-o.m[0][1],m[1][0]-o.m[1][0],m[1][1]-o.m[1][1]); end; times(o:SAME):SAME is return #(m[0][0]*o.m[0][0]+m[0][1]*o.m[1][0],m[0][0]*o.m[0][1]+m[0][1]*o.m[1][1], m[1][0]*o.m[0][0]+m[1][1]*o.m[1][0],m[1][0]*o.m[0][1]+m[1][1]*o.m[1][1]); end; times(i:ET):SAME is return #(m[0][0]*i,m[0][1]*i,m[1][0]*i,m[1][1]*i); end; cofactor_matrix:SAME is return #(m[1][1],-m[0][1],-m[1][0],m[0][0]); end; end;

class TEST_MAT2P

class TEST_MAT2P is include TEST; test_mat2p is class_name("MAT2P"); p:INT:=11.int; MAT2P::set_base(p); m,m1,m2:MAT2P; m:=#(1.int,2.int,3.int,4.int); test("create",m.str,"(1, 2 : 3, 4)"); test("negate",(-m).str,"(10, 9 : 8, 7)"); test("copy",(m.copy=m).str,"true"); test("det",m.det.str,"9"); m1:=#(2.int,3.int,4.int,5.int); test("is_zero",(m1.is_zero).str,"false"); test("is_eq",(m1=m).str,"false"); test("is_eq",(m=m).str,"true"); test("is_lt",(m>m1).str,"false"); test("is_lt",(m<m1).str,"true"); test("plus",(m+m1).str,"(3, 5 : 7, 9)"); test("minus",(m1-m).str,"(1, 1 : 1, 1)"); test("times",(m*m1).str,"(10, 2 : 0, 7)"); test("times",(m*2.int).str,"(2, 4 : 6, 8)"); test("cofactor",m.cofactor_matrix.str,"(4, 9 : 8, 1)"); test("det.inverse",m.det.inverse.str,"5"); test("inverse",m.inverse.str,"(9, 1 : 7, 5)"); test("times inverse",(m*(m.inverse)).str,MAT2P::one.str); test("div by int",(m/2.int).str,"(6, 1 : 7, 2)"); test("div times",((m/m1)*m1).str,m.str); test("div times",(m/m1).str,"(7, 5 : 6, 6)"); finish; end; test_sl2p is class_name("SL2P"); p:INT:=3.int; m,m1,m2:SL2P; SL2P::set_base(p); m:=#(1.int,2.int,2.int,5.int); #OUT+m.str+".up_mat!: det="+m.det.str+"\n"; #OUT.flush; loop m1:=m.up_mat!; #OUT+m1.str+"\n"; #OUT.flush; end; #OUT+m.str+".up_sl: det="+m.det.str+"\n"; #OUT.flush; loop m1:=m.up_sl!; #OUT+m1.str+"\n"; #OUT.flush; end; m:=#(0.int,1.int,-1,0.int); #OUT+m.str+".up_sl!\n"; #OUT.flush; loop m1:=m.up_sl!; #OUT+m1.str+"\n"; #OUT.flush; end; -- print conjugate class SL2P::set_base(5.int); #OUT+#SL2P_CNJ_CLS.str; end; main is test_mat2p; test_sl2p; end; end;