• srand(0)

    From Michael Sanders@porkchop@invalid.foo to comp.lang.c on Mon Dec 22 08:48:10 2025
    From Newsgroup: comp.lang.c

    Is it incorrect to use 0 (zero) to seed srand()?

    int seed = (argc >= 2 && strlen(argv[1]) == 9)
    ? atoi(argv[1])
    : (int)(time(NULL) % 900000000 + 100000000);

    srand(seed);
    --
    :wq
    Mike Sanders
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From James Kuyper@jameskuyper@alumni.caltech.edu to comp.lang.c on Mon Dec 22 06:44:42 2025
    From Newsgroup: comp.lang.c

    On 2025-12-22 03:48, Michael Sanders wrote:
    Is it incorrect to use 0 (zero) to seed srand()?

    int seed = (argc >= 2 && strlen(argv[1]) == 9)
    ? atoi(argv[1])
    : (int)(time(NULL) % 900000000 + 100000000);

    srand(seed);

    No, why whould you think so?
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Mon Dec 22 13:18:19 2025
    From Newsgroup: comp.lang.c

    On 2025-12-22 12:44, James Kuyper wrote:
    On 2025-12-22 03:48, Michael Sanders wrote:
    Is it incorrect to use 0 (zero) to seed srand()?

    int seed = (argc >= 2 && strlen(argv[1]) == 9)
    ? atoi(argv[1])
    : (int)(time(NULL) % 900000000 + 100000000);

    srand(seed);

    No, why whould you think so?

    There's number sequence generators that produce 0 sequences if seeded
    with 0. And maybe the comment in 'man 3 rand', "If no seed value is
    provided, the rand() function is automatically seeded with a value
    of 1.", may have fostered his doubt.

    Janis

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From James Kuyper@jameskuyper@alumni.caltech.edu to comp.lang.c on Mon Dec 22 12:13:37 2025
    From Newsgroup: comp.lang.c

    On 2025-12-22 07:18, Janis Papanagnou wrote:
    On 2025-12-22 12:44, James Kuyper wrote:
    On 2025-12-22 03:48, Michael Sanders wrote:
    Is it incorrect to use 0 (zero) to seed srand()?

    int seed = (argc >= 2 && strlen(argv[1]) == 9)
    ? atoi(argv[1])
    : (int)(time(NULL) % 900000000 + 100000000);

    srand(seed);

    No, why whould you think so?

    There's number sequence generators that produce 0 sequences if seeded
    with 0. ...

    The details of how the seed affects the random number sequence are
    unspecified by the standard. I personally would consider a pseudo-random
    number generator to be quite defective if there were any seed that
    produced a constant output.

    ... And maybe the comment in 'man 3 rand', "If no seed value is
    provided, the rand() function is automatically seeded with a value
    of 1.", may have fostered his doubt.

    The C standard explains that as follows: "If rand is called before any
    calls to srand have been made, the same sequence shall be generated as
    when srand is first called with a seed value of 1." (7.24.2.2p2).

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Mon Dec 22 18:41:10 2025
    From Newsgroup: comp.lang.c

    On 2025-12-22 18:13, James Kuyper wrote:
    On 2025-12-22 07:18, Janis Papanagnou wrote:
    On 2025-12-22 12:44, James Kuyper wrote:
    On 2025-12-22 03:48, Michael Sanders wrote:
    Is it incorrect to use 0 (zero) to seed srand()?

    int seed = (argc >= 2 && strlen(argv[1]) == 9)
    ? atoi(argv[1])
    : (int)(time(NULL) % 900000000 + 100000000);

    srand(seed);

    No, why whould you think so?

    There's number sequence generators that produce 0 sequences if seeded
    with 0. ...

    The details of how the seed affects the random number sequence are unspecified by the standard. I personally would consider a pseudo-random number generator to be quite defective if there were any seed that
    produced a constant output.

    I wouldn't have mentioned that if there weren't a whole class of
    such functions that expose exactly that behavior by design. Have
    a look for PN-(Pseudo Noise-)generators and LFSR (Linear Feedback
    Shift Registers). These have been defined to produce random noise
    (bit pattern with good statistical distribution). With sophisticated
    generator polynomials they produce also sequences of maximum period;
    say, for N=31 a non-repeating sequence of length 2^N - 1. The one
    element that is missing from the sequence is the 0 (that reproduces
    itself).

    Technically you pick some bit-values from fixed positions (depending
    on the generator polynomial) of the register and xor the bits to shift
    the result into the register. Here's ad hoc an example...

    #include <stdio.h>
    #include <stdint.h>

    int main ()
    {
    uint32_t init = 0x00000038;
    uint32_t reg = init;
    uint32_t new_bit;
    int count = 0;
    do {
    new_bit = ((reg >> 2) + (reg >> 4) + (reg >> 6) + (reg >> 30))
    & 0x1;
    reg <<= 1;
    reg |= new_bit;
    reg &= 0x7fffffff;
    count++;
    } while (reg != init);
    printf ("period: %d\n", count);
    }


    Janis

    [...]

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Michael S@already5chosen@yahoo.com to comp.lang.c on Mon Dec 22 20:45:38 2025
    From Newsgroup: comp.lang.c

    On Mon, 22 Dec 2025 18:41:10 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 2025-12-22 18:13, James Kuyper wrote:
    On 2025-12-22 07:18, Janis Papanagnou wrote:
    On 2025-12-22 12:44, James Kuyper wrote:
    On 2025-12-22 03:48, Michael Sanders wrote:
    Is it incorrect to use 0 (zero) to seed srand()?

    int seed = (argc >= 2 && strlen(argv[1]) == 9)
    ? atoi(argv[1])
    : (int)(time(NULL) % 900000000 + 100000000);

    srand(seed);

    No, why whould you think so?

    There's number sequence generators that produce 0 sequences if
    seeded with 0. ...

    The details of how the seed affects the random number sequence are unspecified by the standard. I personally would consider a
    pseudo-random number generator to be quite defective if there were
    any seed that produced a constant output.

    I wouldn't have mentioned that if there weren't a whole class of
    such functions that expose exactly that behavior by design. Have
    a look for PN-(Pseudo Noise-)generators and LFSR (Linear Feedback
    Shift Registers). These have been defined to produce random noise
    (bit pattern with good statistical distribution). With sophisticated generator polynomials they produce also sequences of maximum period;
    say, for N=31 a non-repeating sequence of length 2^N - 1. The one
    element that is missing from the sequence is the 0 (that reproduces
    itself).

    Technically you pick some bit-values from fixed positions (depending
    on the generator polynomial) of the register and xor the bits to shift
    the result into the register. Here's ad hoc an example...

    #include <stdio.h>
    #include <stdint.h>

    int main ()
    {
    uint32_t init = 0x00000038;
    uint32_t reg = init;
    uint32_t new_bit;
    int count = 0;
    do {
    new_bit = ((reg >> 2) + (reg >> 4) + (reg >> 6) + (reg >>
    30)) & 0x1;
    reg <<= 1;
    reg |= new_bit;
    reg &= 0x7fffffff;
    count++;
    } while (reg != init);
    printf ("period: %d\n", count);
    }


    Janis

    [...]


    Pay attention that C Standard only requires for the same seed to always produces the same sequence. There is no requirement that different
    seeds have to produce different sequences.
    So, for generator in your example, implementation like below would be
    fully legal. Personally, I wouldn't even consider it as particularly
    poor quality:

    void srand(unsigned seed ) { init = seed | 1;}

    [O.T.]
    In practice, using LFSR for rand() is not particularly bright idea for different reason: LFSR is a reasonably good PRNG for a single bit, but
    not when you want to generate a group of 31 pseudo-random bits. In
    order to get 31 new bits, without predictable repetitions from the
    previous value, you would have to do 31 steps. That's slow! The process
    can be accelerate by generation of several bits at time via look up
    tables, but in order to get decent speed the table has to be rater big
    and using big tables in standard library is bad sportsmanship.

    It seems that overwhelming majority C RTLs use Linear Congruential
    Generators, probably because for Stanadard library compactness of both
    code and data is considered more important than very high speed (not
    that on modern HW LCGs are slow) or superior random properties of
    Mersenne Twisters.
    [/O.T]

    IMHO, decent PRNG with decent thread-safe interface (not POSIX
    imbecile rand_r() ) should have been part of the C Standard
    library at least since C11. But somehow it did not happen until now.


    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Kaz Kylheku@046-301-5902@kylheku.com to comp.lang.c on Mon Dec 22 19:16:06 2025
    From Newsgroup: comp.lang.c

    On 2025-12-22, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
    On 2025-12-22 18:13, James Kuyper wrote:
    On 2025-12-22 07:18, Janis Papanagnou wrote:
    On 2025-12-22 12:44, James Kuyper wrote:
    On 2025-12-22 03:48, Michael Sanders wrote:
    Is it incorrect to use 0 (zero) to seed srand()?

    int seed = (argc >= 2 && strlen(argv[1]) == 9)
    ? atoi(argv[1])
    : (int)(time(NULL) % 900000000 + 100000000);

    srand(seed);

    No, why whould you think so?

    There's number sequence generators that produce 0 sequences if seeded
    with 0. ...

    The details of how the seed affects the random number sequence are
    unspecified by the standard. I personally would consider a pseudo-random
    number generator to be quite defective if there were any seed that
    produced a constant output.

    I wouldn't have mentioned that if there weren't a whole class of
    such functions that expose exactly that behavior by design. Have
    a look for PN-(Pseudo Noise-)generators and LFSR (Linear Feedback
    Shift Registers).

    The entire class of LFRS's is not homogeneous in this way; it
    is possible for a Linear Boolean function to generate a nonzero
    out of zero inputs.

    The LFSR page in the Wikipedia references this definition:

    https://en.wikipedia.org/wiki/Linearity#Boolean_functions

    A Boolean linear function of the inputs x1, ... xn is
    a kind of polynomial with coefficients C0, C1, ... CN combined
    with the inputs using AND for multiplication, and XOR for addition:

    f(x1, ... xn) = C0 ^ (C1 & x1) ^ (C2 & x2) ^ .. ^ (Cn ^ xn)

    If c0 is chosen as 1, then we get a 1 output when all the x's are
    zero. (The article uses "b" for the parameters and "a" for the
    coefficients, which I'm not crazy about.)

    Also see the two conditions, given in the description, one of which has
    to be true for Boolean linearity. For condition (2) the remark is given
    that under that condition f(F, F, F, ... F) = T.

    So if we have a "condition 2" linear function, our LSFR avoids
    the behavior.

    I don't recall having paid attention to this exact material in the
    past so it is a "TIL" for me.

    #include <stdint.h>

    int main ()
    {
    uint32_t init = 0x00000038;
    uint32_t reg = init;
    uint32_t new_bit;
    int count = 0;
    do {
    new_bit = ((reg >> 2) + (reg >> 4) + (reg >> 6) + (reg >> 30))
    & 0x1;

    These could of course be XOR, without it making a difference; the least significant bit in a binary addition is the XOR of the LSB's of the
    inputs.

    reg <<= 1;
    reg |= new_bit;

    So to have that C0 = 1 coefficient in the linear function, we just make
    it "reg |= (new_bit ^ 1);".
    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Mon Dec 22 21:16:53 2025
    From Newsgroup: comp.lang.c

    On Mon, 22 Dec 2025 20:45:38 +0200, Michael S wrote:

    ... (not POSIX imbecile rand_r() ) ...

    Obsoleted in newer POSIX, I see.
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Mon Dec 22 22:19:56 2025
    From Newsgroup: comp.lang.c

    On 2025-12-22 19:45, Michael S wrote:
    [...]
    In practice, using LFSR for rand() is not particularly bright idea for different reason: LFSR is a reasonably good PRNG for a single bit, but
    not when you want to generate a group of 31 pseudo-random bits. [...]

    Please note that I've not suggested that.

    I had been merely answering your question concerning Michael's doubts...

    Is it incorrect to use 0 (zero) to seed srand()?
    No, why whould you think so?
    There's number sequence generators that produce 0 sequences if seeded
    with 0.

    Janis

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Mon Dec 22 22:35:35 2025
    From Newsgroup: comp.lang.c

    On 2025-12-22 20:16, Kaz Kylheku wrote:
    On 2025-12-22, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    [...]

    I don't recall having paid attention to this exact material in the
    past so it is a "TIL" for me.

    What does "TIL" mean?

    I actually had used PN-generators in the past; used it in a Pascal
    program to make statistical tests, and also in assembler for a DSP
    codec to create reproducible random payload data to compare after
    transmission. For that purpose it was the perfect choice.


    #include <stdint.h>

    int main ()
    {
    uint32_t init = 0x00000038;
    uint32_t reg = init;
    uint32_t new_bit;
    int count = 0;
    do {
    new_bit = ((reg >> 2) + (reg >> 4) + (reg >> 6) + (reg >> 30))
    & 0x1;

    These could of course be XOR, without it making a difference; the least significant bit in a binary addition is the XOR of the LSB's of the
    inputs.

    Actually the pluses are a remnant of my decades old piece of Pascal
    code that I wrote back then that I now just transcribed. The Pascal
    version I used back then didn't support XOR so I used the addition.
    Being in a boolean context I'd nowadays (in C) have rather written
    purely new_bit = ((reg>>2)^(reg>>4)^(reg>>6)^(reg>>30)) & 0x1;
    but since it's unimportant, as you say, I lazily left it as it was.

    Janis

    [...]

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Mon Dec 22 22:57:27 2025
    From Newsgroup: comp.lang.c

    On 2025-12-22 19:45, Michael S wrote:
    [...] LFSR is a reasonably good PRNG for a single bit, but
    not when you want to generate a group of 31 pseudo-random bits. In
    order to get 31 new bits, without predictable repetitions from the
    previous value, you would have to do 31 steps. That's slow! The process
    can be accelerate by generation of several bits at time via look up
    tables, but in order to get decent speed the table has to be rater big
    and using big tables in standard library is bad sportsmanship.

    Yes. But mind that the speed is also depending on what quality you
    need. For example; I used the PN-generator to create bit-sequences
    (as you also suggest). For another application both, PN-LFSR and
    LCG (that you mention below), were inacceptable; we used a cipher
    to create the random data. (If you compare the speed of creating
    the cipher to a bit-shift-register the latter looks really fast.)


    It seems that overwhelming majority C RTLs use Linear Congruential Generators, probably because for Stanadard library compactness of both
    code and data is considered more important than very high speed (not
    that on modern HW LCGs are slow) or superior random properties of
    Mersenne Twisters.

    For "standard applications" I always used the simple LCGs; simple
    and fast. Or whatever the tools or library provided; which were
    mostly anyway LCGs.

    Janis

    [...]

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From John McCue@jmclnx@gmail.com.invalid to comp.lang.c on Tue Dec 23 00:39:49 2025
    From Newsgroup: comp.lang.c

    Michael Sanders <porkchop@invalid.foo> wrote:
    Is it incorrect to use 0 (zero) to seed srand()?

    int seed = (argc >= 2 && strlen(argv[1]) == 9)
    ? atoi(argv[1])
    : (int)(time(NULL) % 900000000 + 100000000);

    srand(seed);


    I like to just read /dev/urandom when I need a random
    number. Seem easier and more portable across Linux &
    the *BSDs.

    int s;
    read(fd, &s, sizeof(int));
    --
    [t]csh(1) - "An elegant shell, for a more... civilized age."
    - Paraphrasing Star Wars
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Tue Dec 23 02:17:01 2025
    From Newsgroup: comp.lang.c

    On Tue, 23 Dec 2025 00:39:49 -0000 (UTC), John McCue wrote:

    I like to just read /dev/urandom when I need a random number. Seem
    easier and more portable across Linux & the *BSDs.

    Not to mention a lot stronger, cryptographically.
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Ike Naar@ike@sdf.org to comp.lang.c on Tue Dec 23 06:49:22 2025
    From Newsgroup: comp.lang.c

    On 2025-12-23, John McCue <jmclnx@gmail.com.invalid> wrote:
    Michael Sanders <porkchop@invalid.foo> wrote:
    Is it incorrect to use 0 (zero) to seed srand()?

    int seed = (argc >= 2 && strlen(argv[1]) == 9)
    ? atoi(argv[1])
    : (int)(time(NULL) % 900000000 + 100000000);

    srand(seed);


    I like to just read /dev/urandom when I need a random
    number. Seem easier and more portable across Linux &
    the *BSDs.

    int s;
    read(fd, &s, sizeof(int));

    srand takes an unsigned argument.

    unsigned s;
    read(fd, &s, sizeof s);
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Michael Sanders@porkchop@invalid.foo to comp.lang.c on Tue Dec 23 07:17:05 2025
    From Newsgroup: comp.lang.c

    On Mon, 22 Dec 2025 06:44:42 -0500, James Kuyper wrote:

    On 2025-12-22 03:48, Michael Sanders wrote:
    Is it incorrect to use 0 (zero) to seed srand()?

    int seed = (argc >= 2 && strlen(argv[1]) == 9)
    ? atoi(argv[1])
    : (int)(time(NULL) % 900000000 + 100000000);

    srand(seed);

    No, why whould you think so?

    Excuse my delayed reply James (net provider was down most of today).

    Well, I guess I did not expect such large differences between
    gcc & musl somehow (cant test with clang just yet). I understand the
    sequence is deterministic & likely still some differences with musl,
    yet I wrongly assumed it seems, the sequences would be the same...

    #include <stdio.h>
    #include <stdlib.h>

    int main(void) {
    srand(0);
    printf("%d\n", rand());
    return 0;
    }

    /*

    $ gcc -O2 -o rnd rnd.c && ./rnd
    1804289383

    $ musl-gcc -static -O2 -o rnd rnd.c && ./rnd
    2049033599

    */
    --
    :wq
    Mike Sanders
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Michael Sanders@porkchop@invalid.foo to comp.lang.c on Tue Dec 23 07:24:34 2025
    From Newsgroup: comp.lang.c

    On Mon, 22 Dec 2025 13:18:19 +0100, Janis Papanagnou wrote:

    There's number sequence generators that produce 0 sequences if seeded
    with 0. And maybe the comment in 'man 3 rand', "If no seed value is
    provided, the rand() function is automatically seeded with a value
    of 1.", may have fostered his doubt.

    Janis - naive question for you...

    How do I bring up *posix only* man pages using 3?

    I see no difference when invoking any of:

    man 3 srand
    or: man 3 posix srand
    or: man posix 3 srand

    What I'm doing wrong here?
    --
    :wq
    Mike Sanders
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Michael Sanders@porkchop@invalid.foo to comp.lang.c on Tue Dec 23 07:25:42 2025
    From Newsgroup: comp.lang.c

    On Tue, 23 Dec 2025 00:39:49 -0000 (UTC), John McCue wrote:

    I like to just read /dev/urandom when I need a random
    number. Seem easier and more portable across Linux &
    the *BSDs.

    int s;
    read(fd, &s, sizeof(int));

    Thanks John. Wish there was such a 'device' under Windows...
    --
    :wq
    Mike Sanders
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Tue Dec 23 08:25:59 2025
    From Newsgroup: comp.lang.c

    On 23/12/2025 08:17, Michael Sanders wrote:
    On Mon, 22 Dec 2025 06:44:42 -0500, James Kuyper wrote:

    On 2025-12-22 03:48, Michael Sanders wrote:
    Is it incorrect to use 0 (zero) to seed srand()?

    int seed = (argc >= 2 && strlen(argv[1]) == 9)
    ? atoi(argv[1])
    : (int)(time(NULL) % 900000000 + 100000000);

    srand(seed);

    No, why whould you think so?

    Excuse my delayed reply James (net provider was down most of today).

    Well, I guess I did not expect such large differences between
    gcc & musl somehow (cant test with clang just yet). I understand the
    sequence is deterministic & likely still some differences with musl,
    yet I wrongly assumed it seems, the sequences would be the same...

    #include <stdio.h>
    #include <stdlib.h>

    int main(void) {
    srand(0);
    printf("%d\n", rand());
    return 0;
    }

    /*

    $ gcc -O2 -o rnd rnd.c && ./rnd
    1804289383

    $ musl-gcc -static -O2 -o rnd rnd.c && ./rnd
    2049033599

    */


    It is not the compilers that are different, it is the C standard
    libraries that are different. gcc is a compiler, not a library, but you
    are probably using glibc with it by default. musl is a library, not a compiler. There is no reason to suppose that different C standard
    libraries use the same implementation of rand()and srand(), so no reason
    to suppose they would give the same sequences - though each on their own
    will give a deterministic pseudo-random sequence based on their seeds.

    If you swap gcc with clang you will get the same results - it will
    depend on whether you are linking with glibc, musl, or another C library.


    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Tue Dec 23 09:59:27 2025
    From Newsgroup: comp.lang.c

    On 2025-12-23 08:24, Michael Sanders wrote:
    On Mon, 22 Dec 2025 13:18:19 +0100, Janis Papanagnou wrote:

    There's number sequence generators that produce 0 sequences if seeded
    with 0. And maybe the comment in 'man 3 rand', "If no seed value is
    provided, the rand() function is automatically seeded with a value
    of 1.", may have fostered his doubt.

    Janis - naive question for you...

    How do I bring up *posix only* man pages using 3?

    Sorry, can't help you here. Maybe someone else can.

    Myself I only access the Unix man pages as they come,
    i.e. using either 'man entry' or 'man section entry'.
    The POSIX information is usually textually integrated
    in the man pages.


    I see no difference when invoking any of:

    man 3 srand

    That's what I'm doing, and I see, for example,

    ...
    HISTORY
    rand()
    srand()
    SVr4, 4.3BSD, C89, POSIX.1-2001.

    rand_r()
    POSIX.1-2001. Obsolete in POSIX.1-2008.
    ...

    Janis

    or: man 3 posix srand
    or: man posix 3 srand

    What I'm doing wrong here?


    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Michael S@already5chosen@yahoo.com to comp.lang.c on Tue Dec 23 11:18:55 2025
    From Newsgroup: comp.lang.c

    On Mon, 22 Dec 2025 22:57:27 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 2025-12-22 19:45, Michael S wrote:
    [...] LFSR is a reasonably good PRNG for a single bit, but
    not when you want to generate a group of 31 pseudo-random bits. In
    order to get 31 new bits, without predictable repetitions from the
    previous value, you would have to do 31 steps. That's slow! The
    process can be accelerate by generation of several bits at time via
    look up tables, but in order to get decent speed the table has to
    be rater big and using big tables in standard library is bad
    sportsmanship.

    Yes. But mind that the speed is also depending on what quality you
    need. For example; I used the PN-generator to create bit-sequences
    (as you also suggest). For another application both, PN-LFSR and
    LCG (that you mention below), were inacceptable; we used a cipher
    to create the random data. (If you compare the speed of creating
    the cipher to a bit-shift-register the latter looks really fast.)


    It seems that overwhelming majority C RTLs use Linear Congruential Generators, probably because for Stanadard library compactness of
    both code and data is considered more important than very high
    speed (not that on modern HW LCGs are slow) or superior random
    properties of Mersenne Twisters.

    For "standard applications" I always used the simple LCGs; simple
    and fast. Or whatever the tools or library provided; which were
    mostly anyway LCGs.

    Janis

    [...]


    When I need PRNG then I am typically not deeply concerned about size of
    its internal state. On the other hand, I don't want to care about
    potentially insufficient randomness of the output (not in crypto
    sense). On the 3rd hand, vectors that I generate with PRNG tend to be
    big and I don't like to wait, so I do care somewhat about speed.
    Those 3 factors together plus availability long ago made MT19937-64
    into my personal default PRNG of choice.

    MT19937-64 is available out of the box(*) in C++. But not in C,
    unfortunately.

    At higher theoretical level MT is a generalization of LFSR, but it is
    not obvious when one looks at implementation.

    ---------
    * - hidden behind unnecessary levels of abstraction that just make it
    harder to use, but that's another story.

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Tue Dec 23 10:54:23 2025
    From Newsgroup: comp.lang.c

    On 2025-12-23 10:18, Michael S wrote:

    When I need PRNG then I am typically not deeply concerned about size of
    its internal state. On the other hand, I don't want to care about
    potentially insufficient randomness of the output (not in crypto
    sense). On the 3rd hand, vectors that I generate with PRNG tend to be
    big and I don't like to wait, so I do care somewhat about speed.
    Those 3 factors together plus availability long ago made MT19937-64
    into my personal default PRNG of choice.

    I've never intensified my knowledge in direction of MT algorithms.


    MT19937-64 is available out of the box(*) in C++. But not in C, unfortunately.

    This is really strange given that the name ("Mersenne Twister") is
    that prominent.

    Looking that up I find at least "C" code for MT19937 in Wikipedia https://de.wikipedia.org/wiki/Mersenne-Twister
    It's based on 32 bit logic it seems; interpreting your "MT19937-64"
    I assume you're looking for a 64 bit based version?


    At higher theoretical level MT is a generalization of LFSR, but it is
    not obvious when one looks at implementation.

    Well, at least there's the 'mod' operations all based on powers of 2
    along with all the binary op's which suggests some (non-arithmetic) bit-register type of algorithm, but the multiplication with 0x9908b0df
    (5 * 513496723) - which I'd suppose be hard to realize as/with LFSR -
    may suggest some other generator type.

    Janis

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Bonita Montero@Bonita.Montero@gmail.com to comp.lang.c on Tue Dec 23 11:04:07 2025
    From Newsgroup: comp.lang.c

    Am 22.12.2025 um 09:48 schrieb Michael Sanders:
    Is it incorrect to use 0 (zero) to seed srand()?

    int seed = (argc >= 2 && strlen(argv[1]) == 9)
    ? atoi(argv[1])
    : (int)(time(NULL) % 900000000 + 100000000);

    srand(seed);

    Use mt19993_64 ! ;-)

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Michael =?ISO-8859-1?Q?B=E4uerle?=@michael.baeuerle@stz-e.de to comp.lang.c on Tue Dec 23 11:09:02 2025
    From Newsgroup: comp.lang.c

    Janis Papanagnou wrote:
    On 2025-12-23 08:24, Michael Sanders wrote:

    [...]
    How do I bring up *posix only* man pages using 3?

    Sorry, can't help you here. Maybe someone else can.

    Manual pages are for the implementation of the operating system.

    The current standard version can be viewed here: <https://pubs.opengroup.org/onlinepubs/9799919799/functions/srand.html>
    This is the older standard version, still containing rand_r(): <https://pubs.opengroup.org/onlinepubs/9699919799/functions/srand.html>
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Tue Dec 23 02:16:39 2025
    From Newsgroup: comp.lang.c

    Michael Sanders <porkchop@invalid.foo> writes:
    On Mon, 22 Dec 2025 13:18:19 +0100, Janis Papanagnou wrote:
    There's number sequence generators that produce 0 sequences if seeded
    with 0. And maybe the comment in 'man 3 rand', "If no seed value is
    provided, the rand() function is automatically seeded with a value
    of 1.", may have fostered his doubt.

    Janis - naive question for you...

    How do I bring up *posix only* man pages using 3?

    I see no difference when invoking any of:

    man 3 srand
    or: man 3 posix srand
    or: man posix 3 srand

    What I'm doing wrong here?

    On Debian, Ubuntu, and similar systems, you can install the
    "manpages-posix" (section 1) and "manpages-posix-dev" (sections 3
    and 7) packages. You can then view the POSIX man page for srand
    by typing any of:

    man 3posix srand
    man -s 3posix srand
    man srand.3posix

    I'd expect similar packages to be available on (some) other systems.
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Michael S@already5chosen@yahoo.com to comp.lang.c on Tue Dec 23 13:50:31 2025
    From Newsgroup: comp.lang.c

    On Tue, 23 Dec 2025 10:54:23 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 2025-12-23 10:18, Michael S wrote:

    When I need PRNG then I am typically not deeply concerned about
    size of its internal state. On the other hand, I don't want to care
    about potentially insufficient randomness of the output (not in
    crypto sense). On the 3rd hand, vectors that I generate with PRNG
    tend to be big and I don't like to wait, so I do care somewhat
    about speed. Those 3 factors together plus availability long ago
    made MT19937-64 into my personal default PRNG of choice.

    I've never intensified my knowledge in direction of MT algorithms.


    MT19937-64 is available out of the box(*) in C++. But not in C, unfortunately.

    This is really strange given that the name ("Mersenne Twister") is
    that prominent.

    Looking that up I find at least "C" code for MT19937 in Wikipedia https://de.wikipedia.org/wiki/Mersenne-Twister
    It's based on 32 bit logic it seems; interpreting your "MT19937-64"
    I assume you're looking for a 64 bit based version?


    "Available out of the box" in this sentence means "part of standard
    library".
    Of course, MT19937-64 is available as 'C' source. But that's one more source+header to copy from project to project. Unlike in C++ where it's
    always here.


    At higher theoretical level MT is a generalization of LFSR, but it
    is not obvious when one looks at implementation.

    Well, at least there's the 'mod' operations all based on powers of 2
    along with all the binary op's which suggests some (non-arithmetic) bit-register type of algorithm, but the multiplication with 0x9908b0df
    (5 * 513496723) - which I'd suppose be hard to realize as/with LFSR -
    may suggest some other generator type.

    Janis



    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Michael Sanders@porkchop@invalid.foo to comp.lang.c on Tue Dec 23 14:45:26 2025
    From Newsgroup: comp.lang.c

    On Tue, 23 Dec 2025 08:25:59 +0100, David Brown wrote:

    It is not the compilers that are different, it is the C standard
    libraries that are different. gcc is a compiler, not a library, but you
    are probably using glibc with it by default. musl is a library, not a compiler. There is no reason to suppose that different C standard
    libraries use the same implementation of rand()and srand(), so no reason
    to suppose they would give the same sequences - though each on their own will give a deterministic pseudo-random sequence based on their seeds.

    If you swap gcc with clang you will get the same results - it will
    depend on whether you are linking with glibc, musl, or another C library.

    Sure enough & thank you David - I appreciate your explanation.

    I see where my thinking was off now. You're 100% correct
    (I'm still learning as you noticed).
    --
    :wq
    Mike Sanders
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Michael Sanders@porkchop@invalid.foo to comp.lang.c on Tue Dec 23 14:47:59 2025
    From Newsgroup: comp.lang.c

    On Tue, 23 Dec 2025 02:16:39 -0800, Keith Thompson wrote:

    On Debian, Ubuntu, and similar systems, you can install the
    "manpages-posix" (section 1) and "manpages-posix-dev" (sections 3
    and 7) packages. You can then view the POSIX man page for srand
    by typing any of:

    man 3posix srand
    man -s 3posix srand
    man srand.3posix

    I'd expect similar packages to be available on (some) other systems.

    Great! Thanks Keith, you sir are a walking encyclopedia.
    --
    :wq
    Mike Sanders
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Michael Sanders@porkchop@invalid.foo to comp.lang.c on Tue Dec 23 14:49:28 2025
    From Newsgroup: comp.lang.c

    On Tue, 23 Dec 2025 11:09:02 +0100 (CET), Michael Bäuerle wrote:

    Manual pages are for the implementation of the operating system.

    The current standard version can be viewed here: <https://pubs.opengroup.org/onlinepubs/9799919799/functions/srand.html>
    This is the older standard version, still containing rand_r(): <https://pubs.opengroup.org/onlinepubs/9699919799/functions/srand.html>

    Thank you for the pointers, I appreciate your insight.
    --
    :wq
    Mike Sanders
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Michael Sanders@porkchop@invalid.foo to comp.lang.c on Tue Dec 23 14:55:59 2025
    From Newsgroup: comp.lang.c

    On Tue, 23 Dec 2025 02:17:01 -0000 (UTC), Lawrence D’Oliveiro wrote:

    On Tue, 23 Dec 2025 00:39:49 -0000 (UTC), John McCue wrote:

    I like to just read /dev/urandom when I need a random number. Seem
    easier and more portable across Linux & the *BSDs.

    Not to mention a lot stronger, cryptographically.

    No srand() combined with crypto on my end. Sounds like an invitation
    to get hacked from everything I've ever read about mixing the two.
    --
    :wq
    Mike Sanders
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From scott@scott@slp53.sl.home (Scott Lurndal) to comp.lang.c on Tue Dec 23 16:08:49 2025
    From Newsgroup: comp.lang.c

    Michael Sanders <porkchop@invalid.foo> writes:
    On Mon, 22 Dec 2025 13:18:19 +0100, Janis Papanagnou wrote:

    There's number sequence generators that produce 0 sequences if seeded
    with 0. And maybe the comment in 'man 3 rand', "If no seed value is
    provided, the rand() function is automatically seeded with a value
    of 1.", may have fostered his doubt.

    Janis - naive question for you...

    How do I bring up *posix only* man pages using 3?

    I see no difference when invoking any of:

    man 3 srand
    or: man 3 posix srand
    or: man posix 3 srand

    What I'm doing wrong here?

    You're looking in the wrong place.

    https://pubs.opengroup.org/onlinepubs/9799919799/

    Select <System Interface> in the top left frame,
    select (3) in the subsequent bottom left frame and
    select the interface name in the bottom left frame. The
    manual page will be in the right frame.

    https://pubs.opengroup.org/onlinepubs/9799919799/functions/rand.html
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From scott@scott@slp53.sl.home (Scott Lurndal) to comp.lang.c on Tue Dec 23 16:13:18 2025
    From Newsgroup: comp.lang.c

    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
    On 2025-12-23 08:24, Michael Sanders wrote:
    On Mon, 22 Dec 2025 13:18:19 +0100, Janis Papanagnou wrote:

    There's number sequence generators that produce 0 sequences if seeded
    with 0. And maybe the comment in 'man 3 rand', "If no seed value is
    provided, the rand() function is automatically seeded with a value
    of 1.", may have fostered his doubt.

    Janis - naive question for you...

    How do I bring up *posix only* man pages using 3?

    Sorry, can't help you here. Maybe someone else can.

    Myself I only access the Unix man pages as they come,
    i.e. using either 'man entry' or 'man section entry'.
    The POSIX information is usually textually integrated
    in the man pages.


    I see no difference when invoking any of:

    man 3 srand

    That's what I'm doing, and I see, for example,

    ...
    HISTORY
    rand()
    srand()
    SVr4, 4.3BSD, C89, POSIX.1-2001.

    Those interfaces were originally documented in the SVID
    (System V Interface Definition). The third edition (1989) states:

    "The function rand() uses a multiplicative congruential random-number
    generator with a period 2^32 that returns successive psuedo-random
    numbers in the range 0 to 32767."

    In the FUTURE DIRECTIONS section, it notes:

    "The algorithms used in rand() and srand() are obsolete and will
    be replaced with algorithms providing better pseudo-random characteristics
    in a future issue".

    There was never a fourth edition.

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From antispam@antispam@fricas.org (Waldek Hebisch) to comp.lang.c on Tue Dec 23 17:54:05 2025
    From Newsgroup: comp.lang.c

    Michael S <already5chosen@yahoo.com> wrote:
    On Mon, 22 Dec 2025 18:41:10 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 2025-12-22 18:13, James Kuyper wrote:
    On 2025-12-22 07:18, Janis Papanagnou wrote:
    On 2025-12-22 12:44, James Kuyper wrote:
    On 2025-12-22 03:48, Michael Sanders wrote:
    Is it incorrect to use 0 (zero) to seed srand()?

    int seed = (argc >= 2 && strlen(argv[1]) == 9)
    ? atoi(argv[1])
    : (int)(time(NULL) % 900000000 + 100000000);

    srand(seed);

    No, why whould you think so?

    There's number sequence generators that produce 0 sequences if
    seeded with 0. ...

    The details of how the seed affects the random number sequence are
    unspecified by the standard. I personally would consider a
    pseudo-random number generator to be quite defective if there were
    any seed that produced a constant output.

    I wouldn't have mentioned that if there weren't a whole class of
    such functions that expose exactly that behavior by design. Have
    a look for PN-(Pseudo Noise-)generators and LFSR (Linear Feedback
    Shift Registers). These have been defined to produce random noise
    (bit pattern with good statistical distribution). With sophisticated
    generator polynomials they produce also sequences of maximum period;
    say, for N=31 a non-repeating sequence of length 2^N - 1. The one
    element that is missing from the sequence is the 0 (that reproduces
    itself).

    Technically you pick some bit-values from fixed positions (depending
    on the generator polynomial) of the register and xor the bits to shift
    the result into the register. Here's ad hoc an example...

    #include <stdio.h>
    #include <stdint.h>

    int main ()
    {
    uint32_t init = 0x00000038;
    uint32_t reg = init;
    uint32_t new_bit;
    int count = 0;
    do {
    new_bit = ((reg >> 2) + (reg >> 4) + (reg >> 6) + (reg >>
    30)) & 0x1;
    reg <<= 1;
    reg |= new_bit;
    reg &= 0x7fffffff;
    count++;
    } while (reg != init);
    printf ("period: %d\n", count);
    }


    Janis

    [...]


    Pay attention that C Standard only requires for the same seed to always produces the same sequence. There is no requirement that different
    seeds have to produce different sequences.
    So, for generator in your example, implementation like below would be
    fully legal. Personally, I wouldn't even consider it as particularly
    poor quality:

    void srand(unsigned seed ) { init = seed | 1;}

    [O.T.]
    In practice, using LFSR for rand() is not particularly bright idea for different reason: LFSR is a reasonably good PRNG for a single bit, but
    not when you want to generate a group of 31 pseudo-random bits. In
    order to get 31 new bits, without predictable repetitions from the
    previous value, you would have to do 31 steps. That's slow! The process
    can be accelerate by generation of several bits at time via look up
    tables, but in order to get decent speed the table has to be rater big
    and using big tables in standard library is bad sportsmanship.

    It seems that overwhelming majority C RTLs use Linear Congruential Generators, probably because for Stanadard library compactness of both
    code and data is considered more important than very high speed (not
    that on modern HW LCGs are slow) or superior random properties of
    Mersenne Twisters.

    There is a paper "PCG: A Family of Simple Fast Space-Efficient
    Statistically Good Algorithms for Random Number Generation"
    by M. O’Neill where she gives a family of algorithms and runs
    several statistical tests against known algorithms. Mersenne
    Twister does not look good in tests. If you have enough (128) bits
    LCGs do pass tests. A bunch of generators with 64-bit state also
    passes tests. So the only reason to prefer Mersenne Twister is
    that it is implemented in available libraries. Otherwise it is
    not so good, have large state and needs more execution time
    than alternatives.
    --
    Waldek Hebisch
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From David Brown@david.brown@hesbynett.no to comp.lang.c on Tue Dec 23 19:15:24 2025
    From Newsgroup: comp.lang.c

    On 23/12/2025 15:45, Michael Sanders wrote:
    On Tue, 23 Dec 2025 08:25:59 +0100, David Brown wrote:

    It is not the compilers that are different, it is the C standard
    libraries that are different. gcc is a compiler, not a library, but you
    are probably using glibc with it by default. musl is a library, not a
    compiler. There is no reason to suppose that different C standard
    libraries use the same implementation of rand()and srand(), so no reason
    to suppose they would give the same sequences - though each on their own
    will give a deterministic pseudo-random sequence based on their seeds.

    If you swap gcc with clang you will get the same results - it will
    depend on whether you are linking with glibc, musl, or another C library.

    Sure enough & thank you David - I appreciate your explanation.

    I see where my thinking was off now. You're 100% correct
    (I'm still learning as you noticed).


    There are people who have been in this group for decades that still have trouble understanding the distinction between a C compiler, a C standard library, and a C implementation (which combines both). There are C
    compilers that have a standard library tightly attached or "built in" in
    the same product, and others which can work with a number of different C standard libraries. There are C standard libraries that only work with
    a single compiler, and others that are much more general - though you
    can't write a complete C standard library purely in fully portable C.
    And C compilers can implement standard library functions in the compiler itself (this is typically done for small functions like memcpy, or maths functions - things that can be significantly more efficient when handled inline by the compiler). There are many nuances involved - but you've
    found a clear way to show a difference between two common C libraries,
    so that's a good start.


    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From richard@richard@cogsci.ed.ac.uk (Richard Tobin) to comp.lang.c on Tue Dec 23 19:05:28 2025
    From Newsgroup: comp.lang.c

    In article <ycz2R.198208$79B9.129561@fx14.iad>,
    Scott Lurndal <slp53@pacbell.net> wrote:

    HISTORY
    rand()
    srand()
    SVr4, 4.3BSD, C89, POSIX.1-2001.

    Those interfaces were originally documented in the SVID
    (System V Interface Definition).

    Not "originally".

    The third edition (1989) states:

    "The function rand() uses a multiplicative congruential random-number
    generator with a period 2^32 that returns successive psuedo-random
    numbers in the range 0 to 32767."

    Unix 5th edition (page dated 1/15/73) says:

    Rand uses a multiplicative congruential random number generator to
    return successive pseudo-random numbers (in r0) in the range from 1
    to 2^15-1.

    (In those days they documented the assembler interface as well.)

    The SVID r3 text is almost identical to 7th edition's (1979).

    In the FUTURE DIRECTIONS section, it notes:

    "The algorithms used in rand() and srand() are obsolete and will
    be replaced with algorithms providing better pseudo-random characteristics
    in a future issue".

    There was never a fourth edition.

    There was, but it was post-Posix. Rather than having improved
    algorithms in [s]rand() it has "see also drand48".

    https://www.sco.com/developers/devspecs/vol1a.pdf

    -- Richard
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From John McCue@jmclnx@gmail.com.invalid to comp.lang.c on Tue Dec 23 20:37:42 2025
    From Newsgroup: comp.lang.c

    Ike Naar <ike@sdf.org> wrote:
    On 2025-12-23, John McCue <jmclnx@gmail.com.invalid> wrote:
    Michael Sanders <porkchop@invalid.foo> wrote:
    Is it incorrect to use 0 (zero) to seed srand()?

    int seed = (argc >= 2 && strlen(argv[1]) == 9)
    ? atoi(argv[1])
    : (int)(time(NULL) % 900000000 + 100000000);

    srand(seed);


    I like to just read /dev/urandom when I need a random
    number. Seem easier and more portable across Linux &
    the *BSDs.

    int s;
    read(fd, &s, sizeof(int));

    srand takes an unsigned argument.

    unsigned s;
    read(fd, &s, sizeof s);

    I am not quite sure what you are saying about srand(3).

    If you decide to read /dev/urandom, there is no need to
    call srand(3), the OS maintains random data itself. So
    read(2) will just return the random number of the type
    you want based upon the call.
    --
    [t]csh(1) - "An elegant shell, for a more... civilized age."
    - Paraphrasing Star Wars
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Michael S@already5chosen@yahoo.com to comp.lang.c on Wed Dec 24 00:08:24 2025
    From Newsgroup: comp.lang.c

    On Tue, 23 Dec 2025 17:54:05 -0000 (UTC)
    antispam@fricas.org (Waldek Hebisch) wrote:
    Michael S <already5chosen@yahoo.com> wrote:
    On Mon, 22 Dec 2025 18:41:10 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 2025-12-22 18:13, James Kuyper wrote:
    On 2025-12-22 07:18, Janis Papanagnou wrote:
    On 2025-12-22 12:44, James Kuyper wrote:
    On 2025-12-22 03:48, Michael Sanders wrote:
    Is it incorrect to use 0 (zero) to seed srand()?

    int seed = (argc >= 2 && strlen(argv[1]) == 9)
    ? atoi(argv[1])
    : (int)(time(NULL) % 900000000 + 100000000);

    srand(seed);

    No, why whould you think so?

    There's number sequence generators that produce 0 sequences if
    seeded with 0. ...

    The details of how the seed affects the random number sequence
    are unspecified by the standard. I personally would consider a
    pseudo-random number generator to be quite defective if there
    were any seed that produced a constant output.

    I wouldn't have mentioned that if there weren't a whole class of
    such functions that expose exactly that behavior by design. Have
    a look for PN-(Pseudo Noise-)generators and LFSR (Linear Feedback
    Shift Registers). These have been defined to produce random noise
    (bit pattern with good statistical distribution). With
    sophisticated generator polynomials they produce also sequences of
    maximum period; say, for N=31 a non-repeating sequence of length
    2^N - 1. The one element that is missing from the sequence is the
    0 (that reproduces itself).

    Technically you pick some bit-values from fixed positions
    (depending on the generator polynomial) of the register and xor
    the bits to shift the result into the register. Here's ad hoc an
    example...

    #include <stdio.h>
    #include <stdint.h>

    int main ()
    {
    uint32_t init = 0x00000038;
    uint32_t reg = init;
    uint32_t new_bit;
    int count = 0;
    do {
    new_bit = ((reg >> 2) + (reg >> 4) + (reg >> 6) + (reg >>
    30)) & 0x1;
    reg <<= 1;
    reg |= new_bit;
    reg &= 0x7fffffff;
    count++;
    } while (reg != init);
    printf ("period: %d\n", count);
    }


    Janis

    [...]


    Pay attention that C Standard only requires for the same seed to
    always produces the same sequence. There is no requirement that
    different seeds have to produce different sequences.
    So, for generator in your example, implementation like below would
    be fully legal. Personally, I wouldn't even consider it as
    particularly poor quality:

    void srand(unsigned seed ) { init = seed | 1;}

    [O.T.]
    In practice, using LFSR for rand() is not particularly bright idea
    for different reason: LFSR is a reasonably good PRNG for a single
    bit, but not when you want to generate a group of 31 pseudo-random
    bits. In order to get 31 new bits, without predictable repetitions
    from the previous value, you would have to do 31 steps. That's
    slow! The process can be accelerate by generation of several bits
    at time via look up tables, but in order to get decent speed the
    table has to be rater big and using big tables in standard library
    is bad sportsmanship.

    It seems that overwhelming majority C RTLs use Linear Congruential Generators, probably because for Stanadard library compactness of
    both code and data is considered more important than very high
    speed (not that on modern HW LCGs are slow) or superior random
    properties of Mersenne Twisters.

    There is a paper "PCG: A Family of Simple Fast Space-Efficient
    Statistically Good Algorithms for Random Number Generation"
    by M. O’Neill where she gives a family of algorithms and runs
    several statistical tests against known algorithms. Mersenne
    Twister does not look good in tests. If you have enough (128) bits
    LCGs do pass tests. A bunch of generators with 64-bit state also
    passes tests. So the only reason to prefer Mersenne Twister is
    that it is implemented in available libraries. Otherwise it is
    not so good, have large state and needs more execution time
    than alternatives.

    I don't know. Testing randomness is complicated matter.
    How can I be sure that L’Ecuyer and Simard’s TestU01 suite tests things that I personally care about and that it does not test things that are
    of no interest for me? Especially, the latter.
    Also, the TestU01 suit is made for generators with 32-bit output.
    M. O’Neill used ad hoc technique to make it applicable to generators
    with 64-bit output. Is this technique right? Or may be it put 64-bit
    PRNG at unfair disadvantage?
    Besides, I strongly disagree with at least one assertion made by
    O’Neill: "While security-related applications should
    use a secure generator, because we cannot always know the future
    contexts in which our code will be used, it seems wise for all
    applications to avoid generators that make discovering their entire
    internal state completely trivial."
    No, I know exactly what I am doing/ I know exactly that for my
    application easy discovery of complete state of PRNG is not a defect.
    Anyway, even if I am skeptical about her criticism of popular PRNGs, intuitively I agree with the constructive part of the article -
    medium-quality PRNG that feeds medium quality hash function can
    potentially produce very good fast PRNG with rather small internal
    state.
    On related note, I think that even simple counter fed into high quality
    hash function (not cryptographically high quality, far less than that)
    can produce excellent PRNG with even smaller internal state. But not
    very fast one. Although the speed depends on specifics of used
    computer. I can imagine computer that has low-latency Rijndael128
    instruction. On such computer, running counter through 3-4 rounds of
    Rijndael ill produce very good PRNG that is only 2-3 times slower than,
    for example, LCG 128/64.
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From James Kuyper@jameskuyper@alumni.caltech.edu to comp.lang.c on Tue Dec 23 18:29:58 2025
    From Newsgroup: comp.lang.c

    On 2025-12-23 06:50, Michael S wrote:
    On Tue, 23 Dec 2025 10:54:23 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 2025-12-23 10:18, Michael S wrote:
    ...
    MT19937-64 is available out of the box(*) in C++. But not in C,
    unfortunately.

    This is really strange given that the name ("Mersenne Twister") is
    that prominent.

    Looking that up I find at least "C" code for MT19937 in Wikipedia
    https://de.wikipedia.org/wiki/Mersenne-Twister
    It's based on 32 bit logic it seems; interpreting your "MT19937-64"
    I assume you're looking for a 64 bit based version?


    "Available out of the box" in this sentence means "part of standard
    library".

    Citation, please? I can find neither Mersenne nor "MT19937-64" anywhere
    in n5001.pdf, the latest draft version of the C++ standard that I have
    access to, which is dated 2024-12-17.
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Keith Thompson@Keith.S.Thompson+u@gmail.com to comp.lang.c on Tue Dec 23 16:30:16 2025
    From Newsgroup: comp.lang.c

    James Kuyper <jameskuyper@alumni.caltech.edu> writes:
    On 2025-12-23 06:50, Michael S wrote:
    On Tue, 23 Dec 2025 10:54:23 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 2025-12-23 10:18, Michael S wrote:
    ...
    MT19937-64 is available out of the box(*) in C++. But not in C,
    unfortunately.

    This is really strange given that the name ("Mersenne Twister") is
    that prominent.

    Looking that up I find at least "C" code for MT19937 in Wikipedia
    https://de.wikipedia.org/wiki/Mersenne-Twister
    It's based on 32 bit logic it seems; interpreting your "MT19937-64"
    I assume you're looking for a 64 bit based version?


    "Available out of the box" in this sentence means "part of standard
    library".

    Citation, please? I can find neither Mersenne nor "MT19937-64" anywhere
    in n5001.pdf, the latest draft version of the C++ standard that I have
    access to, which is dated 2024-12-17.

    N5001 29.5.4.3 [rand.eng.mers] "Class template mersenne_twister_engine".

    N5001 29.5.6 [rand.predef] "Engines and engine adaptors with predefined parameters" defines "mt19937" and "mt19937_64".

    Its description of the algorithm isn't very detailed, but it
    does impose some very specific requirements. For mt19937:
    "Required behavior: The 10000th consecutive invocation of a
    default-constructed object of type mt19937 produces the value
    4123659995.". For mt19937_64: "Required behavior: The 10000th
    consecutive invocation of a default-constructed object of type
    mt19937_64 produces the value 9981545732273789042."

    If we're going to discuss this in any more detail (rather than
    discussing random numbers in general), I suggest comp.lang.c++.

    As already mentioned, there are implementations of mt19937 for C,
    but unlike in C++ they aren't part of the standard library.
    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Wed Dec 24 02:02:59 2025
    From Newsgroup: comp.lang.c

    On Wed, 24 Dec 2025 00:08:24 +0200, Michael S wrote:

    Testing randomness is complicated matter.

    Impossible, really, if you define “random” as “Nobody can know what comes
    next”.
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From James Kuyper@jameskuyper@alumni.caltech.edu to comp.lang.c on Tue Dec 23 23:43:19 2025
    From Newsgroup: comp.lang.c

    On 2025-12-23 21:02, Lawrence D’Oliveiro wrote:
    On Wed, 24 Dec 2025 00:08:24 +0200, Michael S wrote:

    Testing randomness is complicated matter.

    Impossible, really, if you define “random” as “Nobody can know what comes
    next”.

    The quality of pseudo-random number generators can be measured, but you
    need to carefully define what you mean by "quality". The relevant
    measures can be different for different purposes. I've seen a randome
    number generator used in a context where the only relevant criteria was
    that the probability of each number occurring was equal. In that
    particular contest, a function that simply always returned the sequence
    0, 1, 2, ... RAND_MAX, and then started over again at the beginning
    would have been good enough. Most applications have somewhat stronger requirements :-)

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Wed Dec 24 05:34:40 2025
    From Newsgroup: comp.lang.c

    On Tue, 23 Dec 2025 23:43:19 -0500, James Kuyper wrote:

    On 2025-12-23 21:02, Lawrence D’Oliveiro wrote:

    On Wed, 24 Dec 2025 00:08:24 +0200, Michael S wrote:

    Testing randomness is complicated matter.

    Impossible, really, if you define “random” as “Nobody can know what
    comes next”.

    The quality of pseudo-random number generators can be measured, but you
    need to carefully define what you mean by "quality".

    That’s not exactly disagreeing with what I’m saying ...
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Tue Dec 23 21:44:04 2025
    From Newsgroup: comp.lang.c

    On 12/22/2025 12:48 AM, Michael Sanders wrote:
    Is it incorrect to use 0 (zero) to seed srand()?

    int seed = (argc >= 2 && strlen(argv[1]) == 9)
    ? atoi(argv[1])
    : (int)(time(NULL) % 900000000 + 100000000);

    srand(seed);


    Forgive me for C++, but this RNG of mine might be useful for detecting
    the state of a system:

    https://groups.google.com/g/comp.lang.c++/c/7u_rLgQe86k/m/fYU9SnuAFQAJ
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Wed Dec 24 06:16:51 2025
    From Newsgroup: comp.lang.c

    On Tue, 23 Dec 2025 07:25:42 -0000 (UTC), Michael Sanders wrote:

    Wish there was such a 'device' under Windows...

    You should get one if you install WSL2.
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Michael S@already5chosen@yahoo.com to comp.lang.c on Wed Dec 24 10:51:14 2025
    From Newsgroup: comp.lang.c

    On Tue, 23 Dec 2025 07:25:42 -0000 (UTC)
    Michael Sanders <porkchop@invalid.foo> wrote:

    On Tue, 23 Dec 2025 00:39:49 -0000 (UTC), John McCue wrote:

    I like to just read /dev/urandom when I need a random
    number. Seem easier and more portable across Linux &
    the *BSDs.

    int s;
    read(fd, &s, sizeof(int));

    Thanks John. Wish there was such a 'device' under Windows...


    There is.
    Windows XP/Vista/7: https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptgenrandom
    Win8 and later: https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom


    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c on Wed Dec 24 00:59:16 2025
    From Newsgroup: comp.lang.c

    On 12/24/2025 12:51 AM, Michael S wrote:
    On Tue, 23 Dec 2025 07:25:42 -0000 (UTC)
    Michael Sanders <porkchop@invalid.foo> wrote:

    On Tue, 23 Dec 2025 00:39:49 -0000 (UTC), John McCue wrote:

    I like to just read /dev/urandom when I need a random
    number. Seem easier and more portable across Linux &
    the *BSDs.

    int s;
    read(fd, &s, sizeof(int));

    Thanks John. Wish there was such a 'device' under Windows...


    There is.
    Windows XP/Vista/7: https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptgenrandom
    Win8 and later: https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom



    CSPRNG, vs an actual TRNG?
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From antispam@antispam@fricas.org (Waldek Hebisch) to comp.lang.c on Wed Dec 24 09:00:50 2025
    From Newsgroup: comp.lang.c

    Michael S <already5chosen@yahoo.com> wrote:
    On Tue, 23 Dec 2025 17:54:05 -0000 (UTC)
    antispam@fricas.org (Waldek Hebisch) wrote:

    Michael S <already5chosen@yahoo.com> wrote:
    On Mon, 22 Dec 2025 18:41:10 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 2025-12-22 18:13, James Kuyper wrote:
    On 2025-12-22 07:18, Janis Papanagnou wrote:
    On 2025-12-22 12:44, James Kuyper wrote:
    On 2025-12-22 03:48, Michael Sanders wrote:
    Is it incorrect to use 0 (zero) to seed srand()?

    int seed = (argc >= 2 && strlen(argv[1]) == 9)
    ? atoi(argv[1])
    : (int)(time(NULL) % 900000000 + 100000000);

    srand(seed);

    No, why whould you think so?

    There's number sequence generators that produce 0 sequences if
    seeded with 0. ...

    The details of how the seed affects the random number sequence
    are unspecified by the standard. I personally would consider a
    pseudo-random number generator to be quite defective if there
    were any seed that produced a constant output.

    I wouldn't have mentioned that if there weren't a whole class of
    such functions that expose exactly that behavior by design. Have
    a look for PN-(Pseudo Noise-)generators and LFSR (Linear Feedback
    Shift Registers). These have been defined to produce random noise
    (bit pattern with good statistical distribution). With
    sophisticated generator polynomials they produce also sequences of
    maximum period; say, for N=31 a non-repeating sequence of length
    2^N - 1. The one element that is missing from the sequence is the
    0 (that reproduces itself).

    Technically you pick some bit-values from fixed positions
    (depending on the generator polynomial) of the register and xor
    the bits to shift the result into the register. Here's ad hoc an
    example...

    #include <stdio.h>
    #include <stdint.h>

    int main ()
    {
    uint32_t init = 0x00000038;
    uint32_t reg = init;
    uint32_t new_bit;
    int count = 0;
    do {
    new_bit = ((reg >> 2) + (reg >> 4) + (reg >> 6) + (reg >>
    30)) & 0x1;
    reg <<= 1;
    reg |= new_bit;
    reg &= 0x7fffffff;
    count++;
    } while (reg != init);
    printf ("period: %d\n", count);
    }


    Janis

    [...]


    Pay attention that C Standard only requires for the same seed to
    always produces the same sequence. There is no requirement that
    different seeds have to produce different sequences.
    So, for generator in your example, implementation like below would
    be fully legal. Personally, I wouldn't even consider it as
    particularly poor quality:

    void srand(unsigned seed ) { init = seed | 1;}

    [O.T.]
    In practice, using LFSR for rand() is not particularly bright idea
    for different reason: LFSR is a reasonably good PRNG for a single
    bit, but not when you want to generate a group of 31 pseudo-random
    bits. In order to get 31 new bits, without predictable repetitions
    from the previous value, you would have to do 31 steps. That's
    slow! The process can be accelerate by generation of several bits
    at time via look up tables, but in order to get decent speed the
    table has to be rater big and using big tables in standard library
    is bad sportsmanship.

    It seems that overwhelming majority C RTLs use Linear Congruential
    Generators, probably because for Stanadard library compactness of
    both code and data is considered more important than very high
    speed (not that on modern HW LCGs are slow) or superior random
    properties of Mersenne Twisters.

    There is a paper "PCG: A Family of Simple Fast Space-Efficient
    Statistically Good Algorithms for Random Number Generation"
    by M. O’Neill where she gives a family of algorithms and runs
    several statistical tests against known algorithms. Mersenne
    Twister does not look good in tests. If you have enough (128) bits
    LCGs do pass tests. A bunch of generators with 64-bit state also
    passes tests. So the only reason to prefer Mersenne Twister is
    that it is implemented in available libraries. Otherwise it is
    not so good, have large state and needs more execution time
    than alternatives.


    I don't know. Testing randomness is complicated matter.
    How can I be sure that L’Ecuyer and Simard’s TestU01 suite tests things that I personally care about and that it does not test things that are
    of no interest for me? Especially, the latter.

    It is extremaly unlikely that TestU only tests things that are
    important to you. However, IMO value of such test is that
    generator which passes the test avoids several common traps.
    If any of them is relevant for you, generator will avoid it.
    Of course, you may have _very_ special situation with
    extremaly uncommon problem, but this is unlikely and anyway
    in such case you probably should extensively test generator
    that you want to use.

    Also, the TestU01 suit is made for generators with 32-bit output.
    M. O’Neill used ad hoc technique to make it applicable to generators
    with 64-bit output. Is this technique right? Or may be it put 64-bit
    PRNG at unfair disadvantage?

    My point of view is that generator can be used to generate long
    bistream. Then you can cut the bitstream and get number of
    desired size. Good tests should check that such usage leads
    to reasonable properties. So, fact that one generator produces
    32-bit pieces and other produces 64-bit pieces should be irrelevant
    to the test.

    Besides, I strongly disagree with at least one assertion made by
    O’Neill: "While security-related applications should
    use a secure generator, because we cannot always know the future
    contexts in which our code will be used, it seems wise for all
    applications to avoid generators that make discovering their entire
    internal state completely trivial."
    No, I know exactly what I am doing/ I know exactly that for my
    application easy discovery of complete state of PRNG is not a defect.

    O’Neill is not a prophet, ignore what she say it you think you
    know better (which is probably the above).

    Anyway, even if I am skeptical about her criticism of popular PRNGs, intuitively I agree with the constructive part of the article - medium-quality PRNG that feeds medium quality hash function can
    potentially produce very good fast PRNG with rather small internal
    state.

    She seem to care very much about having minimal possible state.
    That is may be nice on embeded systems, but in general I would
    happily accept slighty bigger state (say 256 bits). But if
    we can get good properties with very small state, then why not?
    After all looking at state and updating it takes code, so
    small state helps with having fast generator.

    Concerning Mersenne Twister, she is not the only one to
    criticise it. My personal opinion is that given large
    state and not so simple update Mersenne Twister would
    have to be very very good to justify its use. But it
    fails some tests, so does not look _better_ than other
    generators.

    On related note, I think that even simple counter fed into high quality
    hash function (not cryptographically high quality, far less than that)
    can produce excellent PRNG with even smaller internal state. But not
    very fast one. Although the speed depends on specifics of used
    computer. I can imagine computer that has low-latency Rijndael128 instruction. On such computer, running counter through 3-4 rounds of
    Rijndael ill produce very good PRNG that is only 2-3 times slower than,
    for example, LCG 128/64.

    Maybe.
    --
    Waldek Hebisch
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Michael S@already5chosen@yahoo.com to comp.lang.c on Wed Dec 24 12:12:11 2025
    From Newsgroup: comp.lang.c

    On Wed, 24 Dec 2025 09:00:50 -0000 (UTC)
    antispam@fricas.org (Waldek Hebisch) wrote:
    Michael S <already5chosen@yahoo.com> wrote:
    On Tue, 23 Dec 2025 17:54:05 -0000 (UTC)
    antispam@fricas.org (Waldek Hebisch) wrote:

    Michael S <already5chosen@yahoo.com> wrote:
    On Mon, 22 Dec 2025 18:41:10 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:


    Also, the TestU01 suit is made for generators with 32-bit output.
    M. O’Neill used ad hoc technique to make it applicable to generators
    with 64-bit output. Is this technique right? Or may be it put 64-bit
    PRNG at unfair disadvantage?

    My point of view is that generator can be used to generate long
    bistream. Then you can cut the bitstream and get number of
    desired size. Good tests should check that such usage leads
    to reasonable properties. So, fact that one generator produces
    32-bit pieces and other produces 64-bit pieces should be irrelevant
    to the test.

    What you say is correct in few use cases. But there are many uses
    cases (in field of testing of numeric code, probably, most of them)
    in which "less random" LS bits are acceptable.
    Not that I can see why it could be the case for MT19937-64, but it
    could apply to one of two of other 64-bit generators tested by O'Neill.
    Besides, I strongly disagree with at least one assertion made by
    O’Neill: "While security-related applications should
    use a secure generator, because we cannot always know the future
    contexts in which our code will be used, it seems wise for all
    applications to avoid generators that make discovering their entire internal state completely trivial."
    No, I know exactly what I am doing/ I know exactly that for my
    application easy discovery of complete state of PRNG is not a
    defect.

    O’Neill is not a prophet, ignore what she say it you think you
    know better (which is probably the above).

    Anyway, even if I am skeptical about her criticism of popular PRNGs, intuitively I agree with the constructive part of the article - medium-quality PRNG that feeds medium quality hash function can
    potentially produce very good fast PRNG with rather small internal
    state.

    She seem to care very much about having minimal possible state.
    That is may be nice on embeded systems, but in general I would
    happily accept slighty bigger state (say 256 bits). But if
    we can get good properties with very small state, then why not?
    After all looking at state and updating it takes code, so
    small state helps with having fast generator.

    Agreed.
    Concerning Mersenne Twister, she is not the only one to
    criticise it. My personal opinion is that given large
    state and not so simple update Mersenne Twister would
    have to be very very good to justify its use.
    One theoretical advantage of MT19937 is that it has period of astronomic proportions. Which means that one instance of PRNG could be
    de-multiplexed into millions or billions of sub-streams with no
    detectable degradation of the quality of each sub-stream.
    However I fail to see how de-multiplexing into more than ~ one
    thousand of sub-streams can be practical. And for the latter one does
    not need to be astronomical, something like period=2**96 would be
    fully sufficient with many bits to spare.
    So, in theory I agree with the criticism. But in practice I am not
    bothered by the size of MT state.
    But it
    fails some tests, so does not look _better_ than other
    generators.

    It would be interesting to find out what were those tests that failed.
    I wonder, if tests suit can run faster on multicore computer. I don't
    want to wait 5-6 hours just to find out that report does not provide an information that I am looking for.
    On related note, I think that even simple counter fed into high
    quality hash function (not cryptographically high quality, far less
    than that) can produce excellent PRNG with even smaller internal
    state. But not very fast one. Although the speed depends on
    specifics of used computer. I can imagine computer that has
    low-latency Rijndael128 instruction. On such computer, running
    counter through 3-4 rounds of Rijndael ill produce very good PRNG
    that is only 2-3 times slower than, for example, LCG 128/64.

    Maybe.

    May be I'd even test my hypothesis. Eventually. Except that, again, I
    am not thrilled by idea of waiting 6 hours for each result.
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From BGB@cr88192@gmail.com to comp.lang.c on Wed Dec 24 05:22:11 2025
    From Newsgroup: comp.lang.c

    On 12/23/2025 11:54 AM, Waldek Hebisch wrote:
    Michael S <already5chosen@yahoo.com> wrote:
    On Mon, 22 Dec 2025 18:41:10 +0100
    Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

    On 2025-12-22 18:13, James Kuyper wrote:
    On 2025-12-22 07:18, Janis Papanagnou wrote:
    On 2025-12-22 12:44, James Kuyper wrote:
    On 2025-12-22 03:48, Michael Sanders wrote:
    Is it incorrect to use 0 (zero) to seed srand()?

    int seed = (argc >= 2 && strlen(argv[1]) == 9)
    ? atoi(argv[1])
    : (int)(time(NULL) % 900000000 + 100000000);

    srand(seed);

    No, why whould you think so?

    There's number sequence generators that produce 0 sequences if
    seeded with 0. ...

    The details of how the seed affects the random number sequence are
    unspecified by the standard. I personally would consider a
    pseudo-random number generator to be quite defective if there were
    any seed that produced a constant output.

    I wouldn't have mentioned that if there weren't a whole class of
    such functions that expose exactly that behavior by design. Have
    a look for PN-(Pseudo Noise-)generators and LFSR (Linear Feedback
    Shift Registers). These have been defined to produce random noise
    (bit pattern with good statistical distribution). With sophisticated
    generator polynomials they produce also sequences of maximum period;
    say, for N=31 a non-repeating sequence of length 2^N - 1. The one
    element that is missing from the sequence is the 0 (that reproduces
    itself).

    Technically you pick some bit-values from fixed positions (depending
    on the generator polynomial) of the register and xor the bits to shift
    the result into the register. Here's ad hoc an example...

    #include <stdio.h>
    #include <stdint.h>

    int main ()
    {
    uint32_t init = 0x00000038;
    uint32_t reg = init;
    uint32_t new_bit;
    int count = 0;
    do {
    new_bit = ((reg >> 2) + (reg >> 4) + (reg >> 6) + (reg >>
    30)) & 0x1;
    reg <<= 1;
    reg |= new_bit;
    reg &= 0x7fffffff;
    count++;
    } while (reg != init);
    printf ("period: %d\n", count);
    }


    Janis

    [...]


    Pay attention that C Standard only requires for the same seed to always
    produces the same sequence. There is no requirement that different
    seeds have to produce different sequences.
    So, for generator in your example, implementation like below would be
    fully legal. Personally, I wouldn't even consider it as particularly
    poor quality:

    void srand(unsigned seed ) { init = seed | 1;}

    [O.T.]
    In practice, using LFSR for rand() is not particularly bright idea for
    different reason: LFSR is a reasonably good PRNG for a single bit, but
    not when you want to generate a group of 31 pseudo-random bits. In
    order to get 31 new bits, without predictable repetitions from the
    previous value, you would have to do 31 steps. That's slow! The process
    can be accelerate by generation of several bits at time via look up
    tables, but in order to get decent speed the table has to be rater big
    and using big tables in standard library is bad sportsmanship.

    It seems that overwhelming majority C RTLs use Linear Congruential
    Generators, probably because for Stanadard library compactness of both
    code and data is considered more important than very high speed (not
    that on modern HW LCGs are slow) or superior random properties of
    Mersenne Twisters.

    There is a paper "PCG: A Family of Simple Fast Space-Efficient
    Statistically Good Algorithms for Random Number Generation"
    by M. O’Neill where she gives a family of algorithms and runs
    several statistical tests against known algorithms. Mersenne
    Twister does not look good in tests. If you have enough (128) bits
    LCGs do pass tests. A bunch of generators with 64-bit state also
    passes tests. So the only reason to prefer Mersenne Twister is
    that it is implemented in available libraries. Otherwise it is
    not so good, have large state and needs more execution time
    than alternatives.


    A lot can depend on what one wants as well...

    Fast/Simple:
    seed=seed*65521+17;
    val=(seed>>16)&32767;

    At first glance, this approach seems random enough, but these type of
    RNGs have a type of repeating pattern that can become obvious, say, if
    using them to generate random noise images.



    Or, can also work OK (also fast/simple):
    seed=(seed<<1)^(~(seed>>7));
    val=(seed>>8)&32767;

    Some people seem to really like using lookup tables.

    64-bit multiply can potentially be very slow, and multiply in general
    isn't always cheap, so can make sense to avoid using it if not necessary.

    So, shift-and-XOR is fast, above approach is also trivially extended to
    64 bits.

    Its randomness can be improved somewhat (at the cost of speed), say:
    seed1=(seed1<<1)^(~(seed1>>13));
    seed2=(seed2<<3)^(~(seed2>>19));
    seed1^=seed2>>23;
    seed2^=seed1>>23;
    val=(seed1>>11)^(seed2>>11);
    val=(val^(val>>17))&32767;

    Where seed1 and seed2 are two 64-bit values.

    Not much formal testing here, mostly just sort of approaches that seemed
    to work OK IME.



    Had also noted that there are ways to do checksums that are a lot faster
    and simpler than more widespread algorithms and also seem to still do reasonably well at error detection.

    Say, for example:
    sum1=1; sum2=1;
    for(i=0; i<szWords; i++)
    { sum1+=data[i]; sum2+=sum1; }
    sum1=((uint32_t)sum1)+(sum1>>32);
    sum2=((uint32_t)sum2)+(sum2>>32);
    csum=sum1^sum2;

    Where, sum1/sum2 are 64-bit, and data is interpreted as 32-bit words,
    all unsigned.

    But, yeah...

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Michael Sanders@porkchop@invalid.foo to comp.lang.c on Wed Dec 24 15:21:11 2025
    From Newsgroup: comp.lang.c

    On Wed, 24 Dec 2025 06:16:51 -0000 (UTC), Lawrence D’Oliveiro wrote:

    Wish there was such a 'device' under Windows...

    You should get one if you install WSL2.

    To be fair there is the 'Windows entropy pool' & its
    non-deterministic too but its only available via API.
    --
    :wq
    Mike Sanders
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Ike Naar@ike@sdf.org to comp.lang.c on Wed Dec 24 15:22:47 2025
    From Newsgroup: comp.lang.c

    On 2025-12-23, John McCue <jmclnx@gmail.com.invalid> wrote:
    Ike Naar <ike@sdf.org> wrote:
    On 2025-12-23, John McCue <jmclnx@gmail.com.invalid> wrote:
    Michael Sanders <porkchop@invalid.foo> wrote:
    Is it incorrect to use 0 (zero) to seed srand()?

    int seed = (argc >= 2 && strlen(argv[1]) == 9)
    ? atoi(argv[1])
    : (int)(time(NULL) % 900000000 + 100000000);

    srand(seed);


    I like to just read /dev/urandom when I need a random
    number. Seem easier and more portable across Linux &
    the *BSDs.

    int s;
    read(fd, &s, sizeof(int));

    srand takes an unsigned argument.

    unsigned s;
    read(fd, &s, sizeof s);

    I am not quite sure what you are saying about srand(3).

    If you decide to read /dev/urandom, there is no need to
    call srand(3), the OS maintains random data itself. So
    read(2) will just return the random number of the type
    you want based upon the call.

    Sorry, my misunderstanding. I thought you wanted to use a random
    number (from /dev/urandom instead of time(NULL)) to seed srand().
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Michael Sanders@porkchop@invalid.foo to comp.lang.c on Wed Dec 24 15:28:24 2025
    From Newsgroup: comp.lang.c

    On Wed, 24 Dec 2025 10:51:14 +0200, Michael S wrote:

    On Tue, 23 Dec 2025 07:25:42 -0000 (UTC)
    Michael Sanders <porkchop@invalid.foo> wrote:

    On Tue, 23 Dec 2025 00:39:49 -0000 (UTC), John McCue wrote:

    I like to just read /dev/urandom when I need a random
    number. Seem easier and more portable across Linux &
    the *BSDs.

    int s;
    read(fd, &s, sizeof(int));

    Thanks John. Wish there was such a 'device' under Windows...


    There is.
    Windows XP/Vista/7: https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptgenrandom
    Win8 and later: https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom

    Was referring to the concept of a device in the same idiom of BSD/Linux/Apple...

    Something that is just as easy to use.
    --
    :wq
    Mike Sanders
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Michael Sanders@porkchop@invalid.foo to comp.lang.c on Wed Dec 24 15:41:13 2025
    From Newsgroup: comp.lang.c

    On Tue, 23 Dec 2025 21:44:04 -0800, Chris M. Thomasson wrote:

    On 12/22/2025 12:48 AM, Michael Sanders wrote:
    Is it incorrect to use 0 (zero) to seed srand()?

    int seed = (argc >= 2 && strlen(argv[1]) == 9)
    ? atoi(argv[1])
    : (int)(time(NULL) % 900000000 + 100000000);

    srand(seed);


    Forgive me for C++, but this RNG of mine might be useful for detecting
    the state of a system:

    https://groups.google.com/g/comp.lang.c++/c/7u_rLgQe86k/m/fYU9SnuAFQAJ

    My aims (mostly just learning my around C at this point)
    are *much* more simple. I needed something that is seed-able/deterministic/portable allowing the user a
    shot at replaying a round in a silly game I've been
    working on every now & again:

    int genseed(int seed_in) {
    if (seed_in >= 10000000) return seed_in;
    unsigned long t = (unsigned long)time(NULL);
    unsigned long c = (unsigned long)clock();
    return (int)(((t ^ c) % 80000000UL) + 10000000UL);
    }
    --
    :wq
    Mike Sanders
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Michael Sanders@porkchop@invalid.foo to comp.lang.c on Wed Dec 24 15:44:33 2025
    From Newsgroup: comp.lang.c

    On Tue, 23 Dec 2025 16:08:49 GMT, Scott Lurndal wrote:

    Michael Sanders <porkchop@invalid.foo> writes:
    On Mon, 22 Dec 2025 13:18:19 +0100, Janis Papanagnou wrote:

    There's number sequence generators that produce 0 sequences if seeded
    with 0. And maybe the comment in 'man 3 rand', "If no seed value is
    provided, the rand() function is automatically seeded with a value
    of 1.", may have fostered his doubt.

    Janis - naive question for you...

    How do I bring up *posix only* man pages using 3?

    I see no difference when invoking any of:

    man 3 srand
    or: man 3 posix srand
    or: man posix 3 srand

    What I'm doing wrong here?

    You're looking in the wrong place.

    https://pubs.opengroup.org/onlinepubs/9799919799/

    Select <System Interface> in the top left frame,
    select (3) in the subsequent bottom left frame and
    select the interface name in the bottom left frame. The
    manual page will be in the right frame.

    https://pubs.opengroup.org/onlinepubs/9799919799/functions/rand.html

    Thank you Scott.
    --
    :wq
    Mike Sanders
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Michael S@already5chosen@yahoo.com to comp.lang.c on Wed Dec 24 17:44:52 2025
    From Newsgroup: comp.lang.c

    On Wed, 24 Dec 2025 15:28:24 -0000 (UTC)
    Michael Sanders <porkchop@invalid.foo> wrote:

    On Wed, 24 Dec 2025 10:51:14 +0200, Michael S wrote:

    On Tue, 23 Dec 2025 07:25:42 -0000 (UTC)
    Michael Sanders <porkchop@invalid.foo> wrote:

    On Tue, 23 Dec 2025 00:39:49 -0000 (UTC), John McCue wrote:

    I like to just read /dev/urandom when I need a random
    number. Seem easier and more portable across Linux &
    the *BSDs.

    int s;
    read(fd, &s, sizeof(int));

    Thanks John. Wish there was such a 'device' under Windows...


    There is.
    Windows XP/Vista/7: https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptgenrandom
    Win8 and later: https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom


    Was referring to the concept of a device in the same idiom of BSD/Linux/Apple...

    Something that is just as easy to use.


    What is not easy in the functions referred above? You do the same
    couple of steps as on Unix: open device then read few bytes from it.
    Only names are different.


    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Michael Sanders@porkchop@invalid.foo to comp.lang.c on Wed Dec 24 16:17:03 2025
    From Newsgroup: comp.lang.c

    On Wed, 24 Dec 2025 17:44:52 +0200, Michael S wrote:

    On Wed, 24 Dec 2025 15:28:24 -0000 (UTC)
    Michael Sanders <porkchop@invalid.foo> wrote:

    On Wed, 24 Dec 2025 10:51:14 +0200, Michael S wrote:

    On Tue, 23 Dec 2025 07:25:42 -0000 (UTC)
    Michael Sanders <porkchop@invalid.foo> wrote:

    On Tue, 23 Dec 2025 00:39:49 -0000 (UTC), John McCue wrote:

    I like to just read /dev/urandom when I need a random
    number. Seem easier and more portable across Linux &
    the *BSDs.

    int s;
    read(fd, &s, sizeof(int));

    Thanks John. Wish there was such a 'device' under Windows...


    There is.
    Windows XP/Vista/7:
    https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptgenrandom
    Win8 and later:
    https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom


    Was referring to the concept of a device in the same idiom of
    BSD/Linux/Apple...

    Something that is just as easy to use.


    What is not easy in the functions referred above? You do the same
    couple of steps as on Unix: open device then read few bytes from it.
    Only names are different.

    Depends the toolkit no?

    Unix:
    $ head -c 8 /dev/urandom | od -An | tr -d ' '
    4fa2c3d17b9a8f12

    Windows:
    PS C:\Users\Bob>
    $bytes = New-Object byte[] 8 [System.Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($bytes) [Console]::Write($bytes | ForEach-Object { "{0:x2}" -f $_ })
    --
    :wq
    Mike Sanders
    es
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Wed Dec 24 17:53:54 2025
    From Newsgroup: comp.lang.c

    On 2025-12-24 17:17, Michael Sanders wrote:

    Unix:
    $ head -c 8 /dev/urandom | od -An | tr -d ' '
    4fa2c3d17b9a8f12

    Windows:
    PS C:\Users\Bob>
    $bytes = New-Object byte[] 8 [System.Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($bytes)
    [Console]::Write($bytes | ForEach-Object { "{0:x2}" -f $_ })

    Amazing! 8-o

    Or rather; frightening! ("The little Shop of Horrors")
    A mixture (best/worst) of all; OO, Functional, and Shell?

    What is that; "Powershell", or something else?
    (I've mostly ignored Windows during the past 20+ years.)

    Janis

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.c on Wed Dec 24 18:04:05 2025
    From Newsgroup: comp.lang.c

    On 2025-12-24 16:41, Michael Sanders wrote:

    My aims (mostly just learning my around C at this point)
    are *much* more simple. I needed something that is seed-able/deterministic/portable allowing the user a
    shot at replaying a round in a silly game I've been
    working on every now & again:

    int genseed(int seed_in) {
    if (seed_in >= 10000000) return seed_in;
    unsigned long t = (unsigned long)time(NULL);
    unsigned long c = (unsigned long)clock();
    return (int)(((t ^ c) % 80000000UL) + 10000000UL);
    }


    If you need a portable function across different platforms
    you may want to write an own random() function, code based
    on some simple, proven algorithm. Or borrow a piece of code
    from some existing public source code library.

    For "_replaying_ a round in a silly game" across platforms
    (or generally) you should not seed it with time() or other
    random factors (as shown in your code snippet).

    Janis

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From scott@scott@slp53.sl.home (Scott Lurndal) to comp.lang.c on Wed Dec 24 17:08:48 2025
    From Newsgroup: comp.lang.c

    Michael S <already5chosen@yahoo.com> writes:
    On Wed, 24 Dec 2025 15:28:24 -0000 (UTC)
    Michael Sanders <porkchop@invalid.foo> wrote:

    On Wed, 24 Dec 2025 10:51:14 +0200, Michael S wrote:

    On Tue, 23 Dec 2025 07:25:42 -0000 (UTC)
    Michael Sanders <porkchop@invalid.foo> wrote:

    On Tue, 23 Dec 2025 00:39:49 -0000 (UTC), John McCue wrote:

    I like to just read /dev/urandom when I need a random
    number. Seem easier and more portable across Linux &
    the *BSDs.

    int s;
    read(fd, &s, sizeof(int));

    Thanks John. Wish there was such a 'device' under Windows...


    There is.
    Windows XP/Vista/7:
    https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptgenrandom
    Win8 and later:
    https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom


    Was referring to the concept of a device in the same idiom of
    BSD/Linux/Apple...

    Something that is just as easy to use.


    What is not easy in the functions referred above? You do the same
    couple of steps as on Unix: open device then read few bytes from it.
    Only names are different.

    Even easier in the GCC; one can just generate the rdrand instruction directly for intel targets:

    unsigned int __builtin_ia32_rdrand16_step (unsigned short *);
    unsigned int __builtin_ia32_rdrand32_step (unsigned int *);
    unsigned int __builtin_ia32_rdrand64_step (unsigned long long *);

    ARM64 provides a system register (RNDR) which is accessible at
    all exception levels. The Neoverse implementations provide implementation-defined system registers that convert the
    read of the register into a bus transaction to a device which
    satisfies the random number request (set up by the boot firmware);
    so the characteristics of the hardware generator are specific to
    an implementation of a neoverse core.

    int __builtin_arm_rndr(uint64_t *val);
    int __builtin_arm_rndrrs(uint64_t *val);
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Michael Sanders@porkchop@invalid.foo to comp.lang.c on Wed Dec 24 17:27:32 2025
    From Newsgroup: comp.lang.c

    On Wed, 24 Dec 2025 17:53:54 +0100, Janis Papanagnou wrote:

    On 2025-12-24 17:17, Michael Sanders wrote:

    Unix:
    $ head -c 8 /dev/urandom | od -An | tr -d ' '
    4fa2c3d17b9a8f12

    Windows:
    PS C:\Users\Bob>
    $bytes = New-Object byte[] 8
    [System.Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($bytes)
    [Console]::Write($bytes | ForEach-Object { "{0:x2}" -f $_ })

    Amazing! 8-o

    Or rather; frightening! ("The little Shop of Horrors")
    A mixture (best/worst) of all; OO, Functional, and Shell?

    What is that; "Powershell", or something else?
    (I've mostly ignored Windows during the past 20+ years.)

    Janis

    Yes its Powershell. You nailed it spot on IMO its terrible Janis.
    *Speaking only for myself* it's: thick/crufty/oop/functional/shell
    all mashed together like sludge. Awful stuff.

    And plain old 'cmd.exe' (more or less the Windows equivalent
    of /bin/sh) has evolved oddly too with all its 'syntactical sugar'...

    witness: echo hello world? | | tr 'A-Za-z' 'N-ZA-Mn-za-m'

    vs.: <https://rosettacode.org/wiki/Rot-13#Batch_File>

    I'm breaking free from it =)

    This tool helps: <https://frippery.org/busybox/>
    --
    :wq
    Mike Sanders
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Michael Sanders@porkchop@invalid.foo to comp.lang.c on Wed Dec 24 17:33:23 2025
    From Newsgroup: comp.lang.c

    On Wed, 24 Dec 2025 17:27:32 -0000 (UTC), Michael Sanders wrote:

    witness: echo hello world? | | tr 'A-Za-z' 'N-ZA-Mn-za-m'

    typo, should be: echo hello world? | tr 'A-Za-z' 'N-ZA-Mn-za-m'
    --
    :wq
    Mike Sanders
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Michael S@already5chosen@yahoo.com to comp.lang.c on Wed Dec 24 20:16:22 2025
    From Newsgroup: comp.lang.c

    On Wed, 24 Dec 2025 17:33:23 -0000 (UTC)
    Michael Sanders <porkchop@invalid.foo> wrote:

    On Wed, 24 Dec 2025 17:27:32 -0000 (UTC), Michael Sanders wrote:

    witness: echo hello world? | | tr 'A-Za-z' 'N-ZA-Mn-za-m'

    typo, should be: echo hello world? | tr 'A-Za-z' 'N-ZA-Mn-za-m'


    I agree that Powershell is too complicated and too "wannabe real
    programming language" which makes it bad shell scripting language.
    Esp. so for quick throwaway scripts.

    However I don't quite understand what you find wrong with cmd.exe.
    Cryptic? May be. But I can not imagine shell scripting language which is
    not cryptic in some way.
    Has few limitations that one would not expect in shell script in 2025?
    Yes.
    set a= 1000000
    set /A ab= %a% * 1000
    1000000000
    set /A ab= %a% * 2000
    2000000000
    set /A ab= %a% * 3000
    -1294967296

    But cmd.exe language certainly is *not* over-complicated. Rather more
    like too primitive.

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Lawrence =?iso-8859-13?q?D=FFOliveiro?=@ldo@nz.invalid to comp.lang.c on Wed Dec 24 19:00:32 2025
    From Newsgroup: comp.lang.c

    On Wed, 24 Dec 2025 15:21:11 -0000 (UTC), Michael Sanders wrote:

    On Wed, 24 Dec 2025 06:16:51 -0000 (UTC), Lawrence D’Oliveiro wrote:

    Wish there was such a 'device' under Windows...

    You should get one if you install WSL2.

    To be fair there is the 'Windows entropy pool' & its
    non-deterministic too but its only available via API.

    You begin to see why Microsoft is supporting Linux more and more.
    --- Synchronet 3.21a-Linux NewsLink 1.2