OLD | NEW |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |