use fixed32::Fp;
#[test]
fn add() {
let result = Fp::from(2) + Fp::from(2);
assert_eq!(result.inner(), 4 * Fp::SCALE);
}
#[test]
fn mul() {
let result = Fp::from(3) * Fp::from(2);
assert_eq!(result.inner(), 6 * Fp::SCALE);
}
#[test]
fn div() {
let result = Fp::from(99) / Fp::from(3);
assert_eq!(result.inner(), 33 * Fp::SCALE);
}
#[test]
fn div_bigger_number() {
let result = Fp::from(30000) / Fp::from(12);
assert_eq!(result.inner(), 2500 * Fp::SCALE);
}
#[test]
fn sub() {
let result = Fp::from(-42) + Fp::from(43);
assert_eq!(result.inner(), 1 * Fp::SCALE);
}
#[test]
fn div_int() {
let result = 400 / Fp::from(10);
let i: i32 = result.into();
assert_eq!(i, 40);
}
#[test]
fn mul_int() {
let result = 99 * Fp::from(10);
let i: i16 = result.into();
assert_eq!(i, 990);
}
#[test]
fn from_float() {
let result = 99 * Fp::from(10.0);
let i: i16 = result.into();
assert_eq!(i, 990);
}
#[test]
fn acos_test() {
let test_values = [
(core::f32::consts::PI, -1.0), (core::f32::consts::FRAC_PI_2, 0.0), (0.0, 1.0), (core::f32::consts::FRAC_PI_3, 0.5), (2.0944, -0.5), (
core::f32::consts::FRAC_PI_4,
core::f32::consts::FRAC_1_SQRT_2,
), (2.3562, -core::f32::consts::FRAC_1_SQRT_2), (core::f32::consts::FRAC_PI_6, 0.866), (2.61799, -0.866), ];
println!("Expected fixed-point values (16.16 format):");
for &(expected_radian, unit_interval) in test_values.iter() {
let fp_unit_interval = Fp::from(unit_interval);
let result_radian = fp_unit_interval.acos();
let fp_raw_radian = result_radian.inner();
let expected_raw_radian = Fp::from(expected_radian).inner();
let diff = (fp_raw_radian - expected_raw_radian).abs();
println!(
"Input: {:.4}, Calculated: {:.4} ({:.4}), Expected: {} ({:.4}) diff: {diff}",
unit_interval,
fp_raw_radian,
fp_raw_radian as f64 / Fp::SCALE as f64,
expected_raw_radian,
expected_raw_radian as f64 / Fp::SCALE as f64,
);
if diff > 500 {
panic!("too far off. got {result_radian}, but expected {expected_raw_radian}");
}
}
}
#[test]
fn custom_sin() {
let test_values = [
(0.0, 0.0),
(core::f64::consts::PI / 2.0, 1.0),
(5.0 * core::f64::consts::PI / 2.0, 1.0),
(core::f64::consts::PI, 0.0),
(3.0 * core::f64::consts::PI / 2.0, -1.0),
(2.0 * core::f64::consts::PI, 0.0),
(core::f64::consts::PI / 6.0, 0.5),
(1.01598529, 0.85),
];
for (input, expected) in test_values {
let fp = Fp::from(input as f32);
let fp_result = fp.sin();
let result: f32 = fp_result.into();
println!("result: {result} expected: {expected}");
assert!(
(result - expected).abs() < 0.03,
"Expected sin({}) ≈ {}, got {}",
input,
expected,
result
);
}
}
#[test]
fn sqrt_zero() {
let value = Fp::from(0);
let result = value.sqrt();
assert_eq!(result, Fp::zero()); }
#[test]
fn sqrt_one() {
let value = Fp::one();
let result = value.sqrt();
assert_eq!(result, Fp::one()); }
#[test]
fn sqrt_four() {
let value = Fp::from(4);
let result = value.sqrt();
assert_eq!(result, Fp::from(2)); }
#[test]
fn sqrt_fraction() {
let value = Fp::from(4225);
let result = value.sqrt();
assert_eq!(result, Fp::from(65)); }
#[test]
#[should_panic]
fn sqrt_negative() {
let value = Fp::from(-3923);
let _ = value.sqrt();
}
#[inline]
fn from_bits(v: i32) -> Fp {
Fp::from_raw(v)
}
#[test]
fn sqrt_tiny_raw_lsb() {
let tiny = from_bits(1);
let result = tiny.sqrt();
let expected = from_bits(256);
assert_eq!(
result, expected,
"sqrt(1/2^16) = 1/2^8 exactly; got {:?}, want {:?}",
result, expected
);
}
#[test]
fn sqrt_small_fraction() {
let small = from_bits(4);
let result = small.sqrt();
let expected = from_bits(512);
assert!(
(result - expected).inner().abs() <= 1,
"sqrt(4/2^16) ≈ 2/2^8; got {:?}, want {:?} (±1 LSB)",
result,
expected
);
}
#[test]
fn sqrt_random_precision() {
let raw_inputs = [1, 2, 3, 10, 100, 1_000, 10_000, 42_000];
for &xf in &raw_inputs {
let x = from_bits(xf);
let result = x.sqrt();
let expected_bits = (((xf as f64) / 65_536.0).sqrt() * 65_536.0).round() as i32;
let expected = from_bits(expected_bits);
let diff = (result - expected).inner().abs();
assert!(
diff <= 1,
"√(raw={xf}) ≈ {expected_bits} bits; got {:?} ({:?} bits), diff = {} LSB",
result,
result.inner(),
diff
);
}
}
#[test]
fn ceil_positive() {
let value = Fp::from(5);
let result = value.ceil();
assert_eq!(result, value);
}
#[test]
fn ceil_negative() {
let value = Fp::from(-5) - Fp::from_raw(1);
let result = value.ceil();
assert_eq!(result, Fp::from(-5)); }
#[test]
fn round_positive() {
let value = Fp::from(5) + 0.5.into(); let result = value.round();
assert_eq!(result, Fp::from(6)); }
#[test]
fn round_negative() {
let value = Fp::from(-5) - Fp::from_raw(Fp::SCALE / 2); let result = value.round();
assert_eq!(result, Fp::from(-5)); }
#[test]
fn clamp_within_range() {
let value = Fp::from(5);
let min = Fp::from(3);
let max = Fp::from(7);
let result = value.clamp(min, max);
assert_eq!(result, value); }
#[test]
fn clamp_below_range() {
let value: Fp = (-4).into();
let min = Fp::from(-3);
let max = Fp::from(7);
let result = value.clamp(min, max);
assert_eq!(result, min);
}
#[test]
fn clamp_above_range() {
let value = Fp::from(8);
let min = Fp::from(-3);
let max = 7.into();
let result = value.clamp(min, max);
assert_eq!(result, max); }
#[test]
fn abs_positive() {
let value = Fp::from(5);
let result = value.abs();
assert_eq!(result, value); }
#[test]
fn abs_negative() {
let value = Fp::from(-5);
let result = value.abs();
assert_eq!(result, Fp::from(5)); }
#[test]
fn int16_less_than() {
let value = Fp::from(-5);
let result = value < -4;
assert!(result);
}
#[test]
fn int16_greater_than() {
let value = Fp::from(-5);
let result = value > -6;
assert!(result);
}
#[test]
fn int16_equal() {
let value = Fp::from(-42);
let result = value == -42;
assert!(result);
}
#[test]
fn int16_not_equal() {
let value = Fp::from(-42);
let result = value != 90;
assert!(result);
}