/*
 * $Id: IntVec3.h,v 1.2 2000/05/15 14:20:43 yamauchi Exp $
 *
 *	(m\pi)^2 : Integer three dimensional vector class 
 *	Copyright (C) 1993-2000 YAMAUCHI Hitoshi 山内 斉
 *
 * 平成５年１０月１８日(月)
 *	演算などの機能は無い。3次元の配列のアクセス時使用クラス
 * 
 * 平成６年６月１８日(土)
 *	特殊な値として、ILLEGAL_VALUE = -1 を使用している。この値のも
 * 	のをアクセスすると、Warning であるので、2次元しか使わない場
 * 	合はセットすると良い
 * 	
 * 1998年3月 4日(水)
 * 	もうこのクラスを変更することはないかと思っていたが、新たに
 *	getAsArray method を付加した。ただしこれは vector としてではなく
 * 	指標などとして使用すること自体がまずいのかもしれない。
 *
 * 2000年5月11日(木)
 *	Java 風に書き直す 
 *
 */
#ifndef _IntVec3_h
#define _IntVec3_h 1

#include <iostream.h>

#ifdef MEMORY_REDUCE_INT
#define int short
#endif

static const int ILLEGAL_VALUE = -1; // 配列の添え字に使うため(未使用のフラグ)
				     // こういうもののせいで難しくなるんだが、、
class IntVec3 {
public:
    enum Direction {	X,	Y,	Z,	ELEM    };

protected:
    int mE[IntVec3::ELEM];
    
public:
    IntVec3(void)
    {
	this->mE[IntVec3::X] = ILLEGAL_VALUE;		
	this->mE[IntVec3::Y] = ILLEGAL_VALUE;
	this->mE[IntVec3::Z] = ILLEGAL_VALUE;
    }
    IntVec3(const int aX, const int aY, const int aZ)
    {
	this->mE[IntVec3::X] = aX;
	this->mE[IntVec3::Y] = aY;
	this->mE[IntVec3::Z] = aZ;    
    }
    IntVec3(const int aIVvec[])
    {
	this->mE[IntVec3::X] = aIVvec[IntVec3::X];
	this->mE[IntVec3::Y] = aIVvec[IntVec3::Y];
	this->mE[IntVec3::Z] = aIVvec[IntVec3::Z];    
    }
    IntVec3(const IntVec3 &rhs)
    {
	this->mE[IntVec3::X] = rhs.mE[IntVec3::X];
	this->mE[IntVec3::Y] = rhs.mE[IntVec3::Y];
	this->mE[IntVec3::Z] = rhs.mE[IntVec3::Z];
    }
    void set(const int aX, const int aY, const int aZ)
    {
	this->mE[IntVec3::X] = aX;
	this->mE[IntVec3::Y] = aY;
	this->mE[IntVec3::Z] = aZ;    
    }
    int get(const int sc) const
    {
#ifndef NDEBUG
	if((sc < int(IntVec3::X)) || (sc > IntVec3::Z))
	{
	    cerr << "Error!: Illegal IntVec3 direction number " << sc << "\n";
	    return(ILLEGAL_VALUE);
	}
#endif
	return(this->mE[sc]);
    }

    void getAsArray(int ret[]) const
    {
	ret[IntVec3::X] = this->mE[IntVec3::X];
	ret[IntVec3::Y] = this->mE[IntVec3::Y];
	ret[IntVec3::Z] = this->mE[IntVec3::Z];
    }
    void setByArray(int v[])
    {
	this->mE[IntVec3::X] = v[IntVec3::X];
	this->mE[IntVec3::Y] = v[IntVec3::Y];
	this->mE[IntVec3::Z] = v[IntVec3::Z];
    }

    const IntVec3& operator=(const IntVec3& rhs)
    {
	if(this != &rhs)
	{
	    this->mE[IntVec3::X] = rhs.mE[IntVec3::X];
	    this->mE[IntVec3::Y] = rhs.mE[IntVec3::Y];
	    this->mE[IntVec3::Z] = rhs.mE[IntVec3::Z];
	}
	return(*this);
    }

    friend int operator==(const IntVec3& a, const IntVec3& b)
    {
	return(a.mE[IntVec3::X] == b.mE[IntVec3::X] &&
	       a.mE[IntVec3::Y] == b.mE[IntVec3::Y] &&
	       a.mE[IntVec3::Z] == b.mE[IntVec3::Z]);
    }

    friend int operator!=(const IntVec3& a, const IntVec3& b)
    {
	if((a.mE[IntVec3::X] != b.mE[IntVec3::X]) ||
	   (a.mE[IntVec3::Y] != b.mE[IntVec3::Y]) ||
	   (a.mE[IntVec3::Z] != b.mE[IntVec3::Z]))
	{
	    return(!0);
	}else
	{
	    return(0);
	}
    }

    friend ostream& operator<<(ostream& s, const IntVec3& v)
    {
	s << v.mE[IntVec3::X] << "\t" << v.mE[IntVec3::Y] << "\t" 
	  << v.mE[IntVec3::Z];
	return(s);
    }

    friend IntVec3 operator+(const IntVec3& v1, const IntVec3& v2)
    {
	return (IntVec3(v1.mE[IntVec3::X] + v2.mE[IntVec3::X],
			v1.mE[IntVec3::Y] + v2.mE[IntVec3::Y],
			v1.mE[IntVec3::Z] + v2.mE[IntVec3::Z]));
    }
    
    friend IntVec3 operator-(const IntVec3& v1, const IntVec3& v2)
    {
	return (IntVec3(v1.mE[IntVec3::X] - v2.mE[IntVec3::X],
			v1.mE[IntVec3::Y] - v2.mE[IntVec3::Y],
			v1.mE[IntVec3::Z] - v2.mE[IntVec3::Z]));
    }
};

#ifdef MEMORY_REDUCE_INT
#undef int 
#endif

#endif // #ifndef _IntVec3_h
