LCOV - code coverage report
Current view: top level - src/libs/elektra - rand.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 19 24 79.2 %
Date: 2019-09-12 12:28:41 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief Rand for Elektra.
       5             :  *
       6             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       7             :  */
       8             : 
       9             : #include "kdbrand.h"
      10             : #include <kdbassert.h>
      11             : #include <time.h>
      12             : 
      13             : /**
      14             :  * @brief Non cryptographic pseudo random number generator
      15             :  *
      16             :  * By Ray Gardner
      17             :  * www8.cs.umu.se/~isak/snippets/rg_rand.c
      18             :  *
      19             :  * based on "Random Number Generators: Good Ones Are Hard to Find",
      20             :  * S.K. Park and K.W. Miller, Communications of the ACM 31:10 (Oct 1988),
      21             :  * and "Two Fast Implementations of the 'Minimal Standard' Random
      22             :  * Number Generator", David G. Carta, Comm. ACM 33, 1 (Jan 1990), p. 87-88
      23             :  *
      24             :  * linear congruential generator f(z) = 16807 z mod (2 ** 31 - 1)
      25             :  *
      26             :  * uses L. Schrage's method to avoid overflow problems
      27             :  *
      28             :  * Make sure the initial seed is: 0 < seed < ELEKTRARANDMAX
      29             :  *
      30             :  * @param seed a pointer to the seed
      31             :  *
      32             :  */
      33      204386 : void elektraRand (int32_t * seed)
      34             : {
      35      204386 :         ELEKTRA_ASSERT (seed, "seed is NULL");
      36      204386 :         ELEKTRA_ASSERT (*seed, "seed is 0");
      37      204386 :         ELEKTRA_ASSERT (*seed < ELEKTRARANDMAX, "seed is equal or bigger than ELEKTRARANDMAX");
      38             :         uint32_t lo, hi;
      39      204386 :         lo = 16807 * (int32_t) (*seed & 0xFFFF);
      40      204386 :         hi = 16807 * (int32_t) ((uint32_t) *seed >> 16);
      41      204386 :         lo += (hi & 0x7FFF) << 16;
      42      204386 :         if (lo > ELEKTRARANDMAX)
      43             :         {
      44       41677 :                 lo &= ELEKTRARANDMAX;
      45       41677 :                 ++lo;
      46             :         }
      47      204386 :         lo += hi >> 15;
      48      204386 :         if (lo > ELEKTRARANDMAX)
      49             :         {
      50           0 :                 lo &= ELEKTRARANDMAX;
      51           0 :                 ++lo;
      52             :         }
      53      204386 :         *seed = (int32_t) lo;
      54      204386 : }
      55             : 
      56             : /**
      57             :  * @brief Random initial seed generator
      58             :  *
      59             :  * Generates a random initial seed for the `elektraRand (...)` function.
      60             :  * Two invocations in the same second return the same random initial seed, due to
      61             :  * the usage of `time (0)`.
      62             :  *
      63             :  * @retval random initial seed
      64             :  *
      65             :  */
      66          28 : int32_t elektraRandGetInitSeed (void)
      67             : {
      68          28 :         int32_t initSeed = time (0);
      69             :         // ELEKTRARANDMAX is limit
      70          28 :         if (initSeed >= ELEKTRARANDMAX)
      71             :         {
      72           0 :                 initSeed = initSeed % ELEKTRARANDMAX;
      73             :         }
      74             :         // 0 not accepted by elektraRand
      75          28 :         if (!initSeed)
      76             :         {
      77           0 :                 initSeed = 1;
      78             :         }
      79             : #ifdef KDBRAND_BENCHMARK
      80           0 :         initSeed = elektraRandBenchmarkInitSeed;
      81             : #endif
      82          28 :         return initSeed;
      83             : }

Generated by: LCOV version 1.13