1use super::{Error, SampleBorrow, SampleUniform, UniformSampler};
13use crate::distr::utils::WideningMultiply;
14#[cfg(feature = "simd_support")]
15use crate::distr::{Distribution, StandardUniform};
16use crate::{Rng, RngExt};
17
18#[cfg(feature = "simd_support")]
19use core::simd::{Select, prelude::*};
20
21#[cfg(feature = "serde")]
22use serde::{Deserialize, Serialize};
23
24#[derive(Clone, Copy, Debug, PartialEq, Eq)]
68#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
69pub struct UniformInt<X> {
70 pub(super) low: X,
71 pub(super) range: X,
72 thresh: X, }
74
75macro_rules! uniform_int_impl {
76 ($ty:ty, $uty:ty, $sample_ty:ident) => {
77 impl UniformInt<$ty> {
78 #[allow(unused)]
80 #[inline]
81 pub(crate) fn max(&self) -> $ty {
82 if self.range == 0 {
83 return <$ty>::MAX;
84 } else {
85 let max = self.low.wrapping_add(self.range.wrapping_sub(1));
89 if max < self.low { <$ty>::MAX } else { max }
90 }
91 }
92 }
93
94 impl SampleUniform for $ty {
95 type Sampler = UniformInt<$ty>;
96 }
97
98 impl UniformSampler for UniformInt<$ty> {
99 type X = $ty;
105
106 #[inline] fn new<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error>
109 where
110 B1: SampleBorrow<Self::X> + Sized,
111 B2: SampleBorrow<Self::X> + Sized,
112 {
113 let low = *low_b.borrow();
114 let high = *high_b.borrow();
115 if !(low < high) {
116 return Err(Error::EmptyRange);
117 }
118 UniformSampler::new_inclusive(low, high - 1)
119 }
120
121 #[inline] fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error>
124 where
125 B1: SampleBorrow<Self::X> + Sized,
126 B2: SampleBorrow<Self::X> + Sized,
127 {
128 let low = *low_b.borrow();
129 let high = *high_b.borrow();
130 if !(low <= high) {
131 return Err(Error::EmptyRange);
132 }
133
134 let range = high.wrapping_sub(low).wrapping_add(1) as $uty;
135 let thresh = if range > 0 {
136 let range = $sample_ty::from(range);
137 (range.wrapping_neg() % range)
138 } else {
139 0
140 };
141
142 Ok(UniformInt {
143 low,
144 range: range as $ty, thresh: thresh as $uty as $ty, })
147 }
148
149 #[inline]
151 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
152 let range = self.range as $uty as $sample_ty;
153 if range == 0 {
154 return rng.random();
155 }
156
157 let thresh = self.thresh as $uty as $sample_ty;
158 let hi = loop {
159 let (hi, lo) = rng.random::<$sample_ty>().wmul(range);
160 if lo >= thresh {
161 break hi;
162 }
163 };
164 self.low.wrapping_add(hi as $ty)
165 }
166
167 #[inline]
168 fn sample_single<R: Rng + ?Sized, B1, B2>(
169 low_b: B1,
170 high_b: B2,
171 rng: &mut R,
172 ) -> Result<Self::X, Error>
173 where
174 B1: SampleBorrow<Self::X> + Sized,
175 B2: SampleBorrow<Self::X> + Sized,
176 {
177 let low = *low_b.borrow();
178 let high = *high_b.borrow();
179 if !(low < high) {
180 return Err(Error::EmptyRange);
181 }
182 Self::sample_single_inclusive(low, high - 1, rng)
183 }
184
185 #[cfg(not(feature = "unbiased"))]
190 #[inline]
191 fn sample_single_inclusive<R: Rng + ?Sized, B1, B2>(
192 low_b: B1,
193 high_b: B2,
194 rng: &mut R,
195 ) -> Result<Self::X, Error>
196 where
197 B1: SampleBorrow<Self::X> + Sized,
198 B2: SampleBorrow<Self::X> + Sized,
199 {
200 let low = *low_b.borrow();
201 let high = *high_b.borrow();
202 if !(low <= high) {
203 return Err(Error::EmptyRange);
204 }
205 let range = high.wrapping_sub(low).wrapping_add(1) as $uty as $sample_ty;
206 if range == 0 {
207 return Ok(rng.random());
209 }
210
211 let (mut result, lo_order) = rng.random::<$sample_ty>().wmul(range);
213
214 if lo_order > range.wrapping_neg() {
216 let (new_hi_order, _) = (rng.random::<$sample_ty>()).wmul(range as $sample_ty);
218 let is_overflow = lo_order.checked_add(new_hi_order as $sample_ty).is_none();
220 result += is_overflow as $sample_ty;
221 }
222
223 Ok(low.wrapping_add(result as $ty))
224 }
225
226 #[cfg(feature = "unbiased")]
228 #[inline]
229 fn sample_single_inclusive<R: Rng + ?Sized, B1, B2>(
230 low_b: B1,
231 high_b: B2,
232 rng: &mut R,
233 ) -> Result<Self::X, Error>
234 where
235 B1: SampleBorrow<$ty> + Sized,
236 B2: SampleBorrow<$ty> + Sized,
237 {
238 let low = *low_b.borrow();
239 let high = *high_b.borrow();
240 if !(low <= high) {
241 return Err(Error::EmptyRange);
242 }
243 let range = high.wrapping_sub(low).wrapping_add(1) as $uty as $sample_ty;
244 if range == 0 {
245 return Ok(rng.random());
247 }
248
249 let (mut result, mut lo) = rng.random::<$sample_ty>().wmul(range);
250
251 while lo > range.wrapping_neg() {
253 let (new_hi, new_lo) = (rng.random::<$sample_ty>()).wmul(range);
254 match lo.checked_add(new_hi) {
255 Some(x) if x < $sample_ty::MAX => {
256 break;
258 }
259 None => {
260 result += 1;
262 break;
263 }
264 _ => {
265 lo = new_lo;
267 continue;
268 }
269 }
270 }
271
272 Ok(low.wrapping_add(result as $ty))
273 }
274 }
275 };
276}
277
278uniform_int_impl! { i8, u8, u32 }
279uniform_int_impl! { i16, u16, u32 }
280uniform_int_impl! { i32, u32, u32 }
281uniform_int_impl! { i64, u64, u64 }
282uniform_int_impl! { i128, u128, u128 }
283uniform_int_impl! { u8, u8, u32 }
284uniform_int_impl! { u16, u16, u32 }
285uniform_int_impl! { u32, u32, u32 }
286uniform_int_impl! { u64, u64, u64 }
287uniform_int_impl! { u128, u128, u128 }
288
289#[cfg(feature = "simd_support")]
290macro_rules! uniform_simd_int_impl {
291 ($ty:ident, $unsigned:ident) => {
292 #[cfg(feature = "simd_support")]
299 impl<const LANES: usize> SampleUniform for Simd<$ty, LANES>
300 where
301 Simd<$unsigned, LANES>:
302 WideningMultiply<Output = (Simd<$unsigned, LANES>, Simd<$unsigned, LANES>)>,
303 StandardUniform: Distribution<Simd<$unsigned, LANES>>,
304 {
305 type Sampler = UniformInt<Simd<$ty, LANES>>;
306 }
307
308 #[cfg(feature = "simd_support")]
309 impl<const LANES: usize> UniformSampler for UniformInt<Simd<$ty, LANES>>
310 where
311 Simd<$unsigned, LANES>:
312 WideningMultiply<Output = (Simd<$unsigned, LANES>, Simd<$unsigned, LANES>)>,
313 StandardUniform: Distribution<Simd<$unsigned, LANES>>,
314 {
315 type X = Simd<$ty, LANES>;
316
317 #[inline] fn new<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error>
320 where B1: SampleBorrow<Self::X> + Sized,
321 B2: SampleBorrow<Self::X> + Sized
322 {
323 let low = *low_b.borrow();
324 let high = *high_b.borrow();
325 if !(low.simd_lt(high).all()) {
326 return Err(Error::EmptyRange);
327 }
328 UniformSampler::new_inclusive(low, high - Simd::splat(1))
329 }
330
331 #[inline] fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error>
334 where B1: SampleBorrow<Self::X> + Sized,
335 B2: SampleBorrow<Self::X> + Sized
336 {
337 let low = *low_b.borrow();
338 let high = *high_b.borrow();
339 if !(low.simd_le(high).all()) {
340 return Err(Error::EmptyRange);
341 }
342
343 let range: Simd<$unsigned, LANES> = ((high - low) + Simd::splat(1)).cast();
346
347 let not_full_range = range.simd_gt(Simd::splat(0));
349 let modulo = not_full_range.select(range, Simd::splat(1));
350 let ints_to_reject = range.wrapping_neg() % modulo;
351
352 Ok(UniformInt {
353 low,
354 range: range.cast(),
356 thresh: ints_to_reject.cast(),
357 })
358 }
359
360 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X {
361 let range: Simd<$unsigned, LANES> = self.range.cast();
362 let thresh: Simd<$unsigned, LANES> = self.thresh.cast();
363
364 let mut v: Simd<$unsigned, LANES> = rng.random();
374 loop {
375 let (hi, lo) = v.wmul(range);
376 let mask = lo.simd_ge(thresh);
377 if mask.all() {
378 let hi: Simd<$ty, LANES> = hi.cast();
379 let result = self.low + hi;
381 let v: Simd<$ty, LANES> = v.cast();
385 return range.simd_gt(Simd::splat(0)).select(result, v);
386 }
387 v = mask.select(v, rng.random());
389 }
390 }
391 }
392 };
393
394 ($(($unsigned:ident, $signed:ident)),+) => {
396 $(
397 uniform_simd_int_impl!($unsigned, $unsigned);
398 uniform_simd_int_impl!($signed, $unsigned);
399 )+
400 };
401}
402
403#[cfg(feature = "simd_support")]
404uniform_simd_int_impl! { (u8, i8), (u16, i16), (u32, i32), (u64, i64) }
405
406#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
417#[derive(Clone, Copy, Debug, PartialEq, Eq)]
418#[cfg_attr(all(feature = "serde"), derive(Serialize))]
419#[cfg_attr(
425 all(feature = "serde", target_pointer_width = "64"),
426 derive(Deserialize)
427)]
428pub struct UniformUsize {
429 low: usize,
431 range: usize,
433 thresh: usize,
435 #[cfg(target_pointer_width = "64")]
437 #[cfg_attr(feature = "serde", serde(default))]
440 mode64: bool,
441}
442
443#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
444impl SampleUniform for usize {
445 type Sampler = UniformUsize;
446}
447
448#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
449impl UniformSampler for UniformUsize {
450 type X = usize;
451
452 #[inline] fn new<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error>
455 where
456 B1: SampleBorrow<Self::X> + Sized,
457 B2: SampleBorrow<Self::X> + Sized,
458 {
459 let low = *low_b.borrow();
460 let high = *high_b.borrow();
461 if !(low < high) {
462 return Err(Error::EmptyRange);
463 }
464
465 UniformSampler::new_inclusive(low, high - 1)
466 }
467
468 #[inline] fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Result<Self, Error>
471 where
472 B1: SampleBorrow<Self::X> + Sized,
473 B2: SampleBorrow<Self::X> + Sized,
474 {
475 let low = *low_b.borrow();
476 let high = *high_b.borrow();
477 if !(low <= high) {
478 return Err(Error::EmptyRange);
479 }
480
481 #[cfg(target_pointer_width = "64")]
482 let mode64 = high > (u32::MAX as usize);
483 #[cfg(target_pointer_width = "32")]
484 let mode64 = false;
485
486 let (range, thresh);
487 if cfg!(target_pointer_width = "64") && !mode64 {
488 let range32 = (high as u32).wrapping_sub(low as u32).wrapping_add(1);
489 range = range32 as usize;
490 thresh = if range32 > 0 {
491 (range32.wrapping_neg() % range32) as usize
492 } else {
493 0
494 };
495 } else {
496 range = high.wrapping_sub(low).wrapping_add(1);
497 thresh = if range > 0 {
498 range.wrapping_neg() % range
499 } else {
500 0
501 };
502 }
503
504 Ok(UniformUsize {
505 low,
506 range,
507 thresh,
508 #[cfg(target_pointer_width = "64")]
509 mode64,
510 })
511 }
512
513 #[inline]
514 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize {
515 #[cfg(target_pointer_width = "32")]
516 let mode32 = true;
517 #[cfg(target_pointer_width = "64")]
518 let mode32 = !self.mode64;
519
520 if mode32 {
521 let range = self.range as u32;
522 if range == 0 {
523 return rng.random::<u32>() as usize;
524 }
525
526 let thresh = self.thresh as u32;
527 let hi = loop {
528 let (hi, lo) = rng.random::<u32>().wmul(range);
529 if lo >= thresh {
530 break hi;
531 }
532 };
533 self.low.wrapping_add(hi as usize)
534 } else {
535 let range = self.range as u64;
536 if range == 0 {
537 return rng.random::<u64>() as usize;
538 }
539
540 let thresh = self.thresh as u64;
541 let hi = loop {
542 let (hi, lo) = rng.random::<u64>().wmul(range);
543 if lo >= thresh {
544 break hi;
545 }
546 };
547 self.low.wrapping_add(hi as usize)
548 }
549 }
550
551 #[inline]
552 fn sample_single<R: Rng + ?Sized, B1, B2>(
553 low_b: B1,
554 high_b: B2,
555 rng: &mut R,
556 ) -> Result<Self::X, Error>
557 where
558 B1: SampleBorrow<Self::X> + Sized,
559 B2: SampleBorrow<Self::X> + Sized,
560 {
561 let low = *low_b.borrow();
562 let high = *high_b.borrow();
563 if !(low < high) {
564 return Err(Error::EmptyRange);
565 }
566
567 if cfg!(target_pointer_width = "64") && high > (u32::MAX as usize) {
568 return UniformInt::<u64>::sample_single(low as u64, high as u64, rng)
569 .map(|x| x as usize);
570 }
571
572 UniformInt::<u32>::sample_single(low as u32, high as u32, rng).map(|x| x as usize)
573 }
574
575 #[inline]
576 fn sample_single_inclusive<R: Rng + ?Sized, B1, B2>(
577 low_b: B1,
578 high_b: B2,
579 rng: &mut R,
580 ) -> Result<Self::X, Error>
581 where
582 B1: SampleBorrow<Self::X> + Sized,
583 B2: SampleBorrow<Self::X> + Sized,
584 {
585 let low = *low_b.borrow();
586 let high = *high_b.borrow();
587 if !(low <= high) {
588 return Err(Error::EmptyRange);
589 }
590
591 if cfg!(target_pointer_width = "64") && high > (u32::MAX as usize) {
592 return UniformInt::<u64>::sample_single_inclusive(low as u64, high as u64, rng)
593 .map(|x| x as usize);
594 }
595
596 UniformInt::<u32>::sample_single_inclusive(low as u32, high as u32, rng).map(|x| x as usize)
597 }
598}
599
600#[cfg(test)]
601mod tests {
602 use super::*;
603 use crate::distr::{Distribution, Uniform};
604 use core::fmt::Debug;
605 use core::ops::Add;
606
607 #[test]
608 fn test_uniform_bad_limits_equal_int() {
609 assert_eq!(Uniform::new(10, 10), Err(Error::EmptyRange));
610 }
611
612 #[test]
613 fn test_uniform_good_limits_equal_int() {
614 let mut rng = crate::test::rng(804);
615 let dist = Uniform::new_inclusive(10, 10).unwrap();
616 for _ in 0..20 {
617 assert_eq!(rng.sample(dist), 10);
618 }
619 }
620
621 #[test]
622 fn test_uniform_bad_limits_flipped_int() {
623 assert_eq!(Uniform::new(10, 5), Err(Error::EmptyRange));
624 }
625
626 #[test]
627 #[cfg_attr(miri, ignore)] fn test_integers() {
629 let mut rng = crate::test::rng(251);
630 macro_rules! t {
631 ($ty:ident, $v:expr, $le:expr, $lt:expr) => {{
632 for &(low, high) in $v.iter() {
633 let my_uniform = Uniform::new(low, high).unwrap();
634 for _ in 0..1000 {
635 let v: $ty = rng.sample(my_uniform);
636 assert!($le(low, v) && $lt(v, high));
637 }
638
639 let my_uniform = Uniform::new_inclusive(low, high).unwrap();
640 for _ in 0..1000 {
641 let v: $ty = rng.sample(my_uniform);
642 assert!($le(low, v) && $le(v, high));
643 }
644
645 let my_uniform = Uniform::new(&low, high).unwrap();
646 for _ in 0..1000 {
647 let v: $ty = rng.sample(my_uniform);
648 assert!($le(low, v) && $lt(v, high));
649 }
650
651 let my_uniform = Uniform::new_inclusive(&low, &high).unwrap();
652 for _ in 0..1000 {
653 let v: $ty = rng.sample(my_uniform);
654 assert!($le(low, v) && $le(v, high));
655 }
656
657 for _ in 0..1000 {
658 let v = <$ty as SampleUniform>::Sampler::sample_single(low, high, &mut rng).unwrap();
659 assert!($le(low, v) && $lt(v, high));
660 }
661
662 for _ in 0..1000 {
663 let v = <$ty as SampleUniform>::Sampler::sample_single_inclusive(low, high, &mut rng).unwrap();
664 assert!($le(low, v) && $le(v, high));
665 }
666 }
667 }};
668
669 ($($ty:ident),*) => {{
671 $(t!(
672 $ty,
673 [(0, 10), (10, 127), ($ty::MIN, $ty::MAX)],
674 |x, y| x <= y,
675 |x, y| x < y
676 );)*
677 }};
678
679 ($($ty:ident),* => $scalar:ident) => {{
681 $(t!(
682 $ty,
683 [
684 ($ty::splat(0), $ty::splat(10)),
685 ($ty::splat(10), $ty::splat(127)),
686 ($ty::splat($scalar::MIN), $ty::splat($scalar::MAX)),
687 ],
688 |x: $ty, y| x.simd_le(y).all(),
689 |x: $ty, y| x.simd_lt(y).all()
690 );)*
691 }};
692 }
693 t!(i8, i16, i32, i64, i128, u8, u16, u32, u64, usize, u128);
694
695 #[cfg(feature = "simd_support")]
696 {
697 t!(u8x4, u8x8, u8x16, u8x32, u8x64 => u8);
698 t!(i8x4, i8x8, i8x16, i8x32, i8x64 => i8);
699 t!(u16x2, u16x4, u16x8, u16x16, u16x32 => u16);
700 t!(i16x2, i16x4, i16x8, i16x16, i16x32 => i16);
701 t!(u32x2, u32x4, u32x8, u32x16 => u32);
702 t!(i32x2, i32x4, i32x8, i32x16 => i32);
703 t!(u64x2, u64x4, u64x8 => u64);
704 t!(i64x2, i64x4, i64x8 => i64);
705 }
706 }
707
708 #[test]
709 fn test_uniform_from_std_range() {
710 let r = Uniform::try_from(2u32..7).unwrap();
711 assert_eq!(r.0.low, 2);
712 assert_eq!(r.0.range, 5);
713 assert_eq!(r.0.max(), 6);
714 }
715
716 #[test]
717 fn test_uniform_from_std_range_bad_limits() {
718 #![allow(clippy::reversed_empty_ranges)]
719 assert!(Uniform::try_from(100..10).is_err());
720 assert!(Uniform::try_from(100..100).is_err());
721 }
722
723 #[test]
724 fn test_uniform_from_std_range_inclusive() {
725 let r = Uniform::try_from(2u32..=6).unwrap();
726 assert_eq!(r.0.low, 2);
727 assert_eq!(r.0.range, 5);
728 assert_eq!(r.0.max(), 6);
729 }
730
731 #[test]
732 fn test_uniform_from_std_range_inclusive_bad_limits() {
733 #![allow(clippy::reversed_empty_ranges)]
734 assert!(Uniform::try_from(100..=10).is_err());
735 assert!(Uniform::try_from(100..=99).is_err());
736 }
737
738 #[test]
739 fn value_stability() {
740 fn test_samples<T: SampleUniform + Copy + Debug + PartialEq + Add<T>>(
741 lb: T,
742 ub: T,
743 ub_excl: T,
744 expected: &[T],
745 ) where
746 Uniform<T>: Distribution<T>,
747 {
748 let mut rng = crate::test::rng(897);
749 let mut buf = [lb; 6];
750
751 for x in &mut buf[0..3] {
752 *x = T::Sampler::sample_single_inclusive(lb, ub, &mut rng).unwrap();
753 }
754
755 let distr = Uniform::new_inclusive(lb, ub).unwrap();
756 for x in &mut buf[3..6] {
757 *x = rng.sample(&distr);
758 }
759 assert_eq!(&buf, expected);
760
761 let mut rng = crate::test::rng(897);
762
763 for x in &mut buf[0..3] {
764 *x = T::Sampler::sample_single(lb, ub_excl, &mut rng).unwrap();
765 }
766
767 let distr = Uniform::new(lb, ub_excl).unwrap();
768 for x in &mut buf[3..6] {
769 *x = rng.sample(&distr);
770 }
771 assert_eq!(&buf, expected);
772 }
773
774 test_samples(-105i8, 111, 112, &[-99, -48, 107, 72, -19, 56]);
775 test_samples(2i16, 1352, 1353, &[43, 361, 1325, 1109, 539, 1005]);
776 test_samples(
777 -313853i32,
778 13513,
779 13514,
780 &[-303803, -226673, 6912, -45605, -183505, -70668],
781 );
782 test_samples(
783 131521i64,
784 6542165,
785 6542166,
786 &[1838724, 5384489, 4893692, 3712948, 3951509, 4094926],
787 );
788 test_samples(
789 -0x8000_0000_0000_0000_0000_0000_0000_0000i128,
790 -1,
791 0,
792 &[
793 -30725222750250982319765550926688025855,
794 -75088619368053423329503924805178012357,
795 -64950748766625548510467638647674468829,
796 -41794017901603587121582892414659436495,
797 -63623852319608406524605295913876414006,
798 -17404679390297612013597359206379189023,
799 ],
800 );
801 test_samples(11u8, 218, 219, &[17, 66, 214, 181, 93, 165]);
802 test_samples(11u16, 218, 219, &[17, 66, 214, 181, 93, 165]);
803 test_samples(11u32, 218, 219, &[17, 66, 214, 181, 93, 165]);
804 test_samples(11u64, 218, 219, &[66, 181, 165, 127, 134, 139]);
805 test_samples(11u128, 218, 219, &[181, 127, 139, 167, 141, 197]);
806 test_samples(11usize, 218, 219, &[17, 66, 214, 181, 93, 165]);
807
808 #[cfg(feature = "simd_support")]
809 {
810 let lb = Simd::from([11u8, 0, 128, 127]);
811 let ub = Simd::from([218, 254, 254, 254]);
812 let ub_excl = ub + Simd::splat(1);
813 test_samples(
814 lb,
815 ub,
816 ub_excl,
817 &[
818 Simd::from([13, 5, 237, 130]),
819 Simd::from([126, 186, 149, 161]),
820 Simd::from([103, 86, 234, 252]),
821 Simd::from([35, 18, 225, 231]),
822 Simd::from([106, 153, 246, 177]),
823 Simd::from([195, 168, 149, 222]),
824 ],
825 );
826 }
827 }
828
829 #[test]
830 fn test_uniform_usize_empty_range() {
831 assert_eq!(UniformUsize::new(10, 10), Err(Error::EmptyRange));
832 assert!(UniformUsize::new(10, 11).is_ok());
833
834 assert_eq!(UniformUsize::new_inclusive(10, 9), Err(Error::EmptyRange));
835 assert!(UniformUsize::new_inclusive(10, 10).is_ok());
836 }
837
838 #[test]
839 fn test_uniform_usize_constructors() {
840 assert_eq!(
841 UniformUsize::new_inclusive(u32::MAX as usize, u32::MAX as usize),
842 Ok(UniformUsize {
843 low: u32::MAX as usize,
844 range: 1,
845 thresh: 0,
846 #[cfg(target_pointer_width = "64")]
847 mode64: false
848 })
849 );
850 assert_eq!(
851 UniformUsize::new_inclusive(0, u32::MAX as usize),
852 Ok(UniformUsize {
853 low: 0,
854 range: 0,
855 thresh: 0,
856 #[cfg(target_pointer_width = "64")]
857 mode64: false
858 })
859 );
860 #[cfg(target_pointer_width = "64")]
861 assert_eq!(
862 UniformUsize::new_inclusive(0, u32::MAX as usize + 1),
863 Ok(UniformUsize {
864 low: 0,
865 range: u32::MAX as usize + 2,
866 thresh: 1,
867 mode64: true
868 })
869 );
870 #[cfg(target_pointer_width = "64")]
871 assert_eq!(
872 UniformUsize::new_inclusive(u32::MAX as usize, u64::MAX as usize),
873 Ok(UniformUsize {
874 low: u32::MAX as usize,
875 range: u64::MAX as usize - u32::MAX as usize + 1,
876 thresh: u32::MAX as usize,
877 mode64: true
878 })
879 );
880 }
881
882 #[cfg(all(feature = "serde", target_pointer_width = "64"))]
884 #[test]
885 fn test_uniform_usize_deserialization() {
886 use serde_json;
887 let original = UniformUsize::new_inclusive(10, 100).expect("creation");
888 let serialized = serde_json::to_string(&original).expect("serialization");
889 let deserialized: UniformUsize =
890 serde_json::from_str(&serialized).expect("deserialization");
891 assert_eq!(deserialized, original);
892 }
893
894 #[cfg(all(feature = "serde", target_pointer_width = "64"))]
895 #[test]
896 fn test_uniform_usize_deserialization_from_32bit() {
897 use serde_json;
898 let serialized_on_32bit = r#"{"low":10,"range":91,"thresh":74}"#;
899 let deserialized: UniformUsize =
900 serde_json::from_str(serialized_on_32bit).expect("deserialization");
901 assert_eq!(
902 deserialized,
903 UniformUsize::new_inclusive(10, 100).expect("creation")
904 );
905 }
906
907 #[cfg(all(feature = "serde", target_pointer_width = "64"))]
908 #[test]
909 fn test_uniform_usize_deserialization_64bit() {
910 use serde_json;
911 let original = UniformUsize::new_inclusive(1, u64::MAX as usize - 1).expect("creation");
912 assert!(original.mode64);
913 let serialized = serde_json::to_string(&original).expect("serialization");
914 let deserialized: UniformUsize =
915 serde_json::from_str(&serialized).expect("deserialization");
916 assert_eq!(deserialized, original);
917 }
918}