22
22
23
23
use std:: f64:: consts:: PI ;
24
24
25
+ use num:: { Float , FromPrimitive } ;
26
+
25
27
/// Cross-in-tray test function
26
28
///
27
29
/// Defined as
@@ -36,52 +38,74 @@ use std::f64::consts::PI;
36
38
/// * `f(x_1, x_2) = f(1.34941, -1.34941) = -2.06261`.
37
39
/// * `f(x_1, x_2) = f(-1.34941, 1.34941) = -2.06261`.
38
40
/// * `f(x_1, x_2) = f(-1.34941, -1.34941) = -2.06261`.
39
- pub fn cross_in_tray ( param : & [ f64 ] ) -> f64 {
40
- assert ! ( param . len ( ) == 2 ) ;
41
- let ( x1 , x2 ) = ( param[ 0 ] , param [ 1 ] ) ;
42
- // let pi = T::from_f64(PI).unwrap();
43
- // T::from_f64(-0.0001).unwrap()
44
- // * ((x1.sin() * x2.sin()
45
- // * (T::from_f64(100.0).unwrap() - (x1.powi(2) + x2.powi(2)).sqrt() / pi)
46
- // .abs()
47
- // .exp())
48
- // .abs() + T::from_f64(1.0).unwrap())
49
- // .powf(T::from_f64(0.1).unwrap ())
50
- - 0.0001
51
- * ( ( x1 . sin ( ) * x2 . sin ( ) * ( 100.0 - ( x1 . powi ( 2 ) + x2 . powi ( 2 ) ) . sqrt ( ) / PI ) . abs ( ) . exp ( ) )
52
- . abs ( )
53
- + 1.0 )
54
- . powf ( 0.1 )
41
+ ///
42
+ /// Note: Even if the input parameters are f32, internal computations will be performed in f64.
43
+ pub fn cross_in_tray < T > ( param : & [ T ; 2 ] ) -> T
44
+ where
45
+ T : Float + Into < f64 > + FromPrimitive ,
46
+ {
47
+ let x1 : f64 = param [ 0 ] . into ( ) ;
48
+ let x2 : f64 = param [ 1 ] . into ( ) ;
49
+ T :: from_f64 (
50
+ - 0.0001
51
+ * ( ( x1 . sin ( ) * x2 . sin ( ) * ( 100.0 - ( x1 . powi ( 2 ) + x2 . powi ( 2 ) ) . sqrt ( ) / PI ) . abs ( ) . exp ( ) )
52
+ . abs ( )
53
+ + 1.0 )
54
+ . powf ( 0.1 ) ,
55
+ )
56
+ . unwrap ( )
55
57
}
56
58
57
59
#[ cfg( test) ]
58
60
mod tests {
59
61
use super :: * ;
62
+ use approx:: assert_relative_eq;
60
63
use std:: f32;
61
64
62
65
#[ test]
63
66
fn test_cross_in_tray_optimum ( ) {
64
67
// This isnt exactly a great way to test this. The function can only be computed with the
65
68
// use of f64; however, I only have the minimum points available in f32, which is why I use
66
69
// the f32 EPSILONs.
67
- assert ! (
68
- ( cross_in_tray( & [ 1.34941_f64 , 1.34941_f64 ] ) + 2.062611870 ) . abs( ) < f32 :: EPSILON . into( )
70
+ assert_relative_eq ! (
71
+ cross_in_tray( & [ 1.34941_f64 , 1.34941_f64 ] ) ,
72
+ -2.062611870 ,
73
+ epsilon = f32 :: EPSILON . into( )
69
74
) ;
70
- assert ! (
71
- ( cross_in_tray( & [ 1.34941_f64 , -1.34941_f64 ] ) + 2.062611870 ) . abs( ) < f32 :: EPSILON . into( )
75
+ assert_relative_eq ! (
76
+ cross_in_tray( & [ 1.34941_f64 , -1.34941_f64 ] ) ,
77
+ -2.062611870 ,
78
+ epsilon = f32 :: EPSILON . into( )
72
79
) ;
73
- assert ! (
74
- ( cross_in_tray( & [ -1.34941_f64 , 1.34941_f64 ] ) + 2.062611870 ) . abs( ) < f32 :: EPSILON . into( )
80
+ assert_relative_eq ! (
81
+ cross_in_tray( & [ -1.34941_f64 , 1.34941_f64 ] ) ,
82
+ -2.062611870 ,
83
+ epsilon = f32 :: EPSILON . into( )
75
84
) ;
76
- assert ! (
77
- ( cross_in_tray( & [ -1.34941_f64 , -1.34941_f64 ] ) + 2.062611870 ) . abs( )
78
- < f32 :: EPSILON . into( )
85
+ assert_relative_eq ! (
86
+ cross_in_tray( & [ -1.34941_f64 , -1.34941_f64 ] ) ,
87
+ -2.062611870 ,
88
+ epsilon = f32 :: EPSILON . into( )
89
+ ) ;
90
+ assert_relative_eq ! (
91
+ cross_in_tray( & [ 1.34941_f32 , 1.34941_f32 ] ) ,
92
+ -2.062611870 ,
93
+ epsilon = f32 :: EPSILON . into( )
94
+ ) ;
95
+ assert_relative_eq ! (
96
+ cross_in_tray( & [ 1.34941_f32 , -1.34941_f32 ] ) ,
97
+ -2.062611870 ,
98
+ epsilon = f32 :: EPSILON . into( )
99
+ ) ;
100
+ assert_relative_eq ! (
101
+ cross_in_tray( & [ -1.34941_f32 , 1.34941_f32 ] ) ,
102
+ -2.062611870 ,
103
+ epsilon = f32 :: EPSILON . into( )
104
+ ) ;
105
+ assert_relative_eq ! (
106
+ cross_in_tray( & [ -1.34941_f32 , -1.34941_f32 ] ) ,
107
+ -2.062611870 ,
108
+ epsilon = f32 :: EPSILON . into( )
79
109
) ;
80
- }
81
-
82
- #[ test]
83
- #[ should_panic]
84
- fn test_cross_in_tray_param_length ( ) {
85
- cross_in_tray ( & [ 0.0 , -1.0 , 0.1 ] ) ;
86
110
}
87
111
}
0 commit comments