weird_data/
lib.rs

1//! Generate random data in such a way as to make rare edge-cases very likely.
2//!
3//! > Disclaimer: the random number generators used in this crate are NOT
4//! CRYPTOGRAPHICALLY SECURE. Only use these generators for generating testing
5//! inputs, do not rely on them for cryptographic purposes in production code!
6//! For instance, you may test a cryptographic tool with these generators, but
7//! you may not deploy code that relies on these generators for security in
8//! production.
9//!
10//! For instance, if generating a random `f32` by uniformly sampling 32 bits of
11//! data, certain values will rarely appear, such as `NAN` and `INFINITY`. When
12//! doing randomized testing, like fuzzing, it isn't very useful to repeatedly
13//! generate well-behaved data. It is much more useful if we can artificially
14//! increase the likelihood of these special values, so that we test with them
15//! more often.
16//!
17//! Additionally, some random number crates will never generate certain
18//! problematic bit-patterns, such as `NAN`.
19//!
20//! This crate is based on the [fastrand]() crate.
21//!
22//! This crate can work with `no_std`, if you disable the `std` feature. You
23//! cannot use the global functions when in a `no_std` environment. In that
24//! case, you can explicitly instantiate [Wdg] and call the methods on it.
25//! They are equivalent.
26//!
27//! If using `std`, it's more ergonomic to use the global functions in the
28//! [global_functions] module.
29
30#![cfg_attr(not(feature = "std"), no_std)]
31
32use fastrand as fr;
33use paste::paste;
34
35#[cfg(feature = "std")]
36mod global_functions;
37
38#[cfg(feature = "std")]
39pub use global_functions::*;
40
41#[cfg(test)]
42mod float_utils;
43
44/// A weird data generator
45#[derive(Clone)]
46pub struct Wdg(fr::Rng);
47
48macro_rules! int {
49    ($self:tt, [$($t:ty),+ $(,)?]) => {
50        $(
51            int_inner!($self, $t);
52        )+
53    };
54}
55
56macro_rules! int_inner {
57    ($self:tt, $t:ty) => {
58        paste! {
59            /// Generate a random
60            #[doc = stringify!($t)]
61            /// "special" value
62            ///
63            /// A special value is what I call specific values that are unique and
64            /// are pretty much impossible to generate by chance, and have some unusual
65            /// properties. For instance `MAX` and 0.
66            pub fn [<special_ $t>](&mut $self) -> $t {
67                match $self.0.u8(0..5) {
68                    0 => 0,
69                    1 => 1,
70                    2 => $t::MAX,
71                    3 => -1,
72                    4 => $t::MIN,
73                    _ => unreachable!(),
74                }
75            }
76
77            /// Generate a random
78            #[doc = stringify!($t)]
79            /// , such that special or problematic values are much
80            /// more common than normal.
81            pub fn $t(&mut $self) -> $t {
82                match $self.0.u8(0..3) {
83                    0 => $self.[<special_ $t>](),
84                    1 => $self.0.$t(2..$t::MAX),
85                    2 => $self.0.$t($t::MIN..-1),
86                    _ => unreachable!(),
87                }
88            }
89        }
90    };
91}
92
93macro_rules! uint {
94    ($self:tt, [$($t:ty),+ $(,)?]) => {
95        $(
96            uint_inner!($self, $t);
97        )+
98    };
99}
100
101macro_rules! uint_inner {
102    ($self:tt, $t:ty) => {
103        paste! {
104            /// Generate a random
105            #[doc = stringify!($t)]
106            /// "special" value
107            ///
108            /// A special value is what I call specific values that are unique and
109            /// are pretty much impossible to generate by chance, and have some unusual
110            /// properties.
111            pub fn [<special_ $t>](&mut $self) -> $t {
112                match $self.0.u8(0..3) {
113                    0 => 0,
114                    1 => 1,
115                    2 => $t::MAX,
116                    _ => unreachable!(),
117                }
118            }
119
120            pub fn $t(&mut $self) -> $t {
121                match $self.0.u8(0..2) {
122                    0 => $self.[<special_ $t>](),
123                    1 => $self.0.$t(2..$t::MAX),
124                    _ => unreachable!(),
125                }
126            }
127        }
128    };
129}
130
131impl Wdg {
132    #[must_use]
133    pub fn with_seed(seed: u64) -> Self {
134        Self(fr::Rng::with_seed(seed))
135    }
136
137    #[must_use]
138    pub fn fork(&mut self) -> Self {
139        Self(self.0.fork())
140    }
141
142    pub fn seed(&mut self, seed: u64) {
143        self.0.seed(seed);
144    }
145
146    pub fn get_seed(&mut self) -> u64 {
147        self.0.get_seed()
148    }
149
150    /// Generates a random f32 `NAN` value.
151    ///
152    /// There are multiple bit patterns that are equivalent to a `NAN`.
153    /// This generator covers all possible `NAN` values as specified in
154    /// IEEE-754, even ones that Rust would normally not generate.
155    pub fn nan_f32(&mut self) -> f32 {
156        let sign: u32 = self.0.u32(0..=1) << 31;
157        let exponent: u32 = 0b1111_1111 << 23;
158
159        // mantissa 00...00 is INFINITY not NAN!
160        let mantissa: u32 = self.0.u32(1..(1 << 23));
161
162        let bits = sign | exponent | mantissa;
163        f32::from_bits(bits)
164    }
165
166    /// Generates a random f64 `NAN` value.
167    ///
168    /// There are multiple bit patterns that are equivalent to a `NAN`.
169    /// This generator covers all possible `NAN` values as specified in
170    /// IEEE-754, even ones that Rust would normally not generate.
171    pub fn nan_f64(&mut self) -> f64 {
172        let sign: u64 = self.0.u64(0..=1) << 63;
173        let exponent: u64 = 0b0111_1111_1111 << 52;
174
175        // mantissa 00...00 is INFINITY not NAN!
176        let mantissa: u64 = self.0.u64(1..(1 << 52));
177
178        let bits = sign | exponent | mantissa;
179        f64::from_bits(bits)
180    }
181
182    /// Generates a random f32 denormal value.
183    ///
184    /// This generator covers all possible denormal values as specified in
185    /// IEEE-754.
186    pub fn subnormal_f32(&mut self) -> f32 {
187        let sign: u32 = self.0.u32(0..=1) << 31;
188
189        // mantissa 00...00 is zero not denormal!
190        let mantissa: u32 = self.0.u32(1..(1 << 23));
191
192        let bits = sign | mantissa;
193        f32::from_bits(bits)
194    }
195
196    /// Generates a random f64 denormal value.
197    ///
198    /// This generator covers all possible denormal values as specified in
199    /// IEEE-754.
200    pub fn subnormal_f64(&mut self) -> f64 {
201        let sign: u64 = self.0.u64(0..=1) << 63;
202
203        // mantissa 00...00 is zero not denormal!
204        let mantissa: u64 = self.0.u64(1..(1 << 52));
205
206        let bits = sign | mantissa;
207        f64::from_bits(bits)
208    }
209
210    /// Generate a random f32 normal value
211    pub fn normal_f32(&mut self) -> f32 {
212        let sign: u32 = self.0.u32(0..=1) << 31;
213
214        // careful with this range, all zeros and all ones are not normal
215        let exponent: u32 = self.0.u32(0b0000_0001..=0b1111_1110) << 23;
216
217        let mantissa: u32 = self.0.u32(0..=(1 << 23));
218        let bits = sign | exponent | mantissa;
219        f32::from_bits(bits)
220    }
221
222    /// Generate a random f64 normal value
223    pub fn normal_f64(&mut self) -> f64 {
224        let sign: u64 = self.0.u64(0..=1) << 63;
225
226        // careful with this range, all zeros and all ones are not normal
227        let exponent: u64 = self.0.u64(0b000_0000_0001..=0b111_1111_1110) << 52;
228
229        let mantissa: u64 = self.0.u64(0..=(1 << 52));
230        let bits = sign | exponent | mantissa;
231        f64::from_bits(bits)
232    }
233
234    /// Generate a random f32 "special" value
235    ///
236    /// A special value is what I call specific float values that are unique and
237    /// are pretty much impossible to generate by chance, and have some unusual
238    /// properties.
239    pub fn special_f32(&mut self) -> f32 {
240        match self.0.u8(0..=11) {
241            0 => 0.0,
242            1 => -0.0,
243            2 => f32::INFINITY,
244            3 => -f32::INFINITY,
245            4 => 1.0,
246            5 => -1.0,
247            6 => f32::MIN,
248            7 => f32::MAX,
249            8 => f32::MIN_POSITIVE,
250            9 => -f32::MIN_POSITIVE,
251            10 => f32::EPSILON,
252            11 => -f32::EPSILON,
253            _ => unreachable!(),
254        }
255    }
256
257    /// Generate a random f64 "special" value
258    ///
259    /// A special value is what I call specific float values that are unique and
260    /// are pretty much impossible to generate by chance, and have some unusual
261    /// properties.
262    pub fn special_f64(&mut self) -> f64 {
263        match self.0.u8(0..=11) {
264            0 => 0.0,
265            1 => -0.0,
266            2 => f64::INFINITY,
267            3 => -f64::INFINITY,
268            4 => 1.0,
269            5 => -1.0,
270            6 => f64::MIN,
271            7 => f64::MAX,
272            8 => f64::MIN_POSITIVE,
273            9 => -f64::MIN_POSITIVE,
274            10 => f64::EPSILON,
275            11 => -f64::EPSILON,
276            _ => unreachable!(),
277        }
278    }
279
280    /// Generate a random f32, such that special or problematic values are much
281    /// more common than normal.
282    ///
283    /// The distribution is not statistically useful, but it ensures that all edge-case
284    /// values get a fair chance of being generated. This is better than using a regular
285    /// random number generator, because in the vast majority of cases, a random number
286    /// generator will generate perfectly regular and well-behaved values, and certain
287    /// values, like `INFINITY` and `NAN` may be impossible to generate.
288    ///
289    /// The distribution is as follows:
290    /// - 25% normal values
291    /// - 25% subnormal values
292    /// - 25% `NAN` values, including all possible payloads, quiet and signaling `NAN`.
293    /// - 25% "special" values, i.e. unique values with special properties such as `INFINITY` and `-0.0`
294    pub fn f32(&mut self) -> f32 {
295        match self.0.u8(0..4) {
296            0 => self.normal_f32(),
297            1 => self.subnormal_f32(),
298            2 => self.nan_f32(),
299            3 => self.special_f32(),
300            _ => unreachable!(),
301        }
302    }
303
304    /// Generate a random f64, such that special or problematic values are much
305    /// more common than normal.
306    ///
307    /// The distribution is not statistically useful, but it ensures that all edge-case
308    /// values get a fair chance of being generated. This is better than using a regular
309    /// random number generator, because in the vast majority of cases, a random number
310    /// generator will generate perfectly regular and well-behaved values, and certain
311    /// values, like `INFINITY` and `NAN` may be impossible to generate.
312    ///
313    /// The distribution is as follows:
314    /// - 25% normal values
315    /// - 25% subnormal values
316    /// - 25% `NAN` values, including all possible payloads, quiet and signaling `NAN`.
317    /// - 25% "special" values, i.e. unique values with special properties such as `INFINITY` and `-0.0`
318    pub fn f64(&mut self) -> f64 {
319        match self.0.u8(0..4) {
320            0 => self.normal_f64(),
321            1 => self.subnormal_f64(),
322            2 => self.nan_f64(),
323            3 => self.special_f64(),
324            _ => unreachable!(),
325        }
326    }
327
328    uint!(self, [u8, u16, u32, u64, u128, usize]);
329
330    int!(self, [i8, i16, i32, i64, i128, isize]);
331}
332
333#[cfg(test)]
334mod test_unit {
335    extern crate std;
336
337    use super::*;
338
339    #[test]
340    fn nan_f32() {
341        let mut gen = Wdg::with_seed(0);
342        assert!(gen.nan_f32().is_nan());
343    }
344
345    #[test]
346    fn nan_f64() {
347        let mut gen = Wdg::with_seed(0);
348        assert!(gen.nan_f64().is_nan());
349    }
350
351    #[test]
352    fn subnormal_f32() {
353        let mut gen = Wdg::with_seed(0);
354        assert!(gen.subnormal_f32().is_subnormal());
355    }
356
357    #[test]
358    fn subnormal_f64() {
359        let mut gen = Wdg::with_seed(0);
360        assert!(gen.subnormal_f64().is_subnormal());
361    }
362
363    #[test]
364    fn normal_f32() {
365        let mut gen = Wdg::with_seed(0);
366        assert!(!gen.normal_f32().is_subnormal());
367    }
368
369    #[test]
370    fn normal_f64() {
371        let mut gen = Wdg::with_seed(0);
372        assert!(!gen.normal_f64().is_subnormal());
373    }
374}
375
376#[cfg(test)]
377mod test_fuzz {
378    // fuzzing tests, they may take a while to run. Shouldn't last more than
379    // a minute per test (or I'll get impatient/cargo will complain)
380
381    extern crate std;
382
383    use crate::float_utils::{f32_exact_eq, f64_exact_eq};
384
385    use super::*;
386
387    // TODO: all seeds here should be picked at random from RANDOM.org
388
389    #[test]
390    #[ignore]
391    fn nan_f32_is_nan() {
392        let mut gen = Wdg::with_seed(0x0b_65_58_2b_4e_d8_20_fe);
393        for i in 0..(1 << 30) {
394            let num = gen.nan_f32();
395            assert!(num.is_nan(), "{}: {:032b}", i, num.to_bits());
396        }
397    }
398
399    #[test]
400    #[ignore]
401    fn nan_f64_is_nan() {
402        let mut gen = Wdg::with_seed(0x36_44_3e_f8_40_af_6e_49);
403        // TODO: this test has poor coverage, there are 1 << 52 possible mantissas
404        //       way too many to guess the bad ones at random. Maybe do something
405        //       meta where you use this crate to fuzz itself?
406        for i in 0..1 << 30 {
407            let num = gen.nan_f64();
408            assert!(num.is_nan(), "{}: {:064b}", i, num.to_bits());
409        }
410    }
411
412    #[test]
413    fn nan_f32_range() {
414        let mut gen = Wdg::with_seed(0x29_21_f1_bd_8b_a9_c6_b6);
415        let mut coverage: u32 = 0b0;
416        for _ in 0..10000 {
417            let num = gen.nan_f32();
418            coverage |= num.to_bits();
419        }
420
421        // every bit should be generated at least once, given enough attempts
422        assert_eq!(coverage, u32::MAX, "{:032b}", coverage);
423    }
424
425    #[test]
426    fn nan_f64_range() {
427        let mut gen = Wdg::with_seed(0x6f_35_67_53_e6_37_13_c3);
428        let mut coverage: u64 = 0b0;
429        for _ in 0..10000 {
430            let num = gen.nan_f64();
431            coverage |= num.to_bits();
432        }
433
434        // every bit should be generated at least once, given enough attempts
435        assert_eq!(coverage, u64::MAX, "{:064b}", coverage);
436    }
437
438    #[test]
439    #[ignore]
440    fn subnoraml_f32_is_subnormal() {
441        let mut gen = Wdg::with_seed(0x52_58_4a_d1_55_e1_72_10);
442        for i in 0..(1 << 30) {
443            let num = gen.subnormal_f32();
444            assert!(num.is_subnormal(), "{}: {:032b}", i, num.to_bits());
445        }
446    }
447
448    #[test]
449    #[ignore]
450    fn subnormal_f64_is_subnormal() {
451        let mut gen = Wdg::with_seed(0x2d_46_cc_c0_45_c5_ec_03);
452        // TODO: this test has poor coverage, there are 1 << 52 possible mantissas
453        //       way too many to guess the bad ones at random. Maybe do something
454        //       meta where you use this crate to fuzz itself?
455        for i in 0..1 << 30 {
456            let num = gen.subnormal_f64();
457            assert!(num.is_subnormal(), "{}: {:064b}", i, num.to_bits());
458        }
459    }
460
461    #[test]
462    fn subnormal_f32_range() {
463        let mut gen = Wdg::with_seed(0x98_fb_6b_ef_ac_5d_81_f3);
464        let mut coverage: u32 = 0b1111_1111 << 23;
465        for _ in 0..10000 {
466            let num = gen.subnormal_f32();
467            coverage |= num.to_bits();
468        }
469
470        // every bit should be generated at least once, given enough attempts
471        assert_eq!(coverage, u32::MAX, "{:032b}", coverage);
472    }
473
474    #[test]
475    fn subnormal_f64_range() {
476        let mut gen = Wdg::with_seed(0x7a_07_58_14_f4_b8_2f_49);
477        let mut coverage: u64 = 0b111_1111_1111 << 52;
478        for _ in 0..10000 {
479            let num = gen.subnormal_f64();
480            coverage |= num.to_bits();
481        }
482
483        // every bit should be generated at least once, given enough attempts
484        assert_eq!(coverage, u64::MAX, "{:064b}", coverage);
485    }
486
487    #[test]
488    #[ignore]
489    fn noraml_f32_is_not_subnormal() {
490        let mut gen = Wdg::with_seed(0x2c_fe_59_bb_7a_56_28_20);
491        for i in 0..(1 << 30) {
492            let num = gen.normal_f32();
493            assert!(!num.is_subnormal(), "{}: {:032b}", i, num.to_bits());
494        }
495    }
496
497    #[test]
498    #[ignore]
499    fn normal_f64_is_not_subnormal() {
500        let mut gen = Wdg::with_seed(0xa9_26_d1_d9_7b_d7_94_15);
501        // TODO: this test has poor coverage, there are 1 << 52 possible mantissas
502        //       way too many to guess the bad ones at random. Maybe do something
503        //       meta where you use this crate to fuzz itself?
504        for i in 0..1 << 30 {
505            let num = gen.normal_f64();
506            assert!(!num.is_subnormal(), "{}: {:064b}", i, num.to_bits());
507        }
508    }
509
510    #[test]
511    fn normal_f32_range() {
512        let mut gen = Wdg::with_seed(0x15_63_e3_11_09_cb_11_b5);
513        let mut coverage: u32 = 0;
514        for _ in 0..10000 {
515            let num = gen.normal_f32();
516            coverage |= num.to_bits();
517        }
518
519        // every bit should be generated at least once, given enough attempts
520        assert_eq!(coverage, u32::MAX, "{:032b}", coverage);
521    }
522
523    #[test]
524    fn normal_f64_range() {
525        let mut gen = Wdg::with_seed(0x56_e5_19_b1_47_f2_5e_0d);
526        let mut coverage: u64 = 0;
527        for _ in 0..10000 {
528            let num = gen.normal_f64();
529            coverage |= num.to_bits();
530        }
531
532        // every bit should be generated at least once, given enough attempts
533        assert_eq!(coverage, u64::MAX, "{:064b}", coverage);
534    }
535
536    #[test]
537    fn special_f32() {
538        let mut gen = Wdg::with_seed(0x69_1b_e9_82_15_ed_a0_7d);
539        for _ in 0..10000 {
540            gen.special_f32();
541        }
542    }
543
544    #[test]
545    fn special_f64() {
546        let mut gen = Wdg::with_seed(0xf5_31_9e_51_c4_1f_9e_35);
547        for _ in 0..10000 {
548            gen.special_f64();
549        }
550    }
551
552    macro_rules! int_uint {
553        ($($t:ty),+ $(,)?) => {
554            $(
555                int_uint_inner!($t);
556            )+
557        };
558    }
559
560    macro_rules! int_uint_inner {
561        ($t:ty) => {
562            paste! {
563                #[test]
564                pub fn [<special_ $t>]() {
565                    let mut gen = Wdg::with_seed(0x29_2d_3a_df_ed_dd_c0_82);
566                    for _ in 0..10000 {
567                        gen.[<special_ $t>]();
568                    }
569                }
570
571                #[test]
572                pub fn $t(){
573                    let mut gen = Wdg::with_seed(0x8e_bd_46_37_50_b4_9b_1a);
574                    for _ in 0..10000 {
575                        gen.$t();
576                    }
577                }
578            }
579        };
580    }
581
582    int_uint!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
583
584    #[test]
585    fn special_f32_range() {
586        let mut gen = Wdg::with_seed(0x90_ae_72_03_34_a0_d7_4b);
587        let mut had_infinite = false;
588        let mut had_neg_infinite = false;
589        let mut had_zero = false;
590        let mut had_neg_zero = false;
591        let mut had_one = false;
592        let mut had_neg_one = false;
593        let mut had_min_positive = false;
594        let mut had_max_negative = false;
595        let mut had_epsilon = false;
596        let mut had_neg_epsilon = false;
597        for _ in 0..10000 {
598            let num = gen.special_f32();
599            had_infinite |= f32_exact_eq(num, f32::INFINITY);
600            had_neg_infinite |= f32_exact_eq(num, f32::NEG_INFINITY);
601            had_zero |= f32_exact_eq(num, 0.0);
602            had_neg_zero |= f32_exact_eq(num, -0.0);
603            had_one |= f32_exact_eq(num, 1.0);
604            had_neg_one |= f32_exact_eq(num, -1.0);
605            had_min_positive |= f32_exact_eq(num, f32::MIN_POSITIVE);
606            had_max_negative |= f32_exact_eq(num, -f32::MIN_POSITIVE);
607            had_epsilon |= f32_exact_eq(num, f32::EPSILON);
608            had_neg_epsilon |= f32_exact_eq(num, -f32::EPSILON);
609        }
610        assert!(
611            had_infinite
612                && had_neg_infinite
613                && had_zero
614                && had_neg_zero
615                && had_one
616                && had_neg_one
617                && had_min_positive
618                && had_max_negative
619                && had_epsilon
620                && had_neg_epsilon
621        );
622    }
623
624    #[test]
625    fn special_f64_range() {
626        let mut gen = Wdg::with_seed(0x10_6c_a1_34_a5_6d_03_97);
627        let mut had_infinite = false;
628        let mut had_neg_infinite = false;
629        let mut had_zero = false;
630        let mut had_neg_zero = false;
631        let mut had_one = false;
632        let mut had_neg_one = false;
633        let mut had_min_positive = false;
634        let mut had_max_negative = false;
635        let mut had_epsilon = false;
636        let mut had_neg_epsilon = false;
637        for _ in 0..10000 {
638            let num = gen.special_f64();
639            had_infinite |= f64_exact_eq(num, f64::INFINITY);
640            had_neg_infinite |= f64_exact_eq(num, f64::NEG_INFINITY);
641            had_zero |= f64_exact_eq(num, 0.0);
642            had_neg_zero |= f64_exact_eq(num, -0.0);
643            had_one |= f64_exact_eq(num, 1.0);
644            had_neg_one |= f64_exact_eq(num, -1.0);
645            had_min_positive |= f64_exact_eq(num, f64::MIN_POSITIVE);
646            had_max_negative |= f64_exact_eq(num, -f64::MIN_POSITIVE);
647            had_epsilon |= f64_exact_eq(num, f64::EPSILON);
648            had_neg_epsilon |= f64_exact_eq(num, -f64::EPSILON);
649        }
650        assert!(
651            had_infinite
652                && had_neg_infinite
653                && had_zero
654                && had_neg_zero
655                && had_one
656                && had_neg_one
657                && had_min_positive
658                && had_max_negative
659                && had_epsilon
660                && had_neg_epsilon
661        );
662    }
663
664    #[test]
665    fn f32_range() {
666        let mut gen = Wdg::with_seed(0x7c_65_54_c7_d6_a9_d4_b7);
667
668        // these should all be true by the end, given enough attempts
669        let mut had_normal = false;
670        let mut had_subnormal = false;
671        let mut had_nan = false;
672        let mut had_special = false;
673        for _ in 0..10000 {
674            let num = gen.f32();
675            had_normal |= num.is_normal();
676            had_subnormal |= num.is_subnormal();
677            had_nan |= num.is_nan();
678            had_special |= num.is_infinite()
679                | f32_exact_eq(num, 0.0)
680                | f32_exact_eq(num, -0.0)
681                | f32_exact_eq(num, 1.0)
682                | f32_exact_eq(num, -1.0)
683                | f32_exact_eq(num, f32::MIN)
684                | f32_exact_eq(num, f32::MAX)
685                | f32_exact_eq(num, f32::MIN_POSITIVE)
686                | f32_exact_eq(num, -f32::MIN_POSITIVE)
687                | f32_exact_eq(num, f32::EPSILON)
688                | f32_exact_eq(num, -f32::EPSILON);
689        }
690        assert!(had_normal && had_subnormal && had_nan && had_special);
691    }
692
693    #[test]
694    fn f64_range() {
695        let mut gen = Wdg::with_seed(0x9a_a4_ee_0f_08_ba_d9_de);
696
697        // these should all be true by the end, given enough attempts
698        let mut had_normal = false;
699        let mut had_subnormal = false;
700        let mut had_nan = false;
701        let mut had_special = false;
702        for _ in 0..10000 {
703            let num = gen.f64();
704            had_normal |= num.is_normal();
705            had_subnormal |= num.is_subnormal();
706            had_nan |= num.is_nan();
707            had_special |= num.is_infinite()
708                | f64_exact_eq(num, 0.0)
709                | f64_exact_eq(num, -0.0)
710                | f64_exact_eq(num, 1.0)
711                | f64_exact_eq(num, -1.0)
712                | f64_exact_eq(num, f64::MIN)
713                | f64_exact_eq(num, f64::MAX)
714                | f64_exact_eq(num, f64::MIN_POSITIVE)
715                | f64_exact_eq(num, -f64::MIN_POSITIVE)
716                | f64_exact_eq(num, f64::EPSILON)
717                | f64_exact_eq(num, -f64::EPSILON);
718        }
719        assert!(had_normal && had_subnormal && had_nan && had_special);
720    }
721}