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