#ifndef __OGL2_VECTOR4_H__
#define __OGL2_VECTOR4_H__

#if !defined (__GNUG__) && !defined (__attribute__)
#define __attribute__(foo) /* Ignore.  */
#endif

#include <iostream>

extern "C++" {

template <class __type>
struct Vector4 {
  __type x;
  __type y;
  __type z;
  __type w;

  Vector4() :
    x(0), y(0), z(0), w(0) {}
  Vector4(__type _x, __type _y, __type _z, __type _w) :
    x(_x), y(_y), z(_z), w(_w) {}
  Vector4<__type>& operator () (__type _x, __type _y, __type _z, __type _w) {
    x = _x; y = _y; z = _z; w = _w;
    return *this;
  }
  Vector4<__type>& operator () (const Vector4<__type>& b) {
    x = b.x;
    y = b.y;
    z = b.z;
    w = b.w;
    return *this;
  }
  Vector4<__type>& operator += (const Vector4<__type>& b) {
    x += b.x;
    y += b.y;
    z += b.z;
    w += b.w;
    return *this;
  }
  Vector4<__type>& operator -= (const Vector4<__type>& b) {
    x -= b.x;
    y -= b.y;
    z -= b.z;
    w -= b.w;
    return *this;
  }
  Vector4<__type>& operator *= (const Vector4<__type>& b) {
    x *= b.x;
    y *= b.y;
    z *= b.z;
    w *= b.w;
    return *this;
  }
  Vector4<__type>& operator *= (__type s) {
    x *= s;
    y *= s;
    z *= s;
    w *= s;
    return *this;
  }
  __type Length () {
    return sqrt(x*x + y*y + z*z + w*w);
  }
  __type Len () {
    return Length();
  }

  void Unpack(__type* u) {
    u[0] = x;
    u[1] = y;
    u[2] = z;
    u[3] = w;
  }
};

template struct Vector4<GLfloat>;
template struct Vector4<GLdouble>;

typedef Vector4<GLfloat> Vector4f;
typedef Vector4<GLdouble> Vector4d;

template <class __type>
ostream& operator << (ostream& s, const Vector4<__type>& a) {
  return s << "(" << a.x << "," << a.y << "," << a.z << "," << a.w << ")";
}

template <class __type> inline Vector4<__type>
operator + (const Vector4<__type>& a) __attribute__ ((const));

template <class __type> inline Vector4<__type>
operator + (const Vector4<__type>& a) {
  return a;
}

template <class __type> inline Vector4<__type>
operator - (const Vector4<__type>& a) __attribute__ ((const));

template <class __type> inline Vector4<__type>
operator - (const Vector4<__type>& a) {
  return Vector4<__type> (-a.x, -a.y, -a.z, -a.w);
}

template <class __type> inline Vector4<__type>
operator + (const Vector4<__type>& a, const Vector4<__type>& b) __attribute__ ((const));

template <class __type> inline Vector4<__type>
operator + (const Vector4<__type>& a, const Vector4<__type>& b) {
  return Vector4<__type> (a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w);
}

template <class __type> inline Vector4<__type>
operator - (const Vector4<__type>& a, const Vector4<__type>& b) __attribute__ ((const));

template <class __type> inline Vector4<__type>
operator - (const Vector4<__type>& a, const Vector4<__type>& b) {
  return Vector4<__type> (a.x-b.x, a.y-b.y, a.z-b.z, a.w-b.w);
}

template <class __type> inline Vector4<__type>
operator * (const Vector4<__type>& a, __type s) __attribute__ ((const));

template <class __type> inline Vector4<__type>
operator * (const Vector4<__type>& a, __type s)
{
  return Vector4<__type> (a.x*s, a.y*s, a.z*s, a.w*s);
}

template <class __type> inline Vector4<__type>
operator * (__type s, const Vector4<__type>& a) __attribute__ ((const));

template <class __type> inline Vector4<__type>
operator * (__type s, const Vector4<__type>& a)
{
  return Vector4<__type> (s*a.x, s*a.y, s*a.z, s*a.w);
}

template <class __type> inline Vector4<__type>
operator * (const Vector4<__type>& a, const Vector4<__type>& b) __attribute__ ((const));

template <class __type> inline Vector4<__type>
operator * (const Vector4<__type>& a, const Vector4<__type>& b) {
  return Vector4<__type> (a.x*b.x, a.y*b.y, a.z*b.z, a.w*b.w);
}

template <class __type> inline __type
Dot (const Vector4<__type>& a, const Vector4<__type>& b) __attribute__ ((const));

template <class __type> inline __type
Dot (const Vector4<__type>& a, const Vector4<__type>& b) {
  return (a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w);
}


} // extern "C++"

#endif 
