Date: Mon, 30 May 2016 11:12:54 -0500 From: Pedro Giffuni <pfg@FreeBSD.org> To: Bruce Evans <brde@optusnet.com.au>, "Andrey A. Chernov" <ache@freebsd.org> Cc: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: Re: svn commit: r300956 - head/lib/libc/stdlib Message-ID: <c9e9ddbc-8e53-366a-96c0-8195c3e0a6ac@FreeBSD.org> In-Reply-To: <20160530110541.I924@besplex.bde.org> References: <201605291357.u4TDv6No071840@repo.freebsd.org> <20160530110541.I924@besplex.bde.org>
next in thread | previous in thread | raw e-mail | index | archive | help
(Interesting discussion) On 05/29/16 21:17, Bruce Evans wrote: > On Sun, 29 May 2016, Andrey A. Chernov wrote: > >> Log: >> 1) Unifdef USE_WEAK_SEEDING since it is too obsolete to support and >> makes >> reading hard. > > Good. > >> 2) Instead of doing range transformation in each and every function >> here, >> do it single time directly in do_rand(). One "mod" operation overhead >> is not >> a big deal, but the code looks nicer and possible future functions >> additions >> or PRNG change do not miss range transformations neither have >> unneeded ones. > > The whole implementation is silly. It is manually optimized for 1980's > compilers. More below. > >> 3) Use POSIX argument types for visible functions (cosmetic). > > Not sure I like type changes. > >> Modified: head/lib/libc/stdlib/rand.c >> ============================================================================== >> >> --- head/lib/libc/stdlib/rand.c Sun May 29 12:21:54 2016 (r300955) >> +++ head/lib/libc/stdlib/rand.c Sun May 29 13:57:06 2016 (r300956) >> @@ -48,14 +48,6 @@ __FBSDID("$FreeBSD$"); >> static int >> do_rand(unsigned long *ctx) >> { >> -#ifdef USE_WEAK_SEEDING >> -/* >> - * Historic implementation compatibility. >> - * The random sequences do not vary much with the seed, >> - * even with overflowing. >> - */ >> - return ((*ctx = *ctx * 1103515245 + 12345) % ((u_long)RAND_MAX + >> 1)); > > This is a good implementation of a not very good LCG, made very bad by > botching RAND_MAX. The magic numbers except for RAND_MAX are copied > from the example in the C90 spec. I think they are good enough there. > The comment in at least the C99 spec says "// RAND_MAX assumed to be > 32767". This means that these magic numbers were chosen to work with > this value of RAND_MAX. (unsigned) longs are used to give a period > much longer than RAND_MAX and for technical reasons. Taking the modulo > to many fewer bits than the minimum of 32 for an unsigned long then > disguises the linearity. The BSD version almost completly breaks this > on arches with 32 bit longs by taking the modulo to 31 bits (mod 32 bits > would give complete breakage). Arches with 64-bit longs accidentally > work a bit better, by the coefficients are poorly chosen -- they should > be 64 bits and the arithmetic 128 bits. > FWIW, there are coefficients for a 64 bit LCG here: http://nuclear.llnl.gov/CNP/rng/rngman/node4.html It would be interesting to have a LCG optimized for modern platforms, even if we cannot produce more than 31 bits due to the standards. Pedro.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?c9e9ddbc-8e53-366a-96c0-8195c3e0a6ac>