Skip to main content

px_native/cipher/
remap.rs

1//! `vM(t, n, e, r, g)` — linear remap from `[n, e]` to `[r, g]`,
2//! `Math.floor`-rounded. JS reference:
3//!
4//! ```text
5//! function vM(t, n, e, r, g) {
6//!   return Math.floor((t - n) / (e - n) * (g - r) + r);
7//! }
8//! ```
9//!
10//! All call sites we observe pass non-negative integers and `n < e`,
11//! so the integer-cast path is exact; we still go through `f64` to
12//! match JS rounding when intermediate products overflow u32.
13
14#[inline]
15pub fn v_m(t: i64, n: i64, e: i64, r: i64, g: i64) -> i64 {
16    let denom = (e - n) as f64;
17    let numer = (t - n) as f64;
18    let scale = (g - r) as f64;
19    let bias = r as f64;
20    (numer / denom * scale + bias).floor() as i64
21}
22
23#[cfg(test)]
24mod tests {
25    use super::*;
26
27    #[test]
28    fn remap_midpoint() {
29        assert_eq!(v_m(50, 0, 100, 0, 10), 5);
30    }
31
32    #[test]
33    fn remap_zero_zero() {
34        assert_eq!(v_m(0, 0, 1, 0, 1), 0);
35    }
36}