/***************************************************************************
                          ZN.cpp  -  description
                             -------------------
    begin                : Mon Feb 28 2005
    copyright            : (C) 2005 by klaus frieler
    email                : kgf@omniversum.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
#ifndef _LIBMATH_ZN_H
#define _LIBMATH_ZN_H

template<int n>
class ZN
{
public:
   ZN():m_val(0){ }
   ZN(long i):m_val(i){ norm();}
   ZN(unsigned long i):m_val((long)i){ norm();}
   ZN(int i):m_val((long)i){ norm();}
   ZN(unsigned int i):m_val((long)i){ norm();}
   ZN(short i):m_val((long)i){ norm();}
   ZN(unsigned short i):m_val((long)i){ norm();}
   ZN(const ZN<n>& zn): m_val(zn.m_val){ norm();}
   ZN& operator=(const ZN<n>& zn){ m_val = zn.m_val; norm(); return *this;}

   ZN& operator +=(const ZN<n>& zn){ m_val += zn.m_val; norm(); return *this;}
   ZN& operator -=(const ZN<n>& zn){ m_val -= zn.m_val; norm(); return *this;}
   ZN& operator /=(const ZN<n>& zn){ m_val /= zn.m_val; norm(); return *this;}
   ZN& operator *=(const ZN<n>& zn){ m_val *= zn.m_val; norm(); return *this;}
   ZN& operator +(const ZN<n>& zn) { ZN<n> tmp(*this); tmp.m_val += zn.m_val; tmp.norm(); return tmp;}
   ZN& operator -(const ZN<n>& zn) { ZN<n> tmp(*this); tmp.m_val -= zn.m_val; tmp.norm(); return tmp;}
   ZN& operator *(const ZN<n>& zn) { ZN<n> tmp(*this); tmp.m_val *= zn.m_val; tmp.norm(); return tmp;}
   ZN& operator /(const ZN<n>& zn) { ZN<n> tmp(*this); tmp.m_val /= zn.m_val; tmp.norm(); return tmp;}
   bool  operator ==(const ZN<n>& zn)const{ return m_val == zn.m_val;}
   bool  operator !=(const ZN<n>& zn)const{ return m_val != zn.m_val;}
   bool  operator <(const ZN<n>& zn)const{ return m_val < zn.m_val;}
   bool  operator <=(const ZN<n>& zn)const{ return m_val <= zn.m_val;}
   bool  operator >(const ZN<n>& zn)const{ return m_val > zn.m_val;}
   bool  operator >=(const ZN<n>& zn)const{ return m_val >= zn.m_val;}
   long  get(){ return m_val;}
   double toDouble(){ return static_cast<double>(m_val);}
   void  dump(){cout<<m_val;}
protected:
   long     m_val;

   void     norm()
   {
      if(m_val>=0) m_val = m_val %n;
      else m_val = n + m_val %n;
   }
};
typedef ZN<12> Chroma;
#endif


