@@ -504,6 +504,7 @@ public: | |||||
{ | { | ||||
const int numSamples = 2048; | const int numSamples = 2048; | ||||
int32 original [numSamples], converted [numSamples], reversed [numSamples]; | int32 original [numSamples], converted [numSamples], reversed [numSamples]; | ||||
Random r; | |||||
{ | { | ||||
AudioData::Pointer<F1, E1, AudioData::NonInterleaved, AudioData::NonConst> d (original); | AudioData::Pointer<F1, E1, AudioData::NonInterleaved, AudioData::NonConst> d (original); | ||||
@@ -511,13 +512,13 @@ public: | |||||
for (int i = 0; i < numSamples / 2; ++i) | 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()) | if (! d.isFloatingPoint()) | ||||
clippingFailed = d.getAsFloat() > 1.0f || d.getAsFloat() < -1.0f || clippingFailed; | clippingFailed = d.getAsFloat() > 1.0f || d.getAsFloat() < -1.0f || clippingFailed; | ||||
++d; | ++d; | ||||
d.setAsInt32 (Random::getSystemRandom().nextInt()); | |||||
d.setAsInt32 (r.nextInt()); | |||||
++d; | ++d; | ||||
} | } | ||||
@@ -165,10 +165,11 @@ public: | |||||
void run() | void run() | ||||
{ | { | ||||
int n = 0; | int n = 0; | ||||
Random r; | |||||
while (! threadShouldExit()) | while (! threadShouldExit()) | ||||
{ | { | ||||
int num = Random::getSystemRandom().nextInt (2000) + 1; | |||||
int num = r.nextInt (2000) + 1; | |||||
int start1, size1, start2, size2; | int start1, size1, start2, size2; | ||||
fifo.prepareToWrite (num, start1, size1, start2, size2); | fifo.prepareToWrite (num, start1, size1, start2, size2); | ||||
@@ -203,10 +204,11 @@ public: | |||||
WriteThread writer (fifo, buffer); | WriteThread writer (fifo, buffer); | ||||
int n = 0; | int n = 0; | ||||
Random r; | |||||
for (int count = 1000000; --count >= 0;) | for (int count = 1000000; --count >= 0;) | ||||
{ | { | ||||
int num = Random::getSystemRandom().nextInt (6000) + 1; | |||||
int num = r.nextInt (6000) + 1; | |||||
int start1, size1, start2, size2; | int start1, size1, start2, size2; | ||||
fifo.prepareToRead (num, 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 "../io/network/juce_MACAddress.h" | ||||
#include "../memory/juce_MemoryBlock.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; | Array<MACAddress> result; | ||||
MACAddress::findAllAddresses (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;) | 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 | Uuid::~Uuid() noexcept | ||||
@@ -171,14 +171,14 @@ BigInteger Primes::createProbablePrime (const int bitLength, | |||||
{ | { | ||||
randomSeeds = defaultSeeds; | randomSeeds = defaultSeeds; | ||||
numRandomSeeds = numElementsInArray (defaultSeeds); | numRandomSeeds = numElementsInArray (defaultSeeds); | ||||
Random r; | |||||
Random r1, r2; | |||||
for (int j = 10; --j >= 0;) | for (int j = 10; --j >= 0;) | ||||
{ | { | ||||
r.setSeedRandomly(); | |||||
r1.setSeedRandomly(); | |||||
for (int i = numRandomSeeds; --i >= 0;) | 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> relPos (sourceComponent->getLocalPoint (nullptr, lastMouseDown)); | ||||
Point<int> clipped (dragImage.getBounds().getConstrainedPoint (relPos)); | Point<int> clipped (dragImage.getBounds().getConstrainedPoint (relPos)); | ||||
Random random; | |||||
for (int y = dragImage.getHeight(); --y >= 0;) | for (int y = dragImage.getHeight(); --y >= 0;) | ||||
{ | { | ||||
@@ -373,7 +374,7 @@ void DragAndDropContainer::startDragging (const var& sourceDescription, | |||||
{ | { | ||||
const float alpha = (distance > hi) ? 0 | const float alpha = (distance > hi) ? 0 | ||||
: (hi - distance) / (float) (hi - lo) | : (hi - distance) / (float) (hi - lo) | ||||
+ Random::getSystemRandom().nextFloat() * 0.008f; | |||||
+ random.nextFloat() * 0.008f; | |||||
dragImage.multiplyAlphaAt (x, y, alpha); | dragImage.multiplyAlphaAt (x, y, alpha); | ||||
} | } | ||||
@@ -135,9 +135,11 @@ void ComponentPeer::handlePaint (LowLevelGraphicsContext& contextToPaintTo) | |||||
// clearly when things are being repainted. | // clearly when things are being repainted. | ||||
g.restoreState(); | 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)); | (uint8) 0x50)); | ||||
#endif | #endif | ||||
@@ -890,7 +890,7 @@ String File::getRelativePathFrom (const File& dir) const | |||||
File File::createTempFile (const String& fileNameEnding) | File File::createTempFile (const String& fileNameEnding) | ||||
{ | { | ||||
const File tempFile (getSpecialLocation (tempDirectory) | const File tempFile (getSpecialLocation (tempDirectory) | ||||
.getChildFile ("temp_" + String (Random::getSystemRandom().nextInt())) | |||||
.getChildFile ("temp_" + String::toHexString (Random::getSystemRandom().nextInt())) | |||||
.withFileExtension (fileNameEnding)); | .withFileExtension (fileNameEnding)); | ||||
if (tempFile.exists()) | if (tempFile.exists()) | ||||
@@ -36,7 +36,7 @@ BEGIN_JUCE_NAMESPACE | |||||
TemporaryFile::TemporaryFile (const String& suffix, const int optionFlags) | TemporaryFile::TemporaryFile (const String& suffix, const int optionFlags) | ||||
{ | { | ||||
createTempFile (File::getSpecialLocation (File::tempDirectory), | createTempFile (File::getSpecialLocation (File::tempDirectory), | ||||
"temp_" + String (Random::getSystemRandom().nextInt()), | |||||
"temp_" + String::toHexString (Random::getSystemRandom().nextInt()), | |||||
suffix, | suffix, | ||||
optionFlags); | optionFlags); | ||||
} | } | ||||
@@ -48,7 +48,8 @@ TemporaryFile::TemporaryFile (const File& targetFile_, const int optionFlags) | |||||
jassert (targetFile != File::nonexistent); | jassert (targetFile != File::nonexistent); | ||||
createTempFile (targetFile.getParentDirectory(), | createTempFile (targetFile.getParentDirectory(), | ||||
targetFile.getFileNameWithoutExtension() + "_temp" + String (Random::getSystemRandom().nextInt()), | |||||
targetFile.getFileNameWithoutExtension() | |||||
+ "_temp" + String::toHexString (Random::getSystemRandom().nextInt()), | |||||
targetFile.getFileExtension(), | targetFile.getFileExtension(), | ||||
optionFlags); | optionFlags); | ||||
} | } | ||||
@@ -113,10 +113,11 @@ public: | |||||
void runTest() | void runTest() | ||||
{ | { | ||||
beginTest ("Basics"); | 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()); | String randomString (createRandomWideCharString()); | ||||
MemoryOutputStream mo; | MemoryOutputStream mo; | ||||
@@ -146,16 +147,16 @@ public: | |||||
for (int i = 0; i < numElementsInArray (buffer) - 1; ++i) | for (int i = 0; i < numElementsInArray (buffer) - 1; ++i) | ||||
{ | { | ||||
if (Random::getSystemRandom().nextBool()) | |||||
if (r.nextBool()) | |||||
{ | { | ||||
do | 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])); | while (! CharPointer_UTF16::canRepresent (buffer[i])); | ||||
} | } | ||||
else | else | ||||
buffer[i] = (juce_wchar) (1 + Random::getSystemRandom().nextInt (0xff)); | |||||
buffer[i] = (juce_wchar) (1 + r.nextInt (0xff)); | |||||
} | } | ||||
return CharPointer_UTF32 (buffer); | return CharPointer_UTF32 (buffer); | ||||
@@ -59,11 +59,14 @@ void Random::combineSeed (const int64 seedValue) noexcept | |||||
void Random::setSeedRandomly() | 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::getMillisecondCounter()); | ||||
combineSeed (Time::getHighResolutionTicks()); | combineSeed (Time::getHighResolutionTicks()); | ||||
combineSeed (Time::getHighResolutionTicksPerSecond()); | combineSeed (Time::getHighResolutionTicksPerSecond()); | ||||
combineSeed (Time::currentTimeMillis()); | combineSeed (Time::currentTimeMillis()); | ||||
globalSeed ^= seed; | |||||
} | } | ||||
Random& Random::getSystemRandom() noexcept | Random& Random::getSystemRandom() noexcept | ||||
@@ -83,7 +86,7 @@ int Random::nextInt() noexcept | |||||
int Random::nextInt (const int maxValue) noexcept | int Random::nextInt (const int maxValue) noexcept | ||||
{ | { | ||||
jassert (maxValue > 0); | jassert (maxValue > 0); | ||||
return (nextInt() & 0x7fffffff) % maxValue; | |||||
return (((unsigned int) nextInt()) * (uint64) maxValue) >> 32; | |||||
} | } | ||||
int64 Random::nextInt64() noexcept | int64 Random::nextInt64() noexcept | ||||
@@ -34,9 +34,6 @@ | |||||
A random number generator. | A random number generator. | ||||
You can create a Random object and use it to generate a sequence of random numbers. | 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 | class JUCE_API Random | ||||
{ | { | ||||
@@ -67,7 +64,7 @@ public: | |||||
int nextInt() noexcept; | int nextInt() noexcept; | ||||
/** Returns the next random number, limited to a given range. | /** 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). | @returns a random integer between 0 (inclusive) and maxValue (exclusive). | ||||
*/ | */ | ||||
int nextInt (int maxValue) noexcept; | int nextInt (int maxValue) noexcept; | ||||
@@ -104,14 +101,6 @@ public: | |||||
void fillBitsRandomly (BigInteger& arrayToChange, int startBit, int numBits); | 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. */ | /** Resets this Random object to a given seed value. */ | ||||
void setSeed (int64 newSeed) noexcept; | void setSeed (int64 newSeed) noexcept; | ||||
@@ -129,6 +118,14 @@ public: | |||||
*/ | */ | ||||
void setSeedRandomly(); | 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: | private: | ||||
//============================================================================== | //============================================================================== | ||||
int64 seed; | int64 seed; | ||||
@@ -2161,19 +2161,20 @@ public: | |||||
static String createRandomWideCharString() | static String createRandomWideCharString() | ||||
{ | { | ||||
juce_wchar buffer[50] = { 0 }; | juce_wchar buffer[50] = { 0 }; | ||||
Random r; | |||||
for (int i = 0; i < numElementsInArray (buffer) - 1; ++i) | for (int i = 0; i < numElementsInArray (buffer) - 1; ++i) | ||||
{ | { | ||||
if (Random::getSystemRandom().nextBool()) | |||||
if (r.nextBool()) | |||||
{ | { | ||||
do | 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])); | while (! CharPointer_UTF16::canRepresent (buffer[i])); | ||||
} | } | ||||
else | else | ||||
buffer[i] = (juce_wchar) (1 + Random::getSystemRandom().nextInt (0xff)); | |||||
buffer[i] = (juce_wchar) (1 + r.nextInt (0xff)); | |||||
} | } | ||||
return CharPointer_UTF32 (buffer); | return CharPointer_UTF32 (buffer); | ||||