From bothner@cygnus.com Mon Jan  4 14:53:41 1993
Status: RO
X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil]
	["3298" "Mon" "04" "January" "93" "22:53:41" "-0800" "bothner@cygnus.com" "bothner@cygnus.com" nil nil "Proposed change to Normal.cc" "^From:" nil nil "1"])
Received: from bruno.cs.colorado.edu by foobar.cs.Colorado.EDU with SMTP id AA01411
  (5.65c/IDA-1.4.4 for <grunwald@foobar.cs.colorado.edu>); Mon, 4 Jan 1993 23:53:47 -0700
Received: from relay1.UU.NET by bruno.cs.colorado.edu with SMTP id AA28639
  (5.65c/IDA-1.4.4 for <grunwald@cs.colorado.edu>); Mon, 4 Jan 1993 23:53:45 -0700
Received: from cygnus.com by relay1.UU.NET with SMTP 
	(5.61/UUNET-internet-primary) id AA09844; Tue, 5 Jan 93 01:53:42 -0500
Received: from localhost.cygnus.com by cygnus.com (4.1/SMI-4.1)
	id AA09692; Mon, 4 Jan 93 22:53:41 PST
Message-Id: <9301050653.AA09692@cygnus.com>
From: bothner@cygnus.com
To: grunwald@cs.colorado.edu
Subject: Proposed change to Normal.cc
Date: Mon, 04 Jan 93 22:53:41 -0800

Could I get a ruling as to whether this change is desirable?
	--Per
------- Forwarded Message

Return-Path: gnulists@ai.mit.edu
Return-Path: <gnulists@ai.mit.edu>
Received: from life.ai.mit.edu by cygnus.com (4.1/SMI-4.1)
	id AA05239; Mon, 4 Jan 93 19:07:11 PST
Received: from raisin-nut (raisin-nut.ai.mit.edu) by life.ai.mit.edu (4.1/AI-4.10) id AA14342; Mon, 4 Jan 93 22:07:01 EST
Received: by raisin-nut (4.1/AI-4.10) id AA12685; Mon, 4 Jan 93 22:06:44 EST
Resent-Date: Mon, 04 Jan 93 16:46:18 -0800
Resent-Message-Id: <9301050306.AA12685@raisin-nut>
Received: from julia.math.ucla.edu by life.ai.mit.edu (4.1/AI-4.10) id AA09078; Mon, 4 Jan 93 19:46:06 EST
Received: from malibu2.pic.ucla.edu by julia.math.ucla.edu via SMTP 
	(Sendmail 5.61/1.07) id AA15865; Mon, 4 Jan 93 16:46:19 -0800
Received: from localhost by malibu.pic.ucla.edu via SMTP 
	(Sendmail 5.61/1.07) id AA06293; Mon, 4 Jan 93 16:46:19 -0800
Message-Id: <9301050046.AA06293@malibu.pic.ucla.edu>
To: bug-lib-g++@prep.ai.mit.edu
Subject: Normal.cc may not be normal
Date: Mon, 04 Jan 93 16:46:18 -0800
>From: jimc@pic.ucla.edu
Sender: gnulists@ai.mit.edu
Resent-From: bug-lib-g++-request@prep.ai.mit.edu



Gnu g++ v2.3.2 for Sparc-Sun-SunOS 4.1.1.  libg++ v2.3.  

In Normal.cc, I am not sure that the given algorithm gives an exactly
normally distributed pair of results.  I have included a modification
implementing the Box-Muller algorithm, which is exact, at the cost of
a sin/cos evaluation.  

James F. Carter        (213) 825-2897
UCLA-Mathnet;  6221 MSA; 405 Hilgard Ave.; Los Angeles, CA, USA  90024-1555
Internet: jimc@math.ucla.edu            BITNET: jimc%math.ucla.edu@INTERBIT
UUCP:...!{ucsd,ames,ncar,gatech,purdue,rutgers,decvax,uunet}!math.ucla.edu!jimc

- ----------- From libg++.2.3/libg++/src/Normal.cc

double Normal::operator()()
{
    
    if (haveCachedNormal == 1) {
	haveCachedNormal = 0;
	return(cachedNormal * pStdDev + pMean );
    } else {
	
	for(;;) {
	    double u1 = pGenerator -> asDouble();
	    double u2 = pGenerator -> asDouble();
	    double v1 = 2 * u1 - 1;
	    double v2 = 2 * u2 - 1;
	    double w = (v1 * v1) + (v2 * v2);
	    
//
//	We actually generate two IID normal distribution variables.
//	We cache the one & return the other.
// 
	    if (w <= 1) {
		double y = sqrt( (-2 * log(w)) / w);
		double x1 = v1 * y;
		double x2 = v2 * y;
		
		haveCachedNormal = 1;
		cachedNormal = x2;
		return(x1 * pStdDev + pMean);
	    }
	}
    }
}

- ------------ Suggested change

// Reference: Ripley, Brian D.  Stochastic Simulation.  Wiley (NY) 1987.
// p. 54, algorithm 3.1, Box-Muller (not Mu\"ller).
double Normal::operator()()
{
    
    if (haveCachedNormal == 1) {
	haveCachedNormal = 0;
	return(cachedNormal * pStdDev + pMean );
    } else {

//	Get 2 flat random variables in 0..1.  Generator gives 0 <= u1 < 1.
	double u1 = pGenerator -> asDouble();
//	This one must never be zero.
	double u2;
	while (0.0 == (u2 = pGenerator -> asDouble())) /*null stmt*/;
	    
//
//	We actually generate two IID normal distribution variables.
//	We cache the one & return the other.
// 
	double th = 6.28318530717958648 * u1
	double r = sqrt(-2 * log(u2));
		
	haveCachedNormal = 1;
	cachedNormal = r * sin(th);
	return(pStdDev*r*cos(th) + pMean);
    }
}



------- End of Forwarded Message



