Commit 962abebbf215337ffe4ec227d58b9e8b458f12c5
1 parent
d56eb4f2
Replace use of rand() in RandSample, this was resulting in poor results from RndSubspace on windows
Showing
2 changed files
with
18 additions
and
9 deletions
openbr/core/common.cpp
| @@ -16,21 +16,32 @@ | @@ -16,21 +16,32 @@ | ||
| 16 | 16 | ||
| 17 | #include "common.h" | 17 | #include "common.h" |
| 18 | #include <QMutex> | 18 | #include <QMutex> |
| 19 | +#include <RandomLib\Random.hpp> | ||
| 19 | 20 | ||
| 20 | using namespace std; | 21 | using namespace std; |
| 21 | 22 | ||
| 23 | +static RandomLib::Random g_rand; | ||
| 24 | +static QMutex rngLock; | ||
| 25 | + | ||
| 22 | /**** GLOBAL ****/ | 26 | /**** GLOBAL ****/ |
| 23 | void Common::seedRNG() { | 27 | void Common::seedRNG() { |
| 24 | - static QMutex seedControl; | ||
| 25 | - QMutexLocker lock(&seedControl); | 28 | + QMutexLocker lock(&rngLock); |
| 26 | 29 | ||
| 27 | static bool seeded = false; | 30 | static bool seeded = false; |
| 28 | if (!seeded) { | 31 | if (!seeded) { |
| 29 | srand(0); // We seed with 0 instead of time(NULL) to have reproducible randomness | 32 | srand(0); // We seed with 0 instead of time(NULL) to have reproducible randomness |
| 30 | seeded = true; | 33 | seeded = true; |
| 34 | + g_rand.Reseed(0); | ||
| 31 | } | 35 | } |
| 32 | } | 36 | } |
| 33 | 37 | ||
| 38 | +double Common::randN() | ||
| 39 | +{ | ||
| 40 | + QMutexLocker lock(&rngLock); | ||
| 41 | + | ||
| 42 | + return g_rand.FloatN(); | ||
| 43 | +} | ||
| 44 | + | ||
| 34 | QList<int> Common::RandSample(int n, int max, int min, bool unique) | 45 | QList<int> Common::RandSample(int n, int max, int min, bool unique) |
| 35 | { | 46 | { |
| 36 | QList<int> samples; samples.reserve(n); | 47 | QList<int> samples; samples.reserve(n); |
openbr/core/common.h
| @@ -220,6 +220,9 @@ double KernelDensityEstimation(const V<T> &vals, double x, double h) | @@ -220,6 +220,9 @@ double KernelDensityEstimation(const V<T> &vals, double x, double h) | ||
| 220 | return y / (vals.size() * h); | 220 | return y / (vals.size() * h); |
| 221 | } | 221 | } |
| 222 | 222 | ||
| 223 | +// Return a random number, uniformly distributed over 0,1 | ||
| 224 | +double randN(); | ||
| 225 | + | ||
| 223 | /*! | 226 | /*! |
| 224 | * \brief Returns a vector of n integers sampled in the range <min, max]. | 227 | * \brief Returns a vector of n integers sampled in the range <min, max]. |
| 225 | * | 228 | * |
| @@ -236,19 +239,14 @@ QList<int> RandSample(int n, const QSet<int> &values, bool unique = false); | @@ -236,19 +239,14 @@ QList<int> RandSample(int n, const QSet<int> &values, bool unique = false); | ||
| 236 | template <typename T> | 239 | template <typename T> |
| 237 | QList<int> RandSample(int n, const QList<T> &weights, bool unique = false) | 240 | QList<int> RandSample(int n, const QList<T> &weights, bool unique = false) |
| 238 | { | 241 | { |
| 239 | - static bool seeded = false; | ||
| 240 | - if (!seeded) { | ||
| 241 | - srand(time(NULL)); | ||
| 242 | - seeded = true; | ||
| 243 | - } | ||
| 244 | - | ||
| 245 | QList<T> cdf = CumSum(weights); | 242 | QList<T> cdf = CumSum(weights); |
| 246 | for (int i=0; i<cdf.size(); i++) // Normalize cdf | 243 | for (int i=0; i<cdf.size(); i++) // Normalize cdf |
| 247 | cdf[i] = cdf[i] / cdf.last(); | 244 | cdf[i] = cdf[i] / cdf.last(); |
| 248 | 245 | ||
| 249 | QList<int> samples; samples.reserve(n); | 246 | QList<int> samples; samples.reserve(n); |
| 250 | while (samples.size() < n) { | 247 | while (samples.size() < n) { |
| 251 | - T r = (T)rand() / (T)RAND_MAX; | 248 | + T r = randN(); |
| 249 | + | ||
| 252 | for (int j=0; j<weights.size(); j++) { | 250 | for (int j=0; j<weights.size(); j++) { |
| 253 | if ((r >= cdf[j]) && (r <= cdf[j+1])) { | 251 | if ((r >= cdf[j]) && (r <= cdf[j+1])) { |
| 254 | if (!unique || !samples.contains(j)) | 252 | if (!unique || !samples.contains(j)) |