// Rascal, the Advanced Scientific CALculator
// Copyright (C) 2001, Sebastian Ritterbusch (Rascal@Ritterbusch.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.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more detauls.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//

// Long Integer Library
// (C) 1999 Jochen Suckfüll
// (C) 2001 Sebastian Ritterbusch

#ifndef LANGZAHL_HPP_INCLUDED
#define LANGZAHL_HPP_INCLUDED

#include <iostream>
#include <string>

using std::string;

#include <iomanip>
#include <stdlib.h>
#include <time.h>

#undef RAND_MAX
#define RAND_MAX 100000000
#define ILOG232 0.104
#define LOG232 9.633
#define MAX(a,b) (a>b?a:b)

#define LONG32 int

extern class init_rand
{
   public:
   init_rand() { srand(time(0)); }
} randomstate;

class lsize
{
   private:
   int s;
   public:
   lsize(int i) throw():s(i) { }
   ~lsize() { };
   int size() const { return s; }
};

class langzahl
{
   private:
   int longs;
   int sign;
   LONG32 *dat;
   
   public:
   langzahl() throw():longs(0),sign(0),dat(0) { };
   langzahl(const LONG32) throw();
   langzahl(const lsize &) throw();
   langzahl(const string &) throw();
   langzahl(const langzahl &) throw();
   
   ~langzahl() throw() { delete [] dat; }

   void kuerze() throw();

   friend istream &operator >>(istream &,langzahl &) throw();
   friend string  &operator >>(string &,langzahl &) throw();
   friend ostream &operator <<(ostream &,const langzahl &) throw();
   friend string  &operator <<(string &,const langzahl &) throw();

   langzahl &operator =(const langzahl &) throw();
   langzahl &operator =(LONG32) throw();
   langzahl &operator =(const char *) throw();

   friend bool operator ==(const langzahl &,const langzahl &) throw();
   friend bool operator !=(const langzahl &,const langzahl &) throw();
   friend bool operator <=(const langzahl &,const langzahl &) throw();
   friend bool operator >=(const langzahl &,const langzahl &) throw();
   friend bool operator <(const langzahl &,const langzahl &) throw();
   friend bool operator >(const langzahl &,const langzahl &) throw();
   
   friend inline bool operator ==(const langzahl &a,LONG32 b) throw() { return a==langzahl(b); }
   friend inline bool operator !=(const langzahl &a,LONG32 b) throw() { return a!=langzahl(b); }
   friend inline bool operator <=(const langzahl &a,LONG32 b) throw() { return a<=langzahl(b); }
   friend inline bool operator >=(const langzahl &a,LONG32 b) throw() { return a>=langzahl(b); }
   friend inline bool operator <(const langzahl &a,LONG32 b) throw() { return a<langzahl(b); }
   friend inline bool operator >(const langzahl &a,LONG32 b) throw() { return a>langzahl(b); }

   friend inline bool operator ==(LONG32 a,const langzahl & b) throw() { return langzahl(a)==b; }
   friend inline bool operator !=(LONG32 a,const langzahl & b) throw() { return langzahl(a)!=b; }
   friend inline bool operator <=(LONG32 a,const langzahl & b) throw() { return langzahl(a)<=b; }
   friend inline bool operator >=(LONG32 a,const langzahl & b) throw() { return langzahl(a)>=b; }
   friend inline bool operator <(LONG32 a,const langzahl & b) throw() { return langzahl(a)<b; }
   friend inline bool operator >(LONG32 a,const langzahl & b) throw() { return langzahl(a)>b; }


   friend bool eqzero(const langzahl &) throw();
   friend bool grzero(const langzahl &) throw();
   friend bool ltzero(const langzahl &) throw();

   friend langzahl operator -(const langzahl &) throw();
   friend langzahl operator %(langzahl,langzahl) throw();
   friend inline langzahl operator %(const langzahl &a,LONG32 b) throw() { return a%langzahl(b); }
   friend inline langzahl operator %(LONG32 a,const langzahl &b) throw() { return langzahl(a)%b; }
   friend langzahl operator /(langzahl,langzahl) throw();
   friend inline langzahl operator /(const langzahl &a,LONG32 b) throw() { return a/langzahl(b); }
   friend inline langzahl operator /(LONG32 a,const langzahl &b) throw() { return langzahl(a)/b; }

   friend langzahl _llplus(const langzahl &,const langzahl &) throw();
   friend langzahl _llminus(const langzahl &,const langzahl &) throw();
   friend langzahl operator +(const langzahl &,const langzahl &) throw();
   friend inline langzahl operator +(const langzahl &a,LONG32 b) throw() { return a+langzahl(b); }
   friend inline langzahl operator +(LONG32 a,const langzahl &b) throw() { return langzahl(a)+b; }
   friend langzahl operator -(const langzahl &,const langzahl &) throw();
   friend inline langzahl operator -(const langzahl &a,LONG32 b) throw() { return a-langzahl(b); }
   friend inline langzahl operator -(LONG32 a,const langzahl &b) throw() { return langzahl(a)-b; }
   friend langzahl operator *(const langzahl &,const langzahl &) throw();
   friend inline langzahl operator *(const langzahl &a,LONG32 b) throw() { return a*langzahl(b); }
   friend inline langzahl operator *(LONG32 a,const langzahl &b) throw() { return langzahl(a)*b; }

   langzahl &operator +=(const langzahl &) throw();
   langzahl &operator -=(const langzahl &) throw();
   langzahl &operator *=(const langzahl &) throw();
   langzahl &operator %=(const langzahl &) throw();
   
   // addm(a,b,m)=(a+b)%m
   friend langzahl addm(const langzahl &,const langzahl &,const langzahl &) throw();
   // subm(a,b,m)=(a-b)%m
   friend langzahl subm(const langzahl &,const langzahl &,const langzahl &) throw();
   // multm(a,b,m)=(a*b)%m
   friend langzahl multm(const langzahl &,const langzahl &,const langzahl &) throw();
   friend langzahl potm(const langzahl &,const int,const langzahl &) throw();
   friend langzahl potm(const langzahl &,const langzahl &,const langzahl &) throw();

   friend langzahl pow(const langzahl &,const langzahl &) throw();
   friend langzahl pow(const langzahl &,const int) throw();
   friend langzahl operator *=(langzahl &,const int) throw();
   friend langzahl operator /=(langzahl &,const int) throw();

   // ggT liefert immer einen positiven Wert
   friend langzahl ggT(const langzahl &,const langzahl &) throw();

   friend void div2(langzahl &) throw();
   friend void mul2(langzahl &) throw();

   // Rabin-Miller-Pseudoprimtest
   // Ist n pseudoprim zur Basis a?
   // 0-> sicher nicht,   1-> *wahrscheinlich* schon
   friend bool pprim(const langzahl &n,const langzahl &a) throw();

   // erzeuge zufaellige langzahl mit n longs
   friend langzahl lrandom(const int n) throw();

   friend langzahl fak(LONG32) throw();

   // Pollard p-1 Methode zur Faktorisierung
   friend langzahl pollard(const langzahl &) throw();
   
   int operator !() const throw();
   
   template <class T>
   friend T convert(const langzahl & a) throw();


   inline operator double(void) const { return convert<double>(*this); }

};

template <class T>
T convert(const langzahl & a) throw()
{
   T dest(0);
   T mul(1);
   for(int i=0;i<a.longs;i++)
   {
      dest=dest+mul*a.dat[i];
      mul=mul*100000000;
   }
   if(a.sign)
      return -dest;
   else
      return dest;
}


#endif


syntax highlighted by Code2HTML, v. 0.9.1