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