| @@ -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); | ||||