]> gitweb.hamatoma.de Git - reqt/commitdiff
ReRandomizer: more generators
authorhama <hama@siduction.net>
Wed, 7 Oct 2015 22:37:19 +0000 (00:37 +0200)
committerhama <hama@siduction.net>
Wed, 7 Oct 2015 22:37:19 +0000 (00:37 +0200)
base/ReRandomizer.cpp
base/ReRandomizer.hpp
cunit/allTests.cpp
cunit/cuReRandomizer.cpp [new file with mode: 0644]
cunit/cunit.pro
os/ReFileSystem.cpp

index 9c5b69f055604ba26cdcebf3e235001f366110ba..6b4fa8a1f1f5b120e465e22d8f2e6e1fc8d0513f 100644 (file)
 #include "base/rebase.hpp"
 
 static bool s_trace = false;
+const int ReRandomizer::m_primes[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31,
+    37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109,
+    113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193,
+    197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277,
+    281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373,
+    379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461,
+    463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569,
+    571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653,
+    659, 661, 673, 677, 683, 691 };
+const int ReRandomizer::m_countPrimes = sizeof ReRandomizer::m_primes
+    / sizeof(int);
+
 /**
  * @brief Constructor.
+ *
+ * @param name the name of the generator
  */
-ReRandomizer::ReRandomizer() {
+ReRandomizer::ReRandomizer(const char* name) :
+           m_name(name) {
 }
 /**
  * @brief Destructor.
@@ -28,16 +43,14 @@ inline int abs(int x) {
        return x < 0 ? -x : x;
 }
 #endif
+
 /**
- * @brief Returns the next random character.
- *
- * The character is in the range ' ' .. chr(127) (inclusive).
+ * Returns the name of the generator.
  *
- * @return The next random character.
+ * @return     the name
  */
-char ReRandomizer::nextChar() {
-       char rc = nextInt(' ', ' ' + CHARRANGE - 1);
-       return rc;
+const QByteArray& ReRandomizer::name() const {
+       return m_name;
 }
 
 /**
@@ -63,6 +76,19 @@ ReRandomizer::seed_t ReRandomizer::nearTrueRandom() {
 #endif
        return rc;
 }
+
+/**
+ * @brief Returns the next random character.
+ *
+ * The character is in the range ' ' .. chr(127) (inclusive).
+ *
+ * @return The next random character.
+ */
+char ReRandomizer::nextChar() {
+       char rc = nextInt(' ', ' ' + CHARRANGE - 1);
+       return rc;
+}
+
 /**
  * @brief Returns the next random integer.
  *
@@ -218,36 +244,135 @@ void ReRandomizer::shuffle(void* array, size_t length, size_t elemSize) {
        }
 }
 /**
- * @brief Constructor.
+ * Builds a number from a text by hasing.
+ *
+ * Conditions:
+ * <ul><li>It should be difficult to restore the text from the hash.</li>
+ * <li>Same text must return the same hash value.</li>
+ * <li>All bits should be set from any text (except the empty text)</li>
+ * </ul>
+ *
+ * @param text the text to hash
+ * @return             a number
  */
-ReCongruentialGenerator::ReCongruentialGenerator() :
-           m_seed(0x4711),
-           m_factor(214013),
-           m_increment(2531011),
-           m_lastSetSeed(0x4711) {
+ReRandomizer::seed_t ReRandomizer::hash(const QByteArray& text) {
+       seed_t rc = 0x200a110b190c580dLL;
+       int ixPrimes = m_countPrimes / 2;
+       for (int ix = text.length() - 1; ix >= 0; ix--) {
+               rc = rc * m_primes[ixPrimes] + text.at(ix) * m_primes[ixPrimes - 1];
+               if ((ixPrimes -= 2) <= 0)
+                       ixPrimes = m_countPrimes;
+       }
+       return rc;
 }
+
 /**
- * @brief Destructor.
+ * Converts a text into a seed
+ * @param text
+ * @param seed
  */
-ReCongruentialGenerator::~ReCongruentialGenerator() {
+void ReRandomizer::hash(const QByteArray& text, QByteArray& seed) {
+       int ixSrc = text.length() / sizeof(seed_t) - 1;
+       int maxSrc = text.length() / sizeof(seed_t) - 1;
+       const seed_t* src = reinterpret_cast<const seed_t*>(text.constData());
+       seed_t srcSeed = 0x44112200773355LL;
+       if (text.length() < (int) sizeof(seed_t)) {
+               for (int ix = text.length() - 1; ix >= 0; ix--)
+                       srcSeed = (srcSeed << 8) | text.at(ix);
+               src = &srcSeed;
+               maxSrc = 1;
+       }
+       seed_t last = 0x112012041919891LL;
+       seed_t* trg = reinterpret_cast<seed_t*>(seed.data());
+       int ixTrg;
+       int ixPrime = m_countPrimes;
+       int maxTrg = seed.length() / sizeof(seed_t) - 1;
+       for (ixTrg = 0; ixTrg < maxTrg; ixTrg++) {
+               last = trg[ixTrg] = last * m_primes[ixPrime]
+                   + src[ixSrc] * m_primes[ixPrime - 1];
+               if ((ixPrime -= 2) <= 0)
+                       ixPrime = m_countPrimes;
+               if (--ixSrc <= 0)
+                       ixSrc = maxSrc;
+       }
+       ixSrc = text.length() - 1;
+       char* trgPtr = reinterpret_cast<char*>(seed.data());
+       for (ixTrg = seed.length() % sizeof(seed_t); ixTrg < seed.length();
+           ixTrg++) {
+               last = last + text.at(ixSrc) * m_primes[ixPrime];
+               trgPtr[ixTrg] = (char) last;
+               if (--ixPrime < 0)
+                       ixPrime = m_countPrimes;
+               if (--ixSrc < 0)
+                       ixSrc = text.length() - 1;
+       }
+       ixTrg = 0;
+       for (int ix = seed.length(); ix < text.length(); ix++) {
+               trg[ixTrg] ^= text.at(ixSrc);
+               if (--ixSrc < 0)
+                       ixSrc = text.length() - 1;
+               if (ixTrg++ >= seed.length())
+                       ixTrg = 0;
+       }
 }
 
 /**
- * @brief Returns the current factor.
+ * @brief Sets the seed to the value given by the last <code>setSeed()</code>.
  *
- * @return The current factor.
+ * Note: The constructor does the first <code>setSeed()</code>.
  */
-ReRandomizer::seed_t ReCongruentialGenerator::factor() const {
-       return m_factor;
+/**
+ * Constructor.
+ *
+ * @param name the name of the generator
+ */
+ReSingleSeedRandomizer::ReSingleSeedRandomizer(const char* name) :
+           ReRandomizer(name),
+           m_seed(0x1120120419198991ull),
+           m_lastSetSeed(0x1120120419198991ull) {
+}
+/**
+ * Sets the seed to the start point (defined with setSeed()).
+ */
+void ReSingleSeedRandomizer::reset() {
+       m_seed = m_lastSetSeed;
 }
 
 /**
- * @brief Returns the current increment.
+ * Sets the current point of pseudo random.
  *
- * @return The current increment.
+ * @param seed the current point of pseudo random
  */
-ReRandomizer::seed_t ReCongruentialGenerator::increment() const {
-       return m_increment;
+void ReSingleSeedRandomizer::restoreSeed(const QByteArray& seed) {
+       if (seed.size() >= (int) sizeof(seed_t)) {
+               memcpy(&m_seed, seed.constData(), sizeof m_seed);
+       } else {
+               QByteArray buffer = seed;
+               buffer.resize(sizeof m_seed);
+               memset(buffer.data() + seed.size(), 0, sizeof(m_seed) - seed.size());
+               memcpy(&m_seed, buffer.constData(), sizeof m_seed);
+       }
+       m_lastSetSeed = m_seed;
+}
+
+/** @brief Sets the current seed.
+ *
+ * @param seed The seed to set.
+ */
+void ReSingleSeedRandomizer::setSeed(seed_t seed) {
+       m_seed = m_lastSetSeed = seed;
+       if (s_trace)
+               printf(" Seed: %llx ", (long long) seed);
+}
+
+/**
+ * Gets the current point of pseudo random.
+ *
+ * @param seed the current point of pseudo random
+ */
+void ReSingleSeedRandomizer::saveSeed(QByteArray& seed) const {
+       seed.resize(sizeof m_seed);
+       memcpy(seed.data(), &m_seed, sizeof m_seed);
 }
 
 /**
@@ -255,17 +380,43 @@ ReRandomizer::seed_t ReCongruentialGenerator::increment() const {
  *
  * @return The current seed.
  */
-ReRandomizer::seed_t ReCongruentialGenerator::seed() const {
+ReRandomizer::seed_t ReSingleSeedRandomizer::seed() const {
        return m_seed;
 }
 
 /**
- * @brief Sets the seed to the value given by the last <code>setSeed()</code>.
+ * Converts a text (e.g. password) into the generator specific seed.
  *
- * Note: The constructor does the first <code>setSeed()</code>.
+ * @param text the text to convert
  */
-void ReCongruentialGenerator::reset() {
-       m_seed = m_lastSetSeed;
+void ReSingleSeedRandomizer::textToSeed(const QByteArray& text) {
+       setSeed(hash(text));
+}
+
+/**
+ * @brief Constructor.
+ */
+ReCongruentialGeneratorBase::ReCongruentialGeneratorBase() :
+           m_factor(214013),
+           m_increment(2531011) {
+}
+
+/**
+ * @brief Returns the current factor.
+ *
+ * @return The current factor.
+ */
+ReRandomizer::seed_t ReCongruentialGeneratorBase::factor() const {
+       return m_factor;
+}
+
+/**
+ * @brief Returns the current increment.
+ *
+ * @return The current increment.
+ */
+ReRandomizer::seed_t ReCongruentialGeneratorBase::increment() const {
+       return m_increment;
 }
 
 /**
@@ -273,7 +424,7 @@ void ReCongruentialGenerator::reset() {
  *
  * @param factor       The new factor.
  */
-void ReCongruentialGenerator::setFactor(seed_t factor) {
+void ReCongruentialGeneratorBase::setFactor(ReRandomizer::seed_t factor) {
        this->m_factor = factor;
 }
 
@@ -282,58 +433,170 @@ void ReCongruentialGenerator::setFactor(seed_t factor) {
  *
  * @param increment    The new increment.
  */
-void ReCongruentialGenerator::setIncrement(seed_t increment) {
+void ReCongruentialGeneratorBase::setIncrement(ReRandomizer::seed_t increment) {
        this->m_increment = increment;
 }
 
-/** @brief Sets the current seed.
+/**
+ * @brief Constructor.
+ */
+ReCongruentialGenerator::ReCongruentialGenerator() :
+           ReSingleSeedRandomizer("Linear Congruential Generator"),
+           ReCongruentialGeneratorBase() {
+}
+
+/** @brief Returns the next 64 bit pseudo random number.
  *
- * @param seed The seed to set.
+ * A congruential generator produces good random in the most significant
+ * bits. Therefore we exchange the bits of the result.
+ * Then x % m returns better results.
+ *
+ * @return a pseudo random number
  */
-void ReCongruentialGenerator::setSeed(seed_t seed) {
-       m_seed = m_lastSetSeed = seed;
-       if (s_trace)
-               printf(" Seed: %llx ", (long long) seed);
+ReRandomizer::seed_t ReRotateRandomizer::nextSeed() {
+       seed_t rc = ReCongruentialGenerator::nextSeed();
+       rc = ((rc & 0x7fffffff) << 33) | ((rc >> 31) & 0x1ffffffffll);
+       return rc;
 }
 
 /**
- * Gets the current point of pseudo random.
+ * Constructor.
+ */
+
+ReMultiSeedRandomizer::ReMultiSeedRandomizer(int countSeeds, const char* name) :
+           ReRandomizer(name),
+           m_countSeeds(min(256, max(countSeeds, 2))),
+           m_seedBuffer(),
+           m_startSeed(),
+           m_seeds() {
+       m_seedBuffer.fill(0x38, m_countSeeds * sizeof m_seeds[0]);
+       m_seeds = reinterpret_cast<seed_t*>(m_seedBuffer.data());
+       m_startSeed = m_seedBuffer;
+}
+
+/** @brief Sets the instance to a defined start state.
+ */
+void ReMultiSeedRandomizer::reset() {
+       m_seedBuffer = m_startSeed;
+}
+
+/**
+ * Sets the current point of pseudo random with a seed saved by <code>saveSeed()</code>.
  *
  * @param seed the current point of pseudo random
  */
-void ReCongruentialGenerator::seed(QByteArray& seed) {
-       seed.resize(sizeof m_seed);
-       memcpy(seed.data(), &m_seed, sizeof m_seed);
+void ReMultiSeedRandomizer::restoreSeed(const QByteArray& seed) {
+       size_t length = min(seed.length(), m_seedBuffer.length());
+       memcpy(m_seedBuffer.data(), seed.constData(), length);
 }
 
 /**
- * Sets the current point of pseudo random.
+ * Stores the the current point of pseudo random in a buffer.
+ *
+ * Restoring is done by <code>restoreSeed()</code>
  *
  * @param seed the current point of pseudo random
  */
-void ReCongruentialGenerator::setSeed(const QByteArray& seed) {
-       if (seed.size() >= sizeof(seed_t)) {
-               memcpy(&m_seed, seed.constData(), sizeof m_seed);
-       } else {
-               QByteArray buffer = seed;
-               buffer.resize(sizeof m_seed);
-               memset(buffer.data() + seed.size(), 0, sizeof(m_seed) - seed.size());
-               memcpy(&m_seed, buffer.constData(), sizeof m_seed);
-       }
-       m_lastSetSeed = m_seed;
+void ReMultiSeedRandomizer::saveSeed(QByteArray& seed) const {
+       size_t size = m_seedBuffer.length();
+       seed.resize(size);
+       memcpy(seed.data(), m_seedBuffer.constData(), size);
+}
 
+/**
+ * Converts a text (e.g. password) into the generator specific seed.
+ *
+ * @param text the text to convert
+ */
+void ReMultiSeedRandomizer::textToSeed(const QByteArray& text) {
+       hash(text, m_seedBuffer);
+       m_startSeed = m_seedBuffer;
 }
 
-/** @brief Returns the next 64 bit pseudo random number.
+/**
+ * Constructor.
  *
- * A congruential generator produces good random in the most significant
- * bits. Therefore we exchange the bits of the result.
- * Then x % m returns better results.
+ * @param countSeeds   number of seeds
+ */
+ReMultiCongruentialGenerator::ReMultiCongruentialGenerator(int countSeeds) :
+           ReMultiSeedRandomizer(countSeeds, "Multi LCG"),
+           ReCongruentialGeneratorBase(),
+           m_currentSeed(-1) {
+}
+
+/** @brief Returns the next 64 bit pseudo random number.
  *
  * @return a pseudo random number
  */
-ReRandomizer::seed_t ReShiftRandom::nextSeed() {
-       seed_t rc = ReCongruentialGenerator::nextSeed();
-       rc = ((rc & 0x7fffffff) << 33) | ((rc >> 31) & 0x1ffffffffll);
+ReRandomizer::seed_t ReMultiCongruentialGenerator::nextSeed() {
+       m_currentSeed = (m_currentSeed + 1) % m_countSeeds;
+       seed_t rc = m_seeds[m_currentSeed] * m_factor + m_increment;
+       m_seeds[m_currentSeed] = rc;
+       rc = ((rc & 0x7fffffff) << 33) | ((rc >> 31) & 0x1ffffffffLL);
        return rc;
 }
+
+/**
+ * Constructor.
+ *
+ * @return
+ */
+ReXorShift64Randomizer::ReXorShift64Randomizer() :
+           ReSingleSeedRandomizer("ShiftXor64") {
+}
+
+/**
+ * Calculates the next pseudo random value.
+ *
+ * @return the next pseudo random value
+ */
+ReRandomizer::seed_t ReXorShift64Randomizer::nextSeed() {
+       m_seed ^= m_seed << 13;
+       m_seed ^= m_seed >> 7;
+       m_seed ^= m_seed << 17;
+       return m_seed;
+}
+
+/**
+ * Constructor.
+ */
+ReKISSRandomizer::ReKISSRandomizer() :
+           ReMultiSeedRandomizer(6, "KISS") {
+       m_seeds[0] = 1234567890987654321ULL;
+       m_seeds[1] = 362436362436362436ULL;
+       m_seeds[2] = 1066149217761810ULL;
+       m_seeds[3] = 123456123456123456ULL;
+       m_seeds[4] = 0x20ab110c19d058ULL;
+       m_seeds[5] = 0x20ab040c19d091ULL;
+}
+
+/**
+ * Calculates the next pseudo random value.
+ * @return
+ */
+ReRandomizer::seed_t ReKISSRandomizer::nextSeed() {
+       static const int x = 0;
+       static const int y = 1;
+       static const int z = 2;
+       static const int c = 3;
+       static const int fac = 4;
+       static const int inc = 5;
+
+       seed_t t;
+
+       // Linear congruence generator
+       m_seeds[z] = m_seeds[fac] * m_seeds[z] + m_seeds[inc];
+
+       // Xorshift
+       m_seeds[y] ^= (m_seeds[y] << 13);
+       m_seeds[y] ^= (m_seeds[y] >> 17);
+       m_seeds[y] ^= (m_seeds[y] << 43);
+
+       // Multiply-with-carry
+       t = (m_seeds[x] << 58) + m_seeds[c];
+       m_seeds[c] = (m_seeds[x] >> 6);
+       m_seeds[x] += t;
+       m_seeds[c] += (m_seeds[x] < t);
+
+       return m_seeds[x] + m_seeds[y] + m_seeds[z];
+}
index 6e24fa7d2a1af3d00de06c835309432a28553a32..2a1255fdf9f3afe33677e1cded98e4e127428d9b 100644 (file)
@@ -23,71 +23,165 @@ public:
        };
        typedef uint64_t seed_t;
 public:
-       ReRandomizer();
+       ReRandomizer(const char* name);
        virtual ~ReRandomizer();
 public:
-       virtual int nextInt(int maxValue = INT_MAX, int minValue = 0);
-       virtual int64_t nextInt64(int64_t maxValue = LLONG_MAX,
-           int64_t minValue = 0);
+       const QByteArray& name() const;
+       seed_t nearTrueRandom();
        char nextChar();
+       int nextInt(int maxValue = INT_MAX, int minValue = 0);
+       int64_t nextInt64(int64_t maxValue = LLONG_MAX, int64_t minValue = 0);
        const char* nextString(int minLength, int maxLength, QByteArray& buffer);
        void shuffle(void* array, size_t length, size_t elemSize);
+public:
        /** @brief Sets the instance to a defined start state.
         */
        virtual void reset() = 0;
        /**
-        * Gets the current point of pseudo random.
+        * Sets the current point of pseudo random with a seed saved by <code>saveSeed()</code>.
         *
         * @param seed  the current point of pseudo random
         */
-       virtual void seed(QByteArray& seed) = 0;
+       virtual void restoreSeed(const QByteArray& seed) = 0;
        /**
-        * Sets the current point of pseudo random.
+        * Stores the the current point of pseudo random in a buffer.
+        *
+        * Restoring is done by <code>restoreSeed()</code>
         *
         * @param seed  the current point of pseudo random
         */
-       virtual void setSeed(QByteArray& seed) = 0;
+       virtual void saveSeed(QByteArray& seed) const = 0;
+       /**
+        * Converts a text (e.g. password) into the generator specific seed.
+        * @param text  the text to convert
+        */
+       virtual void textToSeed(const QByteArray& text) = 0;
+public:
+       static seed_t hash(const QByteArray& text);
+       static void hash(const QByteArray& text, QByteArray& seed);
+
 protected:
        /** @brief Returns the next pseudo random number.
         * @return the next pseudo random number
         * */
        virtual seed_t nextSeed() = 0;
+protected:
+       QByteArray m_name;
 public:
-       seed_t nearTrueRandom();
+       // the first 125 prime numbers
+       static const int m_primes[];
+       static const int m_countPrimes;
 };
 
 /**
- * Implements a simple random generator.
- * A linear congruential generator produces the next value using this formula:
- * seed = (seed * factor + increment) % modulus
- * In this implementation modulus is 2**64.
+ * Base class for pseudo random generators with a state variable (seed) of 64 bit.
  */
-class ReCongruentialGenerator: public ReRandomizer {
+class ReSingleSeedRandomizer: public ReRandomizer {
 public:
-       ReCongruentialGenerator();
-       virtual ~ReCongruentialGenerator();
+       ReSingleSeedRandomizer(const char* name);
 public:
-       seed_t factor() const;
-       seed_t increment() const;
        virtual void reset();
        seed_t seed() const;
-       virtual void seed(QByteArray& seed);
-       void setFactor(seed_t factor);
-       void setIncrement(seed_t increment);
        void setSeed(seed_t m_seed);
-       virtual void setSeed(const QByteArray& seed);
+       virtual void restoreSeed(const QByteArray& seed);
+       virtual void saveSeed(QByteArray& seed) const;
+       virtual void textToSeed(const QByteArray& text);
 protected:
-       friend class ReShiftRandom;
-       virtual seed_t nextSeed();
-private:
        seed_t m_seed;
-       seed_t m_factor;
-       seed_t m_increment;
        seed_t m_lastSetSeed;
 };
 
-class ReShiftRandom: public ReCongruentialGenerator {
+class ReCongruentialGeneratorBase {
+public:
+       ReCongruentialGeneratorBase();
+public:
+       ReRandomizer::seed_t factor() const;
+       ReRandomizer::seed_t increment() const;
+       void setFactor(ReRandomizer::seed_t factor);
+       void setIncrement(ReRandomizer::seed_t increment);
+protected:
+       ReRandomizer::seed_t m_factor;
+       ReRandomizer::seed_t m_increment;
+};
+
+/**
+ * Implements a simple pseudo random generator.
+ * A linear congruential generator produces the next value using this formula:
+ * seed = (seed * factor + increment) % modulus
+ * In this implementation modulus is 2**64.
+ */
+class ReCongruentialGenerator: public ReSingleSeedRandomizer,
+    public ReCongruentialGeneratorBase {
+public:
+       ReCongruentialGenerator();
+protected:
+       friend class ReShiftRandom;
+       virtual seed_t nextSeed();
+};
+
+/**
+ * A simple pseudo random generator simular to <code>ReCongruentialGenerator</code>.
+ *
+ * A congruential generator produces good random in the most significant
+ * bits. Therefore we exchange the bits of the result.
+ * Then x % m returns better results.
+ */
+class ReRotateRandomizer: public ReCongruentialGenerator {
+protected:
+       virtual seed_t nextSeed();
+};
+
+/**
+ * Abstract base class for pseudo random generators with a state variable larger than 64 bit.
+ */
+class ReMultiSeedRandomizer: public ReRandomizer {
+public:
+       ReMultiSeedRandomizer(int countSeeds, const char* name);
+public:
+       virtual void reset();
+       virtual void restoreSeed(const QByteArray& seed);
+       virtual void saveSeed(QByteArray& seed) const;
+       virtual void textToSeed(const QByteArray& text);
 protected:
+       int m_countSeeds;
+       QByteArray m_seedBuffer;
+       QByteArray m_startSeed;
+       seed_t* m_seeds;
+};
+
+/**
+ * A simple pseudo random generator simular to <code>ReCongruentialGenerator</code>.
+ *
+ * Difference: An array of seeds is used (round robin)</code>.
+ */
+class ReMultiCongruentialGenerator: public ReMultiSeedRandomizer,
+    public ReCongruentialGeneratorBase {
+public:
+       ReMultiCongruentialGenerator(int countSeeds);
+public:
+       virtual seed_t nextSeed();
+protected:
+       int m_currentSeed;
+};
+
+class ReXorShift64Randomizer: public ReSingleSeedRandomizer {
+public:
+       ReXorShift64Randomizer();
+public:
+       virtual seed_t nextSeed();
+};
+
+/**
+ * A simple pseudo random generator but it fulfills some statistically tests.
+ *
+ * Combines a congruent generator, a xor-shift generator and the multiply
+ * with carry method.
+ */
+class ReKISSRandomizer: public ReMultiSeedRandomizer {
+public:
+       ReKISSRandomizer();
+public:
        virtual seed_t nextSeed();
 };
+
 #endif /* RANDOMIZER_H_ */
index cad6fc215e03ae2f4acc61d572d5fdec0cfee7bd..4bf3cf045b219fa2615a0381cb4c3040ecd5148e 100644 (file)
@@ -29,6 +29,7 @@ static void testGui() {
 }
 
 static void testBase() {
+       void testReRandomizer();
        void testReByteStorage();
        void testReCharPtrMap();
        void testReConfig();
@@ -40,11 +41,13 @@ static void testBase() {
        void testReFile();
        void testReFileUtils();
        void testReMatcher();
+       testReRandomizer();
        testReMatcher();
        testReQStringUtil();
        testReFile();
        testReFileUtils();
        if (s_allTest) {
+               testReRandomizer();
                testReByteStorage();
                testReCharPtrMap();
                testReConfig();
@@ -89,8 +92,8 @@ static void testOs() {
        testReFileSystem();
 }
 void allTests() {
-       testOs();
        testBase();
+       testOs();
        testGui();
        if (s_allTest) {
                testBase();
diff --git a/cunit/cuReRandomizer.cpp b/cunit/cuReRandomizer.cpp
new file mode 100644 (file)
index 0000000..879654f
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * cuReRandomizer.cpp
+ *
+ * License: Public Domain
+ * You can use and modify this file without any restriction.
+ * Do what you want.
+ * No warranties and disclaimer of any damages.
+ * You also can use this license: http://www.wtfpl.net
+ * The latest sources: https://github.com/republib
+ */
+/** @file
+ * @brief Unit test of the ReString tools.
+ */
+
+#include "../base/rebase.hpp"
+
+class TestReRandomizer: public ReTest {
+public:
+       TestReRandomizer() :
+                   ReTest("ReRandomizer") {
+               doIt();
+       }
+
+public:
+       void testOne(ReRandomizer& rand) {
+               QByteArray password("1");
+               QByteArray seed1;
+               QByteArray seed2;
+               rand.saveSeed(seed1);
+               char cc1 = rand.nextChar();
+               rand.reset();
+               rand.saveSeed(seed2);
+               checkEqu(seed1, seed2);
+
+               rand.textToSeed(password);
+               rand.saveSeed(seed1);
+               char cc2 = rand.nextChar();
+               checkEqu(cc1, cc2);
+               rand.reset();
+               rand.saveSeed(seed2);
+               checkEqu(seed1, seed2);
+
+               int numbers[16];
+               for (size_t ix = 0; ix < sizeof numbers / sizeof numbers[0]; ix++)
+                       numbers[ix] = rand.nextInt();
+               rand.reset();
+               rand.saveSeed(seed2);
+               checkEqu(seed1, seed2);
+               for (size_t ix = 0; ix < sizeof numbers / sizeof numbers[0]; ix++)
+                       checkEqu(numbers[ix], rand.nextInt());
+               clock_t start = clock();
+               for (int ix = 0; ix < 1000 * 1000; ix++) {
+                       rand.nextInt64();
+               }
+               double duration = double(clock() - start) / CLOCKS_PER_SEC;
+               printf("%s (1E6): %.3f sec\n", rand.name().constData(), duration);
+       }
+
+       void testBasics() {
+               ReKISSRandomizer rand3;
+               testOne(rand3);
+               ReCongruentialGenerator rand;
+               testOne(rand);
+               ReRotateRandomizer rand2;
+               testOne(rand2);
+               ReMultiCongruentialGenerator rand4(4);
+               testOne(rand4);
+               ReXorShift64Randomizer rand5;
+               testOne(rand5);
+       }
+
+       virtual void run(void) {
+               testBasics();
+       }
+};
+void testReRandomizer() {
+       TestReRandomizer test;
+}
+
index 7f33dea7c9770dc83b214bd539fcdf01b5a18140..1a2bb9dff362ec4df65068b8d077dd6ac669910f 100644 (file)
@@ -16,6 +16,7 @@ TEMPLATE = app
 INCLUDEPATH = ..
 
 SOURCES += main.cpp \
+        cuReRandomizer.cpp \
         cuReQStringUtils.cpp \
         cuReStringUtils.cpp \
         cuReFile.cpp \
index 842814d59744fcc5ef91da9e71d32a0afbeff48a..49a4233d36fd3671a46ea779c6dae627b479d70a 100644 (file)
@@ -619,8 +619,8 @@ ReCryptFileSystem::ReCryptFileSystem(ReFileSystem& hostFileSystem,
            m_contentSeed(),
            m_nameSeed(),
            m_buffer() {
-       m_contentRandom.seed(m_contentSeed);
-       m_nameRandom.seed(m_nameSeed);
+       m_contentRandom.saveSeed(m_contentSeed);
+       m_nameRandom.saveSeed(m_nameSeed);
        m_buffer.reserve(256);
 }