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