新增 TLUSTY 模块: - crossd: 光电离截面评估 (bound-free cross section) - sgmer0: 合并能级光电离截面初始化 - sgmerd: 合并能级光电离截面计算 - dwnfr0: 频率网格下载 (continuum) - convc1: 对流收敛控制 (radiative) - chckse: 统计平衡检查 (rates) 扩展 RESOLV 编排器: - 添加 Feautrier 形式解 - 添加 Lucy 温度修正 - 添加 ROSSTD/PZEVAL/CONOUT 调用 - 添加 IFPOPR=2 占据数更新 - 添加 HESOL6 流体静力平衡修正 修复: - sgmer0.rs: 修复 config 未声明为 mut 的编译错误 - crossd.rs: 修复测试中使用错误字段路径的问题 (frqall.ijbf/phoexp.aijbf/phoexp.bfcs 而非 obfpar) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
78 lines
1.8 KiB
Rust
78 lines
1.8 KiB
Rust
//! 二分查找子程序。
|
||
//!
|
||
//! 重构自 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);
|
||
}
|
||
}
|