use super::fundamental_args::{IERS2010FundamentalArgs, MHB2000FundamentalArgs};
use super::lunisolar_terms::LUNISOLAR_TERMS;
use super::planetary_terms::PLANETARY_TERMS;
use super::types::NutationResult;
use crate::constants::{MICROARCSEC_TO_RAD, TWOPI};
use crate::errors::AstroResult;
use crate::math::fmod;
#[derive(Debug, Clone, Copy)]
pub struct NutationIAU2000A;
impl Default for NutationIAU2000A {
fn default() -> Self {
Self::new()
}
}
impl NutationIAU2000A {
pub fn new() -> Self {
Self
}
pub fn compute(&self, jd1: f64, jd2: f64) -> AstroResult<NutationResult> {
let t = crate::utils::jd_to_centuries(jd1, jd2);
let lunisolar_args = [
t.moon_mean_anomaly(),
t.sun_mean_anomaly_mhb(),
t.mean_argument_of_latitude(),
t.mean_elongation_mhb(),
t.moon_ascending_node_longitude(),
];
let (delta_psi_ls, delta_eps_ls) = self.compute_lunisolar(&lunisolar_args, t);
let (delta_psi_planetary, delta_eps_planetary) = self.compute_planetary(t);
Ok(NutationResult {
delta_psi: delta_psi_planetary + delta_psi_ls,
delta_eps: delta_eps_planetary + delta_eps_ls,
})
}
pub fn compute_lunisolar(&self, args: &[f64; 5], t: f64) -> (f64, f64) {
let mut dpsi = 0.0;
let mut deps = 0.0;
for term in LUNISOLAR_TERMS.iter().rev() {
let arg = fmod(
(term.0 as f64) * args[0]
+ (term.1 as f64) * args[1]
+ (term.2 as f64) * args[2]
+ (term.3 as f64) * args[3]
+ (term.4 as f64) * args[4],
TWOPI,
);
let (sarg, carg) = libm::sincos(arg);
dpsi += (term.5 + term.6 * t) * sarg + term.7 * carg;
deps += (term.8 + term.9 * t) * carg + term.10 * sarg;
}
(dpsi * MICROARCSEC_TO_RAD, deps * MICROARCSEC_TO_RAD)
}
pub fn compute_planetary(&self, t: f64) -> (f64, f64) {
let al = fmod(2.35555598 + 8328.6914269554 * t, TWOPI);
let af = fmod(1.627905234 + 8433.466158131 * t, TWOPI);
let ad = fmod(5.198466741 + 7771.3771468121 * t, TWOPI);
let aom = fmod(2.18243920 - 33.757045 * t, TWOPI);
let apa = t.precession();
let alme = t.mercury_lng();
let alve = t.venus_lng();
let alea = t.earth_lng();
let alma = t.mars_lng();
let alju = t.jupiter_lng();
let alsa = t.saturn_lng();
let alur = t.uranus_lng();
let alne = t.neptune_longitude_mhb();
let mut dpsi = 0.0;
let mut deps = 0.0;
for &(nl, nf, nd, nom, nme, nve, nea, nma, nju, nsa, nur, nne, npa, sp, cp, se, ce) in
PLANETARY_TERMS.iter().rev()
{
let arg = fmod(
(nl as f64) * al
+ (nf as f64) * af
+ (nd as f64) * ad
+ (nom as f64) * aom
+ (nme as f64) * alme
+ (nve as f64) * alve
+ (nea as f64) * alea
+ (nma as f64) * alma
+ (nju as f64) * alju
+ (nsa as f64) * alsa
+ (nur as f64) * alur
+ (nne as f64) * alne
+ (npa as f64) * apa,
TWOPI,
);
let (sarg, carg) = libm::sincos(arg);
dpsi += (sp as f64) * sarg + (cp as f64) * carg;
deps += (se as f64) * sarg + (ce as f64) * carg;
}
(dpsi * MICROARCSEC_TO_RAD, deps * MICROARCSEC_TO_RAD)
}
}