|
| 1 | +//! Generators for values of type `isize`. |
| 2 | +
|
| 3 | +// Please note! This module does not use the integer_module macro, since the |
| 4 | +// underlying rand library does not support isize directly. For details, see: |
| 5 | +// https://rust-random.github.io/book/update-0.9.html |
| 6 | +// |
| 7 | +// The code here should be similar to what the macro would have generated, but |
| 8 | +// is piggybacking on the generators for type `i64` and just maps to type |
| 9 | +// `isize`. |
| 10 | + |
| 11 | +use super::int_bounds; |
| 12 | +use crate::BoxGen; |
| 13 | +use crate::*; |
| 14 | +use core::panic; |
| 15 | +use std::ops::{RangeBounds, RangeInclusive}; |
| 16 | + |
| 17 | +/// Roughly uniformly distributed unbound range of values, with |
| 18 | +/// some overwheight to extremes (min and max). |
| 19 | +pub fn any() -> BoxGen<isize> { |
| 20 | + ranged(..) |
| 21 | +} |
| 22 | + |
| 23 | +/// Roughly uniformly distributed range of values, with some |
| 24 | +/// overwheight to extremes (min and max) of given bounds. |
| 25 | +pub fn ranged<B>(bounds: B) -> BoxGen<isize> |
| 26 | +where |
| 27 | + B: RangeBounds<isize>, |
| 28 | +{ |
| 29 | + assert_lib_supports_isize_bit_width(); |
| 30 | + let i64_bounds = map_to_i64_bounds(&bounds); |
| 31 | + map_to_isize_gen(super::i64::ranged(i64_bounds)) |
| 32 | +} |
| 33 | + |
| 34 | +/// Int generator with completely random distribution. This |
| 35 | +/// function has a long name, since `ranged` should be preferred. |
| 36 | +pub fn completely_random<B>(bounds: B) -> BoxGen<isize> |
| 37 | +where |
| 38 | + B: RangeBounds<isize>, |
| 39 | +{ |
| 40 | + assert_lib_supports_isize_bit_width(); |
| 41 | + let i64_bounds = map_to_i64_bounds(&bounds); |
| 42 | + map_to_isize_gen(super::i64::completely_random(i64_bounds)) |
| 43 | +} |
| 44 | + |
| 45 | +/// Maps isize bounds to i64 bounds. |
| 46 | +fn map_to_i64_bounds<B>(i_bounds: &B) -> RangeInclusive<i64> |
| 47 | +where |
| 48 | + B: RangeBounds<isize>, |
| 49 | +{ |
| 50 | + let start: isize = int_bounds::start(i_bounds); |
| 51 | + let end: isize = int_bounds::end(i_bounds); |
| 52 | + (start as i64)..=(end as i64) |
| 53 | +} |
| 54 | + |
| 55 | +/// Maps `i64` generator to a `isize` generator. |
| 56 | +fn map_to_isize_gen(gen: BoxGen<i64>) -> BoxGen<isize> { |
| 57 | + gen.map(|i| i as isize, |j| j as i64) |
| 58 | +} |
| 59 | + |
| 60 | +/// Ensure that the library supports the bit width of isize on this platform. |
| 61 | +fn assert_lib_supports_isize_bit_width() { |
| 62 | + if isize::BITS > i64::BITS { |
| 63 | + panic!( |
| 64 | + "Generators for isize only support platforms where isize is at most \ |
| 65 | + 64 bits wide. \ |
| 66 | + Please contact the library author for support for wider isize types."); |
| 67 | + } |
| 68 | +} |
| 69 | + |
| 70 | +#[cfg(test)] |
| 71 | +mod tests { |
| 72 | + use crate::testing::distribution::assert_generator_has_distribution_within_percent; |
| 73 | + use crate::testing::distribution::distribution_from_pairs; |
| 74 | + |
| 75 | + /// Generator values should be evenly distributed within range. |
| 76 | + #[test] |
| 77 | + fn random_inclusive_has_uniform_distribution() { |
| 78 | + assert_generator_has_distribution_within_percent( |
| 79 | + super::completely_random(-10isize..=10isize), |
| 80 | + distribution_from_pairs(&[ |
| 81 | + (1, -10isize), |
| 82 | + (1, -9isize), |
| 83 | + (1, -8isize), |
| 84 | + (1, -7isize), |
| 85 | + (1, -6isize), |
| 86 | + (1, -5isize), |
| 87 | + (1, -4isize), |
| 88 | + (1, -3isize), |
| 89 | + (1, -2isize), |
| 90 | + (1, -1isize), |
| 91 | + (1, 0isize), |
| 92 | + (1, 1isize), |
| 93 | + (1, 2isize), |
| 94 | + (1, 3isize), |
| 95 | + (1, 4isize), |
| 96 | + (1, 5isize), |
| 97 | + (1, 6isize), |
| 98 | + (1, 7isize), |
| 99 | + (1, 8isize), |
| 100 | + (1, 9isize), |
| 101 | + (1, 10isize), |
| 102 | + ]), |
| 103 | + 2.0, // 2% tolerance |
| 104 | + ); |
| 105 | + } |
| 106 | +} |
0 commit comments