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