use vedaksha_math::angle::{deg_to_rad, normalize_degrees, rad_to_deg};
use super::{HouseCusps, HouseSystem};
fn ra_to_longitude(ra_deg: f64, eps_deg: f64) -> f64 {
let ra = deg_to_rad(ra_deg);
let eps = deg_to_rad(eps_deg);
normalize_degrees(rad_to_deg(libm::atan2(
libm::sin(ra) * libm::cos(eps),
libm::cos(ra),
)))
}
#[allow(clippy::cast_precision_loss)]
pub(super) fn compute(ramc: f64, latitude: f64, obliquity: f64) -> HouseCusps {
let (asc, mc) = super::compute_asc_mc(ramc, latitude, obliquity);
let cusps = core::array::from_fn(|i| {
let equator_ra = normalize_degrees(ramc + ((i as f64) - 9.0) * 30.0);
ra_to_longitude(equator_ra, obliquity)
});
HouseCusps {
cusps,
asc,
mc,
system: HouseSystem::Morinus,
polar_fallback: false,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn cusp10_near_mc() {
let result = compute(30.0, 45.0, 23.44);
let diff = normalize_degrees(result.cusps[9] - result.mc);
assert!(
diff < 6.0 || diff > 354.0,
"cusp10={} mc={}",
result.cusps[9],
result.mc
);
}
#[test]
fn latitude_independent_cusps() {
let r1 = compute(60.0, 0.0, 23.44);
let r2 = compute(60.0, 50.0, 23.44);
for i in 0..12 {
assert!(
(r1.cusps[i] - r2.cusps[i]).abs() < 1e-10,
"cusp {i}: {} vs {}",
r1.cusps[i],
r2.cusps[i]
);
}
}
#[test]
fn all_cusps_in_range() {
let result = compute(200.0, 30.0, 23.44);
for (i, &c) in result.cusps.iter().enumerate() {
assert!((0.0..360.0).contains(&c), "cusp {i}: {c}");
}
}
#[test]
fn system_tag() {
let result = compute(0.0, 0.0, 23.44);
assert_eq!(result.system, HouseSystem::Morinus);
}
}