Make randomNumber generate 2^53 values instead of 2^32 (or 2^31 for rand() platforms)
authoroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 2 Jan 2009 20:17:21 +0000 (20:17 +0000)
committeroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 2 Jan 2009 20:17:21 +0000 (20:17 +0000)
Reviewed by Maciej Stachowiak

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@39553 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JavaScriptCore/ChangeLog
JavaScriptCore/wtf/RandomNumber.cpp
JavaScriptCore/wtf/RandomNumberSeed.h

index 219262f..f4471e8 100644 (file)
@@ -1,3 +1,12 @@
+2009-01-02  Oliver Hunt  <oliver@apple.com>
+
+        Reviewed by Maciej Stachowiak.
+
+        Make randomNumber generate 2^53 values instead of 2^32 (or 2^31 for rand() platforms)
+
+        * wtf/RandomNumber.cpp:
+        (WTF::randomNumber):
+
 2009-01-02  David Kilzer  <ddkilzer@apple.com>
 
         Remove declaration for JSC::Identifier::initializeIdentifierThreading()
index b40bb14..e569227 100644 (file)
@@ -45,17 +45,43 @@ double randomNumber()
         s_initialized = true;
     }
 #endif
-
+    
+    uint32_t part1;
+    uint32_t part2;
+    uint64_t fullRandom;
 #if COMPILER(MSVC) && defined(_CRT_RAND_S)
-    unsigned u;
-    rand_s(&u);
-
-    return static_cast<double>(u) / (static_cast<double>(UINT_MAX) + 1.0);
+    rand_s(&part1);
+    rand_s(&part2);
+    fullRandom = part1;
+    fullRandom <<= 32;
+    fullRandom |= part2;
 #elif PLATFORM(DARWIN)
-    return static_cast<double>(arc4random()) / (static_cast<double>(std::numeric_limits<uint32_t>::max()) + 1.0);
+    part1 = arc4random();
+    part2 = arc4random();
+    fullRandom = part1;
+    fullRandom <<= 32;
+    fullRandom |= part2;
+#elif PLATFORM(UNIX)
+    part1 = random() & (RAND_MAX - 1);
+    part2 = random() & (RAND_MAX - 1);
+    // random only provides 31 bits
+    fullRandom = part1;
+    fullRandom <<= 31;
+    fullRandom |= part2;
 #else
-    return static_cast<double>(rand()) / (static_cast<double>(RAND_MAX) + 1.0);
+    part1 = rand() & (RAND_MAX - 1);
+    part2 = rand() & (RAND_MAX - 1);
+    // rand only provides 31 bits, and the low order bits of that aren't very random
+    // so we take the high 26 bits of part 1, and the high 27 bits of part2.
+    part1 >>= 5; // drop the low 5 bits
+    part2 >>= 4; // drop the low 4 bits
+    fullRandom = part1;
+    fullRandom <<= 27;
+    fullRandom |= part2;
 #endif
+    // Mask off the low 53bits
+    fullRandom &= (1LL << 53) - 1;
+    return static_cast<double>(fullRandom)/static_cast<double>(1LL << 53);
 }
 
 }
index c5f9580..5a6f426 100644 (file)
@@ -38,6 +38,11 @@ inline void initializeRandomNumberGenerator()
     // On Darwin we use arc4random which initialises itself.
 #elif COMPILER(MSVC) && defined(_CRT_RAND_S)
     // On Windows we use rand_s which intialises itself
+#elif PLATFORM(UNIX)
+    // srandomdev is not guaranteed to exist on linux so we use this poor seed, this should be improved
+    timeval time;
+    gettimeofday(&time, 0);
+    srandom(static_cast<unsigned>(time.tv_usec * getpid()));
 #else
     srand(static_cast<unsigned>(time(0)));
 #endif