pcg_random/
lib.rs

1use std::marker::PhantomData;
2
3use self::{
4	lcg::{Integer, Lcg, Parameters},
5	output::Output
6};
7
8pub mod lcg;
9pub mod output;
10pub mod variants;
11
12#[cfg(feature = "rand")]
13mod rand;
14
15#[derive(Clone, Debug, Eq, Hash, PartialEq)]
16pub struct Pcg<L, P, S, O> {
17	pub lcg: Lcg<L, S>,
18	pub output: PhantomData<(P, O)>
19}
20
21impl<L, P, S, O> Pcg<L, P, S, O>
22where
23	L: Copy + Default + Into<Parameters<S>>,
24	P: Output<S, O>,
25	S: Integer
26{
27	pub fn new(seed: S) -> Self {
28		Self::with_parameters(seed, L::default())
29	}
30}
31
32impl<L, P, S, O> Pcg<L, P, S, O>
33where
34	L: Copy + Into<Parameters<S>>,
35	P: Output<S, O>,
36	S: Integer
37{
38	pub fn with_parameters(seed: S, parameters: L) -> Self {
39		let increment = parameters.into().increment;
40
41		let mut lcg = Lcg {
42			state: if increment == S::ZERO { seed | S::ONE } else { seed.add(increment) },
43			parameters
44		};
45
46		let _ = lcg.generate();
47		Self { lcg, output: PhantomData }
48	}
49
50	pub fn current(&self) -> O {
51		P::output(self.lcg.current())
52	}
53
54	pub fn generate(&mut self) -> O {
55		let state = self.lcg.state;
56		let _ = self.lcg.generate();
57		P::output(state)
58	}
59
60	pub fn jump_forward(&mut self, steps: S) -> O {
61		let state = self.lcg.jump_forward(steps.sub(S::ONE));
62		let _ = self.lcg.generate();
63		P::output(state)
64	}
65
66	pub fn jump_backward(&mut self, steps: S) -> O {
67		let state = self.lcg.jump_backward(steps.add(S::ONE));
68		let _ = self.lcg.generate();
69		P::output(state)
70	}
71}
72
73#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
74pub struct DefaultLcgParameters<S>(PhantomData<S>);
75
76#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
77pub struct DefaultCheapLcgParameters<S>(PhantomData<S>);
78
79#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
80pub struct DefaultMcgParameters<S>(PhantomData<S>);
81
82#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
83pub struct DefaultCheapMcgParameters<S>(PhantomData<S>);
84
85macro_rules! impl_default_parameters {
86	($ty:ty, $mul:literal, $inc:literal) => {
87		impl_default_parameters!($ty, $mul, $inc, cheap_mul: $mul);
88	};
89
90	($ty:ty, $mul:literal, $inc:literal, cheap_mul: $cheap_mul:literal) => {
91		impl DefaultLcgParameters<$ty> {
92			#[inline]
93			pub const fn multiplier() -> $ty {
94				$mul
95			}
96
97			#[inline]
98			pub const fn increment() -> $ty {
99				$inc
100			}
101		}
102
103		impl From<DefaultLcgParameters<$ty>> for Parameters<$ty> {
104			#[inline]
105			fn from(_: DefaultLcgParameters<$ty>) -> Parameters<$ty> {
106				Parameters { multiplier: $mul, increment: $inc }
107			}
108		}
109
110		impl DefaultCheapLcgParameters<$ty> {
111			#[inline]
112			pub const fn multiplier() -> $ty {
113				$cheap_mul
114			}
115
116			#[inline]
117			pub const fn increment() -> $ty {
118				$inc
119			}
120		}
121
122		impl From<DefaultCheapLcgParameters<$ty>> for Parameters<$ty> {
123			#[inline]
124			fn from(_: DefaultCheapLcgParameters<$ty>) -> Parameters<$ty> {
125				Parameters { multiplier: $cheap_mul, increment: $inc }
126			}
127		}
128
129		impl DefaultMcgParameters<$ty> {
130			#[inline]
131			pub const fn multiplier() -> $ty {
132				$mul
133			}
134		}
135
136		impl From<DefaultMcgParameters<$ty>> for Parameters<$ty> {
137			#[inline]
138			fn from(_: DefaultMcgParameters<$ty>) -> Parameters<$ty> {
139				Parameters { multiplier: $mul, increment: 0 }
140			}
141		}
142
143		impl DefaultCheapMcgParameters<$ty> {
144			#[inline]
145			pub const fn multiplier() -> $ty {
146				$cheap_mul
147			}
148		}
149
150		impl From<DefaultCheapMcgParameters<$ty>> for Parameters<$ty> {
151			#[inline]
152			fn from(_: DefaultCheapMcgParameters<$ty>) -> Parameters<$ty> {
153				Parameters { multiplier: $cheap_mul, increment: 0 }
154			}
155		}
156	};
157}
158
159impl_default_parameters!(u8, 0x8d, 0x4d);
160impl_default_parameters!(u16, 0x321d, 0xbb75);
161impl_default_parameters!(u32, 0x2c9277b5, 0xac564b05);
162impl_default_parameters!(u64, 0x5851f42d4c957f2d, 0x14057b7ef767814f);
163
164impl_default_parameters!(
165	u128,
166	0x2360ed051fc65da44385df649fccf645,
167	0x5851f42d4c957f2d14057b7ef767814f,
168	cheap_mul: 0xda942042e4dd58b5
169);