#![allow(clippy::inconsistent_digit_grouping)]
#![allow(clippy::excessive_precision)]
use core::f64::consts::TAU;
use super::{DAS2R, Rad, TURNAS};
#[derive(Debug)]
pub struct FundamentalArguments {
pub l: Rad,
pub l_prime: Rad,
pub f: Rad,
pub d: Rad,
pub omega: Rad,
pub l_me: Rad,
pub l_ve: Rad,
pub l_e: Rad,
pub l_ma: Rad,
pub l_j: Rad,
pub l_sa: Rad,
pub l_u: Rad,
pub l_ne: Rad,
pub p_a: Rad,
}
impl FundamentalArguments {
pub fn evaluate(t: f64) -> Self {
Self {
l: fa_l(t),
l_prime: fa_l_prime(t),
f: fa_f(t),
d: fa_d(t),
omega: fa_omega(t),
l_me: fa_l_me(t),
l_ve: fa_l_ve(t),
l_e: fa_l_e(t),
l_ma: fa_l_ma(t),
l_j: fa_l_j(t),
l_sa: fa_l_sa(t),
l_u: fa_l_u(t),
l_ne: fa_l_ne(t),
p_a: fa_p_a(t),
}
}
}
#[inline]
fn horner5(t: f64, c0: f64, c1: f64, c2: f64, c3: f64, c4: f64) -> f64 {
c0 + t * (c1 + t * (c2 + t * (c3 + t * c4)))
}
#[inline]
fn arcsec_mod_turn_to_rad(arcsec: f64) -> Rad {
Rad::new((arcsec % TURNAS) * DAS2R)
}
pub fn fa_l(t: f64) -> Rad {
let a = horner5(
t,
485868.249036,
1717915923.2178,
31.8792,
0.051635,
-0.00024470,
);
arcsec_mod_turn_to_rad(a)
}
pub fn fa_l_prime(t: f64) -> Rad {
let a = horner5(
t,
1287104.793048,
129596581.0481,
-0.5532,
0.000136,
-0.00001149,
);
arcsec_mod_turn_to_rad(a)
}
pub fn fa_f(t: f64) -> Rad {
let a = horner5(
t,
335779.526232,
1739527262.8478,
-12.7512,
-0.001037,
0.00000417,
);
arcsec_mod_turn_to_rad(a)
}
pub fn fa_d(t: f64) -> Rad {
let a = horner5(
t,
1072260.703692,
1602961601.2090,
-6.3706,
0.006593,
-0.00003169,
);
arcsec_mod_turn_to_rad(a)
}
pub fn fa_omega(t: f64) -> Rad {
let a = horner5(
t,
450160.398036,
-6962890.5431,
7.4722,
0.007702,
-0.00005939,
);
arcsec_mod_turn_to_rad(a)
}
pub fn fa_l_me(t: f64) -> Rad {
Rad::new((4.402608842 + 2608.7903141574 * t) % TAU)
}
pub fn fa_l_ve(t: f64) -> Rad {
Rad::new((3.176146697 + 1021.3285546211 * t) % TAU)
}
pub fn fa_l_e(t: f64) -> Rad {
Rad::new((1.753470314 + 628.3075849991 * t) % TAU)
}
pub fn fa_l_ma(t: f64) -> Rad {
Rad::new((6.203480913 + 334.0612426700 * t) % TAU)
}
pub fn fa_l_j(t: f64) -> Rad {
Rad::new((0.599546497 + 52.9690962641 * t) % TAU)
}
pub fn fa_l_sa(t: f64) -> Rad {
Rad::new((0.874016757 + 21.3299104960 * t) % TAU)
}
pub fn fa_l_u(t: f64) -> Rad {
Rad::new((5.481293872 + 7.4781598567 * t) % TAU)
}
pub fn fa_l_ne(t: f64) -> Rad {
Rad::new((5.311886287 + 3.8133035638 * t) % TAU)
}
pub fn fa_p_a(t: f64) -> Rad {
Rad::new(0.02438175 * t + 0.00000538691 * t * t)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn all_evaluators_return_finite_across_wide_t_range() {
for &t in &[-10.0, -1.0, -0.5, -0.1, 0.0, 0.1, 0.5, 1.0, 10.0] {
let fa = FundamentalArguments::evaluate(t);
for (name, value) in [
("l", fa.l),
("l_prime", fa.l_prime),
("f", fa.f),
("d", fa.d),
("omega", fa.omega),
("l_me", fa.l_me),
("l_ve", fa.l_ve),
("l_e", fa.l_e),
("l_ma", fa.l_ma),
("l_j", fa.l_j),
("l_sa", fa.l_sa),
("l_u", fa.l_u),
("l_ne", fa.l_ne),
("p_a", fa.p_a),
] {
assert!(
value.is_finite(),
"{name} at t={t} was non-finite: {value:?}"
);
}
}
}
#[test]
fn reduced_arguments_stay_within_one_turn() {
for &t in &[-10.0, -1.0, 0.0, 1.0, 10.0] {
let fa = FundamentalArguments::evaluate(t);
for (name, value) in [
("l", fa.l),
("l_prime", fa.l_prime),
("f", fa.f),
("d", fa.d),
("omega", fa.omega),
("l_me", fa.l_me),
("l_ve", fa.l_ve),
("l_e", fa.l_e),
("l_ma", fa.l_ma),
("l_j", fa.l_j),
("l_sa", fa.l_sa),
("l_u", fa.l_u),
("l_ne", fa.l_ne),
] {
assert!(
value.raw().abs() < TAU,
"{name} at t={t} exceeded 2π: {value:?}"
);
}
}
}
#[test]
fn evaluate_dispatches_each_field_to_its_evaluator() {
let t = 0.1234;
let fa = FundamentalArguments::evaluate(t);
assert_eq!(fa.l.raw(), fa_l(t).raw());
assert_eq!(fa.l_prime.raw(), fa_l_prime(t).raw());
assert_eq!(fa.f.raw(), fa_f(t).raw());
assert_eq!(fa.d.raw(), fa_d(t).raw());
assert_eq!(fa.omega.raw(), fa_omega(t).raw());
assert_eq!(fa.l_me.raw(), fa_l_me(t).raw());
assert_eq!(fa.l_ve.raw(), fa_l_ve(t).raw());
assert_eq!(fa.l_e.raw(), fa_l_e(t).raw());
assert_eq!(fa.l_ma.raw(), fa_l_ma(t).raw());
assert_eq!(fa.l_j.raw(), fa_l_j(t).raw());
assert_eq!(fa.l_sa.raw(), fa_l_sa(t).raw());
assert_eq!(fa.l_u.raw(), fa_l_u(t).raw());
assert_eq!(fa.l_ne.raw(), fa_l_ne(t).raw());
assert_eq!(fa.p_a.raw(), fa_p_a(t).raw());
}
}