pub fn nspline(rbkg: f64, kmin: f64, kmax: f64) -> usize {
let x = 2.0 * rbkg * (kmax - kmin) / std::f64::consts::PI;
1 + round_half_even(x) as usize
}
fn round_half_even(x: f64) -> f64 {
let lower = x.floor();
let frac = x - lower;
if frac < 0.5 {
lower
} else if frac > 0.5 {
lower + 1.0
} else if (lower as i64) % 2 == 0 {
lower
} else {
lower + 1.0
}
}
pub fn bkg_knots(kmin: f64, kmax: f64, nspline: usize) -> Vec<f64> {
let step = (kmax - kmin) / (nspline - 1) as f64;
let kk: Vec<f64> = (0..nspline).map(|i| kmin + i as f64 * step).collect();
let mut t = Vec::with_capacity(nspline + 4);
for _ in 0..4 {
t.push(kmin);
}
t.extend_from_slice(&kk[2..nspline - 2]);
for _ in 0..4 {
t.push(kmax);
}
t
}
fn fpbspl(t: &[f64], k: usize, x: f64, l: usize, h: &mut [f64]) {
let tt = |i: usize| t[i - 1];
let mut hh = [0.0f64; 19]; h[0] = 1.0;
for j in 1..=k {
hh[..j].copy_from_slice(&h[..j]);
h[0] = 0.0;
for i in 1..=j {
let li = l + i;
let lj = li - j;
if tt(li) == tt(lj) {
h[i] = 0.0;
} else {
let f = hh[i - 1] / (tt(li) - tt(lj));
h[i - 1] += f * (tt(li) - x);
h[i] = f * (x - tt(lj));
}
}
}
}
pub fn splev(t: &[f64], c: &[f64], k: usize, x: &[f64]) -> Vec<f64> {
let n = t.len();
let k1 = k + 1;
let nk1 = n - k1; let tt = |i: usize| t[i - 1];
let cc = |i: usize| c[i - 1];
let mut h = [0.0f64; 20];
let mut out = Vec::with_capacity(x.len());
for &arg in x {
let mut l = k1;
while l < nk1 && arg >= tt(l + 1) {
l += 1;
}
fpbspl(t, k, arg, l, &mut h);
let mut sp = 0.0;
let mut ll = l - k1;
for j in 1..=k1 {
ll += 1;
sp += cc(ll) * h[j - 1];
}
out.push(sp);
}
out
}