1use core::time::Duration;
110use core::ops::{Range, RangeInclusive};
111
112use crate::distributions::float::IntoFloat;
113use crate::distributions::utils::{BoolAsSIMD, FloatAsSIMD, FloatSIMDUtils, WideningMultiply};
114use crate::distributions::Distribution;
115use crate::{Rng, RngCore};
116
117#[cfg(not(feature = "std"))]
118#[allow(unused_imports)] use crate::distributions::utils::Float;
120
121#[cfg(feature = "serde1")]
122use serde::{Serialize, Deserialize};
123
124#[derive(Clone, Copy, Debug, PartialEq)]
174#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
175#[cfg_attr(feature = "serde1", serde(bound(serialize = "X::Sampler: Serialize")))]
176#[cfg_attr(feature = "serde1", serde(bound(deserialize = "X::Sampler: Deserialize<'de>")))]
177pub struct Uniform<X: SampleUniform>(X::Sampler);
178
179impl<X: SampleUniform> Uniform<X> {
180 pub fn new<B1, B2>(low: B1, high: B2) -> Uniform<X>
183 where
184 B1: SampleBorrow<X> + Sized,
185 B2: SampleBorrow<X> + Sized,
186 {
187 Uniform(X::Sampler::new(low, high))
188 }
189
190 pub fn new_inclusive<B1, B2>(low: B1, high: B2) -> Uniform<X>
193 where
194 B1: SampleBorrow<X> + Sized,
195 B2: SampleBorrow<X> + Sized,
196 {
197 Uniform(X::Sampler::new_inclusive(low, high))
198 }
199}
200
201impl<X: SampleUniform> Distribution<X> for Uniform<X> {
202 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> X {
203 self.0.sample(rng)
204 }
205}
206
207pub trait SampleUniform: Sized {
215 type Sampler: UniformSampler<X = Self>;
217}
218
219pub trait UniformSampler: Sized {
230 type X;
232
233 fn new<B1, B2>(low: B1, high: B2) -> Self
239 where
240 B1: SampleBorrow<Self::X> + Sized,
241 B2: SampleBorrow<Self::X> + Sized;
242
243 fn new_inclusive<B1, B2>(low: B1, high: B2) -> Self
249 where
250 B1: SampleBorrow<Self::X> + Sized,
251 B2: SampleBorrow<Self::X> + Sized;
252
253 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X;
255
256 fn sample_single<R: Rng + ?Sized, B1, B2>(low: B1, high: B2, rng: &mut R) -> Self::X
276 where
277 B1: SampleBorrow<Self::X> + Sized,
278 B2: SampleBorrow<Self::X> + Sized,
279 {
280 let uniform: Self = UniformSampler::new(low, high);
281 uniform.sample(rng)
282 }
283
284 fn sample_single_inclusive<R: Rng + ?Sized, B1, B2>(low: B1, high: B2, rng: &mut R)
293 -> Self::X
294 where B1: SampleBorrow<Self::X> + Sized,
295 B2: SampleBorrow<Self::X> + Sized
296 {
297 let uniform: Self = UniformSampler::new_inclusive(low, high);
298 uniform.sample(rng)
299 }
300}
301
302impl<X: SampleUniform> From<Range<X>> for Uniform<X> {
303 fn from(r: ::core::ops::Range<X>) -> Uniform<X> {
304 Uniform::new(r.start, r.end)
305 }
306}
307
308impl<X: SampleUniform> From<RangeInclusive<X>> for Uniform<X> {
309 fn from(r: ::core::ops::RangeInclusive<X>) -> Uniform<X> {
310 Uniform::new_inclusive(r.start(), r.end())
311 }
312}
313
314
315pub trait SampleBorrow<Borrowed> {
321 fn borrow(&self) -> &Borrowed;
325}
326impl<Borrowed> SampleBorrow<Borrowed> for Borrowed
327where Borrowed: SampleUniform
328{
329 #[inline(always)]
330 fn borrow(&self) -> &Borrowed {
331 self
332 }
333}
334impl<'a, Borrowed> SampleBorrow<Borrowed> for &'a Borrowed
335where Borrowed: SampleUniform
336{
337 #[inline(always)]
338 fn borrow(&self) -> &Borrowed {
339 *self
340 }
341}
342
343pub trait SampleRange<T> {
348 fn sample_single<R: RngCore + ?Sized>(self, rng: &mut R) -> T;
350
351 fn is_empty(&self) -> bool;
353}
354
355impl<T: SampleUniform + PartialOrd> SampleRange<T> for Range<T> {
356 #[inline]
357 fn sample_single<R: RngCore + ?Sized>(self, rng: &mut R) -> T {
358 T::Sampler::sample_single(self.start, self.end, rng)
359 }
360
361 #[inline]
362 fn is_empty(&self) -> bool {
363 !(self.start < self.end)
364 }
365}
366
367impl<T: SampleUniform + PartialOrd> SampleRange<T> for RangeInclusive<T> {
368 #[inline]
369 fn sample_single<R: RngCore + ?Sized>(self, rng: &mut R) -> T {
370 T::Sampler::sample_single_inclusive(self.start(), self.end(), rng)
371 }
372
373 #[inline]
374 fn is_empty(&self) -> bool {
375 !(self.start() <= self.end())
376 }
377}
378
379
380#[derive(Clone, Copy, Debug, PartialEq)]
420#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
421pub struct UniformInt<X> {
422 low: X,
423 range: X,
424 z: X, }
426
427macro_rules! uniform_int_impl {
428 ($ty:ty, $unsigned:ident, $u_large:ident) => {
429 impl UniformInt<$ty> {
430 #[allow(unused)]
432 #[inline]
433 pub(crate) fn max(&self) -> $ty {
434 self.range.wrapping_sub(1).wrapping_add(self.low)
435 }
436 }
437
438 impl SampleUniform for $ty {
439 type Sampler = UniformInt<$ty>;
440 }
441
442 impl UniformSampler for UniformInt<$ty> {
443 type X = $ty;
449
450 #[inline] fn new<B1, B2>(low_b: B1, high_b: B2) -> Self
453 where
454 B1: SampleBorrow<Self::X> + Sized,
455 B2: SampleBorrow<Self::X> + Sized,
456 {
457 let low = *low_b.borrow();
458 let high = *high_b.borrow();
459 assert!(low < high, "Uniform::new called with `low >= high`");
460 UniformSampler::new_inclusive(low, high - 1)
461 }
462
463 #[inline] fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self
466 where
467 B1: SampleBorrow<Self::X> + Sized,
468 B2: SampleBorrow<Self::X> + Sized,
469 {
470 let low = *low_b.borrow();
471 let high = *high_b.borrow();
472 assert!(
473 low <= high,
474 "Uniform::new_inclusive called with `low > high`"
475 );
476 let unsigned_max = ::core::$u_large::MAX;
477
478 let range = high.wrapping_sub(low).wrapping_add(1) as $unsigned;
479 let ints_to_reject = if range > 0 {
480 let range = $u_large::from(range);
481 (unsigned_max - range + 1) % range
482 } else {
483 0
484 };
485
486 UniformInt {
487 low,
488 range: range as $ty,
490 z: ints_to_reject as $unsigned as $ty,
491 }
492 }
493
494 #[inline]
495 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
496 let range = self.range as $unsigned as $u_large;
497 if range > 0 {
498 let unsigned_max = ::core::$u_large::MAX;
499 let zone = unsigned_max - (self.z as $unsigned as $u_large);
500 loop {
501 let v: $u_large = rng.gen();
502 let (hi, lo) = v.wmul(range);
503 if lo <= zone {
504 return self.low.wrapping_add(hi as $ty);
505 }
506 }
507 } else {
508 rng.gen()
510 }
511 }
512
513 #[inline]
514 fn sample_single<R: Rng + ?Sized, B1, B2>(low_b: B1, high_b: B2, rng: &mut R) -> Self::X
515 where
516 B1: SampleBorrow<Self::X> + Sized,
517 B2: SampleBorrow<Self::X> + Sized,
518 {
519 let low = *low_b.borrow();
520 let high = *high_b.borrow();
521 assert!(low < high, "UniformSampler::sample_single: low >= high");
522 Self::sample_single_inclusive(low, high - 1, rng)
523 }
524
525 #[inline]
526 fn sample_single_inclusive<R: Rng + ?Sized, B1, B2>(low_b: B1, high_b: B2, rng: &mut R) -> Self::X
527 where
528 B1: SampleBorrow<Self::X> + Sized,
529 B2: SampleBorrow<Self::X> + Sized,
530 {
531 let low = *low_b.borrow();
532 let high = *high_b.borrow();
533 assert!(low <= high, "UniformSampler::sample_single_inclusive: low > high");
534 let range = high.wrapping_sub(low).wrapping_add(1) as $unsigned as $u_large;
535 if range == 0 {
538 return rng.gen();
539 }
540
541 let zone = if ::core::$unsigned::MAX <= ::core::u16::MAX as $unsigned {
542 let unsigned_max: $u_large = ::core::$u_large::MAX;
546 let ints_to_reject = (unsigned_max - range + 1) % range;
547 unsigned_max - ints_to_reject
548 } else {
549 (range << range.leading_zeros()).wrapping_sub(1)
552 };
553
554 loop {
555 let v: $u_large = rng.gen();
556 let (hi, lo) = v.wmul(range);
557 if lo <= zone {
558 return low.wrapping_add(hi as $ty);
559 }
560 }
561 }
562 }
563 };
564}
565
566uniform_int_impl! { i8, u8, u32 }
567uniform_int_impl! { i16, u16, u32 }
568uniform_int_impl! { i32, u32, u32 }
569uniform_int_impl! { i64, u64, u64 }
570uniform_int_impl! { i128, u128, u128 }
571uniform_int_impl! { isize, usize, usize }
572uniform_int_impl! { u8, u8, u32 }
573uniform_int_impl! { u16, u16, u32 }
574uniform_int_impl! { u32, u32, u32 }
575uniform_int_impl! { u64, u64, u64 }
576uniform_int_impl! { usize, usize, usize }
577uniform_int_impl! { u128, u128, u128 }
578
579impl SampleUniform for char {
580 type Sampler = UniformChar;
581}
582
583#[derive(Clone, Copy, Debug)]
593#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
594pub struct UniformChar {
595 #[cfg_attr(feature = "serde1", serde(deserialize_with = "deser_sampler"))]
596 sampler: UniformInt<u32>,
597}
598
599#[cfg(feature = "serde1")]
600fn deser_sampler<'de, D>(d: D) -> Result<UniformInt<u32>, D::Error>
601where
602D: serde::Deserializer<'de>,
603{
604 let sampler = <UniformInt<u32> as serde::Deserialize>::deserialize(d)?;
605 if sampler.max() > std::char::MAX as u32 - CHAR_SURROGATE_LEN {
606 return Err(serde::de::Error::custom(
607 "bad sampler range for UniformChar",
608 ));
609 }
610 Ok(sampler)
611}
612
613const CHAR_SURROGATE_START: u32 = 0xD800;
615const CHAR_SURROGATE_LEN: u32 = 0xE000 - CHAR_SURROGATE_START;
617
618fn char_to_comp_u32(c: char) -> u32 {
620 match c as u32 {
621 c if c >= CHAR_SURROGATE_START => c - CHAR_SURROGATE_LEN,
622 c => c,
623 }
624}
625
626impl UniformSampler for UniformChar {
627 type X = char;
628
629 #[inline] fn new<B1, B2>(low_b: B1, high_b: B2) -> Self
632 where
633 B1: SampleBorrow<Self::X> + Sized,
634 B2: SampleBorrow<Self::X> + Sized,
635 {
636 let low = char_to_comp_u32(*low_b.borrow());
637 let high = char_to_comp_u32(*high_b.borrow());
638 let sampler = UniformInt::<u32>::new(low, high);
639 UniformChar { sampler }
640 }
641
642 #[inline] fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self
645 where
646 B1: SampleBorrow<Self::X> + Sized,
647 B2: SampleBorrow<Self::X> + Sized,
648 {
649 let low = char_to_comp_u32(*low_b.borrow());
650 let high = char_to_comp_u32(*high_b.borrow());
651 let sampler = UniformInt::<u32>::new_inclusive(low, high);
652 UniformChar { sampler }
653 }
654
655 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
656 let mut x = self.sampler.sample(rng);
657 if x >= CHAR_SURROGATE_START {
658 x += CHAR_SURROGATE_LEN;
659 }
660 unsafe { core::char::from_u32_unchecked(x) }
664 }
665}
666
667#[derive(Clone, Copy, Debug, PartialEq)]
687#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
688pub struct UniformFloat<X> {
689 low: X,
690 scale: X,
691}
692
693macro_rules! uniform_float_impl {
694 ($ty:ty, $uty:ident, $f_scalar:ident, $u_scalar:ident, $bits_to_discard:expr) => {
695 impl SampleUniform for $ty {
696 type Sampler = UniformFloat<$ty>;
697 }
698
699 impl UniformSampler for UniformFloat<$ty> {
700 type X = $ty;
701
702 fn new<B1, B2>(low_b: B1, high_b: B2) -> Self
703 where
704 B1: SampleBorrow<Self::X> + Sized,
705 B2: SampleBorrow<Self::X> + Sized,
706 {
707 let low = *low_b.borrow();
708 let high = *high_b.borrow();
709 debug_assert!(
710 low.all_finite(),
711 "Uniform::new called with `low` non-finite."
712 );
713 debug_assert!(
714 high.all_finite(),
715 "Uniform::new called with `high` non-finite."
716 );
717 assert!(low.all_lt(high), "Uniform::new called with `low >= high`");
718 let max_rand = <$ty>::splat(
719 (::core::$u_scalar::MAX >> $bits_to_discard).into_float_with_exponent(0) - 1.0,
720 );
721
722 let mut scale = high - low;
723 assert!(scale.all_finite(), "Uniform::new: range overflow");
724
725 loop {
726 let mask = (scale * max_rand + low).ge_mask(high);
727 if mask.none() {
728 break;
729 }
730 scale = scale.decrease_masked(mask);
731 }
732
733 debug_assert!(<$ty>::splat(0.0).all_le(scale));
734
735 UniformFloat { low, scale }
736 }
737
738 fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self
739 where
740 B1: SampleBorrow<Self::X> + Sized,
741 B2: SampleBorrow<Self::X> + Sized,
742 {
743 let low = *low_b.borrow();
744 let high = *high_b.borrow();
745 debug_assert!(
746 low.all_finite(),
747 "Uniform::new_inclusive called with `low` non-finite."
748 );
749 debug_assert!(
750 high.all_finite(),
751 "Uniform::new_inclusive called with `high` non-finite."
752 );
753 assert!(
754 low.all_le(high),
755 "Uniform::new_inclusive called with `low > high`"
756 );
757 let max_rand = <$ty>::splat(
758 (::core::$u_scalar::MAX >> $bits_to_discard).into_float_with_exponent(0) - 1.0,
759 );
760
761 let mut scale = (high - low) / max_rand;
762 assert!(scale.all_finite(), "Uniform::new_inclusive: range overflow");
763
764 loop {
765 let mask = (scale * max_rand + low).gt_mask(high);
766 if mask.none() {
767 break;
768 }
769 scale = scale.decrease_masked(mask);
770 }
771
772 debug_assert!(<$ty>::splat(0.0).all_le(scale));
773
774 UniformFloat { low, scale }
775 }
776
777 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
778 let value1_2 = (rng.gen::<$uty>() >> $bits_to_discard).into_float_with_exponent(0);
780
781 let value0_1 = value1_2 - 1.0;
784
785 value0_1 * self.scale + self.low
791 }
792
793 #[inline]
794 fn sample_single<R: Rng + ?Sized, B1, B2>(low_b: B1, high_b: B2, rng: &mut R) -> Self::X
795 where
796 B1: SampleBorrow<Self::X> + Sized,
797 B2: SampleBorrow<Self::X> + Sized,
798 {
799 let low = *low_b.borrow();
800 let high = *high_b.borrow();
801 debug_assert!(
802 low.all_finite(),
803 "UniformSampler::sample_single called with `low` non-finite."
804 );
805 debug_assert!(
806 high.all_finite(),
807 "UniformSampler::sample_single called with `high` non-finite."
808 );
809 assert!(
810 low.all_lt(high),
811 "UniformSampler::sample_single: low >= high"
812 );
813 let mut scale = high - low;
814 assert!(scale.all_finite(), "UniformSampler::sample_single: range overflow");
815
816 loop {
817 let value1_2 =
819 (rng.gen::<$uty>() >> $bits_to_discard).into_float_with_exponent(0);
820
821 let value0_1 = value1_2 - 1.0;
824
825 let res = value0_1 * scale + low;
828
829 debug_assert!(low.all_le(res) || !scale.all_finite());
830 if res.all_lt(high) {
831 return res;
832 }
833
834 let mask = !scale.finite_mask();
862 if mask.any() {
863 assert!(
864 low.all_finite() && high.all_finite(),
865 "Uniform::sample_single: low and high must be finite"
866 );
867 scale = scale.decrease_masked(mask);
868 }
869 }
870 }
871 }
872 };
873}
874
875uniform_float_impl! { f32, u32, f32, u32, 32 - 23 }
876uniform_float_impl! { f64, u64, f64, u64, 64 - 52 }
877
878#[derive(Clone, Copy, Debug)]
883#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
884pub struct UniformDuration {
885 mode: UniformDurationMode,
886 offset: u32,
887}
888
889#[derive(Debug, Copy, Clone)]
890#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
891enum UniformDurationMode {
892 Small {
893 secs: u64,
894 nanos: Uniform<u32>,
895 },
896 Medium {
897 nanos: Uniform<u64>,
898 },
899 Large {
900 max_secs: u64,
901 max_nanos: u32,
902 secs: Uniform<u64>,
903 },
904}
905
906impl SampleUniform for Duration {
907 type Sampler = UniformDuration;
908}
909
910impl UniformSampler for UniformDuration {
911 type X = Duration;
912
913 #[inline]
914 fn new<B1, B2>(low_b: B1, high_b: B2) -> Self
915 where
916 B1: SampleBorrow<Self::X> + Sized,
917 B2: SampleBorrow<Self::X> + Sized,
918 {
919 let low = *low_b.borrow();
920 let high = *high_b.borrow();
921 assert!(low < high, "Uniform::new called with `low >= high`");
922 UniformDuration::new_inclusive(low, high - Duration::new(0, 1))
923 }
924
925 #[inline]
926 fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self
927 where
928 B1: SampleBorrow<Self::X> + Sized,
929 B2: SampleBorrow<Self::X> + Sized,
930 {
931 let low = *low_b.borrow();
932 let high = *high_b.borrow();
933 assert!(
934 low <= high,
935 "Uniform::new_inclusive called with `low > high`"
936 );
937
938 let low_s = low.as_secs();
939 let low_n = low.subsec_nanos();
940 let mut high_s = high.as_secs();
941 let mut high_n = high.subsec_nanos();
942
943 if high_n < low_n {
944 high_s -= 1;
945 high_n += 1_000_000_000;
946 }
947
948 let mode = if low_s == high_s {
949 UniformDurationMode::Small {
950 secs: low_s,
951 nanos: Uniform::new_inclusive(low_n, high_n),
952 }
953 } else {
954 let max = high_s
955 .checked_mul(1_000_000_000)
956 .and_then(|n| n.checked_add(u64::from(high_n)));
957
958 if let Some(higher_bound) = max {
959 let lower_bound = low_s * 1_000_000_000 + u64::from(low_n);
960 UniformDurationMode::Medium {
961 nanos: Uniform::new_inclusive(lower_bound, higher_bound),
962 }
963 } else {
964 let max_nanos = high_n - low_n;
966 UniformDurationMode::Large {
967 max_secs: high_s,
968 max_nanos,
969 secs: Uniform::new_inclusive(low_s, high_s),
970 }
971 }
972 };
973 UniformDuration {
974 mode,
975 offset: low_n,
976 }
977 }
978
979 #[inline]
980 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Duration {
981 match self.mode {
982 UniformDurationMode::Small { secs, nanos } => {
983 let n = nanos.sample(rng);
984 Duration::new(secs, n)
985 }
986 UniformDurationMode::Medium { nanos } => {
987 let nanos = nanos.sample(rng);
988 Duration::new(nanos / 1_000_000_000, (nanos % 1_000_000_000) as u32)
989 }
990 UniformDurationMode::Large {
991 max_secs,
992 max_nanos,
993 secs,
994 } => {
995 let nano_range = Uniform::new(0, 1_000_000_000);
997 loop {
998 let s = secs.sample(rng);
999 let n = nano_range.sample(rng);
1000 if !(s == max_secs && n > max_nanos) {
1001 let sum = n + self.offset;
1002 break Duration::new(s, sum);
1003 }
1004 }
1005 }
1006 }
1007 }
1008}
1009
1010#[cfg(test)]
1011mod tests {
1012 use super::*;
1013 use crate::rngs::mock::StepRng;
1014
1015 #[test]
1016 #[cfg(feature = "serde1")]
1017 fn test_serialization_uniform_duration() {
1018 let distr = UniformDuration::new(Duration::from_secs(10), Duration::from_secs(60));
1019 let de_distr: UniformDuration = bincode::deserialize(&bincode::serialize(&distr).unwrap()).unwrap();
1020 assert_eq!(
1021 distr.offset, de_distr.offset
1022 );
1023 match (distr.mode, de_distr.mode) {
1024 (UniformDurationMode::Small {secs: a_secs, nanos: a_nanos}, UniformDurationMode::Small {secs, nanos}) => {
1025 assert_eq!(a_secs, secs);
1026
1027 assert_eq!(a_nanos.0.low, nanos.0.low);
1028 assert_eq!(a_nanos.0.range, nanos.0.range);
1029 assert_eq!(a_nanos.0.z, nanos.0.z);
1030 }
1031 (UniformDurationMode::Medium {nanos: a_nanos} , UniformDurationMode::Medium {nanos}) => {
1032 assert_eq!(a_nanos.0.low, nanos.0.low);
1033 assert_eq!(a_nanos.0.range, nanos.0.range);
1034 assert_eq!(a_nanos.0.z, nanos.0.z);
1035 }
1036 (UniformDurationMode::Large {max_secs:a_max_secs, max_nanos:a_max_nanos, secs:a_secs}, UniformDurationMode::Large {max_secs, max_nanos, secs} ) => {
1037 assert_eq!(a_max_secs, max_secs);
1038 assert_eq!(a_max_nanos, max_nanos);
1039
1040 assert_eq!(a_secs.0.low, secs.0.low);
1041 assert_eq!(a_secs.0.range, secs.0.range);
1042 assert_eq!(a_secs.0.z, secs.0.z);
1043 }
1044 _ => panic!("`UniformDurationMode` was not serialized/deserialized correctly")
1045 }
1046 }
1047
1048 #[test]
1049 #[cfg(feature = "serde1")]
1050 fn test_uniform_serialization() {
1051 let unit_box: Uniform<i32> = Uniform::new(-1, 1);
1052 let de_unit_box: Uniform<i32> = bincode::deserialize(&bincode::serialize(&unit_box).unwrap()).unwrap();
1053
1054 assert_eq!(unit_box.0.low, de_unit_box.0.low);
1055 assert_eq!(unit_box.0.range, de_unit_box.0.range);
1056 assert_eq!(unit_box.0.z, de_unit_box.0.z);
1057
1058 let unit_box: Uniform<f32> = Uniform::new(-1., 1.);
1059 let de_unit_box: Uniform<f32> = bincode::deserialize(&bincode::serialize(&unit_box).unwrap()).unwrap();
1060
1061 assert_eq!(unit_box.0.low, de_unit_box.0.low);
1062 assert_eq!(unit_box.0.scale, de_unit_box.0.scale);
1063 }
1064
1065 #[should_panic]
1066 #[test]
1067 fn test_uniform_bad_limits_equal_int() {
1068 Uniform::new(10, 10);
1069 }
1070
1071 #[test]
1072 fn test_uniform_good_limits_equal_int() {
1073 let mut rng = crate::test::rng(804);
1074 let dist = Uniform::new_inclusive(10, 10);
1075 for _ in 0..20 {
1076 assert_eq!(rng.sample(dist), 10);
1077 }
1078 }
1079
1080 #[should_panic]
1081 #[test]
1082 fn test_uniform_bad_limits_flipped_int() {
1083 Uniform::new(10, 5);
1084 }
1085
1086 #[test]
1087 #[cfg_attr(miri, ignore)] fn test_integers() {
1089 use core::{i128, u128};
1090 use core::{i16, i32, i64, i8, isize};
1091 use core::{u16, u32, u64, u8, usize};
1092
1093 let mut rng = crate::test::rng(251);
1094 macro_rules! t {
1095 ($ty:ident, $v:expr, $le:expr, $lt:expr) => {{
1096 for &(low, high) in $v.iter() {
1097 let my_uniform = Uniform::new(low, high);
1098 for _ in 0..1000 {
1099 let v: $ty = rng.sample(my_uniform);
1100 assert!($le(low, v) && $lt(v, high));
1101 }
1102
1103 let my_uniform = Uniform::new_inclusive(low, high);
1104 for _ in 0..1000 {
1105 let v: $ty = rng.sample(my_uniform);
1106 assert!($le(low, v) && $le(v, high));
1107 }
1108
1109 let my_uniform = Uniform::new(&low, high);
1110 for _ in 0..1000 {
1111 let v: $ty = rng.sample(my_uniform);
1112 assert!($le(low, v) && $lt(v, high));
1113 }
1114
1115 let my_uniform = Uniform::new_inclusive(&low, &high);
1116 for _ in 0..1000 {
1117 let v: $ty = rng.sample(my_uniform);
1118 assert!($le(low, v) && $le(v, high));
1119 }
1120
1121 for _ in 0..1000 {
1122 let v = <$ty as SampleUniform>::Sampler::sample_single(low, high, &mut rng);
1123 assert!($le(low, v) && $lt(v, high));
1124 }
1125
1126 for _ in 0..1000 {
1127 let v = <$ty as SampleUniform>::Sampler::sample_single_inclusive(low, high, &mut rng);
1128 assert!($le(low, v) && $le(v, high));
1129 }
1130 }
1131 }};
1132
1133 ($($ty:ident),*) => {{
1135 $(t!(
1136 $ty,
1137 [(0, 10), (10, 127), ($ty::MIN, $ty::MAX)],
1138 |x, y| x <= y,
1139 |x, y| x < y
1140 );)*
1141 }};
1142
1143 ($($ty:ident),* => $scalar:ident) => {{
1145 $(t!(
1146 $ty,
1147 [
1148 ($ty::splat(0), $ty::splat(10)),
1149 ($ty::splat(10), $ty::splat(127)),
1150 ($ty::splat($scalar::MIN), $ty::splat($scalar::MAX)),
1151 ],
1152 |x: $ty, y| x.le(y).all(),
1153 |x: $ty, y| x.lt(y).all()
1154 );)*
1155 }};
1156 }
1157 t!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize, i128, u128);
1158 }
1159
1160 #[test]
1161 #[cfg_attr(miri, ignore)] fn test_char() {
1163 let mut rng = crate::test::rng(891);
1164 let mut max = core::char::from_u32(0).unwrap();
1165 for _ in 0..100 {
1166 let c = rng.gen_range('A'..='Z');
1167 assert!(('A'..='Z').contains(&c));
1168 max = max.max(c);
1169 }
1170 assert_eq!(max, 'Z');
1171 let d = Uniform::new(
1172 core::char::from_u32(0xD7F0).unwrap(),
1173 core::char::from_u32(0xE010).unwrap(),
1174 );
1175 for _ in 0..100 {
1176 let c = d.sample(&mut rng);
1177 assert!((c as u32) < 0xD800 || (c as u32) > 0xDFFF);
1178 }
1179 }
1180
1181 #[test]
1182 #[cfg(feature = "serde1")]
1183 fn test_char_bad_deser() {
1184 let json = r#"{"sampler":{"low":4294967200,"range":0,"z":0}}"#;
1185 let result = serde_json::from_str::<Uniform<char>>(json);
1186 assert!(result.is_err());
1187 let err = result.unwrap_err();
1188 assert_eq!(err.classify(), serde_json::error::Category::Data);
1189
1190 #[cfg(feature = "alloc")]
1191 {
1192 assert_eq!(
1193 alloc::string::ToString::to_string(&err),
1194 "bad sampler range for UniformChar at line 1 column 46"
1195 );
1196 }
1197 }
1198
1199 #[test]
1200 #[cfg_attr(miri, ignore)] fn test_floats() {
1202 let mut rng = crate::test::rng(252);
1203 let mut zero_rng = StepRng::new(0, 0);
1204 let mut max_rng = StepRng::new(0xffff_ffff_ffff_ffff, 0);
1205 macro_rules! t {
1206 ($ty:ty, $f_scalar:ident, $bits_shifted:expr) => {{
1207 let v: &[($f_scalar, $f_scalar)] = &[
1208 (0.0, 100.0),
1209 (-1e35, -1e25),
1210 (1e-35, 1e-25),
1211 (-1e35, 1e35),
1212 (<$f_scalar>::from_bits(0), <$f_scalar>::from_bits(3)),
1213 (-<$f_scalar>::from_bits(10), -<$f_scalar>::from_bits(1)),
1214 (-<$f_scalar>::from_bits(5), 0.0),
1215 (-<$f_scalar>::from_bits(7), -0.0),
1216 (0.1 * ::core::$f_scalar::MAX, ::core::$f_scalar::MAX),
1217 (-::core::$f_scalar::MAX * 0.2, ::core::$f_scalar::MAX * 0.7),
1218 ];
1219 for &(low_scalar, high_scalar) in v.iter() {
1220 for lane in 0..<$ty>::lanes() {
1221 let low = <$ty>::splat(0.0 as $f_scalar).replace(lane, low_scalar);
1222 let high = <$ty>::splat(1.0 as $f_scalar).replace(lane, high_scalar);
1223 let my_uniform = Uniform::new(low, high);
1224 let my_incl_uniform = Uniform::new_inclusive(low, high);
1225 for _ in 0..100 {
1226 let v = rng.sample(my_uniform).extract(lane);
1227 assert!(low_scalar <= v && v < high_scalar);
1228 let v = rng.sample(my_incl_uniform).extract(lane);
1229 assert!(low_scalar <= v && v <= high_scalar);
1230 let v = <$ty as SampleUniform>::Sampler
1231 ::sample_single(low, high, &mut rng).extract(lane);
1232 assert!(low_scalar <= v && v < high_scalar);
1233 }
1234
1235 assert_eq!(
1236 rng.sample(Uniform::new_inclusive(low, low)).extract(lane),
1237 low_scalar
1238 );
1239
1240 assert_eq!(zero_rng.sample(my_uniform).extract(lane), low_scalar);
1241 assert_eq!(zero_rng.sample(my_incl_uniform).extract(lane), low_scalar);
1242 assert_eq!(<$ty as SampleUniform>::Sampler
1243 ::sample_single(low, high, &mut zero_rng)
1244 .extract(lane), low_scalar);
1245 assert!(max_rng.sample(my_uniform).extract(lane) < high_scalar);
1246 assert!(max_rng.sample(my_incl_uniform).extract(lane) <= high_scalar);
1247
1248 if (high_scalar - low_scalar) > 0.0001 {
1252 let mut lowering_max_rng = StepRng::new(
1253 0xffff_ffff_ffff_ffff,
1254 (-1i64 << $bits_shifted) as u64,
1255 );
1256 assert!(
1257 <$ty as SampleUniform>::Sampler
1258 ::sample_single(low, high, &mut lowering_max_rng)
1259 .extract(lane) < high_scalar
1260 );
1261 }
1262 }
1263 }
1264
1265 assert_eq!(
1266 rng.sample(Uniform::new_inclusive(
1267 ::core::$f_scalar::MAX,
1268 ::core::$f_scalar::MAX
1269 )),
1270 ::core::$f_scalar::MAX
1271 );
1272 assert_eq!(
1273 rng.sample(Uniform::new_inclusive(
1274 -::core::$f_scalar::MAX,
1275 -::core::$f_scalar::MAX
1276 )),
1277 -::core::$f_scalar::MAX
1278 );
1279 }};
1280 }
1281
1282 t!(f32, f32, 32 - 23);
1283 t!(f64, f64, 64 - 52);
1284 }
1285
1286 #[test]
1287 #[should_panic]
1288 fn test_float_overflow() {
1289 let _ = Uniform::from(::core::f64::MIN..::core::f64::MAX);
1290 }
1291
1292 #[test]
1293 #[should_panic]
1294 fn test_float_overflow_single() {
1295 let mut rng = crate::test::rng(252);
1296 rng.gen_range(::core::f64::MIN..::core::f64::MAX);
1297 }
1298
1299 #[test]
1300 #[cfg(all(
1301 feature = "std",
1302 not(target_arch = "wasm32"),
1303 ))]
1304 fn test_float_assertions() {
1305 use super::SampleUniform;
1306 use std::panic::catch_unwind;
1307 fn range<T: SampleUniform>(low: T, high: T) {
1308 let mut rng = crate::test::rng(253);
1309 T::Sampler::sample_single(low, high, &mut rng);
1310 }
1311
1312 macro_rules! t {
1313 ($ty:ident, $f_scalar:ident) => {{
1314 let v: &[($f_scalar, $f_scalar)] = &[
1315 (::std::$f_scalar::NAN, 0.0),
1316 (1.0, ::std::$f_scalar::NAN),
1317 (::std::$f_scalar::NAN, ::std::$f_scalar::NAN),
1318 (1.0, 0.5),
1319 (::std::$f_scalar::MAX, -::std::$f_scalar::MAX),
1320 (::std::$f_scalar::INFINITY, ::std::$f_scalar::INFINITY),
1321 (
1322 ::std::$f_scalar::NEG_INFINITY,
1323 ::std::$f_scalar::NEG_INFINITY,
1324 ),
1325 (::std::$f_scalar::NEG_INFINITY, 5.0),
1326 (5.0, ::std::$f_scalar::INFINITY),
1327 (::std::$f_scalar::NAN, ::std::$f_scalar::INFINITY),
1328 (::std::$f_scalar::NEG_INFINITY, ::std::$f_scalar::NAN),
1329 (::std::$f_scalar::NEG_INFINITY, ::std::$f_scalar::INFINITY),
1330 ];
1331 for &(low_scalar, high_scalar) in v.iter() {
1332 for lane in 0..<$ty>::lanes() {
1333 let low = <$ty>::splat(0.0 as $f_scalar).replace(lane, low_scalar);
1334 let high = <$ty>::splat(1.0 as $f_scalar).replace(lane, high_scalar);
1335 assert!(catch_unwind(|| range(low, high)).is_err());
1336 assert!(catch_unwind(|| Uniform::new(low, high)).is_err());
1337 assert!(catch_unwind(|| Uniform::new_inclusive(low, high)).is_err());
1338 assert!(catch_unwind(|| range(low, low)).is_err());
1339 assert!(catch_unwind(|| Uniform::new(low, low)).is_err());
1340 }
1341 }
1342 }};
1343 }
1344
1345 t!(f32, f32);
1346 t!(f64, f64);
1347 }
1348
1349
1350 #[test]
1351 #[cfg_attr(miri, ignore)] fn test_durations() {
1353 let mut rng = crate::test::rng(253);
1354
1355 let v = &[
1356 (Duration::new(10, 50000), Duration::new(100, 1234)),
1357 (Duration::new(0, 100), Duration::new(1, 50)),
1358 (
1359 Duration::new(0, 0),
1360 Duration::new(u64::max_value(), 999_999_999),
1361 ),
1362 ];
1363 for &(low, high) in v.iter() {
1364 let my_uniform = Uniform::new(low, high);
1365 for _ in 0..1000 {
1366 let v = rng.sample(my_uniform);
1367 assert!(low <= v && v < high);
1368 }
1369 }
1370 }
1371
1372 #[test]
1373 fn test_custom_uniform() {
1374 use crate::distributions::uniform::{
1375 SampleBorrow, SampleUniform, UniformFloat, UniformSampler,
1376 };
1377 #[derive(Clone, Copy, PartialEq, PartialOrd)]
1378 struct MyF32 {
1379 x: f32,
1380 }
1381 #[derive(Clone, Copy, Debug)]
1382 struct UniformMyF32(UniformFloat<f32>);
1383 impl UniformSampler for UniformMyF32 {
1384 type X = MyF32;
1385
1386 fn new<B1, B2>(low: B1, high: B2) -> Self
1387 where
1388 B1: SampleBorrow<Self::X> + Sized,
1389 B2: SampleBorrow<Self::X> + Sized,
1390 {
1391 UniformMyF32(UniformFloat::<f32>::new(low.borrow().x, high.borrow().x))
1392 }
1393
1394 fn new_inclusive<B1, B2>(low: B1, high: B2) -> Self
1395 where
1396 B1: SampleBorrow<Self::X> + Sized,
1397 B2: SampleBorrow<Self::X> + Sized,
1398 {
1399 UniformSampler::new(low, high)
1400 }
1401
1402 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
1403 MyF32 {
1404 x: self.0.sample(rng),
1405 }
1406 }
1407 }
1408 impl SampleUniform for MyF32 {
1409 type Sampler = UniformMyF32;
1410 }
1411
1412 let (low, high) = (MyF32 { x: 17.0f32 }, MyF32 { x: 22.0f32 });
1413 let uniform = Uniform::new(low, high);
1414 let mut rng = crate::test::rng(804);
1415 for _ in 0..100 {
1416 let x: MyF32 = rng.sample(uniform);
1417 assert!(low <= x && x < high);
1418 }
1419 }
1420
1421 #[test]
1422 fn test_uniform_from_std_range() {
1423 let r = Uniform::from(2u32..7);
1424 assert_eq!(r.0.low, 2);
1425 assert_eq!(r.0.range, 5);
1426 assert_eq!(r.0.max(), 6);
1427 let r = Uniform::from(2.0f64..7.0);
1428 assert_eq!(r.0.low, 2.0);
1429 assert_eq!(r.0.scale, 5.0);
1430 }
1431
1432 #[test]
1433 fn test_uniform_from_std_range_inclusive() {
1434 let r = Uniform::from(2u32..=6);
1435 assert_eq!(r.0.low, 2);
1436 assert_eq!(r.0.range, 5);
1437 assert_eq!(r.0.max(), 6);
1438 let r = Uniform::from(2.0f64..=7.0);
1439 assert_eq!(r.0.low, 2.0);
1440 assert!(r.0.scale > 5.0);
1441 assert!(r.0.scale < 5.0 + 1e-14);
1442 }
1443
1444 #[test]
1445 fn value_stability() {
1446 fn test_samples<T: SampleUniform + Copy + core::fmt::Debug + PartialEq>(
1447 lb: T, ub: T, expected_single: &[T], expected_multiple: &[T],
1448 ) where Uniform<T>: Distribution<T> {
1449 let mut rng = crate::test::rng(897);
1450 let mut buf = [lb; 3];
1451
1452 for x in &mut buf {
1453 *x = T::Sampler::sample_single(lb, ub, &mut rng);
1454 }
1455 assert_eq!(&buf, expected_single);
1456
1457 let distr = Uniform::new(lb, ub);
1458 for x in &mut buf {
1459 *x = rng.sample(&distr);
1460 }
1461 assert_eq!(&buf, expected_multiple);
1462 }
1463
1464 test_samples(11u8, 219, &[17, 66, 214], &[181, 93, 165]);
1468 test_samples(11u32, 219, &[17, 66, 214], &[181, 93, 165]);
1469
1470 test_samples(0f32, 1e-2f32, &[0.0003070104, 0.0026630748, 0.00979833], &[
1471 0.008194133,
1472 0.00398172,
1473 0.007428536,
1474 ]);
1475 test_samples(
1476 -1e10f64,
1477 1e10f64,
1478 &[-4673848682.871551, 6388267422.932352, 4857075081.198343],
1479 &[1173375212.1808167, 1917642852.109581, 2365076174.3153973],
1480 );
1481
1482 test_samples(
1483 Duration::new(2, 0),
1484 Duration::new(4, 0),
1485 &[
1486 Duration::new(2, 532615131),
1487 Duration::new(3, 638826742),
1488 Duration::new(3, 485707508),
1489 ],
1490 &[
1491 Duration::new(3, 117337521),
1492 Duration::new(3, 191764285),
1493 Duration::new(3, 236507617),
1494 ],
1495 );
1496 }
1497
1498 #[test]
1499 fn uniform_distributions_can_be_compared() {
1500 assert_eq!(Uniform::new(1.0, 2.0), Uniform::new(1.0, 2.0));
1501
1502 assert_eq!(Uniform::new(1 as u32, 2 as u32), Uniform::new(1 as u32, 2 as u32));
1504 }
1505}