use spirix::*;
macro_rules! test_arithmetic_for_type {
($circle_type:ident) => {
let a = $circle_type::from((40u8, 2i8));
let b = $circle_type::from((3f32, -5i16));
let sum = a + b;
assert!(sum.r() == 43u16);
assert!(sum.i() == -3i32);
let real_only = $circle_type::from(15i64);
assert!(real_only.r() == 15u128);
assert!(real_only.i().is_zero());
let c = $circle_type::from((12i16, 8f32));
let d = $circle_type::from((5i32, 3f64));
let diff = c - d;
assert!(diff.r() == 7usize);
assert!(diff.i() == 5isize);
let e = $circle_type::from((3f32, 4i64));
let f = 2u32;
let product = e * f;
assert!(product.r() == 6i128);
assert!(product.i() == 8f32);
let g = $circle_type::from((15usize, 9isize));
let h = 3f64;
let quotient = g / h;
assert!(quotient.r() == 5f32);
assert!(quotient.i() == 3f64);
let complex = $circle_type::from((3.5f32, 2.75f64));
assert!(complex.r() == 3.5);
assert!(complex.i() == 2.75);
let pos = $circle_type::from((42f32, -17f64));
let neg = -pos;
assert!(neg.r() == -42);
assert!(neg.i() == 17);
let zero = $circle_type::ZERO;
assert!($circle_type::from((5u32, 3i16)) + zero == $circle_type::from((5usize, 3isize)));
assert!(zero + $circle_type::from((7isize, -2f32)) == $circle_type::from((7f64, -2f32)));
assert!($circle_type::from((3i16, 4u32)) * zero == zero);
assert!(zero * $circle_type::from((8u64, -5i128)) == zero);
let one = $circle_type::ONE;
assert!($circle_type::from((5i32, 3f32)) * one == $circle_type::from((5f64, 3f64)));
assert!(one * $circle_type::from((9u16, -7i64)) == $circle_type::from((9f32, -7f64)));
let i = $circle_type::POS_I;
assert!(i.r().is_zero());
assert!(i.i() == 1u32);
assert!(i.square() == -1f32);
let neg_i = $circle_type::NEG_I;
assert!(neg_i.r().is_zero());
assert!(neg_i.i() == -1i32);
assert!(neg_i.square() == -1f64);
assert!(one.is_normal());
assert!(zero.is_zero());
assert!(i.is_normal());
assert!(neg_i.is_normal());
assert!($circle_type::PI.is_normal());
assert!($circle_type::E.is_normal());
let normal = $circle_type::from((42f32, 17i64));
assert!(normal.is_normal());
assert!(!zero.is_normal());
let complex_val = $circle_type::from((3f32, 4i16));
let conj = complex_val.conjugate();
assert!(conj.r() == 3f64);
assert!(conj.i() == -4i32);
let mag = complex_val.magnitude();
assert!(mag == 5f32);
let mag_sq = complex_val.magnitude_squared();
assert!(mag_sq == 25u64);
let unit = complex_val.sign();
let unit_mag = unit.magnitude();
assert!((unit_mag - 1f32).magnitude() < 0.1);
let max_val = $circle_type::MAX;
assert!(max_val.is_normal());
let exploded: $circle_type = max_val * 2;
assert!(exploded.exploded());
let min_pos = $circle_type::MIN_POS;
let vanished: $circle_type = min_pos.square();
assert!(vanished.vanished());
let undefined = $circle_type::from(0) / zero;
assert!(undefined.is_undefined());
let propagated = undefined + $circle_type::from((42f32, 17i64));
assert!(propagated.is_undefined());
};
}
macro_rules! all_circle_types {
($macro_name:ident) => {
$macro_name!(
CircleF3E3, CircleF3E4, CircleF3E5, CircleF3E6, CircleF3E7, CircleF4E3, CircleF4E4,
CircleF4E5, CircleF4E6, CircleF4E7, CircleF5E3, CircleF5E4, CircleF5E5, CircleF5E6,
CircleF5E7, CircleF6E3, CircleF6E4, CircleF6E5, CircleF6E6, CircleF6E7, CircleF7E3,
CircleF7E4, CircleF7E5, CircleF7E6, CircleF7E7
);
};
}
macro_rules! test_all_circle_types {
($($circle_type:ident),+) => {
$(
paste::paste! {
#[test]
fn [<test_ $circle_type:lower _comprehensive>]() {
test_arithmetic_for_type!($circle_type);
}
}
)+
};
}
all_circle_types!(test_all_circle_types);
#[cfg(test)]
mod basic_operations {
use super::*;
macro_rules! test_circle_creation_for_type {
($circle_type:ident) => {
let a = $circle_type::from((42u8, -17i16));
let b = $circle_type::from((100u32, 50i64));
assert!(a.is_normal());
assert!(b.is_normal());
assert!(a.r() == 42);
assert!(a.i() == -17);
assert!(b.r() == 100);
assert!(b.i() == 50);
let pi_e = $circle_type::from((3.14159f32, 2.71828f64));
assert!(pi_e.is_normal());
assert!(pi_e.r() > 3f32 && pi_e.r() < 4f32);
assert!(pi_e.i() > 2f32 && pi_e.i() < 3f32);
let real_only = $circle_type::from(7.5f64);
assert!(real_only.r() == 7.5);
assert!(real_only.i().is_zero());
let zero = $circle_type::ZERO;
let one = $circle_type::ONE;
let pos_i = $circle_type::POS_I;
let neg_i = $circle_type::NEG_I;
let pi_const = $circle_type::PI;
let e_const = $circle_type::E;
assert!(zero.is_zero());
assert!(one.is_normal());
assert!(pos_i.is_normal());
assert!(neg_i.is_normal());
assert!(pi_const.is_normal());
assert!(e_const.is_normal());
assert!(pos_i.square() == -1isize);
assert!(neg_i.square() == -1isize);
assert!((pos_i * neg_i - 1i8).magnitude() < 0.1f32);
assert!(a.r() == 42usize);
assert!(a.i() == -17isize);
assert!(one.r() == 1f32);
assert!(zero.r() == 0f64);
};
}
macro_rules! generate_circle_creation_tests {
($($circle_type:ident),+) => {
$(
paste::paste! {
#[test]
fn [<test_circle_creation_ $circle_type:lower>]() {
test_circle_creation_for_type!($circle_type);
}
}
)+
};
}
all_circle_types!(generate_circle_creation_tests);
macro_rules! test_basic_arithmetic_for_type {
($circle_type:ident) => {
let a1 = $circle_type::from((7i8, 3f32));
let b1 = $circle_type::from((3f32, 2i16));
let sum1 = a1 + b1;
assert!(sum1.r() == 10);
assert!(sum1.i() == 5);
let a2 = $circle_type::from((12u16, 8i32));
let b2 = $circle_type::from((5i32, 3f64));
let diff2 = a2 - b2;
assert!(diff2.r() == 7u64);
assert!(diff2.i() == 5i128);
let a3 = $circle_type::from((1f32, 2f64));
let b3 = $circle_type::from((3i64, 4u32));
let product3 = a3 * b3;
assert!(product3.r() == -5i128);
assert!(product3.i() == 10f32);
let a4 = $circle_type::from((20usize, 10isize));
let b4 = 2f64;
let quotient4 = a4 / b4;
assert!(quotient4.r() == 10f64);
assert!(quotient4.i() == 5f32);
let a5 = $circle_type::from((15i128, 25u32));
let scalar_add = a5 + 2f32;
assert!(scalar_add.r() == 17f64);
assert!(scalar_add.i() == 25);
let a6 = $circle_type::from((100f64, 37u8));
let scalar_sub = a6 - 37i16;
assert!(scalar_sub.r() == 63i16);
assert!(scalar_sub.i() == 37);
let a7 = $circle_type::from((9i8, 7f32));
let scalar_mult = 3u64 * a7;
assert!(scalar_mult.r() == 27);
assert!(scalar_mult.i() == 21);
let zero = $circle_type::ZERO;
let fortytwo_seventeen = $circle_type::from((42i64, 17f32));
let sum9 = zero + fortytwo_seventeen;
assert!(sum9.r() == 42);
assert!(sum9.i() == 17);
let pos = $circle_type::from((17f64, -23i32));
let neg = -pos;
assert!(neg.r() == -17);
assert!(neg.i() == 23);
};
}
macro_rules! generate_basic_arithmetic_tests {
($($circle_type:ident),+) => {
$(
paste::paste! {
#[test]
fn [<test_basic_arithmetic_ $circle_type:lower>]() {
test_basic_arithmetic_for_type!($circle_type);
}
}
)+
};
}
all_circle_types!(generate_basic_arithmetic_tests);
macro_rules! test_zero_operations_for_type {
($circle_type:ident) => {
let zero = $circle_type::ZERO;
let five_three = $circle_type::from((5u8, 3i16));
let result = five_three + zero;
assert!(result.r() == 5i16);
assert!(result.i() == 3u32);
let result2 = zero + $circle_type::from((7isize, -2f32));
assert!(result2.r() == 7f32);
assert!(result2.i() == -2f64);
let result3 = $circle_type::from((3u32, 4i64)) * zero;
assert!(result3 == zero);
let result4 = zero * $circle_type::from((9f64, -1i8));
assert!(result4.is_zero());
let div_by_zero = $circle_type::from((0i8, 0u16)) / zero;
assert!(div_by_zero.is_undefined());
};
}
macro_rules! test_arithmetic_properties_for_type {
($circle_type:ident) => {
let a = $circle_type::from((12u16, 5i32));
let b = $circle_type::from((8i32, -3f32));
let c = $circle_type::from((2f32, 7i64));
assert!(a + b == b + a);
assert!((a + b) + c == a + (b + c));
let zero = $circle_type::ZERO;
let one = $circle_type::ONE;
assert!(a + zero == a);
assert!(
one * $circle_type::from((42isize, 17f64)) == $circle_type::from((42f32, 17f32))
);
};
}
macro_rules! generate_zero_operations_tests {
($($circle_type:ident),+) => {
$(
paste::paste! {
#[test]
fn [<test_zero_operations_ $circle_type:lower>]() {
test_zero_operations_for_type!($circle_type);
}
}
)+
};
}
macro_rules! generate_arithmetic_properties_tests {
($($circle_type:ident),+) => {
$(
paste::paste! {
#[test]
fn [<test_arithmetic_properties_ $circle_type:lower>]() {
test_arithmetic_properties_for_type!($circle_type);
}
}
)+
};
}
all_circle_types!(generate_zero_operations_tests);
all_circle_types!(generate_arithmetic_properties_tests);
}
#[cfg(test)]
mod special_values {
use super::*;
macro_rules! test_escaped_values_for_type {
($circle_type:ident) => {
let max_val = $circle_type::MAX;
let exploded = max_val * 2f32;
assert!(exploded.exploded());
assert!(!exploded.is_normal());
assert!(!exploded.is_zero());
let exploded_imag = $circle_type::from((1f32, max_val.r())) * 2f64;
assert!(exploded_imag.exploded());
let min_pos = $circle_type::MIN_POS;
let vanished = min_pos / 1000u16;
assert!(vanished.vanished());
assert!(!vanished.is_normal());
assert!(!vanished.is_zero());
let vanished_imag = $circle_type::from((1f32, min_pos.r())) / 1000i32;
assert!(vanished_imag.vanished());
};
}
macro_rules! test_undefined_states_for_type {
($circle_type:ident) => {
let zero_div_zero = 0u8 / $circle_type::ZERO;
assert!(zero_div_zero.is_undefined());
let zero_pow_zero = $circle_type::ZERO.pow(0);
assert!(zero_pow_zero.r() == 1u128);
assert!(zero_pow_zero.i().is_zero());
let complex_with_neg = $circle_type::from((-4i16, 0f32));
let sqrt_complex = complex_with_neg.sqrt();
assert!(sqrt_complex.is_normal() || sqrt_complex.vanished());
let propagated = zero_div_zero + $circle_type::from((42i64, 17f32));
assert!(propagated.is_undefined());
let propagated2 = zero_div_zero * $circle_type::from((10f64, -5i8));
assert!(propagated2.is_undefined());
};
}
macro_rules! test_escaped_operations_for_type {
($circle_type:ident) => {
let exploded = $circle_type::MAX * 2usize;
let vanished = $circle_type::MIN_POS / 1000isize;
let exploded_squared = exploded.square();
assert!(exploded_squared.exploded());
let vanished_squared = vanished.square();
assert!(vanished_squared.vanished());
let neg_exploded = -exploded;
assert!(neg_exploded.exploded());
};
}
macro_rules! generate_escaped_values_tests {
($($circle_type:ident),+) => {
$(
paste::paste! {
#[test]
fn [<test_escaped_values_ $circle_type:lower>]() {
test_escaped_values_for_type!($circle_type);
}
}
)+
};
}
macro_rules! generate_undefined_states_tests {
($($circle_type:ident),+) => {
$(
paste::paste! {
#[test]
fn [<test_undefined_states_ $circle_type:lower>]() {
test_undefined_states_for_type!($circle_type);
}
}
)+
};
}
macro_rules! generate_escaped_operations_tests {
($($circle_type:ident),+) => {
$(
paste::paste! {
#[test]
fn [<test_escaped_operations_ $circle_type:lower>]() {
test_escaped_operations_for_type!($circle_type);
}
}
)+
};
}
all_circle_types!(generate_escaped_values_tests);
all_circle_types!(generate_undefined_states_tests);
all_circle_types!(generate_escaped_operations_tests);
}
#[cfg(test)]
mod mathematical_functions {
use super::*;
macro_rules! test_power_functions_for_type {
($circle_type:ident) => {
let base = $circle_type::from((2u8, 1i16));
let exp = 2f32;
let result = base.pow(exp);
assert!((result.r() - 3f32).magnitude() < 0.1);
assert!((result.i() - 4f32).magnitude() < 0.1);
let square = base.square();
assert!((square.r() - 3f64).magnitude() < 0.1);
assert!((square.i() - 4f64).magnitude() < 0.1);
let sqrt_val = $circle_type::from(9f32).sqrt();
assert!(sqrt_val == 3f64);
let recip = $circle_type::from((2usize, 0isize)).reciprocal();
assert!((recip.r() - 0.5f32).magnitude() < 0.1);
assert!(recip.i().magnitude() < 0.1);
};
}
macro_rules! test_exp_log_for_type {
($circle_type:ident) => {
let exp_result = $circle_type::from((1isize, 0f32)).exp();
let e_const = $circle_type::E;
assert!((exp_result.r() - e_const.r()).magnitude() < 0.1f32);
let ln_e = e_const.ln();
assert!((ln_e.r() - 1u128).magnitude() < 0.1f32);
};
}
macro_rules! test_trig_functions_for_type {
($circle_type:ident) => {
let zero = $circle_type::ZERO;
let sin_zero = zero.sin();
assert!(sin_zero.r().magnitude() < 0.1);
assert!(sin_zero.i().magnitude() < 0.1);
let cos_zero = zero.cos();
assert!((cos_zero.r() - 1u16).magnitude() < 0.1);
assert!(cos_zero.i().magnitude() < 0.1);
let tan_zero = zero.tan();
assert!(tan_zero.r().magnitude() < 0.1);
assert!(tan_zero.i().magnitude() < 0.1);
let pure_imag = $circle_type::from((0f32, 1i64));
let sin_i = pure_imag.sin();
assert!(sin_i.r().magnitude() < 0.1);
assert!(sin_i.i() != 0f64);
};
}
macro_rules! test_hyperbolic_for_type {
($circle_type:ident) => {
let zero = $circle_type::ZERO;
let sinh_0 = zero.sinh();
assert!(sinh_0.r().magnitude() < 0.1);
assert!(sinh_0.i().magnitude() < 0.1);
let cosh_0 = zero.cosh();
assert!((cosh_0.r() - 1u32).magnitude() < 0.1);
assert!(cosh_0.i().magnitude() < 0.1);
let tanh_0 = zero.tanh();
assert!(tanh_0.r().magnitude() < 0.1);
assert!(tanh_0.i().magnitude() < 0.1);
let pure_imag = $circle_type::from((0f32, 1f64));
let sinh_i = pure_imag.sinh();
assert!(sinh_i.r().magnitude() < 0.1);
assert!(sinh_i.i() != 0i64);
};
}
macro_rules! generate_power_tests {
($($circle_type:ident),+) => {
$(
paste::paste! {
#[test]
fn [<test_power_functions_ $circle_type:lower>]() {
test_power_functions_for_type!($circle_type);
}
}
)+
};
}
macro_rules! generate_exp_log_tests {
($($circle_type:ident),+) => {
$(
paste::paste! {
#[test]
fn [<test_exp_log_ $circle_type:lower>]() {
test_exp_log_for_type!($circle_type);
}
}
)+
};
}
macro_rules! generate_trig_tests {
($($circle_type:ident),+) => {
$(
paste::paste! {
#[test]
fn [<test_trig_ $circle_type:lower>]() {
test_trig_functions_for_type!($circle_type);
}
}
)+
};
}
macro_rules! generate_hyperbolic_tests {
($($circle_type:ident),+) => {
$(
paste::paste! {
#[test]
fn [<test_hyperbolic_ $circle_type:lower>]() {
test_hyperbolic_for_type!($circle_type);
}
}
)+
};
}
all_circle_types!(generate_power_tests);
all_circle_types!(generate_exp_log_tests);
all_circle_types!(generate_trig_tests);
all_circle_types!(generate_hyperbolic_tests);
}
#[cfg(test)]
mod comparison_and_utility {
use super::*;
macro_rules! test_equality_for_type {
($circle_type:ident) => {
let a = $circle_type::from((5u8, 3i16));
let b = $circle_type::from((5f32, 3f64));
let c = $circle_type::from((8i32, -2i64));
assert!(a == b);
assert!(a != c);
assert!(a == a);
assert!(c == c);
let zero = $circle_type::ZERO;
assert!(zero == $circle_type::from((0u8, 0i16)));
assert!($circle_type::from((0f32, 0f64)) == zero);
};
}
macro_rules! test_state_checking_for_type {
($circle_type:ident) => {
let normal = $circle_type::from((42u64, 17i32));
let zero = $circle_type::ZERO;
let exploded = $circle_type::MAX * 2f32;
let vanished = $circle_type::MIN_POS / 1000f64;
let undefined = $circle_type::INFINITY / $circle_type::INFINITY;
assert!(normal.is_normal());
assert!(normal.is_finite());
assert!(!normal.is_zero());
assert!(!normal.vanished());
assert!(!normal.exploded());
assert!(!normal.is_undefined());
assert!(!zero.is_normal());
assert!(zero.is_finite());
assert!(zero.is_zero());
assert!(zero.is_negligible());
assert!(!exploded.is_normal());
assert!(!exploded.is_finite());
assert!(exploded.exploded());
assert!(!vanished.is_normal());
assert!(!vanished.is_finite());
assert!(vanished.vanished());
assert!(vanished.is_negligible());
assert!(!undefined.is_normal());
assert!(!undefined.is_finite());
assert!(undefined.is_undefined());
};
}
macro_rules! generate_equality_tests {
($($circle_type:ident),+) => {
$(
paste::paste! {
#[test]
fn [<test_equality_ $circle_type:lower>]() {
test_equality_for_type!($circle_type);
}
}
)+
};
}
macro_rules! generate_state_checking_tests {
($($circle_type:ident),+) => {
$(
paste::paste! {
#[test]
fn [<test_state_checking_ $circle_type:lower>]() {
test_state_checking_for_type!($circle_type);
}
}
)+
};
}
all_circle_types!(generate_equality_tests);
all_circle_types!(generate_state_checking_tests);
}
#[cfg(test)]
mod bitwise_operations {
use super::*;
macro_rules! test_bitwise_for_type {
($circle_type:ident) => {
let a = $circle_type::from((42i32, 51i32)); let b = $circle_type::from((85i32, 102i32));
let and_result = a & b;
assert!(and_result.r() == 0i32);
assert!(and_result.i() == 34i32);
let or_result = a | b;
assert!(or_result.r() == 127i32);
assert!(or_result.i() == 119i32);
let xor_result = a ^ b;
assert!(xor_result.r() == 127i32);
assert!(xor_result.i() == 85i32);
assert!(a & b == b & a);
assert!(a | b == b | a);
assert!(a ^ b == b ^ a);
let zero = $circle_type::from((0i32, 0i32));
assert!(a & zero == zero);
assert!(a | zero == a);
assert!(a ^ zero == a);
let ones = $circle_type::from((-1i32, -1i32));
assert!(a & ones == a);
assert!(a | ones == ones);
let left_shift = a << 1i32;
assert!(left_shift.r() == 84i32);
assert!(left_shift.i() == 102i32);
let right_shift = left_shift >> 1i32;
assert!(right_shift.r() == 42i32);
assert!(right_shift.i() == 51i32);
assert!(right_shift == a);
};
}
macro_rules! generate_bitwise_tests {
($($circle_type:ident),+) => {
$(
paste::paste! {
#[test]
fn [<test_bitwise_ $circle_type:lower>]() {
test_bitwise_for_type!($circle_type);
}
}
)+
};
}
all_circle_types!(generate_bitwise_tests);
}
#[cfg(test)]
mod modular_operations {
use super::*;
macro_rules! test_modulo_for_type {
($circle_type:ident) => {
let a = $circle_type::from((17u8, 13i16));
let b = $circle_type::from((5i16, 4f32));
let remainder = a % b;
assert!(remainder.is_normal() || remainder.is_zero() || remainder.is_undefined());
let component_mod = a.modulo(b);
assert!(component_mod.r() == 2f32);
assert!(component_mod.i() == 1f64);
let scalar_mod = a % 3u64;
assert!(scalar_mod.is_normal() || scalar_mod.is_zero() || scalar_mod.is_undefined());
let component_scalar_mod = a.modulo(3i32);
assert!(component_scalar_mod.r() == 2i128);
assert!(component_scalar_mod.i() == 1f32);
let zero = $circle_type::ZERO;
assert!((zero % $circle_type::from((5u16, 3i32))).is_zero());
assert!((zero % 7f64).is_zero());
assert!(($circle_type::from((42, 17)) % zero).is_zero());
assert!(($circle_type::from((17f32, 23i64)) % zero).is_zero());
let exploded = $circle_type::MAX * 2usize;
let vanished = $circle_type::MIN_POS / 1000isize;
let exploded_mod = exploded % $circle_type::from((5f32, 3f64));
assert!(exploded_mod.is_undefined() || exploded_mod.exploded());
let mod_vanished = $circle_type::from((42u32, 17i8)) % vanished;
assert!(mod_vanished.is_undefined());
assert!((exploded % zero).is_zero());
assert!((vanished % zero).is_zero());
let undefined = $circle_type::INFINITY / $circle_type::INFINITY;
assert!((undefined % $circle_type::from((5, 3))).is_undefined());
assert!(($circle_type::from((5, 3)) % undefined).is_undefined());
};
}
macro_rules! generate_modular_tests {
($($circle_type:ident),+) => {
$(
paste::paste! {
#[test]
fn [<test_modulo_ $circle_type:lower>]() {
test_modulo_for_type!($circle_type);
}
}
)+
};
}
all_circle_types!(generate_modular_tests);
}
#[cfg(test)]
mod random_testing {
use super::*;
macro_rules! test_random_for_type {
($circle_type:ident) => {
const SAMPLE_SIZE: usize = 50; let mut uniform_samples = Vec::with_capacity(SAMPLE_SIZE);
let mut gauss_samples = Vec::with_capacity(SAMPLE_SIZE);
for _ in 0..SAMPLE_SIZE {
let random_val = $circle_type::random();
assert!(random_val.is_normal() || random_val.is_zero() || random_val.vanished());
if random_val.is_normal() {
uniform_samples.push(random_val);
}
let random_gauss = $circle_type::random_gauss();
assert!(
random_gauss.is_normal()
|| random_gauss.is_zero()
|| random_gauss.exploded()
|| random_gauss.vanished()
);
if random_gauss.is_normal() {
gauss_samples.push(random_gauss);
}
}
if !uniform_samples.is_empty() {
let mut within_unit_circle = 0u32;
for &sample in &uniform_samples {
if sample.magnitude() <= 1.5 {
within_unit_circle += 1;
}
}
let within_ratio = within_unit_circle as f64 / uniform_samples.len() as f64;
assert!(
within_ratio > 0.3,
"Too many uniform samples outside reasonable range: {:.2}",
within_ratio
);
}
let rand_test = $circle_type::random();
assert!(rand_test == rand_test); assert!(rand_test.magnitude() >= 0u8);
let gauss_test = $circle_type::random_gauss();
let combined = rand_test + gauss_test;
assert!(
combined.is_normal()
|| combined.is_zero()
|| combined.exploded()
|| combined.vanished()
|| combined.is_undefined()
);
let complex_rand = $circle_type::random();
let real_part = complex_rand.r();
let imag_part = complex_rand.i();
assert!(real_part.is_normal() || real_part.is_zero() || real_part.vanished());
assert!(imag_part.is_normal() || imag_part.is_zero() || imag_part.vanished());
};
}
macro_rules! generate_random_tests {
($($circle_type:ident),+) => {
$(
paste::paste! {
#[test]
fn [<test_random_ $circle_type:lower>]() {
test_random_for_type!($circle_type);
}
}
)+
};
}
all_circle_types!(generate_random_tests);
}
#[cfg(test)]
mod complex_specific {
use super::*;
macro_rules! test_complex_operations_for_type {
($circle_type:ident) => {
let complex = $circle_type::from((3f32, 4i16));
let conj = complex.conjugate();
assert!(conj.r() == 3f64);
assert!(conj.i() == -4i32);
assert!(conj.conjugate() == complex);
let real_only = $circle_type::from(42f64);
assert!(real_only.conjugate() == real_only);
let complex_3_4 = $circle_type::from((3f32, 4f64));
let mag = complex_3_4.magnitude();
let mag_sq = complex_3_4.magnitude_squared();
assert!((mag - 5f32).magnitude() < 0.1);
assert!((mag_sq - 25u64).magnitude() < 0.1);
let product_with_conj = complex_3_4 * complex_3_4.conjugate();
assert!((product_with_conj.r() - mag_sq).magnitude() < 0.1);
assert!(product_with_conj.i().magnitude() < 0.1);
let unit = complex_3_4.sign();
let unit_mag = unit.magnitude();
assert!((unit_mag - 1f32).magnitude() < 0.1);
let zero_sign = $circle_type::ZERO.sign();
assert!(zero_sign.is_undefined());
let i = $circle_type::POS_I;
let neg_i = $circle_type::NEG_I;
assert!(i.square().r() == -1f32);
assert!(i.square().i().magnitude() < 0.1);
assert!(neg_i.square().r() == -1f64);
assert!(neg_i.square().i().magnitude() < 0.1);
let i_times_neg_i = i * neg_i;
assert!((i_times_neg_i.r() - 1f32).magnitude() < 0.1);
assert!(i_times_neg_i.i().magnitude() < 0.1);
assert!(i.conjugate() == neg_i);
assert!(neg_i.conjugate() == i);
let i_pi = $circle_type::POS_I * $circle_type::PI;
let euler = i_pi.exp();
assert!((euler.r() + 1f32).magnitude() < 0.1);
assert!(euler.i().magnitude() < 0.1);
let complex_test = $circle_type::from((7.5f32, -2.3f64));
assert!(complex_test.r() == 7.5);
assert!(complex_test.i() == -2.3);
let real_num = $circle_type::from(42i64);
assert!(real_num.r() == 42u128);
assert!(real_num.i().is_zero());
};
}
macro_rules! generate_complex_specific_tests {
($($circle_type:ident),+) => {
$(
paste::paste! {
#[test]
fn [<test_complex_operations_ $circle_type:lower>]() {
test_complex_operations_for_type!($circle_type);
}
}
)+
};
}
all_circle_types!(generate_complex_specific_tests);
}