#ifndef __AMSMATHUTIL25_VEC3_HPP__
#define __AMSMATHUTIL25_VEC3_HPP__

namespace ams
{


class vec3; 
class mat3;

class vec3
{
public:
    double x;
    double y;
    double z;

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

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

//vector operations
double vec3_dot(vec3 v1, vec3 v2);
double vec3_norm(vec3 v);
vec3 vec3_normalize(vec3 v);
double vec3_dist(vec3 v1, vec3 v2);
vec3 vec3_cross(vec3 v1, vec3 v2);
vec3 vec3_proj(vec3 v1, vec3 v2);
mat3 vec3_hodgedual(vec3 v); 

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

class mat3
{
public:
    double data[9];

    mat3();
    mat3(double _xx, double _yx, double _zx, double _xy, double _yy, double _zy, double _xz, double _yz, double _zz);
    mat3(const double *_data);
    mat3(const mat3 &rhs);
    mat3(const vec3 _col1, const vec3 _col2, const vec3 _col3);

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

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

    mat3 operator*(double rhs) const;
    mat3 operator/(double rhs) const;
    vec3 operator*(vec3 rhs) const;

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

    double det();
    mat3 inverse();
    void invert();
    mat3 transpose();
    void dotranspose();
};

//matrix operations
mat3 mat3_eye();
mat3 mat3_zeros();
mat3 mat3_ones();

mat3 mat3_mult(mat3 a, mat3 b);
vec3 mat3_mult(vec3 a, mat3 b);
vec3 mat3_mult(mat3 a, vec3 b);

double mat3_det(mat3 a);
mat3 mat3_inverse(mat3 a);
mat3 mat3_transpose(mat3 a);

}; //end namespace ams

#endif

