Message-Id: <200004271315.JAA03708@delorie.com> From: "Dieter Buerssner" To: Martin Stromberg Date: Thu, 27 Apr 2000 16:20:23 +0200 MIME-Version: 1.0 Content-type: text/plain; charset=US-ASCII Content-transfer-encoding: 7BIT Subject: Re: rand() in libc CC: djgpp-workers AT delorie DOT com (DJGPP-WORKERS) In-reply-to: <200004271205.OAA00093@lws256.lu.erisoft.se> References: <200004270947 DOT FAA27604 AT delorie DOT com> from "Dieter Buerssner" at Apr 27, 2000 12:52:02 PM X-mailer: Pegasus Mail for Win32 (v3.12b) Reply-To: djgpp-workers AT delorie DOT com Errors-To: nobody AT delorie DOT com X-Mailing-List: djgpp-workers AT delorie DOT com X-Unsubscribes-To: listserv AT delorie DOT com Precedence: bulk On 27 Apr 00, at 14:05, Martin Stromberg wrote: > I'm interested in whether the rand48() functions behave approximately > as well as on other architectures/implementations, because I wrote > them from scratch and I didn't do any extensive testing (of lack of > knowledge how). mrand48 produces the same sequence of numbers, than a version I have coded. The multiplier and the additive term are the ones described in my linux man-page. Side note: A djgpp specific implementation of the code could yield in quite a speedup. (Instead of doing the multiplication "manually", unsigned long long * unsigned long long could be used. This would probabably result in 3 MULs. With a bit help, gcc may be able to optimize this to two multiplications. > In particular I wonder how the ones generating doubles > (drand48(), erand48()) behave, as I improvised most on them. My manpages don't document the method, that should be used, to create a [0,1[ double. If I understand your code correctly, you "mix" the bits of the three state variables. return (b16s2,b16s1,b16s0,b15s2,b15s1,b15s0, ..., b1s2,b1s1,b1s0)/2^48. (b16s2 is the most significant bit of s2, and so on ...) A more natural approach seems to me to just do s2*2^-16 + s1*2^-32 + s0*2^-48; Doing this with floating point arithmetics will always yield "exact" results, no rounding will be involved with binary floating point representation. Reason for my suggestion: s0 is not very random at all (period 2^16). With the "mixing method", information of s0 will creep into the most significant digits of the returned double. BTW. The "mixing method" would be preferable, when one wants to create a random double out of two independant call to some integer PRNG, that is known to have better high significant bits. When this mixing is really needed for the rand48 family, the loop can be optimized away by precalculating suitable constants. Something like return s2 *(2^-17+2^-20+...+2^-62) + s1*(2^-18+2^-21+...+2^-63) + s0*(2^-19+2^-22+...+2^-64) /* untested */ -- Regards, Dieter Buerssner Anyone who considers arithmetical methods of producing random numbers is, of course, in a state of sin. (John Louis von Neumann)