/*++ Copyright (c) 1989 Microsoft Corporation Module Name: Random.c Abstract: This module implements a simple random number generator Author: Gary Kimura [GaryKi] 26-May-1989 Environment: Pure utility routine Revision History: Vishnu Patankar [VishnuP] 12-Nov-2000 Added new random number generator RtlRandomEx() --*/ #include #if defined(ALLOC_PRAGMA) && defined(NTOS_KERNEL_RUNTIME) #pragma alloc_text(PAGE, RtlRandom) #endif #define Multiplier ((ULONG)(0x80000000ul - 19)) // 2**31 - 19 #define Increment ((ULONG)(0x80000000ul - 61)) // 2**31 - 61 #define Modulus ((ULONG)(0x80000000ul - 1)) // 2**31 - 1 #if !defined(NTOS_KERNEL_RUNTIME) ULONG RtlUniform ( IN OUT PULONG Seed ) /*++ Routine Description: A simple uniform random number generator, based on D.H. Lehmer's 1948 alrogithm. Arguments: Seed - Supplies a pointer to the random number generator seed. Return Value: ULONG - returns a random number uniformly distributed over [0..MAXLONG] --*/ { *Seed = ((Multiplier * (*Seed)) + Increment) % Modulus; return *Seed; } #endif #define UniformMacro(Seed) ( \ *Seed = (((Multiplier * (*Seed)) + Increment) % Modulus) \ ) extern ULONG RtlpRandomConstantVector[]; ULONG RtlRandom ( IN OUT PULONG Seed ) /*++ Routine Description: An every better random number generator based on MacLaren and Marsaglia. Arguments: Seed - Supplies a pointer to the random number generator seed. Return Value: ULONG - returns a random number uniformly distributed over [0..MAXLONG] --*/ { ULONG X; ULONG Y; ULONG j; ULONG Result; RTL_PAGED_CODE(); X = UniformMacro(Seed); Y = UniformMacro(Seed); j = Y % 128; Result = RtlpRandomConstantVector[j]; RtlpRandomConstantVector[j] = X; return Result; } extern ULONG RtlpRandomExAuxVarY; extern ULONG RtlpRandomExConstantVector[]; ULONG RtlRandomEx( IN OUT PULONG Seed ) /*++ Routine Description: This algorithm is preferred over RtlRandom() for two reasons: (a) it is faster than RtlRandom() since it saves one multiplication, one addition and one modulus operation. This almost doubles the performance since it halves the number of clocks even on a pipelined Integer Unit such as the P6/ia64 processors i.e. ~ 52% perf gain. Plain RtlRandom() suffers from a RAW data dependency that integer pipelines cannot exploit. (b) it produces better random numbers than RtlRandom() since the period of the random numbers generated is comparatively higher. The algorithm here is based on a paper by Carter Bays and S.D.Durham [ACM Trans. Math. Software 2, pp. 59-64]. Knuth's The Art of Computer Programming (Seminumerical Algorithms) outlines the algorithm with proofs to support claims (a) and (b) above. Arguments: Seed - Supplies a pointer to the random number generator seed. Return Value: ULONG - returns a random number uniformly distributed over [0..MAXLONG] --*/ { ULONG j; ULONG Result; RTL_PAGED_CODE(); j = RtlpRandomExAuxVarY % 128; RtlpRandomExAuxVarY = RtlpRandomExConstantVector[j]; Result = RtlpRandomExAuxVarY; RtlpRandomExConstantVector[j] = UniformMacro(Seed); return Result; }