1 /*
2 ** This is a standalone module and exists independently of the original Rmath module.
3 ** As so it is being released under the Boost Software License 1.0.
4 ** Author: Chibisi Chima-Okereke
5 ** Date: 2017-08-08
6 **
7 */
8 
9 module rmathd.rng.rng;
10 
11 import std.random;
12 
13 static bool seedSet = false;
14 static bool userSeed = false;
15 static uint randomSeed = 0;
16 
17 void set_seed(uint _seed)
18 {
19 	randomSeed = _seed;
20 	userSeed = true;
21 	seedSet = false;
22 }
23 
24 void seed_set()
25 {
26 	seedSet = true;
27 }
28 
29 void get_seed(ref uint _seed)
30 {
31 	_seed = randomSeed;
32 }
33 
34 class RandomNumberGenerator{
35 	immutable(string) RNGName;
36 	this()
37 	{
38 		RNGName = "default";
39 	}
40 	this(immutable(string) name)
41 	{
42 		RNGName = name;
43 	}
44 }
45 class MT19937: RandomNumberGenerator
46 {
47 	immutable(string) RNGName;
48 	Mt19937 engine;
49 	this(){
50 		super("MT19937");
51 		RNGName = "MT19937";
52 	}
53 	this(immutable(string) name){
54 		super("MT19937");
55 		RNGName = "MT19937";
56 	}
57 }
58 class MT1993764: RandomNumberGenerator
59 {
60 	immutable(string) RNGName;
61 	Mt19937_64 engine;
62 	this(){
63 		super("MT1993764");
64 		RNGName = "MT1993764";
65 	}
66 	this(immutable(string) name){
67 		super("MT1993764");
68 		RNGName = "MT1993764";
69 	}
70 }
71 class MINSTDRAND: RandomNumberGenerator
72 {
73 	immutable(string) RNGName;
74 	MinstdRand engine;
75 	this(){
76 		super("MINSTDRAND");
77 		RNGName = "MINSTDRAND";
78 	}
79 	this(immutable(string) name){
80 		super("MINSTDRAND");
81 		RNGName = "MINSTDRAND";
82 	}
83 }
84 class MINSTDRAND0: RandomNumberGenerator
85 {
86 	immutable(string) RNGName;
87 	MinstdRand0 engine;
88 	this(){
89 		super("MINSTDRAND0");
90 		RNGName = "MINSTDRAND0";
91 	}
92 	this(immutable(string) name){
93 		super("MINSTDRAND0");
94 		RNGName = "MINSTDRAND0";
95 	}
96 }
97 
98 __gshared static RandomNumberGenerator threadRNG = new MT1993764();
99 
100 void setRNG(RNG: RandomNumberGenerator)(RNG rng)
101 {
102 	threadRNG = rng;
103 }
104 
105 immutable(string) gen_rand_num_code()
106 {
107 	return `if(!seedSet && userSeed){
108 		Rng.engine.seed(randomSeed);
109 		seed_set();
110 	}else if(!seedSet && !userSeed){
111 		Rng.engine.seed(unpredictableSeed);
112 		seed_set();
113 	}
114 	auto output = uniform!("[]", T, T)(lower, upper, Rng.engine);
115 	    return output;`;
116 }
117 
118 auto rand(T = double)(T lower = 0.0, T upper = 1.0)
119 {
120 	if(threadRNG.RNGName == "MT19937"){
121 	    MT19937 Rng = cast(MT19937)threadRNG;
122 	    mixin (gen_rand_num_code());
123 	}
124 	else if(threadRNG.RNGName == "MT1993764"){
125 		MT1993764 Rng = cast(MT1993764)threadRNG;
126 		mixin (gen_rand_num_code());
127 	}
128 	else if(threadRNG.RNGName == "MINSTDRAND"){
129 		MINSTDRAND Rng = cast(MINSTDRAND)threadRNG;
130 		mixin (gen_rand_num_code());
131 	}
132 	else if(threadRNG.RNGName == "MINSTDRAND0"){
133 		MINSTDRAND0 Rng = cast(MINSTDRAND0)threadRNG;
134 		mixin (gen_rand_num_code());
135 	}
136 	else{
137 		MT1993764 Rng = cast(MT1993764)threadRNG;
138 		mixin (gen_rand_num_code());
139 	}
140 }