public class vector
{
public double xyz[];

//--------- optimization ---------
private static vector temp[] = null;
public  static void init_static()
    {
	if(temp == null)
	    {
		temp = new vector[10];
		for(int i = 0; i<10; i++)
		    temp[i] = new vector();
	    }
    }
//--------------------------------
    
public vector()
    {
	xyz = new double[3];
	xyz[0] = 0;
	xyz[1] = 0;
	xyz[2] = 0;
    }

public vector(vector v)
    {
	xyz = new double[3];
	xyz[0] = v.xyz[0];
	xyz[1] = v.xyz[1];
	xyz[2] = v.xyz[2];	
    }

public vector(double x, double y, double z)
    {
	xyz = new double[3];
	xyz[0] = x;
	xyz[1] = y;
	xyz[2] = z;	
    }

public static void subtract(vector a, vector b, vector r) // r = a - b
    {
	r.xyz[0] = a.xyz[0] - b.xyz[0];
	r.xyz[1] = a.xyz[1] - b.xyz[1];
	r.xyz[2] = a.xyz[2] - b.xyz[2];
    }

public static void subu(vector a, vector b, vector r) // r = (a - b) / |a - b|
    {
	r.xyz[0] = a.xyz[0] - b.xyz[0];
	r.xyz[1] = a.xyz[1] - b.xyz[1];
	r.xyz[2] = a.xyz[2] - b.xyz[2];
	double mag = (double)Math.sqrt(r.xyz[0]*r.xyz[0] + r.xyz[1]*r.xyz[1] + r.xyz[2]*r.xyz[2]);
	r.xyz[0] = r.xyz[0]/mag;
	r.xyz[1] = r.xyz[1]/mag;
	r.xyz[2] = r.xyz[2]/mag;
    }

public static void add(vector a, vector b, vector r) // r = a + b
    {
	r.xyz[0] = a.xyz[0] + b.xyz[0];
	r.xyz[1] = a.xyz[1] + b.xyz[1];
	r.xyz[2] = a.xyz[2] + b.xyz[2];
    }

public static void addu(vector a, vector b, vector r) // r = a + b
    {
	r.xyz[0] = a.xyz[0] + b.xyz[0];
	r.xyz[1] = a.xyz[1] + b.xyz[1];
	r.xyz[2] = a.xyz[2] + b.xyz[2];
	double mag = (double)Math.sqrt(r.xyz[0]*r.xyz[0] + r.xyz[1]*r.xyz[1] + r.xyz[2]*r.xyz[2]);
	r.xyz[0] = r.xyz[0]/mag;
	r.xyz[1] = r.xyz[1]/mag;
	r.xyz[2] = r.xyz[2]/mag;
    }

public static void cross(vector a, vector b, vector r) // r = a x b
    {
	r.xyz[0] = a.xyz[1]*b.xyz[2] - a.xyz[2]*b.xyz[1];
	r.xyz[1] = a.xyz[2]*b.xyz[0] - a.xyz[0]*b.xyz[2];
	r.xyz[2] = a.xyz[0]*b.xyz[1] - b.xyz[0]*a.xyz[1];
    }

public static void crossu(vector a, vector b, vector r) // r = (a x b) / |a x b|
    {
	r.xyz[0] = a.xyz[1]*b.xyz[2] - a.xyz[2]*b.xyz[1];
	r.xyz[1] = a.xyz[2]*b.xyz[0] - a.xyz[0]*b.xyz[2];
	r.xyz[2] = a.xyz[0]*b.xyz[1] - b.xyz[0]*a.xyz[1];
	double mag = (double)Math.sqrt(r.xyz[0]*r.xyz[0] + r.xyz[1]*r.xyz[1] + r.xyz[2]*r.xyz[2]);
	r.xyz[0] = r.xyz[0]/mag;
	r.xyz[1] = r.xyz[1]/mag;
	r.xyz[2] = r.xyz[2]/mag;
    }
    
public static double dot(vector a, vector b)
    {
	return (a.xyz[0]*b.xyz[0] + a.xyz[1]*b.xyz[1] + a.xyz[2]*b.xyz[2]);
    }

public static void scale(vector v, double f, vector r) // r = v * f
    {
	r.xyz[0] = v.xyz[0]*f;
	r.xyz[1] = v.xyz[1]*f;
	r.xyz[2] = v.xyz[2]*f;
    }

public static void assign(vector a, vector b) // a <- b
    {
	a.xyz[0] = b.xyz[0];
	a.xyz[1] = b.xyz[1];
	a.xyz[2] = b.xyz[2];
    }
    
public double magnitude()
    {
	return (double)Math.sqrt(xyz[0]*xyz[0] + xyz[1]*xyz[1] + xyz[2]*xyz[2]);
    }
    
public boolean normalize()
    {
	double mag = magnitude();
	if(mag!=0.0f)
	    {
		xyz[0]=xyz[0]/mag;
		xyz[1]=xyz[1]/mag;
		xyz[2]=xyz[2]/mag;
		return true;
	    }
	return false;
    }
        
public boolean equals(vector v)
    {
	boolean result = ((v.xyz[0] == xyz[0]) && (v.xyz[1] == xyz[1]) && (v.xyz[2] == xyz[2]));
	return result;
    }
    
public void dump()
    {
	System.out.println("("+xyz[0]+"  "+xyz[1]+"  "+xyz[2]+")");
    }
    
public void dump(String mesg)
    {
	System.out.println(mesg + " ("+xyz[0]+"  "+xyz[1]+"  "+xyz[2]+")  magnitude:"+magnitude()); 
    }
}

