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