delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2000/04/27/10:09:24

Message-Id: <200004271315.JAA03708@delorie.com>
From: "Dieter Buerssner" <buers AT gmx DOT de>
To: Martin Stromberg <Martin DOT Stromberg AT lu DOT erisoft DOT se>
Date: Thu, 27 Apr 2000 16:20:23 +0200
MIME-Version: 1.0
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

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)




- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019