On Sunday 09 February 2014 22:40:22 Kurt Pattyn wrote: > If I use std::random as Thiago proposed (see > http://en.cppreference.com/w/cpp/numeric/random), like: > > //one time initialisation > Q_CONST_EXPR std::size_t numSeeds = 13; //arbitrary number > quint32 seeds[numSeeds] = { 0 }; > bool success = false; > > try { > std::random_device seeder; //supported since MSVS 2008, > since GCC > 4.5 if (seeder.entropy() >= 0.5) { > std::generate_n(seeds, numSeeds, seeder); > success = true; > } > } catch (const std::exception &) { > //fall through > } > #ifdef Q_OS_WIN //the MinGW implementation of GCC 4.8 has a known bug in > std::random_device if (!success) { > HCRYPTPROV hp = 0; > BYTE rb[4]; > if ((success = CryptAcquireContext(&hp, 0, 0, PROV_RSA_FULL, > CRYPT_VERIFYCONTEXT)) == TRUE) for (std::size_t i = 0; i < numSeeds; ++i) { > if ((success = CryptGenRandom(hp, sizeof(quint32), seeds + > i) != TRUE) break; > } > CryptReleaseContext(hp, 0); > } > #endif > if (!success) { > qsrand(static_cast<uint>(QDateTime::currentMSecsSinceEpoch())); > for (std::size_t i = 0; i < numSeeds; ++i) { > const qreal multiplier = > qreal(std::numeric_limits<quint8>::max()) / qreal(RAND_MAX); const quint32 > byte1 = quint32(qrand() * multiplier) & 0xFF; const quint32 byte2 = > quint32(qrand() * multiplier) & 0xFF; const quint32 byte3 = quint32(qrand() > * multiplier) & 0xFF; const quint32 byte4 = quint32(qrand() * multiplier) & > 0xFF; seeds[i] = byte1 | byte2 << 8 | byte3 << 16 | byte4 << 24; } > } > > std::seek_seq seedSequence(seeds, seeds + numSeeds); > std::mt19937 randomiser(seedSequence); > //std::uniform_int_distribution<std::uint32_t> dist; //range from 0 > to > UINT_MAX > > > //somewhere else > return randomiser(); //no need to use a distribution function as > mt19937 > outputs 2^32 > > > Would this already be more acceptable? > Of course, this implementation requires C++11 support. > An interesting presentation about std::random can be found here: > http://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful > > If the above implementation suffices, then a virtual method would not be > needed anymore. > > Should I fall back to the ordinary qrand() when the other methods fail? >
I think you are making it more complicated than it need to be. qrand has maximum 32bit entropy (because it uses rand_r internally which only has 32 bit state), therefore calling it several time in a row is totally useless and don't add entropy. It turns out 32 bit entropy is enough because that's the size of your mask, so just use qrand with a decent proper seed: #if has_std_randrom_device return qsrand(std::random_device()()); #else static QElapsedTimer t; return qsrand(t.nsecsElapsed()); #endif -- Olivier Woboq - Qt services and support - http://woboq.com - http://code.woboq.org _______________________________________________ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development