import java.applet.Applet; import java.awt.*; import java.awt.event.*; import java.applet.*; import java.awt.geom.*; import java.math.*; public class ComputeArithmeticGraph implements Runnable { Manager M; Complex SOURCE; int halt; double A; int[][] LIST=new int[2][100000]; int LOW=0; int CLOSED=0; public ComputeArithmeticGraph() { } public ComputeArithmeticGraph(Complex z,Manager MM) { this.SOURCE=new Complex(z.x,z.y); this.M=MM; } public void run() { int mode=M.C.CON_G.getOption(); int p=M.C.SES.getNumerator(); int q=M.C.SES.getDenominator(); if(mode< 4) LOW=0; if(mode==0) orbitPlot2(); //both directions if(mode==1) orbitPlot(0); //forwards if(mode==2) orbitPlot(1); //backwards if(mode==3) periodPlot(p,q,0,0,0,1); //period plot if(mode==4) pivotPlot(); //pivot arc if(mode==5) monsterPlot(); //all even predecessors if(mode==6) lowPlot(0); //all even low components if(mode==7) lowPlot(1); //all odd low components if(mode==8) blockPlot1(); //block plot if(mode==9) blockPlot2(); //block plot if(mode==10) comparePlot(); //comparison } public void sendMessage(int c) { if((c>0)&&(c%100==0)) { Integer COUNT=new Integer(c); M.C.PROGRESS=COUNT.toString(); M.C.repaint(); } } /***********plotting routines**********/ public GeneralPath straighten(int p,int q,GeneralPath gp1) { return(gp1); } public void orbitPlot(int direction) { int m=(int)(SOURCE.x); int n=(int)(SOURCE.y); int p=M.C.SES.getNumerator(); int q=M.C.SES.getDenominator(); int parity=(direction+m+n+100000)%2; periodPlot(p,q,m,n,parity,0); } public void orbitPlot2() { int m=(int)(SOURCE.x); int n=(int)(SOURCE.y); int p=M.C.SES.getNumerator(); int q=M.C.SES.getDenominator(); periodPlot2(p,q,m,n,0); } /*STOP=1 -- plot 1 period in the unstable case. STOP=0 -- no constraints */ public void periodPlot(int p,int q,int m,int n,int dir,int STOP) { CLOSED=0; GeneralPath gp=getPeriodPlot(p,q,m,n,dir,STOP); int style=M.C.CON_G.STYLE.mode; if(CLOSED==0) style=0; gp=straighten(p,q,gp); M.R.nextPathLast(gp,style); M.R.repaint(); } public void periodPlot2(int p,int q,int m,int n,int STOP) { CLOSED=0; GeneralPath gp=getPeriodPlot(p,q,m,n,0,STOP); if(CLOSED==0) { GeneralPath gp2=getPeriodPlot(p,q,m,n,1,STOP); gp.append(gp2,false); } int style=M.C.CON_G.STYLE.mode; if(CLOSED==0) style=0; gp=straighten(p,q,gp); M.R.nextPathLast(gp,style); M.R.repaint(); } public GeneralPath getPeriodPlot(int pp,int qq,int m,int n,int dir,int STOP) { GeneralPath gp=new GeneralPath(); A=1.0*pp/qq; ArithmeticPoint P1=new ArithmeticPoint(m,n,-1); ArithmeticPoint P2=new ArithmeticPoint(m,n,-1); double LIM=M.C.CON_G.getLimit(); int count=0; int closed=0; halt=1; gp.moveTo(P1.m,P1.n); while((halt==1)&&(count1) { M.C.CS.C=C[parity]; periodPlot(p,q,0,0,0,1); int[] x=MathRational.evenPredecessor(p,q); p=x[0]; q=x[1]; parity=(parity+1)%3; } } } /*These routines measure the location of a point with respect to the floor grid.*/ public static double linearV0(int p,int q,double m,double n) { double a=p*m+q*n; return(a); } public static double linearV(int p,int q,double m,double n) { double a=linearV0(p,q,m,n); double b=linearV0(p,q,0,.5*(p+q)); double t=0.5; if((p+q)%2==0) t=1.0; return(t*a/b); } public static double linearW0(int p,int q,double m,double n) { double a=2*p*q; double b=2*p*q+q*q-p*p; double f=-b*m+a*n; return(f); } public static double linearW(int p,int q,double m,double n) { double t=1.0; if((p+q)%2==0) t=2.0; double a=linearW0(p,q,m,n); double b=linearW0(p,q,q,-p); return(t*a/b); } public void blockPlot1() { double A=M.C.SES.getParameter(); ArithmeticGraphLocal L; int i2=(int)(SOURCE.x); int j2=(int)(SOURCE.y); GeneralPath gp=new GeneralPath(); int LIM1=M.C.CON_G.getWidthLimit(); int LIM2=M.C.CON_G.getHeightLimit(); int i,j; i=-LIM1; j=-LIM2; halt=1; while((j=0;--ii) { if((i==LIST[0][ii])&&(j==LIST[1][ii])) test=1; } parity=(i+j+100001)%2; if((test==0)&&(parity==choice)) { periodPlot(p,q,i,j,0,1); } } halt=0; LOW=0; M.R.repaint(); } /** routines associated to the return map */ public Complex toComplex(ArithmeticPoint P,double AA) { double d=2*AA*P.m+2*P.n+.00000001; return(new Complex(d,P.y)); } public ArithmeticPoint firstReturn(ArithmeticPoint P,double AA,int direction) { PinwheelMap RM=new PinwheelMap(AA); int[] ret=new int[3]; ArithmeticPoint PP=new ArithmeticPoint(P); if(direction==1) PP.y=-P.y; Complex z=toComplex(PP,AA); ret=RM.doReturnIntegral(z); ArithmeticPoint Q=new ArithmeticPoint(P.m+ret[0],P.n+ret[1],ret[2]); if(direction==1) Q.y=-Q.y; return(Q); } public ArithmeticGraphLocal doLocal(int i,int j,double AA) { ArithmeticGraphLocal L=new ArithmeticGraphLocal(); ArithmeticPoint P1=new ArithmeticPoint(i,j,-1); ArithmeticPoint P2=new ArithmeticPoint(); ArithmeticPoint P3=new ArithmeticPoint(); Complex test=toComplex(P1,AA); P2=firstReturn(P1,AA,0); P3=firstReturn(P1,AA,1); L.x[0]=P2.m-P1.m; L.x[1]=P2.n-P1.n; L.x[2]=P3.m-P1.m; L.x[3]=P3.n-P1.n; L.gp=new GeneralPath(); L.gp.moveTo(P1.m,P1.n); L.gp.lineTo(P2.m,P2.n); L.gp.moveTo(P1.m,P1.n); L.gp.lineTo(P3.m,P3.n); L.gp.closePath(); return(L); } /*This is just a wrapper class for a pair of integers and a double*/ public class ArithmeticPoint { int m,n; double y; public ArithmeticPoint() {} public ArithmeticPoint(ArithmeticPoint P) { m=P.m; n=P.n; y=P.y; } public ArithmeticPoint(int mm,int nn,double yy) { m=mm; n=nn; y=yy; } public int testLow(double A) { double t1=A*m+n; double t2=t1-1; if(t1<0) return(0); if(t2>0) return(0); return(1); } } }