diff --git a/samples/blackmisc/samplesperformance.cpp b/samples/blackmisc/samplesperformance.cpp index 86a342043..218bb3b08 100644 --- a/samples/blackmisc/samplesperformance.cpp +++ b/samples/blackmisc/samplesperformance.cpp @@ -23,6 +23,7 @@ #include "blackmisc/aviation/callsign.h" #include "blackmisc/aviation/liverylist.h" #include "blackmisc/geo/coordinategeodetic.h" +#include "blackmisc/math/mathutils.h" #include "blackmisc/pq/units.h" #include "blackmisc/test/testing.h" #include "blackmisc/directoryutils.h" @@ -47,6 +48,7 @@ using namespace BlackMisc; using namespace BlackMisc::Aviation; using namespace BlackMisc::Geo; +using namespace BlackMisc::Math; using namespace BlackMisc::Network; using namespace BlackMisc::PhysicalQuantities; using namespace BlackMisc::Simulation; @@ -149,7 +151,7 @@ namespace BlackSample out << "Copied 10k stations " << number << " times in " << ms << "ms" << endl; // Regex pattern matching with lists of 10000 strings containing random hex numbers - auto generator = []() { return QString::number(qrand() | (qrand() << 16), 16); }; + auto generator = []() { return QString::number(CMathUtils::randomGenerator().generate(), 16); }; QStringList strList1, strList2, strList3, strList4; std::generate_n(std::back_inserter(strList1), 100000, generator); std::generate_n(std::back_inserter(strList2), 100000, generator); @@ -350,7 +352,7 @@ namespace BlackSample std::generate_n(std::back_inserter(strings), 100000, [] { QString s; - std::generate_n(std::back_inserter(s), 10, [] { return chars[qrand() % chars.size()]; }); + std::generate_n(std::back_inserter(s), 10, [] { return chars[CMathUtils::randomInteger(0, chars.size() - 1)]; }); return s; }); QString bigString = strings.join("\n"); @@ -698,9 +700,9 @@ namespace BlackSample CAircraftModelList models; for (int i = 0; i < numberOfModels; ++i) { - const auto &aircraftIcao = aircraftIcaos[qrand() % numberOfMemoParts]; - const auto &livery = liveries[qrand() % numberOfMemoParts]; - const auto &distributor = distributors[qrand() % numberOfMemoParts]; + const auto &aircraftIcao = aircraftIcaos[CMathUtils::randomInteger(0, numberOfMemoParts - 1)]; + const auto &livery = liveries[CMathUtils::randomInteger(0, numberOfMemoParts - 1)]; + const auto &distributor = distributors[CMathUtils::randomInteger(0, numberOfMemoParts - 1)]; models.push_back(CAircraftModel(QString::number(i), CAircraftModel::TypeUnknown, CSimulatorInfo::FSX, QString::number(i), QString::number(i), aircraftIcao, livery)); models.back().setDistributor(distributor); } diff --git a/src/blackcore/simulator.cpp b/src/blackcore/simulator.cpp index 947a797da..af0ec4f82 100644 --- a/src/blackcore/simulator.cpp +++ b/src/blackcore/simulator.cpp @@ -14,6 +14,7 @@ #include "blackmisc/directoryutils.h" #include "blackmisc/threadutils.h" #include "blackmisc/logmessage.h" +#include "blackmisc/math/mathutils.h" #include #include @@ -32,6 +33,7 @@ using namespace BlackConfig; using namespace BlackMisc; using namespace BlackMisc::Aviation; using namespace BlackMisc::Geo; +using namespace BlackMisc::Math; using namespace BlackMisc::Simulation; using namespace BlackMisc::Simulation::Settings; using namespace BlackMisc::PhysicalQuantities; @@ -1104,7 +1106,7 @@ namespace BlackCore emit this->requestUiConsoleMessage(dm, true); } - const int t = 4500 + (qrand() % 1000); // makes sure not always using the same time difference + const int t = CMathUtils::randomInteger(4500, 5500); // makes sure not always using the same time difference const QPointer myself(this); QTimer::singleShot(t, this, [ = ] { diff --git a/src/blackmisc/algorithm.h b/src/blackmisc/algorithm.h index 74e712e63..35b3b7975 100644 --- a/src/blackmisc/algorithm.h +++ b/src/blackmisc/algorithm.h @@ -15,6 +15,7 @@ #include "integersequence.h" #include +#include #include #include #include @@ -51,7 +52,7 @@ namespace BlackMisc { //! \fixme Qt 5.10: Use QRandomGenerator. static QThreadStorage rng; - if (rng.hasLocalData()) { rng.setLocalData(std::mt19937(static_cast(qrand()))); } + if (rng.hasLocalData()) { rng.setLocalData(std::mt19937(static_cast(QRandomGenerator::global()->generate()))); } return rng.localData(); } } diff --git a/src/blackmisc/math/mathutils.cpp b/src/blackmisc/math/mathutils.cpp index 88e6354a2..ef55c0566 100644 --- a/src/blackmisc/math/mathutils.cpp +++ b/src/blackmisc/math/mathutils.cpp @@ -99,32 +99,30 @@ namespace BlackMisc return (result >= 0.0) ? result : result + 360.0; } + QRandomGenerator &CMathUtils::randomGenerator() + { + thread_local QRandomGenerator rng(QRandomGenerator::global()->generate()); + return rng; + } + int CMathUtils::randomInteger(int low, int high) { - static QThreadStorage seeds; Q_ASSERT_X(high < INT_MAX, Q_FUNC_INFO, "Cannot add 1"); - Q_ASSERT_X(low >= 0 && high >= 0, Q_FUNC_INFO, "Only valid for positive values"); - if (!seeds.hasLocalData()) - { - // seed is per thread! - const uint seed = static_cast(QTime::currentTime().msec()); - qsrand(seed); - seeds.setLocalData(seed); - } - const int r(qrand()); - const int mod = (high + 1) - low; - Q_ASSERT_X(mod <= RAND_MAX, Q_FUNC_INFO, "RAND_MAX exceeded"); - return (r % mod) + low; + return randomGenerator().bounded(low, high + 1); } double CMathUtils::randomDouble(double max) { - // on Win system, RAND_MAX is only 16bit, on other systems higher - static const int MAX(RAND_MAX < INT_MAX ? RAND_MAX - 1 : INT_MAX - 1); + constexpr int MAX(std::min(RAND_MAX - 1, INT_MAX - 1)); const double r = randomInteger(0, MAX); return (r / MAX) * max; } + bool CMathUtils::randomBool() + { + return randomInteger(0, 1); + } + int CMathUtils::roundToMultipleOf(int value, int divisor) { Q_ASSERT(divisor != 0); diff --git a/src/blackmisc/math/mathutils.h b/src/blackmisc/math/mathutils.h index bc1651ae8..635c125cd 100644 --- a/src/blackmisc/math/mathutils.h +++ b/src/blackmisc/math/mathutils.h @@ -14,6 +14,7 @@ #include "blackmisc/blackmiscexport.h" +#include #include #include #include @@ -115,12 +116,18 @@ namespace BlackMisc //! Normalize: 0≤ degrees <360 static double normalizeDegrees360(double degrees); + //! Thread-local random generator + static QRandomGenerator &randomGenerator(); + //! Random number between low and high static int randomInteger(int low, int high); //! Random double 0-max static double randomDouble(double max = 1); + //! Random boolean + static bool randomBool(); + //! Round numToRound to the nearest multiple of divisor static int roundToMultipleOf(int value, int divisor); diff --git a/src/blackmisc/test/testdata.cpp b/src/blackmisc/test/testdata.cpp index 9bddd5ae1..bd056fbab 100644 --- a/src/blackmisc/test/testdata.cpp +++ b/src/blackmisc/test/testdata.cpp @@ -16,9 +16,11 @@ #include "blackmisc/fileutils.h" #include "blackmisc/directoryutils.h" #include "blackmisc/variantlist.h" +#include "blackmisc/math/mathutils.h" using namespace BlackMisc::Aviation; using namespace BlackMisc::Geo; +using namespace BlackMisc::Math; using namespace BlackMisc::Network; using namespace BlackMisc::Audio; using namespace BlackMisc::PhysicalQuantities; @@ -30,7 +32,7 @@ namespace BlackMisc { int randomIndex(int size) { - return qrand() % size; + return CMathUtils::randomInteger(0, size - 1); } const CServer &CTestData::getTrafficServer() diff --git a/src/blackmisc/thirdparty/simplecrypt.cpp b/src/blackmisc/thirdparty/simplecrypt.cpp index 0dd666e64..c46e88e94 100644 --- a/src/blackmisc/thirdparty/simplecrypt.cpp +++ b/src/blackmisc/thirdparty/simplecrypt.cpp @@ -31,7 +31,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include +#include namespace BlackMisc { @@ -42,9 +44,7 @@ namespace BlackMisc m_compressionMode(CompressionAuto), m_protectionMode(ProtectionChecksum), m_lastError(ErrorNoError) - { - qsrand(uint(QDateTime::currentMSecsSinceEpoch() & 0xFFFF)); - } + {} SimpleCrypt::SimpleCrypt(quint64 key): m_key(key), @@ -52,7 +52,6 @@ namespace BlackMisc m_protectionMode(ProtectionChecksum), m_lastError(ErrorNoError) { - qsrand(uint(QDateTime::currentMSecsSinceEpoch() & 0xFFFF)); splitKey(); } @@ -127,7 +126,8 @@ namespace BlackMisc } //prepend a random char to the string - char randomChar = char(qrand() & 0xFF); + thread_local QRandomGenerator rng(QRandomGenerator::global()->generate()); + char randomChar = static_cast(rng.bounded(static_cast(std::numeric_limits::min()), static_cast(std::numeric_limits::max()) + 1)); ba = randomChar + integrityProtection + ba; int pos(0); diff --git a/tests/blackmisc/testcontainers/testcontainers.cpp b/tests/blackmisc/testcontainers/testcontainers.cpp index cdd6f8fdc..bf71d5cc0 100644 --- a/tests/blackmisc/testcontainers/testcontainers.cpp +++ b/tests/blackmisc/testcontainers/testcontainers.cpp @@ -25,6 +25,7 @@ #include "blackmisc/range.h" #include "blackmisc/registermetadata.h" #include "blackmisc/sequence.h" +#include "blackmisc/math/mathutils.h" #include "test.h" #include @@ -44,6 +45,7 @@ using namespace BlackMisc; using namespace BlackMisc::Aviation; using namespace BlackMisc::Geo; +using namespace BlackMisc::Math; using namespace BlackMisc::PhysicalQuantities; namespace BlackMiscTest @@ -369,7 +371,6 @@ namespace BlackMiscTest void CTestContainers::offsetTimestampList() { - qsrand(QDateTime::currentDateTime().toTime_t()); CAircraftSituationList situations; static const CCoordinateGeodetic geoPos = CCoordinateGeodetic::fromWgs84("48° 21′ 13″ N", "11° 47′ 09″ E", { 1487, CLengthUnit::ft() }); qint64 ts = 1000000; @@ -384,16 +385,14 @@ namespace BlackMiscTest s.setMSecsSinceEpoch(ts); s.setCallsign("CS" + QString::number(i)); - if (qrand() % 2 == 0) + if (CMathUtils::randomBool()) { - // 4500-5500 - dt = 4500 + (qrand() % 1000); + dt = CMathUtils::randomInteger(4500, 5500); s.setTimeOffsetMs(6000); } else { - // 900-1100 - dt = 900 + (qrand() % 200); + dt = CMathUtils::randomInteger(900, 1100); s.setTimeOffsetMs(2000); }