import java.awt.event.*;
import java.awt.*;

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

public class Complex {
    double x,y;
    int[] a=new int[3]; //code for the graph
    
    public Complex() {
        this.x=0.0;
        this.y=0.0;
    } 
    
    public Complex(double x,double y) {
        this.x=x;
        this.y=y;
    }
    
    public Complex(Complex z) {
        this.x=z.x;
        this.y=z.y;
	for(int i=0;i<3;++i) this.a[i]=z.a[i];
    }

    public static double norm(Complex z) {
        return Math.sqrt(z.x*z.x+z.y*z.y);
    }

    public static Complex unit(Complex z) {
        double d=z.norm(z);
        return new Complex(z.x/d,z.y/d);
    }

    public static Complex plus(Complex z1,Complex z2) {
        return new Complex(z1.x+z2.x, z1.y+z2.y);
    }
    
    public static Complex negative(Complex z) {
	Complex w=new Complex(-z.x,-z.y);
	return(w);
    }




    public static Complex minus(Complex z1,Complex z2) {
        return new Complex(z1.x-z2.x, z1.y-z2.y);
    }
    

    public static Complex times(Complex z1,Complex z2) {
        return new Complex(z1.x*z2.x-z1.y*z2.y,
        z1.x*z2.y+z1.y*z2.x);
    }

    public static Complex inverse(Complex z) {
        double d=z.x*z.x+z.y*z.y;
        return new Complex(z.x/d,-z.y/d);
    }
    

    public static Complex divide(Complex z1,Complex z2) {
        return times(z1,inverse(z2));
    }
    
    public static Complex conjugate(Complex z) {
        return new Complex(z.x,-z.y);
    }
    

    public static double dot(Complex a, Complex b) {
        return a.x*b.x+a.y*b.y;
    }
    
    public static double dist(Complex a,Complex b) {
        Complex z=minus(a,b);
        return(norm(z));
    }
    
    
    
    
    public double norm() {
        return Math.sqrt(x*x+y*y);
    }

    public Complex unit() {
        double d=norm();
        return new Complex(x/d,y/d);
    }

    public Complex plus(Complex z) {
        return new Complex(x+z.x, y+z.y);
    }
    

    public Complex minus(Complex z) {
        return new Complex(x-z.x, y-z.y);
    }

    public Complex times(Complex z) {
        return new Complex(x*z.x-y*z.y,
        x*z.y+y*z.x);
    }
    
    

    public Complex inverse() {
        double d=x*x+y*y;
        return new Complex(x/d,-y/d);
    }
    
    public Complex divide(Complex z2) {
        return times(inverse(z2));
    }
    
    
    public Complex conjugate() {
        return new Complex(x,-y);
    }

    public double dot(Complex a) {
        return a.x*x+a.y*y;
    }
    
    public boolean equals(Complex a) {
        return ((a.x==x)&&(a.y==y));
    }
    
    
    public double arg(){
        return Math.atan2(y,x);
    }

    public Complex reflect(Complex z) {
	Complex w=new Complex(2*x-z.x,2*y-z.y);
	return(w);
    }



    public static Complex eis(int a0,int a1) {
	int[] a={a0,a1};
	return eis(a);
    }

    public static Complex eis(int[] a) {
	Complex z0=new Complex(1,0);
	Complex z1=alpha();
	z0=z0.scale(a[0]);
	z1=z1.scale(a[1]);
	Complex z2=Complex.plus(z0,z1);
	return z2;
    }
	
    public static Complex alpha(int q) {
	Complex z=new Complex(1,0);
	if(q<0) q=q+6;
	if(q<0) q=q+6;
	Complex w=alpha();
	for(int i=0;i<q;++i) z=Complex.times(z,w);
	return z;
    }
    
    public static Complex alpha() {
	double x=1.0/2;
	double y=Math.sqrt(3)/2;
	return new Complex(x,y);
    }

    public int[] toEis() {
	double s=Math.sqrt(3)/2;
	int y1=(int)(Math.floor(this.y/s+.5));
	Complex z=Complex.minus(this,alpha(1).scale(y1));
	int x1=(int)(Math.floor(z.x+.5));
	int[] xy={x1,y1};
	return xy;
    }

    public Complex toEisCx() {
	int[] t=this.toEis();
	return eis(t);
    }

    
    

    public static boolean doTheyCross(Complex z1,Complex z2,Complex z3,Complex z4) {
   	Complex q=findCross(z1,z2,z3,z4);
	if(q==null) return false;
	boolean test=onSegment(q,z1,z2);
	if(test==false) return false;
	test=onSegment(q,z3,z4);
	if(test==false) return false;
	return true;
    }


    /**demands an interior crossing*/
    
    public static boolean doTheyCrossStrict(Complex z1,Complex z2,Complex z3,Complex z4) {
	boolean test=doTheyCross(z1,z2,z3,z4);
	if(test==false) return false;
	if(Complex.dist(z1,z3)<.000000001) return false;
	if(Complex.dist(z2,z3)<.000000001) return false;
	if(Complex.dist(z1,z4)<.000000001) return false;
	if(Complex.dist(z2,z4)<.000000001) return false;
	return true;
    }

    public static Complex findCross(Complex z1,Complex z2,Complex z3,Complex z4) {
	double x1=z1.x;
	double y1=z1.y;
	double x2=z2.x;
	double y2=z2.y;
	double x3=z3.x;
	double y3=z3.y;
	double x4=z4.x;
	double y4=z4.y;
	double a=y1*(x2*x4-x2*x3)+y2*(x1*x3-x1*x4)+y3*(x1*x4-x2*x4)+y4*(x2*x3-x1*x3);
	double b=x1*(y2*y4-y2*y3)+x2*(y1*y3-y1*y4)+x3*(y1*y4-y2*y4)+x4*(y2*y3-y1*y3);
	double c=x2*y4+x1*y3+x3*y2+x4*y1-x3*y1-x2*y3-x1*y4-x4*y2;
	a=a/c;
	b=-b/c;
	if(Math.abs(c)<.00000001) return null;
	return new Complex(a,b);
    }

    public static boolean onSegment(Complex q,Complex z1,Complex z2) {
	double d12=Complex.dist(z1,z2);
	double d1=Complex.dist(q,z1);
	double d2=Complex.dist(q,z2);
	if(d1+d2<d12+.000000001) return true;
	return false;
    }
    
    
    public Complex scale(double r) {
	return new Complex(r*x,r*y);
    }
    

    public static boolean  isPositivelyOriented(Complex z1,Complex z2,Complex z3) {
	double w=signedArea(z1,z2,z3);
	if(w<0) return(true);
	return(false);
    }

    public static double  signedArea(Complex z1,Complex z2,Complex z3) {
        Complex[] z=new Complex[5];
        for(int i=1;i<=4;++i) z[i]=new Complex();
        z[1]=Complex.minus(z2,z1);
        z[2]=Complex.minus(z3,z1);
        z[3]=Complex.conjugate(z[2]);
        z[4]=Complex.times(z[1],z[3]);
	return z[4].y;
    }

    
    public static boolean  isPositivelyOriented(Complex[] Z) {
	return isPositivelyOriented(Z[0],Z[1],Z[2]);
    }

    public void print() {
	System.out.println("Complex: "+this.x+" "+this.y);
    }
    
    public void print2() {
	System.out.println("Complex: "+this.x+" "+this.y+"   "+a[0]+" "+a[1]+" "+a[2]);
    }
    
}

