@@ -77,6 +77,7 @@ impl_call!((f64) -> f64: x: x.0);
7777impl_call ! ( ( f64 ) -> i32 : x: x. 0 ) ;
7878impl_call ! ( ( f32 ) -> i32 : x: x. 0 ) ;
7979impl_call ! ( ( f32 , f32 ) -> f32 : x: x. 0 , x. 1 ) ;
80+ impl_call ! ( ( f32 , f64 ) -> f32 : x: x. 0 , x. 1 ) ;
8081impl_call ! ( ( f64 , f64 ) -> f64 : x: x. 0 , x. 1 ) ;
8182impl_call ! ( ( f64 , i32 ) -> f64 : x: x. 0 , x. 1 ) ;
8283impl_call ! ( ( f32 , i32 ) -> f32 : x: x. 0 , x. 1 ) ;
@@ -85,23 +86,53 @@ impl_call!((i32, f32) -> f32: x: x.0, x.1);
8586impl_call ! ( ( f32 , f32 , f32 ) -> f32 : x: x. 0 , x. 1 , x. 2 ) ;
8687impl_call ! ( ( f64 , f64 , f64 ) -> f64 : x: x. 0 , x. 1 , x. 2 ) ;
8788
88- // Adjust the input of a function.
89+ pub trait TupleVec {
90+ type Output ;
91+ fn get ( & self , i : usize ) -> Self :: Output ;
92+ }
93+
94+ macro_rules! impl_tuple_vec {
95+ ( ( $( $arg_tys: ty) ,* ) : $self_: ident: $( $xs: expr) ,* ) => {
96+ impl TupleVec for ( $( Vec <$arg_tys>, ) +) {
97+ type Output = ( $( $arg_tys, ) +) ;
98+ fn get( & self , i: usize ) -> Self :: Output {
99+ let $self_ = self ;
100+ ( $( $xs[ i] , ) * )
101+ }
102+ }
103+ } ;
104+ }
105+
106+ impl_tuple_vec ! ( ( f32 ) : x: x. 0 ) ;
107+ impl_tuple_vec ! ( ( f64 ) : x: x. 0 ) ;
108+ impl_tuple_vec ! ( ( f32 , f32 ) : x: x. 0 , x. 1 ) ;
109+ impl_tuple_vec ! ( ( f32 , f64 ) : x: x. 0 , x. 1 ) ;
110+ impl_tuple_vec ! ( ( f64 , f64 ) : x: x. 0 , x. 1 ) ;
111+ impl_tuple_vec ! ( ( f64 , i32 ) : x: x. 0 , x. 1 ) ;
112+ impl_tuple_vec ! ( ( f32 , i32 ) : x: x. 0 , x. 1 ) ;
113+ impl_tuple_vec ! ( ( i32 , f64 ) : x: x. 0 , x. 1 ) ;
114+ impl_tuple_vec ! ( ( i32 , f32 ) : x: x. 0 , x. 1 ) ;
115+ impl_tuple_vec ! ( ( f32 , f32 , f32 ) : x: x. 0 , x. 1 , x. 2 ) ;
116+ impl_tuple_vec ! ( ( f64 , f64 , f64 ) : x: x. 0 , x. 1 , x. 2 ) ;
117+
118+ /// Kind of LibmApi - used to handle generating tests
119+ /// for some functions slightly differently.
120+ #[ derive( Copy , Clone , Debug , PartialEq ) ]
121+ pub enum ApiKind {
122+ Jx ,
123+ Other ,
124+ }
125+
89126#[ macro_export]
90- macro_rules! adjust_input {
91- ( fn : j1, input : $arg : ident ) => {
92- adjust_input! ( adjust : $arg )
127+ macro_rules! get_api_kind {
128+ ( fn : j1) => {
129+ $crate :: ApiKind :: Jx
93130 } ;
94- ( fn : jn, input : $arg : ident ) => {
95- adjust_input! ( adjust : $arg )
131+ ( fn : jn) => {
132+ $crate :: ApiKind :: Jx
96133 } ;
97- ( fn : $id: ident, input: $args: ident) => { } ;
98- ( adjust: $arg: ident) => {
99- // First argument to these functions are a number of
100- // iterations and passing large random numbers takes forever
101- // to execute, so check if their higher bits are set and
102- // zero them:
103- let p = & mut $arg as * mut _ as * mut i32 ;
104- unsafe { p. write( p. read( ) & 0xffff ) }
134+ ( fn : $id: ident) => {
135+ $crate:: ApiKind :: Other
105136 } ;
106137}
107138
@@ -121,3 +152,100 @@ macro_rules! assert_approx_eq {
121152 }
122153 } ;
123154}
155+
156+ pub trait Toward : Sized {
157+ fn toward ( self , other : Self , len : usize ) -> Vec < Self > ;
158+ }
159+
160+ macro_rules! impl_toward_f {
161+ ( $float_ty: ident, $toward_fn: path) => {
162+ impl Toward for $float_ty {
163+ fn toward( self , other: Self , len: usize ) -> Vec <Self > {
164+ let mut vec = Vec :: with_capacity( len) ;
165+ let mut current = self ;
166+ vec. push( self ) ;
167+ for _ in 0 ..=len {
168+ current = $toward_fn( current, other as _) ;
169+ vec. push( self ) ;
170+ if current. to_bits( ) == other. to_bits( ) {
171+ break ;
172+ }
173+ }
174+ vec
175+ }
176+ }
177+ } ;
178+ }
179+ impl_toward_f ! ( f32 , libm:: nextafterf) ;
180+ impl_toward_f ! ( f64 , libm:: nextafter) ;
181+
182+ pub trait RandSeq : Sized {
183+ fn rand_seq < R : rand:: Rng > ( rng : & mut R , api_kind : ApiKind , len : usize ) -> Vec < Self > ;
184+ }
185+
186+ macro_rules! impl_rand_seq_f {
187+ ( $float_ty: ident) => {
188+ impl RandSeq for $float_ty {
189+ fn rand_seq<R : rand:: Rng >( rng: & mut R , _api_kind: ApiKind , len: usize ) -> Vec <Self > {
190+ use std:: $float_ty:: * ;
191+ let mut vec = Vec :: with_capacity( len) ;
192+
193+ // These inputs are always tested
194+ const BOUNDS : [ $float_ty; 9 ] = [
195+ NAN ,
196+ INFINITY ,
197+ NEG_INFINITY ,
198+ EPSILON ,
199+ -EPSILON ,
200+ MAX ,
201+ MIN ,
202+ MIN_POSITIVE ,
203+ -MIN_POSITIVE ,
204+ ] ;
205+ vec. extend( & BOUNDS ) ;
206+ // A range around the inputs is also always tested:
207+ const NSTEPS : usize = 1_000 ;
208+ vec. extend( INFINITY . toward( 0. , NSTEPS ) ) ;
209+ vec. extend( NEG_INFINITY . toward( 0. , NSTEPS ) ) ;
210+ vec. extend( ( 0. as $float_ty) . toward( MIN_POSITIVE , NSTEPS ) ) ;
211+ vec. extend( ( 0. as $float_ty) . toward( -MIN_POSITIVE , NSTEPS ) ) ;
212+
213+ for i in 0 ..=NSTEPS {
214+ let dx = 2. / NSTEPS as $float_ty;
215+ let next = ( -1. as $float_ty) + ( i as $float_ty) * dx;
216+ vec. push( next) ;
217+ }
218+
219+ // ~NSTEPS * 4
220+ assert!( len > 2 * 4 * NSTEPS , "len {} !> {}" , len, 2 * 4 * NSTEPS ) ;
221+ let current_len = vec. len( ) ;
222+ let remaining_len = len. checked_sub( current_len) . unwrap( ) ;
223+
224+ for _ in 0 ..remaining_len {
225+ let n = rng. gen :: <$float_ty>( ) ;
226+ vec. push( n) ;
227+ }
228+ assert_eq!( vec. len( ) , len) ;
229+ vec
230+ }
231+ }
232+ } ;
233+ }
234+
235+ impl_rand_seq_f ! ( f32 ) ;
236+ impl_rand_seq_f ! ( f64 ) ;
237+
238+ impl RandSeq for i32 {
239+ fn rand_seq < R : rand:: Rng > ( rng : & mut R , api_kind : ApiKind , len : usize ) -> Vec < Self > {
240+ let mut v = Vec :: with_capacity ( len) ;
241+ for _ in 0 ..len {
242+ let mut r = rng. gen :: < i32 > ( ) ;
243+ if let ApiKind :: Jx = api_kind {
244+ r &= 0xffff ;
245+ }
246+ v. push ( r) ;
247+ }
248+ assert_eq ! ( v. len( ) , len) ;
249+ v
250+ }
251+ }
0 commit comments