//
// montyrep.hxx
//
// Copyright (C) 1996-7 by Leonard Janke (janke@unixg.ubc.ca)

#ifndef _MONTYREP_HXX
#define _MONTYREP_HXX

#include <linteger/linteger.hxx>

class MontyRing
{
private:
  int _digitsOfN;
  unsigned int _nPrimeModB;
  unsigned int* _n;
  unsigned int* _rSquaredModN;

public:
  MontyRing();
  MontyRing(const LInteger& N); 
  MontyRing(const MontyRing& x);
  ~MontyRing();

  MontyRing& operator=(const MontyRing&);

  friend class MontyRep;
};

class MontyRep 
{
private:
  unsigned int* _montyRep;

  static MontyRing ring;
  static unsigned int* TScratch;

  static void MontyMultiply(const unsigned int* x,
			    const unsigned int* y,
			    unsigned int* z);
  static void ReduceTScratch();
public:
  MontyRep(); 
  MontyRep(const LInteger& residue);
  MontyRep(const MontyRep& x);
  ~MontyRep();

  MontyRep& operator=(const MontyRep& x);

  static inline MontyRep MultiplicativeIdentity();

  static inline const MontyRing& Ring();
  static MontyRing SetRing(const MontyRing& newRing); 

  inline MontyRep& operator*=(const MontyRep& x);

  MontyRep& Square();

  LInteger ToLInteger() const;
}; 

#include <linteger/montyrep.inl>

#endif
