biginteger.h
Go to the documentation of this file.
1 // Tencent is pleased to support the open source community by making RapidJSON
2 // available.
3 //
4 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All
5 // rights reserved.
6 //
7 // Licensed under the MIT License (the "License"); you may not use this file
8 // except in compliance with the License. You may obtain a copy of the License
9 // at
10 //
11 // http://opensource.org/licenses/MIT
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16 // License for the specific language governing permissions and limitations under
17 // the License.
18 
19 #ifndef RAPIDJSON_BIGINTEGER_H_
20 #define RAPIDJSON_BIGINTEGER_H_
21 
22 #include "../rapidjson.h"
23 
24 #if defined(_MSC_VER) && !__INTEL_COMPILER && defined(_M_AMD64)
25 #include <intrin.h> // for _umul128
26 #pragma intrinsic(_umul128)
27 #endif
28 
30 namespace internal {
31 
32 class BigInteger {
33  public:
34  typedef uint64_t Type;
35 
36  BigInteger(const BigInteger &rhs) : count_(rhs.count_) {
37  std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
38  }
39 
40  explicit BigInteger(uint64_t u) : count_(1) { digits_[0] = u; }
41 
42  BigInteger(const char *decimals, size_t length) : count_(1) {
43  RAPIDJSON_ASSERT(length > 0);
44  digits_[0] = 0;
45  size_t i = 0;
46  const size_t kMaxDigitPerIteration =
47  19; // 2^64 = 18446744073709551616 > 10^19
48  while (length >= kMaxDigitPerIteration) {
49  AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration);
50  length -= kMaxDigitPerIteration;
51  i += kMaxDigitPerIteration;
52  }
53 
54  if (length > 0) AppendDecimal64(decimals + i, decimals + i + length);
55  }
56 
58  if (this != &rhs) {
59  count_ = rhs.count_;
60  std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
61  }
62  return *this;
63  }
64 
66  digits_[0] = u;
67  count_ = 1;
68  return *this;
69  }
70 
72  Type backup = digits_[0];
73  digits_[0] += u;
74  for (size_t i = 0; i < count_ - 1; i++) {
75  if (digits_[i] >= backup) return *this; // no carry
76  backup = digits_[i + 1];
77  digits_[i + 1] += 1;
78  }
79 
80  // Last carry
81  if (digits_[count_ - 1] < backup) PushBack(1);
82 
83  return *this;
84  }
85 
87  if (u == 0) return *this = 0;
88  if (u == 1) return *this;
89  if (*this == 1) return *this = u;
90 
91  uint64_t k = 0;
92  for (size_t i = 0; i < count_; i++) {
93  uint64_t hi;
94  digits_[i] = MulAdd64(digits_[i], u, k, &hi);
95  k = hi;
96  }
97 
98  if (k > 0) PushBack(k);
99 
100  return *this;
101  }
102 
104  if (u == 0) return *this = 0;
105  if (u == 1) return *this;
106  if (*this == 1) return *this = u;
107 
108  uint64_t k = 0;
109  for (size_t i = 0; i < count_; i++) {
110  const uint64_t c = digits_[i] >> 32;
111  const uint64_t d = digits_[i] & 0xFFFFFFFF;
112  const uint64_t uc = u * c;
113  const uint64_t ud = u * d;
114  const uint64_t p0 = ud + k;
115  const uint64_t p1 = uc + (p0 >> 32);
116  digits_[i] = (p0 & 0xFFFFFFFF) | (p1 << 32);
117  k = p1 >> 32;
118  }
119 
120  if (k > 0) PushBack(k);
121 
122  return *this;
123  }
124 
125  BigInteger &operator<<=(size_t shift) {
126  if (IsZero() || shift == 0) return *this;
127 
128  size_t offset = shift / kTypeBit;
129  size_t interShift = shift % kTypeBit;
130  RAPIDJSON_ASSERT(count_ + offset <= kCapacity);
131 
132  if (interShift == 0) {
133  std::memmove(digits_ + offset, digits_, count_ * sizeof(Type));
134  count_ += offset;
135  } else {
136  digits_[count_] = 0;
137  for (size_t i = count_; i > 0; i--)
138  digits_[i + offset] = (digits_[i] << interShift) |
139  (digits_[i - 1] >> (kTypeBit - interShift));
140  digits_[offset] = digits_[0] << interShift;
141  count_ += offset;
142  if (digits_[count_]) count_++;
143  }
144 
145  std::memset(digits_, 0, offset * sizeof(Type));
146 
147  return *this;
148  }
149 
150  bool operator==(const BigInteger &rhs) const {
151  return count_ == rhs.count_ &&
152  std::memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0;
153  }
154 
155  bool operator==(const Type rhs) const {
156  return count_ == 1 && digits_[0] == rhs;
157  }
158 
159  BigInteger &MultiplyPow5(unsigned exp) {
160  static const uint32_t kPow5[12] = {
161  5,
162  5 * 5,
163  5 * 5 * 5,
164  5 * 5 * 5 * 5,
165  5 * 5 * 5 * 5 * 5,
166  5 * 5 * 5 * 5 * 5 * 5,
167  5 * 5 * 5 * 5 * 5 * 5 * 5,
168  5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
169  5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
170  5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
171  5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
172  5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5};
173  if (exp == 0) return *this;
174  for (; exp >= 27; exp -= 27)
175  *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27
176  for (; exp >= 13; exp -= 13)
177  *this *= static_cast<uint32_t>(1220703125u); // 5^13
178  if (exp > 0) *this *= kPow5[exp - 1];
179  return *this;
180  }
181 
182  // Compute absolute difference of this and rhs.
183  // Assume this != rhs
184  bool Difference(const BigInteger &rhs, BigInteger *out) const {
185  int cmp = Compare(rhs);
186  RAPIDJSON_ASSERT(cmp != 0);
187  const BigInteger *a, *b; // Makes a > b
188  bool ret;
189  if (cmp < 0) {
190  a = &rhs;
191  b = this;
192  ret = true;
193  } else {
194  a = this;
195  b = &rhs;
196  ret = false;
197  }
198 
199  Type borrow = 0;
200  for (size_t i = 0; i < a->count_; i++) {
201  Type d = a->digits_[i] - borrow;
202  if (i < b->count_) d -= b->digits_[i];
203  borrow = (d > a->digits_[i]) ? 1 : 0;
204  out->digits_[i] = d;
205  if (d != 0) out->count_ = i + 1;
206  }
207 
208  return ret;
209  }
210 
211  int Compare(const BigInteger &rhs) const {
212  if (count_ != rhs.count_) return count_ < rhs.count_ ? -1 : 1;
213 
214  for (size_t i = count_; i-- > 0;)
215  if (digits_[i] != rhs.digits_[i])
216  return digits_[i] < rhs.digits_[i] ? -1 : 1;
217 
218  return 0;
219  }
220 
221  size_t GetCount() const { return count_; }
222  Type GetDigit(size_t index) const {
223  RAPIDJSON_ASSERT(index < count_);
224  return digits_[index];
225  }
226  bool IsZero() const { return count_ == 1 && digits_[0] == 0; }
227 
228  private:
229  void AppendDecimal64(const char *begin, const char *end) {
230  uint64_t u = ParseUint64(begin, end);
231  if (IsZero())
232  *this = u;
233  else {
234  unsigned exp = static_cast<unsigned>(end - begin);
235  (MultiplyPow5(exp) <<= exp) += u; // *this = *this * 10^exp + u
236  }
237  }
238 
239  void PushBack(Type digit) {
241  digits_[count_++] = digit;
242  }
243 
244  static uint64_t ParseUint64(const char *begin, const char *end) {
245  uint64_t r = 0;
246  for (const char *p = begin; p != end; ++p) {
247  RAPIDJSON_ASSERT(*p >= '0' && *p <= '9');
248  r = r * 10u + static_cast<unsigned>(*p - '0');
249  }
250  return r;
251  }
252 
253  // Assume a * b + k < 2^128
255  uint64_t *outHigh) {
256 #if defined(_MSC_VER) && defined(_M_AMD64)
257  uint64_t low = _umul128(a, b, outHigh) + k;
258  if (low < k) (*outHigh)++;
259  return low;
260 #elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && \
261  defined(__x86_64__)
262  __extension__ typedef unsigned __int128 uint128;
263  uint128 p = static_cast<uint128>(a) * static_cast<uint128>(b);
264  p += k;
265  *outHigh = static_cast<uint64_t>(p >> 64);
266  return static_cast<uint64_t>(p);
267 #else
268  const uint64_t a0 = a & 0xFFFFFFFF, a1 = a >> 32, b0 = b & 0xFFFFFFFF,
269  b1 = b >> 32;
270  uint64_t x0 = a0 * b0, x1 = a0 * b1, x2 = a1 * b0, x3 = a1 * b1;
271  x1 += (x0 >> 32); // can't give carry
272  x1 += x2;
273  if (x1 < x2) x3 += (static_cast<uint64_t>(1) << 32);
274  uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF);
275  uint64_t hi = x3 + (x1 >> 32);
276 
277  lo += k;
278  if (lo < k) hi++;
279  *outHigh = hi;
280  return lo;
281 #endif
282  }
283 
284  static const size_t kBitCount = 3328; // 64bit * 54 > 10^1000
285  static const size_t kCapacity = kBitCount / sizeof(Type);
286  static const size_t kTypeBit = sizeof(Type) * 8;
287 
289  size_t count_;
290 };
291 
292 } // namespace internal
294 
295 #endif // RAPIDJSON_BIGINTEGER_H_
static const size_t kCapacity
Definition: biginteger.h:285
d
BigInteger & operator<<=(size_t shift)
Definition: biginteger.h:125
BigInteger & operator+=(uint64_t u)
Definition: biginteger.h:71
bool IsZero() const
Definition: biginteger.h:226
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:433
Type GetDigit(size_t index) const
Definition: biginteger.h:222
#define RAPIDJSON_UINT64_C2(high32, low32)
Construct a 64-bit literal by a pair of 32-bit integer.
Definition: rapidjson.h:306
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition: rapidjson.h:131
void AppendDecimal64(const char *begin, const char *end)
Definition: biginteger.h:229
BigInteger & operator=(uint64_t u)
Definition: biginteger.h:65
BigInteger & operator*=(uint32_t u)
Definition: biginteger.h:103
size_t GetCount() const
Definition: biginteger.h:221
int Compare(const BigInteger &rhs) const
Definition: biginteger.h:211
void PushBack(Type digit)
Definition: biginteger.h:239
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition: rapidjson.h:128
BigInteger(const BigInteger &rhs)
Definition: biginteger.h:36
static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t *outHigh)
Definition: biginteger.h:254
BigInteger(const char *decimals, size_t length)
Definition: biginteger.h:42
unsigned int uint32_t
Definition: stdint.h:127
static uint64_t ParseUint64(const char *begin, const char *end)
Definition: biginteger.h:244
BigInteger(uint64_t u)
Definition: biginteger.h:40
unsigned __int64 uint64_t
Definition: stdint.h:137
BigInteger & operator=(const BigInteger &rhs)
Definition: biginteger.h:57
BigInteger & operator*=(uint64_t u)
Definition: biginteger.h:86
Type digits_[kCapacity]
Definition: biginteger.h:288
bool operator==(const Type rhs) const
Definition: biginteger.h:155
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1365
static const size_t kTypeBit
Definition: biginteger.h:286
bool operator==(const BigInteger &rhs) const
Definition: biginteger.h:150
static const size_t kBitCount
Definition: biginteger.h:284
BigInteger & MultiplyPow5(unsigned exp)
Definition: biginteger.h:159
bool Difference(const BigInteger &rhs, BigInteger *out) const
Definition: biginteger.h:184


livox_ros_driver
Author(s): Livox Dev Team
autogenerated on Mon Mar 15 2021 02:40:45