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

Side by Side Diff: test/cctest/test-strtod.cc

Issue 4060001: Bignum implementation of Strtod. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: bignum.h changes that somehow disappeared earlier. Created 10 years, 1 month 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 | « test/cctest/test-bignum.cc ('k') | tools/gyp/v8.gyp » ('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 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 2
3 #include <stdlib.h> 3 #include <stdlib.h>
4 4
5 #include "v8.h" 5 #include "v8.h"
6 6
7 #include "bignum.h"
7 #include "cctest.h" 8 #include "cctest.h"
9 #include "diy-fp.h"
10 #include "double.h"
8 #include "strtod.h" 11 #include "strtod.h"
9 12
10 using namespace v8::internal; 13 using namespace v8::internal;
11 14
12 static Vector<const char> StringToVector(const char* str) { 15 static Vector<const char> StringToVector(const char* str) {
13 return Vector<const char>(str, StrLength(str)); 16 return Vector<const char>(str, StrLength(str));
14 } 17 }
15 18
16 19
17 static double StrtodChar(const char* str, int exponent) { 20 static double StrtodChar(const char* str, int exponent) {
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 CHECK_EQ(V8_INFINITY, StrtodChar("00000001000000", 303)); 198 CHECK_EQ(V8_INFINITY, StrtodChar("00000001000000", 303));
196 CHECK_EQ(1e308, StrtodChar("000000000000100000", 303)); 199 CHECK_EQ(1e308, StrtodChar("000000000000100000", 303));
197 CHECK_EQ(1234e305, StrtodChar("00000000123400000", 300)); 200 CHECK_EQ(1234e305, StrtodChar("00000000123400000", 300));
198 CHECK_EQ(1234e304, StrtodChar("0000000123400000", 299)); 201 CHECK_EQ(1234e304, StrtodChar("0000000123400000", 299));
199 CHECK_EQ(V8_INFINITY, StrtodChar("00000000180000000", 300)); 202 CHECK_EQ(V8_INFINITY, StrtodChar("00000000180000000", 300));
200 CHECK_EQ(17e307, StrtodChar("00000000170000000", 300)); 203 CHECK_EQ(17e307, StrtodChar("00000000170000000", 300));
201 CHECK_EQ(1.7976931348623157E+308, StrtodChar("17976931348623157", 292)); 204 CHECK_EQ(1.7976931348623157E+308, StrtodChar("17976931348623157", 292));
202 CHECK_EQ(1.7976931348623158E+308, StrtodChar("17976931348623158", 292)); 205 CHECK_EQ(1.7976931348623158E+308, StrtodChar("17976931348623158", 292));
203 CHECK_EQ(V8_INFINITY, StrtodChar("17976931348623159", 292)); 206 CHECK_EQ(V8_INFINITY, StrtodChar("17976931348623159", 292));
204 207
205 // The following number is the result of 89255.0/1e-22. Both floating-point 208 // The following number is the result of 89255.0/1e22. Both floating-point
206 // numbers can be accurately represented with doubles. However on Linux,x86 209 // numbers can be accurately represented with doubles. However on Linux,x86
207 // the floating-point stack is set to 80bits and the double-rounding 210 // the floating-point stack is set to 80bits and the double-rounding
208 // introduces an error. 211 // introduces an error.
209 CHECK_EQ(89255e-22, StrtodChar("89255", -22)); 212 CHECK_EQ(89255e-22, StrtodChar("89255", -22));
213
214 // Some random values.
215 CHECK_EQ(358416272e-33, StrtodChar("358416272", -33));
210 CHECK_EQ(104110013277974872254e-225, 216 CHECK_EQ(104110013277974872254e-225,
211 StrtodChar("104110013277974872254", -225)); 217 StrtodChar("104110013277974872254", -225));
212 218
213 CHECK_EQ(123456789e108, StrtodChar("123456789", 108)); 219 CHECK_EQ(123456789e108, StrtodChar("123456789", 108));
214 CHECK_EQ(123456789e109, StrtodChar("123456789", 109)); 220 CHECK_EQ(123456789e109, StrtodChar("123456789", 109));
215 CHECK_EQ(123456789e110, StrtodChar("123456789", 110)); 221 CHECK_EQ(123456789e110, StrtodChar("123456789", 110));
216 CHECK_EQ(123456789e111, StrtodChar("123456789", 111)); 222 CHECK_EQ(123456789e111, StrtodChar("123456789", 111));
217 CHECK_EQ(123456789e112, StrtodChar("123456789", 112)); 223 CHECK_EQ(123456789e112, StrtodChar("123456789", 112));
218 CHECK_EQ(123456789e113, StrtodChar("123456789", 113)); 224 CHECK_EQ(123456789e113, StrtodChar("123456789", 113));
219 CHECK_EQ(123456789e114, StrtodChar("123456789", 114)); 225 CHECK_EQ(123456789e114, StrtodChar("123456789", 114));
(...skipping 25 matching lines...) Expand all
245 CHECK_EQ(1234567890123456789052345e111, 251 CHECK_EQ(1234567890123456789052345e111,
246 StrtodChar("1234567890123456789052345", 111)); 252 StrtodChar("1234567890123456789052345", 111));
247 CHECK_EQ(1234567890123456789052345e112, 253 CHECK_EQ(1234567890123456789052345e112,
248 StrtodChar("1234567890123456789052345", 112)); 254 StrtodChar("1234567890123456789052345", 112));
249 CHECK_EQ(1234567890123456789052345e113, 255 CHECK_EQ(1234567890123456789052345e113,
250 StrtodChar("1234567890123456789052345", 113)); 256 StrtodChar("1234567890123456789052345", 113));
251 CHECK_EQ(1234567890123456789052345e114, 257 CHECK_EQ(1234567890123456789052345e114,
252 StrtodChar("1234567890123456789052345", 114)); 258 StrtodChar("1234567890123456789052345", 114));
253 CHECK_EQ(1234567890123456789052345e115, 259 CHECK_EQ(1234567890123456789052345e115,
254 StrtodChar("1234567890123456789052345", 115)); 260 StrtodChar("1234567890123456789052345", 115));
261
262 // Boundary cases.
263 // 0x1FFFFFFFFFFFF * 2^3 = 72057594037927928
264 // next: 72057594037927936
265 // boundary: 72057594037927932
266 CHECK_EQ(72057594037927928.0, StrtodChar("72057594037927928", 0));
267 CHECK_EQ(72057594037927936.0, StrtodChar("72057594037927936", 0));
268 CHECK_EQ(72057594037927936.0, StrtodChar("72057594037927932", 0));
269 CHECK_EQ(72057594037927928.0, StrtodChar("7205759403792793199999", -5));
270 CHECK_EQ(72057594037927936.0, StrtodChar("7205759403792793200001", -5));
271
272 // 0x1FFFFFFFFFFFF * 2^10 = 9223372036854774784
273 // next: 9223372036854775808
274 // boundary: 9223372036854775296
275 CHECK_EQ(9223372036854774784.0, StrtodChar("9223372036854774784", 0));
276 CHECK_EQ(9223372036854775808.0, StrtodChar("9223372036854775808", 0));
277 CHECK_EQ(9223372036854775296.0, StrtodChar("9223372036854775296", 0));
278 CHECK_EQ(9223372036854774784.0, StrtodChar("922337203685477529599999", -5));
279 CHECK_EQ(9223372036854775808.0, StrtodChar("922337203685477529600001", -5));
280
281 // 0x1FFFFFFFFFFFF * 2^50 = 10141204801825834086073718800384
282 // next: 10141204801825835211973625643008
283 // boundary: 10141204801825834649023672221696
284 CHECK_EQ(10141204801825834086073718800384.0,
285 StrtodChar("10141204801825834086073718800384", 0));
286 CHECK_EQ(10141204801825835211973625643008.0,
287 StrtodChar("10141204801825835211973625643008", 0));
288 CHECK_EQ(10141204801825834649023672221696.0,
289 StrtodChar("10141204801825834649023672221696", 0));
290 CHECK_EQ(10141204801825834086073718800384.0,
291 StrtodChar("1014120480182583464902367222169599999", -5));
292 CHECK_EQ(10141204801825835211973625643008.0,
293 StrtodChar("1014120480182583464902367222169600001", -5));
294
295 // 0x1FFFFFFFFFFFF * 2^99 = 5708990770823838890407843763683279797179383808
296 // next: 5708990770823839524233143877797980545530986496
297 // boundary: 5708990770823839207320493820740630171355185152
298 CHECK_EQ(5708990770823838890407843763683279797179383808.0,
299 StrtodChar("5708990770823838890407843763683279797179383808", 0));
300 CHECK_EQ(5708990770823839524233143877797980545530986496.0,
301 StrtodChar("5708990770823839524233143877797980545530986496", 0));
302 CHECK_EQ(5708990770823839207320493820740630171355185152.0,
303 StrtodChar("5708990770823839207320493820740630171355185152", 0));
304 CHECK_EQ(5708990770823838890407843763683279797179383808.0,
305 StrtodChar("5708990770823839207320493820740630171355185151999", -3));
306 CHECK_EQ(5708990770823839524233143877797980545530986496.0,
307 StrtodChar("5708990770823839207320493820740630171355185152001", -3));
255 } 308 }
309
310
311 static int CompareBignumToDiyFp(const Bignum& bignum_digits,
312 int bignum_exponent,
313 DiyFp diy_fp) {
314 Bignum bignum;
315 bignum.AssignBignum(bignum_digits);
316 Bignum other;
317 other.AssignUInt64(diy_fp.f());
318 if (bignum_exponent >= 0) {
319 bignum.MultiplyByPowerOfTen(bignum_exponent);
320 } else {
321 other.MultiplyByPowerOfTen(-bignum_exponent);
322 }
323 if (diy_fp.e() >= 0) {
324 other.ShiftLeft(diy_fp.e());
325 } else {
326 bignum.ShiftLeft(-diy_fp.e());
327 }
328 return Bignum::Compare(bignum, other);
329 }
330
331
332 static bool CheckDouble(Vector<const char> buffer,
333 int exponent,
334 double to_check) {
335 DiyFp lower_boundary;
336 DiyFp upper_boundary;
337 Bignum input_digits;
338 input_digits.AssignDecimalString(buffer);
339 if (to_check == 0.0) {
340 const double kMinDouble = 4e-324;
341 // Check that the buffer*10^exponent < (0 + kMinDouble)/2.
342 Double d(kMinDouble);
343 d.NormalizedBoundaries(&lower_boundary, &upper_boundary);
344 return CompareBignumToDiyFp(input_digits, exponent, lower_boundary) <= 0;
345 }
346 if (to_check == V8_INFINITY) {
347 const double kMaxDouble = 1.7976931348623157e308;
348 // Check that the buffer*10^exponent >= boundary between kMaxDouble and inf.
349 Double d(kMaxDouble);
350 d.NormalizedBoundaries(&lower_boundary, &upper_boundary);
351 return CompareBignumToDiyFp(input_digits, exponent, upper_boundary) >= 0;
352 }
353 Double d(to_check);
354 d.NormalizedBoundaries(&lower_boundary, &upper_boundary);
355 if ((d.Significand() & 1) == 0) {
356 return CompareBignumToDiyFp(input_digits, exponent, lower_boundary) >= 0 &&
357 CompareBignumToDiyFp(input_digits, exponent, upper_boundary) <= 0;
358 } else {
359 return CompareBignumToDiyFp(input_digits, exponent, lower_boundary) > 0 &&
360 CompareBignumToDiyFp(input_digits, exponent, upper_boundary) < 0;
361 }
362 }
363
364
365 // Copied from v8.cc and adapted to make the function deterministic.
366 static uint32_t DeterministicRandom() {
367 // Random number generator using George Marsaglia's MWC algorithm.
368 static uint32_t hi = 0;
369 static uint32_t lo = 0;
370
371 // Initialization values don't have any special meaning. (They are the result
372 // of two calls to random().)
373 if (hi == 0) hi = 0xbfe166e7;
374 if (lo == 0) lo = 0x64d1c3c9;
375
376 // Mix the bits.
377 hi = 36969 * (hi & 0xFFFF) + (hi >> 16);
378 lo = 18273 * (lo & 0xFFFF) + (lo >> 16);
379 return (hi << 16) + (lo & 0xFFFF);
380 }
381
382
383 static const int kBufferSize = 1024;
384 static const int kShortStrtodRandomCount = 2;
385 static const int kLargeStrtodRandomCount = 2;
386
387 TEST(RandomStrtod) {
388 char buffer[kBufferSize];
389 for (int length = 1; length < 15; length++) {
390 for (int i = 0; i < kShortStrtodRandomCount; ++i) {
391 int pos = 0;
392 for (int j = 0; j < length; ++j) {
393 buffer[pos++] = random() % 10 + '0';
394 }
395 int exponent = DeterministicRandom() % (25*2 + 1) - 25 - length;
396 buffer[pos] = '\0';
397 Vector<const char> vector(buffer, pos);
398 double strtod_result = Strtod(vector, exponent);
399 CHECK(CheckDouble(vector, exponent, strtod_result));
400 }
401 }
402 for (int length = 15; length < 800; length += 2) {
403 for (int i = 0; i < kLargeStrtodRandomCount; ++i) {
404 int pos = 0;
405 for (int j = 0; j < length; ++j) {
406 buffer[pos++] = random() % 10 + '0';
407 }
408 int exponent = DeterministicRandom() % (308*2 + 1) - 308 - length;
409 buffer[pos] = '\0';
410 Vector<const char> vector(buffer, pos);
411 double strtod_result = Strtod(vector, exponent);
412 CHECK(CheckDouble(vector, exponent, strtod_result));
413 }
414 }
415 }
OLDNEW
« no previous file with comments | « test/cctest/test-bignum.cc ('k') | tools/gyp/v8.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698