use crate::consts::{DAU, DD2R, DJ00, DJC};
use crate::pnp::pfw06;
use crate::vm::{ir, rx, rxpv, rz, s2pv};
pub fn moon98(date1: f64, date2: f64) -> [[f64; 3]; 2] {
const ELP0: f64 = 218.31665436;
const ELP1: f64 = 481267.88123421;
const ELP2: f64 = -0.0015786;
const ELP3: f64 = 1.0 / 538841.0;
const ELP4: f64 = -1.0 / 65194000.0;
const D0: f64 = 297.8501921;
const D1: f64 = 445267.1114034;
const D2: f64 = -0.0018819;
const D3: f64 = 1.0 / 545868.0;
const D4: f64 = 1.0 / 113065000.0;
const EM0: f64 = 357.5291092;
const EM1: f64 = 35999.0502909;
const EM2: f64 = -0.0001536;
const EM3: f64 = 1.0 / 24490000.0;
const EM4: f64 = 0.0;
const EMP0: f64 = 134.9633964;
const EMP1: f64 = 477198.8675055;
const EMP2: f64 = 0.0087414;
const EMP3: f64 = 1.0 / 69699.0;
const EMP4: f64 = -1.0 / 14712000.0;
const F0: f64 = 93.2720950;
const F1: f64 = 483202.0175233;
const F2: f64 = -0.0036539;
const F3: f64 = 1.0 / 3526000.0;
const F4: f64 = 1.0 / 863310000.0;
const A10: f64 = 119.75;
const A11: f64 = 131.849;
const A20: f64 = 53.09;
const A21: f64 = 479264.290;
const A30: f64 = 313.45;
const A31: f64 = 481266.484;
const AL1: f64 = 0.003958;
const AL2: f64 = 0.001962;
const AL3: f64 = 0.000318;
const AB1: f64 = -0.002235;
const AB2: f64 = 0.000382;
const AB3: f64 = 0.000175;
const AB4: f64 = 0.000175;
const AB5: f64 = 0.000127;
const AB6: f64 = -0.000115;
const R0: f64 = 385000560.0;
const E1: f64 = -0.002516;
const E2: f64 = -0.0000074;
struct TermLR {
nd: i32,
nem: i32,
nemp: i32,
nf: i32,
coefl: f64,
coefr: f64,
}
const TLR: [TermLR; 60] = [
TermLR { nd: 0, nem: 0, nemp: 1, nf: 0, coefl: 6.288774, coefr: -20905355.0 },
TermLR { nd: 2, nem: 0, nemp: -1, nf: 0, coefl: 1.274027, coefr: -3699111.0 },
TermLR { nd: 2, nem: 0, nemp: 0, nf: 0, coefl: 0.658314, coefr: -2955968.0 },
TermLR { nd: 0, nem: 0, nemp: 2, nf: 0, coefl: 0.213618, coefr: -569925.0 },
TermLR { nd: 0, nem: 1, nemp: 0, nf: 0, coefl: -0.185116, coefr: 48888.0 },
TermLR { nd: 0, nem: 0, nemp: 0, nf: 2, coefl: -0.114332, coefr: -3149.0 },
TermLR { nd: 2, nem: 0, nemp: -2, nf: 0, coefl: 0.058793, coefr: 246158.0 },
TermLR { nd: 2, nem: -1, nemp: -1, nf: 0, coefl: 0.057066, coefr: -152138.0 },
TermLR { nd: 2, nem: 0, nemp: 1, nf: 0, coefl: 0.053322, coefr: -170733.0 },
TermLR { nd: 2, nem: -1, nemp: 0, nf: 0, coefl: 0.045758, coefr: -204586.0 },
TermLR { nd: 0, nem: 1, nemp: -1, nf: 0, coefl: -0.040923, coefr: -129620.0 },
TermLR { nd: 1, nem: 0, nemp: 0, nf: 0, coefl: -0.034720, coefr: 108743.0 },
TermLR { nd: 0, nem: 1, nemp: 1, nf: 0, coefl: -0.030383, coefr: 104755.0 },
TermLR { nd: 2, nem: 0, nemp: 0, nf: -2, coefl: 0.015327, coefr: 10321.0 },
TermLR { nd: 0, nem: 0, nemp: 1, nf: 2, coefl: -0.012528, coefr: 0.0 },
TermLR { nd: 0, nem: 0, nemp: 1, nf: -2, coefl: 0.010980, coefr: 79661.0 },
TermLR { nd: 4, nem: 0, nemp: -1, nf: 0, coefl: 0.010675, coefr: -34782.0 },
TermLR { nd: 0, nem: 0, nemp: 3, nf: 0, coefl: 0.010034, coefr: -23210.0 },
TermLR { nd: 4, nem: 0, nemp: -2, nf: 0, coefl: 0.008548, coefr: -21636.0 },
TermLR { nd: 2, nem: 1, nemp: -1, nf: 0, coefl: -0.007888, coefr: 24208.0 },
TermLR { nd: 2, nem: 1, nemp: 0, nf: 0, coefl: -0.006766, coefr: 30824.0 },
TermLR { nd: 1, nem: 0, nemp: -1, nf: 0, coefl: -0.005163, coefr: -8379.0 },
TermLR { nd: 1, nem: 1, nemp: 0, nf: 0, coefl: 0.004987, coefr: -16675.0 },
TermLR { nd: 2, nem: -1, nemp: 1, nf: 0, coefl: 0.004036, coefr: -12831.0 },
TermLR { nd: 2, nem: 0, nemp: 2, nf: 0, coefl: 0.003994, coefr: -10445.0 },
TermLR { nd: 4, nem: 0, nemp: 0, nf: 0, coefl: 0.003861, coefr: -11650.0 },
TermLR { nd: 2, nem: 0, nemp: -3, nf: 0, coefl: 0.003665, coefr: 14403.0 },
TermLR { nd: 0, nem: 1, nemp: -2, nf: 0, coefl: -0.002689, coefr: -7003.0 },
TermLR { nd: 2, nem: 0, nemp: -1, nf: 2, coefl: -0.002602, coefr: 0.0 },
TermLR { nd: 2, nem: -1, nemp: -2, nf: 0, coefl: 0.002390, coefr: 10056.0 },
TermLR { nd: 1, nem: 0, nemp: 1, nf: 0, coefl: -0.002348, coefr: 6322.0 },
TermLR { nd: 2, nem: -2, nemp: 0, nf: 0, coefl: 0.002236, coefr: -9884.0 },
TermLR { nd: 0, nem: 1, nemp: 2, nf: 0, coefl: -0.002120, coefr: 5751.0 },
TermLR { nd: 0, nem: 2, nemp: 0, nf: 0, coefl: -0.002069, coefr: 0.0 },
TermLR { nd: 2, nem: -2, nemp: -1, nf: 0, coefl: 0.002048, coefr: -4950.0 },
TermLR { nd: 2, nem: 0, nemp: 1, nf: -2, coefl: -0.001773, coefr: 4130.0 },
TermLR { nd: 2, nem: 0, nemp: 0, nf: 2, coefl: -0.001595, coefr: 0.0 },
TermLR { nd: 4, nem: -1, nemp: -1, nf: 0, coefl: 0.001215, coefr: -3958.0 },
TermLR { nd: 0, nem: 0, nemp: 2, nf: 2, coefl: -0.001110, coefr: 0.0 },
TermLR { nd: 3, nem: 0, nemp: -1, nf: 0, coefl: -0.000892, coefr: 3258.0 },
TermLR { nd: 2, nem: 1, nemp: 1, nf: 0, coefl: -0.000810, coefr: 2616.0 },
TermLR { nd: 4, nem: -1, nemp: -2, nf: 0, coefl: 0.000759, coefr: -1897.0 },
TermLR { nd: 0, nem: 2, nemp: -1, nf: 0, coefl: -0.000713, coefr: -2117.0 },
TermLR { nd: 2, nem: 2, nemp: -1, nf: 0, coefl: -0.000700, coefr: 2354.0 },
TermLR { nd: 2, nem: 1, nemp: -2, nf: 0, coefl: 0.000691, coefr: 0.0 },
TermLR { nd: 2, nem: -1, nemp: 0, nf: -2, coefl: 0.000596, coefr: 0.0 },
TermLR { nd: 4, nem: 0, nemp: 1, nf: 0, coefl: 0.000549, coefr: -1423.0 },
TermLR { nd: 0, nem: 0, nemp: 4, nf: 0, coefl: 0.000537, coefr: -1117.0 },
TermLR { nd: 4, nem: -1, nemp: 0, nf: 0, coefl: 0.000520, coefr: -1571.0 },
TermLR { nd: 1, nem: 0, nemp: -2, nf: 0, coefl: -0.000487, coefr: -1739.0 },
TermLR { nd: 2, nem: 1, nemp: 0, nf: -2, coefl: -0.000399, coefr: 0.0 },
TermLR { nd: 0, nem: 0, nemp: 2, nf: -2, coefl: -0.000381, coefr: -4421.0 },
TermLR { nd: 1, nem: 1, nemp: 1, nf: 0, coefl: 0.000351, coefr: 0.0 },
TermLR { nd: 3, nem: 0, nemp: -2, nf: 0, coefl: -0.000340, coefr: 0.0 },
TermLR { nd: 4, nem: 0, nemp: -3, nf: 0, coefl: 0.000330, coefr: 0.0 },
TermLR { nd: 2, nem: -1, nemp: 2, nf: 0, coefl: 0.000327, coefr: 0.0 },
TermLR { nd: 0, nem: 2, nemp: 1, nf: 0, coefl: -0.000323, coefr: 1165.0 },
TermLR { nd: 1, nem: 1, nemp: -1, nf: 0, coefl: 0.000299, coefr: 0.0 },
TermLR { nd: 2, nem: 0, nemp: 3, nf: 0, coefl: 0.000294, coefr: 0.0 },
TermLR { nd: 2, nem: 0, nemp: -1, nf: -2, coefl: 0.000000, coefr: 8752.0 },
];
struct TermB {
nd: i32,
nem: i32,
nemp: i32,
nf: i32,
coefb: f64,
}
const TB: [TermB; 60] = [
TermB { nd: 0, nem: 0, nemp: 0, nf: 1, coefb: 5.128122 },
TermB { nd: 0, nem: 0, nemp: 1, nf: 1, coefb: 0.280602 },
TermB { nd: 0, nem: 0, nemp: 1, nf: -1, coefb: 0.277693 },
TermB { nd: 2, nem: 0, nemp: 0, nf: -1, coefb: 0.173237 },
TermB { nd: 2, nem: 0, nemp: -1, nf: 1, coefb: 0.055413 },
TermB { nd: 2, nem: 0, nemp: -1, nf: -1, coefb: 0.046271 },
TermB { nd: 2, nem: 0, nemp: 0, nf: 1, coefb: 0.032573 },
TermB { nd: 0, nem: 0, nemp: 2, nf: 1, coefb: 0.017198 },
TermB { nd: 2, nem: 0, nemp: 1, nf: -1, coefb: 0.009266 },
TermB { nd: 0, nem: 0, nemp: 2, nf: -1, coefb: 0.008822 },
TermB { nd: 2, nem: -1, nemp: 0, nf: -1, coefb: 0.008216 },
TermB { nd: 2, nem: 0, nemp: -2, nf: -1, coefb: 0.004324 },
TermB { nd: 2, nem: 0, nemp: 1, nf: 1, coefb: 0.004200 },
TermB { nd: 2, nem: 1, nemp: 0, nf: -1, coefb: -0.003359 },
TermB { nd: 2, nem: -1, nemp: -1, nf: 1, coefb: 0.002463 },
TermB { nd: 2, nem: -1, nemp: 0, nf: 1, coefb: 0.002211 },
TermB { nd: 2, nem: -1, nemp: -1, nf: -1, coefb: 0.002065 },
TermB { nd: 0, nem: 1, nemp: -1, nf: -1, coefb: -0.001870 },
TermB { nd: 4, nem: 0, nemp: -1, nf: -1, coefb: 0.001828 },
TermB { nd: 0, nem: 1, nemp: 0, nf: 1, coefb: -0.001794 },
TermB { nd: 0, nem: 0, nemp: 0, nf: 3, coefb: -0.001749 },
TermB { nd: 0, nem: 1, nemp: -1, nf: 1, coefb: -0.001565 },
TermB { nd: 1, nem: 0, nemp: 0, nf: 1, coefb: -0.001491 },
TermB { nd: 0, nem: 1, nemp: 1, nf: 1, coefb: -0.001475 },
TermB { nd: 0, nem: 1, nemp: 1, nf: -1, coefb: -0.001410 },
TermB { nd: 0, nem: 1, nemp: 0, nf: -1, coefb: -0.001344 },
TermB { nd: 1, nem: 0, nemp: 0, nf: -1, coefb: -0.001335 },
TermB { nd: 0, nem: 0, nemp: 3, nf: 1, coefb: 0.001107 },
TermB { nd: 4, nem: 0, nemp: 0, nf: -1, coefb: 0.001021 },
TermB { nd: 4, nem: 0, nemp: -1, nf: 1, coefb: 0.000833 },
TermB { nd: 0, nem: 0, nemp: 1, nf: -3, coefb: 0.000777 },
TermB { nd: 4, nem: 0, nemp: -2, nf: 1, coefb: 0.000671 },
TermB { nd: 2, nem: 0, nemp: 0, nf: -3, coefb: 0.000607 },
TermB { nd: 2, nem: 0, nemp: 2, nf: -1, coefb: 0.000596 },
TermB { nd: 2, nem: -1, nemp: 1, nf: -1, coefb: 0.000491 },
TermB { nd: 2, nem: 0, nemp: -2, nf: 1, coefb: -0.000451 },
TermB { nd: 0, nem: 0, nemp: 3, nf: -1, coefb: 0.000439 },
TermB { nd: 2, nem: 0, nemp: 2, nf: 1, coefb: 0.000422 },
TermB { nd: 2, nem: 0, nemp: -3, nf: -1, coefb: 0.000421 },
TermB { nd: 2, nem: 1, nemp: -1, nf: 1, coefb: -0.000366 },
TermB { nd: 2, nem: 1, nemp: 0, nf: 1, coefb: -0.000351 },
TermB { nd: 4, nem: 0, nemp: 0, nf: 1, coefb: 0.000331 },
TermB { nd: 2, nem: -1, nemp: 1, nf: 1, coefb: 0.000315 },
TermB { nd: 2, nem: -2, nemp: 0, nf: -1, coefb: 0.000302 },
TermB { nd: 0, nem: 0, nemp: 1, nf: 3, coefb: -0.000283 },
TermB { nd: 2, nem: 1, nemp: 1, nf: -1, coefb: -0.000229 },
TermB { nd: 1, nem: 1, nemp: 0, nf: -1, coefb: 0.000223 },
TermB { nd: 1, nem: 1, nemp: 0, nf: 1, coefb: 0.000223 },
TermB { nd: 0, nem: 1, nemp: -2, nf: -1, coefb: -0.000220 },
TermB { nd: 2, nem: 1, nemp: -1, nf: -1, coefb: -0.000220 },
TermB { nd: 1, nem: 0, nemp: 1, nf: 1, coefb: -0.000185 },
TermB { nd: 2, nem: -1, nemp: -2, nf: -1, coefb: 0.000181 },
TermB { nd: 0, nem: 1, nemp: 2, nf: 1, coefb: -0.000177 },
TermB { nd: 4, nem: 0, nemp: -2, nf: -1, coefb: 0.000176 },
TermB { nd: 4, nem: -1, nemp: -1, nf: -1, coefb: 0.000166 },
TermB { nd: 1, nem: 0, nemp: 1, nf: -1, coefb: -0.000164 },
TermB { nd: 4, nem: 0, nemp: 1, nf: -1, coefb: 0.000132 },
TermB { nd: 1, nem: 0, nemp: -1, nf: -1, coefb: -0.000119 },
TermB { nd: 4, nem: -1, nemp: 0, nf: -1, coefb: 0.000115 },
TermB { nd: 2, nem: -2, nemp: 0, nf: 1, coefb: 0.000107 },
];
let mut rm = [[0.0; 3]; 3];
let t = ((date1 - DJ00) + date2) / DJC;
let elp = DD2R * (ELP0 + (ELP1 + (ELP2 + (ELP3 + ELP4 * t) * t) * t) * t).rem_euclid(360.0);
let delp = DD2R * (ELP1 + (ELP2 * 2.0 + (ELP3 * 3.0 + ELP4 * 4.0 * t) * t) * t);
let d = DD2R * (D0 + (D1 + (D2 + (D3 + D4 * t) * t) * t) * t).rem_euclid(360.0);
let dd = DD2R * (D1 + (D2 * 2.0 + (D3 * 3.0 + D4 * 4.0 * t) * t) * t);
let em = DD2R * (EM0 + (EM1 + (EM2 + (EM3 + EM4 * t) * t) * t) * t).rem_euclid(360.0);
let dem = DD2R * (EM1 + (EM2 * 2.0 + (EM3 * 3.0 + EM4 * 4.0 * t) * t) * t);
let emp = DD2R * (EMP0 + (EMP1 + (EMP2 + (EMP3 + EMP4 * t) * t) * t) * t).rem_euclid(360.0);
let demp = DD2R * (EMP1 + (EMP2 * 2.0 + (EMP3 * 3.0 + EMP4 * 4.0 * t) * t) * t);
let f = DD2R * (F0 + (F1 + (F2 + (F3 + F4 * t) * t) * t) * t).rem_euclid(360.0);
let df = DD2R * (F1 + (F2 * 2.0 + (F3 * 3.0 + F4 * 4.0 * t) * t) * t);
let a1 = DD2R * (A10 + A11 * t);
let da1 = DD2R * A11;
let a2 = DD2R * (A20 + A21 * t);
let da2 = DD2R * A21;
let a3 = DD2R * (A30 + A31 * t);
let da3 = DD2R * A31;
let e = 1.0 + (E1 + E2 * t) * t;
let de = E1 + 2.0 * E2 * t;
let esq = e * e;
let desq = 2.0 * e * de;
let elpmf = elp - f;
let delpmf = delp - df;
let mut vel = AL1 * a1.sin() + AL2 * elpmf.sin() + AL3 * a2.sin();
let mut vdel = AL1 * a1.cos() * da1 + AL2 * elpmf.cos() * delpmf + AL3 * a2.cos() * da2;
let mut vr = 0.0;
let mut vdr = 0.0;
let a1mf = a1 - f;
let da1mf = da1 - df;
let a1pf = a1 + f;
let da1pf = da1 + df;
let dlpmp = elp - emp;
let slpmp = elp + emp;
let mut vb = AB1 * elp.sin()
+ AB2 * a3.sin()
+ AB3 * a1mf.sin()
+ AB4 * a1pf.sin()
+ AB5 * dlpmp.sin()
+ AB6 * slpmp.sin();
let mut vdb = AB1 * elp.cos() * delp
+ AB2 * a3.cos() * da3
+ AB3 * a1mf.cos() * da1mf
+ AB4 * a1pf.cos() * da1pf
+ AB5 * dlpmp.cos() * (delp - demp)
+ AB6 * slpmp.cos() * (delp + demp);
for n in (0..TLR.len()).rev() {
let dn = TLR[n].nd as f64;
let i_val = TLR[n].nem;
let emn = i_val as f64;
let empn = TLR[n].nemp as f64;
let fn_val = TLR[n].nf as f64;
let en;
let den;
match i_val.abs() {
1 => {
en = e;
den = de;
}
2 => {
en = esq;
den = desq;
}
_ => {
en = 1.0;
den = 0.0;
}
}
let arg = dn * d + emn * em + empn * emp + fn_val * f;
let darg = dn * dd + emn * dem + empn * demp + fn_val * df;
let mut farg = arg.sin();
let mut v = farg * en;
let mut dv = arg.cos() * darg * en + farg * den;
let mut coeff = TLR[n].coefl;
vel += coeff * v;
vdel += coeff * dv;
farg = arg.cos();
v = farg * en;
dv = -arg.sin() * darg * en + farg * den;
coeff = TLR[n].coefr;
vr += coeff * v;
vdr += coeff * dv;
}
let el = elp + DD2R * vel;
let del = (delp + DD2R * vdel) / DJC;
let r = (vr + R0) / DAU;
let dr = vdr / DAU / DJC;
for n in (0..TB.len()).rev() {
let dn = TB[n].nd as f64;
let i_val = TB[n].nem;
let emn = i_val as f64;
let empn = TB[n].nemp as f64;
let fn_val = TB[n].nf as f64;
let en;
let den;
match i_val.abs() {
1 => {
en = e;
den = de;
}
2 => {
en = esq;
den = desq;
}
_ => {
en = 1.0;
den = 0.0;
}
}
let arg = dn * d + emn * em + empn * emp + fn_val * f;
let darg = dn * dd + emn * dem + empn * demp + fn_val * df;
let farg = arg.sin();
let v = farg * en;
let dv = arg.cos() * darg * en + farg * den;
let coeff = TB[n].coefb;
vb += coeff * v;
vdb += coeff * dv;
}
let b = vb * DD2R;
let db = vdb * DD2R / DJC;
let pv = s2pv(el, b, r, del, db, dr);
let (gamb, phib, psib, _) = pfw06(date1, date2);
ir(&mut rm);
rz(psib, &mut rm);
rx(-phib, &mut rm);
rz(-gamb, &mut rm);
let mut res = [[0.0; 3]; 2];
rxpv(&rm, &pv, &mut res);
res
}