use core::cmp::Ordering;
use super::*;
#[test]
fn cmp_int_float_nan_returns_none() {
assert_eq!(cmp_int_float(0, f64::NAN), None);
assert_eq!(cmp_int_float(i64::MAX, f64::NAN), None);
assert_eq!(cmp_int_float(i64::MIN, f64::NAN), None);
}
#[test]
fn cmp_int_float_positive_infinity() {
assert_eq!(cmp_int_float(0, f64::INFINITY), Some(Ordering::Less));
assert_eq!(cmp_int_float(i64::MAX, f64::INFINITY), Some(Ordering::Less));
assert_eq!(cmp_int_float(i64::MIN, f64::INFINITY), Some(Ordering::Less));
}
#[test]
fn cmp_int_float_negative_infinity() {
assert_eq!(cmp_int_float(0, f64::NEG_INFINITY), Some(Ordering::Greater));
assert_eq!(
cmp_int_float(i64::MIN, f64::NEG_INFINITY),
Some(Ordering::Greater)
);
}
#[test]
fn cmp_int_float_exact_zero() {
assert_eq!(cmp_int_float(0, 0.0), Some(Ordering::Equal));
assert_eq!(cmp_int_float(0, -0.0), Some(Ordering::Equal));
}
#[test]
fn cmp_int_float_exact_integer_values() {
assert_eq!(cmp_int_float(1, 1.0), Some(Ordering::Equal));
assert_eq!(cmp_int_float(-1, -1.0), Some(Ordering::Equal));
assert_eq!(cmp_int_float(100, 100.0), Some(Ordering::Equal));
}
#[test]
fn cmp_int_float_integer_less_than_float_with_fraction() {
assert_eq!(cmp_int_float(1, 1.5), Some(Ordering::Less));
}
#[test]
fn cmp_int_float_integer_greater_than_float_with_fraction() {
assert_eq!(cmp_int_float(2, 1.5), Some(Ordering::Greater));
}
#[test]
fn cmp_int_float_negative_fraction() {
assert_eq!(cmp_int_float(-2, -1.5), Some(Ordering::Less));
assert_eq!(cmp_int_float(-1, -1.5), Some(Ordering::Greater));
}
#[test]
fn cmp_int_float_i64_max() {
let f: f64 = 9_223_372_036_854_775_808.0; assert_eq!(cmp_int_float(i64::MAX, f), Some(Ordering::Less));
}
#[test]
fn cmp_int_float_i64_min() {
let f: f64 = -9_223_372_036_854_775_808.0; assert_eq!(cmp_int_float(i64::MIN, f), Some(Ordering::Equal));
}
#[test]
fn cmp_int_float_subnormal() {
let subnormal = f64::MIN_POSITIVE / 2.0;
assert!(subnormal > 0.0 && subnormal < f64::MIN_POSITIVE);
assert_eq!(cmp_int_float(0, subnormal), Some(Ordering::Less));
assert_eq!(cmp_int_float(1, subnormal), Some(Ordering::Greater));
}
#[test]
fn decompose_f64_zero() {
let (int_part, has_frac, negative) = decompose_f64(0.0);
assert_eq!(int_part, 0);
assert!(!has_frac);
assert!(!negative);
}
#[test]
fn decompose_f64_negative_zero() {
let (int_part, has_frac, negative) = decompose_f64(-0.0);
assert_eq!(int_part, 0);
assert!(!has_frac);
assert!(negative);
}
#[test]
fn decompose_f64_positive_integer() {
let (int_part, has_frac, negative) = decompose_f64(42.0);
assert_eq!(int_part, 42);
assert!(!has_frac);
assert!(!negative);
}
#[test]
fn decompose_f64_negative_with_fraction() {
let (int_part, has_frac, negative) = decompose_f64(-2.78);
assert_eq!(int_part, 2);
assert!(has_frac);
assert!(negative);
}
#[test]
fn decompose_f64_subnormal() {
let subnormal = f64::MIN_POSITIVE / 2.0;
let (int_part, has_frac, negative) = decompose_f64(subnormal);
assert_eq!(int_part, 0);
assert!(has_frac); assert!(!negative);
}
#[test]
fn decompose_f64_exact_float_int_boundary() {
let boundary: f64 = 4_503_599_627_370_496.0; let (int_part, has_frac, negative) = decompose_f64(boundary);
assert_eq!(int_part, 1_u64 << 52);
assert!(!has_frac);
assert!(!negative);
}
#[test]
fn decompose_f64_value_less_than_one() {
let (int_part, has_frac, negative) = decompose_f64(0.5);
assert_eq!(int_part, 0);
assert!(has_frac);
assert!(!negative);
}
fn fixed(f: f64, precision: usize) -> String {
let mut out = String::new();
write_fixed_float(f, precision, &mut out);
out
}
fn fixed_std(f: f64, precision: usize) -> String {
format!("{f:.precision$}")
}
#[test]
fn write_fixed_float_basic_positive() {
assert_eq!(fixed(98.7, 1), "98.7");
assert_eq!(fixed(45.2, 1), "45.2");
assert_eq!(fixed(12.3, 1), "12.3");
assert_eq!(fixed(3.14258, 2), "3.14");
}
#[test]
fn write_fixed_float_rounding() {
assert_eq!(fixed(1.25, 1), "1.3"); assert_eq!(fixed(1.35, 1), "1.4"); assert_eq!(fixed(1.45, 1), "1.5"); assert_eq!(fixed(2.999, 2), "3.00"); }
#[test]
fn write_fixed_float_zero_precision() {
assert_eq!(fixed(3.7, 0), "4"); assert_eq!(fixed(3.2, 0), "3"); assert_eq!(fixed(0.0, 0), "0");
}
#[test]
fn write_fixed_float_negative() {
assert_eq!(fixed(-1.5, 1), "-1.5");
assert_eq!(fixed(-0.5, 2), "-0.50");
assert_eq!(fixed(-99.999, 2), "-100.00");
}
#[test]
fn write_fixed_float_zero() {
assert_eq!(fixed(0.0, 1), "0.0");
assert_eq!(fixed(0.0, 3), "0.000");
assert_eq!(fixed(-0.0, 2), "0.00"); }
#[test]
fn write_fixed_float_leading_zeros_in_fraction() {
assert_eq!(fixed(1.001, 3), "1.001");
assert_eq!(fixed(1.01, 3), "1.010");
assert_eq!(fixed(1.0001, 4), "1.0001");
}
#[test]
fn write_fixed_float_matches_std() {
let values = [0.0, 1.0, -1.0, 3.14258, 98.7, 45.2, 12.3, 0.001, 999.999];
for &v in &values {
for p in 0..=6 {
assert_eq!(fixed(v, p), fixed_std(v, p), "mismatch for fixed({v}, {p})");
}
}
}
fn render_fixed_int(int_val: i64, precision: usize) -> String {
use crate::{Template, ctx};
let src =
alloc::format!("---\nparams:\n - val = int\n---\n{{{{ val | fixed({precision}) }}}}");
let tmpl = Template::from_source(&src).expect("compile");
tmpl.render_ctx(&ctx! { val: int_val }).expect("render")
}
fn fixed_int_general(int_val: i64, precision: usize) -> String {
if precision == 0 {
alloc::format!("{int_val}")
} else {
let mut s = alloc::format!("{int_val}.");
for _ in 0..precision {
s.push('0');
}
s
}
}
#[test]
fn fast_path_fixed_int_small_values() {
assert_eq!(render_fixed_int(0, 1), "0.0");
assert_eq!(render_fixed_int(42, 2), "42.00");
assert_eq!(render_fixed_int(-7, 1), "-7.0");
assert_eq!(render_fixed_int(1, 0), "1");
assert_eq!(render_fixed_int(0, 0), "0");
}
#[test]
fn fast_path_fixed_int_large_values_no_precision_loss() {
let big = 9_007_199_254_740_993_i64;
assert_eq!(render_fixed_int(big, 1), fixed_int_general(big, 1));
assert_eq!(render_fixed_int(big, 0), fixed_int_general(big, 0));
assert_eq!(
render_fixed_int(i64::MAX, 2),
fixed_int_general(i64::MAX, 2)
);
assert_eq!(
render_fixed_int(i64::MIN, 1),
fixed_int_general(i64::MIN, 1)
);
}
#[test]
fn fast_path_fixed_int_matches_general_path() {
let values = [
0,
1,
-1,
100,
-100,
i64::MAX,
i64::MIN,
9_007_199_254_740_993,
];
for &v in &values {
for p in 0..=4 {
assert_eq!(
render_fixed_int(v, p),
fixed_int_general(v, p),
"mismatch for fixed({v}, {p})"
);
}
}
}