Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(186)

Side by Side Diff: vm/bigint_operations.cc

Issue 9835074: Fix for issue 2233 (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « vm/bigint_operations.h ('k') | vm/object.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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::ComputeChunkLength(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;
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 = ComputeChunkLength(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
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
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 = ComputeChunkLength(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
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
OLDNEW
« no previous file with comments | « vm/bigint_operations.h ('k') | vm/object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698