1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#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