public class Vector {
	public static final Vector ZERO = new Vector(0.0, 0.0, 0.0);

	private double x;
	private double y;
	private double z;

	private Vector(double x, double y, double z) {
		this.x = x;
		this.y = y;
		this.z = z;
	}

	public double getX() { return x; }
	public double getY() { return y; }
	public double getZ() { return z; }
	public double getLengthSquared() {
		return x * x + y * y + z * z;
	}
	public double getLength() {
		return Math.sqrt(getLengthSquared());
	}
	public Vector normalize() {
		double len2 = getLengthSquared();
		if(len2 == 0.0 || len2 == 1.0) return this;
		return this.scale(1.0 / Math.sqrt(len2));
	}
	public double dot(Vector other) {
		return this.x * other.x + this.y * other.y + this.z * other.z;
	}
	public Vector cross(Vector other) {
		return Vector.create(
				this.y * other.z - this.z * other.y,
				this.z * other.x - this.x * other.z,
				this.x * other.y - this.y * other.x);
	}
	public Vector add(Vector other) {
		return Vector.create(this.x + other.x, this.y + other.y, this.z + other.z);
	}
	public Vector subtract(Vector other) {
		return Vector.create(this.x - other.x, this.y - other.y, this.z - other.z);
	}
	public Vector projectOnto(Vector other) {
		double x = this.dot(other);
		return other.scale(x);
	}
	public Vector scale(double scalar) {
		if(scalar == 1.0) return this;
		return Vector.create(scalar * this.x, scalar * this.y, scalar * this.z);
	}
	public String toString() { return "(" + x + "," + y + "," + z + ")"; }

	public static Vector create(double x, double y, double z) {
		return new Vector(x, y, z);
	}
}
