//! 二分查找子程序。 //! //! 重构自 SYNSPEC `locate.f` //! //! 在有序数组 `xx` 中查找值 `x` 的位置,使得 `xx[j] <= x < xx[j+1]`。 /// 在有序数组中二分查找。 /// /// 查找 `x` 在有序数组 `xx[0..n]` 中的插入位置。 /// 返回索引 `j`,使得 `xx[j-1] <= x < xx[j]`(1-indexed)。 /// /// # 参数 /// /// * `xx` - 有序数组(升序或降序) /// * `n` - 数组有效长度 /// * `x` - 待查找的值 /// /// # 返回值 /// /// 索引 `j`(1-indexed),使得 `xx[j-1] <= x < xx[j]` pub fn locate(xx: &[f64], n: usize, x: f64) -> usize { let mut jl: isize = 0; let mut ju = (n + 1) as isize; while ju - jl > 1 { let jm = (ju + jl) / 2; if (xx[n - 1] >= xx[0]) == (x >= xx[jm as usize - 1]) { jl = jm; } else { ju = jm; } } if x == xx[0] { 1 } else if x == xx[n - 1] { n - 1 } else { jl as usize } } #[cfg(test)] mod tests { use super::*; #[test] fn test_locate_basic() { let xx = [1.0, 2.0, 3.0, 4.0, 5.0]; // x=2.5 应该在 xx[1] 和 xx[2] 之间,返回 j=2 let j = locate(&xx, 5, 2.5); assert!(j >= 1 && j <= 4); assert!(xx[j - 1] <= 2.5 && xx[j] >= 2.5); } #[test] fn test_locate_exact_first() { let xx = [1.0, 2.0, 3.0, 4.0, 5.0]; let j = locate(&xx, 5, 1.0); assert_eq!(j, 1); } #[test] fn test_locate_exact_last() { let xx = [1.0, 2.0, 3.0, 4.0, 5.0]; let j = locate(&xx, 5, 5.0); assert_eq!(j, 4); } #[test] fn test_locate_between() { let xx = [0.0, 10.0, 20.0, 30.0]; let j = locate(&xx, 4, 15.0); assert!(j >= 1 && j <= 3); assert!(xx[j - 1] <= 15.0 && xx[j] >= 15.0); } }