bignum.h revision b8a8cc1952d61a2f3a2568848933943a543b5d3e
1600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// Copyright 2010 the V8 project authors. All rights reserved. 2600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// Use of this source code is governed by a BSD-style license that can be 3600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang// found in the LICENSE file. 4600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 5600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang#ifndef V8_BIGNUM_H_ 6600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang#define V8_BIGNUM_H_ 7600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 8600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangnamespace v8 { 9600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangnamespace internal { 10600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 11600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangclass Bignum { 12600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public: 13600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // 3584 = 128 * 28. We can represent 2^3584 > 10^1000 accurately. 14600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // This bignum can encode much bigger numbers, since it contains an 15600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // exponent. 16600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang static const int kMaxSignificantBits = 3584; 17600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 18600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Bignum(); 19600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang void AssignUInt16(uint16_t value); 20600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang void AssignUInt64(uint64_t value); 21600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang void AssignBignum(const Bignum& other); 22600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 23600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang void AssignDecimalString(Vector<const char> value); 24600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang void AssignHexString(Vector<const char> value); 25600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 26600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang void AssignPowerUInt16(uint16_t base, int exponent); 27600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 28600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang void AddUInt16(uint16_t operand); 29600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang void AddUInt64(uint64_t operand); 30600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang void AddBignum(const Bignum& other); 31600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Precondition: this >= other. 32600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang void SubtractBignum(const Bignum& other); 33600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 34600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang void Square(); 35600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang void ShiftLeft(int shift_amount); 36600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang void MultiplyByUInt32(uint32_t factor); 37600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang void MultiplyByUInt64(uint64_t factor); 38600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang void MultiplyByPowerOfTen(int exponent); 39600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang void Times10() { return MultiplyByUInt32(10); } 40600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Pseudocode: 41600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // int result = this / other; 42600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // this = this % other; 43600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // In the worst case this function is in O(this/other). 44600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang uint16_t DivideModuloIntBignum(const Bignum& other); 45600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 46600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang bool ToHexString(char* buffer, int buffer_size) const; 47600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 48600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang static int Compare(const Bignum& a, const Bignum& b); 49600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang static bool Equal(const Bignum& a, const Bignum& b) { 50600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return Compare(a, b) == 0; 51600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 52600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang static bool LessEqual(const Bignum& a, const Bignum& b) { 53600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return Compare(a, b) <= 0; 54600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 55600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang static bool Less(const Bignum& a, const Bignum& b) { 56600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return Compare(a, b) < 0; 57600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 58600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Returns Compare(a + b, c); 59600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang static int PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c); 60600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Returns a + b == c 61600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang static bool PlusEqual(const Bignum& a, const Bignum& b, const Bignum& c) { 62600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return PlusCompare(a, b, c) == 0; 63600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 64600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Returns a + b <= c 65600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang static bool PlusLessEqual(const Bignum& a, const Bignum& b, const Bignum& c) { 66600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return PlusCompare(a, b, c) <= 0; 67600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 68600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Returns a + b < c 69600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang static bool PlusLess(const Bignum& a, const Bignum& b, const Bignum& c) { 70600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return PlusCompare(a, b, c) < 0; 71600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 72600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 73600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private: 74600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang typedef uint32_t Chunk; 75600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang typedef uint64_t DoubleChunk; 76600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 77600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang static const int kChunkSize = sizeof(Chunk) * 8; 78600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang static const int kDoubleChunkSize = sizeof(DoubleChunk) * 8; 79600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // With bigit size of 28 we loose some bits, but a double still fits easily 80600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // into two chunks, and more importantly we can use the Comba multiplication. 81600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang static const int kBigitSize = 28; 82600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang static const Chunk kBigitMask = (1 << kBigitSize) - 1; 83600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Every instance allocates kBigitLength chunks on the stack. Bignums cannot 84600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // grow. There are no checks if the stack-allocated space is sufficient. 85600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang static const int kBigitCapacity = kMaxSignificantBits / kBigitSize; 86600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 87600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang void EnsureCapacity(int size) { 88600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (size > kBigitCapacity) { 89600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang UNREACHABLE(); 90600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 91600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 92600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang void Align(const Bignum& other); 93600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang void Clamp(); 94600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang bool IsClamped() const; 95600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang void Zero(); 96600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Requires this to have enough capacity (no tests done). 97600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Updates used_digits_ if necessary. 98600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // by must be < kBigitSize. 99600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang void BigitsShiftLeft(int shift_amount); 100600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // BigitLength includes the "hidden" digits encoded in the exponent. 101600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int BigitLength() const { return used_digits_ + exponent_; } 102600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Chunk BigitAt(int index) const; 103600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang void SubtractTimes(const Bignum& other, int factor); 104600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 105600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Chunk bigits_buffer_[kBigitCapacity]; 106600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // A vector backed by bigits_buffer_. This way accesses to the array are 107600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // checked for out-of-bounds errors. 108600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Vector<Chunk> bigits_; 109600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int used_digits_; 110600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // The Bignum's value equals value(bigits_) * 2^(exponent_ * kBigitSize). 111600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int exponent_; 112600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 113600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang DISALLOW_COPY_AND_ASSIGN(Bignum); 114600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang}; 115600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 116600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang} } // namespace v8::internal 117600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 118600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang#endif // V8_BIGNUM_H_ 119600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang