#![allow(non_snake_case)]
#![allow(clippy::excessive_precision)]
use erfa::{
aliases::{
eraAnp, eraC2s, eraEpj, eraEpj2jd, eraEpv00, eraGmst06, eraP06e, eraPdp, eraPmat06, eraPn,
eraPnm06a, eraRx, eraRxp, eraRxpv, eraRxr, eraRz, eraS2c,
},
constants::{ERFA_AULT, ERFA_DAYSEC, ERFA_DJM0},
};
pub fn palGmst(ut1: f64) -> f64 {
eraGmst06(ERFA_DJM0, ut1, ERFA_DJM0, ut1)
}
pub unsafe fn palDcs2c(a: f64, b: f64, v: *mut f64) {
let v2 = eraS2c(a, b);
let v = std::slice::from_raw_parts_mut(v, 3);
v.iter_mut().zip(v2).for_each(|(v, v2)| *v = v2);
}
pub unsafe fn palDcc2s(v: *mut f64, a: &mut f64, b: &mut f64) {
let v = std::slice::from_raw_parts(v, 3).try_into().unwrap();
let (a2, b2) = eraC2s(v);
*a = a2;
*b = b2;
}
pub fn palDranrm(angle: f64) -> f64 {
eraAnp(angle)
}
pub unsafe fn palDvn(v: *mut f64, uv: *mut f64, vm: *mut f64) {
let v = std::slice::from_raw_parts(v, 3).try_into().unwrap();
let uv = std::slice::from_raw_parts_mut(uv, 3);
let (m, uv2) = eraPn(v);
*vm = m;
uv.iter_mut().zip(uv2).for_each(|(uv, uv2)| *uv = uv2);
}
pub unsafe fn palDvdv(va: *mut f64, vb: *mut f64) -> f64 {
let va: [f64; 3] = std::slice::from_raw_parts(va, 3).try_into().unwrap();
let vb: [f64; 3] = std::slice::from_raw_parts(vb, 3).try_into().unwrap();
eraPdp(va, vb)
}
pub unsafe fn palDmxv(dm: *mut [f64; 3], va: *mut f64, vb: *mut f64) {
let dm: [[f64; 3]; 3] = std::slice::from_raw_parts(dm, 3).try_into().unwrap();
let va: [f64; 3] = std::slice::from_raw_parts(va, 3).try_into().unwrap();
let vb = std::slice::from_raw_parts_mut(vb, 3);
let vb2 = eraRxp(dm, va);
vb.iter_mut().zip(vb2).for_each(|(vb, vb2)| *vb = vb2);
}
pub unsafe fn palEvp(
date: f64,
deqx: f64,
dvb: *mut f64,
dpb: *mut f64,
dvh: *mut f64,
dph: *mut f64,
) {
let (_, mut pvh, mut pvb) = eraEpv00(2400000.5, date);
if deqx > 0.0 {
let (d1, d2) = eraEpj2jd(deqx);
let r = eraPmat06(d1, d2);
let pvh2 = eraRxpv(r, pvh);
pvh = pvh2;
let pvb2 = eraRxpv(r, pvb);
pvb = pvb2;
}
let dvb = std::slice::from_raw_parts_mut(dvb, 3);
let dpb = std::slice::from_raw_parts_mut(dpb, 3);
let dvh = std::slice::from_raw_parts_mut(dvh, 3);
let dph = std::slice::from_raw_parts_mut(dph, 3);
for i in 0..3 {
dvh[i] = pvh[1][i] / ERFA_DAYSEC;
dvb[i] = pvb[1][i] / ERFA_DAYSEC;
dph[i] = pvh[0][i];
dpb[i] = pvb[0][i];
}
}
pub unsafe fn palPrenut(epoch: f64, date: f64, rmatpn: *mut [f64; 3]) {
let (d1, d2) = eraEpj2jd(epoch);
let (eps0, psia, oma, _, _, _, _, _, chia, _, _, _, _, _, _, _) = eraP06e(d1, d2);
let mut r1 = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]];
eraRz(-chia, &mut r1);
eraRx(oma, &mut r1);
eraRz(psia, &mut r1);
eraRx(-eps0, &mut r1);
let r2 = eraPnm06a(ERFA_DJM0, date);
let rmatpn2 = eraRxr(r2, r1);
let rmatpn = std::slice::from_raw_parts_mut(rmatpn, 3);
rmatpn[0][0] = rmatpn2[0][0];
rmatpn[0][1] = rmatpn2[0][1];
rmatpn[0][2] = rmatpn2[0][2];
rmatpn[1][0] = rmatpn2[1][0];
rmatpn[1][1] = rmatpn2[1][1];
rmatpn[1][2] = rmatpn2[1][2];
rmatpn[2][0] = rmatpn2[2][0];
rmatpn[2][1] = rmatpn2[2][1];
rmatpn[2][2] = rmatpn2[2][2];
}
pub unsafe fn palMappa(eq: f64, date: f64, amprms: *mut f64) {
let gr2: f64 = 2.0 * 9.87063e-9;
let mut ebd = [0.0; 3];
let mut ehd = [0.0; 3];
let mut eh = [0.0; 3];
let amprms = std::slice::from_raw_parts_mut(amprms, 21);
amprms.fill(0.0);
amprms[0] = eraEpj(ERFA_DJM0, date) - eq;
palEvp(
date,
eq,
ebd.as_mut_ptr(),
&mut amprms[1],
ehd.as_mut_ptr(),
eh.as_mut_ptr(),
);
let (e, amprms_from_4) = eraPn(eh);
amprms[4] = amprms_from_4[0];
amprms[5] = amprms_from_4[1];
amprms[6] = amprms_from_4[2];
amprms[7] = gr2 / e;
for i in 0..3 {
amprms[i + 8] = ebd[i] * ERFA_AULT;
}
let (vm, _) = eraPn(amprms[8..11].try_into().unwrap());
amprms[11] = (1.0 - vm * vm).sqrt();
palPrenut(eq, date, amprms.as_mut_ptr().add(12) as _);
}
#[cfg(test)]
mod tests {
use super::*;
use crate::ndarray::prelude::*;
use approx::assert_abs_diff_eq;
#[test]
fn gmst() {
assert_abs_diff_eq!(palGmst(53736.), 1.754174971870091203, epsilon = 1e-12);
}
#[test]
fn vecmat() {
let mut dv1 = [0_f64; 3];
let mut dv2 = [0_f64; 3];
let mut dv3 = [0_f64; 3];
let mut dv5 = [0.006889040510209034, -1.577473205461961, 0.5201843672856759];
let mut dv6 = [0_f64; 3];
let mut dvm = 0_f64;
let mut drm1: [[f64; 3]; 3] = [
[0.9930075842721269, 0.05902743090199868, -0.1022335560329612],
[
-0.07113807138648245,
0.9903204657727545,
-0.1191836812279541,
],
[0.09420887631983825, 0.1256229973879967, 0.9875948309655174],
];
let mut drm2: [[f64; 3]; 3] = [
[-0.1681574770810878, 0.1981362273264315, 0.9656423242187410],
[-0.2285369373983370, 0.9450659587140423, -0.2337117924378156],
[
-0.9589024617479674,
-0.2599853247796050,
-0.1136384607117296,
],
];
unsafe { palDcs2c(3.0123, -0.999, dv1.as_mut_ptr()) };
assert_abs_diff_eq!(dv1[0], -0.5366267667260525, epsilon = 1e-12);
assert_abs_diff_eq!(dv1[1], 0.06977111097651444, epsilon = 1e-12);
assert_abs_diff_eq!(dv1[2], -0.8409302618566215, epsilon = 1e-12);
unsafe { palDmxv(drm1.as_mut_ptr(), dv1.as_mut_ptr(), dv2.as_mut_ptr()) };
unsafe { palDmxv(drm2.as_mut_ptr(), dv2.as_mut_ptr(), dv3.as_mut_ptr()) };
assert_abs_diff_eq!(dv3[0], -0.7267487768696160, epsilon = 1e-10);
assert_abs_diff_eq!(dv3[1], 0.5011537352639822, epsilon = 1e-12);
assert_abs_diff_eq!(dv3[2], 0.4697671220397141, epsilon = 1e-12);
dv5.iter_mut().for_each(|x| *x *= 1000.0);
unsafe { palDvn(dv5.as_mut_ptr(), dv6.as_mut_ptr(), &mut dvm) };
assert_abs_diff_eq!(dv6[0], 0.004147420704640065, epsilon = 1e-12);
assert_abs_diff_eq!(dv6[1], -0.9496888606842218, epsilon = 1e-12);
assert_abs_diff_eq!(dv6[2], 0.3131674740355448, epsilon = 1e-12);
assert_abs_diff_eq!(dvm, 1661.042127339937, epsilon = 1e-9);
}
#[test]
fn dcc2s() {
let mut dv = [100_f64, -50_f64, 25_f64];
let mut da = 0_f64;
let mut db = 0_f64;
unsafe { palDcc2s(dv.as_mut_ptr(), &mut da, &mut db) };
assert_abs_diff_eq!(da, -0.4636476090008061, epsilon = 1e-12);
assert_abs_diff_eq!(db, 0.2199879773954594, epsilon = 1e-12);
}
#[test]
fn dranrm() {
assert_abs_diff_eq!(palDranrm(-0.1), 6.183185307179587, epsilon = 1e-12);
}
#[test]
fn evp() {
let mut dvb = Array1::zeros(3);
let mut dpb = Array1::zeros(3);
let mut dvh = Array1::zeros(3);
let mut dph = Array1::zeros(3);
let vbex = array![
1.6957348127008098514e-07,
-9.1093446116039685966e-08,
-3.9528532243991863036e-08,
];
let pbex = array![
-0.49771075259730546136,
-0.80273812396332311359,
-0.34851593942866060383,
];
let vhex = array![
1.6964379181455713805e-07,
-9.1147224045727438391e-08,
-3.9553158272334222497e-08,
];
let phex = array![
-0.50169124421419830639,
-0.80650980174901798492,
-0.34997162028527262212,
];
unsafe {
palEvp(
2010.0,
2012.0,
dvb.as_mut_ptr(),
dpb.as_mut_ptr(),
dvh.as_mut_ptr(),
dph.as_mut_ptr(),
);
};
assert_abs_diff_eq!(dvb, vbex, epsilon = 1e-12);
assert_abs_diff_eq!(dpb, pbex, epsilon = 1e-12);
assert_abs_diff_eq!(dvh, vhex, epsilon = 1e-12);
assert_abs_diff_eq!(dph, phex, epsilon = 1e-12);
}
#[test]
fn prenut() {
}
#[test]
fn mappa() {
let mut amprms = Array1::zeros(21);
let expected = array![
1.9986310746064646082_f64,
-0.1728200754134739392,
0.88745394651412767839,
0.38472374350184274094,
-0.17245634725219796679,
0.90374808622520386159,
0.3917884696321610738,
2.0075929387510784968e-08,
-9.9464149073251757597e-05,
-1.6125306981057062306e-05,
-6.9897255793245634435e-06,
0.99999999489900059935,
0.99999983777998024959,
-0.00052248206600935195865,
-0.00022683144398381763045,
0.00052248547063364874764,
0.99999986339269864022,
1.4950491424992534218e-05,
0.00022682360163333854623,
-1.5069005133483779417e-05,
0.99999997416198904698,
];
unsafe { palMappa(2010.0, 55927.0, amprms.as_mut_ptr()) };
assert_abs_diff_eq!(amprms, expected, epsilon = 1e-12);
}
}