00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef _BigInteger_h
00018 #define _BigInteger_h
00019
00020 #include <spl/types.h>
00021 #include <spl/collection/Array.h>
00022 #include <spl/math/Random.h>
00023 #include <spl/RefCountPtr.h>
00024 #include <spl/String.h>
00025
00032 #define BIGINTEGER_MAJIC 721 //< Majic number for ASSERT's in Compare and Convert
00033
00034 class BigInteger;
00035 typedef RefCountPtr<BigInteger> BigIntegerPtr;
00036 typedef WeakReference<BigInteger, BigIntegerPtr> BigIntegerRef;
00037
00038 REGISTER_TYPEOF( 550, BigIntegerPtr );
00039 REGISTER_TYPEOF( 552, BigIntegerRef );
00040
00042 class BigInteger : public IComparable, public IMemoryValidate
00043 {
00044
00045 private:
00046
00047 #define BIGINTEGER_PRIMELIST_ROWS 52
00048 #define BIGINTEGER_PRIMELIST_COLS 9
00049
00050 static const int m_primeLists[BIGINTEGER_PRIMELIST_ROWS][BIGINTEGER_PRIMELIST_COLS];
00051 static int m_primeProducts[BIGINTEGER_PRIMELIST_ROWS];
00052 static bool m_primeProductsInited;
00053
00054 static const byte m_rndMask[];
00055
00056 #define BIGINTEGER_IMASK ((int64)0xffffffffL)
00057 #define BIGINTEGER_UIMASK ((uint64)0xffffffffL)
00058
00059 static const int m_chunk2;
00060 static const int m_chunk10;
00061 static const int m_chunk16;
00062
00063 #define BitsPerByte 8
00064 #define BitsPerInt 32
00065 #define BytesPerInt 4
00066
00067 static Random m_randomSource;
00068 static BigIntegerPtr m_zero;
00069 static BigIntegerPtr m_one;
00070 static BigIntegerPtr m_two;
00071
00072 static void Init2();
00073
00074 inline static void Init()
00075 {
00076 if (m_primeProductsInited)
00077 {
00078 return;
00079 }
00080 Init2();
00081 }
00082
00083 static int GetByteLength(int nBits)
00084 {
00085 return (nBits + BitsPerByte - 1) / BitsPerByte;
00086 }
00087
00088 static BigIntegerPtr CreateUValueOf(uint64 value);
00089 static BigIntegerPtr CreateValueOf(int64 value);
00090
00091 static RefCountPtr<Array<int32> > MakeMagnitude(const Array<byte>& bytes, int offset, int length);
00092
00093 static int CompareNoLeadingZeroes(int xIndx, const Array<int32>& x, int yIndx, const Array<int32>& y);
00094
00095 inline static int BitLen(int w)
00096 {
00097
00098 return (w < 1 << 15 ? (w < 1 << 7
00099 ? (w < 1 << 3 ? (w < 1 << 1
00100 ? (w < 1 << 0 ? (w < 0 ? 32 : 0) : 1)
00101 : (w < 1 << 2 ? 2 : 3)) : (w < 1 << 5
00102 ? (w < 1 << 4 ? 4 : 5)
00103 : (w < 1 << 6 ? 6 : 7)))
00104 : (w < 1 << 11
00105 ? (w < 1 << 9 ? (w < 1 << 8 ? 8 : 9) : (w < 1 << 10 ? 10 : 11))
00106 : (w < 1 << 13 ? (w < 1 << 12 ? 12 : 13) : (w < 1 << 14 ? 14 : 15)))) : (w < 1 << 23 ? (w < 1 << 19
00107 ? (w < 1 << 17 ? (w < 1 << 16 ? 16 : 17) : (w < 1 << 18 ? 18 : 19))
00108 : (w < 1 << 21 ? (w < 1 << 20 ? 20 : 21) : (w < 1 << 22 ? 22 : 23))) : (w < 1 << 27
00109 ? (w < 1 << 25 ? (w < 1 << 24 ? 24 : 25) : (w < 1 << 26 ? 26 : 27))
00110 : (w < 1 << 29 ? (w < 1 << 28 ? 28 : 29) : (w < 1 << 30 ? 30 : 31)))));
00111 }
00112
00113 static RefCountPtr<Array<int32> > DoSubBigLil(Array<int32>& bigMag, Array<int32>& lilMag);
00114
00115 static void ShiftRightOneInPlace(int start, Array<int32>& mag);
00116 static void ShiftRightInPlace(int start, Array<int32>& mag, int n);
00117 static RefCountPtr<Array<int32> > ShiftLeft(Array<int32>& mag, int n);
00118
00119 static void AddMagnitudes(Array<int32>& a, Array<int32>& b);
00120
00121 static const BigInteger& Two();
00122
00123 static void Subtract
00124 (
00125 int xIndx,
00126 Array<int32>& x,
00127 int yIndx,
00128 Array<int32>& y
00129 );
00130
00131 static void Multiply
00132 (
00133 Array<int32>& x,
00134 Array<int32>& y,
00135 Array<int32>& z
00136 );
00137
00138 static void MultiplyMonty
00139 (
00140 Array<int32>& a,
00141 Array<int32>& x,
00142 Array<int32>& y,
00143 Array<int32>& m,
00144 int64 mQuote
00145 );
00146
00147 static uint32 MultiplyMontyNIsOne
00148 (
00149 uint32 x,
00150 uint32 y,
00151 uint32 m,
00152 uint64 mQuote
00153 );
00154
00155 static int CompareTo
00156 (
00157 int xIndx,
00158 Array<int32>& x,
00159 int yIndx,
00160 Array<int32>& y
00161 );
00162
00163 static RefCountPtr<Array<int32> > Square
00164 (
00165 RefCountPtr<Array<int32> > w,
00166 RefCountPtr<Array<int32> > x
00167 );
00168
00169 static BigIntegerPtr ExtEuclid
00170 (
00171 const BigInteger& a,
00172 const BigInteger& b,
00173 BigIntegerPtr u1Out,
00174 BigIntegerPtr u2Out
00175 );
00176
00177
00178 private:
00179 int32 m_sign;
00180 RefCountPtr<Array<int32> > m_magnitude;
00181 int32 m_nBits;
00182 int32 m_nBitLength;
00183 int64 m_mQuote;
00184
00185 inline void ConstructCommon()
00186 {
00187 Init();
00188 m_nBits = -1;
00189 m_nBitLength = -1;
00190 m_mQuote = -1L;
00191 }
00192
00193 inline bool QuickPow2Check() const
00194 {
00195 return m_sign > 0 && m_nBits == 1;
00196 }
00197
00198 BigInteger(int signNum, RefCountPtr<Array<int32> > mag, bool checkMag);
00199
00200 void ConstructWith(int signNum, RefCountPtr<Array<int32> > mag, bool checkMag);
00201 void ConstructWith(Array<byte>& bytes, int offset, int length);
00202 void ConstructWith(int sign, Array<byte>& bytes, int offset, int length);
00203
00204 int64 GetMQuote();
00205 bool CheckProbablePrime(int certainty, Random& random) const;
00206 bool RabinMillerTest(int certainty, Random& random) const;
00207
00208 int CalcBitLength(int indx, const Array<int32>& mag) const;
00209 RefCountPtr<Array<int32> > LastNBits(int n) const;
00210
00211 BigIntegerPtr AddToMagnitude(RefCountPtr<Array<int32> > magToAdd) const;
00212
00213 int32 Remainder(int m) const;
00214 void Remainder(RefCountPtr<Array<int32> > x, RefCountPtr<Array<int32> > y) const;
00215
00216 RefCountPtr<Array<int32> > Divide
00217 (
00218 RefCountPtr<Array<int32> > x,
00219 RefCountPtr<Array<int32> > y
00220 ) const;
00221
00222 BigIntegerPtr Inc() const;
00223 BigIntegerPtr FlipExistingBit(int n) const;
00224
00225 inline BigIntegerPtr AndNot(const BigInteger& val) const
00226 {
00227 BigIntegerPtr tmp = val.Not();
00228 return And(*tmp);
00229 }
00230
00231 void ToByteArray(Array<byte>& a, bool isUnsigned) const;
00232
00233 public:
00234 BigInteger();
00235 BigInteger(Array<byte>& bytes);
00236 BigInteger(Array<byte>& bytes, int offset, int length);
00237 BigInteger(int sign, Array<byte>& bytes, int offset, int length);
00238 BigInteger(int sign, Array<byte>& bytes);
00239 BigInteger(int sizeInBits, Random& random);
00240 BigInteger(int bitLength, int certainty, Random& random);
00241
00242 BigInteger(const BigInteger& toCopy);
00243 BigInteger& operator =(const BigInteger& toAssign);
00244 BigInteger& operator =(const int64 i);
00245 virtual ~BigInteger();
00246
00247 bool TestBit(int n) const;
00248
00249 inline int GetBitLength() const
00250 {
00251 return m_nBitLength;
00252 }
00253
00254 int GetLowestSetBit() const;
00255
00256 inline BigIntegerPtr Abs() const
00257 {
00258 return m_sign >= 0 ? BigIntegerPtr(new BigInteger(*this)) : Negate();
00259 }
00260
00261 inline BigIntegerPtr Not() const
00262 {
00263 return Inc()->Negate();
00264 }
00265
00266 BigIntegerPtr And(const BigInteger& value) const;
00267 BigIntegerPtr Or(const BigInteger& value) const;
00268 BigIntegerPtr Xor(const BigInteger& value) const;
00269 BigIntegerPtr SetBit(int n) const;
00270 BigIntegerPtr ClearBit(int n) const;
00271 BigIntegerPtr FlipBit(int n) const;
00272
00273 inline BigIntegerPtr Negate() const
00274 {
00275 if (m_sign == 0)
00276 return BigIntegerPtr(new BigInteger(*this));
00277
00278 return BigIntegerPtr(new BigInteger(-m_sign, RefCountPtr<Array<int32> >(m_magnitude->Clone()), false));
00279 }
00280
00281 BigIntegerPtr ShiftRight(int n) const;
00282 BigIntegerPtr ShiftLeft(int n) const;
00283
00284 BigIntegerPtr Remainder(const BigInteger& n) const;
00285 BigIntegerPtr ModPow(const BigInteger& exponent, BigInteger& m);
00286 BigIntegerPtr Mod(const BigInteger &m) const;
00287 BigIntegerPtr ModInverse(const BigInteger& m) const;
00288
00289 BigIntegerPtr Multiply(const BigInteger& val) const;
00290
00291 BigIntegerPtr Divide(const BigInteger& val) const;
00292 Array<BigIntegerPtr> DivideAndRemainder(const BigInteger& val) const;
00293
00294 BigIntegerPtr Add(const BigInteger& value) const;
00295 BigIntegerPtr Subtract(const BigInteger& n) const;
00296
00297 BigIntegerPtr Gcd(const BigInteger& value) const;
00298 bool IsProbablePrime(int certainty) const;
00299
00300 inline BigInteger& operator +=(const BigInteger& bi) { *this = *Add(bi); return *this; }
00301 inline BigInteger& operator -=(const BigInteger& bi) { *this = *Subtract(bi); return *this; }
00302 inline BigInteger& operator *=(const BigInteger& bi) { *this = *Multiply(bi); return *this; }
00303 inline BigInteger& operator /=(const BigInteger& bi) { *this = *Divide(bi); return *this; }
00304
00305 inline BigInteger& operator <<=(int shiftVal) { *this = *ShiftLeft(shiftVal); return *this; }
00306 inline BigInteger& operator >>=(int shiftVal) { *this = *ShiftRight(shiftVal); return *this; }
00307
00308 BigInteger& operator %=(const BigInteger& bi) { *this = *Mod(bi); return *this; }
00309 BigInteger& operator &=(const BigInteger& bi) { *this = *And(bi); return *this; }
00310 BigInteger& operator |=(const BigInteger& bi) { *this = *Or(bi); return *this; }
00311 BigInteger& operator ^=(const BigInteger& bi) { *this = *Xor(bi); return *this; }
00312
00313 inline friend BigInteger operator +(const BigInteger& bi1, const BigInteger& bi2) { return *bi1.Add(bi2); }
00314 inline friend BigInteger operator -(const BigInteger& bi1, const BigInteger& bi2) { return *bi1.Subtract(bi2); }
00315 inline friend BigInteger operator *(const BigInteger& bi1, const BigInteger& bi2) { return *bi1.Multiply(bi2); }
00316 inline friend BigInteger operator /(const BigInteger& bi1, const BigInteger& bi2) { return *bi1.Divide(bi2); }
00317 inline friend BigInteger operator %(const BigInteger& bi1, const BigInteger& bi2) { return *bi1.Mod(bi2); }
00318
00319 inline friend BigInteger operator +(const BigInteger& bi1, int64 i) { BigInteger tmp = *ValueOf(i); return *bi1.Add(tmp); }
00320 inline friend BigInteger operator -(const BigInteger& bi1, int64 i) { BigInteger tmp = *ValueOf(i); return *bi1.Subtract(tmp); }
00321 inline friend BigInteger operator *(const BigInteger& bi1, int64 i) { BigInteger tmp = *ValueOf(i); return *bi1.Multiply(tmp); }
00322 inline friend BigInteger operator /(const BigInteger& bi1, int64 i) { BigInteger tmp = *ValueOf(i); return *bi1.Divide(tmp); }
00323 inline friend BigInteger operator %(const BigInteger& bi1, int64 i) { BigInteger tmp = *ValueOf(i); return *bi1.Mod(tmp); }
00324
00325 inline friend BigInteger operator &(const BigInteger& bi1, const BigInteger& bi2) { return *bi1.And(bi2); }
00326 inline friend BigInteger operator |(const BigInteger& bi1, const BigInteger& bi2) { return *bi1.Or(bi2); }
00327 inline friend BigInteger operator ^(const BigInteger& bi1, const BigInteger& bi2) { return *bi1.Xor(bi2); }
00328
00329 inline BigInteger operator <<(int shiftVal) const { return *ShiftLeft(shiftVal); }
00330 inline BigInteger operator >>(int shiftVal) const { return *ShiftRight(shiftVal); }
00331
00332 inline friend BigInteger operator -(const BigInteger& bi) { return *bi.Negate(); }
00333 friend BigInteger operator ~(const BigInteger& bi);
00334 inline friend BigInteger operator !(const BigInteger& bi) { return *bi.Not(); }
00335
00336 inline friend bool operator ==(const BigInteger& bi1, const BigInteger& bi2) { return bi1.Equals(bi2); }
00337 inline friend bool operator ==(const BigInteger& bi1, int64 i) { BigInteger tmp = *ValueOf(i); return bi1 == tmp; }
00338 inline friend bool operator !=(const BigInteger& bi1, const BigInteger& bi2) { return !bi1.Equals(bi2); }
00339 inline friend bool operator !=(const BigInteger& bi1, int64 i) { return bi1 != i; }
00340 inline friend bool operator >(const BigInteger& bi1, const BigInteger& bi2) { return bi1.Compare(bi2) > 0; }
00341 inline friend bool operator <(const BigInteger& bi1, const BigInteger& bi2) { return bi1.Compare(bi2) < 0; }
00342 inline friend bool operator >=(const BigInteger& bi1, const BigInteger& bi2) { return bi1.Compare(bi2) >= 0; }
00343 inline friend bool operator <=(const BigInteger& bi1, const BigInteger& bi2) { return bi1.Compare(bi2) <= 0; }
00344
00345 inline friend bool operator &&(const BigInteger& bi1, const BigInteger& bi2) { BigInteger tmp = *bi1.And(bi2); return tmp != 0; }
00346 inline friend bool operator ||(const BigInteger& bi1, const BigInteger& bi2) { BigInteger tmp = *bi1.Or(bi2); return tmp != 0; }
00347
00348 String ToString() const;
00349
00350 inline Array<byte> ToByteArrayUnsigned() const
00351 {
00352 Array<byte> a;
00353 ToByteArray(a, true);
00354 return a;
00355 }
00356
00357 inline void ToByteArrayUnsigned(Array<byte>& a) const
00358 {
00359 ToByteArray(a, true);
00360 }
00361
00362 inline Array<byte> ToByteArray() const
00363 {
00364 Array<byte> a;
00365 ToByteArray(a, false);
00366 return a;
00367 }
00368
00369 inline void ToByteArray(Array<byte>& a) const
00370 {
00371 ToByteArray(a, false);
00372 }
00373
00374 inline int32 ToInt() const
00375 {
00376 return m_sign == 0 ? 0
00377 : m_sign > 0 ? (*m_magnitude)[m_magnitude->Length() - 1]
00378 : -(*m_magnitude)[m_magnitude->Length() - 1];
00379 }
00380
00381 inline int64 ToInt64() const
00382 {
00383 if( m_sign == 0 )
00384 {
00385 return 0;
00386 }
00387
00388 int64 i = (uint32)(*m_magnitude)[m_magnitude->Length() - 1];
00389 if (m_magnitude->Count() > 1)
00390 {
00391 int64 i2 = (uint32)(*m_magnitude)[m_magnitude->Length() - 2];
00392 i |= i2 << 32;
00393 }
00394
00395 if (m_sign < 0)
00396 {
00397 return -i;
00398 }
00399 return i;
00400 }
00401
00402 inline uint32 ToUInt() const
00403 {
00404 return (*m_magnitude)[m_magnitude->Length() - 1];
00405 }
00406
00407 virtual bool Equals( const IComparable *a ) const;
00408 virtual int Compare( const IComparable *a ) const;
00409 virtual bool Equals( const IComparable& a ) const;
00410 virtual int Compare( const IComparable& a ) const;
00411 bool Equals(int64 i) const;
00412
00415 virtual int32 MajicNumber() const;
00416 virtual int32 HashCode() const;
00417
00418 inline static BigIntegerPtr ValueOf(int64 i) { return CreateValueOf(i); }
00419 static const BigInteger& Zero();
00420 static BigIntegerPtr ZeroPtr();
00421 static const BigInteger& One();
00422 static BigIntegerPtr OnePtr();
00423
00424 #if defined(DEBUG) || defined(_DEBUG)
00425 virtual void CheckMem() const;
00426 virtual void ValidateMem() const;
00427
00428 static void CheckMemStatics();
00429 static void DebugClearStatics();
00430 #endif
00431 };
00432
00433 inline void ValidateType(const BigInteger& b)
00434 {
00435 #ifdef DEBUG
00436 b.ValidateMem();
00437 b.CheckMem();
00438 #endif
00439 }
00440
00441 inline void ValidateType(BigIntegerPtr b)
00442 {
00443 #ifdef DEBUG
00444 b.ValidateMem();
00445 b.CheckMem();
00446 #endif
00447 }
00448
00449 REGISTER_TYPEOF( 554, BigInteger );
00450
00453 #endif