use crate::traits::{Statistics, StatisticsType};
#[inline]
#[allow(dead_code)]
fn is_odd_period(tau: f64, beta: f64) -> bool {
tau < 0.0 || tau > beta
}
pub fn normalize_tau<S: StatisticsType>(tau: f64, beta: f64) -> (f64, f64) {
if tau < -beta || tau > beta {
panic!(
"tau = {} is outside allowed range [-beta = {}, beta = {}]",
tau, -beta, beta
);
}
if tau.is_sign_negative() && tau == 0.0 {
return match S::STATISTICS {
Statistics::Fermionic => (beta, -1.0), Statistics::Bosonic => (beta, 1.0), };
}
if tau >= 0.0 && tau <= beta {
return (tau, 1.0);
}
let tau_normalized = tau + beta;
let sign = match S::STATISTICS {
Statistics::Fermionic => -1.0, Statistics::Bosonic => 1.0, };
(tau_normalized, sign)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::traits::{Bosonic, Fermionic};
#[test]
fn test_is_odd_period() {
let beta = 1.0;
assert!(!is_odd_period(0.0, beta));
assert!(!is_odd_period(0.5, beta));
assert!(!is_odd_period(beta, beta));
assert!(is_odd_period(-0.1, beta));
assert!(is_odd_period(1.1, beta));
}
#[test]
fn test_normalize_tau_generic_fermionic() {
let beta = 1.0;
let (tau_norm, sign) = normalize_tau::<Fermionic>(0.5, beta);
assert!((tau_norm - 0.5).abs() < 1e-14);
assert!((sign - 1.0).abs() < 1e-14);
let (tau_norm, sign) = normalize_tau::<Fermionic>(beta, beta);
assert!((tau_norm - beta).abs() < 1e-14);
assert!((sign - 1.0).abs() < 1e-14);
let (tau_norm, sign) = normalize_tau::<Fermionic>(0.0, beta);
assert!(tau_norm.abs() < 1e-14);
assert!((sign - 1.0).abs() < 1e-14);
let (tau_norm, sign) = normalize_tau::<Fermionic>(-0.3, beta);
assert!((tau_norm - 0.7).abs() < 1e-14);
assert!((sign - (-1.0)).abs() < 1e-14);
let (tau_norm, sign) = normalize_tau::<Fermionic>(-beta, beta);
assert!(tau_norm.abs() < 1e-14); assert!((sign - (-1.0)).abs() < 1e-14);
}
#[test]
fn test_normalize_tau_negative_zero_fermionic() {
let beta = 1.0;
let (tau_norm, sign) = normalize_tau::<Fermionic>(-0.0, beta);
assert!(
(tau_norm - beta).abs() < 1e-14,
"Expected tau_normalized = {}, got {}",
beta,
tau_norm
);
assert!(
(sign - (-1.0)).abs() < 1e-14,
"Expected sign = -1.0, got {}",
sign
);
let (tau_norm, sign) = normalize_tau::<Fermionic>(0.0, beta);
assert!(
tau_norm.abs() < 1e-14,
"Expected tau_normalized = 0.0, got {}",
tau_norm
);
assert!(
(sign - 1.0).abs() < 1e-14,
"Expected sign = 1.0, got {}",
sign
);
assert_ne!(
(-0.0_f64).to_bits(),
0.0_f64.to_bits(),
"Rust should distinguish -0.0 from 0.0"
);
}
#[test]
fn test_normalize_tau_generic_bosonic() {
let beta = 1.0;
let (tau_norm, sign) = normalize_tau::<Bosonic>(0.5, beta);
assert!((tau_norm - 0.5).abs() < 1e-14);
assert!((sign - 1.0).abs() < 1e-14);
let (tau_norm, sign) = normalize_tau::<Bosonic>(beta, beta);
assert!((tau_norm - beta).abs() < 1e-14);
assert!((sign - 1.0).abs() < 1e-14);
let (tau_norm, sign) = normalize_tau::<Bosonic>(0.0, beta);
assert!(tau_norm.abs() < 1e-14);
assert!((sign - 1.0).abs() < 1e-14);
let (tau_norm, sign) = normalize_tau::<Bosonic>(-0.3, beta);
assert!((tau_norm - 0.7).abs() < 1e-14);
assert!((sign - 1.0).abs() < 1e-14);
let (tau_norm, sign) = normalize_tau::<Bosonic>(-beta, beta);
assert!(tau_norm.abs() < 1e-14); assert!((sign - 1.0).abs() < 1e-14);
}
#[test]
#[should_panic(expected = "outside allowed range")]
fn test_normalize_tau_out_of_range_positive() {
let beta = 1.0;
let _ = normalize_tau::<Fermionic>(1.5, beta);
}
#[test]
#[should_panic(expected = "outside allowed range")]
fn test_normalize_tau_out_of_range_negative() {
let beta = 1.0;
let _ = normalize_tau::<Fermionic>(-1.5, beta);
}
}