


#include <LiDIA/bigmod.h>


 //
 // ***** define static elements *****
 //

 residue_class<bigint>* bigmod::Mp = nil;
 bigint bigmod::M = (bigint)((long) 0);



 //
 // ***** modulus handling *****
 //

 void bigmod::set_modulus ( const bigint & m ) 
  {
    if (m.is_zero ())
        lidia_error_handler ("bigmod", "set_modulus::zero modulus");

    if (base_bigmod::L == nil)
       base_bigmod::L = new residue_class_list <bigint>;

    else if (bigmod::Mp != nil)
       (base_bigmod::L)->clear (bigmod::Mp);

    if (m.is_positive())
       bigmod::M = m;
    else
       bigmod::M = -m;

    bigmod::Mp = (base_bigmod::L)->insert(bigmod::M);
  }


   //
   // ***** operator overloading *****
   //

   bigmod operator - (const bigmod & a)
    {
      bigmod c(a);
      if (!c.I.is_zero())
       {
	 c.I.negate();
	 add(c.I, c.I, bigmod::M);
       }
      return c;
    }



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

   void bigmod::randomize()
    {
      I.assign(::randomize(bigmod::M));
      if (I.compare(bigmod::M) == 0) 
         I.assign_zero();
    }

   bigmod randomize()
    {
      bigmod c;
      c.I.assign(::randomize(bigmod::M));
      if (c.I.compare(bigmod::M) == 0) 
         c.I.assign_zero();
      return c;
    }
	
	
   //
   // ***** input / output *****
   //

   istream & operator >> (istream & in, bigmod & a)
    {
      in >> a.I;
      a.normalize();
      return in;
    }

   ostream & operator << (ostream & out, const bigmod & a)
    {
      out << a.I;
      return out;
    }

   int
   string_to_bigmod(char *s, bigmod & a)
    {
      int i = string_to_bigint(s, a.I);
      a.normalize();
      return i;
    }

   int
   bigmod_to_string(const bigmod & a, char *s)
    {
      return bigint_to_string(a.I, s);
    }


   //
   // using fread/fwrite
   //

   void bigmod::
   read_from_file(FILE * fp)
    {
      I.read_from_file(fp);
      this->normalize();
    }

   void bigmod::
   write_to_file(FILE * fp)
    {
      I.write_to_file(fp);
    }


   //
   // using fscanf/fprintf
   //

   void bigmod::
   scan_from_file(FILE * fp)
    {
      I.scan_from_file(fp);
      this->normalize();
    }

   void bigmod::
   print_to_file(FILE * fp)
    {
      I.print_to_file(fp);
    }

