proptest/
num.rs

1//-
2// Copyright 2017, 2018 Jason Lingle
3//
4// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7// option. This file may not be copied, modified, or distributed
8// except according to those terms.
9
10//! Strategies to generate numeric values (as opposed to integers used as bit
11//! fields).
12//!
13//! All strategies in this module shrink by binary searching towards 0.
14
15mod float_samplers;
16
17use crate::test_runner::TestRunner;
18use rand::distr::uniform::{SampleUniform, Uniform};
19use rand::distr::{Distribution, StandardUniform};
20
21/// Generate a random value of `X`, sampled uniformly from the half
22/// open range `[low, high)` (excluding `high`). Panics if `low >= high`.
23pub(crate) fn sample_uniform<X: SampleUniform>(
24    run: &mut TestRunner,
25    start: X,
26    end: X,
27) -> X {
28    Uniform::new(start, end).expect("not uniform").sample(run.rng())
29}
30
31/// Generate a random value of `X`, sampled uniformly from the closed
32/// range `[low, high]` (inclusive). Panics if `low > high`.
33pub fn sample_uniform_incl<X: SampleUniform>(
34    run: &mut TestRunner,
35    start: X,
36    end: X,
37) -> X {
38    Uniform::new_inclusive(start, end).expect("not uniform").sample(run.rng())
39}
40
41macro_rules! sample_uniform {
42    ($name: ident, $incl:ident, $from:ty, $to:ty) => {
43        fn $name<X>(
44            run: &mut TestRunner,
45            start: $to,
46            end: $to,
47        ) -> $to {
48            Uniform::<$from>::new(start as $from, end as $from).expect("not uniform").sample(run.rng()) as $to
49        }
50
51        fn $incl<X>(
52            run: &mut TestRunner,
53            start: $to,
54            end: $to,
55        ) -> $to {
56            Uniform::<$from>::new_inclusive(start as $from, end as $from).expect("not uniform").sample(run.rng()) as $to
57        }        
58    }
59}
60
61#[cfg(target_pointer_width = "64")]
62sample_uniform!(usize_sample_uniform, usize_sample_uniform_incl, u64, usize);
63#[cfg(target_pointer_width = "32")]
64sample_uniform!(usize_sample_uniform, usize_sample_uniform_incl, u32, usize);
65#[cfg(target_pointer_width = "16")]
66sample_uniform!(usize_sample_uniform, usize_sample_uniform_incl, u16, usize);
67
68#[cfg(target_pointer_width = "64")]
69sample_uniform!(isize_sample_uniform, isize_sample_uniform_incl, i64, isize);
70#[cfg(target_pointer_width = "32")]
71sample_uniform!(isize_sample_uniform, isize_sample_uniform_incl, i32, isize);
72#[cfg(target_pointer_width = "16")]
73sample_uniform!(isize_sample_uniform, isize_sample_uniform_incl, i16, isize);
74
75macro_rules! supported_int_any {
76    ($runner:ident, $typ:ty) => {
77        $runner.rng().random()
78    };
79}
80
81#[cfg(target_pointer_width = "64")]
82macro_rules! unsupported_int_any {
83    ($runner:ident, $typ:ty) => {
84        $runner.rng().next_u64() as $typ
85    };
86}
87
88#[cfg(not(target_pointer_width = "64"))]
89macro_rules! unsupported_int_any {
90    ($runner:ident, $typ:ty) => {
91        $runner.rng().next_u32() as $typ
92    };
93}
94
95macro_rules! int_any {
96    ($typ: ident, $int_any: ident) => {
97        /// Type of the `ANY` constant.
98        #[derive(Clone, Copy, Debug)]
99        #[must_use = "strategies do nothing unless used"]
100        pub struct Any(());
101        /// Generates integers with completely arbitrary values, uniformly
102        /// distributed over the whole range.
103        pub const ANY: Any = Any(());
104
105        impl Strategy for Any {
106            type Tree = BinarySearch;
107            type Value = $typ;
108
109            fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
110                Ok(BinarySearch::new($int_any!(runner, $typ)))
111            }
112        }
113    };
114}
115
116macro_rules! numeric_api {
117    ($typ:ident, $epsilon:expr) => {
118        numeric_api!($typ, $typ, $epsilon);
119    };
120    ($typ:ident, $sample_typ:ty, $epsilon:expr) => {
121        numeric_api!($typ, $sample_typ, $epsilon, sample_uniform, sample_uniform_incl);
122    };
123    ($typ:ident, $epsilon:expr, $uniform:ident, $incl:ident) => {
124        numeric_api!($typ, $typ, $epsilon, $uniform, $incl);
125    };
126    ($typ:ident, $sample_typ:ty, $epsilon:expr, $uniform:ident, $incl:ident) => {
127        impl Strategy for ::core::ops::Range<$typ> {
128            type Tree = BinarySearch;
129            type Value = $typ;
130
131            fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
132                if self.is_empty() {
133                    panic!(
134                        "Invalid use of empty range {}..{}.",
135                        self.start, self.end
136                    );
137                }
138
139                Ok(BinarySearch::new_clamped(
140                    self.start,
141                    $crate::num::$uniform::<$sample_typ>(
142                        runner,
143                        self.start.into(),
144                        self.end.into(),
145                    )
146                    .into(),
147                    self.end - $epsilon,
148                ))
149            }
150        }
151
152        impl Strategy for ::core::ops::RangeInclusive<$typ> {
153            type Tree = BinarySearch;
154            type Value = $typ;
155
156            fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
157                if self.is_empty() {
158                    panic!(
159                        "Invalid use of empty range {}..={}.",
160                        self.start(),
161                        self.end()
162                    );
163                }
164
165                Ok(BinarySearch::new_clamped(
166                    *self.start(),
167                    $crate::num::$incl::<$sample_typ>(
168                        runner,
169                        (*self.start()).into(),
170                        (*self.end()).into(),
171                    )
172                    .into(),
173                    *self.end(),
174                ))
175            }
176        }
177
178        impl Strategy for ::core::ops::RangeFrom<$typ> {
179            type Tree = BinarySearch;
180            type Value = $typ;
181
182            fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
183                Ok(BinarySearch::new_clamped(
184                    self.start,
185                    $crate::num::$incl::<$sample_typ>(
186                        runner,
187                        self.start.into(),
188                        ::core::$typ::MAX.into(),
189                    )
190                    .into(),
191                    ::core::$typ::MAX,
192                ))
193            }
194        }
195
196        impl Strategy for ::core::ops::RangeTo<$typ> {
197            type Tree = BinarySearch;
198            type Value = $typ;
199
200            fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
201                Ok(BinarySearch::new_clamped(
202                    ::core::$typ::MIN,
203                    $crate::num::$uniform::<$sample_typ>(
204                        runner,
205                        ::core::$typ::MIN.into(),
206                        self.end.into(),
207                    )
208                    .into(),
209                    self.end,
210                ))
211            }
212        }
213
214        impl Strategy for ::core::ops::RangeToInclusive<$typ> {
215            type Tree = BinarySearch;
216            type Value = $typ;
217
218            fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
219                Ok(BinarySearch::new_clamped(
220                    ::core::$typ::MIN,
221                    $crate::num::$incl::<$sample_typ>(
222                        runner,
223                        ::core::$typ::MIN.into(),
224                        self.end.into(),
225                    )
226                    .into(),
227                    self.end,
228                ))
229            }
230        }
231    };
232}
233
234macro_rules! signed_integer_bin_search {
235    ($typ:ident) => {
236        signed_integer_bin_search!($typ, supported_int_any, sample_uniform, sample_uniform_incl);
237    };
238    ($typ:ident, $int_any: ident, $uniform: ident, $incl: ident) => {
239        #[allow(missing_docs)]
240        pub mod $typ {
241            use rand::{Rng, RngCore};
242
243            use crate::strategy::*;
244            use crate::test_runner::TestRunner;
245
246            int_any!($typ, $int_any);
247
248            /// Shrinks an integer towards 0, using binary search to find
249            /// boundary points.
250            #[derive(Clone, Copy, Debug)]
251            pub struct BinarySearch {
252                lo: $typ,
253                curr: $typ,
254                hi: $typ,
255            }
256            impl BinarySearch {
257                /// Creates a new binary searcher starting at the given value.
258                pub fn new(start: $typ) -> Self {
259                    BinarySearch {
260                        lo: 0,
261                        curr: start,
262                        hi: start,
263                    }
264                }
265
266                /// Creates a new binary searcher which will not produce values
267                /// on the other side of `lo` or `hi` from `start`. `lo` is
268                /// inclusive, `hi` is exclusive.
269                fn new_clamped(lo: $typ, start: $typ, hi: $typ) -> Self {
270                    use core::cmp::{max, min};
271
272                    BinarySearch {
273                        lo: if start < 0 {
274                            min(0, hi - 1)
275                        } else {
276                            max(0, lo)
277                        },
278                        hi: start,
279                        curr: start,
280                    }
281                }
282
283                fn reposition(&mut self) -> bool {
284                    // Won't ever overflow since lo starts at 0 and advances
285                    // towards hi.
286                    let interval = self.hi - self.lo;
287                    let new_mid = self.lo + interval / 2;
288
289                    if new_mid == self.curr {
290                        false
291                    } else {
292                        self.curr = new_mid;
293                        true
294                    }
295                }
296
297                fn magnitude_greater(lhs: $typ, rhs: $typ) -> bool {
298                    if 0 == lhs {
299                        false
300                    } else if lhs < 0 {
301                        lhs < rhs
302                    } else {
303                        lhs > rhs
304                    }
305                }
306            }
307            impl ValueTree for BinarySearch {
308                type Value = $typ;
309
310                fn current(&self) -> $typ {
311                    self.curr
312                }
313
314                fn simplify(&mut self) -> bool {
315                    if !BinarySearch::magnitude_greater(self.hi, self.lo) {
316                        return false;
317                    }
318
319                    self.hi = self.curr;
320                    self.reposition()
321                }
322
323                fn complicate(&mut self) -> bool {
324                    if !BinarySearch::magnitude_greater(self.hi, self.lo) {
325                        return false;
326                    }
327
328                    self.lo = self.curr + if self.hi < 0 { -1 } else { 1 };
329
330                    self.reposition()
331                }
332            }
333
334            numeric_api!($typ, 1, $uniform, $incl);
335        }
336    };
337}
338
339macro_rules! unsigned_integer_bin_search {
340    ($typ:ident) => {
341        unsigned_integer_bin_search!($typ, supported_int_any, sample_uniform, sample_uniform_incl);
342    };
343    ($typ:ident, $int_any: ident, $uniform: ident, $incl: ident) => {
344        #[allow(missing_docs)]
345        pub mod $typ {
346            use rand::{Rng, RngCore};
347
348            use crate::strategy::*;
349            use crate::test_runner::TestRunner;
350
351            int_any!($typ, $int_any);
352
353            /// Shrinks an integer towards 0, using binary search to find
354            /// boundary points.
355            #[derive(Clone, Copy, Debug)]
356            pub struct BinarySearch {
357                lo: $typ,
358                curr: $typ,
359                hi: $typ,
360            }
361            impl BinarySearch {
362                /// Creates a new binary searcher starting at the given value.
363                pub fn new(start: $typ) -> Self {
364                    BinarySearch {
365                        lo: 0,
366                        curr: start,
367                        hi: start,
368                    }
369                }
370
371                /// Creates a new binary searcher which will not search below
372                /// the given `lo` value.
373                fn new_clamped(lo: $typ, start: $typ, _hi: $typ) -> Self {
374                    BinarySearch {
375                        lo: lo,
376                        curr: start,
377                        hi: start,
378                    }
379                }
380
381                /// Creates a new binary searcher which will not search below
382                /// the given `lo` value.
383                pub fn new_above(lo: $typ, start: $typ) -> Self {
384                    BinarySearch::new_clamped(lo, start, start)
385                }
386
387                fn reposition(&mut self) -> bool {
388                    let interval = self.hi - self.lo;
389                    let new_mid = self.lo + interval / 2;
390
391                    if new_mid == self.curr {
392                        false
393                    } else {
394                        self.curr = new_mid;
395                        true
396                    }
397                }
398            }
399            impl ValueTree for BinarySearch {
400                type Value = $typ;
401
402                fn current(&self) -> $typ {
403                    self.curr
404                }
405
406                fn simplify(&mut self) -> bool {
407                    if self.hi <= self.lo {
408                        return false;
409                    }
410
411                    self.hi = self.curr;
412                    self.reposition()
413                }
414
415                fn complicate(&mut self) -> bool {
416                    if self.hi <= self.lo {
417                        return false;
418                    }
419
420                    self.lo = self.curr + 1;
421                    self.reposition()
422                }
423            }
424
425            numeric_api!($typ, 1, $uniform, $incl);
426        }
427    };
428}
429
430signed_integer_bin_search!(i8);
431signed_integer_bin_search!(i16);
432signed_integer_bin_search!(i32);
433signed_integer_bin_search!(i64);
434signed_integer_bin_search!(i128);
435signed_integer_bin_search!(isize, unsupported_int_any, isize_sample_uniform, isize_sample_uniform_incl);
436unsigned_integer_bin_search!(u8);
437unsigned_integer_bin_search!(u16);
438unsigned_integer_bin_search!(u32);
439unsigned_integer_bin_search!(u64);
440unsigned_integer_bin_search!(u128);
441unsigned_integer_bin_search!(usize, unsupported_int_any, usize_sample_uniform, usize_sample_uniform_incl);
442
443bitflags! {
444    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
445    pub(crate) struct FloatTypes: u32 {
446        const POSITIVE          = 0b0000_0001;
447        const NEGATIVE          = 0b0000_0010;
448        const NORMAL            = 0b0000_0100;
449        const SUBNORMAL         = 0b0000_1000;
450        const ZERO              = 0b0001_0000;
451        const INFINITE          = 0b0010_0000;
452        const QUIET_NAN         = 0b0100_0000;
453        const SIGNALING_NAN     = 0b1000_0000;
454        const ANY =
455            Self::POSITIVE.bits() |
456            Self::NEGATIVE.bits() |
457            Self::NORMAL.bits() |
458            Self::SUBNORMAL.bits() |
459            Self::ZERO.bits() |
460            Self::INFINITE.bits() |
461            Self::QUIET_NAN.bits();
462    }
463}
464
465impl FloatTypes {
466    fn normalise(mut self) -> Self {
467        if !self.intersects(FloatTypes::POSITIVE | FloatTypes::NEGATIVE) {
468            self |= FloatTypes::POSITIVE;
469        }
470
471        if !self.intersects(
472            FloatTypes::NORMAL
473                | FloatTypes::SUBNORMAL
474                | FloatTypes::ZERO
475                | FloatTypes::INFINITE
476                | FloatTypes::QUIET_NAN
477                | FloatTypes::SIGNALING_NAN,
478        ) {
479            self |= FloatTypes::NORMAL;
480        }
481        self
482    }
483}
484
485trait FloatLayout
486where
487    StandardUniform: Distribution<Self::Bits>,
488{
489    type Bits: Copy;
490
491    const SIGN_MASK: Self::Bits;
492    const EXP_MASK: Self::Bits;
493    const EXP_ZERO: Self::Bits;
494    const MANTISSA_MASK: Self::Bits;
495}
496
497impl FloatLayout for f32 {
498    type Bits = u32;
499
500    const SIGN_MASK: u32 = 0x8000_0000;
501    const EXP_MASK: u32 = 0x7F80_0000;
502    const EXP_ZERO: u32 = 0x3F80_0000;
503    const MANTISSA_MASK: u32 = 0x007F_FFFF;
504}
505
506impl FloatLayout for f64 {
507    type Bits = u64;
508
509    const SIGN_MASK: u64 = 0x8000_0000_0000_0000;
510    const EXP_MASK: u64 = 0x7FF0_0000_0000_0000;
511    const EXP_ZERO: u64 = 0x3FF0_0000_0000_0000;
512    const MANTISSA_MASK: u64 = 0x000F_FFFF_FFFF_FFFF;
513}
514
515macro_rules! float_any {
516    ($typ:ident) => {
517        /// Strategies which produce floating-point values from particular
518        /// classes. See the various `Any`-typed constants in this module.
519        ///
520        /// Note that this usage is fairly advanced and primarily useful to
521        /// implementors of algorithms that need to handle wild values in a
522        /// particular way. For testing things like graphics processing or game
523        /// physics, simply using ranges (e.g., `-1.0..2.0`) will often be more
524        /// practical.
525        ///
526        /// `Any` can be OR'ed to combine multiple classes. For example,
527        /// `POSITIVE | INFINITE` will generate arbitrary positive, non-NaN
528        /// floats, including positive infinity (but not negative infinity, of
529        /// course).
530        ///
531        /// If neither `POSITIVE` nor `NEGATIVE` has been OR'ed into an `Any`
532        /// but a type to be generated requires a sign, `POSITIVE` is assumed.
533        /// If no classes are OR'ed into an `Any` (i.e., only `POSITIVE` and/or
534        /// `NEGATIVE` are given), `NORMAL` is assumed.
535        ///
536        /// The various float classes are assigned fixed weights for generation
537        /// which are believed to be reasonable for most applications. Roughly:
538        ///
539        /// - If `POSITIVE | NEGATIVE`, the sign is evenly distributed between
540        ///   both options.
541        ///
542        /// - Classes are weighted as follows, in descending order:
543        ///   `NORMAL` > `ZERO` > `SUBNORMAL` > `INFINITE` > `QUIET_NAN` =
544        ///   `SIGNALING_NAN`.
545        #[derive(Clone, Copy, Debug)]
546        #[must_use = "strategies do nothing unless used"]
547        pub struct Any(FloatTypes);
548
549        #[cfg(test)]
550        impl Any {
551            pub(crate) fn from_bits(bits: u32) -> Self {
552                Any(FloatTypes::from_bits_truncate(bits))
553            }
554
555            pub(crate) fn normal_bits(&self) -> FloatTypes {
556                self.0.normalise()
557            }
558        }
559
560        impl ops::BitOr for Any {
561            type Output = Self;
562
563            fn bitor(self, rhs: Self) -> Self {
564                Any(self.0 | rhs.0)
565            }
566        }
567
568        impl ops::BitOrAssign for Any {
569            fn bitor_assign(&mut self, rhs: Self) {
570                self.0 |= rhs.0
571            }
572        }
573
574        /// Generates positive floats
575        ///
576        /// By itself, implies the `NORMAL` class, unless another class is
577        /// OR'ed in. That is, using `POSITIVE` as a strategy by itself will
578        /// generate arbitrary values between the type's `MIN_POSITIVE` and
579        /// `MAX`, while `POSITIVE | INFINITE` would only allow generating
580        /// positive infinity.
581        pub const POSITIVE: Any = Any(FloatTypes::POSITIVE);
582        /// Generates negative floats.
583        ///
584        /// By itself, implies the `NORMAL` class, unless another class is
585        /// OR'ed in. That is, using `POSITIVE` as a strategy by itself will
586        /// generate arbitrary values between the type's `MIN` and
587        /// `-MIN_POSITIVE`, while `NEGATIVE | INFINITE` would only allow
588        /// generating positive infinity.
589        pub const NEGATIVE: Any = Any(FloatTypes::NEGATIVE);
590        /// Generates "normal" floats.
591        ///
592        /// These are finite values where the first bit of the mantissa is an
593        /// implied `1`. When positive, this represents the range
594        /// `MIN_POSITIVE` through `MAX`, both inclusive.
595        ///
596        /// Generated values are uniform over the discrete floating-point
597        /// space, which means the numeric distribution is an inverse
598        /// exponential step function. For example, values between 1.0 and 2.0
599        /// are generated with the same frequency as values between 2.0 and
600        /// 4.0, even though the latter covers twice the numeric range.
601        ///
602        /// If neither `POSITIVE` nor `NEGATIVE` is OR'ed with this constant,
603        /// `POSITIVE` is implied.
604        pub const NORMAL: Any = Any(FloatTypes::NORMAL);
605        /// Generates subnormal floats.
606        ///
607        /// These are finite non-zero values where the first bit of the
608        /// mantissa is not an implied zero. When positive, this represents the
609        /// range `MIN`, inclusive, through `MIN_POSITIVE`, exclusive.
610        ///
611        /// Subnormals are generated with a uniform distribution both in terms
612        /// of discrete floating-point space and numerically.
613        ///
614        /// If neither `POSITIVE` nor `NEGATIVE` is OR'ed with this constant,
615        /// `POSITIVE` is implied.
616        pub const SUBNORMAL: Any = Any(FloatTypes::SUBNORMAL);
617        /// Generates zero-valued floats.
618        ///
619        /// Note that IEEE floats support both positive and negative zero, so
620        /// this class does interact with the sign flags.
621        ///
622        /// If neither `POSITIVE` nor `NEGATIVE` is OR'ed with this constant,
623        /// `POSITIVE` is implied.
624        pub const ZERO: Any = Any(FloatTypes::ZERO);
625        /// Generates infinity floats.
626        ///
627        /// If neither `POSITIVE` nor `NEGATIVE` is OR'ed with this constant,
628        /// `POSITIVE` is implied.
629        pub const INFINITE: Any = Any(FloatTypes::INFINITE);
630        /// Generates "Quiet NaN" floats.
631        ///
632        /// Operations on quiet NaNs generally simply propagate the NaN rather
633        /// than invoke any exception mechanism.
634        ///
635        /// The payload of the NaN is uniformly distributed over the possible
636        /// values which safe Rust allows, including the sign bit (as
637        /// controlled by `POSITIVE` and `NEGATIVE`).
638        ///
639        /// Note however that in Rust 1.23.0 and earlier, this constitutes only
640        /// one particular payload due to apparent issues with particular MIPS
641        /// and PA-RISC processors which fail to implement IEEE 754-2008
642        /// correctly.
643        ///
644        /// On Rust 1.24.0 and later, this does produce arbitrary payloads as
645        /// documented.
646        ///
647        /// On platforms where the CPU and the IEEE standard disagree on the
648        /// format of a quiet NaN, values generated conform to the hardware's
649        /// expectations.
650        pub const QUIET_NAN: Any = Any(FloatTypes::QUIET_NAN);
651        /// Generates "Signaling NaN" floats if allowed by the platform.
652        ///
653        /// On most platforms, signalling NaNs by default behave the same as
654        /// quiet NaNs, but it is possible to configure the OS or CPU to raise
655        /// an asynchronous exception if an operation is performed on a
656        /// signalling NaN.
657        ///
658        /// In Rust 1.23.0 and earlier, this silently behaves the same as
659        /// [`QUIET_NAN`](const.QUIET_NAN.html).
660        ///
661        /// On platforms where the CPU and the IEEE standard disagree on the
662        /// format of a quiet NaN, values generated conform to the hardware's
663        /// expectations.
664        ///
665        /// Note that certain platforms — most notably, x86/AMD64 — allow the
666        /// architecture to turn a signalling NaN into a quiet NaN with the
667        /// same payload. Whether this happens can depend on what registers the
668        /// compiler decides to use to pass the value around, what CPU flags
669        /// are set, and what compiler settings are in use.
670        pub const SIGNALING_NAN: Any = Any(FloatTypes::SIGNALING_NAN);
671
672        /// Generates literally arbitrary floating-point values, including
673        /// infinities and quiet NaNs (but not signaling NaNs).
674        ///
675        /// Equivalent to `POSITIVE | NEGATIVE | NORMAL | SUBNORMAL | ZERO |
676        /// INFINITE | QUIET_NAN`.
677        ///
678        /// See [`SIGNALING_NAN`](const.SIGNALING_NAN.html) if you also want to
679        /// generate signalling NaNs. This signalling NaNs are not included by
680        /// default since in most contexts they either make no difference, or
681        /// if the process enabled the relevant CPU mode, result in
682        /// hardware-triggered exceptions that usually just abort the process.
683        ///
684        /// Before proptest 0.4.1, this erroneously generated values in the
685        /// range 0.0..1.0.
686        pub const ANY: Any = Any(FloatTypes::ANY);
687
688        impl Strategy for Any {
689            type Tree = BinarySearch;
690            type Value = $typ;
691
692            fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
693                let flags = self.0.normalise();
694                let sign_mask = if flags.contains(FloatTypes::NEGATIVE) {
695                    $typ::SIGN_MASK
696                } else {
697                    0
698                };
699                let sign_or = if flags.contains(FloatTypes::POSITIVE) {
700                    0
701                } else {
702                    $typ::SIGN_MASK
703                };
704
705                macro_rules! weight {
706                    ($case:ident, $weight:expr) => {
707                        if flags.contains(FloatTypes::$case) {
708                            $weight
709                        } else {
710                            0
711                        }
712                    }
713                }
714
715                // A few CPUs disagree with IEEE about the meaning of the
716                // signalling bit. Assume the `NAN` constant is a quiet NaN as
717                // interpreted by the hardware and generate values based on
718                // that.
719                let quiet_or = ::core::$typ::NAN.to_bits() &
720                    ($typ::EXP_MASK | ($typ::EXP_MASK >> 1));
721                let signaling_or = (quiet_or ^ ($typ::EXP_MASK >> 1)) |
722                    $typ::EXP_MASK;
723
724                let (class_mask, class_or, allow_edge_exp, allow_zero_mant) =
725                    prop_oneof![
726                        weight!(NORMAL, 20) => Just(
727                            ($typ::EXP_MASK | $typ::MANTISSA_MASK, 0,
728                             false, true)),
729                        weight!(SUBNORMAL, 3) => Just(
730                            ($typ::MANTISSA_MASK, 0, true, false)),
731                        weight!(ZERO, 4) => Just(
732                            (0, 0, true, true)),
733                        weight!(INFINITE, 2) => Just(
734                            (0, $typ::EXP_MASK, true, true)),
735                        weight!(QUIET_NAN, 1) => Just(
736                            ($typ::MANTISSA_MASK >> 1, quiet_or,
737                             true, false)),
738                        weight!(SIGNALING_NAN, 1) => Just(
739                            ($typ::MANTISSA_MASK >> 1, signaling_or,
740                             true, false)),
741                    ].new_tree(runner)?.current();
742
743                let mut generated_value: <$typ as FloatLayout>::Bits =
744                    runner.rng().random();
745                generated_value &= sign_mask | class_mask;
746                generated_value |= sign_or | class_or;
747                let exp = generated_value & $typ::EXP_MASK;
748                if !allow_edge_exp && (0 == exp || $typ::EXP_MASK == exp) {
749                    generated_value &= !$typ::EXP_MASK;
750                    generated_value |= $typ::EXP_ZERO;
751                }
752                if !allow_zero_mant &&
753                    0 == generated_value & $typ::MANTISSA_MASK
754                {
755                    generated_value |= 1;
756                }
757
758                Ok(BinarySearch::new_with_types(
759                    $typ::from_bits(generated_value), flags))
760            }
761        }
762    }
763}
764
765macro_rules! float_bin_search {
766    ($typ:ident, $sample_typ:ident) => {
767        #[allow(missing_docs)]
768        pub mod $typ {
769            use super::float_samplers::$sample_typ;
770
771            use core::ops;
772            #[cfg(not(feature = "std"))]
773            use num_traits::float::FloatCore;
774
775            use rand::Rng;
776
777            use super::{FloatLayout, FloatTypes};
778            use crate::strategy::*;
779            use crate::test_runner::TestRunner;
780
781            float_any!($typ);
782
783            /// Shrinks a float towards 0, using binary search to find boundary
784            /// points.
785            ///
786            /// Non-finite values immediately shrink to 0.
787            #[derive(Clone, Copy, Debug)]
788            pub struct BinarySearch {
789                lo: $typ,
790                curr: $typ,
791                hi: $typ,
792                allowed: FloatTypes,
793            }
794
795            impl BinarySearch {
796                /// Creates a new binary searcher starting at the given value.
797                pub fn new(start: $typ) -> Self {
798                    BinarySearch {
799                        lo: 0.0,
800                        curr: start,
801                        hi: start,
802                        allowed: FloatTypes::all(),
803                    }
804                }
805
806                fn new_with_types(start: $typ, allowed: FloatTypes) -> Self {
807                    BinarySearch {
808                        lo: 0.0,
809                        curr: start,
810                        hi: start,
811                        allowed,
812                    }
813                }
814
815                /// Creates a new binary searcher which will not produce values
816                /// on the other side of `lo` or `hi` from `start`. `lo` is
817                /// inclusive, `hi` is exclusive.
818                fn new_clamped(lo: $typ, start: $typ, hi: $typ) -> Self {
819                    BinarySearch {
820                        lo: if start.is_sign_negative() {
821                            hi.min(0.0)
822                        } else {
823                            lo.max(0.0)
824                        },
825                        hi: start,
826                        curr: start,
827                        allowed: FloatTypes::all(),
828                    }
829                }
830
831                fn current_allowed(&self) -> bool {
832                    use core::num::FpCategory::*;
833
834                    // Don't reposition if the new value is not allowed
835                    let class_allowed = match self.curr.classify() {
836                        Nan =>
837                        // We don't need to inspect whether the
838                        // signallingness of the NaN matches the allowed
839                        // set, as we never try to switch between them,
840                        // instead shrinking to 0.
841                        {
842                            self.allowed.contains(FloatTypes::QUIET_NAN)
843                                || self
844                                    .allowed
845                                    .contains(FloatTypes::SIGNALING_NAN)
846                        }
847                        Infinite => self.allowed.contains(FloatTypes::INFINITE),
848                        Zero => self.allowed.contains(FloatTypes::ZERO),
849                        Subnormal => {
850                            self.allowed.contains(FloatTypes::SUBNORMAL)
851                        }
852                        Normal => self.allowed.contains(FloatTypes::NORMAL),
853                    };
854                    let signum = self.curr.signum();
855                    let sign_allowed = if signum > 0.0 {
856                        self.allowed.contains(FloatTypes::POSITIVE)
857                    } else if signum < 0.0 {
858                        self.allowed.contains(FloatTypes::NEGATIVE)
859                    } else {
860                        true
861                    };
862
863                    class_allowed && sign_allowed
864                }
865
866                fn ensure_acceptable(&mut self) {
867                    while !self.current_allowed() {
868                        if !self.complicate_once() {
869                            panic!(
870                                "Unable to complicate floating-point back \
871                                 to acceptable value"
872                            );
873                        }
874                    }
875                }
876
877                fn reposition(&mut self) -> bool {
878                    let interval = self.hi - self.lo;
879                    let interval =
880                        if interval.is_finite() { interval } else { 0.0 };
881                    let new_mid = self.lo + interval / 2.0;
882
883                    let new_mid = if new_mid == self.curr || 0.0 == interval {
884                        new_mid
885                    } else {
886                        self.lo
887                    };
888
889                    if new_mid == self.curr {
890                        false
891                    } else {
892                        self.curr = new_mid;
893                        true
894                    }
895                }
896
897                fn done(lo: $typ, hi: $typ) -> bool {
898                    (lo.abs() > hi.abs() && !hi.is_nan()) || lo.is_nan()
899                }
900
901                fn complicate_once(&mut self) -> bool {
902                    if BinarySearch::done(self.lo, self.hi) {
903                        return false;
904                    }
905
906                    self.lo = if self.curr == self.lo {
907                        self.hi
908                    } else {
909                        self.curr
910                    };
911
912                    self.reposition()
913                }
914            }
915            impl ValueTree for BinarySearch {
916                type Value = $typ;
917
918                fn current(&self) -> $typ {
919                    self.curr
920                }
921
922                fn simplify(&mut self) -> bool {
923                    if BinarySearch::done(self.lo, self.hi) {
924                        return false;
925                    }
926
927                    self.hi = self.curr;
928                    if self.reposition() {
929                        self.ensure_acceptable();
930                        true
931                    } else {
932                        false
933                    }
934                }
935
936                fn complicate(&mut self) -> bool {
937                    if self.complicate_once() {
938                        self.ensure_acceptable();
939                        true
940                    } else {
941                        false
942                    }
943                }
944            }
945
946            numeric_api!($typ, $sample_typ, 0.0);
947        }
948    };
949}
950
951float_bin_search!(f32, F32U);
952float_bin_search!(f64, F64U);
953
954#[cfg(test)]
955mod test {
956    use crate::strategy::*;
957    use crate::test_runner::*;
958
959    use super::*;
960
961    #[test]
962    fn u8_inclusive_end_included() {
963        let mut runner = TestRunner::deterministic();
964        let mut ok = 0;
965        for _ in 0..20 {
966            let tree = (0..=1).new_tree(&mut runner).unwrap();
967            let test = runner.run_one(tree, |v| {
968                prop_assert_eq!(v, 1);
969                Ok(())
970            });
971            if test.is_ok() {
972                ok += 1;
973            }
974        }
975        assert!(ok > 1, "inclusive end not included.");
976    }
977
978    #[test]
979    fn u8_inclusive_to_end_included() {
980        let mut runner = TestRunner::deterministic();
981        let mut ok = 0;
982        for _ in 0..20 {
983            let tree = (..=1u8).new_tree(&mut runner).unwrap();
984            let test = runner.run_one(tree, |v| {
985                prop_assert_eq!(v, 1);
986                Ok(())
987            });
988            if test.is_ok() {
989                ok += 1;
990            }
991        }
992        assert!(ok > 1, "inclusive end not included.");
993    }
994
995    #[test]
996    fn i8_binary_search_always_converges() {
997        fn assert_converges<P: Fn(i32) -> bool>(start: i8, pass: P) {
998            let mut state = i8::BinarySearch::new(start);
999            loop {
1000                if !pass(state.current() as i32) {
1001                    if !state.simplify() {
1002                        break;
1003                    }
1004                } else {
1005                    if !state.complicate() {
1006                        break;
1007                    }
1008                }
1009            }
1010
1011            assert!(!pass(state.current() as i32));
1012            assert!(
1013                pass(state.current() as i32 - 1)
1014                    || pass(state.current() as i32 + 1)
1015            );
1016        }
1017
1018        for start in -128..0 {
1019            for target in start + 1..1 {
1020                assert_converges(start as i8, |v| v > target);
1021            }
1022        }
1023
1024        for start in 0..128 {
1025            for target in 0..start {
1026                assert_converges(start as i8, |v| v < target);
1027            }
1028        }
1029    }
1030
1031    #[test]
1032    fn u8_binary_search_always_converges() {
1033        fn assert_converges<P: Fn(u32) -> bool>(start: u8, pass: P) {
1034            let mut state = u8::BinarySearch::new(start);
1035            loop {
1036                if !pass(state.current() as u32) {
1037                    if !state.simplify() {
1038                        break;
1039                    }
1040                } else {
1041                    if !state.complicate() {
1042                        break;
1043                    }
1044                }
1045            }
1046
1047            assert!(!pass(state.current() as u32));
1048            assert!(pass(state.current() as u32 - 1));
1049        }
1050
1051        for start in 0..255 {
1052            for target in 0..start {
1053                assert_converges(start as u8, |v| v <= target);
1054            }
1055        }
1056    }
1057
1058    #[test]
1059    fn signed_integer_range_including_zero_converges_to_zero() {
1060        let mut runner = TestRunner::default();
1061        for _ in 0..100 {
1062            let mut state = (-42i32..64i32).new_tree(&mut runner).unwrap();
1063            let init_value = state.current();
1064            assert!(init_value >= -42 && init_value < 64);
1065
1066            while state.simplify() {
1067                let v = state.current();
1068                assert!(v >= -42 && v < 64);
1069            }
1070
1071            assert_eq!(0, state.current());
1072        }
1073    }
1074
1075    #[test]
1076    fn negative_integer_range_stays_in_bounds() {
1077        let mut runner = TestRunner::default();
1078        for _ in 0..100 {
1079            let mut state = (..-42i32).new_tree(&mut runner).unwrap();
1080            let init_value = state.current();
1081            assert!(init_value < -42);
1082
1083            while state.simplify() {
1084                assert!(
1085                    state.current() < -42,
1086                    "Violated bounds: {}",
1087                    state.current()
1088                );
1089            }
1090
1091            assert_eq!(-43, state.current());
1092        }
1093    }
1094
1095    #[test]
1096    fn positive_signed_integer_range_stays_in_bounds() {
1097        let mut runner = TestRunner::default();
1098        for _ in 0..100 {
1099            let mut state = (42i32..).new_tree(&mut runner).unwrap();
1100            let init_value = state.current();
1101            assert!(init_value >= 42);
1102
1103            while state.simplify() {
1104                assert!(
1105                    state.current() >= 42,
1106                    "Violated bounds: {}",
1107                    state.current()
1108                );
1109            }
1110
1111            assert_eq!(42, state.current());
1112        }
1113    }
1114
1115    #[test]
1116    fn unsigned_integer_range_stays_in_bounds() {
1117        let mut runner = TestRunner::default();
1118        for _ in 0..100 {
1119            let mut state = (42u32..56u32).new_tree(&mut runner).unwrap();
1120            let init_value = state.current();
1121            assert!(init_value >= 42 && init_value < 56);
1122
1123            while state.simplify() {
1124                assert!(
1125                    state.current() >= 42,
1126                    "Violated bounds: {}",
1127                    state.current()
1128                );
1129            }
1130
1131            assert_eq!(42, state.current());
1132        }
1133    }
1134
1135    mod contract_sanity {
1136        macro_rules! contract_sanity {
1137            ($t:tt) => {
1138                mod $t {
1139                    use crate::strategy::check_strategy_sanity;
1140
1141                    const FORTY_TWO: $t = 42 as $t;
1142                    const FIFTY_SIX: $t = 56 as $t;
1143
1144                    #[test]
1145                    fn range() {
1146                        check_strategy_sanity(FORTY_TWO..FIFTY_SIX, None);
1147                    }
1148
1149                    #[test]
1150                    fn range_inclusive() {
1151                        check_strategy_sanity(FORTY_TWO..=FIFTY_SIX, None);
1152                    }
1153
1154                    #[test]
1155                    fn range_to() {
1156                        check_strategy_sanity(..FIFTY_SIX, None);
1157                    }
1158
1159                    #[test]
1160                    fn range_to_inclusive() {
1161                        check_strategy_sanity(..=FIFTY_SIX, None);
1162                    }
1163
1164                    #[test]
1165                    fn range_from() {
1166                        check_strategy_sanity(FORTY_TWO.., None);
1167                    }
1168                }
1169            };
1170        }
1171        contract_sanity!(u8);
1172        contract_sanity!(i8);
1173        contract_sanity!(u16);
1174        contract_sanity!(i16);
1175        contract_sanity!(u32);
1176        contract_sanity!(i32);
1177        contract_sanity!(u64);
1178        contract_sanity!(i64);
1179        contract_sanity!(usize);
1180        contract_sanity!(isize);
1181        contract_sanity!(f32);
1182        contract_sanity!(f64);
1183    }
1184
1185    #[test]
1186    fn unsigned_integer_binsearch_simplify_complicate_contract_upheld() {
1187        check_strategy_sanity(0u32..1000u32, None);
1188        check_strategy_sanity(0u32..1u32, None);
1189    }
1190
1191    #[test]
1192    fn signed_integer_binsearch_simplify_complicate_contract_upheld() {
1193        check_strategy_sanity(0i32..1000i32, None);
1194        check_strategy_sanity(0i32..1i32, None);
1195    }
1196
1197    #[test]
1198    fn positive_float_simplifies_to_zero() {
1199        let mut runner = TestRunner::default();
1200        let mut value = (0.0f64..2.0).new_tree(&mut runner).unwrap();
1201
1202        while value.simplify() {}
1203
1204        assert_eq!(0.0, value.current());
1205    }
1206
1207    #[test]
1208    fn positive_float_simplifies_to_base() {
1209        let mut runner = TestRunner::default();
1210        let mut value = (1.0f64..2.0).new_tree(&mut runner).unwrap();
1211
1212        while value.simplify() {}
1213
1214        assert_eq!(1.0, value.current());
1215    }
1216
1217    #[test]
1218    fn negative_float_simplifies_to_zero() {
1219        let mut runner = TestRunner::default();
1220        let mut value = (-2.0f64..0.0).new_tree(&mut runner).unwrap();
1221
1222        while value.simplify() {}
1223
1224        assert_eq!(0.0, value.current());
1225    }
1226
1227    #[test]
1228    fn positive_float_complicates_to_original() {
1229        let mut runner = TestRunner::default();
1230        let mut value = (1.0f64..2.0).new_tree(&mut runner).unwrap();
1231        let orig = value.current();
1232
1233        assert!(value.simplify());
1234        while value.complicate() {}
1235
1236        assert_eq!(orig, value.current());
1237    }
1238
1239    #[test]
1240    fn positive_infinity_simplifies_directly_to_zero() {
1241        let mut value = f64::BinarySearch::new(::std::f64::INFINITY);
1242
1243        assert!(value.simplify());
1244        assert_eq!(0.0, value.current());
1245        assert!(value.complicate());
1246        assert_eq!(::std::f64::INFINITY, value.current());
1247        assert!(!value.clone().complicate());
1248        assert!(!value.clone().simplify());
1249    }
1250
1251    #[test]
1252    fn negative_infinity_simplifies_directly_to_zero() {
1253        let mut value = f64::BinarySearch::new(::std::f64::NEG_INFINITY);
1254
1255        assert!(value.simplify());
1256        assert_eq!(0.0, value.current());
1257        assert!(value.complicate());
1258        assert_eq!(::std::f64::NEG_INFINITY, value.current());
1259        assert!(!value.clone().complicate());
1260        assert!(!value.clone().simplify());
1261    }
1262
1263    #[test]
1264    fn nan_simplifies_directly_to_zero() {
1265        let mut value = f64::BinarySearch::new(::std::f64::NAN);
1266
1267        assert!(value.simplify());
1268        assert_eq!(0.0, value.current());
1269        assert!(value.complicate());
1270        assert!(value.current().is_nan());
1271        assert!(!value.clone().complicate());
1272        assert!(!value.clone().simplify());
1273    }
1274
1275    #[test]
1276    fn float_simplifies_to_smallest_normal() {
1277        let mut runner = TestRunner::default();
1278        let mut value = (::std::f64::MIN_POSITIVE..2.0)
1279            .new_tree(&mut runner)
1280            .unwrap();
1281
1282        while value.simplify() {}
1283
1284        assert_eq!(::std::f64::MIN_POSITIVE, value.current());
1285    }
1286
1287    macro_rules! float_generation_test_body {
1288        ($strategy:ident, $typ:ident) => {
1289            use std::num::FpCategory;
1290
1291            let strategy = $strategy;
1292            let bits = strategy.normal_bits();
1293
1294            let mut seen_positive = 0;
1295            let mut seen_negative = 0;
1296            let mut seen_normal = 0;
1297            let mut seen_subnormal = 0;
1298            let mut seen_zero = 0;
1299            let mut seen_infinite = 0;
1300            let mut seen_quiet_nan = 0;
1301            let mut seen_signaling_nan = 0;
1302            let mut runner = TestRunner::deterministic();
1303
1304            // Check whether this version of Rust honours the NaN payload in
1305            // from_bits
1306            let fidelity_1 = f32::from_bits(0x7F80_0001).to_bits();
1307            let fidelity_2 = f32::from_bits(0xFF80_0001).to_bits();
1308            let nan_fidelity = fidelity_1 != fidelity_2;
1309
1310            for _ in 0..1024 {
1311                let mut tree = strategy.new_tree(&mut runner).unwrap();
1312                let mut increment = 1;
1313
1314                loop {
1315                    let value = tree.current();
1316
1317                    let sign = value.signum(); // So we correctly handle -0
1318                    if sign < 0.0 {
1319                        prop_assert!(bits.contains(FloatTypes::NEGATIVE));
1320                        seen_negative += increment;
1321                    } else if sign > 0.0 {
1322                        // i.e., not NaN
1323                        prop_assert!(bits.contains(FloatTypes::POSITIVE));
1324                        seen_positive += increment;
1325                    }
1326
1327                    match value.classify() {
1328                        FpCategory::Nan if nan_fidelity => {
1329                            let raw = value.to_bits();
1330                            let is_negative = raw << 1 >> 1 != raw;
1331                            if is_negative {
1332                                prop_assert!(
1333                                    bits.contains(FloatTypes::NEGATIVE)
1334                                );
1335                                seen_negative += increment;
1336                            } else {
1337                                prop_assert!(
1338                                    bits.contains(FloatTypes::POSITIVE)
1339                                );
1340                                seen_positive += increment;
1341                            }
1342
1343                            let is_quiet = raw & ($typ::EXP_MASK >> 1)
1344                                == ::std::$typ::NAN.to_bits()
1345                                    & ($typ::EXP_MASK >> 1);
1346                            if is_quiet {
1347                                // x86/AMD64 turn signalling NaNs into quiet
1348                                // NaNs quite aggressively depending on what
1349                                // registers LLVM decides to use to pass the
1350                                // value around, so accept either case here.
1351                                prop_assert!(
1352                                    bits.contains(FloatTypes::QUIET_NAN)
1353                                        || bits.contains(
1354                                            FloatTypes::SIGNALING_NAN
1355                                        )
1356                                );
1357                                seen_quiet_nan += increment;
1358                                seen_signaling_nan += increment;
1359                            } else {
1360                                prop_assert!(
1361                                    bits.contains(FloatTypes::SIGNALING_NAN)
1362                                );
1363                                seen_signaling_nan += increment;
1364                            }
1365                        }
1366
1367                        FpCategory::Nan => {
1368                            // Since safe Rust doesn't currently allow
1369                            // generating any NaN other than one particular
1370                            // payload, don't check the sign or signallingness
1371                            // and consider this to be both signs and
1372                            // signallingness for counting purposes.
1373                            seen_positive += increment;
1374                            seen_negative += increment;
1375                            seen_quiet_nan += increment;
1376                            seen_signaling_nan += increment;
1377                            prop_assert!(
1378                                bits.contains(FloatTypes::QUIET_NAN)
1379                                    || bits.contains(FloatTypes::SIGNALING_NAN)
1380                            );
1381                        }
1382                        FpCategory::Infinite => {
1383                            prop_assert!(bits.contains(FloatTypes::INFINITE));
1384                            seen_infinite += increment;
1385                        }
1386                        FpCategory::Zero => {
1387                            prop_assert!(bits.contains(FloatTypes::ZERO));
1388                            seen_zero += increment;
1389                        }
1390                        FpCategory::Subnormal => {
1391                            prop_assert!(bits.contains(FloatTypes::SUBNORMAL));
1392                            seen_subnormal += increment;
1393                        }
1394                        FpCategory::Normal => {
1395                            prop_assert!(bits.contains(FloatTypes::NORMAL));
1396                            seen_normal += increment;
1397                        }
1398                    }
1399
1400                    // Don't count simplified values towards the counts
1401                    increment = 0;
1402                    if !tree.simplify() {
1403                        break;
1404                    }
1405                }
1406            }
1407
1408            if bits.contains(FloatTypes::POSITIVE) {
1409                prop_assert!(seen_positive > 200);
1410            }
1411            if bits.contains(FloatTypes::NEGATIVE) {
1412                prop_assert!(seen_negative > 200);
1413            }
1414            if bits.contains(FloatTypes::NORMAL) {
1415                prop_assert!(seen_normal > 100);
1416            }
1417            if bits.contains(FloatTypes::SUBNORMAL) {
1418                prop_assert!(seen_subnormal > 5);
1419            }
1420            if bits.contains(FloatTypes::ZERO) {
1421                prop_assert!(seen_zero > 5);
1422            }
1423            if bits.contains(FloatTypes::INFINITE) {
1424                prop_assert!(seen_infinite > 0);
1425            }
1426            if bits.contains(FloatTypes::QUIET_NAN) {
1427                prop_assert!(seen_quiet_nan > 0);
1428            }
1429            if bits.contains(FloatTypes::SIGNALING_NAN) {
1430                prop_assert!(seen_signaling_nan > 0);
1431            }
1432        };
1433    }
1434
1435    proptest! {
1436        #![proptest_config(crate::test_runner::Config::with_cases(1024))]
1437
1438        #[test]
1439        fn f32_any_generates_desired_values(
1440            strategy in crate::bits::u32::ANY.prop_map(f32::Any::from_bits)
1441        ) {
1442            float_generation_test_body!(strategy, f32);
1443        }
1444
1445        #[test]
1446        fn f32_any_sanity(
1447            strategy in crate::bits::u32::ANY.prop_map(f32::Any::from_bits)
1448        ) {
1449            check_strategy_sanity(strategy, Some(CheckStrategySanityOptions {
1450                strict_complicate_after_simplify: false,
1451                .. CheckStrategySanityOptions::default()
1452            }));
1453        }
1454
1455        #[test]
1456        fn f64_any_generates_desired_values(
1457            strategy in crate::bits::u32::ANY.prop_map(f64::Any::from_bits)
1458        ) {
1459            float_generation_test_body!(strategy, f64);
1460        }
1461
1462        #[test]
1463        fn f64_any_sanity(
1464            strategy in crate::bits::u32::ANY.prop_map(f64::Any::from_bits)
1465        ) {
1466            check_strategy_sanity(strategy, Some(CheckStrategySanityOptions {
1467                strict_complicate_after_simplify: false,
1468                .. CheckStrategySanityOptions::default()
1469            }));
1470        }
1471    }
1472
1473    mod panic_on_empty {
1474        macro_rules! panic_on_empty {
1475            ($t:tt) => {
1476                mod $t {
1477                    use crate::strategy::Strategy;
1478                    use crate::test_runner::TestRunner;
1479                    use std::panic;
1480                    use std::string::String;
1481
1482                    const ZERO: $t = 0 as $t;
1483                    const ONE: $t = 1 as $t;
1484
1485                    #[test]
1486                    fn range() {
1487                        assert_eq!(
1488                            panic::catch_unwind(|| {
1489                                let mut runner = TestRunner::deterministic();
1490                                let _ = (ZERO..ZERO).new_tree(&mut runner);
1491                            })
1492                            .err()
1493                            .and_then(|a| a
1494                                .downcast_ref::<String>()
1495                                .map(|s| {
1496                                    s == "Invalid use of empty range 0..0."
1497                                })),
1498                            Some(true)
1499                        );
1500                    }
1501
1502                    #[test]
1503                    fn range_inclusive() {
1504                        assert_eq!(
1505                            panic::catch_unwind(|| {
1506                                let mut runner = TestRunner::deterministic();
1507                                let _ = (ONE..=ZERO).new_tree(&mut runner);
1508                            })
1509                            .err()
1510                            .and_then(|a| a
1511                                .downcast_ref::<String>()
1512                                .map(|s| {
1513                                    s == "Invalid use of empty range 1..=0."
1514                                })),
1515                            Some(true)
1516                        );
1517                    }
1518                }
1519            };
1520        }
1521        panic_on_empty!(u8);
1522        panic_on_empty!(i8);
1523        panic_on_empty!(u16);
1524        panic_on_empty!(i16);
1525        panic_on_empty!(u32);
1526        panic_on_empty!(i32);
1527        panic_on_empty!(u64);
1528        panic_on_empty!(i64);
1529        panic_on_empty!(usize);
1530        panic_on_empty!(isize);
1531        panic_on_empty!(f32);
1532        panic_on_empty!(f64);
1533    }
1534}