Skip to main content

proptest/
num.rs

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