🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: gnu.g++.lib.bug
Article #411

Normal.cc may not be normal

#411
From: jimc
Date: Mon, 04 Jan 1993 08:46
76 lines
2550 bytes
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);
    }
}
Technical Details
Message-ID: <9301050046.AA06293@malibu.pic.ucla.edu>
Path: arc1-ca.pugleaf.net!sparky!uunet!zaphod.mps.ohio-state.edu!cis.ohio-state.edu!pic.ucla.edu!jimc

Show Full Headers
Complete Article Headers
Newsgroups: gnu.g++.lib.bug
Path: arc1-ca.pugleaf.net!sparky!uunet!zaphod.mps.ohio-state.edu!cis.ohio-state.edu!pic.ucla.edu!jimc
From: jimc@pic.ucla.edu
Subject: Normal.cc may not be normal
Message-ID: <9301050046.AA06293@malibu.pic.ucla.edu>
Sender: gnulists@ai.mit.edu
Organization: GNUs Not Usenet
Distribution: gnu
Date: Mon, 4 Jan 1993 08:46:18 GMT
Approved: bug-lib-g++@prep.ai.mit.edu
Lines: 78