#include <amsculib3/amsculib3.hpp>

namespace amscuda
{

//////////////////
// Vector Class //
//////////////////

__host__ __device__ cuvec4i::cuvec4i() 
{
    x = 0; y = 0; z = 0; w = 0; 
    return;
}

__host__ __device__ cuvec4i::~cuvec4i() 
{
    x = 0; y = 0; z = 0; w = 0; 
    return;
}

__host__ __device__ cuvec4i::cuvec4i(const int &_x, const int &_y, const int &_z, const int &_w) 
{
    x = _x; y = _y; z = _z; w = _w; 
    return;
}

__host__ __device__ int& cuvec4i::operator[](const int &I)
{
    switch(I)
    {
        case 0:
            return x;
        case 1:
            return y;
        case 2:
            return z;
        case 3:
            return w;
    }

    return x;
}

__host__ __device__ const int& cuvec4i::operator[](const int &I) const
{
    switch(I)
    {
        case 0:
            return x;
        case 1:
            return y;
        case 2:
            return z;
        case 3:
            return w;
    }

    return x;
}

__host__ __device__ cuvec4i cuvec4i::operator+(const cuvec4i& rhs) const
{
    cuvec4i ret;
    ret.x = x + rhs.x;
    ret.y = y + rhs.y;
    ret.z = z + rhs.z;
    ret.w = w + rhs.w;
    return ret;
}

__host__ __device__ cuvec4i cuvec4i::operator-(const cuvec4i& rhs) const
{
    cuvec4i ret;
    ret.x = x - rhs.x;
    ret.y = y - rhs.y;
    ret.z = z - rhs.z;
    ret.w = w - rhs.w;
    return ret;
}

__host__ __device__ cuvec4i cuvec4i::operator*(const cuvec4i& rhs) const
{
    //Elementwise product
    cuvec4i ret;
    ret.x = x * rhs.x;
    ret.y = y * rhs.y;
    ret.z = z * rhs.z;
    ret.w = w * rhs.w;
    return ret;
}

__host__ __device__ cuvec4i cuvec4i::operator/(const cuvec4i& rhs) const
{
    //Elementwise division
    cuvec4i ret;
    ret.x = x / rhs.x;
    ret.y = y / rhs.y;
    ret.z = z / rhs.z;
    ret.w = w / rhs.w;
    return ret;
}

__host__ __device__ cuvec4i operator*(const cuvec4i& lhs, const int& rhs)
{
    cuvec4i ret;
    ret.x = lhs.x*rhs;
    ret.y = lhs.y*rhs;
    ret.z = lhs.z*rhs;
    ret.w = lhs.w*rhs;
    return ret;
}

__host__ __device__ cuvec4i operator*(const int& lhs, const cuvec4i& rhs)
{
    cuvec4i ret;
    ret.x = lhs*rhs.x;
    ret.y = lhs*rhs.y;
    ret.z = lhs*rhs.z;
    ret.w = lhs*rhs.w;
    return ret;
}

__host__ __device__ cuvec4i operator/(const cuvec4i& lhs, const int& rhs)
{
    cuvec4i ret;
    ret.x = lhs.x/rhs;
    ret.y = lhs.y/rhs;
    ret.z = lhs.z/rhs;
    ret.w = lhs.w/rhs;
    return ret;
}

__host__ __device__ cuvec4i operator/(const int& lhs, const cuvec4i& rhs)
{
    cuvec4i ret;
    ret.x = lhs/rhs.x;
    ret.y = lhs/rhs.y;
    ret.z = lhs/rhs.z;
    ret.w = lhs/rhs.w;
    return ret;
}

__host__ __device__ cuvec4i operator-(const cuvec4i& other)
{
    cuvec4i ret;
    ret.x = -other.x;
    ret.y = -other.y;
    ret.z = -other.z;
    ret.w = -other.w;
    return ret;
}

__host__ __device__ cuvec4i& cuvec4i::operator+=(const cuvec4i& rhs)
{
    x += rhs.x;
    y += rhs.y;
    z += rhs.z;
    w += rhs.w;
    return *this;
}

__host__ __device__ cuvec4i& cuvec4i::operator-=(const cuvec4i& rhs)
{
    x -= rhs.x;
    y -= rhs.y;
    z -= rhs.z;
    w -= rhs.w;
    return *this;
}

__host__ __device__ cuvec4i& cuvec4i::operator*=(const int& rhs)
{
    x *= rhs;
    y *= rhs;
    z *= rhs;
    w *= rhs;
    return *this;
}

__host__ __device__ cuvec4i& cuvec4i::operator/=(const int& rhs)
{
    x /= rhs;
    y /= rhs;
    z /= rhs;
    w /= rhs;
    return *this;
}


//////////////////////
// Standalone Funcs //
//////////////////////


///////////
// Tests //
///////////

};