BigUnsigned.hh 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. #ifndef BIGUNSIGNED_H
  2. #define BIGUNSIGNED_H
  3. #include "NumberlikeArray.hh"
  4. /* A BigUnsigned object represents a nonnegative integer of size limited only by
  5. * available memory. BigUnsigneds support most mathematical operators and can
  6. * be converted to and from most primitive integer types.
  7. *
  8. * The number is stored as a NumberlikeArray of unsigned longs as if it were
  9. * written in base 256^sizeof(unsigned long). The least significant block is
  10. * first, and the length is such that the most significant block is nonzero. */
  11. class BigUnsigned : protected NumberlikeArray<unsigned long> {
  12. public:
  13. // Enumeration for the result of a comparison.
  14. enum CmpRes { less = -1, equal = 0, greater = 1 };
  15. // BigUnsigneds are built with a Blk type of unsigned long.
  16. typedef unsigned long Blk;
  17. typedef NumberlikeArray<Blk>::Index Index;
  18. using NumberlikeArray<Blk>::N;
  19. protected:
  20. // Creates a BigUnsigned with a capacity; for internal use.
  21. BigUnsigned(int, Index c) : NumberlikeArray<Blk>(0, c) {}
  22. // Decreases len to eliminate any leading zero blocks.
  23. void zapLeadingZeros() {
  24. while (len > 0 && blk[len - 1] == 0)
  25. len--;
  26. }
  27. public:
  28. // Constructs zero.
  29. BigUnsigned() : NumberlikeArray<Blk>() {}
  30. // Copy constructor
  31. BigUnsigned(const BigUnsigned &x) : NumberlikeArray<Blk>(x) {}
  32. // Assignment operator
  33. void operator=(const BigUnsigned &x) {
  34. NumberlikeArray<Blk>::operator =(x);
  35. }
  36. // Constructor that copies from a given array of blocks.
  37. BigUnsigned(const Blk *b, Index blen) : NumberlikeArray<Blk>(b, blen) {
  38. // Eliminate any leading zeros we may have been passed.
  39. zapLeadingZeros();
  40. }
  41. // Destructor. NumberlikeArray does the delete for us.
  42. ~BigUnsigned() {}
  43. // Constructors from primitive integer types
  44. BigUnsigned(unsigned long x);
  45. BigUnsigned( long x);
  46. BigUnsigned(unsigned int x);
  47. BigUnsigned( int x);
  48. BigUnsigned(unsigned short x);
  49. BigUnsigned( short x);
  50. protected:
  51. // Helpers
  52. template <class X> void initFromPrimitive (X x);
  53. template <class X> void initFromSignedPrimitive(X x);
  54. public:
  55. /* Converters to primitive integer types
  56. * The implicit conversion operators caused trouble, so these are now
  57. * named. */
  58. unsigned long toUnsignedLong () const;
  59. long toLong () const;
  60. unsigned int toUnsignedInt () const;
  61. int toInt () const;
  62. unsigned short toUnsignedShort() const;
  63. short toShort () const;
  64. protected:
  65. // Helpers
  66. template <class X> X convertToSignedPrimitive() const;
  67. template <class X> X convertToPrimitive () const;
  68. public:
  69. // BIT/BLOCK ACCESSORS
  70. // Expose these from NumberlikeArray directly.
  71. using NumberlikeArray<Blk>::getCapacity;
  72. using NumberlikeArray<Blk>::getLength;
  73. /* Returns the requested block, or 0 if it is beyond the length (as if
  74. * the number had 0s infinitely to the left). */
  75. Blk getBlock(Index i) const { return i >= len ? 0 : blk[i]; }
  76. /* Sets the requested block. The number grows or shrinks as necessary. */
  77. void setBlock(Index i, Blk newBlock);
  78. // The number is zero if and only if the canonical length is zero.
  79. bool isZero() const { return NumberlikeArray<Blk>::isEmpty(); }
  80. /* Returns the length of the number in bits, i.e., zero if the number
  81. * is zero and otherwise one more than the largest value of bi for
  82. * which getBit(bi) returns true. */
  83. Index bitLength() const;
  84. /* Get the state of bit bi, which has value 2^bi. Bits beyond the
  85. * number's length are considered to be 0. */
  86. bool getBit(Index bi) const {
  87. return (getBlock(bi / N) & (Blk(1) << (bi % N))) != 0;
  88. }
  89. /* Sets the state of bit bi to newBit. The number grows or shrinks as
  90. * necessary. */
  91. void setBit(Index bi, bool newBit);
  92. // COMPARISONS
  93. // Compares this to x like Perl's <=>
  94. CmpRes compareTo(const BigUnsigned &x) const;
  95. // Ordinary comparison operators
  96. bool operator ==(const BigUnsigned &x) const {
  97. return NumberlikeArray<Blk>::operator ==(x);
  98. }
  99. bool operator !=(const BigUnsigned &x) const {
  100. return NumberlikeArray<Blk>::operator !=(x);
  101. }
  102. bool operator < (const BigUnsigned &x) const { return compareTo(x) == less ; }
  103. bool operator <=(const BigUnsigned &x) const { return compareTo(x) != greater; }
  104. bool operator >=(const BigUnsigned &x) const { return compareTo(x) != less ; }
  105. bool operator > (const BigUnsigned &x) const { return compareTo(x) == greater; }
  106. /*
  107. * BigUnsigned and BigInteger both provide three kinds of operators.
  108. * Here ``big-integer'' refers to BigInteger or BigUnsigned.
  109. *
  110. * (1) Overloaded ``return-by-value'' operators:
  111. * +, -, *, /, %, unary -, &, |, ^, <<, >>.
  112. * Big-integer code using these operators looks identical to code using
  113. * the primitive integer types. These operators take one or two
  114. * big-integer inputs and return a big-integer result, which can then
  115. * be assigned to a BigInteger variable or used in an expression.
  116. * Example:
  117. * BigInteger a(1), b = 1;
  118. * BigInteger c = a + b;
  119. *
  120. * (2) Overloaded assignment operators:
  121. * +=, -=, *=, /=, %=, flipSign, &=, |=, ^=, <<=, >>=, ++, --.
  122. * Again, these are used on big integers just like on ints. They take
  123. * one writable big integer that both provides an operand and receives a
  124. * result. Most also take a second read-only operand.
  125. * Example:
  126. * BigInteger a(1), b(1);
  127. * a += b;
  128. *
  129. * (3) Copy-less operations: `add', `subtract', etc.
  130. * These named methods take operands as arguments and store the result
  131. * in the receiver (*this), avoiding unnecessary copies and allocations.
  132. * `divideWithRemainder' is special: it both takes the dividend from and
  133. * stores the remainder into the receiver, and it takes a separate
  134. * object in which to store the quotient. NOTE: If you are wondering
  135. * why these don't return a value, you probably mean to use the
  136. * overloaded return-by-value operators instead.
  137. *
  138. * Examples:
  139. * BigInteger a(43), b(7), c, d;
  140. *
  141. * c = a + b; // Now c == 50.
  142. * c.add(a, b); // Same effect but without the two copies.
  143. *
  144. * c.divideWithRemainder(b, d);
  145. * // 50 / 7; now d == 7 (quotient) and c == 1 (remainder).
  146. *
  147. * // ``Aliased'' calls now do the right thing using a temporary
  148. * // copy, but see note on `divideWithRemainder'.
  149. * a.add(a, b);
  150. */
  151. // COPY-LESS OPERATIONS
  152. // These 8: Arguments are read-only operands, result is saved in *this.
  153. void add(const BigUnsigned &a, const BigUnsigned &b);
  154. void subtract(const BigUnsigned &a, const BigUnsigned &b);
  155. void multiply(const BigUnsigned &a, const BigUnsigned &b);
  156. void bitAnd(const BigUnsigned &a, const BigUnsigned &b);
  157. void bitOr(const BigUnsigned &a, const BigUnsigned &b);
  158. void bitXor(const BigUnsigned &a, const BigUnsigned &b);
  159. /* Negative shift amounts translate to opposite-direction shifts,
  160. * except for -2^(8*sizeof(int)-1) which is unimplemented. */
  161. void bitShiftLeft(const BigUnsigned &a, int b);
  162. void bitShiftRight(const BigUnsigned &a, int b);
  163. /* `a.divideWithRemainder(b, q)' is like `q = a / b, a %= b'.
  164. * / and % use semantics similar to Knuth's, which differ from the
  165. * primitive integer semantics under division by zero. See the
  166. * implementation in BigUnsigned.cc for details.
  167. * `a.divideWithRemainder(b, a)' throws an exception: it doesn't make
  168. * sense to write quotient and remainder into the same variable. */
  169. void divideWithRemainder(const BigUnsigned &b, BigUnsigned &q);
  170. /* `divide' and `modulo' are no longer offered. Use
  171. * `divideWithRemainder' instead. */
  172. // OVERLOADED RETURN-BY-VALUE OPERATORS
  173. BigUnsigned operator +(const BigUnsigned &x) const;
  174. BigUnsigned operator -(const BigUnsigned &x) const;
  175. BigUnsigned operator *(const BigUnsigned &x) const;
  176. BigUnsigned operator /(const BigUnsigned &x) const;
  177. BigUnsigned operator %(const BigUnsigned &x) const;
  178. /* OK, maybe unary minus could succeed in one case, but it really
  179. * shouldn't be used, so it isn't provided. */
  180. BigUnsigned operator &(const BigUnsigned &x) const;
  181. BigUnsigned operator |(const BigUnsigned &x) const;
  182. BigUnsigned operator ^(const BigUnsigned &x) const;
  183. BigUnsigned operator <<(int b) const;
  184. BigUnsigned operator >>(int b) const;
  185. // OVERLOADED ASSIGNMENT OPERATORS
  186. void operator +=(const BigUnsigned &x);
  187. void operator -=(const BigUnsigned &x);
  188. void operator *=(const BigUnsigned &x);
  189. void operator /=(const BigUnsigned &x);
  190. void operator %=(const BigUnsigned &x);
  191. void operator &=(const BigUnsigned &x);
  192. void operator |=(const BigUnsigned &x);
  193. void operator ^=(const BigUnsigned &x);
  194. void operator <<=(int b);
  195. void operator >>=(int b);
  196. /* INCREMENT/DECREMENT OPERATORS
  197. * To discourage messy coding, these do not return *this, so prefix
  198. * and postfix behave the same. */
  199. void operator ++( );
  200. void operator ++(int);
  201. void operator --( );
  202. void operator --(int);
  203. // Helper function that needs access to BigUnsigned internals
  204. friend Blk getShiftedBlock(const BigUnsigned &num, Index x,
  205. unsigned int y);
  206. // See BigInteger.cc.
  207. template <class X>
  208. friend X convertBigUnsignedToPrimitiveAccess(const BigUnsigned &a);
  209. };
  210. /* Implementing the return-by-value and assignment operators in terms of the
  211. * copy-less operations. The copy-less operations are responsible for making
  212. * any necessary temporary copies to work around aliasing. */
  213. inline BigUnsigned BigUnsigned::operator +(const BigUnsigned &x) const {
  214. BigUnsigned ans;
  215. ans.add(*this, x);
  216. return ans;
  217. }
  218. inline BigUnsigned BigUnsigned::operator -(const BigUnsigned &x) const {
  219. BigUnsigned ans;
  220. ans.subtract(*this, x);
  221. return ans;
  222. }
  223. inline BigUnsigned BigUnsigned::operator *(const BigUnsigned &x) const {
  224. BigUnsigned ans;
  225. ans.multiply(*this, x);
  226. return ans;
  227. }
  228. inline BigUnsigned BigUnsigned::operator /(const BigUnsigned &x) const {
  229. if (x.isZero()) throw "BigUnsigned::operator /: division by zero";
  230. BigUnsigned q, r;
  231. r = *this;
  232. r.divideWithRemainder(x, q);
  233. return q;
  234. }
  235. inline BigUnsigned BigUnsigned::operator %(const BigUnsigned &x) const {
  236. if (x.isZero()) throw "BigUnsigned::operator %: division by zero";
  237. BigUnsigned q, r;
  238. r = *this;
  239. r.divideWithRemainder(x, q);
  240. return r;
  241. }
  242. inline BigUnsigned BigUnsigned::operator &(const BigUnsigned &x) const {
  243. BigUnsigned ans;
  244. ans.bitAnd(*this, x);
  245. return ans;
  246. }
  247. inline BigUnsigned BigUnsigned::operator |(const BigUnsigned &x) const {
  248. BigUnsigned ans;
  249. ans.bitOr(*this, x);
  250. return ans;
  251. }
  252. inline BigUnsigned BigUnsigned::operator ^(const BigUnsigned &x) const {
  253. BigUnsigned ans;
  254. ans.bitXor(*this, x);
  255. return ans;
  256. }
  257. inline BigUnsigned BigUnsigned::operator <<(int b) const {
  258. BigUnsigned ans;
  259. ans.bitShiftLeft(*this, b);
  260. return ans;
  261. }
  262. inline BigUnsigned BigUnsigned::operator >>(int b) const {
  263. BigUnsigned ans;
  264. ans.bitShiftRight(*this, b);
  265. return ans;
  266. }
  267. inline void BigUnsigned::operator +=(const BigUnsigned &x) {
  268. add(*this, x);
  269. }
  270. inline void BigUnsigned::operator -=(const BigUnsigned &x) {
  271. subtract(*this, x);
  272. }
  273. inline void BigUnsigned::operator *=(const BigUnsigned &x) {
  274. multiply(*this, x);
  275. }
  276. inline void BigUnsigned::operator /=(const BigUnsigned &x) {
  277. if (x.isZero()) throw "BigUnsigned::operator /=: division by zero";
  278. /* The following technique is slightly faster than copying *this first
  279. * when x is large. */
  280. BigUnsigned q;
  281. divideWithRemainder(x, q);
  282. // *this contains the remainder, but we overwrite it with the quotient.
  283. *this = q;
  284. }
  285. inline void BigUnsigned::operator %=(const BigUnsigned &x) {
  286. if (x.isZero()) throw "BigUnsigned::operator %=: division by zero";
  287. BigUnsigned q;
  288. // Mods *this by x. Don't care about quotient left in q.
  289. divideWithRemainder(x, q);
  290. }
  291. inline void BigUnsigned::operator &=(const BigUnsigned &x) {
  292. bitAnd(*this, x);
  293. }
  294. inline void BigUnsigned::operator |=(const BigUnsigned &x) {
  295. bitOr(*this, x);
  296. }
  297. inline void BigUnsigned::operator ^=(const BigUnsigned &x) {
  298. bitXor(*this, x);
  299. }
  300. inline void BigUnsigned::operator <<=(int b) {
  301. bitShiftLeft(*this, b);
  302. }
  303. inline void BigUnsigned::operator >>=(int b) {
  304. bitShiftRight(*this, b);
  305. }
  306. /* Templates for conversions of BigUnsigned to and from primitive integers.
  307. * BigInteger.cc needs to instantiate convertToPrimitive, and the uses in
  308. * BigUnsigned.cc didn't do the trick; I think g++ inlined convertToPrimitive
  309. * instead of generating linkable instantiations. So for consistency, I put
  310. * all the templates here. */
  311. // CONSTRUCTION FROM PRIMITIVE INTEGERS
  312. /* Initialize this BigUnsigned from the given primitive integer. The same
  313. * pattern works for all primitive integer types, so I put it into a template to
  314. * reduce code duplication. (Don't worry: this is protected and we instantiate
  315. * it only with primitive integer types.) Type X could be signed, but x is
  316. * known to be nonnegative. */
  317. template <class X>
  318. void BigUnsigned::initFromPrimitive(X x) {
  319. if (x == 0)
  320. ; // NumberlikeArray already initialized us to zero.
  321. else {
  322. // Create a single block. blk is NULL; no need to delete it.
  323. cap = 1;
  324. blk = new Blk[1];
  325. len = 1;
  326. blk[0] = Blk(x);
  327. }
  328. }
  329. /* Ditto, but first check that x is nonnegative. I could have put the check in
  330. * initFromPrimitive and let the compiler optimize it out for unsigned-type
  331. * instantiations, but I wanted to avoid the warning stupidly issued by g++ for
  332. * a condition that is constant in *any* instantiation, even if not in all. */
  333. template <class X>
  334. void BigUnsigned::initFromSignedPrimitive(X x) {
  335. if (x < 0)
  336. throw "BigUnsigned constructor: "
  337. "Cannot construct a BigUnsigned from a negative number";
  338. else
  339. initFromPrimitive(x);
  340. }
  341. // CONVERSION TO PRIMITIVE INTEGERS
  342. /* Template with the same idea as initFromPrimitive. This might be slightly
  343. * slower than the previous version with the masks, but it's much shorter and
  344. * clearer, which is the library's stated goal. */
  345. template <class X>
  346. X BigUnsigned::convertToPrimitive() const {
  347. if (len == 0)
  348. // The number is zero; return zero.
  349. return 0;
  350. else if (len == 1) {
  351. // The single block might fit in an X. Try the conversion.
  352. X x = X(blk[0]);
  353. // Make sure the result accurately represents the block.
  354. if (Blk(x) == blk[0])
  355. // Successful conversion.
  356. return x;
  357. // Otherwise fall through.
  358. }
  359. throw "BigUnsigned::to<Primitive>: "
  360. "Value is too big to fit in the requested type";
  361. }
  362. /* Wrap the above in an x >= 0 test to make sure we got a nonnegative result,
  363. * not a negative one that happened to convert back into the correct nonnegative
  364. * one. (E.g., catch incorrect conversion of 2^31 to the long -2^31.) Again,
  365. * separated to avoid a g++ warning. */
  366. template <class X>
  367. X BigUnsigned::convertToSignedPrimitive() const {
  368. X x = convertToPrimitive<X>();
  369. if (x >= 0)
  370. return x;
  371. else
  372. throw "BigUnsigned::to(Primitive): "
  373. "Value is too big to fit in the requested type";
  374. }
  375. #endif