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