michael@0: // Copyright 2010 the V8 project authors. All rights reserved. michael@0: // Redistribution and use in source and binary forms, with or without michael@0: // modification, are permitted provided that the following conditions are michael@0: // met: michael@0: // michael@0: // * Redistributions of source code must retain the above copyright michael@0: // notice, this list of conditions and the following disclaimer. michael@0: // * Redistributions in binary form must reproduce the above michael@0: // copyright notice, this list of conditions and the following michael@0: // disclaimer in the documentation and/or other materials provided michael@0: // with the distribution. michael@0: // * Neither the name of Google Inc. nor the names of its michael@0: // contributors may be used to endorse or promote products derived michael@0: // from this software without specific prior written permission. michael@0: // michael@0: // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS michael@0: // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT michael@0: // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR michael@0: // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT michael@0: // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, michael@0: // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT michael@0: // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, michael@0: // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY michael@0: // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT michael@0: // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE michael@0: // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. michael@0: michael@0: #ifndef DOUBLE_CONVERSION_BIGNUM_H_ michael@0: #define DOUBLE_CONVERSION_BIGNUM_H_ michael@0: michael@0: #include "utils.h" michael@0: michael@0: namespace double_conversion { michael@0: michael@0: class Bignum { michael@0: public: michael@0: // 3584 = 128 * 28. We can represent 2^3584 > 10^1000 accurately. michael@0: // This bignum can encode much bigger numbers, since it contains an michael@0: // exponent. michael@0: static const int kMaxSignificantBits = 3584; michael@0: michael@0: Bignum(); michael@0: void AssignUInt16(uint16_t value); michael@0: void AssignUInt64(uint64_t value); michael@0: void AssignBignum(const Bignum& other); michael@0: michael@0: void AssignDecimalString(Vector value); michael@0: void AssignHexString(Vector value); michael@0: michael@0: void AssignPowerUInt16(uint16_t base, int exponent); michael@0: michael@0: void AddUInt16(uint16_t operand); michael@0: void AddUInt64(uint64_t operand); michael@0: void AddBignum(const Bignum& other); michael@0: // Precondition: this >= other. michael@0: void SubtractBignum(const Bignum& other); michael@0: michael@0: void Square(); michael@0: void ShiftLeft(int shift_amount); michael@0: void MultiplyByUInt32(uint32_t factor); michael@0: void MultiplyByUInt64(uint64_t factor); michael@0: void MultiplyByPowerOfTen(int exponent); michael@0: void Times10() { return MultiplyByUInt32(10); } michael@0: // Pseudocode: michael@0: // int result = this / other; michael@0: // this = this % other; michael@0: // In the worst case this function is in O(this/other). michael@0: uint16_t DivideModuloIntBignum(const Bignum& other); michael@0: michael@0: bool ToHexString(char* buffer, int buffer_size) const; michael@0: michael@0: // Returns michael@0: // -1 if a < b, michael@0: // 0 if a == b, and michael@0: // +1 if a > b. michael@0: static int Compare(const Bignum& a, const Bignum& b); michael@0: static bool Equal(const Bignum& a, const Bignum& b) { michael@0: return Compare(a, b) == 0; michael@0: } michael@0: static bool LessEqual(const Bignum& a, const Bignum& b) { michael@0: return Compare(a, b) <= 0; michael@0: } michael@0: static bool Less(const Bignum& a, const Bignum& b) { michael@0: return Compare(a, b) < 0; michael@0: } michael@0: // Returns Compare(a + b, c); michael@0: static int PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c); michael@0: // Returns a + b == c michael@0: static bool PlusEqual(const Bignum& a, const Bignum& b, const Bignum& c) { michael@0: return PlusCompare(a, b, c) == 0; michael@0: } michael@0: // Returns a + b <= c michael@0: static bool PlusLessEqual(const Bignum& a, const Bignum& b, const Bignum& c) { michael@0: return PlusCompare(a, b, c) <= 0; michael@0: } michael@0: // Returns a + b < c michael@0: static bool PlusLess(const Bignum& a, const Bignum& b, const Bignum& c) { michael@0: return PlusCompare(a, b, c) < 0; michael@0: } michael@0: private: michael@0: typedef uint32_t Chunk; michael@0: typedef uint64_t DoubleChunk; michael@0: michael@0: static const int kChunkSize = sizeof(Chunk) * 8; michael@0: static const int kDoubleChunkSize = sizeof(DoubleChunk) * 8; michael@0: // With bigit size of 28 we loose some bits, but a double still fits easily michael@0: // into two chunks, and more importantly we can use the Comba multiplication. michael@0: static const int kBigitSize = 28; michael@0: static const Chunk kBigitMask = (1 << kBigitSize) - 1; michael@0: // Every instance allocates kBigitLength chunks on the stack. Bignums cannot michael@0: // grow. There are no checks if the stack-allocated space is sufficient. michael@0: static const int kBigitCapacity = kMaxSignificantBits / kBigitSize; michael@0: michael@0: void EnsureCapacity(int size) { michael@0: if (size > kBigitCapacity) { michael@0: UNREACHABLE(); michael@0: } michael@0: } michael@0: void Align(const Bignum& other); michael@0: void Clamp(); michael@0: bool IsClamped() const; michael@0: void Zero(); michael@0: // Requires this to have enough capacity (no tests done). michael@0: // Updates used_digits_ if necessary. michael@0: // shift_amount must be < kBigitSize. michael@0: void BigitsShiftLeft(int shift_amount); michael@0: // BigitLength includes the "hidden" digits encoded in the exponent. michael@0: int BigitLength() const { return used_digits_ + exponent_; } michael@0: Chunk BigitAt(int index) const; michael@0: void SubtractTimes(const Bignum& other, int factor); michael@0: michael@0: Chunk bigits_buffer_[kBigitCapacity]; michael@0: // A vector backed by bigits_buffer_. This way accesses to the array are michael@0: // checked for out-of-bounds errors. michael@0: Vector bigits_; michael@0: int used_digits_; michael@0: // The Bignum's value equals value(bigits_) * 2^(exponent_ * kBigitSize). michael@0: int exponent_; michael@0: michael@0: DISALLOW_COPY_AND_ASSIGN(Bignum); michael@0: }; michael@0: michael@0: } // namespace double_conversion michael@0: michael@0: #endif // DOUBLE_CONVERSION_BIGNUM_H_