@@ -504,6 +504,7 @@ public: | |||
{ | |||
const int numSamples = 2048; | |||
int32 original [numSamples], converted [numSamples], reversed [numSamples]; | |||
Random r; | |||
{ | |||
AudioData::Pointer<F1, E1, AudioData::NonInterleaved, AudioData::NonConst> d (original); | |||
@@ -511,13 +512,13 @@ public: | |||
for (int i = 0; i < numSamples / 2; ++i) | |||
{ | |||
d.setAsFloat (Random::getSystemRandom().nextFloat() * 2.2f - 1.1f); | |||
d.setAsFloat (r.nextFloat() * 2.2f - 1.1f); | |||
if (! d.isFloatingPoint()) | |||
clippingFailed = d.getAsFloat() > 1.0f || d.getAsFloat() < -1.0f || clippingFailed; | |||
++d; | |||
d.setAsInt32 (Random::getSystemRandom().nextInt()); | |||
d.setAsInt32 (r.nextInt()); | |||
++d; | |||
} | |||
@@ -165,10 +165,11 @@ public: | |||
void run() | |||
{ | |||
int n = 0; | |||
Random r; | |||
while (! threadShouldExit()) | |||
{ | |||
int num = Random::getSystemRandom().nextInt (2000) + 1; | |||
int num = r.nextInt (2000) + 1; | |||
int start1, size1, start2, size2; | |||
fifo.prepareToWrite (num, start1, size1, start2, size2); | |||
@@ -203,10 +204,11 @@ public: | |||
WriteThread writer (fifo, buffer); | |||
int n = 0; | |||
Random r; | |||
for (int count = 1000000; --count >= 0;) | |||
{ | |||
int num = Random::getSystemRandom().nextInt (6000) + 1; | |||
int num = r.nextInt (6000) + 1; | |||
int start1, size1, start2, size2; | |||
fifo.prepareToRead (num, start1, size1, start2, size2); | |||
@@ -33,42 +33,36 @@ BEGIN_JUCE_NAMESPACE | |||
#include "../io/network/juce_MACAddress.h" | |||
#include "../memory/juce_MemoryBlock.h" | |||
//============================================================================== | |||
Uuid::Uuid() | |||
namespace | |||
{ | |||
// Mix up any available MAC addresses with some time-based pseudo-random numbers | |||
// to make it very very unlikely that two UUIDs will ever be the same.. | |||
static int64 macAddresses[2]; | |||
static bool hasCheckedMacAddresses = false; | |||
if (! hasCheckedMacAddresses) | |||
int64 getRandomSeedFromMACAddresses() | |||
{ | |||
hasCheckedMacAddresses = true; | |||
Array<MACAddress> result; | |||
MACAddress::findAllAddresses (result); | |||
for (int i = 0; i < numElementsInArray (macAddresses); ++i) | |||
macAddresses[i] = result[i].toInt64(); | |||
Random r; | |||
for (int i = 0; i < result.size(); ++i) | |||
r.combineSeed (result[i].toInt64()); | |||
return r.nextInt64(); | |||
} | |||
} | |||
value.asInt64[0] = macAddresses[0]; | |||
value.asInt64[1] = macAddresses[1]; | |||
//============================================================================== | |||
Uuid::Uuid() | |||
{ | |||
// The normal random seeding is pretty good, but we'll throw some MAC addresses | |||
// into the mix too, to make it very very unlikely that two UUIDs will ever be the same.. | |||
// We'll use both a local RNG that is re-seeded, plus the shared RNG, | |||
// whose seed will carry over between calls to this method. | |||
static Random r1 (getRandomSeedFromMACAddresses()); | |||
Random r (macAddresses[0] ^ macAddresses[1] | |||
^ Random::getSystemRandom().nextInt64()); | |||
value.asInt64[0] = r1.nextInt64(); | |||
value.asInt64[1] = r1.nextInt64(); | |||
Random r2; | |||
for (int i = 4; --i >= 0;) | |||
{ | |||
r.setSeedRandomly(); // calling this repeatedly improves randomness | |||
value.asInt[i] ^= r.nextInt(); | |||
value.asInt[i] ^= Random::getSystemRandom().nextInt(); | |||
} | |||
value.asInt[i] ^= r2.nextInt(); | |||
} | |||
Uuid::~Uuid() noexcept | |||
@@ -171,14 +171,14 @@ BigInteger Primes::createProbablePrime (const int bitLength, | |||
{ | |||
randomSeeds = defaultSeeds; | |||
numRandomSeeds = numElementsInArray (defaultSeeds); | |||
Random r; | |||
Random r1, r2; | |||
for (int j = 10; --j >= 0;) | |||
{ | |||
r.setSeedRandomly(); | |||
r1.setSeedRandomly(); | |||
for (int i = numRandomSeeds; --i >= 0;) | |||
defaultSeeds[i] ^= r.nextInt() ^ Random::getSystemRandom().nextInt(); | |||
defaultSeeds[i] ^= r1.nextInt() ^ r2.nextInt(); | |||
} | |||
} | |||
@@ -359,6 +359,7 @@ void DragAndDropContainer::startDragging (const var& sourceDescription, | |||
Point<int> relPos (sourceComponent->getLocalPoint (nullptr, lastMouseDown)); | |||
Point<int> clipped (dragImage.getBounds().getConstrainedPoint (relPos)); | |||
Random random; | |||
for (int y = dragImage.getHeight(); --y >= 0;) | |||
{ | |||
@@ -373,7 +374,7 @@ void DragAndDropContainer::startDragging (const var& sourceDescription, | |||
{ | |||
const float alpha = (distance > hi) ? 0 | |||
: (hi - distance) / (float) (hi - lo) | |||
+ Random::getSystemRandom().nextFloat() * 0.008f; | |||
+ random.nextFloat() * 0.008f; | |||
dragImage.multiplyAlphaAt (x, y, alpha); | |||
} | |||
@@ -135,9 +135,11 @@ void ComponentPeer::handlePaint (LowLevelGraphicsContext& contextToPaintTo) | |||
// clearly when things are being repainted. | |||
g.restoreState(); | |||
g.fillAll (Colour ((uint8) Random::getSystemRandom().nextInt (255), | |||
(uint8) Random::getSystemRandom().nextInt (255), | |||
(uint8) Random::getSystemRandom().nextInt (255), | |||
static Random rng; | |||
g.fillAll (Colour ((uint8) rng.nextInt (255), | |||
(uint8) rng.nextInt (255), | |||
(uint8) rng.nextInt (255), | |||
(uint8) 0x50)); | |||
#endif | |||
@@ -890,7 +890,7 @@ String File::getRelativePathFrom (const File& dir) const | |||
File File::createTempFile (const String& fileNameEnding) | |||
{ | |||
const File tempFile (getSpecialLocation (tempDirectory) | |||
.getChildFile ("temp_" + String (Random::getSystemRandom().nextInt())) | |||
.getChildFile ("temp_" + String::toHexString (Random::getSystemRandom().nextInt())) | |||
.withFileExtension (fileNameEnding)); | |||
if (tempFile.exists()) | |||
@@ -36,7 +36,7 @@ BEGIN_JUCE_NAMESPACE | |||
TemporaryFile::TemporaryFile (const String& suffix, const int optionFlags) | |||
{ | |||
createTempFile (File::getSpecialLocation (File::tempDirectory), | |||
"temp_" + String (Random::getSystemRandom().nextInt()), | |||
"temp_" + String::toHexString (Random::getSystemRandom().nextInt()), | |||
suffix, | |||
optionFlags); | |||
} | |||
@@ -48,7 +48,8 @@ TemporaryFile::TemporaryFile (const File& targetFile_, const int optionFlags) | |||
jassert (targetFile != File::nonexistent); | |||
createTempFile (targetFile.getParentDirectory(), | |||
targetFile.getFileNameWithoutExtension() + "_temp" + String (Random::getSystemRandom().nextInt()), | |||
targetFile.getFileNameWithoutExtension() | |||
+ "_temp" + String::toHexString (Random::getSystemRandom().nextInt()), | |||
targetFile.getFileExtension(), | |||
optionFlags); | |||
} | |||
@@ -113,10 +113,11 @@ public: | |||
void runTest() | |||
{ | |||
beginTest ("Basics"); | |||
Random r; | |||
int randomInt = Random::getSystemRandom().nextInt(); | |||
int64 randomInt64 = Random::getSystemRandom().nextInt64(); | |||
double randomDouble = Random::getSystemRandom().nextDouble(); | |||
int randomInt = r.nextInt(); | |||
int64 randomInt64 = r.nextInt64(); | |||
double randomDouble = r.nextDouble(); | |||
String randomString (createRandomWideCharString()); | |||
MemoryOutputStream mo; | |||
@@ -146,16 +147,16 @@ public: | |||
for (int i = 0; i < numElementsInArray (buffer) - 1; ++i) | |||
{ | |||
if (Random::getSystemRandom().nextBool()) | |||
if (r.nextBool()) | |||
{ | |||
do | |||
{ | |||
buffer[i] = (juce_wchar) (1 + Random::getSystemRandom().nextInt (0x10ffff - 1)); | |||
buffer[i] = (juce_wchar) (1 + r.nextInt (0x10ffff - 1)); | |||
} | |||
while (! CharPointer_UTF16::canRepresent (buffer[i])); | |||
} | |||
else | |||
buffer[i] = (juce_wchar) (1 + Random::getSystemRandom().nextInt (0xff)); | |||
buffer[i] = (juce_wchar) (1 + r.nextInt (0xff)); | |||
} | |||
return CharPointer_UTF32 (buffer); | |||
@@ -59,11 +59,14 @@ void Random::combineSeed (const int64 seedValue) noexcept | |||
void Random::setSeedRandomly() | |||
{ | |||
combineSeed ((int64) (pointer_sized_int) this); | |||
static int64 globalSeed = 0; | |||
combineSeed (globalSeed ^ (int64) (pointer_sized_int) this); | |||
combineSeed (Time::getMillisecondCounter()); | |||
combineSeed (Time::getHighResolutionTicks()); | |||
combineSeed (Time::getHighResolutionTicksPerSecond()); | |||
combineSeed (Time::currentTimeMillis()); | |||
globalSeed ^= seed; | |||
} | |||
Random& Random::getSystemRandom() noexcept | |||
@@ -83,7 +86,7 @@ int Random::nextInt() noexcept | |||
int Random::nextInt (const int maxValue) noexcept | |||
{ | |||
jassert (maxValue > 0); | |||
return (nextInt() & 0x7fffffff) % maxValue; | |||
return (((unsigned int) nextInt()) * (uint64) maxValue) >> 32; | |||
} | |||
int64 Random::nextInt64() noexcept | |||
@@ -34,9 +34,6 @@ | |||
A random number generator. | |||
You can create a Random object and use it to generate a sequence of random numbers. | |||
As a handy shortcut to avoid having to create and seed one yourself, you can call | |||
Random::getSystemRandom() to return a global RNG that is seeded randomly when the | |||
app launches. | |||
*/ | |||
class JUCE_API Random | |||
{ | |||
@@ -67,7 +64,7 @@ public: | |||
int nextInt() noexcept; | |||
/** Returns the next random number, limited to a given range. | |||
The maxValue parameter may not be negative, or zero. | |||
@returns a random integer between 0 (inclusive) and maxValue (exclusive). | |||
*/ | |||
int nextInt (int maxValue) noexcept; | |||
@@ -104,14 +101,6 @@ public: | |||
void fillBitsRandomly (BigInteger& arrayToChange, int startBit, int numBits); | |||
//============================================================================== | |||
/** To avoid the overhead of having to create a new Random object whenever | |||
you need a number, this is a shared application-wide object that | |||
can be used. | |||
It's not thread-safe though, so threads should use their own Random object. | |||
*/ | |||
static Random& getSystemRandom() noexcept; | |||
/** Resets this Random object to a given seed value. */ | |||
void setSeed (int64 newSeed) noexcept; | |||
@@ -129,6 +118,14 @@ public: | |||
*/ | |||
void setSeedRandomly(); | |||
/** The overhead of creating a new Random object is fairly small, but if you want to avoid | |||
it, you can call this method to get a global shared Random object. | |||
It's not thread-safe though, so threads should use their own Random object, otherwise | |||
you run the risk of your random numbers becoming.. erm.. randomly corrupted.. | |||
*/ | |||
static Random& getSystemRandom() noexcept; | |||
private: | |||
//============================================================================== | |||
int64 seed; | |||
@@ -2161,19 +2161,20 @@ public: | |||
static String createRandomWideCharString() | |||
{ | |||
juce_wchar buffer[50] = { 0 }; | |||
Random r; | |||
for (int i = 0; i < numElementsInArray (buffer) - 1; ++i) | |||
{ | |||
if (Random::getSystemRandom().nextBool()) | |||
if (r.nextBool()) | |||
{ | |||
do | |||
{ | |||
buffer[i] = (juce_wchar) (1 + Random::getSystemRandom().nextInt (0x10ffff - 1)); | |||
buffer[i] = (juce_wchar) (1 + r.nextInt (0x10ffff - 1)); | |||
} | |||
while (! CharPointer_UTF16::canRepresent (buffer[i])); | |||
} | |||
else | |||
buffer[i] = (juce_wchar) (1 + Random::getSystemRandom().nextInt (0xff)); | |||
buffer[i] = (juce_wchar) (1 + r.nextInt (0xff)); | |||
} | |||
return CharPointer_UTF32 (buffer); | |||