//tests.rs use num_traits::Float; fn calculate_percentage_error(vector1: &[T], vector2: &[T]) -> T where T: Float + std::ops::AddAssign, { let n = vector1.len(); assert_eq!(n, vector2.len(), "Vectors must have equal lengths."); let mut total_error = T::zero(); for i in 0..n { let diff = (vector1[i] - vector2[i]).abs(); let error = diff / if vector1[i] == T::zero() { T::min_positive_value() } else { vector1[i] }; total_error += error; } let average_error = total_error / T::from(n).unwrap(); let percentage_error = average_error * T::from(100).expect("Cannot convert 100 to type T"); percentage_error } #[cfg(test)] mod tests { mod f64_error { use crate::*; use super::super::calculate_percentage_error; use once_cell::sync::Lazy; const TOLERANCE: f64 = 2.5; static X: Lazy> = Lazy::new(|| { (-10000..10000) .map(|a| (a as f64) / 1000.) .collect::>() }); #[test] fn pow2() -> Result<(), Box> { let percentage_error = calculate_percentage_error( &X.iter().map(|&x| x.fast_pow2()).collect::>(), &X.iter().map(|&x| x.powi(2)).collect::>() ); assert!(!percentage_error.is_nan(), "fast_pow2 percentage error is NaN"); assert!( percentage_error < TOLERANCE, "fast_pow2 percentage error: {0}", percentage_error ); Ok(()) } #[test] fn exp() -> Result<(), Box> { let percentage_error = calculate_percentage_error( &X.iter().map(|&x| x.fast_exp()).collect::>(), &X.iter().map(|&x| x.exp()).collect::>() ); assert!(!percentage_error.is_nan(), "fast_exp percentage error is NaN"); assert!( percentage_error < TOLERANCE, "fast_exp percentage error: {0}", percentage_error ); Ok(()) } #[test] fn cos() -> Result<(), Box> { let percentage_error = calculate_percentage_error( &X.iter().map(|&x| x.fast_cos()).collect::>(), &X.iter().map(|&x| x.cos()).collect::>() ); assert!(!percentage_error.is_nan(), "fast_cos percentage error is NaN"); assert!( percentage_error < TOLERANCE, "fast_cos percentage error: {0}", percentage_error ); Ok(()) } #[test] fn sigmoid() -> Result<(), Box> { let percentage_error = calculate_percentage_error( &X.iter().map(|&x| x.fast_sigmoid()).collect::>(), &X.iter().map(|&x| sigmoid_builtin_f64(x)).collect::>() ); assert!(!percentage_error.is_nan(), "fast_sigmoid percentage error is NaN"); assert!( percentage_error < TOLERANCE, "fast_sigmoid percentage error: {0}", percentage_error ); Ok(()) } } mod f32_error { use crate::*; use super::super::calculate_percentage_error; use once_cell::sync::Lazy; const TOLERANCE: f32 = 2.5; static X: Lazy> = Lazy::new(|| { (-10000..10000) .map(|a| (a as f32) / 1000.) .collect::>() }); #[test] fn pow2() -> Result<(), Box> { assert!( calculate_percentage_error( &X.iter().map(|&x| x.fast_pow2()).collect::>(), &X.iter().map(|&x| x.powi(2)).collect::>() ) < TOLERANCE ); Ok(()) } #[test] fn exp() -> Result<(), Box> { assert!( calculate_percentage_error( &X.iter().map(|&x| x.fast_exp()).collect::>(), &X.iter().map(|&x| x.exp()).collect::>() ) < TOLERANCE ); Ok(()) } #[test] fn cos() -> Result<(), Box> { assert!( calculate_percentage_error( &X.iter().map(|&x| x.fast_cos()).collect::>(), &X.iter().map(|&x| x.cos()).collect::>() ) < TOLERANCE ); Ok(()) } #[test] fn sigmoid() -> Result<(), Box> { assert!( calculate_percentage_error( &X.iter().map(|&x| x.fast_sigmoid()).collect::>(), &X.iter().map(|&x| sigmoid_builtin_f32(x)).collect::>() ) < TOLERANCE ); Ok(()) } } }