summaryrefslogtreecommitdiffstats
path: root/private/ntos/rtl/random.c
blob: a5629862f3bc901f40a49c3fc002b859a088fb88 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/*++

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:

--*/

#include <ntrtlp.h>

#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 V[];

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 = V[j];

    V[j] = X;

    return Result;

}