OLD | NEW |
1 // Copyright 2012 Google Inc. All Rights Reserved. | 1 // Copyright 2012 Google Inc. All Rights Reserved. |
2 | 2 |
3 #include "vm/bigint_operations.h" | 3 #include "vm/bigint_operations.h" |
4 | 4 |
5 #include "platform/utils.h" | 5 #include "platform/utils.h" |
6 | 6 |
7 #include "vm/double_internals.h" | 7 #include "vm/double_internals.h" |
8 #include "vm/exceptions.h" | 8 #include "vm/exceptions.h" |
9 #include "vm/object_store.h" | 9 #include "vm/object_store.h" |
10 #include "vm/zone.h" | 10 #include "vm/zone.h" |
(...skipping 1273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1284 if (bigint.IsNegative()) { | 1284 if (bigint.IsNegative()) { |
1285 return UnsignedSubtract(bigint, one_bigint); | 1285 return UnsignedSubtract(bigint, one_bigint); |
1286 } else { | 1286 } else { |
1287 const Bigint& result = Bigint::Handle(UnsignedAdd(bigint, one_bigint)); | 1287 const Bigint& result = Bigint::Handle(UnsignedAdd(bigint, one_bigint)); |
1288 result.ToggleSign(); | 1288 result.ToggleSign(); |
1289 return result.raw(); | 1289 return result.raw(); |
1290 } | 1290 } |
1291 } | 1291 } |
1292 | 1292 |
1293 | 1293 |
| 1294 int64_t BigintOperations::BitLength(const Bigint& bigint) { |
| 1295 ASSERT(IsClamped(bigint)); |
| 1296 intptr_t length = bigint.Length(); |
| 1297 if (length == 0) return 0; |
| 1298 intptr_t last = length - 1; |
| 1299 |
| 1300 Chunk high_chunk = bigint.GetChunkAt(last); |
| 1301 ASSERT(high_chunk != 0); |
| 1302 int64_t bit_length = |
| 1303 static_cast<int64_t>(kDigitBitSize) * last + CountBits(high_chunk); |
| 1304 |
| 1305 if (bigint.IsNegative()) { |
| 1306 // We are calculating the 2's complement bitlength but we have a sign and |
| 1307 // magnitude representation. The length is the same except when the |
| 1308 // magnitude is an exact power of two, 2^k. In 2's complement format, |
| 1309 // -(2^k) takes one fewer bit than (2^k). |
| 1310 |
| 1311 if ((high_chunk & (high_chunk - 1)) == 0) { // Single bit set? |
| 1312 for (intptr_t i = 0; i < last; i++) { |
| 1313 if (bigint.GetChunkAt(i) != 0) return bit_length; |
| 1314 } |
| 1315 bit_length -= 1; |
| 1316 } |
| 1317 } |
| 1318 return bit_length; |
| 1319 } |
| 1320 |
| 1321 |
1294 int BigintOperations::Compare(const Bigint& a, const Bigint& b) { | 1322 int BigintOperations::Compare(const Bigint& a, const Bigint& b) { |
1295 bool a_is_negative = a.IsNegative(); | 1323 bool a_is_negative = a.IsNegative(); |
1296 bool b_is_negative = b.IsNegative(); | 1324 bool b_is_negative = b.IsNegative(); |
1297 if (a_is_negative != b_is_negative) { | 1325 if (a_is_negative != b_is_negative) { |
1298 return a_is_negative ? -1 : 1; | 1326 return a_is_negative ? -1 : 1; |
1299 } | 1327 } |
1300 | 1328 |
1301 if (a_is_negative) { | 1329 if (a_is_negative) { |
1302 return -UnsignedCompare(a, b); | 1330 return -UnsignedCompare(a, b); |
1303 } | 1331 } |
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1720 int BigintOperations::CountBits(Chunk digit) { | 1748 int BigintOperations::CountBits(Chunk digit) { |
1721 int result = 0; | 1749 int result = 0; |
1722 while (digit != 0) { | 1750 while (digit != 0) { |
1723 digit >>= 1; | 1751 digit >>= 1; |
1724 result++; | 1752 result++; |
1725 } | 1753 } |
1726 return result; | 1754 return result; |
1727 } | 1755 } |
1728 | 1756 |
1729 } // namespace dart | 1757 } // namespace dart |
OLD | NEW |