rotchess_core/
floating_drift.rs

1#[macro_export]
2/// If the floats are essentially integers, make them the exact integers.
3///
4/// # Examples
5///
6/// ```
7/// use rotchess_core::floating_drift::floating_drift_adjust;
8/// let result = floating_drift_adjust!(1.000001, 2.5);
9/// assert_eq!(result, (1.0, 2.5));
10/// ```
11macro_rules! floating_drift_adjust {
12    ($($x:expr),+ $(,)?) => {{
13        const EPSILON: f32 = 1e-4;
14
15        // Helper function to round a value if it's close to an integer
16        fn round_if_close_to_integer(val: f32) -> f32 {
17            if (val - val.round()).abs() < EPSILON {
18                val.round()
19            } else {
20                val
21            }
22        }
23
24        // Return tuple with each value individually checked and possibly rounded
25        ($(round_if_close_to_integer($x as f32)),+)
26    }};
27}
28
29pub use floating_drift_adjust;
30
31#[cfg(test)]
32mod tests {
33    #[test]
34    fn values_close_to_integers() {
35        let result = floating_drift_adjust!(1.000001, 2.999999, 3.0);
36        assert_eq!(result, (1.0, 3.0, 3.0));
37    }
38
39    #[test]
40    fn values_not_close_to_integers() {
41        let result = floating_drift_adjust!(1.5, 2.7, 3.2);
42        assert_eq!(result, (1.5, 2.7, 3.2));
43    }
44
45    #[test]
46    fn mixed_close_and_not_close() {
47        let result = floating_drift_adjust!(1.000001, 2.5, 3.999999);
48        assert_eq!(result, (1.0, 2.5, 4.0));
49    }
50
51    #[test]
52    fn mixed_integer_and_float_types() {
53        let result = floating_drift_adjust!(1, 2.000001, 3.999999);
54        assert_eq!(result, (1.0, 2.0, 4.0));
55    }
56
57    #[test]
58    fn single_value_close_to_integer() {
59        let result = floating_drift_adjust!(4.000001);
60        assert_eq!(result, (4.0));
61    }
62
63    #[test]
64    fn single_value_not_close_to_integer() {
65        let result = floating_drift_adjust!(4.5);
66        assert_eq!(result, (4.5));
67    }
68
69    #[test]
70    fn many_values_all_close() {
71        let result = floating_drift_adjust!(1.0, 2.000001, 3.999999, 4.0, 5.000001);
72        assert_eq!(result, (1.0, 2.0, 4.0, 4.0, 5.0));
73    }
74
75    #[test]
76    fn many_values_mixed() {
77        let result = floating_drift_adjust!(1.000001, 2.5, 3.0, 4.7, 5.999999);
78        assert_eq!(result, (1.0, 2.5, 3.0, 4.7, 6.0));
79    }
80
81    #[test]
82    fn negative_values() {
83        let result = floating_drift_adjust!(-1.000001, -2.999999);
84        assert_eq!(result, (-1.0, -3.0));
85    }
86
87    #[test]
88    fn zero_values() {
89        let result = floating_drift_adjust!(0.000001, -0.000001);
90        assert_eq!(result, (0.0, 0.0));
91    }
92
93    #[test]
94    fn mixed_negative_and_positive() {
95        let result = floating_drift_adjust!(-1.000001, 2.5, 3.999999);
96        assert_eq!(result, (-1.0, 2.5, 4.0));
97    }
98}