code_prm.sa
Generated by gen_html_sa_files from ICSI. Contact gomes@icsi.berkeley.edu for details
partial class KCODE{VERT}
partial class KCODE{VERT} is
-- class for KNOT, TCODE, RTCODE
attr k:ARRAY{VERT};
-- Note.
-- k[*]
-- sep={normal}: vertex of the projection.
-- (x,y):coord. of the point.
-- sep={normal,band}: vertex of the projection and end of a band.
-- (x,y):coord. of the point.
-- sep={crossing, under/over}: crossing pt.
-- (x,y):coord. of the crossing pt.
-- sep={separator,ks}:start of a knot.
-- (x,y):=(0,0)
-- sep={separator,ke}:end of a knot.
-- (x,y):=(0,0)
-- sep={separator,ts}:start of a band.
-- (x,y):=(0,0)
-- sep={separator,te}:end of a band.
-- (x,y):=(0,0)
--sep={separator,endc}:end of the code.
-- (x,y):=(0,0)
create:SAME is
res::=new;
res.k:=|#VERT(VERTEXC::code_e)|;
return res;
end;
clone:SAME is
res:SAME:=#; res.k:=#(k.size);
loop i::=k.ind!; res.k[i]:=k[i].clone; end;
return res;
end;
aget(i:CARD):VERT is
return k[i];
end;
aget(i:INT):VERT is
return k[i.card];
end;
aset(i:CARD, v:VERT) is
k[i]:=v;
end;
aset(i:INT, v:VERT) is
k[i.card]:=v;
end;
size:CARD is
return k.size;
end;
length:CARD is
-- code length __except terminator__.
return k.size-1;
end;
has_ind(i:CARD):BOOL is
return k.has_ind(i);
end;
has_ind(i:INT):BOOL is
return i.is_non_neg and has_ind(i.card);
end;
numbers_count(inout cr,inout cr_p,inout cr_n, inout compo,inout band:INT) is
-- # of crossings, knot , band in [stp..enp].
cr:=0; cr_p:=0; cr_n:=0; compo:=0; band:=0;
loop cod::=k.elt!.sep;
if VERTEXC::crossing.in(cod) then cr:=cr+1;
if VERTEXC::positive.in(cod) then cr_p:=cr_p+1;
elsif VERTEXC::negative.in(cod) then cr_n:=cr_n+1;
end;
elsif VERTEXC::ks.in(cod) then compo:=compo+1;
elsif VERTEXC::ts.in(cod) then band:=band+1;
end;
end;
cr:=cr/2; cr_p:=cr_p/2; cr_n:=cr_n/2;
end;
number_crossing:INT is
-- # of crossings
cr,cp,cn,k0,b0:INT;
numbers_count(inout cr,inout cp,inout cn,inout k0,inout b0);
return cr;
end;
number_positive_crossing:INT is
cr,cp,cn,k0,b0:INT;
numbers_count(inout cr,inout cp,inout cn,inout k0,inout b0);
return cp;
end;
number_negative_crossing:INT is
cr,cp,cn,k0,b0:INT;
numbers_count(inout cr,inout cp,inout cn,inout k0,inout b0);
return cn;
end;
number_writhe:INT is
cr,cp,cn,k0,b0:INT;
numbers_count(inout cr,inout cp,inout cn,inout k0,inout b0);
return cp-cn;
end;
number_compo:INT is
cr,cp,cn,k0,b0:INT;
numbers_count(inout cr,inout cp,inout cn,inout k0,inout b0);
return k0;
end;
endOfString(i:INT, dir:INT):INT is
cod:VERTEXC;
if ~has_ind(i) then return i; end;
if dir=1.int then cod:=VERTEXC::enp; else cod:=VERTEXC::stp; end;
loop while!(has_ind(i) and (cod*[i].sep).is_empty); i:=i+dir; end;
return i;
end;
has_band:BOOL is
return size>2 and VERTEXC::te.in(k[k.size-2].sep);
end;
has_band(p1,p2:INT):BOOL is
-- true if segment p1--p2 has band_attach pts.
loop i::=p1.upto!(p2);
if VERTEXC::band.in([i].sep) then return true; end;
end;
return false;
end;
bandStart:INT is
-- k.size-1 if band is not exist
if k.size<2 then return k.size.int-1; end;
if ~VERTEXC::te.in(k[k.size-2].sep) then return k.size.int-1; end;
loop i::=0.upto!(k.size-1);
if VERTEXC::ts.in(k[i].sep) then return i.int; end;
end;
raise "bansStart: missing band start.\n";
end;
compoStart(c:INT):INT is
-- start point of c-th component.
-- return -1, if #compo<c.
i:INT:=0.int;
loop c1::=1.int.up!;
if (c1=c) then return i; end;
i:=endOfString(i,1.int)+1.int;
if i>=length.int then return -1; end;
end;
end;
-------------- add/delete ------------------
CodeIn(v:VERT, i:CARD) pre (i<=k.size) is
-- move up and insert. 'normal vertex,(x=0,y=0),work=0.
--k:=k.resize(k.size+1);
--loop j::=(k.size-2).downto!(i); k[j+1]:=k[j]; end;
--k[i]:=v;
k:=ARRAY_EXT{VERT}::insert_at(i,k,v);
end;
CodeIn(c:VERTEXC, i:CARD) is
CodeIn(#VERT(c),i);
end;
CodeIn(c:VERTEXC, i:INT) pre i.is_neg.not is
CodeIn(c,i.card);
end;
CodeIn(i:CARD) is
CodeIn(#VERT,i);
end;
append(a:SAME) is
--s::=k.size-1; k:=k.resize(s+a.k.size);
--loop i::=0.upto!(a.k.size-1); k[i+s]:=a.k[i]; end;
k:=self.append(a).k;
end;
append(a:SAME):SAME is
--res:SAME:=clone; res.append(a); return res;
s::=k.size-1; res:SAME:=#; res.k:=#(s+a.k.size);
res.k.copy(k); res.k.copy(s,a.k); return res;
end;
append(v:VERT) is
CodeIn(v,k.size-1);
end;
CodeDel(i:CARD) pre (i<k.size) is
-- del the code not search for companion
--loop j::=i.upto!(k.size-2); k[j]:=k[j+1]; end;
--k:=k.resize(k.size-1);
k:=ARRAY_EXT{VERT}::delete_at(i,k);
end;
CodeDel(i:INT) pre (i.is_zero.not) is CodeDel(i.card); end;
cp(inout dist:INT, s_beg,s_end:INT, s_knot:SAME) is
j:INT;
d_end:INT:=dist+s_end-s_beg;
if (d_end+1)>k.size.int then k:=k.resize(d_end.card+1); end;
loop j:=s_beg.upto!(s_end); [dist]:=s_knot[j]; dist:=dist+1; end;
end;
CodeSplice(stp1,enp1,stp2,enp2:INT) is
-- splice the code stp1..enp1 and stp2..enp2, stp1<enp1, stp2<enp2
i:INT;
k1:SAME;
k1:=#;
if (stp1.is_non_neg)and(stp1<=enp1)and(enp1<size.int-1)and
(stp2.is_non_neg)and(stp2<=enp2)and(enp2<size.int-1)and
(enp1.min(enp2)<stp1.max(stp2))
then
k1:=clone;
-- i:=0; cp(0,minINT(stp1,stp2)-1);
i:=stp1.min(stp2);
cp(inout i,stp1,enp1,k1);
cp(inout i,stp2,enp2,k1);
cp(inout i,enp1.min(enp2)+1,stp1.max(stp2)-1,k1);
cp(inout i,enp1.max(enp2)+1,k1.size.int-1,k1);
end;
end;
-- StringSplice(i,j:INT) is
-- Splice and connect strings contains i and j.
-- Must be (end point of i)=(start of j)
-- not implemented.
CodeRev(p1,p2:INT) is
-- Reverse Knot[] codes between p1,p2, needed 0<=p1,p2<=maxK
Kcode:VERT;
i:INT;
if (p1.is_non_neg)and(p1<p2)and(p2<size.int-1) then
loop while!(p1<p2); -- swap
Kcode:=[p1]; [p1]:=[p2]; [p2]:=Kcode;
p1:=p1+1.int; p2:=p2-1;
end;
end;
end;
revK(i:INT) is
-- ori. reverse the string
j0, j1:INT;
j0:=endOfString(i,-1)+1; j1:=endOfString(i,1.int)-1;
CodeRev(j0,j1);
end;
rotBack1(stp, enp:INT) is
-- rotate back component of stp--enp by 1
if ~(VERTEXC::ks.in(k[stp].sep) and VERTEXC::ke.in(k[enp].sep) ) then
return;
end;
loop i::=(stp+1).upto!(enp-2); k[i]:=k[i+1]; end;
k[enp-1]:=k[stp+1].clone;
end;
rotComponent(stp, enp:INT, stp1:INT) is
-- rotate back component of stp--enp
-- move stp1 to head
if ~(VERTEXC::ks.in([stp].sep) and VERTEXC::ke.in([enp].sep) ) then
return;
end;
if (stp1<=stp)or(enp<=stp1) then return; end;
CodeRev(stp+1,enp-2);
CodeRev(stp+1,stp+enp-stp1-1);
CodeRev(stp+enp-stp1,enp-2);
[enp-1]:=[stp+1].clone;
end;
flip is
loop i::=k.ind!;
if VERTEXC::crossing.in([i].sep) then
[i].sep:=[i].sep.xor(VERTEXC::cross_exg);
end;
end;
end;
private bad(message:BOOL,num:CARD, i:INT) is
if message then
#OUT+"Bad code: "+num.str+", i="+i.str+"\n";
end;
end;
end; -- partial class KCODE{VERT}
partial class KCODE_CMP{VERT}
partial class KCODE_CMP{VERT} is
-- Use with include KCODE{VERT};
-- attr of VERT has sep,companion
check(print_message:BOOL):BOOL is
i,i1,i2:INT;
ic:INT;
code:VERTEXC;
msw::=print_message;
res:BOOL:=true;
if void(self) then bad(msw,0,0.int);return false; end;
if void(k) then bad(msw,1,0.int);return false; end;
if k.size=1 then -- TCODE is trivial
end;
loop i:=(0.upto!(k.size-1)).int;
code:=[i].sep;
ic:=[i].companion;
if VERTEXC::gs.in(code) then --10
elsif VERTEXC::ge.in(code) then --20
elsif VERTEXC::ks.in(code) then --30
i2:=endOfString(i,1.int);
i1:=endOfString(i2,-1);
if i/=[ic].companion then
bad(msw,30,i); res:=false;
elsif has_ind(i2).not then bad(msw,31,i); res:=false;
elsif has_ind(i1).not then bad(msw,32,i); res:=false;
elsif i/=i1 then bad(msw,33,i); res:=false;
elsif ~VERTEXC::ke.in([i2].sep) then
bad(msw,34,i); res:=false;
elsif ~VERTEXC::ks.in([i1].sep) then
bad(msw,35,i); res:=false;
elsif i2/=[i].companion then bad(msw,36,i); res:=false;
end;
elsif VERTEXC::ke.in(code) then --40
i1:=endOfString(i,-1);
i2:=endOfString(i1,1.int);
if i/=[ic].companion then
bad(msw,40,i); res:=false;
elsif has_ind(i2).not then bad(msw,41,i); res:=false;
elsif has_ind(i1).not then bad(msw,42,i); res:=false;
elsif i/=i2 then bad(msw,43,i); res:=false;
elsif ~VERTEXC::ke.in([i2].sep) then
bad(msw,44,i); res:=false;
elsif ~VERTEXC::ks.in([i1].sep) then
bad(msw,45,i); res:=false;
elsif i1/=[i].companion then bad(msw,46,i); res:=false;
end;
elsif VERTEXC::ts.in(code) then --50
i2:=endOfString(i,1.int);
i1:=endOfString(i2,-1);
if i/=[ic].companion then
bad(msw,50,i); res:=false;
elsif has_ind(i2).not then bad(msw,51,i); res:=false;
elsif has_ind(i1).not then bad(msw,52,i); res:=false;
elsif i/=i1 then bad(msw,53,i); res:=false;
elsif ~VERTEXC::te.in([i2].sep) then
bad(msw,54,i); res:=false;
elsif ~VERTEXC::ts.in([i1].sep) then
bad(msw,55,i); res:=false;
elsif ~VERTEXC::band.in([ic].sep) then
bad(msw,56,i);res:=false;
end;
elsif VERTEXC::te.in(code) then --60
i1:=endOfString(i,-1);
i2:=endOfString(i1,1.int);
if i/=[ic].companion then
bad(msw,60,i); res:=false;
elsif has_ind(i2).not then bad(msw,61,i); res:=false;
elsif has_ind(i1).not then bad(msw,62,i); res:=false;
elsif i/=i2 then bad(msw,63,i); res:=false;
elsif ~VERTEXC::te.in([i2].sep) then bad(msw,64,i);res:=false;
elsif ~VERTEXC::ts.in([i1].sep) then bad(msw,65,i);res:=false;
elsif ~VERTEXC::band.in([ic].sep) then
bad(msw,66,i);res:=false;
end;
elsif VERTEXC::crossing.in(code) then --70
if i/=[ic].companion then
bad(msw,70,i); res:=false;
end;
elsif VERTEXC::band.in(code) then --80
elsif VERTEXC::endc.in(code) then --90
if i/=(k.size-1).int then bad(msw,90,i); res:=false;
end;
end;
end;
if VERTEXC::code_e/=[size-1].sep then
bad(msw,1,size.int-1); res:=false;
end;
return res;
end;
printD is
-- print for debug
cod:VERTEXC;
#OUT+" companion,sep \n";
loop i::=0.upto!(k.size-1);
#OUT+i.str+":"+[i].companion.str+" ";
-- +k[i].gen.str+" "+k[i].compo.str+" ";
cod:=[i].sep;
if VERTEXC::normal.in(cod) then #OUT+"n"; end;
if VERTEXC::ks.in(cod) then #OUT+"["; end;
if VERTEXC::ke.in(cod) then #OUT+"]"; end;
if VERTEXC::ts.in(cod) then #OUT+"("; end;
if VERTEXC::te.in(cod) then #OUT+")"; end;
if VERTEXC::band.in(cod) then #OUT+"b"; end;
if VERTEXC::crossing.in(cod) then #OUT+"c"; end;
if VERTEXC::under.in(cod) then #OUT+"u"; end;
if VERTEXC::over.in(cod) then #OUT+"o"; end;
if VERTEXC::positive.in(cod) then #OUT+"+"; end;
if VERTEXC::negative.in(cod) then #OUT+"-"; end;
if VERTEXC::endc.in(cod) then #OUT+"/"; end;
#OUT+"\n";
end;
end;
numbers_seg_count(stp,enp:INT, inout cr,inout cr_p,inout cr_n, inout compo,inout band:INT) is
-- # of crossings, knot , band in [stp..enp]
cr:=0; cr_p:=0; cr_n:=0; compo:=0; band:=0;
loop i::=stp.upto!(enp);
if stp<[i].companion and [i].companion<enp then
cod::=[i].sep;
if VERTEXC::crossing.in(cod) then cr:=cr+1; end;
if VERTEXC::positive.in(cod) then cr_p:=cr_p+1;
elsif VERTEXC::negative.in(cod) then cr_n:=cr_n+1;
elsif VERTEXC::ks.in(cod) then compo:=compo+1;
elsif VERTEXC::ts.in(cod) then band:=band+1;
end;
end;
end;
cr:=cr/2.int;
cr_p:=cr_p/2.int;
cr_n:=cr_n/2.int;
end;
numbers_self_count(stp:INT, inout cr, inout cr_p,inout cr_n:INT)
pre VERTEXC::ks.in(k[stp].sep) or VERTEXC::ts.in(k[stp].sep)
is
-- self crossings
enp::=endOfString(stp,1.int);
k0,b0:INT;
numbers_seg_count(stp,enp, inout cr,inout cr_p,inout cr_n, inout k0,inout b0);
end;
number_self_crossing(stp:INT):INT is
cr,cp,cn:INT;
numbers_self_count(stp,inout cr,inout cp,inout cn);
return cr;
end;
number_self_writhe(stp:INT):INT is
cr,cp,cn:INT;
numbers_self_count(stp,inout cr,inout cp,inout cn);
return cp-cn;
end;
CodeInCmp(v:VERT, i:INT) is
-- CodeIn with trimming companion
[k.size-1].companion:=-1; -- endcode
k:=k.resize(k.size+1);
loop j::=(k.size.int-1).downto!(i+1);
[j]:=[j-1];
if has_ind([j].companion) then
[[j].companion].companion:=j;
end;
end;
[k.size-1].companion:=0.int; -- endcode
[i]:=v;
end;
CodeInCmp(v:VERT, i,n:INT) is
-- CodeIn with trimming companion
[k.size-1].companion:=-1; -- endcode
k:=k.resize((k.size.int+n).card);
loop j:INT:=(k.size.int-1).downto!(i+n);
[j]:=[j-n];
if has_ind([j].companion) then
[[j].companion].companion:=j;
end;
end;
[k.size-1].companion:=0.int; -- endcode
loop j:INT:=i.upto!(i+n-1);
[j]:=v.clone;
end;
end;
CodeInCmp(i:INT) is
CodeInCmp(#VERT(-1),i);
end;
CodeInCmp(i,n:INT) is
CodeInCmp(#VERT(-1),i,n);
end;
CodeDelCmp(i:INT) is
-- CodeDel with trimming companion
if (i<k.size.int-1)and has_ind([i].companion) then
[[i].companion].companion:=-1;
end;
[k.size-1].companion:=-1; -- endcode
loop j::=i.upto!(k.size.int-2);
[j]:=[j+1];
if has_ind([j].companion) then
[[j].companion].companion:=j;
end;
end;
k:=k.resize(k.size-1);
[size-1].companion:=0.int; -- endcode
end;
compoDelCmp(stp:INT) is
if ~ VERTEXC::ks.in([stp].sep) then return; end;
enp::=endOfString(stp,1.int);
loop [stp.up!]:=[(enp+1).upto!(length.int)]; end;
k:=k.resize(k.size+stp.card-enp.card-1);
loop i::=k.ind!;
c::=[i].companion;
if c<stp then
elsif stp<=c and c<=enp then c:=-1;
else c:=c-enp+stp-1;
end;
[i].companion:=c;
end;
loop i::=(k.size-1).downto!(0);
if ~has_ind([i].companion) then CodeDelCmp(i.int); end;
end;
end;
expCmp_n(pt:INT, s1,s2,s3:INT):INT is
if pt<s1 then return pt;
elsif pt<s2 then return pt+s3-s2;
elsif pt<s3 then return pt+s1-s2;
else return pt;
end;
end;
exgCmp(s1,s2,s3:INT) pre (s1.is_non_neg)and(s1<=s2)and(s2<=s3)and(s3<=length.int) is
-- Exchange blocks (s1..s2-1) and (s2..s3-1).
-- Assume that 0<= s1 <= s2 <= s3 <= length
if s1=s2 then return; end;
CodeRev(s1,s2-1);
CodeRev(s2,s3-1);
CodeRev(s1,s3-1);
loop i::=0.upto!(k.size-2);
[i].companion:=expCmp_n([i].companion,s1,s2,s3);
end;
end;
rotOvCmp(stp:INT):INT is
-- return moved length
-- move start points until
-- the first crossing of the specified component
-- is over cross
enp,p1:INT;
if ~VERTEXC::ks.in([stp].sep) then return 0; end;
p1:=stp+1; enp:=[stp].companion;
loop while!(VERTEXC::over.in([p1].sep)
or VERTEXC::under.in([p1+1].sep)) ;
p1:=p1+1;
end;
if VERTEXC::under.in([p1].sep)
and VERTEXC::over.in([p1+1].sep) then
exgCmp(stp+1,p1+1,enp);
end;
return p1-stp;
end;
rotateToOverCmp is
-- Attach "rotOV" to each component.
-- move start points until
-- the first crossing of each component is overcross.
tPtr,i:INT;
tPtr:=0.int;
loop
i:=rotOvCmp(tPtr);
tPtr:=[tPtr].companion+1.int;
until!(VERTEXC::endc.in([tPtr].sep));
end;
end;
sCompoCmp(stp:INT) is
--move sepcified component to the top of TCode
--stp points a head of a component. move the component to the first
if (~ VERTEXC::ks.in([stp].sep))or(stp.is_zero) then return; end;
exgCmp(0.int, stp, [stp].companion+1);
end;
revKCmp_num(n,j0,j1:INT):INT is
if n<j0 then return n;
elsif n<=j1 then return j0+j1-n;
else return n;
end;
end;
revKCmp(i:INT) is
-- ori. reverse the string
j0, j1,j:INT;
j0:=endOfString(i,-1)+1; j1:=endOfString(i,1.int)-1;
if j0<j1 then
CodeRev(j0,j1);
loop i:=j0.upto!(j1);
j:=revKCmp_num([i].companion,j0,j1);
[j].companion:=i;
if j0<=j and j<=j1 then
else
[i].sep:=[i].sep.xor(VERTEXC::cross_exs);
[j].sep:=[j].sep.xor(VERTEXC::cross_exs);
end;
end;
end;
end;
end; -- partial class KCODE_CMP{VERT}