use crate::tables::hyperbolic::needs_repeat;
use crate::tables::{ATAN_TABLE, ATANH_TABLE};
use crate::traits::CordicNumber;
#[inline]
const fn table_lookup(table: &[i64; 64], index: u32) -> i64 {
#[allow(
clippy::indexing_slicing,
reason = "index bounded by CORDIC iteration limits"
)]
table[index as usize]
}
#[must_use]
pub fn circular_vectoring<T: CordicNumber>(mut x: T, mut y: T, mut z: T) -> (T, T, T) {
let zero = T::zero();
let iterations = T::frac_bits().min(62);
for i in 0..iterations {
let angle = T::from_i1f63(table_lookup(&ATAN_TABLE, i));
if y < zero {
let x_new = x.saturating_sub(y >> i);
y = y.saturating_add(x >> i);
x = x_new;
z -= angle;
} else {
let x_new = x.saturating_add(y >> i);
y = y.saturating_sub(x >> i);
x = x_new;
z += angle;
}
}
(x, y, z)
}
#[must_use]
pub fn hyperbolic_vectoring<T: CordicNumber>(mut x: T, mut y: T, mut z: T) -> (T, T, T) {
let zero = T::zero();
let max_iterations = T::frac_bits().clamp(24, 54);
let mut i: u32 = 1;
let mut iteration_count: u32 = 0;
let mut repeated = false;
while iteration_count < max_iterations && i < 64 {
let table_index = i.saturating_sub(1);
let angle = T::from_i1f63(table_lookup(&ATANH_TABLE, table_index));
if y < zero {
let x_new = x.saturating_add(y >> i);
y = y.saturating_add(x >> i);
x = x_new;
z -= angle;
} else {
let x_new = x.saturating_sub(y >> i);
y = y.saturating_sub(x >> i);
x = x_new;
z += angle;
}
iteration_count += 1;
if needs_repeat(i) && !repeated {
repeated = true;
} else {
repeated = false;
i += 1;
}
}
(x, y, z)
}