#ifndef POSINT_H #define POSINT_H #include <iostream> #include <vector> /* This class represents an arbitrarily large integer * that is at least 0. It is represented by a vector of * digits, starting from the least-significant digit, and * with each digit between 0 and B-1. */ class PosInt { private: // It must ALWAYS be the case that B = Bbase ^ Bpow. // B is really the one to be concerned about for arithmetic; // Bbase just determines how the number looks for I/O operations. static int B; static int Bbase; static int Bpow; std::vector<int> digits; // Removes leading 0 digits void normalize(); // Result is -1, 0, or 1 if a is <, =, or > than b, // up to the specified length. static int compareDigits (const int* a, int alen, const int* b, int blen); // Computes dest += x, digit-wise static void addArray (int* dest, const int* x, int len); // Computes dest -= x, digit-wise static void subArray (int* dest, const int* x, int len); // Computes dest = dest * x, digit-wise static void mulArray (int* dest, int x, int len); // Computes dest = dest / x, digit-wise, and returns dest % x static int divArray (int* dest, int x, int len); // Computes division with remainder, digit-wise. static void divremArray (int* q, int* r, const int* x, int xlen, const int* y, int ylen); static void fastMulArray (int* dest, const int* x, const int* y, int len); public: // Computes division with remainder. After the call, we have // x = q*y + r, and 0 <= r < y. static void divrem (PosInt& q, PosInt& r, const PosInt& x, const PosInt& y); // Sets the base to base^pow. static void setBase(int base, int pow=1); PosInt() { } PosInt (int x) { set(x); } PosInt (const char* s) { read(s); } // I/O routines void print_array(std::ostream& out) const; void print(std::ostream& out) const; void read(std::istream& in); void read(const char* s); // Sets this PosInt to the given value void set (int x); void set (const PosInt& rhs); // Returns this PosInt as a regular int int convert () const; // Sets this PosInt to a random number between 0 and x-1 void rand (const PosInt& x); // Common comparison tests bool isZero() const { return digits.empty(); } bool isOne() const { return digits.size() == 1 && digits[0] == 1; } bool isEven() const; // Result is -1, 0, or 1 if this is <, =, or > than rhs. int compare (const PosInt& x) const; // this = x + y PosInt& add (const PosInt& x, const PosInt& y); // this = this + x PosInt& add (const PosInt& x); // this = x - y PosInt& sub (const PosInt& x, const PosInt& y); // this = this - x PosInt& sub (const PosInt& x); // this = x * y PosInt& mul (const PosInt& x, const PosInt& y); // this = this * x PosInt& mul (const PosInt& x) { PosInt temp(*this); return mul(temp, x); } // this = x / y PosInt& div (const PosInt& x, const PosInt& y) { PosInt temp; divrem(*this, temp, x, y); return *this; } // this = this / y PosInt& div (const PosInt& x) { PosInt temp; divrem(*this, temp, *this, x); return *this; } // this = x % y PosInt& mod (const PosInt& x, const PosInt& y) { PosInt temp; divrem(temp, *this, x, y); return *this; } // this = this % y PosInt& mod (const PosInt& x) { PosInt temp; divrem(temp, *this, *this, x); return *this; } // this = x ^ y PosInt& pow (const PosInt& x, const PosInt& y); // this = this ^ x PosInt& pow (const PosInt& x) { return pow(*this, x); } // this = gcd(x,y) PosInt& gcd (const PosInt& x, const PosInt& y); // this = gcd(x,y) = s*x - t*y // NOTE THE MINUS SIGN! This is required so that both s and t are // always non-negative. PosInt& xgcd (PosInt& s, PosInt& t, const PosInt& x, const PosInt& y); // return true/false if this is PROBABLY prime bool MillerRabin () const; // Like "mul", only faster! PosInt& fasterMul (const PosInt& x, const PosInt& y); }; std::ostream& operator<< (std::ostream& out, const PosInt& x); std::istream& operator>> (std::istream& out, PosInt& x); #endif // POSINT_H