#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