use crate::astro::era::earth_rotation_angle;
use crate::qtty::*;
use crate::time::JulianDate;
pub use crate::qtty::time::SIDEREAL_DAY;
#[inline]
pub fn gmst_iau2006(jd_ut1: JulianDate, jd_tt: JulianDate) -> Radians {
let era = earth_rotation_angle(jd_ut1);
let t = (jd_tt.raw().value() - 2_451_545.0_f64) / 36_525.0_f64;
let poly_as = 0.014_506 + 4_612.156_534 * t + 1.391_581_7 * t.powi(2)
- 0.000_000_44 * t.powi(3)
- 0.000_029_956 * t.powi(4)
- 0.000_000_036_8 * t.powi(5);
let gmst = era + Arcseconds::new(poly_as).to::<Radian>();
gmst.wrap_pos()
}
#[inline]
pub fn gast_iau2006(
jd_ut1: JulianDate,
jd_tt: JulianDate,
dpsi: Radians,
mean_obliquity: Radians,
) -> Radians {
let gmst = gmst_iau2006(jd_ut1, jd_tt);
let ee = crate::astro::era::equation_of_the_equinoxes_iau2000(jd_tt, dpsi, mean_obliquity);
(gmst + ee).wrap_pos()
}
#[inline]
pub fn gast_iau2006a(jd_ut1: JulianDate, jd_tt: JulianDate) -> Radians {
let nut = crate::astro::nutation::nutation_iau2000b(jd_tt);
gast_iau2006(jd_ut1, jd_tt, nut.dpsi, nut.mean_obliquity)
}
#[cfg(test)]
mod tests {
use super::*;
use std::f64::consts::TAU;
#[test]
fn gmst_iau2006_at_j2000() {
let jd = crate::J2000;
let gmst = gmst_iau2006(jd, jd);
let gmst_deg = gmst.to::<Degree>();
assert!(
(gmst_deg.value() - 280.46_f64).abs() < 0.1,
"GMST at J2000 = {}°, expected ≈ 280.46°",
gmst_deg
);
}
#[test]
fn gmst_iau2006_range() {
for jd in [2_451_545.0, 2_460_000.5, 2_440_000.0] {
let jd = crate::time::JulianDate::new(jd);
let gmst = gmst_iau2006(jd, jd);
assert!(gmst >= Radians::new(0.0), "GMST should be ≥ 0");
assert!(gmst < Radians::new(TAU), "GMST should be < 2π");
}
}
#[test]
fn gast_iau2006_close_to_gmst() {
let jd = crate::time::JulianDate::new(2_460_000.5);
let nutation = crate::astro::nutation::nutation_iau2000b(jd);
let gast = gast_iau2006(jd, jd, nutation.dpsi, nutation.mean_obliquity);
let gmst = gmst_iau2006(jd, jd);
let diff_as = (gast - gmst).value().abs() * 206_264.806;
assert!(
diff_as < 20.0,
"GAST–GMST = {:.3}″, max nutation effect should be < 20″",
diff_as
);
}
#[test]
fn gast_iau2006_matches_sofa_gst06a_reference() {
use crate::astro::nutation::{Iau2006A, NutationModel};
let jd = crate::time::JulianDate::new(2_453_736.5);
let nut = <Iau2006A as NutationModel>::nutation(jd);
let gast = gast_iau2006(jd, jd, nut.dpsi, nut.mean_obliquity);
let sofa = 1.754_166_137_675_019_2_f64;
assert!(
(gast.value() - sofa).abs() < 1e-12,
"GAST = {:.16e}, SOFA gst06a = {:.16e}",
gast.value(),
sofa
);
}
#[test]
fn gast_iau2006a_matches_low_level_gast() {
let jd = crate::time::JulianDate::new(2_460_000.5);
let nut = crate::astro::nutation::nutation_iau2000b(jd);
let low = gast_iau2006(jd, jd, nut.dpsi, nut.mean_obliquity);
let high = gast_iau2006a(jd, jd);
assert!((low.value() - high.value()).abs() < 1.0e-15);
}
}