import java.applet.Applet;
import java.awt.event.*;
import java.awt.*;

/**This class does the basic arithmetic of complex numbers */

public class Symmetrize implements Runnable {
    boolean HALT;

    public Symmetrize() {
	HALT=true;
    }


    public void run() {
	HALT=false;
	double min=100;
	long count=0;
	long count2=0;
	while(HALT==false) {
	   double test=Symmetrize.doTest();
	   if(count==1000000) {
                 System.out.println(count2+" million: min="+min);
		 count=0;
		 ++count2;
	   }
	   ++count;
	   if(min>test) min=test;
	}
	System.out.println("done");
    }


    public static double doTest() {
	double e=1+15*Math.random();
	return doTest(e);
    }

    public static double doTest(double e) {
	Complex[] z=RandomGenerator.randomConfig();
	Complex[] w=symm(z);
	Vector[] V=toVector(z);
	Vector[] W=toVector(w);
	double test1=energy(e,V);
	double test2=energy(e,W);
	double test=test1/test2; 
	if(test<1) System.out.println("exp "+e);
	return test;
    }

    public static double doTestX(double e) {
	Complex[] z=RandomGenerator.randomConfig();
	Vector[] V=toVector(z);
	Vector[] W=Symmetrize.symm(V);
	double test1=energy(e,V);
	double test2=energy(e,W);
	double test=test1/test2; 
	if(test<1) System.out.println("exp "+e);
	return test;
    }

    public static double energy(double e,Complex[] z) {
    Vector[] V=toVector(z);
	return energy(e,V);
    }

    public static Vector[] toVector(Complex[] z) {
	Vector[] V=new Vector[5];
	for(int i=0;i<4;++i) V[i]=Vector.inverseStereo(z[i]);
	V[4]=new Vector(0,0,1);
	return V;
    }


    public static double energy(double e,Vector[] V) {
	double total=0;
	for(int i=0;i<5;++i) {
	    for(int j=i+1;j<5;++j) {
		total=total+interaction(e,V[i],V[j]);
	    }
	}
	return(total);
    }

    public static double interaction(double e,Vector V1,Vector V2) {
	double d=Vector.distSquared(V1,V2);
	d=Math.pow(d,-e/2);
	return(d);
    }

    public static Vector twirl(Vector V) {
	Vector W=new Vector(-V.x[0],-V.x[1],V.x[2]);
	return W;
    }

    public static Vector interpolate(Vector V1,Vector V2) {
	Vector W=Vector.plus(V1,V2);
	double d=Math.sqrt(Vector.dot(W,W));
	for(int i=0;i<3;++i) W.x[i]=W.x[i]/d;
	double test=Vector.dot(W,W);
	return W;
    }

    public static Vector[] symm(Vector[] V) {
	Vector[] W=new Vector[5];
	W[4]=new Vector(0,0,1);
	W[0]=interpolate(V[0],twirl(V[2]));
	W[1]=interpolate(V[1],twirl(V[3]));
	W[2]=twirl(W[0]);
	W[3]=twirl(W[1]);
	return W;
    }

    public static Complex[] symm(Complex[] z) {
	Complex[] w=new Complex[4];
	for(int i=0;i<4;++i) w[i]=new Complex();
	w[0].x=(z[0].x-z[2].x)/2;
	w[0].y=(z[0].y-z[2].y)/2;
	w[1].x=(z[1].x-z[3].x)/2;
	w[1].y=(z[1].y-z[3].y)/2;
	w[2]=new Complex(-w[0].x,-w[0].y);
	w[3]=new Complex(-w[1].x,-w[1].y);
	return w;
    }


}


    
