pcb_toolkit/tables/
interpolate.rs1pub fn lerp(table: &[(f64, f64)], x: f64) -> f64 {
13 assert!(!table.is_empty(), "interpolation table must not be empty");
14
15 if table.len() == 1 || x <= table[0].0 {
16 return table[0].1;
17 }
18 if x >= table[table.len() - 1].0 {
19 return table[table.len() - 1].1;
20 }
21
22 let i = match table.binary_search_by(|entry| entry.0.partial_cmp(&x).unwrap()) {
24 Ok(i) => return table[i].1, Err(i) => i - 1,
26 };
27
28 let (x0, y0) = table[i];
29 let (x1, y1) = table[i + 1];
30 let t = (x - x0) / (x1 - x0);
31 y0 + t * (y1 - y0)
32}
33
34#[cfg(test)]
35mod tests {
36 use super::*;
37
38 #[test]
39 fn exact_match() {
40 let table = &[(1.0, 10.0), (2.0, 20.0), (3.0, 30.0)];
41 assert!((lerp(table, 2.0) - 20.0).abs() < 1e-10);
42 }
43
44 #[test]
45 fn midpoint_interpolation() {
46 let table = &[(0.0, 0.0), (10.0, 100.0)];
47 assert!((lerp(table, 5.0) - 50.0).abs() < 1e-10);
48 }
49
50 #[test]
51 fn clamp_below() {
52 let table = &[(1.0, 10.0), (2.0, 20.0)];
53 assert!((lerp(table, -5.0) - 10.0).abs() < 1e-10);
54 }
55
56 #[test]
57 fn clamp_above() {
58 let table = &[(1.0, 10.0), (2.0, 20.0)];
59 assert!((lerp(table, 99.0) - 20.0).abs() < 1e-10);
60 }
61}