* Rich Felker [2011-06-23 02:54:52 -0400]: > On Tue, Jun 21, 2011 at 03:46:40AM +0200, Szabolcs Nagy wrote: > > * Rich Felker [2011-06-08 19:58:10 -0400]: > > > > > > Importing external code, with major cleanups or rewrite: > > > - PRNG (random) > > > > i looked into this one > > these functions are rather useless > > imho the posix api definition is insane > > http://pubs.opengroup.org/onlinepubs/9699919799/functions/random.html > > > > i wrote something anyway > > see comments in the code: > > http://port70.net/~nsz/musl/prng > > I like this. A couple questions/requests: > > 1. Is this simple code really equivalent (aside from the missing > non-default-size code) to the ugly BSD code that's 100x bigger and > full of undefined behavior? :) > the historical bsd implementation used another lcg for both the <32byte statebuffer and seeding "modern" implementations seems to use the x = (7^5 * x) mod (2^31 - 1) park-miller generator for seeding (it makes the generator less predictable, with the lcg everything is mod 2^k so the numbers 'linearly depend' on the seed) (glibc freebsd openbsd.. all use the same code here) (they use overflowing signed ints and signed >>1 for whatever reason) (they discard the first 10*n rands which i forgot to do) (freebsd seems to use the park-miller generator even for random() in case of small state buffer, which is bad as it will produce uniform random in [0,2^31-2] not in [0,2^31-1]) i used lcg seeding for simplicity the lcg seeding is bad, but the generator does not have good statistical properties and the seeding method won't change that.. now i made all the compatibility changes (attached) the following produces identical output with glibc vs my code: #include #include int main() { char s[256]; int i,j; for (j = 8; j <= 256; j*=2) { initstate(1, s, j); for (i = 0; i < 10; i++) printf("%d %d %ld\n", j, i, random()); } return 0; } (if compatibility does not matter then a 64bit lcg could do the same job without much fuss: static unsigned long long init[] = {1}; unsigned long long *x = init; long random(void){ *x = (6364136223846793005* *x + 1442695040888963407); return *x >> 33; } etc) > 2. If you'd like me to include this in musl, can you please license it > (either LGPL v2.1+ or any LGPL-compatible/less-restrictive license > such as BSD). > ok license is "permission to use, copy, modify, and/or distribute this code for any purpose with or without fee is hereby granted. there is no warranty." so feel free to alter the code eg the parkmiller code might be better to do with uint64 multiplication instead of the div/mod hack to avoid overflow: return (unsigned long long)16807*x % 0x7fffffff; > 3. For future code contributions, please attach the code/patches to > the email rather than just including a link. That way the code being > referred to/discussed is visible even if the version on the website > changes or the website it taken down. > ok