mathpaqs_20230121.0.0_773568e5/random/u_rand.ads

 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
--------------------------------------------------------------------------
-- The following is an implementation of a "universal" random number    --
-- generator algorithm developed by Dr. George Marsaglia of the         --
-- Supercomputer Computations Research Institute (SCRI) at Florida      --
-- State University.  This generator has a period of ~2**144 and has    --
-- been tailored for reproducibility in all CPU's with at least         --
-- 16 bit integer arithmetic and 24 bit floating point.  This algorithm --
-- does not generate random numbers < 2**-24.  At the end of this file  --
-- you will find a self test program that checks generated results      --
-- against known expected results and reports any inaccuracies.         --
--                                                                      --
-- Further references: "Toward a Universal Random Number Generator",    --
-- appearing in the Journal of The American Statistical Association.    --
--                                                                      --
-- This code appeared in the March/April publication of SIGAda's        --
-- Ada Letters and is considered public domain.  PCK                    --
--------------------------------------------------------------------------
--
-- Jul-2009: GdM: - Made generic and task safe: no more globals
--                - Procedure name aliases to make the replacement
--                  of Ada95+'s Ada.Numerics.Float_Random easy.
-- Mar-1988: Published in Ada Letters (Volume VIII, Number 2)

generic
    type Real is digits <>;

package U_Rand is

    subtype Uniformly_Distributed is Real range 0.0 .. 1.0;
    --
    -- ^ also useful to have a type to refer to, when using
    --   this random generator instead of Ada.Numerics.Float_Random

    M1 : constant := 179 ;
    M2 : constant := M1 - 10 ;

    subtype SEED_RANGE_1 is Integer range 1..M1-1 ;
    subtype SEED_RANGE_2 is Integer range 1..M2-1 ;

    Default_I : constant SEED_RANGE_1 := 12 ;
    Default_J : constant SEED_RANGE_1 := 34 ;
    Default_K : constant SEED_RANGE_1 := 56 ;
    Default_L : constant SEED_RANGE_1 := 78 ;

    type Generator is limited private;

    ----------------------------------------------------
    --  Initialization of the pseudo-random sequence  --
    ----------------------------------------------------

    --  Fixed seed initialization
    --
    procedure Start(Gen   : out Generator;
                    New_I : SEED_RANGE_1 := Default_I ;
                    New_J : SEED_RANGE_1 := Default_J ;
                    New_K : SEED_RANGE_1 := Default_K ;
                    New_L : SEED_RANGE_2 := Default_L
                    ) ;

    subtype Seed_range_for_Reset is Integer range 0 .. ((M1-1) ** 3) * (M2-1) - 1;
    --  NB: concretely, the range is: 0 .. 947'478'337

    --  Generator initialization, compatible with Ada 95+
    procedure Reset (Gen : out Generator; Initiator : Seed_range_for_Reset);

    --  Randomize with real-time clock
    --
    procedure Randomize (Gen : out Generator);
    procedure Reset (Gen : out Generator) renames Randomize; -- Ada 95+ style

    -----------------------------------------------
    --  Obtaining the next pseudo-random number  --
    -----------------------------------------------
    --
    function Next(Gen: Generator) return Uniformly_Distributed;
    pragma Inline(Next);
    function Random(Gen: Generator) return Uniformly_Distributed renames Next; -- Ada 95 style

private

    M3 : constant := 97 ;

    subtype RANGE_3 is Integer range 1..M3 ;
    type U_array is array(RANGE_3) of Real;

    type Generator is limited record
      NI, NJ : Integer ;
      C : Real ;
      U : U_array;
    end record;

end U_Rand ;