Reuse, not rework
Home

License Awareness



Highly Reusable Software

By activity
Professions, Sciences, Humanities, Business, ...

User Interface
Text-based, GUI, Audio, Video, Keyboards, Mouse, Images,...

Text Strings
Conversions, tests, processing, manipulation,...

Math
Integer, Floating point, Matrix, Statistics, Boolean, ...

Processing
Algorithms, Memory, Process control, Debugging, ...

Stored Data
Data storage, Integrity, Encryption, Compression, ...

Communications
Networks, protocols, Interprocess, Remote, Client Server, ...

Hard World
Timing, Calendar and Clock, Audio, Video, Printer, Controls...

File System
Management, Filtering, File & Directory access, Viewers, ...


NAME

librock_random - Multithread-capable pseudo-random number generator.
librock_srandom - Initialization routine for librock_random data.
#License - #Source code - #Example Use -

SYNOPSIS

#include <librock/target/bitypes.h>
#include <librock/math.h>

uint32_t
librock_random(struct librock_random_s *state);

struct librock_random_s *
librock_srandom(
        struct librock_random_s *state, /* Pointer to state, or NULL */
        uint32_t x,                     /* Random seed value */
        char *prand,                    /* Random data for state, or NULL */
        int n);                         /* Amount of state information */

DESCRIPTION

This random number generation package is adapted from OpenBSD libc/random.c, (The code is originally from BSD 4.2.) The output and behavior is identical, but the calling conventions were modified to take a pointer to state information as an argument. This efficiently supports multiple concurrent state information blocks within a single process, without the inefficient copying of the original BSD setstate() routine.

Typical use would be to generate pseudo-random streams for games or repeatable tests. See below for typical code.

librock_random() returns a 31-bit random number, in a determined sequence set by the starting seed and initial state. The first argument is a pointer to the state information, which can be NULL to use an internal (static) block with 128 bytes of state, matching the BSD 4.2 output. Otherwise it should be a pointer previously given or returned from a call to librock_srandom().

librock_srandom intializes state information. When the first parameter is NULL, this will malloc() space, and the caller is responsible for calling free(). The number of bytes for static or external allocations of state information is #define'd as librock_SIZEOF_random_s in the header file. Since other pointers and values are kept in the state information block, it is not compatible with the BSD setstate() and initstate() routines.

The parameter n, for the amount of state information is rounded down to the closest or equal value of 1, 32, 64, 128, and 256. (Using 1 is not recommended, even though it is fastest.) The values larger than 1 are equally efficient, but larger values keep more state and have a longer period without repeating.) The return value is NULL on error, or the pointer to the state information block.

prand is an optional pointer to a block of n bytes of random data used to initialize the state. If prand is NULL, the seed value x (or 1 if the seed is 0) is used to initialize the state.

The multi-threaded caller must perform locking when there could be concurrent calls with the same state pointer argument.

The random number generation technique is a linear feedback shift register approach, employing trinomials (since there are fewer terms to sum up that way). In this approach, the least significant bit of all the numbers in the state table will act as a linear feedback shift register, and will have period 2^deg - 1 (where deg is the degree of the polynomial being used, assuming that the polynomial is irreducible and primitive). The higher order bits will have longer periods, since their values are also influenced by pseudo-random carries out of the lower bits. The total period of the generator is approximately deg*(2**deg - 1); thus doubling the amount of state information has a vast influence on the period of the generator. Note: the deg*(2**deg - 1) is an approximation only good for large deg, when the period of the shift register is the dominant factor. With deg equal to seven, the period is actually much longer than the 7*(2**7 - 1) predicted by this formula.

To generate a uniformly distributed pseudo-random integer in the range 0,(N-1) inclusive when N <= 2^31, you could use the following. (If N is unchanging, precalculation of maxuniform will save time.)

#ifdef librock_TYPICAL_USE_random
    #include <librock/target/bitypes.h>
    #include <librock/math.h>
    struct librock_random_s *pstate;
    int N = 8000;
    pstate = librock_srandom(0,0x1234,0,0);

    if (N > 0) {
        long maxuniform = 0x8000000 - (0x80000000 % N);
        long r;
        do {
            r = librock_random(pstate);
        } while (r >= maxuniform);
        r %= N;
        printf("%ld\n",r);
    }
#endif

To generate a uniformly distributed pseudo-random floating point in the range 0 to N, you could use the following. (If N is unchanging, precalculation of a term will save time.)
#ifdef librock_TYPICAL_USE_2_random
    printf("%g\n",(double) librock_random(0) * (N / (double) 0x80000000));
#endif
The original BSD 4.2 code included a srandomdev() routine which seeded the generator with random data. Getting good random seed data for security purposes is a hard problem. Picking clocks (even microsecond clocks) would enable attackers to have a small search space.

For reference the OpenBSD srandomdev() code tried to read from /dev/arandom/, and failing that would use the very less strong gettimeofday().



USES

  malloc()  // librock_srandom if argument is 0
  ldiv      // librock_srandom
  memcpy    // librock_srandom if prand is not 0



LICENSE

 Copyright (c) 1983 Regents of the University of California.
  License text in <librock/license/bsdorig.txt> librock_LIDESC_HC=526b72abf87ca6429325f0b7b0ae8dab0986c030
  Licensed under BSD-ish license, NO WARRANTY. Copies must retain this block.
  Modifications Copyright (c) 2001 Forrest J. Cavalier III d-b-a Mib Software
  License text in <librock/license/librock.txt> librock_LIDESC_HC=12440211096131f5976d36be0cddca4cd9152e45

Source Code

./math/random/random.c (implementation, plus source of this manual page)

Tests and Supported Platform Types

This is a representative sample. Librock code is highly portable. For a particular platform not reported here, request paid support

librock_random passed tests in trandom (Unix/Linux/BSD: 2002/08/08 sys=FreeBSD using gcc)
librock_random passed tests in trandom_main (WIN32: 2002/08/08 sys=NT 4.0 using MSVC)
librock_srandom passed tests in trandom (Unix/Linux/BSD: 2002/08/08 sys=FreeBSD using gcc)
librock_srandom passed tests in trandom_main (WIN32: 2002/08/08 sys=NT 4.0 using MSVC)


This software is part of Librock

Rapid reuse, without rework. Details
This page copyright (C) 2002-2003 Forrest J. Cavalier III, d-b-a Mib Software, Saylorsburg PA 18353, USA

Verbatim copying and distribution of this generated page is permitted in any medium provided that no changes are made.
(The source of this manual page may be covered by a more permissive license which allows modifications.)

Want to help? We welcome comments, patches. -- Need help? Request paid support.