@@ -376,30 +376,16 @@ public TimeSpan RandExponential(TimeSpan mean) {
376376 /// from two uniform random distributed values.
377377 /// </summary>
378378 /// <remarks>
379- /// A spare random variable is generated from the second uniformly
380- /// distributed value. Thus, the two calls to the uniform random number
381- /// generator will be made only every second call .
379+ /// Unlike <see cref="RandNormal(double, double)"/> this method does not
380+ /// make use of a spare random variable. It discards the spare and thus
381+ /// requires twice the number of calls to the underlying IRandom instance .
382382 /// </remarks>
383383 /// <param name="random">The random number generator to use.</param>
384384 /// <param name="mu">The mean of the normal distribution.</param>
385385 /// <param name="sigma">The standard deviation of the normal distribution.</param>
386386 /// <returns>A number that is normal distributed.</returns>
387387 public virtual double RandNormal ( IRandom random , double mu , double sigma ) {
388- if ( useSpareNormal ) {
389- useSpareNormal = false ;
390- return spareNormal * sigma + mu ;
391- } else {
392- double u , v , s ;
393- do {
394- u = random . NextDouble ( ) * 2 - 1 ;
395- v = random . NextDouble ( ) * 2 - 1 ;
396- s = u * u + v * v ;
397- } while ( s >= 1 || s == 0 ) ;
398- var mul = Math . Sqrt ( - 2.0 * Math . Log ( s ) / s ) ;
399- spareNormal = v * mul ;
400- useSpareNormal = true ;
401- return mu + sigma * u * mul ;
402- }
388+ return MarsagliaPolar ( random , mu , sigma , out _ ) ; // do not reuse the spare normal in this case, because it could be from a different RNG
403389 }
404390 /// <summary>
405391 /// Uses the Marsaglia polar method to generate a random variable
@@ -413,8 +399,25 @@ public virtual double RandNormal(IRandom random, double mu, double sigma) {
413399 /// <param name="mu">The mean of the normal distribution.</param>
414400 /// <param name="sigma">The standard deviation of the normal distribution.</param>
415401 /// <returns>A number that is normal distributed.</returns>
416- public double RandNormal ( double mu , double sigma ) {
417- return RandNormal ( Random , mu , sigma ) ;
402+ public virtual double RandNormal ( double mu , double sigma ) {
403+ if ( useSpareNormal ) {
404+ useSpareNormal = false ;
405+ return spareNormal * sigma + mu ;
406+ } else {
407+ useSpareNormal = true ;
408+ return MarsagliaPolar ( Random , mu , sigma , out spareNormal ) ;
409+ }
410+ }
411+ private double MarsagliaPolar ( IRandom random , double mu , double sigma , out double spare ) {
412+ double u , v , s ;
413+ do {
414+ u = random . NextDouble ( ) * 2 - 1 ;
415+ v = random . NextDouble ( ) * 2 - 1 ;
416+ s = u * u + v * v ;
417+ } while ( s > 1 || s == 0 ) ;
418+ var mul = Math . Sqrt ( - 2.0 * Math . Log ( s ) / s ) ;
419+ spare = v * mul ;
420+ return mu + sigma * u * mul ;
418421 }
419422
420423 /// <summary>
@@ -879,6 +882,9 @@ public Environment(DateTime initialDateTime, int randomSeed, TimeSpan? defaultSt
879882 }
880883
881884 protected static readonly double NormalMagicConst = 4 * Math . Exp ( - 0.5 ) / Math . Sqrt ( 2.0 ) ;
885+ public override double RandNormal ( double mu , double sigma ) {
886+ return RandNormal ( Random , mu , sigma ) ;
887+ }
882888 public override double RandNormal ( IRandom random , double mu , double sigma ) {
883889 double z , zz , u1 , u2 ;
884890 do {
0 commit comments