#ifndef __CUVECT2F_HPP__
#define __CUVECT2F_HPP__

namespace amscuda
{

    class cuvect2f
    {
        public:
        float x;
        float y;


        __host__ __device__ cuvect2f();
        __host__ __device__ ~cuvect2f();
        __host__ __device__ cuvect2f(float _x, float _y);

        __host__ __device__ float& operator[](const int I);
        __host__ __device__ const float& operator[](const int I) const;

        __host__ __device__ cuvect2f operator+(cuvect2f lhs);
        __host__ __device__ cuvect2f operator-(cuvect2f lhs);
        __host__ __device__ cuvect2f operator*(float lhs);
        __host__ __device__ cuvect2f operator/(float lhs);
        __host__ __device__ friend cuvect2f operator-(cuvect2f rhs);
    };

    class cumat2f
    {
        public:
        float dat[4];

        __host__ __device__ cumat2f();
        __host__ __device__ ~cumat2f();
        __host__ __device__ float& operator[](const int I);
        __host__ __device__ float& operator()(const int I, const int J);
        __host__ __device__ float& at(const int I, const int J);

        __host__ __device__ cumat2f operator+(cumat2f lhs);
        __host__ __device__ cumat2f operator-(cumat2f lhs);
        __host__ __device__ cumat2f operator*(float lhs);
        __host__ __device__ cumat2f operator/(float lhs);
        __host__ __device__ cuvect2f operator*(cuvect2f lhs);
        __host__ __device__ cumat2f operator*(cumat2f lhs);
        __host__ __device__ friend cumat2f operator-(cumat2f rhs);

        __host__ __device__ float det();
        __host__ __device__ cumat2f transpose();
        __host__ __device__ cumat2f inverse();
    };

    __host__ __device__ float cuvect2f_dot(cuvect2f a, cuvect2f b);
    __host__ __device__ float cuvect2f_cross(cuvect2f a, cuvect2f b);
    __host__ __device__ float cuvect2f_norm(cuvect2f a);
    __host__ __device__ cuvect2f cuvect2f_normalize(cuvect2f a);
    __host__ __device__ cuvect2f cuvect2f_proj(cuvect2f a, cuvect2f b);

    //2x2 matrix operations
    //matrix order is assumed to be mat[I,J] = mat[I+3*J]

    //transpose a 2x2 matrix in place
    __host__ __device__ void mat2f_transpose(float *mat2inout);
    
    //copies src to dest
    __host__ __device__ void mat2f_copy(float *mat2f_dest, const float *mat2f_src);
    
    //inverts mat?inout[4]
    __host__ __device__ void mat2f_inverse(float *mat2inout);
    
    //rotatin matrix from angle
    __host__ __device__ void mat2f_rot_from_angle(float angle, float *mat2);

    //multiplies c = a*b
    __host__ __device__ void mat2f_mult(float *mat2a, float *mat2b, float *mat2c);

    // ret = a*b
    __host__ __device__ cuvect2f mat2f_mult(float *mat2a, cuvect2f b);


    void test_cuvect2f_1();


};

#endif

