#ifndef TTPunctCPP
#define TTPunctCPP
/*---------------------------------------------------------------------------------*/
//#include "Funcs.cpp"
#include "APunct.cpp"
#include <math.h>
/*---------------------------------------------------------------------------------*/
#define TPL          template<class TCoord>
#define TTPuncTpl    TTPunct<TCoord>
#define TPL_(type)   TPL type TTPunct<TCoord>
/*---------------------------------------------------------------------------------*/
template<class TCoord> class TTPunct: public APunct
{
  typedef TCoord*             PCoord;
//  typedef TTPunct<TCoord,3> TTPuncTpl;

  private:
  protected:
    TCoord vec[3];

  public:
    TTPunct(){}
    TTPunct(TCoord x, TCoord y, TCoord z) { vec[0]=x; vec[1]=y; vec[2]=z; }
    TTPunct(TCoord* rhs)                      { if(rhs) BinOpVec(vec, =, rhs); else {vec[0]=0; vec[1]=0; vec[2]=0;} }
    TTPunct(TTPuncTpl& rhs)                   { BinOpVec(vec, =, rhs.vec); } // Copy constructor
    TTPunct(TTPuncTpl& rhs, TCoord fac)       { BinOpVec(vec, =, fac*rhs.vec); }
    TTPunct(TTPuncTpl& v1, TTPuncTpl& v2)     { ProdVec(vec, v1.vec, v2.vec); } /* this = [v1 x v2] */
    ~TTPunct(){}

    inline PCoord coord(){return vec;}

    inline TCoord& __fastcall operator [] (unsigned idx) { return vec[idx < 3 ? idx : idx % 3]; }
    TTPuncTpl& __fastcall operator += (TTPuncTpl& rhs){ BinOpVec(vec, +=, rhs.vec); return *this; }
    TTPuncTpl& __fastcall operator -= (TTPuncTpl& rhs){ BinOpVec(vec, -=, rhs.vec); return *this; }
    TTPuncTpl& __fastcall operator *= (TTPuncTpl& rhs){ BinOpVec(vec, *=, rhs.vec); return *this; }
    TTPuncTpl& __fastcall operator *= (TCoord fac){ BinOpFac(vec,*=,fac); return *this; }
    TTPuncTpl& __fastcall operator /= (TCoord fac){ BinOpFac(vec,/=,fac); return *this; }

    unsigned __fastcall operator == (const TTPuncTpl& rhs) const { if(this==&rhs)return 1; return TernOpVec(vec, ==, rhs.vec, &&); }
    unsigned __fastcall operator != (const TTPuncTpl& rhs) const { return !operator==(rhs); };

    TTPuncTpl& neg(){ BinOpVec(vec, = -, vec); return *this; } /* this = -this */
    TTPuncTpl  vect(TTPuncTpl& rhs){ return TTPuncTpl(*this, rhs); }
    TCoord     scal(TTPuncTpl& rhs){ return TernOpVec(vec,*,rhs.vec,+); }          /* this * rhs   */

    /* typecasts */
    operator long double() const { return sqrt(TernOpVec(vec,*,vec,+)); } /* |this| */
    operator double()      const { return sqrt(TernOpVec(vec,*,vec,+)); } /* |this| */
    operator float()       const { return sqrt(TernOpVec(vec,*,vec,+)); } /* |this| */
    operator unsigned()    const { return sqrt(TernOpVec(vec,*,vec,+)); } /* |this| */ // Dangerous!!! Sometimes the compiler may typecast to int and if TCoord == int, this operator will be called.

    /* By value operators */ // Don't recommend to use these because they are very slow!
    TTPuncTpl& __fastcall operator = (TTPuncTpl rhs){ BinOpVec(vec, =, rhs.vec); return *this; }
    TTPuncTpl             operator - (){ TTPuncTpl r; BinOpVec(r.vec, =, -vec); return r; }
    TTPuncTpl  __fastcall operator + (TTPuncTpl rhs){ return  rhs += *this; }
    TTPuncTpl  __fastcall operator - (TTPuncTpl rhs){ return rhs.neg() += *this; }
    TCoord     __fastcall operator * (TTPuncTpl rhs){ TCoord r = 0; unsigned i=3; while(i--) r += vec[i] * rhs.vec[i]; return r; }

    /* virtuals */
      inline double __fastcall coord(unsigned idx){ return (*this)[idx]; };
      inline double x(){ return vec[0]; };
      inline double y(){ return vec[1]; };
      inline double z(){ return vec[2]; };
      double abs(){ return sqrt(TernOpVec((double)vec,*,vec,+)); };

};
/*---------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------*/
#undef TPL
#undef TPL_
#undef TTPuncTpl
#endif
