
#ifndef __VECTOR3
#define __VECTOR3
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

// inlining can be adjusted here
// #define INLINE_MODE inline
#define INLINE_MODE

// floating point unit can be changed here
#define v3float float
// #define v3float double

// set an epsilon if not set
#ifndef EPSILON
#define EPSILON 0.001f
#endif

class vector3
{
public:
	v3float c[3]; //compenents x, y, z

	// vector3 creation
	vector3() { c[0] = c[1] = c[2] = 0; }
	
	vector3(const vector3 &source)
	{
		c[0] = source.c[0];
		c[1] = source.c[1];
		c[2] = source.c[2];
	}
	
	vector3(const v3float x, const v3float y, const v3float z)
	{ c[0] = x; c[1] = y; c[2] = z; }
	
	vector3(const vector3 &to, const vector3 &from)
	{
		c[0] = to.c[0] - from.c[0];
		c[1] = to.c[1] - from.c[1];
		c[2] = to.c[2] - from.c[2];
	}
	
	INLINE_MODE vector3& randomize();
	
	// operator overload
	INLINE_MODE vector3 operator+(const vector3 &v1) const;
	INLINE_MODE vector3 operator-(const vector3 &v1) const;
	INLINE_MODE vector3 operator+(const v3float f) const;
	INLINE_MODE vector3 operator-(const v3float f) const;
	INLINE_MODE vector3 operator*(const v3float f) const;
	INLINE_MODE vector3 operator/(const v3float f) const;

	INLINE_MODE vector3& operator+=(const vector3 &v1);
	INLINE_MODE vector3& operator-=(const vector3 &v1);
	INLINE_MODE vector3& operator+=(const v3float f);
	INLINE_MODE vector3& operator-=(const v3float f);
	INLINE_MODE vector3& operator*=(const v3float f);
	INLINE_MODE vector3& operator/=(const v3float f);
	INLINE_MODE vector3& operator=(const vector3 &v1);

	INLINE_MODE vector3 operator-();

	// arithmetic operations
	INLINE_MODE v3float dot(const vector3 &a)  const;
	INLINE_MODE vector3 cross(const vector3 &a) const;

	// vector3 unit operations
	INLINE_MODE v3float length() const;
	INLINE_MODE vector3& normalize();
	INLINE_MODE void print() const;

	// vector3 combination operations
	INLINE_MODE v3float distance(const vector3& a);
	INLINE_MODE v3float distancesq(vector3 &a);
	INLINE_MODE v3float angle(const vector3 &a);
	INLINE_MODE vector3 reflect(const vector3 &normal);

};

INLINE_MODE vector3 operator*(const v3float f, const vector3 &v1) {
	return v1*f;
}

#endif