extern crate chobitlibs; use std::prelude::rust_2021::*; use chobitlibs::chobit_complex::*; use chobitlibs::chobit_rand::ChobitRand; #[inline] fn rand_num(rng: &mut ChobitRand) -> f32 { ((rng.next_f64() * 20.0) - 10.0) as f32 } #[test] fn add_test() { const COUNT: usize = 1000; let mut rng = ChobitRand::new("add_test".as_bytes()); for _ in 0..COUNT { let x_re = rand_num(&mut rng); let x_im = rand_num(&mut rng); let y_re = rand_num(&mut rng); let y_im = rand_num(&mut rng); let mut x = Complex::new(x_re, x_im); let y = Complex::new(y_re, y_im); let check = Complex::new(x_re + y_re, x_im + y_im); assert_eq!(x + y, check); x += y; assert_eq!(x, check); let mut scalar = rand_num(&mut rng); let mut x = Complex::new(x_re, x_im); let check = Complex::new(x_re + scalar, x_im); assert_eq!(x + scalar, check); assert_eq!(scalar + x, check); x += scalar; assert_eq!(x, check); let x = Complex::new(x_re, x_im); let check = scalar + x_re; scalar += x; assert_eq!(scalar, check); } } #[test] fn sub_test() { const COUNT: usize = 1000; let mut rng = ChobitRand::new("sub_test".as_bytes()); for _ in 0..COUNT { let x_re = rand_num(&mut rng); let x_im = rand_num(&mut rng); let y_re = rand_num(&mut rng); let y_im = rand_num(&mut rng); let mut x = Complex::new(x_re, x_im); let y = Complex::new(y_re, y_im); let check = Complex::new(x_re - y_re, x_im - y_im); assert_eq!(x - y, check); x -= y; assert_eq!(x, check); let mut scalar = rand_num(&mut rng); let mut x = Complex::new(x_re, x_im); let check = Complex::new(x_re - scalar, x_im); assert_eq!(x - scalar, check); let check = Complex::new(scalar - x_re, x_im); assert_eq!(scalar - x, check); let check = Complex::new(x_re - scalar, x_im); x -= scalar; assert_eq!(x, check); let x = Complex::new(x_re, x_im); let check = scalar - x_re; scalar -= x; assert_eq!(scalar, check); } } #[test] fn mul_test() { const COUNT: usize = 1000; let mut rng = ChobitRand::new("mul_test".as_bytes()); for _ in 0..COUNT { let x_re = rand_num(&mut rng); let x_im = rand_num(&mut rng); let y_re = rand_num(&mut rng); let y_im = rand_num(&mut rng); let mut x = Complex::new(x_re, x_im); let y = Complex::new(y_re, y_im); let check = Complex::new( (x_re * y_re) - (x_im * y_im), (x_re * y_im) + (x_im * y_re) ); assert_eq!(x * y, check); x *= y; assert_eq!(x, check); let mut scalar = rand_num(&mut rng); let mut x = Complex::new(x_re, x_im); let check = Complex::new(x_re * scalar, x_im * scalar); assert_eq!(x * scalar, check); assert_eq!(scalar * x, check); x *= scalar; assert_eq!(x, check); let x = Complex::new(x_re, x_im); let check = scalar * x_re; scalar *= x; assert_eq!(scalar, check); } } #[test] fn div_test() { const COUNT: usize = 1000; let mut rng = ChobitRand::new("div_test".as_bytes()); for _ in 0..COUNT { let x_re = rand_num(&mut rng); let x_im = rand_num(&mut rng); let y_re = rand_num(&mut rng); let y_im = rand_num(&mut rng); let mut x = Complex::new(x_re, x_im); let y = Complex::new(y_re, y_im); let abs_sq = (y_re * y_re) + (y_im * y_im); let check = Complex::new( ((x_re * y_re) + (x_im * y_im)) / abs_sq, ((x_im * y_re) - (x_re * y_im)) / abs_sq ); assert_eq!(x / y, check); x /= y; assert_eq!(x, check); let mut scalar = rand_num(&mut rng); let mut x = Complex::new(x_re, x_im); let check = Complex::new(x_re / scalar, x_im / scalar); assert_eq!(x / scalar, check); x /= scalar; assert_eq!(x, check); let x = Complex::new(x_re, x_im); let check = Complex::new(scalar, 0.0) / Complex::new(x_re, x_im); scalar /= x; assert_eq!(scalar, check.re); } } #[test] fn cis_table_test() { let table = CisTable::new(); for angle in 0..CisTable::full_circle_angle() { let rad = CisTable::angle_to_radian(angle); let complex = Complex::new(rad.cos(), rad.sin()); let diff = table[angle] - complex; assert!(diff.re.abs() < 0.0008); assert!(diff.im.abs() < 0.0008); } } #[test] fn rad_to_angle_test() { for angle in 0..CisTable::full_circle_angle() { let rad = CisTable::angle_to_radian(angle); let angle_2 = CisTable::radian_to_angle(rad); assert_eq!(angle_2, angle); } } #[test] fn rot_test() { const COUNT: usize = 5000; let mut rng = ChobitRand::new("rot_test".as_bytes()); let table = CisTable::new(); for _ in 0..COUNT { let rad = rand_num(&mut rng); let x = Complex::new(1.0, 0.0); let y = x * table[CisTable::radian_to_angle(rad)]; let diff_re = (y.re - rad.cos()).abs(); let diff_im = (y.im - rad.sin()).abs(); assert!(diff_re < 0.0008); assert!(diff_im < 0.0008); } } #[test] fn polar_test_1() { let table = CisTable::new(); for angle in 0..CisTable::full_circle_angle() { let complex = table[angle]; let (_, phase) = complex.polar(&table); let diff = ((phase as i32) - angle as i32).abs(); assert!(diff <= 1); } } #[test] fn polar_test_2() { const COUNT: usize = 20000; let mut rng = ChobitRand::new("polar_test".as_bytes()); let table = CisTable::new(); for _ in 0..COUNT { let x = Complex::new(rand_num(&mut rng), rand_num(&mut rng)); let (mag, phase) = x.polar(&table); let y = table[phase] * mag; let diff = (x - y).abs(); assert!(diff < 0.015); } } #[test] fn div_test_2() { let table = CisTable::new(); for angle in 0..CisTable::full_circle_angle() { let cis_1 = table[angle]; let cis_2 = table[angle]; let check = Complex::new(1.0, 0.0); let result = cis_1 / cis_2; let diff = (result - check).abs(); assert!(diff < 0.000001); } } #[test] fn recip_test() { const COUNT: usize = 10000; let mut rng = ChobitRand::new("recip_test".as_bytes()); for _ in 0..COUNT { let x = Complex::new(rand_num(&mut rng), rand_num(&mut rng)); let y = x.recip(); let check = Complex::new(1.0, 0.0); let result = x * y; let diff = (result - check).abs(); assert!(diff < 0.000001); } } #[test] fn cis_table_abs_test() { let table = CisTable::new(); for cis in table.as_slice() { let abs = cis.abs(); let diff = (abs - 1.0).abs(); assert!(diff < 0.00008); } } #[test] fn normalize_test() { const COUNT: usize = 10000; let mut rng = ChobitRand::new("normalize_test".as_bytes()); let table = CisTable::new(); for _ in 0..COUNT { let x = Complex::new(rand_num(&mut rng), rand_num(&mut rng)); let (_, phase) = x.polar(&table); let cis = table[phase]; let y = x.normalize(); let diff = (y - cis).abs(); assert!(diff < 0.0015); } } #[test] fn cis_table_slice_test() { const QUADRANT_1_ANGLE: usize = CisTable::full_circle_angle() >> 2; const QUADRANT_2_ANGLE: usize = CisTable::full_circle_angle() >> 1; let table = CisTable::new(); let table_slice = &table[QUADRANT_1_ANGLE..QUADRANT_2_ANGLE]; assert_eq!(table_slice.len(), QUADRANT_1_ANGLE); for angle in 0..QUADRANT_1_ANGLE { assert_eq!(table_slice[angle], table[angle + QUADRANT_1_ANGLE]); } } #[test] fn normalize_angle_test() { const QUADRANT_0_ANGLE: usize = 0; const QUADRANT_1_ANGLE: usize = CisTable::full_circle_angle() >> 2; const QUADRANT_2_ANGLE: usize = CisTable::full_circle_angle() >> 1; const QUADRANT_3_ANGLE: usize = QUADRANT_1_ANGLE + QUADRANT_2_ANGLE; let angle = QUADRANT_0_ANGLE; let angle = angle.wrapping_sub(QUADRANT_1_ANGLE); assert_ne!(angle, QUADRANT_3_ANGLE); let angle = CisTable::normalize_angle(angle); assert_eq!(angle, QUADRANT_3_ANGLE); }