1use crate::distributions::utils::FloatSIMDUtils;
12use crate::distributions::{Distribution, Standard};
13use crate::Rng;
14use core::mem;
15
16#[cfg(feature = "serde1")]
17use serde::{Serialize, Deserialize};
18
19#[derive(Clone, Copy, Debug)]
44#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
45pub struct OpenClosed01;
46
47#[derive(Clone, Copy, Debug)]
71#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
72pub struct Open01;
73
74
75#[doc(hidden)]
77pub trait IntoFloat {
78 type F;
79
80 fn into_float_with_exponent(self, exponent: i32) -> Self::F;
89}
90
91macro_rules! float_impls {
92 ($ty:ident, $uty:ident, $f_scalar:ident, $u_scalar:ty,
93 $fraction_bits:expr, $exponent_bias:expr) => {
94 impl IntoFloat for $uty {
95 type F = $ty;
96 #[inline(always)]
97 fn into_float_with_exponent(self, exponent: i32) -> $ty {
98 let exponent_bits: $u_scalar =
100 (($exponent_bias + exponent) as $u_scalar) << $fraction_bits;
101 $ty::from_bits(self | exponent_bits)
102 }
103 }
104
105 impl Distribution<$ty> for Standard {
106 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $ty {
107 let float_size = mem::size_of::<$f_scalar>() as u32 * 8;
111 let precision = $fraction_bits + 1;
112 let scale = 1.0 / ((1 as $u_scalar << precision) as $f_scalar);
113
114 let value: $uty = rng.gen();
115 let value = value >> (float_size - precision);
116 scale * $ty::cast_from_int(value)
117 }
118 }
119
120 impl Distribution<$ty> for OpenClosed01 {
121 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $ty {
122 let float_size = mem::size_of::<$f_scalar>() as u32 * 8;
126 let precision = $fraction_bits + 1;
127 let scale = 1.0 / ((1 as $u_scalar << precision) as $f_scalar);
128
129 let value: $uty = rng.gen();
130 let value = value >> (float_size - precision);
131 scale * $ty::cast_from_int(value + 1)
133 }
134 }
135
136 impl Distribution<$ty> for Open01 {
137 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $ty {
138 use core::$f_scalar::EPSILON;
142 let float_size = mem::size_of::<$f_scalar>() as u32 * 8;
143
144 let value: $uty = rng.gen();
145 let fraction = value >> (float_size - $fraction_bits);
146 fraction.into_float_with_exponent(0) - (1.0 - EPSILON / 2.0)
147 }
148 }
149 }
150}
151
152float_impls! { f32, u32, f32, u32, 23, 127 }
153float_impls! { f64, u64, f64, u64, 52, 1023 }
154
155
156#[cfg(test)]
157mod tests {
158 use super::*;
159 use crate::rngs::mock::StepRng;
160
161 const EPSILON32: f32 = ::core::f32::EPSILON;
162 const EPSILON64: f64 = ::core::f64::EPSILON;
163
164 macro_rules! test_f32 {
165 ($fnn:ident, $ty:ident, $ZERO:expr, $EPSILON:expr) => {
166 #[test]
167 fn $fnn() {
168 let mut zeros = StepRng::new(0, 0);
170 assert_eq!(zeros.gen::<$ty>(), $ZERO);
171 let mut one = StepRng::new(1 << 8 | 1 << (8 + 32), 0);
172 assert_eq!(one.gen::<$ty>(), $EPSILON / 2.0);
173 let mut max = StepRng::new(!0, 0);
174 assert_eq!(max.gen::<$ty>(), 1.0 - $EPSILON / 2.0);
175
176 let mut zeros = StepRng::new(0, 0);
178 assert_eq!(zeros.sample::<$ty, _>(OpenClosed01), 0.0 + $EPSILON / 2.0);
179 let mut one = StepRng::new(1 << 8 | 1 << (8 + 32), 0);
180 assert_eq!(one.sample::<$ty, _>(OpenClosed01), $EPSILON);
181 let mut max = StepRng::new(!0, 0);
182 assert_eq!(max.sample::<$ty, _>(OpenClosed01), $ZERO + 1.0);
183
184 let mut zeros = StepRng::new(0, 0);
186 assert_eq!(zeros.sample::<$ty, _>(Open01), 0.0 + $EPSILON / 2.0);
187 let mut one = StepRng::new(1 << 9 | 1 << (9 + 32), 0);
188 assert_eq!(one.sample::<$ty, _>(Open01), $EPSILON / 2.0 * 3.0);
189 let mut max = StepRng::new(!0, 0);
190 assert_eq!(max.sample::<$ty, _>(Open01), 1.0 - $EPSILON / 2.0);
191 }
192 };
193 }
194 test_f32! { f32_edge_cases, f32, 0.0, EPSILON32 }
195
196 macro_rules! test_f64 {
197 ($fnn:ident, $ty:ident, $ZERO:expr, $EPSILON:expr) => {
198 #[test]
199 fn $fnn() {
200 let mut zeros = StepRng::new(0, 0);
202 assert_eq!(zeros.gen::<$ty>(), $ZERO);
203 let mut one = StepRng::new(1 << 11, 0);
204 assert_eq!(one.gen::<$ty>(), $EPSILON / 2.0);
205 let mut max = StepRng::new(!0, 0);
206 assert_eq!(max.gen::<$ty>(), 1.0 - $EPSILON / 2.0);
207
208 let mut zeros = StepRng::new(0, 0);
210 assert_eq!(zeros.sample::<$ty, _>(OpenClosed01), 0.0 + $EPSILON / 2.0);
211 let mut one = StepRng::new(1 << 11, 0);
212 assert_eq!(one.sample::<$ty, _>(OpenClosed01), $EPSILON);
213 let mut max = StepRng::new(!0, 0);
214 assert_eq!(max.sample::<$ty, _>(OpenClosed01), $ZERO + 1.0);
215
216 let mut zeros = StepRng::new(0, 0);
218 assert_eq!(zeros.sample::<$ty, _>(Open01), 0.0 + $EPSILON / 2.0);
219 let mut one = StepRng::new(1 << 12, 0);
220 assert_eq!(one.sample::<$ty, _>(Open01), $EPSILON / 2.0 * 3.0);
221 let mut max = StepRng::new(!0, 0);
222 assert_eq!(max.sample::<$ty, _>(Open01), 1.0 - $EPSILON / 2.0);
223 }
224 };
225 }
226 test_f64! { f64_edge_cases, f64, 0.0, EPSILON64 }
227
228 #[test]
229 fn value_stability() {
230 fn test_samples<T: Copy + core::fmt::Debug + PartialEq, D: Distribution<T>>(
231 distr: &D, zero: T, expected: &[T],
232 ) {
233 let mut rng = crate::test::rng(0x6f44f5646c2a7334);
234 let mut buf = [zero; 3];
235 for x in &mut buf {
236 *x = rng.sample(&distr);
237 }
238 assert_eq!(&buf, expected);
239 }
240
241 test_samples(&Standard, 0f32, &[0.0035963655, 0.7346052, 0.09778172]);
242 test_samples(&Standard, 0f64, &[
243 0.7346051961657583,
244 0.20298547462974248,
245 0.8166436635290655,
246 ]);
247
248 test_samples(&OpenClosed01, 0f32, &[0.003596425, 0.73460525, 0.09778178]);
249 test_samples(&OpenClosed01, 0f64, &[
250 0.7346051961657584,
251 0.2029854746297426,
252 0.8166436635290656,
253 ]);
254
255 test_samples(&Open01, 0f32, &[0.0035963655, 0.73460525, 0.09778172]);
256 test_samples(&Open01, 0f64, &[
257 0.7346051961657584,
258 0.20298547462974248,
259 0.8166436635290656,
260 ]);
261 }
262}