import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.awt.geom.*;
import java.math.*;
public class TorusMap {
public TorusMap() {}
/**lattice reduction algorithms*/
public static double fractionalPart(double x) {
return(x-Math.floor(x));
}
public static double fractionalPart(double d,double x) {
double y=d*fractionalPart(x/d);
return(y);
}
public static double[] reduceLattice(double A,double x1,double x2,double x3) {
double r1=reduce(-1,1,x1,x3);
double r2=reduce(-1,1,x2,x3);
double n1=reduce(1-A,1+A,r1,r2); //x
double X1=fractionalPart(1+A,n1); //x
double X2=fractionalPart(1+A,r2); //y
double[] z={X1,X2,x3-Math.floor(x3)};
return(z);
}
public static double reduce(double v1,double v2,double x1,double x2) {
double number=Math.floor(x2/v2);
return(x1-v1*number);
}
/**torus classifying maps*/
public static Complex phiPlus(double A,double t) {
double s=0.5*t;
double[] a=reduceLattice(A,s,s+1,s);
Complex z=new Complex(a[0],a[1]);
return(z);
}
public static Complex phiMinus(double A,double t) {
double s=0.5*t;
double[] a=reduceLattice(A,s-1,s,s);
Complex z=new Complex(a[0],a[1]);
return(z);
}
/*3D versions*/
public static double[] phiPlus3D(double A,double m,double n) {
double s=A*m+n;
double[] a=reduceLattice(A,s,s+1,s);
return(a);
}
public static double[] phiPlus3D(double A,double t) {
double s=.5*t;
double[] a=reduceLattice(A,s,s+1,s);
return(a);
}
public static double[] phiMinus3D(double A,double t) {
double s=.5*t;
double[] a=reduceLattice(A,s-1,s,s);
return(a);
}
public static double[] phiMinus3D(double A,double m,double n) {
double s=A*m+n;
double[] a=reduceLattice(A,s-1,s,s);
return(a);
}
/**4D version -- under development */
public static double[] phi4D(double A,double t,double u) {
double[] x2={1-A,1+A,0,0};
double[] x3={.5*(t+u-1),.5*(t+u+1),.5*(t-u+1)};
double u1=.5*u+.5;
double[] a=reduceLattice4D(A,x3[0]-u1*x2[0],x3[1]-u1*x2[1],x3[2]-u1*x2[2]);
return(a);
}
public static Complex phiPlus4D(double A,double t,double u) {
double[] x2={1-A,1+A,0,0};
double[] x3={.5*(t+u-1),.5*(t+u+1),.5*(t-u+1)};
double u1=.5*u+.5;
double[] a=reduceLattice4D(A,x3[0]-u1*x2[0],x3[1]-u1*x2[1],x3[2]-u1*x2[2]);
Complex z=new Complex(a[0],a[1]);
return(z);
}
public static Complex phiMinus4D(double A,double t,double u) {
double[] x2={1-A,1+A,0,0};
double[] x3={.5*(t+u-1),.5*(t+u+1),.5*(t-u+1)};
x3[0]=x3[0]-1;
x3[1]=x3[1]-1;
double u1=.5*u+.5;
double[] a=reduceLattice4D(A,x3[0]-u1*x2[0],x3[1]-u1*x2[1],x3[2]-u1*x2[2]);
Complex z=new Complex(a[0],a[1]);
return(z);
}
public static double[] reduceLattice4D(double A,double x1,double x2,double x3) {
double r1=reduce(-2,2,x1,x3);
double r2=reduce(-2,2,x2,x3);
double n1=reduce(1-A,1+A,r1,r2); //x
double X1=fractionalPart(1+A,n1); //x
double X2=fractionalPart(1+A,r2); //y
double[] z={X1,X2,x3-Math.floor(x3)};
return(z);
}
public static int[] finalPlus(double A,double m,double n) {
double t=2*A*m+2*n+.00000001;
double[] d=phiPlus3D(A,t);
int[] N=characteristics(A,d[0],d[1],d[2]);
N[0]=0;
int[] s=new int[2];
s[0]=getX(N[0],N[1],N[2],N[3],N[4]);
s[1]=getY(N[0],N[1],N[2],N[3],N[4]);
return(s);
}
public static int[] finalMinus(double A,double m,double n) {
double t=2*A*m+2*n+.00000001;
double[] d=phiMinus3D(A,t);
int[] N=characteristics(A,d[0],d[1],d[2]);
N[0]=1;
int[] s=new int[2];
s[0]=getX(N[0],N[1],N[2],N[3],N[4]);
s[1]=getY(N[0],N[1],N[2],N[3],N[4]);
return(s);
}
public static int[] finalPlus(double A,double t) {
double[] d=phiPlus3D(A,t);
int[] N=characteristics(A,d[0],d[1],d[2]);
N[0]=0;
int[] s=new int[2];
s[0]=getX(N[0],N[1],N[2],N[3],N[4]);
s[1]=getY(N[0],N[1],N[2],N[3],N[4]);
return(s);
}
public static int[] finalMinus(double A,double t) {
double[] d=phiMinus3D(A,t);
int[] N=characteristics(A,d[0],d[1],d[2]);
N[0]=1;
int[] s=new int[2];
s[0]=getX(N[0],N[1],N[2],N[3],N[4]);
s[1]=getY(N[0],N[1],N[2],N[3],N[4]);
return(s);
}
public static int getSwap(int s0,int s1,int N0,int N1) {
if(N1==3) return(0);
int n=2-N0;
if(N1==0) {
if((s0==1)&&(s1>-1)) return(n);
}
if(N1==1) {
if((s0==1)&&(s1>-1)) return(n);
if((s0==-1)&&(s1<1)) return(n);
}
if(N1==2) {
if((s0==-1)&&(s1<1)) return(n);
}
return(0);
}
public static double[] exchange(double A,double[] x) {
int[] N=characteristics(A,x[1],x[2],x[3]);
N[0]=(int)(x[0]);
int[] s=new int[2];
s[0]=getX(N[0],N[1],N[2],N[3],N[4]);
s[1]=getY(N[0],N[1],N[2],N[3],N[4]);
double[] y=new double[4];
double t1=s[0]*A+s[1];
double[] yy=new double[3];
int fin=TorusMap.getSwap(s[0],s[1],N[0],N[1]);
if(fin==0) {
yy=reduceLattice(A,x[1]+t1,x[2]+t1,x[3]+t1);
y[0]=x[0];
}
if(fin==1) {
yy=reduceLattice(A,x[1]+t1+1,x[2]+t1+1,x[3]+t1);
y[0]=1-x[0];
}
if(fin==2) {
yy=reduceLattice(A,x[1]+t1-1,x[2]+t1-1,x[3]+t1);
y[0]=1-x[0];
}
y[1]=yy[0];
y[2]=yy[1];
y[3]=yy[2];
return(y);
}
/**determining the local types */
public static int[] characteristics(double A,double x,double y,double z) {
int[] N=new int[5];
N[1]=0;
if((zA)&&(z<1-A)) N[1]=1;
if((z>A)&&(z>1-A)) N[1]=2;
if((z1-A)) N[1]=3;
N[2]=2;
if(x<1) N[2]=1;
if(xy))) return(1);
return(0);
}
public static int getY(int mode,int region,int x,int y,int t) {
if(((region==3)||(region==0))&&(mode==0)) {
if(x==0) return(1);
if((x==1)&&(t!=0)) return(1);
}
if(((region==0)||(region==1))&&(mode==1)) {
if((x>0)&&(t!=0)) return(-1);
if((y==0)&&(x<2)&&(t==0)) return(1);
}
if(((region==1)||(region==2))&&(mode==0)) {
if((x<2)&&(t!=0)) return(1);
if((y==2)&&(x>0)&&(t==0)) return(-1);
}
if(((region==2)||(region==3))&&(mode==1)) {
if(x==2) return(-1);
if((x==1)&&(t!=0)) return(-1);
}
return(0);
}
}