1
- /*
2
- Does the following:
3
-
4
- - Check 100 values near each of the bounds
5
- - If there are defined asymptotes, check those
6
- - Figure out a number of tests to do within the domain. If exhaustive, check all (but skip
7
- NaNs?)
8
- - Check near zero if defined
9
- - If unbounded, ensure that real inputs do not produce any NaNs
10
- - If periodic, check that results are identical for a few periods (?)
11
-
12
-
13
- */
1
+ //! A generator that makes use of the `Domain` trait
2
+ //!
3
+ //! Does the following:
4
+ //!
5
+ //! - Check 100 values near each of the bounds (default)
6
+ //! - If there are defined asymptotes, check those
7
+ //! - Figure out a number of tests to do within the domain. If exhaustive, check all (but skip
8
+ //! NaNs?)
9
+ //! - Check near zero if defined
10
+ //! - If unbounded, ensure that real inputs do not produce any NaNs
11
+ //! - If periodic, check that results are identical for a few periods (?)
14
12
15
13
use std:: iter;
16
14
use std:: ops:: Bound ;
@@ -42,15 +40,16 @@ const NTESTS: usize = {
42
40
}
43
41
} ;
44
42
45
- // // / Some functions have infinite asymptotes, limit how many we check.
46
- // const MAX_ASYMPTOTES: usize = 10;
43
+ /// Some functions have infinite asymptotes, limit how many we check.
44
+ const MAX_ASYMPTOTES : usize = 10 ;
47
45
48
46
/// Create a test case iterator.
49
47
pub fn get_test_cases < F : Float , D : Domain < F > > ( ) -> impl Iterator < Item = ( F , ) >
50
48
where
51
49
F :: Int : TryFrom < usize > ,
52
50
{
53
- // Figure out the ranges we will test on
51
+ // We generate logspaced inputs within a specific range. Use the function domain
52
+ // by default but if the function is periodic, check only within that period.
54
53
let ( start, end) = D :: PERIODIC . unwrap_or ( D :: DEFINED ) ;
55
54
let range_start = match start {
56
55
Bound :: Included ( v) => v,
64
63
} ;
65
64
66
65
let steps = F :: Int :: try_from ( NTESTS ) . unwrap_or ( F :: Int :: MAX ) ;
66
+
67
+ // Always check near bounds in addition to the logspace
67
68
near_bounds :: < F , D > ( ) . into_iter ( ) . chain ( logspace ( range_start, range_end, steps) ) . map ( |v| ( v, ) )
68
69
}
69
70
71
+ /// Create a vector full of values near interesting (bounds, asymptotes, etc).
70
72
fn near_bounds < F : Float , D : Domain < F > > ( ) -> Vec < F > {
71
73
let mut values = Vec :: new ( ) ;
72
74
@@ -105,15 +107,19 @@ fn near_bounds<F: Float, D: Domain<F>>() -> Vec<F> {
105
107
around ( x, & mut values) ;
106
108
}
107
109
108
- // Max, min, and infinities are interesting
110
+ // Values around min and max are interesting
111
+ values. extend ( count_up ( F :: MIN ) . take ( AROUND ) ) ;
112
+ values. extend ( count_down ( F :: MAX ) . take ( AROUND ) ) ;
113
+
114
+ // Check some special values that aren't included in the above ranges
115
+ values. push ( F :: NAN ) ;
109
116
values. push ( F :: MIN ) ;
110
117
values. push ( F :: MAX ) ;
111
118
values. push ( F :: INFINITY ) ;
112
119
values. push ( F :: NEG_INFINITY ) ;
113
120
values. push ( F :: NEG_ZERO ) ;
114
- values. extend ( count_up ( F :: MIN ) . take ( AROUND ) ) ;
115
- values. extend ( count_down ( F :: MAX ) . take ( AROUND ) ) ;
116
121
122
+ // Check period endpoints (as we define them) if available
117
123
if let Some ( ( start, end) ) = D :: PERIODIC {
118
124
validate_bound ( start) ;
119
125
validate_bound ( end) ;
@@ -122,6 +128,8 @@ fn near_bounds<F: Float, D: Domain<F>>() -> Vec<F> {
122
128
around_bound ( end, & mut values) ;
123
129
124
130
let p = D :: period ( ) . unwrap ( ) ;
131
+
132
+ // Check the same points for a few period to make sure there is no drift
125
133
for mul in [ one / two, one, three / two, two, three] {
126
134
let back = D :: period_start ( ) - mul * p;
127
135
let forward = D :: period_end ( ) + mul * p;
@@ -131,11 +139,12 @@ fn near_bounds<F: Float, D: Domain<F>>() -> Vec<F> {
131
139
}
132
140
}
133
141
134
- for ( from, _to) in D :: defined_asymptotes ( ) {
142
+ // Check around asymptotest
143
+ for ( from, _to) in D :: defined_asymptotes ( ) . take ( MAX_ASYMPTOTES ) {
135
144
around ( from, & mut values) ;
136
145
}
137
146
138
- for x in D :: check_points ( ) {
147
+ for x in D :: check_points ( ) . take ( MAX_ASYMPTOTES ) {
139
148
around ( x, & mut values) ;
140
149
}
141
150
@@ -145,7 +154,7 @@ fn near_bounds<F: Float, D: Domain<F>>() -> Vec<F> {
145
154
values
146
155
}
147
156
148
- /// Push `AROUND` values up and `AROUND` values down from a value.
157
+ /// Push `AROUND` values up and `AROUND` values down from a value exhaustively (increments ULP) .
149
158
fn around < F : Float > ( x : F , values : & mut Vec < F > ) {
150
159
values. push ( x) ;
151
160
values. extend ( count_up ( x) . take ( AROUND ) ) ;
0 commit comments