Commit | Line | Data |
---|---|---|
b35b6967 MM |
1 | #ifndef BIGUNSIGNEDINABASE_H |
2 | #define BIGUNSIGNEDINABASE_H | |
05780f4b MM |
3 | |
4 | #include "NumberlikeArray.hh" | |
5 | #include "BigUnsigned.hh" | |
6 | #include <string> | |
7 | ||
8 | /* | |
8cad5ca9 MM |
9 | * A BigUnsignedInABase object represents a nonnegative integer of size limited |
10 | * only by available memory, represented in a user-specified base that can fit | |
11 | * in an `unsigned short' (most can, and this saves memory). | |
6e1e0f2f | 12 | * |
8cad5ca9 MM |
13 | * BigUnsignedInABase is intended as an intermediary class with little |
14 | * functionality of its own. BigUnsignedInABase objects can be constructed | |
15 | * from, and converted to, BigUnsigneds (requiring multiplication, mods, etc.) | |
16 | * and `std::string's (by switching digit values for appropriate characters). | |
6e1e0f2f MM |
17 | * |
18 | * BigUnsignedInABase is similar to BigUnsigned. Note the following: | |
19 | * | |
8cad5ca9 MM |
20 | * (1) They represent the number in exactly the same way, except that |
21 | * BigUnsignedInABase uses ``digits'' (or Digit) where BigUnsigned uses | |
6e1e0f2f MM |
22 | * ``blocks'' (or Blk). |
23 | * | |
8cad5ca9 MM |
24 | * (2) Both use the management features of NumberlikeArray. (In fact, my desire |
25 | * to add a BigUnsignedInABase class without duplicating a lot of code led me to | |
26 | * introduce NumberlikeArray.) | |
6e1e0f2f | 27 | * |
8cad5ca9 MM |
28 | * (3) The only arithmetic operation supported by BigUnsignedInABase is an |
29 | * equality test. Use BigUnsigned for arithmetic. | |
6e1e0f2f | 30 | */ |
05780f4b MM |
31 | |
32 | class BigUnsignedInABase : protected NumberlikeArray<unsigned short> { | |
5ff40cf5 | 33 | |
2301f99c | 34 | public: |
8cad5ca9 MM |
35 | // The digits of a BigUnsignedInABase are unsigned shorts. |
36 | typedef unsigned short Digit; | |
37 | // That's also the type of a base. | |
05780f4b | 38 | typedef Digit Base; |
5ff40cf5 | 39 | |
2301f99c | 40 | protected: |
8cad5ca9 MM |
41 | // The base in which this BigUnsignedInABase is expressed |
42 | Base base; | |
5ff40cf5 | 43 | |
8cad5ca9 MM |
44 | // Creates a BigUnsignedInABase with a capacity; for internal use. |
45 | BigUnsignedInABase(int, Index c) : NumberlikeArray<Digit>(0, c) {} | |
5ff40cf5 | 46 | |
8cad5ca9 MM |
47 | // Decreases len to eliminate any leading zero digits. |
48 | void zapLeadingZeros() { | |
05780f4b MM |
49 | while (len > 0 && blk[len - 1] == 0) |
50 | len--; | |
51 | } | |
5ff40cf5 | 52 | |
2301f99c | 53 | public: |
8cad5ca9 MM |
54 | // Constructs zero in base 2. |
55 | BigUnsignedInABase() : NumberlikeArray<Digit>(), base(2) {} | |
5ff40cf5 | 56 | |
8cad5ca9 MM |
57 | // Copy constructor |
58 | BigUnsignedInABase(const BigUnsignedInABase &x) : NumberlikeArray<Digit>(x), base(x.base) {} | |
59 | ||
60 | // Assignment operator | |
61 | void operator =(const BigUnsignedInABase &x) { | |
05780f4b MM |
62 | NumberlikeArray<Digit>::operator =(x); |
63 | base = x.base; | |
64 | } | |
5ff40cf5 | 65 | |
8cad5ca9 MM |
66 | // Constructor that copies from a given array of digits. |
67 | BigUnsignedInABase(const Digit *d, Index l, Base base); | |
68 | ||
69 | // Destructor. NumberlikeArray does the delete for us. | |
70 | ~BigUnsignedInABase() {} | |
5ff40cf5 | 71 | |
05780f4b MM |
72 | // LINKS TO BIGUNSIGNED |
73 | BigUnsignedInABase(const BigUnsigned &x, Base base); | |
74 | operator BigUnsigned() const; | |
5ff40cf5 | 75 | |
05780f4b | 76 | /* LINKS TO STRINGS |
6e1e0f2f | 77 | * |
8cad5ca9 MM |
78 | * These use the symbols ``0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'' to |
79 | * represent digits of 0 through 35. When parsing strings, lowercase is | |
80 | * also accepted. | |
6e1e0f2f | 81 | * |
8cad5ca9 MM |
82 | * All string representations are big-endian (big-place-value digits |
83 | * first). (Computer scientists have adopted zero-based counting; why | |
84 | * can't they tolerate little-endian numbers?) | |
6e1e0f2f MM |
85 | * |
86 | * No string representation has a ``base indicator'' like ``0x''. | |
87 | * | |
8cad5ca9 MM |
88 | * An exception is made for zero: it is converted to ``0'' and not the |
89 | * empty string. | |
6e1e0f2f | 90 | * |
8cad5ca9 MM |
91 | * If you want different conventions, write your own routines to go |
92 | * between BigUnsignedInABase and strings. It's not hard. | |
6e1e0f2f | 93 | */ |
05780f4b MM |
94 | operator std::string() const; |
95 | BigUnsignedInABase(const std::string &s, Base base); | |
5ff40cf5 | 96 | |
2301f99c | 97 | public: |
8cad5ca9 MM |
98 | |
99 | // ACCESSORS | |
05780f4b | 100 | Base getBase() const { return base; } |
8cad5ca9 MM |
101 | |
102 | // Expose these from NumberlikeArray directly. | |
103 | NumberlikeArray<Digit>::getCapacity; | |
104 | NumberlikeArray<Digit>::getLength; | |
105 | ||
106 | /* Returns the requested digit, or 0 if it is beyond the length (as if | |
107 | * the number had 0s infinitely to the left). */ | |
05780f4b | 108 | Digit getDigit(Index i) const { return i >= len ? 0 : blk[i]; } |
5ff40cf5 | 109 | |
8cad5ca9 MM |
110 | // The number is zero if and only if the canonical length is zero. |
111 | bool isZero() const { return NumberlikeArray<Digit>::isEmpty(); } | |
112 | ||
113 | /* Equality test. For the purposes of this test, two BigUnsignedInABase | |
114 | * values must have the same base to be equal. */ | |
05780f4b MM |
115 | bool operator ==(const BigUnsignedInABase &x) const { |
116 | return base == x.base && NumberlikeArray<Digit>::operator ==(x); | |
117 | } | |
118 | bool operator !=(const BigUnsignedInABase &x) const { return !operator ==(x); } | |
5ff40cf5 | 119 | |
05780f4b MM |
120 | }; |
121 | ||
122 | #endif |