

//
// LiDIA - a library for computational number theory
//   Copyright (c) 1995 by the LiDIA Group
//
// File        : base_bigmod.h 
//		 (Most of the code was taken from the old 
//		  LiDIA - version of bigmod written by Thomas Papanikolaou.)
// Author      : Markus Maurer (MM)
// Last change : MM, Oct 18 1995, initial version 
//


#ifndef LIDIA_BASE_BIGMOD_H
#define LIDIA_BASE_BIGMOD_H  

#if defined(HAVE_MAC_DIRS) || defined(__MWERKS__)
#include <LiDIA:bigint.h>
#else
#include <LiDIA/bigint.h>
#endif


#if !defined(HEADBANGER)
#if defined(HAVE_MAC_DIRS) || defined(__MWERKS__)
#include <LiDIA:residue_class_list.h>
#else
#include <LiDIA/residue_class_list.h>
#endif
#endif


  class base_bigmod
   {

     protected :

         bigint I ;
#if !defined(HEADBANGER)
	 static residue_class_list<bigint> *L ;
#endif
	 void normalize ( const bigint & m ) ;


	 //
	 // ***** constructor / destructor *****
	 //

         base_bigmod () ;
        ~base_bigmod () ;


         //
	 // ***** assignment *****
	 //

	 void assign_zero()
	  {I.assign_zero();}

         void assign_one()
	  {I.assign_one();}

         void assign (const base_bigmod & a)
	  {I.assign(a.I);}


         //
	 // ***** member functions *****
	 //

	 bigint invert ( const bigint & m, int = 0 ) ;
	 void negate ( const bigint & m ) ;

	 void multiply_by_2 ( const bigint & m ) ;
	 void divide_by_2 ( const bigint & m ) ;



	 //
	 // ***** arithmetical procedures *****
	 //

	 friend void invert(base_bigmod & a, const base_bigmod & b, const bigint & m);
         friend void negate(base_bigmod & a, const base_bigmod & b, const bigint & m);

	 friend void add ( base_bigmod & c, const base_bigmod & a, const base_bigmod & b, const bigint & m ) ;
	 friend void add ( base_bigmod & c, const base_bigmod & a, long i	        , const bigint & m ) ;
	 friend void add ( base_bigmod & c, long i	         , const base_bigmod & a, const bigint & m ) ;
	 friend void add ( base_bigmod & c, const base_bigmod & a, const bigint & i     , const bigint & m ) ;
	 friend void add ( base_bigmod & c, const bigint & i     , const base_bigmod & a, const bigint & m ) ;
	
	 friend void subtract ( base_bigmod & c, const base_bigmod & a, const base_bigmod & b, const bigint & m ) ;
	 friend void subtract ( base_bigmod & c, const base_bigmod & a, long i		     , const bigint & m ) ;
	 friend void subtract ( base_bigmod & c, long i		      , const base_bigmod & a, const bigint & m ) ;
	 friend void subtract ( base_bigmod & c, const base_bigmod & a, const bigint & i     , const bigint & m ) ;
	 friend void subtract ( base_bigmod & c, const bigint & i     , const base_bigmod & a, const bigint & m ) ;

	 friend void multiply ( base_bigmod & c, const base_bigmod & a, const base_bigmod & b, const bigint & m ) ;
	 friend void multiply ( base_bigmod & c, const base_bigmod & a, long i		     , const bigint & m ) ;
	 friend void multiply ( base_bigmod & c, long i		      , const base_bigmod & a, const bigint & m ) ;
	 friend void multiply ( base_bigmod & c, const base_bigmod & a, const bigint & i     , const bigint & m ) ;
	 friend void multiply ( base_bigmod & c, const bigint & i     , const base_bigmod & a, const bigint & m ) ;

	 friend void divide ( base_bigmod & c, const base_bigmod & a, const base_bigmod & b, const bigint & m ) ;
	 friend void divide ( base_bigmod & c, const base_bigmod & a, long i		   , const bigint & m ) ;
	 friend void divide ( base_bigmod & c, long i		    , const base_bigmod & a, const bigint & m ) ;
	 friend void divide ( base_bigmod & c, const base_bigmod & a, const bigint & i	   , const bigint & m ) ;
	 friend void divide ( base_bigmod & c, const bigint & i     , const base_bigmod & a, const bigint & m ) ;

	 friend void power ( base_bigmod & c, const base_bigmod & a, const bigint & b, const bigint & m ) ;
	 friend void power ( base_bigmod & c, const base_bigmod & a, long i          , const bigint & m ) ;

         friend void square(base_bigmod & a, const base_bigmod & b, const bigint & m);

	 friend void inc ( base_bigmod & c, const bigint & m ) ;
	 friend void dec ( base_bigmod & c, const bigint & m ) ;

	 //
	 // ***** functions *****
	 //

	 friend base_bigmod inverse ( const base_bigmod & a, const bigint & m ) ;





	 //
	 // ******************************************
	 // ***** THE PUBLIC PART OF BASE_BIGMOD *****
	 // ******************************************
	 //

	 public :


	 //
	 // ***** inline member functions *****
	 //

	 lidia_size_t length() const
	  {return I.length();}

         lidia_size_t bit_length() const
	  {return I.bit_length();}
  
         bool is_zero() const
	  {return I.is_zero();}

         bool is_one() const
	  {return I.is_one();}

         bool intify(int & i) const
	  {return I.intify(i);}

         bool longify(long & i) const
	  {return I.longify(i);}

	 const bigint & mantissa () const
	  {return I;}
	      


         //
	 // ***** inline friend functions *****
	 //

	 friend bigint mantissa ( const base_bigmod & a )
	  {return (a.I);}

         friend void seed ( const base_bigmod & a )
	  {seed(a.I);}

	 friend double dbl ( const base_bigmod & a )
	  {return dbl(a.I);}	 



         //
	 // ***** type checking *****
	 //

         friend bool is_char ( const base_bigmod & a )
	  {return is_char(a.I);}

         friend bool is_uchar ( const base_bigmod & a )
	  {return is_uchar(a.I);}

         friend bool is_short ( const base_bigmod & a )
	  {return is_short(a.I);}

         friend bool is_ushort ( const base_bigmod & a )
	  {return is_ushort(a.I);}

	 friend bool is_int ( const base_bigmod & a )
	  {return is_int(a.I);}

	 friend bool is_uint ( const base_bigmod & a )
	  {return is_uint(a.I);}

	 friend bool is_long ( const base_bigmod & a )
	  {return is_long(a.I);}

	 friend bool is_ulong ( const base_bigmod & a )
	  {return is_ulong(a.I);}
   } ;


#endif


