// vector class
// vector functions and operations

#pragma once

class vector {

public:
	double x,y,z;
	
	vector() {
		x = 0.0;
		y = 0.0;
		z = 0.0;
	}
	vector(const vector& v) {	// copy constructor
		x = v.x;
		y = v.y;
		z = v.z;
	}
	vector(double x_val, double y_val, double z_val) {
		x = x_val;
		y = y_val;
		z = z_val;
	}
	vector& operator=(vector &v) {
		x = v.x;
		y = v.y;
		z = v.z;
	   return *this;  
	} 
	vector operator+(vector &v) {	// vector addition
		return vector( x + v.x, y + v.y, z + v.z );
	}
	vector operator-(vector &v){	// vector subtraction
		return vector( x - v.x, y - v.y, z - v.z );
	}
	vector operator*(vector &v) {	// cross product
		return vector( y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x );
	}
	vector operator*(double c){	// scalar multiplication
		return vector( c * x, c * y, c * z);
	}
	double dot(vector &v) {	// dot product
		return ( x * v.x + y * v.y + z * v.z );
	}
	double length2(void) {
		return (x*x + y*y + z*z);
	}
	double length(void) {
		return sqrt(x*x + y*y + z*z);
	}
	vector& norm(void) {	// normalize vector
		double q=sqrt(x*x + y*y + z*z);
		x/=q;
		y/=q;
		z/=q;
		return *this;
	}
// friend functions
	friend vector operator*(double c, vector &v) {
		return vector( c * v.x, c * v.y, c * v.z );
	}
	friend double dot(vector &v1, vector &v2) {	// dot product
		return ( v1.x * v2.x + v1.y * v2.y + v1.z * v2.z );
	}
	friend vector mul(vector &v1, vector &v2) {	// component-wise multiplication
		return vector( v1.x * v2.x, v1.y * v2.y, v1.z * v2.z );
	}
	friend double length2(vector &v) { // length squared
		return ( v.x * v.x + v.y * v.y + v.z * v.z );
	}
	friend double length(vector &v) {	// length of vector
		return sqrt( v.x * v.x + v.y * v.y + v.z * v.z );
	}	
	friend vector norm(vector &v) {	// returns unit vector
		double q=sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
		return vector(v.x / q , v.y / q , v.z/q);
	}
	friend void print(vector &v) {	
		printf ("(%lg, %lg, %lg)\n",v.x,v.y,v.z);
	}	
};
