home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
modula2
/
library
/
queuem2
/
normrng.mod
< prev
next >
Wrap
Text File
|
1989-08-02
|
6KB
|
175 lines
(* source: h:\modula\code\random\NormRNG.MOD v1.0b revised: 88.06.09
author: G.Greene, AGCS D/429 (NS/TS), 312/681-7783 created: 88.06.09
function:
This is the implementation code for a package which provides generators
of pseudo-random variates of the normal and related distributions in the
form of double-precision reals.
history:
88.06.09 1.0a initial release.
*)
IMPLEMENTATION MODULE NormRNG;
FROM MATHLIB IMPORT (*PROC*) Log, Exp, Sqrt;
FROM UnifRNG IMPORT (*PROC*) UniformVariate;
VAR
HaveSpare: BOOLEAN;
SpareValue: LONGREAL;
(* Return as the function value a normally-distributed LongReal value, with
mean=0 and standard deviation=1. If this function has previously been
invoked an even number of times (including zero), two values will be
generated. One value is returned; the other is saved for future use in
a static variable, local to this package (not exported). On alternate
invocations, the saved value will be returned. The local static boolean
variable HaveSpare is toggled to indicate the source of the next value.
The algorithm used is "algorithm P" in section 3.4.1 of "The Art of
Computer Programming: vol II (Knuth, 1969). Effectively, we start by
generating points (x, y) within a square with coordinates in (-1, +1).
Acceptable points for normal variate generation are those within the unit
circle [center at (0, 0), radius=1). Thus the condition S<1.0 will hold
pi/4 (>78.5%) of the time. More than 2 REPEAT loop repetitions will be
required less than 5% of the time.
*)
PROCEDURE StdNormalVariate ( ): LONGREAL;
VAR
X, Y, (* coordinates of point *)
S, (* distance of point (x, y) from (0, 0) *)
SFactor: LONGREAL; (* common factor for the two random variates *)
(* [2]
source: h:\modula\code\random\NormRNG.MOD v1.0b revised: 88.06.09 *)
BEGIN (* StdNormalVariate *)
IF HaveSpare THEN
HaveSpare := FALSE;
RETURN ( SpareValue );
ELSE
REPEAT
X := 2.0 * UniformVariate ( ) - 1.0;
Y := 2.0 * UniformVariate ( ) - 1.0;
S := X * X + Y * Y;
UNTIL S < 1.0;
(* NB: S>0, since X and Y cannot both be zero; ln(S)<0, since S<1 *)
SFactor := Sqrt ( -2.0 * Log ( S ) / S );
SpareValue := X * SFactor;
HaveSpare := TRUE;
RETURN Y * SFactor;
END;
END StdNormalVariate;
(* Return as the function value a normally-distributed real value, with
mean given by the first parameter, and standard deviation given by the
second parameter.
*)
PROCEDURE NormalVariate (
(*in*) Mean: REAL;
(*in*) StdDev: REAL ): LONGREAL;
BEGIN
RETURN LONGREAL ( Mean ) + LONGREAL ( StdDev ) * StdNormalVariate ( )
END NormalVariate;
(* Return as the function value a lognormally-distributed real value, with
location and shape parameters given by the function parameters. More
commonly, one would want to specify the mean and standard deviation of
the values. Since the computations involved in providing that form
for the parameters would substantially slow the process of generating
variates, a separate procedure, LognormalParameters, is provided below
to do the conversion once for a given distribution. The output values
from that procedure may then be used as the parameters for this one.
*)
PROCEDURE LognormalVariate (
(*in*) Location: REAL;
(*in*) Shape: REAL ): LONGREAL;
BEGIN
RETURN Exp ( LONGREAL ( Location ) +
LONGREAL ( Shape ) * StdNormalVariate ( ) );
END LognormalVariate;
(* [3]
source: h:\modula\code\random\NormRNG.MOD v1.0b revised: 88.06.09 *)
(* The expected value (variate mean) and standard deviation of values for a
lognormal distribution are given as the first and second parameters,
respectively. Set the third and fourth parameters to the corresponding
location and shape parameters for use with procedure LognormalVariate,
above.
*)
PROCEDURE LognormalParameters (
(*in*) Mean: REAL;
(*in*) StdDev: REAL;
(*out*) VAR Location: REAL;
(*out*) VAR Shape: REAL );
VAR
Variance: REAL;
BEGIN
Variance := REAL ( Log ( 1.0 +
LONGREAL ( StdDev * StdDev ) /
LONGREAL ( Mean * Mean ) ) );
Location := REAL ( Log ( LONGREAL ( Mean ) ) ) - Variance * 0.5;
Shape := REAL ( Sqrt ( LONGREAL ( Variance ) ) );
END LognormalParameters;
(* Return as the function value a Cauchy-distributed real value, with
location (median) and scale parameters given by the function parameters.
The implementation assumes that the StdNormalVariate function will not
generate two successive zero values. For the current implementation of
StdNormalVariate, this is equivalent to saying that UniformVariate will
not generate consecutive zero values.
*)
PROCEDURE CauchyVariate (
(*in*) Median: REAL;
(*in*) Scale: REAL ): LONGREAL;
VAR
Normal1,
Normal2,
StdCauchy: LONGREAL;
BEGIN
Normal1 := StdNormalVariate ( );
Normal2 := StdNormalVariate ( );
IF Normal1 = 0.0
THEN StdCauchy := Normal1 / Normal2
ELSE StdCauchy := Normal2 / Normal1;
END;
RETURN LONGREAL ( Median ) + StdCauchy * LONGREAL ( Scale );
END CauchyVariate;
BEGIN (* initialization *)
HaveSpare := FALSE;
SpareValue := 0.0;
END NormRNG.