/*------------------------------------------------------------------------------
 src/lib/dj/djVec.h
 
 Copyright (c) 2004-2006 Darby Johnston.
 All rights reserved.
 Use is subject to license terms.
------------------------------------------------------------------------------*/

#ifndef DJ_VEC_H
#define DJ_VEC_H
#include <djBase.h>

namespace dj {

// Generic vector base.
//
template <int C, class T>
class _Vec {
public:

  _Vec() { zero(); }
  _Vec(const _Vec<C, T> &);

  // Set.
  //
  _Vec<C, T> & operator = (const _Vec<C, T> &);
  T & operator [] (int in) { return _v[in]; }

  // Get.
  //
  const T & operator [] (int in) const { return _v[in]; }
  int size() const { return C; }

  // Functions.
  //
  void zero();
  
protected:

  T _v [C];
};
template <int C, class T>
class Vec : public _Vec<C, T> {};

// Two-dimensional vector base.
//
template <class T>
class Vec<2, T> : public _Vec<2, T> {
public:

  Vec();
  Vec(const T & x, const T & y);
  Vec(const T &);

  // Set.
  //
  void set(const T & x, const T & y);
  void x(const T &);
  void y(const T &);
  
  // Get.
  //
  const T & x() const;
  const T & y() const;
};

// Three-dimensional vector base.
//
template <class T>
class Vec<3, T> : public _Vec<3, T> {
public:

  Vec();
  Vec(const T & x, const T & y, const T & z);
  Vec(const T &);

  // Set.
  //
  void set(const T & x, const T & y, const T & z);
  void x(const T &);
  void y(const T &);
  void z(const T &);
  
  // Get.
  //
  const T & x() const;
  const T & y() const;
  const T & z() const;
};

// Vector types.
//
typedef Vec<2, int> Vec2i;
typedef Vec<2, double> Vec2f;
typedef Vec<3, int> Vec3i;
typedef Vec<3, double> Vec3f;

// Functions.
//
template <int C, class T> const Vec<C, T> normalize(const Vec<C, T> &);
template <int C, class T> double dot(const Vec<C, T> &, const Vec<C, T> &);
template <int C, class T> const Vec<C, T> swap(const Vec<C, T> &);
template <int C, class T> double length(const Vec<C, T> &);

template <int C, class T> const T area(const Vec<C, T> &);
template <int C, class T> bool areaIsValid(const Vec<C, T> &);

template <class T> double aspect(const Vec<2, T> &);

// Arithmetic.
//
template <int C, class T>
const Vec<C, T> operator + (const Vec<C, T> &, const Vec<C, T> &);
template <int C, class T>
const Vec<C, T> operator + (const Vec<C, T> &, const T &);
template <int C, class T>
const Vec<C, T> operator + (const Vec<C, T> &, double);

template <int C, class T>
const Vec<C, T> operator - (const Vec<C, T> &, const Vec<C, T> &);
template <int C, class T>
const Vec<C, T> operator - (const Vec<C, T> &, const T &);
template <int C, class T>
const Vec<C, T> operator - (const Vec<C, T> &, double);

template <int C, class T>
const Vec<C, T> operator * (const Vec<C, T> &, const Vec<C, T> &);
template <int C, class T>
const Vec<C, T> operator * (const Vec<C, T> &, const T &);
template <int C, class T>
const Vec<C, T> operator * (const Vec<C, T> &, double);

template <int C, class T>
const Vec<C, T> operator / (const Vec<C, T> &, const Vec<C, T> &);
template <int C, class T>
const Vec<C, T> operator / (const Vec<C, T> &, const T &);
template <int C, class T>
const Vec<C, T> operator / (const Vec<C, T> &, double);

template <int C, class T>
const Vec<C, T> operator - (const Vec<C, T> &);

// Comparison.
//
template <int C, class T>
const Vec<C, T> min(const Vec<C, T> &, const Vec<C, T> &);
template <int C, class T>
const Vec<C, T> max(const Vec<C, T> &, const Vec<C, T> &);
template <int C, class T>
bool operator == (const Vec<C, T> &, const Vec<C, T> &);
template <int C, class T>
bool operator != (const Vec<C, T> &, const Vec<C, T> &);
template <int C, class T>
bool operator < (const Vec<C, T> &, const Vec<C, T> &);
template <int C, class T>
bool operator <= (const Vec<C, T> &, const Vec<C, T> &);
template <int C, class T>
bool operator > (const Vec<C, T> &, const Vec<C, T> &);
template <int C, class T>
bool operator >= (const Vec<C, T> &, const Vec<C, T> &);

// Serialize.
//
template <int C, class T>
const StrList deflateStr(const Vec<C, T> &);
template <int C, class T>
bool inflateStr(StrList &, Vec<C, T> *);

}

#include <djVec_.h>
#include <djVec2_.h>
#include <djVec3_.h>
#include <djVecFnc_.h>
#endif
