Home | History | Annotate | Download | only in wtf
      1 /*
      2  * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
      3  *           (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  *
     14  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     25  */
     26 
     27 #include "config.h"
     28 #include "RandomNumber.h"
     29 
     30 #include "RandomNumberSeed.h"
     31 
     32 #include <limits>
     33 #include <limits.h>
     34 #include <stdint.h>
     35 #include <stdlib.h>
     36 
     37 #if OS(WINCE)
     38 extern "C" {
     39 #include "wince/mt19937ar.c"
     40 }
     41 #endif
     42 
     43 #if PLATFORM(BREWMP)
     44 #include <AEEAppGen.h>
     45 #include <AEESource.h>
     46 #include <AEEStdLib.h>
     47 #endif
     48 
     49 namespace WTF {
     50 
     51 double weakRandomNumber()
     52 {
     53 #if COMPILER(MSVC) && defined(_CRT_RAND_S)
     54     // rand_s is incredibly slow on windows so we fall back on rand for Math.random
     55     return (rand() + (rand() / (RAND_MAX + 1.0))) / (RAND_MAX + 1.0);
     56 #elif PLATFORM(BREWMP)
     57     uint32_t bits;
     58     GETRAND(reinterpret_cast<byte*>(&bits), sizeof(uint32_t));
     59     return static_cast<double>(bits) / (static_cast<double>(std::numeric_limits<uint32_t>::max()) + 1.0);
     60 #else
     61     return randomNumber();
     62 #endif
     63 }
     64 
     65 double randomNumber()
     66 {
     67 #if !ENABLE(JSC_MULTIPLE_THREADS)
     68     static bool s_initialized = false;
     69     if (!s_initialized) {
     70         initializeRandomNumberGenerator();
     71         s_initialized = true;
     72     }
     73 #endif
     74 
     75 #if COMPILER(MSVC) && defined(_CRT_RAND_S)
     76     uint32_t bits;
     77     rand_s(&bits);
     78     return static_cast<double>(bits) / (static_cast<double>(std::numeric_limits<uint32_t>::max()) + 1.0);
     79 #elif OS(DARWIN)
     80     uint32_t bits = arc4random();
     81     return static_cast<double>(bits) / (static_cast<double>(std::numeric_limits<uint32_t>::max()) + 1.0);
     82 #elif OS(UNIX)
     83     uint32_t part1 = random() & (RAND_MAX - 1);
     84     uint32_t part2 = random() & (RAND_MAX - 1);
     85     // random only provides 31 bits
     86     uint64_t fullRandom = part1;
     87     fullRandom <<= 31;
     88     fullRandom |= part2;
     89 
     90     // Mask off the low 53bits
     91     fullRandom &= (1LL << 53) - 1;
     92     return static_cast<double>(fullRandom)/static_cast<double>(1LL << 53);
     93 #elif OS(WINCE)
     94     return genrand_res53();
     95 #elif OS(WINDOWS)
     96     uint32_t part1 = rand() & (RAND_MAX - 1);
     97     uint32_t part2 = rand() & (RAND_MAX - 1);
     98     uint32_t part3 = rand() & (RAND_MAX - 1);
     99     uint32_t part4 = rand() & (RAND_MAX - 1);
    100     // rand only provides 15 bits on Win32
    101     uint64_t fullRandom = part1;
    102     fullRandom <<= 15;
    103     fullRandom |= part2;
    104     fullRandom <<= 15;
    105     fullRandom |= part3;
    106     fullRandom <<= 15;
    107     fullRandom |= part4;
    108 
    109     // Mask off the low 53bits
    110     fullRandom &= (1LL << 53) - 1;
    111     return static_cast<double>(fullRandom)/static_cast<double>(1LL << 53);
    112 #elif PLATFORM(BREWMP)
    113     uint32_t bits;
    114     ISource* randomSource;
    115 
    116     IShell* shell = reinterpret_cast<AEEApplet*>(GETAPPINSTANCE())->m_pIShell;
    117     ISHELL_CreateInstance(shell, AEECLSID_RANDOM, reinterpret_cast<void**>(&randomSource));
    118     ISOURCE_Read(randomSource, reinterpret_cast<char*>(&bits), 4);
    119     ISOURCE_Release(randomSource);
    120 
    121     return static_cast<double>(bits) / (static_cast<double>(std::numeric_limits<uint32_t>::max()) + 1.0);
    122 #else
    123     uint32_t part1 = rand() & (RAND_MAX - 1);
    124     uint32_t part2 = rand() & (RAND_MAX - 1);
    125     // rand only provides 31 bits, and the low order bits of that aren't very random
    126     // so we take the high 26 bits of part 1, and the high 27 bits of part2.
    127     part1 >>= 5; // drop the low 5 bits
    128     part2 >>= 4; // drop the low 4 bits
    129     uint64_t fullRandom = part1;
    130     fullRandom <<= 27;
    131     fullRandom |= part2;
    132 
    133     // Mask off the low 53bits
    134     fullRandom &= (1LL << 53) - 1;
    135     return static_cast<double>(fullRandom)/static_cast<double>(1LL << 53);
    136 #endif
    137 }
    138 
    139 }
    140