Chromium Code Reviews| 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 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 112 ((str[1] == 'x') || (str[1] == 'X'))) { | 112 ((str[1] == 'x') || (str[1] == 'X'))) { |
| 113 const Bigint& result = Bigint::Handle(FromHexCString(&str[2], space)); | 113 const Bigint& result = Bigint::Handle(FromHexCString(&str[2], space)); |
| 114 ASSERT(IsClamped(result)); | 114 ASSERT(IsClamped(result)); |
| 115 return result.raw(); | 115 return result.raw(); |
| 116 } else { | 116 } else { |
| 117 return FromDecimalCString(str); | 117 return FromDecimalCString(str); |
| 118 } | 118 } |
| 119 } | 119 } |
| 120 | 120 |
| 121 | 121 |
| 122 intptr_t BigintOperations::ComputeLength(const char* hex_string) { | |
| 123 ASSERT(kDigitBitSize % 4 == 0); | |
| 124 intptr_t hex_length = strlen(hex_string); | |
| 125 // Round up. | |
| 126 intptr_t bigint_length = ((hex_length - 1) / kHexCharsPerDigit) + 1; | |
|
cshapiro
2012/03/24 01:48:07
Utils::RoundUp ?
siva
2012/03/24 02:25:03
The current Roundup implementation doesn't quite w
| |
| 127 return bigint_length; | |
| 128 } | |
| 129 | |
| 130 | |
| 122 RawBigint* BigintOperations::FromHexCString(const char* hex_string, | 131 RawBigint* BigintOperations::FromHexCString(const char* hex_string, |
| 123 Heap::Space space) { | 132 Heap::Space space) { |
| 124 // If the string starts with '-' recursively restart the whole operation | 133 // If the string starts with '-' recursively restart the whole operation |
| 125 // without the character and then toggle the sign. | 134 // without the character and then toggle the sign. |
| 126 // This allows multiple leading '-' (which will cancel each other out), but | 135 // This allows multiple leading '-' (which will cancel each other out), but |
| 127 // we have added an assert, to make sure that the returned result of the | 136 // we have added an assert, to make sure that the returned result of the |
| 128 // recursive call is not negative. | 137 // recursive call is not negative. |
| 129 // We don't catch leading '-'s for zero. Ex: "--0", or "---". | 138 // We don't catch leading '-'s for zero. Ex: "--0", or "---". |
| 130 if (hex_string[0] == '-') { | 139 if (hex_string[0] == '-') { |
| 131 const Bigint& value = Bigint::Handle(FromHexCString(&hex_string[1], space)); | 140 const Bigint& value = Bigint::Handle(FromHexCString(&hex_string[1], space)); |
| 132 value.ToggleSign(); | 141 value.ToggleSign(); |
| 133 ASSERT(value.IsZero() || value.IsNegative()); | 142 ASSERT(value.IsZero() || value.IsNegative()); |
| 134 ASSERT(IsClamped(value)); | 143 ASSERT(IsClamped(value)); |
| 135 return value.raw(); | 144 return value.raw(); |
| 136 } | 145 } |
| 137 | 146 intptr_t bigint_length = ComputeLength(hex_string); |
| 138 ASSERT(kDigitBitSize % 4 == 0); | 147 const Bigint& result = Bigint::Handle(Bigint::Allocate(bigint_length, space)); |
| 139 const int kHexCharsPerDigit = kDigitBitSize / 4; | 148 FromHexCString(hex_string, result); |
| 140 | |
| 141 intptr_t hex_length = strlen(hex_string); | |
| 142 // Round up. | |
| 143 intptr_t bigint_length = ((hex_length - 1) / kHexCharsPerDigit) + 1; | |
| 144 const Bigint& result = | |
| 145 Bigint::Handle(Bigint::Allocate(bigint_length, space)); | |
| 146 // The bigint's least significant digit (lsd) is at position 0, whereas the | |
| 147 // given string has it's lsd at the last position. | |
| 148 // The hex_i index, pointing into the string, starts therefore at the end, | |
| 149 // whereas the bigint-index (i) starts at 0. | |
| 150 intptr_t hex_i = hex_length - 1; | |
| 151 for (intptr_t i = 0; i < bigint_length; i++) { | |
| 152 Chunk digit = 0; | |
| 153 int shift = 0; | |
| 154 for (int j = 0; j < kHexCharsPerDigit; j++) { | |
| 155 // Reads a block of hexadecimal digits and stores it in 'digit'. | |
| 156 // Ex: "0123456" with kHexCharsPerDigit == 3, hex_i == 6, reads "456". | |
| 157 if (hex_i < 0) { | |
| 158 break; | |
| 159 } | |
| 160 ASSERT(hex_i >= 0); | |
| 161 char c = hex_string[hex_i--]; | |
| 162 ASSERT(Utils::IsHexDigit(c)); | |
| 163 digit += static_cast<Chunk>(Utils::HexDigitToInt(c)) << shift; | |
| 164 shift += 4; | |
| 165 } | |
| 166 result.SetChunkAt(i, digit); | |
| 167 } | |
| 168 ASSERT(hex_i == -1); | |
| 169 Clamp(result); | |
| 170 return result.raw(); | 149 return result.raw(); |
| 171 } | 150 } |
| 172 | 151 |
| 173 | 152 |
| 174 RawBigint* BigintOperations::FromDecimalCString(const char* str, | 153 RawBigint* BigintOperations::FromDecimalCString(const char* str, |
| 175 Heap::Space space) { | 154 Heap::Space space) { |
| 176 // Read 8 digits a time. 10^8 < 2^27. | 155 // Read 8 digits a time. 10^8 < 2^27. |
| 177 const int kDigitsPerIteration = 8; | 156 const int kDigitsPerIteration = 8; |
| 178 const Chunk kTenMultiplier = 100000000; | 157 const Chunk kTenMultiplier = 100000000; |
| 179 ASSERT(kDigitBitSize >= 27); | 158 ASSERT(kDigitBitSize >= 27); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 255 } | 234 } |
| 256 | 235 |
| 257 | 236 |
| 258 const char* BigintOperations::ToHexCString(intptr_t length, | 237 const char* BigintOperations::ToHexCString(intptr_t length, |
| 259 bool is_negative, | 238 bool is_negative, |
| 260 void* data, | 239 void* data, |
| 261 uword (*allocator)(intptr_t size)) { | 240 uword (*allocator)(intptr_t size)) { |
| 262 NoGCScope no_gc; | 241 NoGCScope no_gc; |
| 263 | 242 |
| 264 ASSERT(kDigitBitSize % 4 == 0); | 243 ASSERT(kDigitBitSize % 4 == 0); |
| 265 const int kHexCharsPerDigit = kDigitBitSize / 4; | |
| 266 | 244 |
| 267 intptr_t chunk_length = length; | 245 intptr_t chunk_length = length; |
| 268 Chunk* chunk_data = reinterpret_cast<Chunk*>(data); | 246 Chunk* chunk_data = reinterpret_cast<Chunk*>(data); |
| 269 if (length == 0) { | 247 if (length == 0) { |
| 270 const char* zero = "0x0"; | 248 const char* zero = "0x0"; |
| 271 const int kLength = strlen(zero); | 249 const int kLength = strlen(zero); |
| 272 char* result = reinterpret_cast<char*>(allocator(kLength + 1)); | 250 char* result = reinterpret_cast<char*>(allocator(kLength + 1)); |
| 273 ASSERT(result != NULL); | 251 ASSERT(result != NULL); |
| 274 memmove(result, zero, kLength); | 252 memmove(result, zero, kLength); |
| 275 result[kLength] = '\0'; | 253 result[kLength] = '\0'; |
| (...skipping 858 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1134 return a_is_negative ? -1 : 1; | 1112 return a_is_negative ? -1 : 1; |
| 1135 } | 1113 } |
| 1136 | 1114 |
| 1137 if (a_is_negative) { | 1115 if (a_is_negative) { |
| 1138 return -UnsignedCompare(a, b); | 1116 return -UnsignedCompare(a, b); |
| 1139 } | 1117 } |
| 1140 return UnsignedCompare(a, b); | 1118 return UnsignedCompare(a, b); |
| 1141 } | 1119 } |
| 1142 | 1120 |
| 1143 | 1121 |
| 1122 void BigintOperations::FromHexCString(const char* hex_string, | |
| 1123 const Bigint& value) { | |
| 1124 ASSERT(hex_string[0] != '-'); | |
| 1125 intptr_t bigint_length = ComputeLength(hex_string); | |
| 1126 // The bigint's least significant digit (lsd) is at position 0, whereas the | |
| 1127 // given string has it's lsd at the last position. | |
| 1128 // The hex_i index, pointing into the string, starts therefore at the end, | |
| 1129 // whereas the bigint-index (i) starts at 0. | |
| 1130 intptr_t hex_length = strlen(hex_string); | |
| 1131 intptr_t hex_i = hex_length - 1; | |
| 1132 for (intptr_t i = 0; i < bigint_length; i++) { | |
| 1133 Chunk digit = 0; | |
| 1134 int shift = 0; | |
| 1135 for (int j = 0; j < kHexCharsPerDigit; j++) { | |
| 1136 // Reads a block of hexadecimal digits and stores it in 'digit'. | |
| 1137 // Ex: "0123456" with kHexCharsPerDigit == 3, hex_i == 6, reads "456". | |
| 1138 if (hex_i < 0) { | |
| 1139 break; | |
| 1140 } | |
| 1141 ASSERT(hex_i >= 0); | |
| 1142 char c = hex_string[hex_i--]; | |
| 1143 ASSERT(Utils::IsHexDigit(c)); | |
| 1144 digit += static_cast<Chunk>(Utils::HexDigitToInt(c)) << shift; | |
| 1145 shift += 4; | |
| 1146 } | |
| 1147 value.SetChunkAt(i, digit); | |
| 1148 } | |
| 1149 ASSERT(hex_i == -1); | |
| 1150 Clamp(value); | |
| 1151 } | |
| 1152 | |
| 1153 | |
| 1144 RawBigint* BigintOperations::AddSubtract(const Bigint& a, | 1154 RawBigint* BigintOperations::AddSubtract(const Bigint& a, |
| 1145 const Bigint& b, | 1155 const Bigint& b, |
| 1146 bool negate_b) { | 1156 bool negate_b) { |
| 1147 ASSERT(IsClamped(a)); | 1157 ASSERT(IsClamped(a)); |
| 1148 ASSERT(IsClamped(b)); | 1158 ASSERT(IsClamped(b)); |
| 1149 Bigint& result = Bigint::Handle(); | 1159 Bigint& result = Bigint::Handle(); |
| 1150 // We perform the subtraction by simulating a negation of the b-argument. | 1160 // We perform the subtraction by simulating a negation of the b-argument. |
| 1151 bool b_is_negative = negate_b ? !b.IsNegative() : b.IsNegative(); | 1161 bool b_is_negative = negate_b ? !b.IsNegative() : b.IsNegative(); |
| 1152 | 1162 |
| 1153 // If both are of the same sign, then we can compute the unsigned addition | 1163 // If both are of the same sign, then we can compute the unsigned addition |
| (...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1507 int BigintOperations::CountBits(Chunk digit) { | 1517 int BigintOperations::CountBits(Chunk digit) { |
| 1508 int result = 0; | 1518 int result = 0; |
| 1509 while (digit != 0) { | 1519 while (digit != 0) { |
| 1510 digit >>= 1; | 1520 digit >>= 1; |
| 1511 result++; | 1521 result++; |
| 1512 } | 1522 } |
| 1513 return result; | 1523 return result; |
| 1514 } | 1524 } |
| 1515 | 1525 |
| 1516 } // namespace dart | 1526 } // namespace dart |
| OLD | NEW |