/*
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License version 2 
    as published by the Free Software Foundation.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

    Copyright (C) 2006  Thierry Berger-Perrin <tbptbp@gmail.com>
*/

#ifndef MATH_VEC_H
#define MATH_VEC_H

#include "math_utility.h"

/* Integer 2D point */
struct point_t {
    union {
        uint64_t bits;
        struct { int32_t x,y; };
    };
    point_t() {}
    point_t(const int a, const int b) : x(a), y(b) {}
    point_t(const uint64_t i) : bits(i) {}
    operator uint64_t() const { return bits; }
    int area() const { return x*y; }
    point_t operator +(const point_t rhs) const { return point_t(x+rhs.x, y+rhs.y); }
    point_t operator -(const point_t rhs) const { return point_t(x-rhs.x, y-rhs.y); }
    point_t operator +(const int rhs) const { return point_t(x+rhs, y+rhs); }
    point_t operator -(const int rhs) const { return point_t(x-rhs, y-rhs); }
    point_t operator *(const int rhs) const { return point_t(x*rhs, y*rhs); }
    point_t operator /(const int rhs) const { return point_t(x/rhs, y/rhs); }
};

/* Float 2D vector */
struct vec2_t {
    union { 
        struct { float x,y; };
        float m[2];
    };
};

/* Float 3D vector */
struct vec_t{
    union { 
        struct { float x,y,z; };
        float m[3];
    };
    vec_t() {}
    vec_t(const float a, const float b, const float c) : x(a), y(b), z(c) {}
    vec_t operator+(const vec_t &v) const { return vec_t(x+v.x,y+v.y,z+v.z); }
    vec_t operator-(const vec_t &v) const { return vec_t(x-v.x,y-v.y,z-v.z); }
    vec_t operator-() const { return vec_t(-x,-y,-z); }
    vec_t operator*(const float d) const { return vec_t(x*d,y*d,z*d); }
    const float &operator[](const uint_t i) const { return m[i]; }
    float &operator[](const uint_t i) { return m[i]; }
    vec_t cross(const vec_t &v) const { return vec_t(y*v.z-z*v.y,z*v.x-x*v.z,x*v.y-y*v.x); }
    vec_t normalize() const { return *this * (1.f/sqrtf(magsqr())); }
    float dot(const vec_t &v) const { return x*v.x+y*v.y+z*v.z; }
    float magsqr() const { return dot(*this); }
    float get_min() const { return minf(minf(x,y),z); }
    float get_max() const { return maxf(maxf(x,y),z); }
    static vec_t zero;
};
#endif
