
#ifndef __vec3_h__
#define __vec3_h__

#include <math.h>


class vec3 {
public:
	float x, y, z;
	
	vec3() {}
	vec3( float x, float y, float z ) {
			this->x = x;
			this->y = y;
			this->z = z;
		}

	vec3 operator + ( const vec3 &v ) const {
			return vec3( x + v.x, y + v.y, z + v.z );
		}

	vec3 operator - ( const vec3 &v ) const {
			return vec3( x - v.x, y - v.y, z - v.z );
		}
		
	vec3 operator * ( float s ) const {
			return vec3( x*s, y*s, z*s );
		}

	vec3 operator / ( float s ) const {
			float is = 1.0f/s;
			return vec3( x*is, y*is, z*is );
		}
		
	vec3 operator - () const {
			return vec3( -x, -y, -z );
		}
		
	float &operator [] ( int i ) {
			return ((float *)this)[i];
		}
		
	const float &operator [] ( int i ) const {
			return ((float *)this)[i];
		}
	
	operator float * () {
			return (float *)this;
		}
	
	operator const float * () const {
			return (float *)this;
		}
	
	
	vec3 &operator += ( const vec3 &v ) {
			x += v.x;
			y += v.y;
			z += v.z;
			return *this;
		}
	
	vec3 &operator -= ( const vec3 &v ) {
			x -= v.x;
			y -= v.y;
			z -= v.z;
			return *this;
		}
	
	vec3 &operator *= ( float s ) {
			x *= s;
			y *= s;
			z *= s;
			return *this;
		}
		
	vec3 &operator /= ( float s ) {
			return *this *= (1.0f/s);
		}
};

inline float dot( const vec3 &v, const vec3 &w )
{
	return v.x*w.x+v.y*w.y+v.z*w.z;
}

/*
	cross(X,Y) == Z
	cross(Y,X) == -Z
	cross(X,Z) == -Y
	cross(Z,X) == Y
	cross(Y,Z) == X
	cross(Z,Y) == -X
*/
inline vec3 cross( const vec3 &v, const vec3 &w )
{
	return vec3( v.y*w.z - w.y*v.z, w.x*v.z - v.x*w.z, v.x*w.y - w.x*v.y );
}

inline float recip_sqrt( float f )
{
#if 0
	float x = __frsqrte(f);
	f *= 0.5f;
	x = 1.5f * x - f * x * x * x;
	x = 1.5f * x - f * x * x * x;
	return x;
#else
	return 1.0f / sqrtf(f);
#endif
}

inline float length_squared( const vec3 &v )
{
	return dot(v,v);
}

inline float length( const vec3 &v )
{
	float l2 = length_squared(v);
	return (l2 > 0.0f ? l2 * recip_sqrt(l2) : 0.0f);
}

inline vec3 operator * ( float s, const vec3 &v )
{
	return v*s;
}

inline vec3 normalized( const vec3 &v )
{
	return v * recip_sqrt( dot(v,v) );
}



#endif

