#ifndef __AMSMATHUTIL25_VEC3F_HPP__
#define __AMSMATHUTIL25_VEC3F_HPP__

namespace ams
{


class vec3f; 
class mat3f;

class vec3f
{
public:
    float x;
    float y;
    float z;

    vec3f();
    vec3f(float _x, float _y, float _z);
    vec3f(const vec3f &rhs);
    vec3f& operator=(const vec3f &rhs);
    bool operator==(vec3f rhs);
    
    vec3f operator+(vec3f rhs) const;
    vec3f operator-(vec3f rhs) const;
    vec3f operator*(float rhs) const;
    vec3f operator/(float rhs) const;
    friend vec3f operator-(vec3f rhs);

    float& operator[](int ind);
    const float& operator[](int ind) const;
};

//vector operations
float vec3f_dot(vec3f v1, vec3f v2);
float vec3f_norm(vec3f v);
vec3f vec3f_normalize(vec3f v);
float vec3f_dist(vec3f v1, vec3f v2);
vec3f vec3f_cross(vec3f v1, vec3f v2);
vec3f vec3f_proj(vec3f v1, vec3f v2);
mat3f vec3f_hodgedual(vec3f v); 

//vector operations (old nomenclature)
float vdot(vec3f v1, vec3f v2);
float vnorm(vec3f v);
vec3f vnormalize(vec3f v);
float vdist(vec3f v1, vec3f v2);
vec3f vcross(vec3f v1, vec3f v2);
vec3f vproj(vec3f v1, vec3f v2);

class mat3f
{
public:
    float data[9];

    mat3f();
    mat3f(float _xx, float _yx, float _zx, float _xy, float _yy, float _zy, float _xz, float _yz, float _zz);
    mat3f(const float *_data);
    mat3f(const mat3f &rhs);
    mat3f(const vec3f _col1, const vec3f _col2, const vec3f _col3);

    mat3f& operator=(const mat3f rhs);
    bool operator==(const mat3f rhs);

    mat3f operator+(mat3f rhs) const;
    mat3f operator-(mat3f rhs) const;
    mat3f operator*(mat3f rhs) const;
    mat3f operator/(mat3f rhs) const;

    mat3f operator*(float rhs) const;
    mat3f operator/(float rhs) const;
    vec3f operator*(vec3f rhs) const;

    float& operator()(int I, int J);
    float& operator[](int I);
    const float& operator()(int I, int J) const;
    const float& operator[](int I) const;
    float& at(int I, int J);
    const float& at(int I, int J) const;

    float det();
    mat3f inverse();
    void invert();
    mat3f transpose();
    void dotranspose();
};

//matrix operations
mat3f mat3f_eye();
mat3f mat3f_zeros();
mat3f mat3f_ones();

mat3f mat3f_mult(mat3f a, mat3f b);
vec3f mat3f_mult(vec3f a, mat3f b);
vec3f mat3f_mult(mat3f a, vec3f b);

float mat3f_det(mat3f a);
mat3f mat3f_inverse(mat3f a);
mat3f mat3f_transpose(mat3f a);

}; //end namespace ams

#endif

