pub const EPSILON: f64 = 1e-7;
pub const OUTER_BOUNDARY_FACTOR: f64 = 0.999;
pub const INNER_BOUNDARY_FACTOR: f64 = 0.001;
pub const MIN_NEIGHBORS_QUADRATIC: usize = 3;
#[inline]
pub fn tricube_weight(u: f64) -> f64 {
let abs_u = u.abs();
if abs_u >= 1.0 {
0.0
} else {
let inner = 1.0 - abs_u.powi(3);
inner.powi(3)
}
}
#[inline]
pub fn tricube_weight_with_bounds(r: f64, h: f64) -> f64 {
if h <= 0.0 {
return 1.0; }
let outer_boundary = OUTER_BOUNDARY_FACTOR * h;
let inner_boundary = INNER_BOUNDARY_FACTOR * h;
if r > outer_boundary {
return 0.0;
}
if r <= inner_boundary {
1.0
} else {
let u = r / h;
let inner = 1.0 - u.powi(3);
inner.powi(3)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_tricube_weight_zero() {
assert_eq!(tricube_weight(0.0), 1.0);
}
#[test]
fn test_tricube_weight_half() {
let result = tricube_weight(0.5);
let expected = 0.669921875;
assert!((result - expected).abs() < 1e-10);
}
#[test]
fn test_tricube_weight_boundary() {
assert_eq!(tricube_weight(1.0), 0.0);
assert_eq!(tricube_weight(-1.0), 0.0);
assert_eq!(tricube_weight(1.5), 0.0);
assert_eq!(tricube_weight(-2.0), 0.0);
}
#[test]
fn test_tricube_weight_symmetry() {
assert_eq!(tricube_weight(-0.3), tricube_weight(0.3));
assert_eq!(tricube_weight(-0.7), tricube_weight(0.7));
assert_eq!(tricube_weight(-0.5), tricube_weight(0.5));
}
#[test]
fn test_tricube_weight_range() {
for i in 0..=100 {
let u = i as f64 / 100.0; let w = tricube_weight(u);
assert!(w >= 0.0 && w <= 1.0, "Weight at {} = {} is out of [0,1]", u, w);
}
}
#[test]
fn test_tricube_weight_monotonic() {
let mut prev_weight = tricube_weight(0.0);
for i in 1..=100 {
let u = i as f64 / 100.0;
let weight = tricube_weight(u);
assert!(
weight <= prev_weight,
"Weight at {} = {} should be <= {}",
u,
weight,
prev_weight
);
prev_weight = weight;
}
}
#[test]
fn test_tricube_weight_with_bounds() {
assert_eq!(tricube_weight_with_bounds(0.0, 1.0), 1.0);
let h = 1.0;
let inner_boundary = INNER_BOUNDARY_FACTOR * h;
let r = inner_boundary * 1.1; let w = tricube_weight_with_bounds(r, h);
assert!(w > 0.0 && w < 1.0);
let outer_boundary = OUTER_BOUNDARY_FACTOR * h;
let r = outer_boundary * 0.9; let w = tricube_weight_with_bounds(r, h);
assert!(w > 0.0 && w < 1.0);
let r = outer_boundary * 1.1; let w = tricube_weight_with_bounds(r, h);
assert_eq!(w, 0.0);
let w = tricube_weight_with_bounds(0.5, 0.0);
assert_eq!(w, 1.0);
}
}