#ifndef __CUVECT4_HPP__
#define __CUVECT4_HPP__

namespace amscuda
{

    class cuvect4
    {
        public:
        double x;
        double y;
        double z;
        double w;

        __host__ __device__ cuvect4();
        __host__ __device__ ~cuvect4();
        __host__ __device__ cuvect4(double _x, double _y, double _z, double _w);
                
        __host__ __device__ double& operator[](const int I);
        __host__ __device__ const double& operator[](const int I) const;

        __host__ __device__ cuvect4 operator+(cuvect4 lhs);
        __host__ __device__ cuvect4 operator-(cuvect4 lhs);
        __host__ __device__ cuvect4 operator*(double lhs);
        __host__ __device__ cuvect4 operator/(double lhs);
        __host__ __device__ friend cuvect4 operator-(cuvect4 rhs);
    };

    class cumat4
    {
        public:
        double dat[16];

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

        __host__ __device__ cumat4 operator+(cumat4 lhs);
        __host__ __device__ cumat4 operator-(cumat4 lhs);
        __host__ __device__ cumat4 operator*(double lhs);
        __host__ __device__ cumat4 operator/(double lhs);
        __host__ __device__ cuvect4 operator*(cuvect4 lhs);
        __host__ __device__ cumat4 operator*(cumat4 lhs);
        __host__ __device__ friend cumat4 operator-(cumat4 rhs);

        __host__ __device__ double det();
        __host__ __device__ cumat4 transpose();
        __host__ __device__ cumat4 inverse();
    };

    __host__ __device__ double cuvect4_dot(cuvect4 a, cuvect4 b);
    __host__ __device__ double cuvect4_norm(cuvect4 a);
    __host__ __device__ cuvect4 cuvect4_normalize(cuvect4 a);
    __host__ __device__ cuvect4 cuvect4_proj(cuvect4 a, cuvect4 b);

}; //end namespace amscuda

#endif

