@@ -1977,3 +1977,65 @@ mod impl_proptest {
19771977 }
19781978 impl_arbitrary ! { f32 , f64 }
19791979}
1980+
1981+ #[ cfg( feature = "arbitrary" ) ]
1982+ mod impl_arbitrary {
1983+ use super :: { FloatIsNan , NotNan , OrderedFloat } ;
1984+ use arbitrary:: { Arbitrary , Unstructured } ;
1985+ use num_traits:: FromPrimitive ;
1986+
1987+ macro_rules! impl_arbitrary {
1988+ ( $( $f: ident) ,+) => {
1989+ $(
1990+ impl <' a> Arbitrary <' a> for NotNan <$f> {
1991+ fn arbitrary( u: & mut Unstructured <' a>) -> arbitrary:: Result <Self > {
1992+ let float: $f = u. arbitrary( ) ?;
1993+ match NotNan :: new( float) {
1994+ Ok ( notnan_value) => Ok ( notnan_value) ,
1995+ Err ( FloatIsNan ) => {
1996+ // If our arbitrary float input was a NaN (encoded by exponent = max
1997+ // value), then replace it with a finite float, reusing the mantissa
1998+ // bits.
1999+ //
2000+ // This means the output is not uniformly distributed among all
2001+ // possible float values, but Arbitrary makes no promise that that
2002+ // is true.
2003+ //
2004+ // An alternative implementation would be to return an
2005+ // `arbitrary::Error`, but that is not as useful since it forces the
2006+ // caller to retry with new random/fuzzed data; and the precendent of
2007+ // `arbitrary`'s built-in implementations is to prefer the approach of
2008+ // mangling the input bits to fit.
2009+
2010+ let ( mantissa, _exponent, sign) =
2011+ num_traits:: Float :: integer_decode( float) ;
2012+ let revised_float = <$f>:: from_i64(
2013+ i64 :: from( sign) * mantissa as i64
2014+ ) . unwrap( ) ;
2015+
2016+ // If this unwrap() fails, then there is a bug in the above code.
2017+ Ok ( NotNan :: new( revised_float) . unwrap( ) )
2018+ }
2019+ }
2020+ }
2021+
2022+ fn size_hint( depth: usize ) -> ( usize , Option <usize >) {
2023+ <$f as Arbitrary >:: size_hint( depth)
2024+ }
2025+ }
2026+
2027+ impl <' a> Arbitrary <' a> for OrderedFloat <$f> {
2028+ fn arbitrary( u: & mut Unstructured <' a>) -> arbitrary:: Result <Self > {
2029+ let float: $f = u. arbitrary( ) ?;
2030+ Ok ( OrderedFloat :: from( float) )
2031+ }
2032+
2033+ fn size_hint( depth: usize ) -> ( usize , Option <usize >) {
2034+ <$f as Arbitrary >:: size_hint( depth)
2035+ }
2036+ }
2037+ ) *
2038+ }
2039+ }
2040+ impl_arbitrary ! { f32 , f64 }
2041+ }
0 commit comments