#include <amsculib3/amsculib3.hpp>

namespace amscuda
{

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

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

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

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

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

    return x;
}

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

    return x;
}

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

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

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

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

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

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

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

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

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

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

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

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

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


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


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

};