├── BigInteger.cpp ├── BigInteger.hpp ├── BigIntegerAlgorithms.cpp ├── BigIntegerAlgorithms.hpp ├── BigIntegerLibrary.hpp ├── BigIntegerUtils.cpp ├── BigIntegerUtils.hpp ├── BigUnsigned.cpp ├── BigUnsigned.hpp ├── BigUnsignedInABase.cpp ├── BigUnsignedInABase.hpp ├── NumberlikeArray.hpp ├── README.md ├── eos_mem_wrapper.cpp └── eos_mem_wrapper.hpp /BigInteger.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This source adapted from https://mattmccutchen.net/bigint/ by Mithrilcoin.io for EOS.IO smart contract. 3 | */ 4 | 5 | #include "BigInteger.hpp" 6 | 7 | void BigInteger::operator =(const BigInteger &x) { 8 | // Calls like a = a have no effect 9 | if (this == &x) 10 | return; 11 | // Copy sign 12 | sign = x.sign; 13 | // Copy the rest 14 | mag = x.mag; 15 | } 16 | 17 | BigInteger::BigInteger(const Blk *b, Index blen, Sign s) : mag(b, blen) { 18 | switch (s) { 19 | case zero: 20 | //swapnibble 21 | assert( mag.isZero() 22 | ,"BigInteger::BigInteger(const Blk *, Index, Sign): Cannot use a sign of zero with a nonzero magnitude"); 23 | // if (!mag.isZero()) 24 | // throw "BigInteger::BigInteger(const Blk *, Index, Sign): Cannot use a sign of zero with a nonzero magnitude"; 25 | sign = zero; 26 | break; 27 | case positive: 28 | case negative: 29 | // If the magnitude is zero, force the sign to zero. 30 | sign = mag.isZero() ? zero : s; 31 | break; 32 | default: 33 | /* g++ seems to be optimizing out this case on the assumption 34 | * that the sign is a valid member of the enumeration. Oh well. */ 35 | //swapnibble throw "BigInteger::BigInteger(const Blk *, Index, Sign): Invalid sign"; 36 | assert( 0, "BigInteger::BigInteger(const Blk *, Index, Sign): Invalid sign"); 37 | break; 38 | } 39 | } 40 | 41 | BigInteger::BigInteger(const BigUnsigned &x, Sign s) : mag(x) { 42 | switch (s) { 43 | case zero: 44 | //swapnibble 45 | assert( mag.isZero() 46 | ,"BigInteger::BigInteger(const BigUnsigned &, Sign): Cannot use a sign of zero with a nonzero magnitude"); 47 | 48 | // if (!mag.isZero()) 49 | // throw "BigInteger::BigInteger(const BigUnsigned &, Sign): Cannot use a sign of zero with a nonzero magnitude"; 50 | sign = zero; 51 | break; 52 | case positive: 53 | case negative: 54 | // If the magnitude is zero, force the sign to zero. 55 | sign = mag.isZero() ? zero : s; 56 | break; 57 | default: 58 | /* g++ seems to be optimizing out this case on the assumption 59 | * that the sign is a valid member of the enumeration. Oh well. */ 60 | //swapnibble throw "BigInteger::BigInteger(const BigUnsigned &, Sign): Invalid sign"; 61 | assert( 0, "BigInteger::BigInteger(const BigUnsigned &, Sign): Invalid sign"); 62 | break; 63 | } 64 | } 65 | 66 | /* CONSTRUCTION FROM PRIMITIVE INTEGERS 67 | * Same idea as in BigUnsigned.cc, except that negative input results in a 68 | * negative BigInteger instead of an exception. */ 69 | 70 | // Done longhand to let us use initialization. 71 | BigInteger::BigInteger(unsigned long x) : mag(x) { sign = mag.isZero() ? zero : positive; } 72 | BigInteger::BigInteger(unsigned int x) : mag(x) { sign = mag.isZero() ? zero : positive; } 73 | BigInteger::BigInteger(unsigned short x) : mag(x) { sign = mag.isZero() ? zero : positive; } 74 | 75 | 76 | 77 | BigInteger::BigInteger(long x) : sign(signOf(x)), mag(magOf(x)) {} 78 | BigInteger::BigInteger(int x) : sign(signOf(x)), mag(magOf(x)) {} 79 | BigInteger::BigInteger(short x) : sign(signOf(x)), mag(magOf(x)) {} 80 | 81 | // CONVERSION TO PRIMITIVE INTEGERS 82 | 83 | /* Reuse BigUnsigned's conversion to an unsigned primitive integer. 84 | * The friend is a separate function rather than 85 | * BigInteger::convertToUnsignedPrimitive to avoid requiring BigUnsigned to 86 | * declare BigInteger. */ 87 | template 88 | X convertBigUnsignedToPrimitiveAccess(const BigUnsigned &a) { 89 | return a.convertToPrimitive(); 90 | } 91 | 92 | template 93 | X BigInteger::convertToUnsignedPrimitive() const { 94 | //swapnibble 95 | assert( sign != negative 96 | , "BigInteger::to: Cannot convert a negative integer to an unsigned type"); 97 | 98 | return convertBigUnsignedToPrimitiveAccess(mag); 99 | /* 100 | if (sign == negative) 101 | throw "BigInteger::to: " 102 | "Cannot convert a negative integer to an unsigned type"; 103 | else 104 | return convertBigUnsignedToPrimitiveAccess(mag); 105 | */ 106 | } 107 | 108 | /* Similar to BigUnsigned::convertToPrimitive, but split into two cases for 109 | * nonnegative and negative numbers. */ 110 | template 111 | X BigInteger::convertToSignedPrimitive() const { 112 | if (sign == zero) 113 | return 0; 114 | else if (mag.getLength() == 1) { 115 | // The single block might fit in an X. Try the conversion. 116 | Blk b = mag.getBlock(0); 117 | if (sign == positive) { 118 | X x = X(b); 119 | if (x >= 0 && Blk(x) == b) 120 | return x; 121 | } else { 122 | X x = -X(b); 123 | /* UX(...) needed to avoid rejecting conversion of 124 | * -2^15 to a short. */ 125 | if (x < 0 && Blk(UX(-x)) == b) 126 | return x; 127 | } 128 | // Otherwise fall through. 129 | } 130 | 131 | // throw "BigInteger::to: " 132 | // "Value is too big to fit in the requested type"; 133 | assert(0, "BigInteger::to: Value is too big to fit in the requested type"); 134 | return 0; 135 | } 136 | 137 | unsigned long BigInteger::toUnsignedLong () const { return convertToUnsignedPrimitive (); } 138 | unsigned int BigInteger::toUnsignedInt () const { return convertToUnsignedPrimitive (); } 139 | unsigned short BigInteger::toUnsignedShort() const { return convertToUnsignedPrimitive (); } 140 | long BigInteger::toLong () const { return convertToSignedPrimitive (); } 141 | int BigInteger::toInt () const { return convertToSignedPrimitive (); } 142 | short BigInteger::toShort () const { return convertToSignedPrimitive (); } 143 | 144 | // COMPARISON 145 | BigInteger::CmpRes BigInteger::compareTo(const BigInteger &x) const { 146 | // A greater sign implies a greater number 147 | if (sign < x.sign) 148 | return less; 149 | else if (sign > x.sign) 150 | return greater; 151 | else switch (sign) { 152 | // If the signs are the same... 153 | case zero: 154 | return equal; // Two zeros are equal 155 | case positive: 156 | // Compare the magnitudes 157 | return mag.compareTo(x.mag); 158 | case negative: 159 | // Compare the magnitudes, but return the opposite result 160 | return CmpRes(-mag.compareTo(x.mag)); 161 | default: 162 | //swapnibble throw "BigInteger internal error"; 163 | assert( 0, "BigInteger internal error"); 164 | break; 165 | } 166 | } 167 | 168 | /* COPY-LESS OPERATIONS 169 | * These do some messing around to determine the sign of the result, 170 | * then call one of BigUnsigned's copy-less operations. */ 171 | 172 | // See remarks about aliased calls in BigUnsigned.cc . 173 | #define DTRT_ALIASED(cond, op) \ 174 | if (cond) { \ 175 | BigInteger tmpThis; \ 176 | tmpThis.op; \ 177 | *this = tmpThis; \ 178 | return; \ 179 | } 180 | 181 | void BigInteger::add(const BigInteger &a, const BigInteger &b) { 182 | DTRT_ALIASED(this == &a || this == &b, add(a, b)); 183 | // If one argument is zero, copy the other. 184 | if (a.sign == zero) 185 | operator =(b); 186 | else if (b.sign == zero) 187 | operator =(a); 188 | // If the arguments have the same sign, take the 189 | // common sign and add their magnitudes. 190 | else if (a.sign == b.sign) { 191 | sign = a.sign; 192 | mag.add(a.mag, b.mag); 193 | } else { 194 | // Otherwise, their magnitudes must be compared. 195 | switch (a.mag.compareTo(b.mag)) { 196 | case equal: 197 | // If their magnitudes are the same, copy zero. 198 | mag = 0; 199 | sign = zero; 200 | break; 201 | // Otherwise, take the sign of the greater, and subtract 202 | // the lesser magnitude from the greater magnitude. 203 | case greater: 204 | sign = a.sign; 205 | mag.subtract(a.mag, b.mag); 206 | break; 207 | case less: 208 | sign = b.sign; 209 | mag.subtract(b.mag, a.mag); 210 | break; 211 | } 212 | } 213 | } 214 | 215 | void BigInteger::subtract(const BigInteger &a, const BigInteger &b) { 216 | // Notice that this routine is identical to BigInteger::add, 217 | // if one replaces b.sign by its opposite. 218 | DTRT_ALIASED(this == &a || this == &b, subtract(a, b)); 219 | // If a is zero, copy b and flip its sign. If b is zero, copy a. 220 | if (a.sign == zero) { 221 | mag = b.mag; 222 | // Take the negative of _b_'s, sign, not ours. 223 | // Bug pointed out by Sam Larkin on 2005.03.30. 224 | sign = Sign(-b.sign); 225 | } else if (b.sign == zero) 226 | operator =(a); 227 | // If their signs differ, take a.sign and add the magnitudes. 228 | else if (a.sign != b.sign) { 229 | sign = a.sign; 230 | mag.add(a.mag, b.mag); 231 | } else { 232 | // Otherwise, their magnitudes must be compared. 233 | switch (a.mag.compareTo(b.mag)) { 234 | // If their magnitudes are the same, copy zero. 235 | case equal: 236 | mag = 0; 237 | sign = zero; 238 | break; 239 | // If a's magnitude is greater, take a.sign and 240 | // subtract a from b. 241 | case greater: 242 | sign = a.sign; 243 | mag.subtract(a.mag, b.mag); 244 | break; 245 | // If b's magnitude is greater, take the opposite 246 | // of b.sign and subtract b from a. 247 | case less: 248 | sign = Sign(-b.sign); 249 | mag.subtract(b.mag, a.mag); 250 | break; 251 | } 252 | } 253 | } 254 | 255 | void BigInteger::multiply(const BigInteger &a, const BigInteger &b) { 256 | DTRT_ALIASED(this == &a || this == &b, multiply(a, b)); 257 | // If one object is zero, copy zero and return. 258 | if (a.sign == zero || b.sign == zero) { 259 | sign = zero; 260 | mag = 0; 261 | return; 262 | } 263 | // If the signs of the arguments are the same, the result 264 | // is positive, otherwise it is negative. 265 | sign = (a.sign == b.sign) ? positive : negative; 266 | // Multiply the magnitudes. 267 | mag.multiply(a.mag, b.mag); 268 | } 269 | 270 | /* 271 | * DIVISION WITH REMAINDER 272 | * Please read the comments before the definition of 273 | * `BigUnsigned::divideWithRemainder' in `BigUnsigned.cc' for lots of 274 | * information you should know before reading this function. 275 | * 276 | * Following Knuth, I decree that x / y is to be 277 | * 0 if y==0 and floor(real-number x / y) if y!=0. 278 | * Then x % y shall be x - y*(integer x / y). 279 | * 280 | * Note that x = y * (x / y) + (x % y) always holds. 281 | * In addition, (x % y) is from 0 to y - 1 if y > 0, 282 | * and from -(|y| - 1) to 0 if y < 0. (x % y) = x if y = 0. 283 | * 284 | * Examples: (q = a / b, r = a % b) 285 | * a b q r 286 | * === === === === 287 | * 4 3 1 1 288 | * -4 3 -2 2 289 | * 4 -3 -2 -2 290 | * -4 -3 1 -1 291 | */ 292 | void BigInteger::divideWithRemainder(const BigInteger &b, BigInteger &q) { 293 | // Defend against aliased calls; 294 | // same idea as in BigUnsigned::divideWithRemainder . 295 | assert( this != &q, "BigInteger::divideWithRemainder: Cannot write quotient and remainder into the same variable"); 296 | // if (this == &q) 297 | // throw "BigInteger::divideWithRemainder: Cannot write quotient and remainder into the same variable"; 298 | 299 | if (this == &b || &q == &b) { 300 | BigInteger tmpB(b); 301 | divideWithRemainder(tmpB, q); 302 | return; 303 | } 304 | 305 | // Division by zero gives quotient 0 and remainder *this 306 | if (b.sign == zero) { 307 | q.mag = 0; 308 | q.sign = zero; 309 | return; 310 | } 311 | // 0 / b gives quotient 0 and remainder 0 312 | if (sign == zero) { 313 | q.mag = 0; 314 | q.sign = zero; 315 | return; 316 | } 317 | 318 | // Here *this != 0, b != 0. 319 | 320 | // Do the operands have the same sign? 321 | if (sign == b.sign) { 322 | // Yes: easy case. Quotient is zero or positive. 323 | q.sign = positive; 324 | } else { 325 | // No: harder case. Quotient is negative. 326 | q.sign = negative; 327 | // Decrease the magnitude of the dividend by one. 328 | mag--; 329 | /* 330 | * We tinker with the dividend before and with the 331 | * quotient and remainder after so that the result 332 | * comes out right. To see why it works, consider the following 333 | * list of examples, where A is the magnitude-decreased 334 | * a, Q and R are the results of BigUnsigned division 335 | * with remainder on A and |b|, and q and r are the 336 | * final results we want: 337 | * 338 | * a A b Q R q r 339 | * -3 -2 3 0 2 -1 0 340 | * -4 -3 3 1 0 -2 2 341 | * -5 -4 3 1 1 -2 1 342 | * -6 -5 3 1 2 -2 0 343 | * 344 | * It appears that we need a total of 3 corrections: 345 | * Decrease the magnitude of a to get A. Increase the 346 | * magnitude of Q to get q (and make it negative). 347 | * Find r = (b - 1) - R and give it the desired sign. 348 | */ 349 | } 350 | 351 | // Divide the magnitudes. 352 | mag.divideWithRemainder(b.mag, q.mag); 353 | 354 | if (sign != b.sign) { 355 | // More for the harder case (as described): 356 | // Increase the magnitude of the quotient by one. 357 | q.mag++; 358 | // Modify the remainder. 359 | mag.subtract(b.mag, mag); 360 | mag--; 361 | } 362 | 363 | // Sign of the remainder is always the sign of the divisor b. 364 | sign = b.sign; 365 | 366 | // Set signs to zero as necessary. (Thanks David Allen!) 367 | if (mag.isZero()) 368 | sign = zero; 369 | if (q.mag.isZero()) 370 | q.sign = zero; 371 | 372 | // WHEW!!! 373 | } 374 | 375 | // Negation 376 | void BigInteger::negate(const BigInteger &a) { 377 | DTRT_ALIASED(this == &a, negate(a)); 378 | // Copy a's magnitude 379 | mag = a.mag; 380 | // Copy the opposite of a.sign 381 | sign = Sign(-a.sign); 382 | } 383 | 384 | // print() override.. 385 | void BigInteger::print() const { 386 | bigIntegerToString(*this).print(); 387 | } 388 | 389 | // INCREMENT/DECREMENT OPERATORS 390 | 391 | // Prefix increment 392 | void BigInteger::operator ++() { 393 | if (sign == negative) { 394 | mag--; 395 | if (mag == 0) 396 | sign = zero; 397 | } else { 398 | mag++; 399 | sign = positive; // if not already 400 | } 401 | } 402 | 403 | // Postfix increment: same as prefix 404 | void BigInteger::operator ++(int) { 405 | operator ++(); 406 | } 407 | 408 | // Prefix decrement 409 | void BigInteger::operator --() { 410 | if (sign == positive) { 411 | mag--; 412 | if (mag == 0) 413 | sign = zero; 414 | } else { 415 | mag++; 416 | sign = negative; 417 | } 418 | } 419 | 420 | // Postfix decrement: same as prefix 421 | void BigInteger::operator --(int) { 422 | operator --(); 423 | } 424 | 425 | 426 | // NORMAL OPERATORS 427 | /* These create an object to hold the result and invoke 428 | * the appropriate put-here operation on it, passing 429 | * this and x. The new object is then returned. */ 430 | BigInteger BigInteger::operator +(const BigInteger &x) const { 431 | BigInteger ans; 432 | ans.add(*this, x); 433 | return ans; 434 | } 435 | BigInteger BigInteger::operator -(const BigInteger &x) const { 436 | BigInteger ans; 437 | ans.subtract(*this, x); 438 | return ans; 439 | } 440 | BigInteger BigInteger::operator *(const BigInteger &x) const { 441 | BigInteger ans; 442 | ans.multiply(*this, x); 443 | return ans; 444 | } 445 | BigInteger BigInteger::operator /(const BigInteger &x) const { 446 | //swapnibble if (x.isZero()) throw "BigInteger::operator /: division by zero"; 447 | assert( !x.isZero(), "BigInteger::operator /: division by zero"); 448 | BigInteger q, r; 449 | r = *this; 450 | r.divideWithRemainder(x, q); 451 | return q; 452 | } 453 | BigInteger BigInteger::operator %(const BigInteger &x) const { 454 | //swapnibble if (x.isZero()) throw "BigInteger::operator %: division by zero"; 455 | assert( !x.isZero(), "BigInteger::operator %: division by zero"); 456 | BigInteger q, r; 457 | r = *this; 458 | r.divideWithRemainder(x, q); 459 | return r; 460 | } 461 | BigInteger BigInteger::operator -() const { 462 | BigInteger ans; 463 | ans.negate(*this); 464 | return ans; 465 | } 466 | 467 | /* 468 | * ASSIGNMENT OPERATORS 469 | * 470 | * Now the responsibility for making a temporary copy if necessary 471 | * belongs to the put-here operations. See Assignment Operators in 472 | * BigUnsigned.hh. 473 | */ 474 | void BigInteger::operator +=(const BigInteger &x) { 475 | add(*this, x); 476 | } 477 | void BigInteger::operator -=(const BigInteger &x) { 478 | subtract(*this, x); 479 | } 480 | void BigInteger::operator *=(const BigInteger &x) { 481 | multiply(*this, x); 482 | } 483 | void BigInteger::operator /=(const BigInteger &x) { 484 | //if (x.isZero()) throw "BigInteger::operator /=: division by zero"; 485 | assert( !x.isZero(), "BigInteger::operator /=: division by zero"); 486 | 487 | /* The following technique is slightly faster than copying *this first 488 | * when x is large. */ 489 | BigInteger q; 490 | divideWithRemainder(x, q); 491 | // *this contains the remainder, but we overwrite it with the quotient. 492 | *this = q; 493 | } 494 | void BigInteger::operator %=(const BigInteger &x) { 495 | //if (x.isZero()) throw "BigInteger::operator %=: division by zero"; 496 | assert( !x.isZero(), "BigInteger::operator %=: division by zero"); 497 | 498 | BigInteger q; 499 | // Mods *this by x. Don't care about quotient left in q. 500 | divideWithRemainder(x, q); 501 | } 502 | // This one is trivial 503 | void BigInteger::flipSign() { 504 | sign = Sign(-sign); 505 | } 506 | -------------------------------------------------------------------------------- /BigInteger.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This source adapted from https://mattmccutchen.net/bigint/ by Mithrilcoin.io for EOS.IO smart contract. 3 | */ 4 | #ifndef BIGINTEGER_H 5 | #define BIGINTEGER_H 6 | 7 | #include "BigUnsigned.hpp" 8 | 9 | /* A BigInteger object represents a signed integer of size limited only by 10 | * available memory. BigUnsigneds support most mathematical operators and can 11 | * be converted to and from most primitive integer types. 12 | * 13 | * A BigInteger is just an aggregate of a BigUnsigned and a sign. (It is no 14 | * longer derived from BigUnsigned because that led to harmful implicit 15 | * conversions.) */ 16 | class BigInteger { 17 | 18 | public: 19 | typedef BigUnsigned::Blk Blk; 20 | typedef BigUnsigned::Index Index; 21 | typedef BigUnsigned::CmpRes CmpRes; 22 | static const CmpRes 23 | less = BigUnsigned::less , 24 | equal = BigUnsigned::equal , 25 | greater = BigUnsigned::greater; 26 | // Enumeration for the sign of a BigInteger. 27 | enum Sign { negative = -1, zero = 0, positive = 1 }; 28 | 29 | protected: 30 | Sign sign; 31 | BigUnsigned mag; 32 | 33 | public: 34 | // Constructs zero. 35 | BigInteger() : sign(zero), mag() {} 36 | 37 | // Copy constructor 38 | BigInteger(const BigInteger &x) : sign(x.sign), mag(x.mag) {}; 39 | 40 | // Assignment operator 41 | void operator=(const BigInteger &x); 42 | 43 | // Constructor that copies from a given array of blocks with a sign. 44 | BigInteger(const Blk *b, Index blen, Sign s); 45 | 46 | // Nonnegative constructor that copies from a given array of blocks. 47 | BigInteger(const Blk *b, Index blen) : mag(b, blen) { 48 | sign = mag.isZero() ? zero : positive; 49 | } 50 | 51 | // Constructor from a BigUnsigned and a sign 52 | BigInteger(const BigUnsigned &x, Sign s); 53 | 54 | // Nonnegative constructor from a BigUnsigned 55 | BigInteger(const BigUnsigned &x) : mag(x) { 56 | sign = mag.isZero() ? zero : positive; 57 | } 58 | 59 | // Constructors from primitive integer types 60 | BigInteger(unsigned long x); 61 | BigInteger( long x); 62 | BigInteger(unsigned int x); 63 | BigInteger( int x); 64 | BigInteger(unsigned short x); 65 | BigInteger( short x); 66 | 67 | /* Converters to primitive integer types 68 | * The implicit conversion operators caused trouble, so these are now 69 | * named. */ 70 | unsigned long toUnsignedLong () const; 71 | long toLong () const; 72 | unsigned int toUnsignedInt () const; 73 | int toInt () const; 74 | unsigned short toUnsignedShort() const; 75 | short toShort () const; 76 | protected: 77 | // Helper 78 | template X convertToUnsignedPrimitive() const; 79 | template X convertToSignedPrimitive() const; 80 | public: 81 | 82 | // ACCESSORS 83 | Sign getSign() const { return sign; } 84 | /* The client can't do any harm by holding a read-only reference to the 85 | * magnitude. */ 86 | const BigUnsigned &getMagnitude() const { return mag; } 87 | 88 | // Some accessors that go through to the magnitude 89 | Index getLength() const { return mag.getLength(); } 90 | Index getCapacity() const { return mag.getCapacity(); } 91 | Blk getBlock(Index i) const { return mag.getBlock(i); } 92 | bool isZero() const { return sign == zero; } // A bit special 93 | 94 | // COMPARISONS 95 | 96 | // Compares this to x like Perl's <=> 97 | CmpRes compareTo(const BigInteger &x) const; 98 | 99 | // Ordinary comparison operators 100 | bool operator ==(const BigInteger &x) const { 101 | return sign == x.sign && mag == x.mag; 102 | } 103 | bool operator !=(const BigInteger &x) const { return !operator ==(x); }; 104 | bool operator < (const BigInteger &x) const { return compareTo(x) == less ; } 105 | bool operator <=(const BigInteger &x) const { return compareTo(x) != greater; } 106 | bool operator >=(const BigInteger &x) const { return compareTo(x) != less ; } 107 | bool operator > (const BigInteger &x) const { return compareTo(x) == greater; } 108 | 109 | // OPERATORS -- See the discussion in BigUnsigned.hh. 110 | void add (const BigInteger &a, const BigInteger &b); 111 | void subtract(const BigInteger &a, const BigInteger &b); 112 | void multiply(const BigInteger &a, const BigInteger &b); 113 | /* See the comment on BigUnsigned::divideWithRemainder. Semantics 114 | * differ from those of primitive integers when negatives and/or zeros 115 | * are involved. */ 116 | void divideWithRemainder(const BigInteger &b, BigInteger &q); 117 | void negate(const BigInteger &a); 118 | 119 | // swapnibble 120 | void print() const; 121 | 122 | /* Bitwise operators are not provided for BigIntegers. Use 123 | * getMagnitude to get the magnitude and operate on that instead. */ 124 | 125 | BigInteger operator +(const BigInteger &x) const; 126 | BigInteger operator -(const BigInteger &x) const; 127 | BigInteger operator *(const BigInteger &x) const; 128 | BigInteger operator /(const BigInteger &x) const; 129 | BigInteger operator %(const BigInteger &x) const; 130 | BigInteger operator -() const; 131 | 132 | void operator +=(const BigInteger &x); 133 | void operator -=(const BigInteger &x); 134 | void operator *=(const BigInteger &x); 135 | void operator /=(const BigInteger &x); 136 | void operator %=(const BigInteger &x); 137 | void flipSign(); 138 | 139 | // INCREMENT/DECREMENT OPERATORS 140 | void operator ++( ); 141 | void operator ++(int); 142 | void operator --( ); 143 | void operator --(int); 144 | 145 | // For signed input, determine the desired magnitude and sign separately. 146 | 147 | template 148 | Blk magOf(X x) { 149 | /* UX(...) cast needed to stop short(-2^15), which negates to 150 | * itself, from sign-extending in the conversion to Blk. */ 151 | return BigInteger::Blk(x < 0 ? UX(-x) : x); 152 | } 153 | template 154 | Sign signOf(X x) { 155 | return (x == 0) ? BigInteger::zero 156 | : (x > 0) ? BigInteger::positive 157 | : BigInteger::negative; 158 | } 159 | }; 160 | 161 | 162 | #endif 163 | -------------------------------------------------------------------------------- /BigIntegerAlgorithms.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This source adapted from https://mattmccutchen.net/bigint/ by Mithrilcoin.io for EOS.IO smart contract. 3 | */ 4 | #include "BigIntegerAlgorithms.hpp" 5 | #include 6 | 7 | BigUnsigned gcd(BigUnsigned a, BigUnsigned b) { 8 | BigUnsigned trash; 9 | // Neat in-place alternating technique. 10 | for (;;) { 11 | if (b.isZero()) 12 | return a; 13 | a.divideWithRemainder(b, trash); 14 | if (a.isZero()) 15 | return b; 16 | b.divideWithRemainder(a, trash); 17 | } 18 | } 19 | 20 | void extendedEuclidean(BigInteger m, BigInteger n, 21 | BigInteger &g, BigInteger &r, BigInteger &s) { 22 | //gongsang 23 | assert( &g != &r && &g != &s && &r != &s 24 | , "BigInteger extendedEuclidean: Outputs are aliased" ); 25 | // if (&g == &r || &g == &s || &r == &s) 26 | // throw "BigInteger extendedEuclidean: Outputs are aliased"; 27 | BigInteger r1(1), s1(0), r2(0), s2(1), q; 28 | /* Invariants: 29 | * r1*m(orig) + s1*n(orig) == m(current) 30 | * r2*m(orig) + s2*n(orig) == n(current) */ 31 | for (;;) { 32 | if (n.isZero()) { 33 | r = r1; s = s1; g = m; 34 | return; 35 | } 36 | // Subtract q times the second invariant from the first invariant. 37 | m.divideWithRemainder(n, q); 38 | r1 -= q*r2; s1 -= q*s2; 39 | 40 | if (m.isZero()) { 41 | r = r2; s = s2; g = n; 42 | return; 43 | } 44 | // Subtract q times the first invariant from the second invariant. 45 | n.divideWithRemainder(m, q); 46 | r2 -= q*r1; s2 -= q*s1; 47 | } 48 | } 49 | 50 | BigUnsigned modinv(const BigInteger &x, const BigUnsigned &n) { 51 | BigInteger g, r, s; 52 | extendedEuclidean(x, n, g, r, s); 53 | if (g == 1) 54 | // r*x + s*n == 1, so r*x === 1 (mod n), so r is the answer. 55 | return (r % n).getMagnitude(); // (r % n) will be nonnegative 56 | else { 57 | //gongsang throw "BigInteger modinv: x and n have a common factor"; 58 | assert( 0, "BigInteger modinv: x and n have a common factor"); 59 | return 0; // here will never be reached! 60 | } 61 | } 62 | 63 | BigUnsigned modexp(const BigInteger &base, const BigUnsigned &exponent, 64 | const BigUnsigned &modulus) { 65 | BigUnsigned ans = 1, base2 = (base % modulus).getMagnitude(); 66 | BigUnsigned::Index i = exponent.bitLength(); 67 | // For each bit of the exponent, most to least significant... 68 | while (i > 0) { 69 | i--; 70 | // Square. 71 | ans *= ans; 72 | ans %= modulus; 73 | // And multiply if the bit is a 1. 74 | if (exponent.getBit(i)) { 75 | ans *= base2; 76 | ans %= modulus; 77 | } 78 | } 79 | return ans; 80 | } 81 | -------------------------------------------------------------------------------- /BigIntegerAlgorithms.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This source adapted from https://mattmccutchen.net/bigint/ by Mithrilcoin.io for EOS.IO smart contract. 3 | */ 4 | 5 | #ifndef BIGINTEGERALGORITHMS_H 6 | #define BIGINTEGERALGORITHMS_H 7 | 8 | #include "BigInteger.hpp" 9 | 10 | /* Some mathematical algorithms for big integers. 11 | * This code is new and, as such, experimental. */ 12 | 13 | // Returns the greatest common divisor of a and b. 14 | BigUnsigned gcd(BigUnsigned a, BigUnsigned b); 15 | 16 | /* Extended Euclidean algorithm. 17 | * Given m and n, finds gcd g and numbers r, s such that r*m + s*n == g. */ 18 | void extendedEuclidean(BigInteger m, BigInteger n, 19 | BigInteger &g, BigInteger &r, BigInteger &s); 20 | 21 | /* Returns the multiplicative inverse of x modulo n, or throws an exception if 22 | * they have a common factor. */ 23 | BigUnsigned modinv(const BigInteger &x, const BigUnsigned &n); 24 | 25 | // Returns (base ^ exponent) % modulus. 26 | BigUnsigned modexp(const BigInteger &base, const BigUnsigned &exponent, 27 | const BigUnsigned &modulus); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /BigIntegerLibrary.hpp: -------------------------------------------------------------------------------- 1 | // This header file includes all of the library header files. 2 | 3 | #include "NumberlikeArray.hpp" 4 | #include "BigUnsigned.hpp" 5 | #include "BigInteger.hpp" 6 | #include "BigIntegerAlgorithms.hpp" 7 | #include "BigUnsignedInABase.hpp" 8 | #include "BigIntegerUtils.hpp" 9 | -------------------------------------------------------------------------------- /BigIntegerUtils.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This source adapted from https://mattmccutchen.net/bigint/ by Mithrilcoin.io for EOS.IO smart contract. 3 | */ 4 | #include "BigIntegerUtils.hpp" 5 | #include "BigUnsignedInABase.hpp" 6 | 7 | eosio::string bigUnsignedToString( const BigUnsigned &x) { 8 | return eosio::string(BigUnsignedInABase(x, BigUnsignedInABase::Base(10) ) ); 9 | } 10 | 11 | eosio::string bigIntegerToString( const BigInteger &x) { 12 | return (x.getSign() == BigInteger::negative) 13 | ? (eosio::string("-") + bigUnsignedToString(x.getMagnitude())) 14 | : (bigUnsignedToString(x.getMagnitude())); 15 | } 16 | 17 | BigUnsigned stringToBigUnsigned(const eosio::string &s) { 18 | return BigUnsigned(BigUnsignedInABase(s, BigUnsignedInABase::Base(10) ) ); 19 | } 20 | 21 | 22 | class ext_string : public eosio::string { 23 | public: 24 | ext_string( const eosio::string &cstr): eosio::string(cstr){} 25 | 26 | const eosio::string substr(size_t offset, size_t substr_size, bool copy) { 27 | return (const eosio::string) ( eosio::string::substr( offset, substr_size, copy) ) ; 28 | } 29 | }; 30 | 31 | BigInteger stringToBigInteger( const eosio::string &s) { 32 | // Recognize a sign followed by a BigUnsigned. 33 | const char signChar = s.get_data()[0]; 34 | ext_string childStr( s ); 35 | 36 | return (signChar == '-') ? BigInteger(stringToBigUnsigned(childStr.substr(1, s.get_size() - 2, false)), BigInteger::negative) 37 | : (signChar == '+') ? BigInteger(stringToBigUnsigned(childStr.substr(1, s.get_size() - 2, false))) 38 | : BigInteger(stringToBigUnsigned(s)); 39 | } 40 | 41 | // commented by swapnibble 42 | /* 43 | eosio::ostream &operator <<(eosio::ostream &os, const BigUnsigned &x) { 44 | BigUnsignedInABase::Base base; 45 | long osFlags = os.flags(); 46 | if (osFlags & os.dec) 47 | base = 10; 48 | else if (osFlags & os.hex) { 49 | base = 16; 50 | if (osFlags & os.showbase) 51 | os << "0x"; 52 | } else if (osFlags & os.oct) { 53 | base = 8; 54 | if (osFlags & os.showbase) 55 | os << '0'; 56 | } else { 57 | throw "eosio::ostream << BigUnsigned: Could not determine the desired base from output-stream flags"; 58 | } 59 | eosio::string s = eosio::string(BigUnsignedInABase(x, base)); 60 | os << s; 61 | return os; 62 | } 63 | 64 | eosio::ostream &operator <<(eosio::ostream &os, const BigInteger &x) { 65 | if (x.getSign() == BigInteger::negative) 66 | os << '-'; 67 | os << x.getMagnitude(); 68 | return os; 69 | } 70 | */ -------------------------------------------------------------------------------- /BigIntegerUtils.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This source adapted from https://mattmccutchen.net/bigint/ by Mithrilcoin.io for EOS.IO smart contract. 3 | */ 4 | #ifndef BIGINTEGERUTILS_H 5 | #define BIGINTEGERUTILS_H 6 | 7 | #include "BigInteger.hpp" 8 | #include 9 | //swapnibble #include 10 | 11 | /* This file provides: 12 | * - Convenient eosio::string <-> BigUnsigned/BigInteger conversion routines 13 | * - eosio::ostream << operators for BigUnsigned/BigInteger */ 14 | 15 | // eosio::string conversion routines. Base 10 only. 16 | eosio::string bigUnsignedToString( const BigUnsigned &x); 17 | eosio::string bigIntegerToString( const BigInteger &x); 18 | BigUnsigned stringToBigUnsigned( const eosio::string &s); 19 | BigInteger stringToBigInteger( const eosio::string &s); 20 | 21 | // Creates a BigInteger from data such as `char's; read below for details. 22 | template 23 | BigInteger dataTobint( T* data, BigInteger::Index length, BigInteger::Sign sign); 24 | 25 | // Outputs x to os, obeying the flags `dec', `hex', `bin', and `showbase'. 26 | // eosio::ostream &operator <<(eosio::ostream &os, const BigUnsigned &x); 27 | 28 | // Outputs x to os, obeying the flags `dec', `hex', `bin', and `showbase'. 29 | // My somewhat arbitrary policy: a negative sign comes before a base indicator (like -0xFF). 30 | // eosio::ostream &operator <<(eosio::ostream &os, const BigInteger &x); 31 | 32 | // BEGIN TEMPLATE DEFINITIONS. 33 | 34 | /* 35 | * Converts binary data to a BigInteger. 36 | * Pass an array `data', its length, and the desired sign. 37 | * 38 | * Elements of `data' may be of any type `T' that has the following 39 | * two properties (this includes almost all integral types): 40 | * 41 | * (1) `sizeof(T)' correctly gives the amount of binary data in one 42 | * value of `T' and is a factor of `sizeof(Blk)'. 43 | * 44 | * (2) When a value of `T' is casted to a `Blk', the low bytes of 45 | * the result contain the desired binary data. 46 | 47 | template 48 | BigInteger dataToBigInteger( T* data, BigInteger::Index length, BigInteger::Sign sign) { 49 | // really ceiling(numBytes / sizeof(BigInteger::Blk)) 50 | unsigned int pieceSizeInBits = 8 * sizeof(T); 51 | unsigned int piecesPerBlock = sizeof(BigInteger::Blk) / sizeof(T); 52 | unsigned int numBlocks = (length + piecesPerBlock - 1) / piecesPerBlock; 53 | 54 | // Allocate our block array 55 | BigInteger::Blk *blocks = new BigInteger::Blk[numBlocks]; 56 | 57 | BigInteger::Index blockNum, pieceNum, pieceNumHere; 58 | 59 | // Convert 60 | for (blockNum = 0, pieceNum = 0; blockNum < numBlocks; blockNum++) { 61 | BigInteger::Blk curBlock = 0; 62 | for (pieceNumHere = 0; pieceNumHere < piecesPerBlock && pieceNum < length; 63 | pieceNumHere++, pieceNum++) 64 | curBlock |= (BigInteger::Blk(data[pieceNum]) << (pieceSizeInBits * pieceNumHere)); 65 | blocks[blockNum] = curBlock; 66 | } 67 | 68 | // Create the BigInteger. 69 | BigInteger x(blocks, numBlocks, sign); 70 | 71 | delete [] blocks; 72 | return x; 73 | } 74 | */ 75 | #endif 76 | -------------------------------------------------------------------------------- /BigUnsigned.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This source adapted from https://mattmccutchen.net/bigint/ by Mithrilcoin.io for EOS.IO smart contract. 3 | */ 4 | #include "BigUnsigned.hpp" 5 | #include "BigIntegerUtils.hpp" 6 | 7 | // Memory management definitions have moved to the bottom of NumberlikeArray.hh. 8 | 9 | // The templates used by these constructors and converters are at the bottom of 10 | // BigUnsigned.hh. 11 | 12 | BigUnsigned::BigUnsigned(unsigned long x) { initFromPrimitive (x); } 13 | BigUnsigned::BigUnsigned(unsigned int x) { initFromPrimitive (x); } 14 | BigUnsigned::BigUnsigned(unsigned short x) { initFromPrimitive (x); } 15 | BigUnsigned::BigUnsigned( long x) { initFromSignedPrimitive(x); } 16 | BigUnsigned::BigUnsigned( int x) { initFromSignedPrimitive(x); } 17 | BigUnsigned::BigUnsigned( short x) { initFromSignedPrimitive(x); } 18 | 19 | unsigned long BigUnsigned::toUnsignedLong () const { return convertToPrimitive (); } 20 | unsigned int BigUnsigned::toUnsignedInt () const { return convertToPrimitive (); } 21 | unsigned short BigUnsigned::toUnsignedShort() const { return convertToPrimitive (); } 22 | long BigUnsigned::toLong () const { return convertToSignedPrimitive< long >(); } 23 | int BigUnsigned::toInt () const { return convertToSignedPrimitive< int >(); } 24 | short BigUnsigned::toShort () const { return convertToSignedPrimitive< short>(); } 25 | 26 | // BIT/BLOCK ACCESSORS 27 | 28 | void BigUnsigned::setBlock(Index i, Blk newBlock) { 29 | if (newBlock == 0) { 30 | if (i < len) { 31 | blk[i] = 0; 32 | zapLeadingZeros(); 33 | } 34 | // If i >= len, no effect. 35 | } else { 36 | if (i >= len) { 37 | // The nonzero block extends the number. 38 | allocateAndCopy(i+1); 39 | // Zero any added blocks that we aren't setting. 40 | for (Index j = len; j < i; j++) 41 | blk[j] = 0; 42 | len = i+1; 43 | } 44 | blk[i] = newBlock; 45 | } 46 | } 47 | 48 | /* Evidently the compiler wants BigUnsigned:: on the return type because, at 49 | * that point, it hasn't yet parsed the BigUnsigned:: on the name to get the 50 | * proper scope. */ 51 | BigUnsigned::Index BigUnsigned::bitLength() const { 52 | if (isZero()) 53 | return 0; 54 | else { 55 | Blk leftmostBlock = getBlock(len - 1); 56 | Index leftmostBlockLen = 0; 57 | while (leftmostBlock != 0) { 58 | leftmostBlock >>= 1; 59 | leftmostBlockLen++; 60 | } 61 | return leftmostBlockLen + (len - 1) * N; 62 | } 63 | } 64 | 65 | void BigUnsigned::setBit(Index bi, bool newBit) { 66 | Index blockI = bi / N; 67 | Blk block = getBlock(blockI), mask = Blk(1) << (bi % N); 68 | block = newBit ? (block | mask) : (block & ~mask); 69 | setBlock(blockI, block); 70 | } 71 | 72 | // COMPARISON 73 | BigUnsigned::CmpRes BigUnsigned::compareTo(const BigUnsigned &x) const { 74 | // A bigger length implies a bigger number. 75 | if (len < x.len) 76 | return less; 77 | else if (len > x.len) 78 | return greater; 79 | else { 80 | // Compare blocks one by one from left to right. 81 | Index i = len; 82 | while (i > 0) { 83 | i--; 84 | if (blk[i] == x.blk[i]) 85 | continue; 86 | else if (blk[i] > x.blk[i]) 87 | return greater; 88 | else 89 | return less; 90 | } 91 | // If no blocks differed, the numbers are equal. 92 | return equal; 93 | } 94 | } 95 | 96 | // COPY-LESS OPERATIONS 97 | 98 | /* 99 | * On most calls to copy-less operations, it's safe to read the inputs little by 100 | * little and write the outputs little by little. However, if one of the 101 | * inputs is coming from the same variable into which the output is to be 102 | * stored (an "aliased" call), we risk overwriting the input before we read it. 103 | * In this case, we first compute the result into a temporary BigUnsigned 104 | * variable and then copy it into the requested output variable *this. 105 | * Each put-here operation uses the DTRT_ALIASED macro (Do The Right Thing on 106 | * aliased calls) to generate code for this check. 107 | * 108 | * I adopted this approach on 2007.02.13 (see Assignment Operators in 109 | * BigUnsigned.hh). Before then, put-here operations rejected aliased calls 110 | * with an exception. I think doing the right thing is better. 111 | * 112 | * Some of the put-here operations can probably handle aliased calls safely 113 | * without the extra copy because (for example) they process blocks strictly 114 | * right-to-left. At some point I might determine which ones don't need the 115 | * copy, but my reasoning would need to be verified very carefully. For now 116 | * I'll leave in the copy. 117 | */ 118 | #define DTRT_ALIASED(cond, op) \ 119 | if (cond) { \ 120 | BigUnsigned tmpThis; \ 121 | tmpThis.op; \ 122 | *this = tmpThis; \ 123 | return; \ 124 | } 125 | 126 | 127 | 128 | void BigUnsigned::add(const BigUnsigned &a, const BigUnsigned &b) { 129 | DTRT_ALIASED(this == &a || this == &b, add(a, b)); 130 | // If one argument is zero, copy the other. 131 | if (a.len == 0) { 132 | operator =(b); 133 | return; 134 | } else if (b.len == 0) { 135 | operator =(a); 136 | return; 137 | } 138 | // Some variables... 139 | // Carries in and out of an addition stage 140 | bool carryIn, carryOut; 141 | Blk temp; 142 | Index i; 143 | // a2 points to the longer input, b2 points to the shorter 144 | const BigUnsigned *a2, *b2; 145 | if (a.len >= b.len) { 146 | a2 = &a; 147 | b2 = &b; 148 | } else { 149 | a2 = &b; 150 | b2 = &a; 151 | } 152 | // Set prelimiary length and make room in this BigUnsigned 153 | len = a2->len + 1; 154 | allocate(len); 155 | // For each block index that is present in both inputs... 156 | for (i = 0, carryIn = false; i < b2->len; i++) { 157 | // Add input blocks 158 | temp = a2->blk[i] + b2->blk[i]; 159 | // If a rollover occurred, the result is less than either input. 160 | // This test is used many times in the BigUnsigned code. 161 | carryOut = (temp < a2->blk[i]); 162 | // If a carry was input, handle it 163 | if (carryIn) { 164 | temp++; 165 | carryOut |= (temp == 0); 166 | } 167 | blk[i] = temp; // Save the addition result 168 | carryIn = carryOut; // Pass the carry along 169 | } 170 | // If there is a carry left over, increase blocks until 171 | // one does not roll over. 172 | for (; i < a2->len && carryIn; i++) { 173 | temp = a2->blk[i] + 1; 174 | carryIn = (temp == 0); 175 | blk[i] = temp; 176 | } 177 | // If the carry was resolved but the larger number 178 | // still has blocks, copy them over. 179 | for (; i < a2->len; i++) 180 | blk[i] = a2->blk[i]; 181 | // Set the extra block if there's still a carry, decrease length otherwise 182 | if (carryIn) 183 | blk[i] = 1; 184 | else 185 | len--; 186 | } 187 | 188 | void BigUnsigned::subtract(const BigUnsigned &a, const BigUnsigned &b) { 189 | DTRT_ALIASED(this == &a || this == &b, subtract(a, b)); 190 | if (b.len == 0) { 191 | // If b is zero, copy a. 192 | operator =(a); 193 | return; 194 | } else { 195 | 196 | assert( a.len >= b.len, "BigUnsigned::subtract: Negative result in unsigned calculation"); 197 | //swapnibble 198 | /* 199 | if (a.len < b.len) 200 | // If a is shorter than b, the result is negative. 201 | throw "BigUnsigned::subtract: " 202 | "Negative result in unsigned calculation"; 203 | */ 204 | } 205 | // Some variables... 206 | bool borrowIn, borrowOut; 207 | Blk temp; 208 | Index i; 209 | // Set preliminary length and make room 210 | len = a.len; 211 | allocate(len); 212 | // For each block index that is present in both inputs... 213 | for (i = 0, borrowIn = false; i < b.len; i++) { 214 | temp = a.blk[i] - b.blk[i]; 215 | // If a reverse rollover occurred, 216 | // the result is greater than the block from a. 217 | borrowOut = (temp > a.blk[i]); 218 | // Handle an incoming borrow 219 | if (borrowIn) { 220 | borrowOut |= (temp == 0); 221 | temp--; 222 | } 223 | blk[i] = temp; // Save the subtraction result 224 | borrowIn = borrowOut; // Pass the borrow along 225 | } 226 | // If there is a borrow left over, decrease blocks until 227 | // one does not reverse rollover. 228 | for (; i < a.len && borrowIn; i++) { 229 | borrowIn = (a.blk[i] == 0); 230 | blk[i] = a.blk[i] - 1; 231 | } 232 | /* If there's still a borrow, the result is negative. 233 | * Throw an exception, but zero out this object so as to leave it in a 234 | * predictable state. */ 235 | if (borrowIn) { 236 | len = 0; 237 | //swapnibble throw "BigUnsigned::subtract: Negative result in unsigned calculation"; 238 | assert(0, "BigUnsigned::subtract: Negative result in unsigned calculation"); 239 | } else 240 | // Copy over the rest of the blocks 241 | for (; i < a.len; i++) 242 | blk[i] = a.blk[i]; 243 | // Zap leading zeros 244 | zapLeadingZeros(); 245 | } 246 | 247 | /* 248 | * About the multiplication and division algorithms: 249 | * 250 | * I searched unsucessfully for fast C++ built-in operations like the `b_0' 251 | * and `c_0' Knuth describes in Section 4.3.1 of ``The Art of Computer 252 | * Programming'' (replace `place' by `Blk'): 253 | * 254 | * ``b_0[:] multiplication of a one-place integer by another one-place 255 | * integer, giving a two-place answer; 256 | * 257 | * ``c_0[:] division of a two-place integer by a one-place integer, 258 | * provided that the quotient is a one-place integer, and yielding 259 | * also a one-place remainder.'' 260 | * 261 | * I also missed his note that ``[b]y adjusting the word size, if 262 | * necessary, nearly all computers will have these three operations 263 | * available'', so I gave up on trying to use algorithms similar to his. 264 | * A future version of the library might include such algorithms; I 265 | * would welcome contributions from others for this. 266 | * 267 | * I eventually decided to use bit-shifting algorithms. To multiply `a' 268 | * and `b', we zero out the result. Then, for each `1' bit in `a', we 269 | * shift `b' left the appropriate amount and add it to the result. 270 | * Similarly, to divide `a' by `b', we shift `b' left varying amounts, 271 | * repeatedly trying to subtract it from `a'. When we succeed, we note 272 | * the fact by setting a bit in the quotient. While these algorithms 273 | * have the same O(n^2) time complexity as Knuth's, the ``constant factor'' 274 | * is likely to be larger. 275 | * 276 | * Because I used these algorithms, which require single-block addition 277 | * and subtraction rather than single-block multiplication and division, 278 | * the innermost loops of all four routines are very similar. Study one 279 | * of them and all will become clear. 280 | */ 281 | 282 | /* 283 | * This is a little inline function used by both the multiplication 284 | * routine and the division routine. 285 | * 286 | * `getShiftedBlock' returns the `x'th block of `num << y'. 287 | * `y' may be anything from 0 to N - 1, and `x' may be anything from 288 | * 0 to `num.len'. 289 | * 290 | * Two things contribute to this block: 291 | * 292 | * (1) The `N - y' low bits of `num.blk[x]', shifted `y' bits left. 293 | * 294 | * (2) The `y' high bits of `num.blk[x-1]', shifted `N - y' bits right. 295 | * 296 | * But we must be careful if `x == 0' or `x == num.len', in 297 | * which case we should use 0 instead of (2) or (1), respectively. 298 | * 299 | * If `y == 0', then (2) contributes 0, as it should. However, 300 | * in some computer environments, for a reason I cannot understand, 301 | * `a >> b' means `a >> (b % N)'. This means `num.blk[x-1] >> (N - y)' 302 | * will return `num.blk[x-1]' instead of the desired 0 when `y == 0'; 303 | * the test `y == 0' handles this case specially. 304 | */ 305 | BigUnsigned::Blk getShiftedBlock(const BigUnsigned &num, 306 | BigUnsigned::Index x, unsigned int y) { 307 | BigUnsigned::Blk part1 = (x == 0 || y == 0) ? 0 : (num.blk[x - 1] >> (BigUnsigned::N - y)); 308 | BigUnsigned::Blk part2 = (x == num.len) ? 0 : (num.blk[x] << y); 309 | return part1 | part2; 310 | } 311 | 312 | void BigUnsigned::multiply(const BigUnsigned &a, const BigUnsigned &b) { 313 | DTRT_ALIASED(this == &a || this == &b, multiply(a, b)); 314 | // If either a or b is zero, set to zero. 315 | if (a.len == 0 || b.len == 0) { 316 | len = 0; 317 | return; 318 | } 319 | /* 320 | * Overall method: 321 | * 322 | * Set this = 0. 323 | * For each 1-bit of `a' (say the `i2'th bit of block `i'): 324 | * Add `b << (i blocks and i2 bits)' to *this. 325 | */ 326 | // Variables for the calculation 327 | Index i, j, k; 328 | unsigned int i2; 329 | Blk temp; 330 | bool carryIn, carryOut; 331 | // Set preliminary length and make room 332 | len = a.len + b.len; 333 | allocate(len); 334 | // Zero out this object 335 | for (i = 0; i < len; i++) 336 | blk[i] = 0; 337 | // For each block of the first number... 338 | for (i = 0; i < a.len; i++) { 339 | // For each 1-bit of that block... 340 | for (i2 = 0; i2 < N; i2++) { 341 | if ((a.blk[i] & (Blk(1) << i2)) == 0) 342 | continue; 343 | /* 344 | * Add b to this, shifted left i blocks and i2 bits. 345 | * j is the index in b, and k = i + j is the index in this. 346 | * 347 | * `getShiftedBlock', a short inline function defined above, 348 | * is now used for the bit handling. It replaces the more 349 | * complex `bHigh' code, in which each run of the loop dealt 350 | * immediately with the low bits and saved the high bits to 351 | * be picked up next time. The last run of the loop used to 352 | * leave leftover high bits, which were handled separately. 353 | * Instead, this loop runs an additional time with j == b.len. 354 | * These changes were made on 2005.01.11. 355 | */ 356 | for (j = 0, k = i, carryIn = false; j <= b.len; j++, k++) { 357 | /* 358 | * The body of this loop is very similar to the body of the first loop 359 | * in `add', except that this loop does a `+=' instead of a `+'. 360 | */ 361 | temp = blk[k] + getShiftedBlock(b, j, i2); 362 | carryOut = (temp < blk[k]); 363 | if (carryIn) { 364 | temp++; 365 | carryOut |= (temp == 0); 366 | } 367 | blk[k] = temp; 368 | carryIn = carryOut; 369 | } 370 | // No more extra iteration to deal with `bHigh'. 371 | // Roll-over a carry as necessary. 372 | for (; carryIn; k++) { 373 | blk[k]++; 374 | carryIn = (blk[k] == 0); 375 | } 376 | } 377 | } 378 | // Zap possible leading zero 379 | if (blk[len - 1] == 0) 380 | len--; 381 | } 382 | 383 | /* 384 | * DIVISION WITH REMAINDER 385 | * This monstrous function mods *this by the given divisor b while storing the 386 | * quotient in the given object q; at the end, *this contains the remainder. 387 | * The seemingly bizarre pattern of inputs and outputs was chosen so that the 388 | * function copies as little as possible (since it is implemented by repeated 389 | * subtraction of multiples of b from *this). 390 | * 391 | * "modWithQuotient" might be a better name for this function, but I would 392 | * rather not change the name now. 393 | */ 394 | void BigUnsigned::divideWithRemainder(const BigUnsigned &b, BigUnsigned &q) { 395 | /* Defending against aliased calls is more complex than usual because we 396 | * are writing to both *this and q. 397 | * 398 | * It would be silly to try to write quotient and remainder to the 399 | * same variable. Rule that out right away. */ 400 | //swapnibble 401 | assert( this != &q 402 | , "BigUnsigned::divideWithRemainder: Cannot write quotient and remainder into the same variable"); 403 | // if (this == &q) 404 | // throw "BigUnsigned::divideWithRemainder: Cannot write quotient and remainder into the same variable"; 405 | 406 | /* Now *this and q are separate, so the only concern is that b might be 407 | * aliased to one of them. If so, use a temporary copy of b. */ 408 | if (this == &b || &q == &b) { 409 | BigUnsigned tmpB(b); 410 | divideWithRemainder(tmpB, q); 411 | return; 412 | } 413 | 414 | /* 415 | * Knuth's definition of mod (which this function uses) is somewhat 416 | * different from the C++ definition of % in case of division by 0. 417 | * 418 | * We let a / 0 == 0 (it doesn't matter much) and a % 0 == a, no 419 | * exceptions thrown. This allows us to preserve both Knuth's demand 420 | * that a mod 0 == a and the useful property that 421 | * (a / b) * b + (a % b) == a. 422 | */ 423 | if (b.len == 0) { 424 | q.len = 0; 425 | return; 426 | } 427 | 428 | /* 429 | * If *this.len < b.len, then *this < b, and we can be sure that b doesn't go into 430 | * *this at all. The quotient is 0 and *this is already the remainder (so leave it alone). 431 | */ 432 | if (len < b.len) { 433 | q.len = 0; 434 | return; 435 | } 436 | 437 | // At this point we know (*this).len >= b.len > 0. (Whew!) 438 | 439 | /* 440 | * Overall method: 441 | * 442 | * For each appropriate i and i2, decreasing: 443 | * Subtract (b << (i blocks and i2 bits)) from *this, storing the 444 | * result in subtractBuf. 445 | * If the subtraction succeeds with a nonnegative result: 446 | * Turn on bit i2 of block i of the quotient q. 447 | * Copy subtractBuf back into *this. 448 | * Otherwise bit i2 of block i remains off, and *this is unchanged. 449 | * 450 | * Eventually q will contain the entire quotient, and *this will 451 | * be left with the remainder. 452 | * 453 | * subtractBuf[x] corresponds to blk[x], not blk[x+i], since 2005.01.11. 454 | * But on a single iteration, we don't touch the i lowest blocks of blk 455 | * (and don't use those of subtractBuf) because these blocks are 456 | * unaffected by the subtraction: we are subtracting 457 | * (b << (i blocks and i2 bits)), which ends in at least `i' zero 458 | * blocks. */ 459 | // Variables for the calculation 460 | Index i, j, k; 461 | unsigned int i2; 462 | Blk temp; 463 | bool borrowIn, borrowOut; 464 | 465 | /* 466 | * Make sure we have an extra zero block just past the value. 467 | * 468 | * When we attempt a subtraction, we might shift `b' so 469 | * its first block begins a few bits left of the dividend, 470 | * and then we'll try to compare these extra bits with 471 | * a nonexistent block to the left of the dividend. The 472 | * extra zero block ensures sensible behavior; we need 473 | * an extra block in `subtractBuf' for exactly the same reason. 474 | */ 475 | Index origLen = len; // Save real length. 476 | /* To avoid an out-of-bounds access in case of reallocation, allocate 477 | * first and then increment the logical length. */ 478 | allocateAndCopy(len + 1); 479 | len++; 480 | blk[origLen] = 0; // Zero the added block. 481 | 482 | // subtractBuf holds part of the result of a subtraction; see above. 483 | Blk *subtractBuf = new Blk[len]; //(Blk *)eosio::malloc( sizeof(Blk)*len) ;//swapnibble 484 | 485 | // Set preliminary length for quotient and make room 486 | q.len = origLen - b.len + 1; 487 | q.allocate(q.len); 488 | // Zero out the quotient 489 | for (i = 0; i < q.len; i++) 490 | q.blk[i] = 0; 491 | 492 | // For each possible left-shift of b in blocks... 493 | i = q.len; 494 | while (i > 0) { 495 | i--; 496 | // For each possible left-shift of b in bits... 497 | // (Remember, N is the number of bits in a Blk.) 498 | q.blk[i] = 0; 499 | i2 = N; 500 | while (i2 > 0) { 501 | i2--; 502 | /* 503 | * Subtract b, shifted left i blocks and i2 bits, from *this, 504 | * and store the answer in subtractBuf. In the for loop, `k == i + j'. 505 | * 506 | * Compare this to the middle section of `multiply'. They 507 | * are in many ways analogous. See especially the discussion 508 | * of `getShiftedBlock'. 509 | */ 510 | for (j = 0, k = i, borrowIn = false; j <= b.len; j++, k++) { 511 | temp = blk[k] - getShiftedBlock(b, j, i2); 512 | borrowOut = (temp > blk[k]); 513 | if (borrowIn) { 514 | borrowOut |= (temp == 0); 515 | temp--; 516 | } 517 | // Since 2005.01.11, indices of `subtractBuf' directly match those of `blk', so use `k'. 518 | subtractBuf[k] = temp; 519 | borrowIn = borrowOut; 520 | } 521 | // No more extra iteration to deal with `bHigh'. 522 | // Roll-over a borrow as necessary. 523 | for (; k < origLen && borrowIn; k++) { 524 | borrowIn = (blk[k] == 0); 525 | subtractBuf[k] = blk[k] - 1; 526 | } 527 | /* 528 | * If the subtraction was performed successfully (!borrowIn), 529 | * set bit i2 in block i of the quotient. 530 | * 531 | * Then, copy the portion of subtractBuf filled by the subtraction 532 | * back to *this. This portion starts with block i and ends-- 533 | * where? Not necessarily at block `i + b.len'! Well, we 534 | * increased k every time we saved a block into subtractBuf, so 535 | * the region of subtractBuf we copy is just [i, k). 536 | */ 537 | if (!borrowIn) { 538 | q.blk[i] |= (Blk(1) << i2); 539 | while (k > i) { 540 | k--; 541 | blk[k] = subtractBuf[k]; 542 | } 543 | } 544 | } 545 | } 546 | // Zap possible leading zero in quotient 547 | if (q.blk[q.len - 1] == 0) 548 | q.len--; 549 | // Zap any/all leading zeros in remainder 550 | zapLeadingZeros(); 551 | // Deallocate subtractBuf. 552 | // (Thanks to Brad Spencer for noticing my accidental omission of this!) 553 | delete [] subtractBuf; //eosio::free(subtractBuf);//swapnibble // 554 | } 555 | 556 | /* BITWISE OPERATORS 557 | * These are straightforward blockwise operations except that they differ in 558 | * the output length and the necessity of zapLeadingZeros. */ 559 | 560 | void BigUnsigned::bitAnd(const BigUnsigned &a, const BigUnsigned &b) { 561 | DTRT_ALIASED(this == &a || this == &b, bitAnd(a, b)); 562 | // The bitwise & can't be longer than either operand. 563 | len = (a.len >= b.len) ? b.len : a.len; 564 | allocate(len); 565 | Index i; 566 | for (i = 0; i < len; i++) 567 | blk[i] = a.blk[i] & b.blk[i]; 568 | zapLeadingZeros(); 569 | } 570 | 571 | void BigUnsigned::bitOr(const BigUnsigned &a, const BigUnsigned &b) { 572 | DTRT_ALIASED(this == &a || this == &b, bitOr(a, b)); 573 | Index i; 574 | const BigUnsigned *a2, *b2; 575 | if (a.len >= b.len) { 576 | a2 = &a; 577 | b2 = &b; 578 | } else { 579 | a2 = &b; 580 | b2 = &a; 581 | } 582 | allocate(a2->len); 583 | for (i = 0; i < b2->len; i++) 584 | blk[i] = a2->blk[i] | b2->blk[i]; 585 | for (; i < a2->len; i++) 586 | blk[i] = a2->blk[i]; 587 | len = a2->len; 588 | // Doesn't need zapLeadingZeros. 589 | } 590 | 591 | void BigUnsigned::bitXor(const BigUnsigned &a, const BigUnsigned &b) { 592 | DTRT_ALIASED(this == &a || this == &b, bitXor(a, b)); 593 | Index i; 594 | const BigUnsigned *a2, *b2; 595 | if (a.len >= b.len) { 596 | a2 = &a; 597 | b2 = &b; 598 | } else { 599 | a2 = &b; 600 | b2 = &a; 601 | } 602 | allocate(a2->len); 603 | for (i = 0; i < b2->len; i++) 604 | blk[i] = a2->blk[i] ^ b2->blk[i]; 605 | for (; i < a2->len; i++) 606 | blk[i] = a2->blk[i]; 607 | len = a2->len; 608 | zapLeadingZeros(); 609 | } 610 | 611 | void BigUnsigned::bitShiftLeft(const BigUnsigned &a, int b) { 612 | DTRT_ALIASED(this == &a, bitShiftLeft(a, b)); 613 | if (b < 0) { 614 | //swapnibble 615 | assert( b << 1 != 0, "BigUnsigned::bitShiftLeft: Pathological shift amount not implemented" ); 616 | 617 | bitShiftRight(a, -b); 618 | return; 619 | /* 620 | if (b << 1 == 0) 621 | throw "BigUnsigned::bitShiftLeft: " 622 | "Pathological shift amount not implemented"; 623 | else { 624 | bitShiftRight(a, -b); 625 | return; 626 | } 627 | */ 628 | } 629 | Index shiftBlocks = b / N; 630 | unsigned int shiftBits = b % N; 631 | // + 1: room for high bits nudged left into another block 632 | len = a.len + shiftBlocks + 1; 633 | allocate(len); 634 | Index i, j; 635 | for (i = 0; i < shiftBlocks; i++) 636 | blk[i] = 0; 637 | for (j = 0, i = shiftBlocks; j <= a.len; j++, i++) 638 | blk[i] = getShiftedBlock(a, j, shiftBits); 639 | // Zap possible leading zero 640 | if (blk[len - 1] == 0) 641 | len--; 642 | } 643 | 644 | void BigUnsigned::bitShiftRight(const BigUnsigned &a, int b) { 645 | DTRT_ALIASED(this == &a, bitShiftRight(a, b)); 646 | if (b < 0) { 647 | //swapnibble 648 | assert( b << 1 != 0, "BigUnsigned::bitShiftRight: Pathological shift amount not implemented" ); 649 | 650 | bitShiftLeft(a, -b); 651 | return; 652 | 653 | // if (b << 1 == 0) 654 | // throw "BigUnsigned::bitShiftRight: " 655 | // "Pathological shift amount not implemented"; 656 | // else { 657 | // bitShiftLeft(a, -b); 658 | // return; 659 | // } 660 | } 661 | // This calculation is wacky, but expressing the shift as a left bit shift 662 | // within each block lets us use getShiftedBlock. 663 | Index rightShiftBlocks = (b + N - 1) / N; 664 | unsigned int leftShiftBits = N * rightShiftBlocks - b; 665 | // Now (N * rightShiftBlocks - leftShiftBits) == b 666 | // and 0 <= leftShiftBits < N. 667 | if (rightShiftBlocks >= a.len + 1) { 668 | // All of a is guaranteed to be shifted off, even considering the left 669 | // bit shift. 670 | len = 0; 671 | return; 672 | } 673 | // Now we're allocating a positive amount. 674 | // + 1: room for high bits nudged left into another block 675 | len = a.len + 1 - rightShiftBlocks; 676 | allocate(len); 677 | Index i, j; 678 | for (j = rightShiftBlocks, i = 0; j <= a.len; j++, i++) 679 | blk[i] = getShiftedBlock(a, j, leftShiftBits); 680 | // Zap possible leading zero 681 | if (blk[len - 1] == 0) 682 | len--; 683 | } 684 | 685 | void BigUnsigned::print() const { 686 | bigUnsignedToString(*this).print(); 687 | } 688 | 689 | // INCREMENT/DECREMENT OPERATORS 690 | 691 | // Prefix increment 692 | void BigUnsigned::operator ++() { 693 | Index i; 694 | bool carry = true; 695 | for (i = 0; i < len && carry; i++) { 696 | blk[i]++; 697 | carry = (blk[i] == 0); 698 | } 699 | if (carry) { 700 | // Allocate and then increase length, as in divideWithRemainder 701 | allocateAndCopy(len + 1); 702 | len++; 703 | blk[i] = 1; 704 | } 705 | } 706 | 707 | // Postfix increment: same as prefix 708 | void BigUnsigned::operator ++(int) { 709 | operator ++(); 710 | } 711 | 712 | // Prefix decrement 713 | void BigUnsigned::operator --() { 714 | //swapnibble 715 | assert( len != 0, "BigUnsigned::operator --(): Cannot decrement an unsigned zero"); 716 | // if (len == 0) 717 | // throw "BigUnsigned::operator --(): Cannot decrement an unsigned zero"; 718 | 719 | Index i; 720 | bool borrow = true; 721 | for (i = 0; borrow; i++) { 722 | borrow = (blk[i] == 0); 723 | blk[i]--; 724 | } 725 | // Zap possible leading zero (there can only be one) 726 | if (blk[len - 1] == 0) 727 | len--; 728 | } 729 | 730 | // Postfix decrement: same as prefix 731 | void BigUnsigned::operator --(int) { 732 | operator --(); 733 | } 734 | 735 | 736 | /* Implementing the return-by-value and assignment operators in terms of the 737 | * copy-less operations. The copy-less operations are responsible for making 738 | * any necessary temporary copies to work around aliasing. */ 739 | 740 | BigUnsigned BigUnsigned::operator +(const BigUnsigned &x) const { 741 | BigUnsigned ans; 742 | ans.add(*this, x); 743 | return ans; 744 | } 745 | BigUnsigned BigUnsigned::operator -(const BigUnsigned &x) const { 746 | BigUnsigned ans; 747 | ans.subtract(*this, x); 748 | return ans; 749 | } 750 | BigUnsigned BigUnsigned::operator *(const BigUnsigned &x) const { 751 | BigUnsigned ans; 752 | ans.multiply(*this, x); 753 | return ans; 754 | } 755 | BigUnsigned BigUnsigned::operator /(const BigUnsigned &x) const { 756 | // swapnibble if (x.isZero()) throw "BigUnsigned::operator /: division by zero"; 757 | assert( !x.isZero(), "BigUnsigned::operator /: division by zero"); 758 | 759 | BigUnsigned q, r; 760 | r = *this; 761 | r.divideWithRemainder(x, q); 762 | return q; 763 | } 764 | BigUnsigned BigUnsigned::operator %(const BigUnsigned &x) const { 765 | // swapnibble if (x.isZero()) throw "BigUnsigned::operator %: division by zero"; 766 | assert( !x.isZero(), "BigUnsigned::operator %: division by zero"); 767 | BigUnsigned q, r; 768 | r = *this; 769 | r.divideWithRemainder(x, q); 770 | return r; 771 | } 772 | BigUnsigned BigUnsigned::operator &(const BigUnsigned &x) const { 773 | BigUnsigned ans; 774 | ans.bitAnd(*this, x); 775 | return ans; 776 | } 777 | BigUnsigned BigUnsigned::operator |(const BigUnsigned &x) const { 778 | BigUnsigned ans; 779 | ans.bitOr(*this, x); 780 | return ans; 781 | } 782 | BigUnsigned BigUnsigned::operator ^(const BigUnsigned &x) const { 783 | BigUnsigned ans; 784 | ans.bitXor(*this, x); 785 | return ans; 786 | } 787 | BigUnsigned BigUnsigned::operator <<(int b) const { 788 | BigUnsigned ans; 789 | ans.bitShiftLeft(*this, b); 790 | return ans; 791 | } 792 | BigUnsigned BigUnsigned::operator >>(int b) const { 793 | BigUnsigned ans; 794 | ans.bitShiftRight(*this, b); 795 | return ans; 796 | } 797 | 798 | void BigUnsigned::operator +=(const BigUnsigned &x) { 799 | add(*this, x); 800 | } 801 | void BigUnsigned::operator -=(const BigUnsigned &x) { 802 | subtract(*this, x); 803 | } 804 | void BigUnsigned::operator *=(const BigUnsigned &x) { 805 | multiply(*this, x); 806 | } 807 | void BigUnsigned::operator /=(const BigUnsigned &x) { 808 | // swapnibble if (x.isZero()) throw "BigUnsigned::operator /=: division by zero"; 809 | assert( !x.isZero(), "BigUnsigned::operator /=: division by zero"); 810 | /* The following technique is slightly faster than copying *this first 811 | * when x is large. */ 812 | BigUnsigned q; 813 | divideWithRemainder(x, q); 814 | // *this contains the remainder, but we overwrite it with the quotient. 815 | *this = q; 816 | } 817 | void BigUnsigned::operator %=(const BigUnsigned &x) { 818 | // swapnibble if (x.isZero()) throw "BigUnsigned::operator %=: division by zero"; 819 | assert( !x.isZero(), "BigUnsigned::operator %=: division by zero"); 820 | BigUnsigned q; 821 | // Mods *this by x. Don't care about quotient left in q. 822 | divideWithRemainder(x, q); 823 | } 824 | void BigUnsigned::operator &=(const BigUnsigned &x) { 825 | bitAnd(*this, x); 826 | } 827 | void BigUnsigned::operator |=(const BigUnsigned &x) { 828 | bitOr(*this, x); 829 | } 830 | void BigUnsigned::operator ^=(const BigUnsigned &x) { 831 | bitXor(*this, x); 832 | } 833 | void BigUnsigned::operator <<=(int b) { 834 | bitShiftLeft(*this, b); 835 | } 836 | void BigUnsigned::operator >>=(int b) { 837 | bitShiftRight(*this, b); 838 | } 839 | 840 | -------------------------------------------------------------------------------- /BigUnsigned.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This source adapted from https://mattmccutchen.net/bigint/ by Mithrilcoin.io for EOS.IO smart contract. 3 | */ 4 | #ifndef BIGUNSIGNED_H 5 | #define BIGUNSIGNED_H 6 | 7 | #include 8 | #include 9 | #include "NumberlikeArray.hpp" 10 | #include "eos_mem_wrapper.hpp" 11 | 12 | /* A BigUnsigned object represents a nonnegative integer of size limited only by 13 | * available memory. BigUnsigneds support most mathematical operators and can 14 | * be converted to and from most primitive integer types. 15 | * 16 | * The number is stored as a NumberlikeArray of unsigned longs as if it were 17 | * written in base 256^sizeof(unsigned long). The least significant block is 18 | * first, and the length is such that the most significant block is nonzero. */ 19 | class BigUnsigned : protected NumberlikeArray { 20 | 21 | public: 22 | // Enumeration for the result of a comparison. 23 | enum CmpRes { less = -1, equal = 0, greater = 1 }; 24 | 25 | // BigUnsigneds are built with a Blk type of unsigned long. 26 | typedef unsigned long Blk; 27 | 28 | typedef NumberlikeArray::Index Index; 29 | using NumberlikeArray::N; 30 | 31 | protected: 32 | // Creates a BigUnsigned with a capacity; for internal use. 33 | BigUnsigned(int, Index c) : NumberlikeArray(0, c) {} 34 | 35 | // Decreases len to eliminate any leading zero blocks. 36 | void zapLeadingZeros() { 37 | while (len > 0 && blk[len - 1] == 0) 38 | len--; 39 | } 40 | 41 | public: 42 | // Constructs zero. 43 | BigUnsigned() : NumberlikeArray() {} 44 | 45 | // Copy constructor 46 | BigUnsigned(const BigUnsigned &x) : NumberlikeArray(x) {} 47 | 48 | // Assignment operator 49 | void operator=(const BigUnsigned &x) { 50 | NumberlikeArray::operator =(x); 51 | } 52 | 53 | // Constructor that copies from a given array of blocks. 54 | BigUnsigned(const Blk *b, Index blen) : NumberlikeArray(b, blen) { 55 | // Eliminate any leading zeros we may have been passed. 56 | zapLeadingZeros(); 57 | } 58 | 59 | // Destructor. NumberlikeArray does the delete for us. 60 | ~BigUnsigned() {} 61 | 62 | // Constructors from primitive integer types 63 | BigUnsigned(unsigned long x); 64 | BigUnsigned( long x); 65 | BigUnsigned(unsigned int x); 66 | BigUnsigned( int x); 67 | BigUnsigned(unsigned short x); 68 | BigUnsigned( short x); 69 | protected: 70 | // Helpers 71 | template void initFromPrimitive (X x); 72 | template void initFromSignedPrimitive(X x); 73 | public: 74 | 75 | /* Converters to primitive integer types 76 | * The implicit conversion operators caused trouble, so these are now 77 | * named. */ 78 | unsigned long toUnsignedLong () const; 79 | long toLong () const; 80 | unsigned int toUnsignedInt () const; 81 | int toInt () const; 82 | unsigned short toUnsignedShort() const; 83 | short toShort () const; 84 | protected: 85 | // Helpers 86 | template X convertToSignedPrimitive() const; 87 | template X convertToPrimitive () const; 88 | public: 89 | 90 | // BIT/BLOCK ACCESSORS 91 | 92 | // Expose these from NumberlikeArray directly. 93 | using NumberlikeArray::getCapacity; 94 | using NumberlikeArray::getLength; 95 | 96 | /* Returns the requested block, or 0 if it is beyond the length (as if 97 | * the number had 0s infinitely to the left). */ 98 | Blk getBlock(Index i) const { return i >= len ? 0 : blk[i]; } 99 | /* Sets the requested block. The number grows or shrinks as necessary. */ 100 | void setBlock(Index i, Blk newBlock); 101 | 102 | // The number is zero if and only if the canonical length is zero. 103 | bool isZero() const { return NumberlikeArray::isEmpty(); } 104 | 105 | /* Returns the length of the number in bits, i.e., zero if the number 106 | * is zero and otherwise one more than the largest value of bi for 107 | * which getBit(bi) returns true. */ 108 | Index bitLength() const; 109 | /* Get the state of bit bi, which has value 2^bi. Bits beyond the 110 | * number's length are considered to be 0. */ 111 | bool getBit(Index bi) const { 112 | return (getBlock(bi / N) & (Blk(1) << (bi % N))) != 0; 113 | } 114 | /* Sets the state of bit bi to newBit. The number grows or shrinks as 115 | * necessary. */ 116 | void setBit(Index bi, bool newBit); 117 | 118 | // COMPARISONS 119 | 120 | // Compares this to x like Perl's <=> 121 | CmpRes compareTo(const BigUnsigned &x) const; 122 | 123 | // Ordinary comparison operators 124 | bool operator ==(const BigUnsigned &x) const { 125 | return NumberlikeArray::operator ==(x); 126 | } 127 | bool operator !=(const BigUnsigned &x) const { 128 | return NumberlikeArray::operator !=(x); 129 | } 130 | bool operator < (const BigUnsigned &x) const { return compareTo(x) == less ; } 131 | bool operator <=(const BigUnsigned &x) const { return compareTo(x) != greater; } 132 | bool operator >=(const BigUnsigned &x) const { return compareTo(x) != less ; } 133 | bool operator > (const BigUnsigned &x) const { return compareTo(x) == greater; } 134 | 135 | /* 136 | * BigUnsigned and BigInteger both provide three kinds of operators. 137 | * Here ``big-integer'' refers to BigInteger or BigUnsigned. 138 | * 139 | * (1) Overloaded ``return-by-value'' operators: 140 | * +, -, *, /, %, unary -, &, |, ^, <<, >>. 141 | * Big-integer code using these operators looks identical to code using 142 | * the primitive integer types. These operators take one or two 143 | * big-integer inputs and return a big-integer result, which can then 144 | * be assigned to a BigInteger variable or used in an expression. 145 | * Example: 146 | * BigInteger a(1), b = 1; 147 | * BigInteger c = a + b; 148 | * 149 | * (2) Overloaded assignment operators: 150 | * +=, -=, *=, /=, %=, flipSign, &=, |=, ^=, <<=, >>=, ++, --. 151 | * Again, these are used on big integers just like on ints. They take 152 | * one writable big integer that both provides an operand and receives a 153 | * result. Most also take a second read-only operand. 154 | * Example: 155 | * BigInteger a(1), b(1); 156 | * a += b; 157 | * 158 | * (3) Copy-less operations: `add', `subtract', etc. 159 | * These named methods take operands as arguments and store the result 160 | * in the receiver (*this), avoiding unnecessary copies and allocations. 161 | * `divideWithRemainder' is special: it both takes the dividend from and 162 | * stores the remainder into the receiver, and it takes a separate 163 | * object in which to store the quotient. NOTE: If you are wondering 164 | * why these don't return a value, you probably mean to use the 165 | * overloaded return-by-value operators instead. 166 | * 167 | * Examples: 168 | * BigInteger a(43), b(7), c, d; 169 | * 170 | * c = a + b; // Now c == 50. 171 | * c.add(a, b); // Same effect but without the two copies. 172 | * 173 | * c.divideWithRemainder(b, d); 174 | * // 50 / 7; now d == 7 (quotient) and c == 1 (remainder). 175 | * 176 | * // ``Aliased'' calls now do the right thing using a temporary 177 | * // copy, but see note on `divideWithRemainder'. 178 | * a.add(a, b); 179 | */ 180 | 181 | // COPY-LESS OPERATIONS 182 | 183 | // These 8: Arguments are read-only operands, result is saved in *this. 184 | void add(const BigUnsigned &a, const BigUnsigned &b); 185 | void subtract(const BigUnsigned &a, const BigUnsigned &b); 186 | void multiply(const BigUnsigned &a, const BigUnsigned &b); 187 | void bitAnd(const BigUnsigned &a, const BigUnsigned &b); 188 | void bitOr(const BigUnsigned &a, const BigUnsigned &b); 189 | void bitXor(const BigUnsigned &a, const BigUnsigned &b); 190 | /* Negative shift amounts translate to opposite-direction shifts, 191 | * except for -2^(8*sizeof(int)-1) which is unimplemented. */ 192 | void bitShiftLeft(const BigUnsigned &a, int b); 193 | void bitShiftRight(const BigUnsigned &a, int b); 194 | 195 | /* `a.divideWithRemainder(b, q)' is like `q = a / b, a %= b'. 196 | * / and % use semantics similar to Knuth's, which differ from the 197 | * primitive integer semantics under division by zero. See the 198 | * implementation in BigUnsigned.cc for details. 199 | * `a.divideWithRemainder(b, a)' throws an exception: it doesn't make 200 | * sense to write quotient and remainder into the same variable. */ 201 | void divideWithRemainder(const BigUnsigned &b, BigUnsigned &q); 202 | 203 | // swapnibble 204 | void print() const; 205 | 206 | /* `divide' and `modulo' are no longer offered. Use 207 | * `divideWithRemainder' instead. */ 208 | 209 | // OVERLOADED RETURN-BY-VALUE OPERATORS 210 | BigUnsigned operator +(const BigUnsigned &x) const; 211 | BigUnsigned operator -(const BigUnsigned &x) const; 212 | BigUnsigned operator *(const BigUnsigned &x) const; 213 | BigUnsigned operator /(const BigUnsigned &x) const; 214 | BigUnsigned operator %(const BigUnsigned &x) const; 215 | /* OK, maybe unary minus could succeed in one case, but it really 216 | * shouldn't be used, so it isn't provided. */ 217 | BigUnsigned operator &(const BigUnsigned &x) const; 218 | BigUnsigned operator |(const BigUnsigned &x) const; 219 | BigUnsigned operator ^(const BigUnsigned &x) const; 220 | BigUnsigned operator <<(int b) const; 221 | BigUnsigned operator >>(int b) const; 222 | 223 | // OVERLOADED ASSIGNMENT OPERATORS 224 | void operator +=(const BigUnsigned &x); 225 | void operator -=(const BigUnsigned &x); 226 | void operator *=(const BigUnsigned &x); 227 | void operator /=(const BigUnsigned &x); 228 | void operator %=(const BigUnsigned &x); 229 | void operator &=(const BigUnsigned &x); 230 | void operator |=(const BigUnsigned &x); 231 | void operator ^=(const BigUnsigned &x); 232 | void operator <<=(int b); 233 | void operator >>=(int b); 234 | 235 | /* INCREMENT/DECREMENT OPERATORS 236 | * To discourage messy coding, these do not return *this, so prefix 237 | * and postfix behave the same. */ 238 | void operator ++( ); 239 | void operator ++(int); 240 | void operator --( ); 241 | void operator --(int); 242 | 243 | // Helper function that needs access to BigUnsigned internals 244 | friend Blk getShiftedBlock(const BigUnsigned &num, Index x, 245 | unsigned int y); 246 | 247 | // See BigInteger.cc. 248 | template 249 | friend X convertBigUnsignedToPrimitiveAccess(const BigUnsigned &a); 250 | }; 251 | 252 | /* Templates for conversions of BigUnsigned to and from primitive integers. 253 | * BigInteger.cc needs to instantiate convertToPrimitive, and the uses in 254 | * BigUnsigned.cc didn't do the trick; I think g++ inlined convertToPrimitive 255 | * instead of generating linkable instantiations. So for consistency, I put 256 | * all the templates here. */ 257 | 258 | // CONSTRUCTION FROM PRIMITIVE INTEGERS 259 | 260 | /* Initialize this BigUnsigned from the given primitive integer. The same 261 | * pattern works for all primitive integer types, so I put it into a template to 262 | * reduce code duplication. (Don't worry: this is protected and we instantiate 263 | * it only with primitive integer types.) Type X could be signed, but x is 264 | * known to be nonnegative. */ 265 | template 266 | void BigUnsigned::initFromPrimitive(X x) { 267 | if (x == 0) 268 | ; // NumberlikeArray already initialized us to zero. 269 | else { 270 | // Create a single block. blk is NULL; no need to delete it. 271 | cap = 1; 272 | blk = (Blk*) eosio::malloc(sizeof(Blk));//swapnibble new Blk[1]; 273 | len = 1; 274 | blk[0] = Blk(x); 275 | } 276 | } 277 | 278 | /* Ditto, but first check that x is nonnegative. I could have put the check in 279 | * initFromPrimitive and let the compiler optimize it out for unsigned-type 280 | * instantiations, but I wanted to avoid the warning stupidly issued by g++ for 281 | * a condition that is constant in *any* instantiation, even if not in all. */ 282 | template 283 | void BigUnsigned::initFromSignedPrimitive(X x) { 284 | //swapnibble 285 | /* 286 | if (x < 0) 287 | throw "BigUnsigned constructor: " 288 | "Cannot construct a BigUnsigned from a negative number"; 289 | else 290 | initFromPrimitive(x); 291 | */ 292 | assert( x >= 0, "BigUnsigned constructor: Cannot construct a BigUnsigned from a negative number"); 293 | 294 | initFromPrimitive(x); 295 | } 296 | 297 | // CONVERSION TO PRIMITIVE INTEGERS 298 | 299 | /* Template with the same idea as initFromPrimitive. This might be slightly 300 | * slower than the previous version with the masks, but it's much shorter and 301 | * clearer, which is the library's stated goal. */ 302 | template 303 | X BigUnsigned::convertToPrimitive() const { 304 | if (len == 0) 305 | // The number is zero; return zero. 306 | return 0; 307 | else if (len == 1) { 308 | // The single block might fit in an X. Try the conversion. 309 | X x = X(blk[0]); 310 | // Make sure the result accurately represents the block. 311 | if (Blk(x) == blk[0]) 312 | // Successful conversion. 313 | return x; 314 | // Otherwise fall through. 315 | } 316 | 317 | //swapnibble 318 | // throw "BigUnsigned::to: " 319 | // "Value is too big to fit in the requested type"; 320 | assert( 0, "BigUnsigned::to: Value is too big to fit in the requested type"); 321 | return 0; 322 | } 323 | 324 | /* Wrap the above in an x >= 0 test to make sure we got a nonnegative result, 325 | * not a negative one that happened to convert back into the correct nonnegative 326 | * one. (E.g., catch incorrect conversion of 2^31 to the long -2^31.) Again, 327 | * separated to avoid a g++ warning. */ 328 | template 329 | X BigUnsigned::convertToSignedPrimitive() const { 330 | X x = convertToPrimitive(); 331 | 332 | //swapnibble 333 | /* 334 | if (x >= 0) 335 | return x; 336 | else 337 | throw "BigUnsigned::to(Primitive): " 338 | "Value is too big to fit in the requested type"; 339 | */ 340 | 341 | assert( x < 0, "BigUnsigned::to(Primitive): Value is too big to fit in the requested type"); 342 | 343 | return x; 344 | } 345 | 346 | #endif 347 | -------------------------------------------------------------------------------- /BigUnsignedInABase.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This source adapted from https://mattmccutchen.net/bigint/ by Mithrilcoin.io for EOS.IO smart contract. 3 | */ 4 | #include "BigUnsignedInABase.hpp" 5 | 6 | 7 | BigUnsignedInABase::BigUnsignedInABase(const Digit *d, Index l, Base base) 8 | : NumberlikeArray(d, l), base(base) { 9 | // Check the base 10 | //swapnibble 11 | assert( base >= 2, "BigUnsignedInABase::BigUnsignedInABase(const Digit *, Index, Base): The base must be at least 2"); 12 | // if (base < 2) 13 | // throw "BigUnsignedInABase::BigUnsignedInABase(const Digit *, Index, Base): The base must be at least 2"; 14 | 15 | // Validate the digits. 16 | for (Index i = 0; i < l; i++) { 17 | //swapnibble 18 | assert( blk[i] < base, 19 | "BigUnsignedInABase::BigUnsignedInABase(const Digit *, Index, Base): A digit is too large for the specified base" ); 20 | // if (blk[i] >= base) 21 | // throw "BigUnsignedInABase::BigUnsignedInABase(const Digit *, Index, Base): A digit is too large for the specified base"; 22 | } 23 | 24 | // Eliminate any leading zeros we may have been passed. 25 | zapLeadingZeros(); 26 | } 27 | 28 | unsigned int bitLen(unsigned int x) { 29 | unsigned int len = 0; 30 | while (x > 0) { 31 | x >>= 1; 32 | len++; 33 | } 34 | return len; 35 | } 36 | unsigned int ceilingDiv(unsigned int a, unsigned int b) { 37 | return (a + b - 1) / b; 38 | } 39 | 40 | BigUnsignedInABase::BigUnsignedInABase(const BigUnsigned &x, Base base) { 41 | // Check the base 42 | //swapnibble 43 | assert( base >= 2, "BigUnsignedInABase(BigUnsigned, Base): The base must be at least 2"); 44 | // if (base < 2) 45 | // throw "BigUnsignedInABase(BigUnsigned, Base): The base must be at least 2"; 46 | this->base = base; 47 | 48 | // Get an upper bound on how much space we need 49 | int maxBitLenOfX = x.getLength() * BigUnsigned::N; 50 | int minBitsPerDigit = bitLen(base) - 1; 51 | int maxDigitLenOfX = ceilingDiv(maxBitLenOfX, minBitsPerDigit); 52 | len = maxDigitLenOfX; // Another change to comply with `staying in bounds'. 53 | allocate(len); // Get the space 54 | 55 | BigUnsigned x2(x), buBase(base); 56 | Index digitNum = 0; 57 | 58 | while (!x2.isZero()) { 59 | // Get last digit. This is like `lastDigit = x2 % buBase, x2 /= buBase'. 60 | BigUnsigned lastDigit(x2); 61 | lastDigit.divideWithRemainder(buBase, x2); 62 | // Save the digit. 63 | blk[digitNum] = lastDigit.toUnsignedShort(); 64 | // Move on. We can't run out of room: we figured it out above. 65 | digitNum++; 66 | } 67 | 68 | // Save the actual length. 69 | len = digitNum; 70 | } 71 | 72 | BigUnsignedInABase::operator BigUnsigned() const { 73 | BigUnsigned ans(0), buBase(base), temp; 74 | Index digitNum = len; 75 | while (digitNum > 0) { 76 | digitNum--; 77 | temp.multiply(ans, buBase); 78 | ans.add(temp, BigUnsigned(blk[digitNum])); 79 | } 80 | return ans; 81 | } 82 | 83 | BigUnsignedInABase::BigUnsignedInABase( const eosio::string &s, Base base) { 84 | // Check the base. 85 | //swapnibble 86 | assert( (int)base <= 36 87 | , "BigUnsignedInABase(std::string, Base): The default string conversion routines use the symbol set 0-9, A-Z and therefore support only up to base 36. You tried a conversion with a base over 36; write your own string conversion routine."); 88 | // if (base > 36) 89 | // throw "BigUnsignedInABase(std::string, Base): The default string conversion routines use the symbol set 0-9, A-Z and therefore support only up to base 36. You tried a conversion with a base over 36; write your own string conversion routine."; 90 | // Save the base. 91 | // This pattern is seldom seen in C++, but the analogous ``this.'' is common in Java. 92 | this->base = base; 93 | 94 | // `s.length()' is a `size_t', while `len' is a `NumberlikeArray::Index', 95 | // also known as an `unsigned int'. Some compilers warn without this cast. 96 | len = Index( s.get_size() - 1);//swapnibble Index(s.length()); 97 | allocate(len); 98 | 99 | Index digitNum, symbolNumInString; 100 | for (digitNum = 0; digitNum < len; digitNum++) { 101 | symbolNumInString = len - 1 - digitNum; 102 | char theSymbol = s.get_data()[symbolNumInString];//swapnibble s[symbolNumInString]; 103 | if (theSymbol >= '0' && theSymbol <= '9') 104 | blk[digitNum] = theSymbol - '0'; 105 | else if (theSymbol >= 'A' && theSymbol <= 'Z') 106 | blk[digitNum] = theSymbol - 'A' + 10; 107 | else if (theSymbol >= 'a' && theSymbol <= 'z') 108 | blk[digitNum] = theSymbol - 'a' + 10; 109 | else { 110 | //swapnibble 111 | eosio::print("\n\nBigUnsignedInABase ctor, stringLen: ", len 112 | , "symbolNumInString: ", symbolNumInString,", theSymbol:", (int)theSymbol, "\n\n"); 113 | assert( 0 114 | , "BigUnsignedInABase(std::string, Base): Bad symbol in input. Only 0-9, A-Z, a-z are accepted."); 115 | // throw "BigUnsignedInABase(std::string, Base): Bad symbol in input. Only 0-9, A-Z, a-z are accepted."; 116 | } 117 | 118 | //swapnibble 119 | assert( blk[digitNum] < base 120 | , "BigUnsignedInABase::BigUnsignedInABase(const Digit *, Index, Base): A digit is too large for the specified base"); 121 | // if (blk[digitNum] >= base) 122 | // throw "BigUnsignedInABase::BigUnsignedInABase(const Digit *, Index, Base): A digit is too large for the specified base"; 123 | } 124 | zapLeadingZeros(); 125 | } 126 | 127 | BigUnsignedInABase::operator eosio::string() const { 128 | //swapnibble 129 | assert( base <= 36 130 | , "BigUnsignedInABase ==> std::string: The default string conversion routines use the symbol set 0-9, A-Z and therefore support only up to base 36. You tried a conversion with a base over 36; write your own string conversion routine."); 131 | // if (base > 36) 132 | // throw "BigUnsignedInABase ==> std::string: The default string conversion routines use the symbol set 0-9, A-Z and therefore support only up to base 36. You tried a conversion with a base over 36; write your own string conversion routine."; 133 | 134 | if (len == 0) 135 | return eosio::string("0"); 136 | // Some compilers don't have push_back, so use a char * buffer instead. 137 | char *s = new char[len + 1]; //(char*)eosio::malloc(len + 1); //swapnibble 138 | s[len] = '\0'; 139 | Index digitNum, symbolNumInString; 140 | for (symbolNumInString = 0; symbolNumInString < len; symbolNumInString++) { 141 | digitNum = len - 1 - symbolNumInString; 142 | Digit theDigit = blk[digitNum]; 143 | if (theDigit < 10) 144 | s[symbolNumInString] = char('0' + theDigit); 145 | else 146 | s[symbolNumInString] = char('A' + theDigit - 10); 147 | } 148 | eosio::string s2(s); 149 | delete [] s; //eosio::free(s);//swapnibble 150 | return s2; 151 | } 152 | -------------------------------------------------------------------------------- /BigUnsignedInABase.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This source adapted from https://mattmccutchen.net/bigint/ by Mithrilcoin.io for EOS.IO smart contract. 3 | */ 4 | #ifndef BIGUNSIGNEDINABASE_H 5 | #define BIGUNSIGNEDINABASE_H 6 | 7 | #include "NumberlikeArray.hpp" 8 | #include "BigUnsigned.hpp" 9 | #include //#include 10 | 11 | /* 12 | * A BigUnsignedInABase object represents a nonnegative integer of size limited 13 | * only by available memory, represented in a user-specified base that can fit 14 | * in an `unsigned short' (most can, and this saves memory). 15 | * 16 | * BigUnsignedInABase is intended as an intermediary class with little 17 | * functionality of its own. BigUnsignedInABase objects can be constructed 18 | * from, and converted to, BigUnsigneds (requiring multiplication, mods, etc.) 19 | * and `std::string's (by switching digit values for appropriate characters). 20 | * 21 | * BigUnsignedInABase is similar to BigUnsigned. Note the following: 22 | * 23 | * (1) They represent the number in exactly the same way, except that 24 | * BigUnsignedInABase uses ``digits'' (or Digit) where BigUnsigned uses 25 | * ``blocks'' (or Blk). 26 | * 27 | * (2) Both use the management features of NumberlikeArray. (In fact, my desire 28 | * to add a BigUnsignedInABase class without duplicating a lot of code led me to 29 | * introduce NumberlikeArray.) 30 | * 31 | * (3) The only arithmetic operation supported by BigUnsignedInABase is an 32 | * equality test. Use BigUnsigned for arithmetic. 33 | */ 34 | class BigUnsignedInABase : protected NumberlikeArray { 35 | 36 | public: 37 | // The digits of a BigUnsignedInABase are unsigned shorts. 38 | typedef unsigned short Digit; 39 | // That's also the type of a base. 40 | typedef Digit Base; 41 | 42 | protected: 43 | // The base in which this BigUnsignedInABase is expressed 44 | Base base; 45 | 46 | // Creates a BigUnsignedInABase with a capacity; for internal use. 47 | BigUnsignedInABase(int, Index c) : NumberlikeArray(0, c) {} 48 | 49 | // Decreases len to eliminate any leading zero digits. 50 | void zapLeadingZeros() { 51 | while (len > 0 && blk[len - 1] == 0) 52 | len--; 53 | } 54 | 55 | public: 56 | // Constructs zero in base 2. 57 | BigUnsignedInABase() : NumberlikeArray(), base(2) {} 58 | 59 | // Copy constructor 60 | BigUnsignedInABase(const BigUnsignedInABase &x) : NumberlikeArray(x), base(x.base) {} 61 | 62 | // Assignment operator 63 | void operator =(const BigUnsignedInABase &x) { 64 | NumberlikeArray::operator =(x); 65 | base = x.base; 66 | } 67 | 68 | // Constructor that copies from a given array of digits. 69 | BigUnsignedInABase(const Digit *d, Index l, Base base); 70 | 71 | // Destructor. NumberlikeArray does the delete for us. 72 | ~BigUnsignedInABase() {} 73 | 74 | // LINKS TO BIGUNSIGNED 75 | BigUnsignedInABase(const BigUnsigned &x, Base base); 76 | operator BigUnsigned() const; 77 | 78 | /* LINKS TO STRINGS 79 | * 80 | * These use the symbols ``0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'' to 81 | * represent digits of 0 through 35. When parsing strings, lowercase is 82 | * also accepted. 83 | * 84 | * All string representations are big-endian (big-place-value digits 85 | * first). (Computer scientists have adopted zero-based counting; why 86 | * can't they tolerate little-endian numbers?) 87 | * 88 | * No string representation has a ``base indicator'' like ``0x''. 89 | * 90 | * An exception is made for zero: it is converted to ``0'' and not the 91 | * empty string. 92 | * 93 | * If you want different conventions, write your own routines to go 94 | * between BigUnsignedInABase and strings. It's not hard. 95 | */ 96 | operator eosio::string() const; 97 | BigUnsignedInABase(const eosio::string &s, Base base); 98 | 99 | public: 100 | 101 | // ACCESSORS 102 | Base getBase() const { return base; } 103 | 104 | // Expose these from NumberlikeArray directly. 105 | using NumberlikeArray::getCapacity; 106 | using NumberlikeArray::getLength; 107 | 108 | /* Returns the requested digit, or 0 if it is beyond the length (as if 109 | * the number had 0s infinitely to the left). */ 110 | Digit getDigit(Index i) const { return i >= len ? 0 : blk[i]; } 111 | 112 | // The number is zero if and only if the canonical length is zero. 113 | bool isZero() const { return NumberlikeArray::isEmpty(); } 114 | 115 | /* Equality test. For the purposes of this test, two BigUnsignedInABase 116 | * values must have the same base to be equal. */ 117 | bool operator ==(const BigUnsignedInABase &x) const { 118 | return base == x.base && NumberlikeArray::operator ==(x); 119 | } 120 | bool operator !=(const BigUnsignedInABase &x) const { return !operator ==(x); } 121 | 122 | }; 123 | 124 | #endif 125 | -------------------------------------------------------------------------------- /NumberlikeArray.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * This source adapted from https://mattmccutchen.net/bigint/ by Mithrilcoin.io for EOS.IO smart contract. 3 | */ 4 | #ifndef NUMBERLIKEARRAY_H 5 | #define NUMBERLIKEARRAY_H 6 | 7 | // Make sure we have NULL. 8 | #ifndef NULL 9 | #define NULL 0 10 | #endif 11 | 12 | #include "eos_mem_wrapper.hpp" 13 | 14 | /* A NumberlikeArray object holds a heap-allocated array of Blk with a 15 | * length and a capacity and provides basic memory management features. 16 | * BigUnsigned and BigUnsignedInABase both subclass it. 17 | * 18 | * NumberlikeArray provides no information hiding. Subclasses should use 19 | * nonpublic inheritance and manually expose members as desired using 20 | * declarations like this: 21 | * 22 | * public: 23 | * NumberlikeArray< the-type-argument >::getLength; 24 | */ 25 | 26 | template 27 | class NumberlikeArray { 28 | public: 29 | 30 | // Type for the index of a block in the array 31 | typedef unsigned int Index; 32 | // The number of bits in a block, defined below. 33 | static const unsigned int N; 34 | 35 | // The current allocated capacity of this NumberlikeArray (in blocks) 36 | Index cap; 37 | // The actual length of the value stored in this NumberlikeArray (in blocks) 38 | Index len; 39 | // Heap-allocated array of the blocks (can be NULL if len == 0) 40 | Blk *blk; 41 | 42 | // void* operator new( unsigned int size) { 43 | // void *pRet = eosio::malloc( size ); 44 | // // print("\nallocFromEosMemMgr: 0x"); 45 | // // ::printhex( pRet, sizeof(void*) ); 46 | // return pRet; 47 | // } 48 | 49 | // void operator delete( void *pPtr ){ 50 | // eosio::free( pPtr ); 51 | // } 52 | 53 | // Constructs a ``zero'' NumberlikeArray with the given capacity. 54 | NumberlikeArray(Index c) : cap(c), len(0) { 55 | blk = (cap > 0) ? (new Blk[cap]) : NULL; //(Blk*)eosio::malloc(cap*sizeof(Blk)) : NULL ;//swapnibble 56 | } 57 | 58 | /* Constructs a zero NumberlikeArray without allocating a backing array. 59 | * A subclass that doesn't know the needed capacity at initialization 60 | * time can use this constructor and then overwrite blk without first 61 | * deleting it. */ 62 | NumberlikeArray() : cap(0), len(0) { 63 | blk = NULL; 64 | } 65 | 66 | // Destructor. Note that `delete NULL' is a no-op. 67 | ~NumberlikeArray() { 68 | delete [] blk; //eosio::free(blk);//swapnibble delete [] blk; // 69 | } 70 | 71 | /* Ensures that the array has at least the requested capacity; may 72 | * destroy the contents. */ 73 | void allocate(Index c); 74 | 75 | /* Ensures that the array has at least the requested capacity; does not 76 | * destroy the contents. */ 77 | void allocateAndCopy(Index c); 78 | 79 | // Copy constructor 80 | NumberlikeArray(const NumberlikeArray &x); 81 | 82 | // Assignment operator 83 | void operator=(const NumberlikeArray &x); 84 | 85 | // Constructor that copies from a given array of blocks 86 | NumberlikeArray(const Blk *b, Index blen); 87 | 88 | // ACCESSORS 89 | Index getCapacity() const { return cap; } 90 | Index getLength() const { return len; } 91 | Blk getBlock(Index i) const { return blk[i]; } 92 | bool isEmpty() const { return len == 0; } 93 | 94 | /* Equality comparison: checks if both objects have the same length and 95 | * equal (==) array elements to that length. Subclasses may wish to 96 | * override. */ 97 | bool operator ==(const NumberlikeArray &x) const; 98 | 99 | bool operator !=(const NumberlikeArray &x) const { 100 | return !operator ==(x); 101 | } 102 | 103 | 104 | }; 105 | 106 | /* BEGIN TEMPLATE DEFINITIONS. They are present here so that source files that 107 | * include this header file can generate the necessary real definitions. */ 108 | 109 | template 110 | const unsigned int NumberlikeArray::N = 8 * sizeof(Blk); 111 | 112 | template 113 | void NumberlikeArray::allocate(Index c) { 114 | // If the requested capacity is more than the current capacity... 115 | if (c > cap) { 116 | // Delete the old number array 117 | delete [] blk; //eosio::free(blk);//swapnibble 118 | // Allocate the new array 119 | cap = c; 120 | blk = new Blk[cap]; //(Blk *)eosio::malloc( sizeof(Blk)*cap);//swapnibble new Blk[cap]; // 121 | } 122 | } 123 | 124 | template 125 | void NumberlikeArray::allocateAndCopy(Index c) { 126 | // If the requested capacity is more than the current capacity... 127 | if (c > cap) { 128 | Blk *oldBlk = blk; 129 | // Allocate the new number array 130 | cap = c; 131 | blk = new Blk[cap]; //(Blk *)eosio::malloc( sizeof(Blk)*cap);//swapnibble new Blk[cap]; // 132 | // Copy number blocks 133 | Index i; 134 | for (i = 0; i < len; i++) 135 | blk[i] = oldBlk[i]; 136 | // Delete the old array 137 | delete [] oldBlk; //eosio::free(oldBlk);//swapnibble delete [] oldBlk; // 138 | } 139 | } 140 | 141 | template 142 | NumberlikeArray::NumberlikeArray(const NumberlikeArray &x) 143 | : len(x.len) { 144 | // Create array 145 | cap = len; 146 | blk = new Blk[cap]; //(Blk *)eosio::malloc( sizeof(Blk)*cap);//swapnibble new Blk[cap]; // 147 | // Copy blocks 148 | Index i; 149 | for (i = 0; i < len; i++) 150 | blk[i] = x.blk[i]; 151 | } 152 | 153 | template 154 | void NumberlikeArray::operator=(const NumberlikeArray &x) { 155 | /* Calls like a = a have no effect; catch them before the aliasing 156 | * causes a problem */ 157 | if (this == &x) 158 | return; 159 | // Copy length 160 | len = x.len; 161 | // Expand array if necessary 162 | allocate(len); 163 | // Copy number blocks 164 | Index i; 165 | for (i = 0; i < len; i++) 166 | blk[i] = x.blk[i]; 167 | } 168 | 169 | template 170 | NumberlikeArray::NumberlikeArray(const Blk *b, Index blen) 171 | : cap(blen), len(blen) { 172 | // Create array 173 | blk = new Blk[cap];//(Blk *)eosio::malloc( sizeof(Blk)*cap);//swapnibble new Blk[cap];// 174 | // Copy blocks 175 | Index i; 176 | for (i = 0; i < len; i++) 177 | blk[i] = b[i]; 178 | } 179 | 180 | template 181 | bool NumberlikeArray::operator ==(const NumberlikeArray &x) const { 182 | if (len != x.len) 183 | // Definitely unequal. 184 | return false; 185 | else { 186 | // Compare corresponding blocks one by one. 187 | Index i; 188 | for (i = 0; i < len; i++) 189 | if (blk[i] != x.blk[i]) 190 | return false; 191 | // No blocks differed, so the objects are equal. 192 | return true; 193 | } 194 | } 195 | 196 | #endif 197 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BigInteger for EOS.IO 2 | 3 | BigInteger library for EOS Smart Contract 4 | 5 | # Table of contents 6 | - [What is this?](#what_is_this) 7 | - [Original author](#original_author) 8 | - [Example](#example) 9 | - [Operators](#operators) 10 | - [Build](#build) 11 | 12 | 13 | You can use this library in a EOS Smart contract to do arithmetic without any precision limit. 14 | 15 | This library has been tested on EOS.IO DAWN 2.x . 16 | See [EOSIO github](https://github.com/EOSIO/eos). 17 | 18 | 19 | ## Original author 20 | Matt McCutchen ( [C++ Big Integer Library](https://mattmccutchen.net/bigint/) ) 21 | 22 | 23 | ## Example 24 |

25 |  #include "eoslib/print.hpp"  
26 |  #include "BigIntegerLibrary.hpp"  
27 |     
28 |  BigInteger a = 65536;  
29 |  print("a * a * a * a * a * a * a * a: ", ( a * a * a * a * a * a * a * a ) );  
30 | 
31 | then, eosd prints 340282366920938463463374607431768211456. 32 | 33 | 34 | ## Operators 35 |

36 | arithmetic : +, -, *, /, %, ++(pre, post), --(pre, post), +=, -=, *=, /=, %=, etc.. ( see header for more details )
37 | bit : &, |, ^, <<=, >>= , etc.. ( see header for more details ) 
38 | 
39 | 40 | 41 | ## Build 42 | `eoscpp -o eos_mem_wrapper.cpp BigInteger.cpp BigIntegerAlgorithms.cpp BigIntegerUtils.cpp BigUnsigned.cpp BigUnsignedInABase.cpp` 43 | 44 | If linker complains about memory_heap variable, then change as followings: 45 | 46 | find `memory_heap` variable in `memory.hpp` ( eoslib ) 47 | then, change : 48 |

49 | static memory_manager memory_heap;
50 | 
5 | 6 | using namespace eosio; 7 | 8 | // new/delete operator overloading for eos smart contract by mithrilcoin.io 9 | void* operator new (unsigned int size){ 10 | return eosio::malloc( size ); 11 | } 12 | 13 | void* operator new[] (unsigned int size){ 14 | return eosio::malloc( size ); 15 | } 16 | 17 | void operator delete (void* ptr){ 18 | eosio::free( ptr); 19 | } 20 | 21 | void operator delete[] (void* ptr) { 22 | eosio::free( ptr); 23 | } -------------------------------------------------------------------------------- /eos_mem_wrapper.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * new/delete operator overloading for eosio smart contract ( on dawn2.x ) 3 | * 4 | * @copyright Mithrilcoin.io 5 | */ 6 | #ifndef __EOS_MEM_WRAPPER_H__ 7 | #define __EOS_MEM_WRAPPER_H__ 8 | 9 | #include 10 | 11 | void* operator new (unsigned int size); 12 | void* operator new[] (unsigned int size); 13 | void operator delete (void* ptr); 14 | void operator delete[] (void* ptr); 15 | #endif --------------------------------------------------------------------------------