1use crate::G1_safe::{eraAnp_safe, eraAnpm_safe};
14use crate::G24_safe::eraPdp_safe;
15use crate::G25_safe::{eraPmp_safe, eraPn_safe};
16use crate::G26_safe::eraPpsp_safe;
17use crate::G27_safe::eraPxp_safe;
18use crate::G28_safe::eraRxp_safe;
19use crate::G29_safe::eraS2c_safe;
20use crate::G33_safe::eraTrxp_safe;
21use crate::G7_safe::eraC2s_safe;
22use crate::H1_safe::{
23 eraLDBODY, ERFA_AULT, ERFA_D2PI, ERFA_DAS2R, ERFA_DAYSEC, ERFA_GMAX, ERFA_GMIN, ERFA_SRS,
24};
25
26pub type ErfaResult<T> = Result<T, ()>;
27
28pub fn eraLd_safe(
33 bm: f64,
34 p: &[f64; 3],
35 q: &[f64; 3],
36 e: &[f64; 3],
37 em: f64,
38 dlim: f64,
39) -> ErfaResult<[f64; 3]> {
40 let qpe = [q[0] + e[0], q[1] + e[1], q[2] + e[2]];
41 let qdqpe = eraPdp_safe(q, &qpe)?;
42 let w = bm * ERFA_SRS / em / ERFA_GMAX(qdqpe, dlim);
43
44 let eq = eraPxp_safe(e, q)?;
45 let peq = eraPxp_safe(p, &eq)?;
46
47 Ok([p[0] + w * peq[0], p[1] + w * peq[1], p[2] + w * peq[2]])
48}
49
50pub fn eraLdn_safe(bodies: &[eraLDBODY], ob: &[f64; 3], sc: &[f64; 3]) -> ErfaResult<[f64; 3]> {
55 const CR: f64 = ERFA_AULT / ERFA_DAYSEC;
57
58 let mut sn = *sc;
59
60 for body in bodies {
61 let v = eraPmp_safe(ob, &body.pv[0])?;
63
64 let dt = ERFA_GMIN(eraPdp_safe(&sn, &v)? * CR, 0.0);
66
67 let ev = eraPpsp_safe(&v, -dt, &body.pv[1])?;
69
70 let (em, e) = eraPn_safe(&ev)?;
72
73 sn = eraLd_safe(body.bm, &sn, &sn, &e, em, body.dl)?;
75 }
76
77 Ok(sn)
78}
79
80pub fn eraLdsun_safe(p: &[f64; 3], e: &[f64; 3], em: f64) -> ErfaResult<[f64; 3]> {
85 let em2 = em * em;
86 let dlim = 1.0e-6 / if em2 < 1.0 { 1.0 } else { em2 };
87 eraLd_safe(1.0, p, p, e, em, dlim)
88}
89
90pub fn eraLteceq_safe(epj: f64, dl: f64, db: f64) -> ErfaResult<(f64, f64)> {
95 let v1 = eraS2c_safe(dl, db)?;
96 let rm = eraLtecm_safe(epj)?;
97 let v2 = eraTrxp_safe(&rm, &v1)?;
98 let (a, b) = eraC2s_safe(&v2)?;
99 let dr = eraAnp_safe(a)?;
100 let dd = eraAnpm_safe(b)?;
101 Ok((dr, dd))
102}
103
104pub fn eraLtecm_safe(epj: f64) -> ErfaResult<[[f64; 3]; 3]> {
109 const DX: f64 = -0.016_617 * ERFA_DAS2R;
111 const DE: f64 = -0.006_819_2 * ERFA_DAS2R;
112 const DR: f64 = -0.014_6 * ERFA_DAS2R;
113
114 let p = eraLtpequ_safe(epj)?;
115 let z = eraLtpecl_safe(epj)?;
116
117 let w = eraPxp_safe(&p, &z)?;
119 let (_s, x) = eraPn_safe(&w)?;
120
121 let y = eraPxp_safe(&z, &x)?;
123
124 let mut m = [[0.0_f64; 3]; 3];
126
127 m[0][0] = x[0] - x[1] * DR + x[2] * DX;
128 m[0][1] = x[0] * DR + x[1] + x[2] * DE;
129 m[0][2] = -x[0] * DX - x[1] * DE + x[2];
130
131 m[1][0] = y[0] - y[1] * DR + y[2] * DX;
132 m[1][1] = y[0] * DR + y[1] + y[2] * DE;
133 m[1][2] = -y[0] * DX - y[1] * DE + y[2];
134
135 m[2][0] = z[0] - z[1] * DR + z[2] * DX;
136 m[2][1] = z[0] * DR + z[1] + z[2] * DE;
137 m[2][2] = -z[0] * DX - z[1] * DE + z[2];
138
139 Ok(m)
140}
141
142pub fn eraLteqec_safe(epj: f64, dr: f64, dd: f64) -> ErfaResult<(f64, f64)> {
147 let v1 = eraS2c_safe(dr, dd)?;
148 let rm = eraLtecm_safe(epj)?;
149 let v2 = eraRxp_safe(&rm, &v1)?;
150 let (a, b) = eraC2s_safe(&v2)?;
151 let dl = eraAnp_safe(a)?;
152 let db = eraAnpm_safe(b)?;
153 Ok((dl, db))
154}
155
156pub fn eraLtp_safe(epj: f64) -> ErfaResult<[[f64; 3]; 3]> {
161 let peqr = eraLtpequ_safe(epj)?;
162 let pecl = eraLtpecl_safe(epj)?;
163
164 let v = eraPxp_safe(&peqr, &pecl)?;
165 let (_w, eqx) = eraPn_safe(&v)?;
166
167 let v2 = eraPxp_safe(&peqr, &eqx)?;
168
169 let mut m = [[0.0_f64; 3]; 3];
170 for i in 0..3 {
171 m[0][i] = eqx[i];
172 m[1][i] = v2[i];
173 m[2][i] = peqr[i];
174 }
175 Ok(m)
176}
177
178pub fn eraLtpb_safe(epj: f64) -> ErfaResult<[[f64; 3]; 3]> {
183 const DX: f64 = -0.016_617 * ERFA_DAS2R;
184 const DE: f64 = -0.006_819_2 * ERFA_DAS2R;
185 const DR: f64 = -0.014_6 * ERFA_DAS2R;
186
187 let rp = eraLtp_safe(epj)?;
188
189 let mut rpb = [[0.0_f64; 3]; 3];
190 for i in 0..3 {
191 rpb[i][0] = rp[i][0] - rp[i][1] * DR + rp[i][2] * DX;
192 rpb[i][1] = rp[i][0] * DR + rp[i][1] + rp[i][2] * DE;
193 rpb[i][2] = -rp[i][0] * DX - rp[i][1] * DE + rp[i][2];
194 }
195 Ok(rpb)
196}
197
198pub fn eraLtpecl_safe(epj: f64) -> ErfaResult<[f64; 3]> {
203 const EPS0: f64 = 84_381.406 * ERFA_DAS2R;
205
206 const PQPOL: [[f64; 4]; 2] = [
208 [5_851.607_687, -0.118_900_0, -0.000_289_13, 0.000_000_101],
209 [-1_600.886_300, 1.168_981_8, -0.000_000_20, -0.000_000_437],
210 ];
211
212 const PQPER: [[f64; 5]; 8] = [
214 [
215 708.15,
216 -5_486.751_211,
217 -684.661_560,
218 667.666_730,
219 -5_523.863_691,
220 ],
221 [
222 2_309.00,
223 -17.127_623,
224 2_446.283_880,
225 -2_354.886_252,
226 -549.747_450,
227 ],
228 [
229 1_620.00,
230 -617.517_403,
231 399.671_049,
232 -428.152_441,
233 -310.998_056,
234 ],
235 [492.20, 413.442_940, -356.652_376, 376.202_861, 421.535_876],
236 [1_183.00, 78.614_193, -186.387_003, 184.778_874, -36.776_172],
237 [
238 622.00,
239 -180.732_815,
240 -316.800_070,
241 335.321_713,
242 -145.278_396,
243 ],
244 [882.00, -87.676_083, 198.296_701, -185.138_669, -34.744_450],
245 [547.00, 46.140_315, 101.135_679, -120.972_830, 22.885_731],
246 ];
247
248 let t = (epj - 2000.0) / 100.0;
250
251 let mut p = 0.0_f64;
253 let mut q = 0.0_f64;
254 let w = ERFA_D2PI * t;
255 for coeff in PQPER {
256 let a = w / coeff[0];
257 let (s, c) = a.sin_cos();
258 p += c * coeff[1] + s * coeff[3];
259 q += c * coeff[2] + s * coeff[4];
260 }
261
262 let mut tt = 1.0_f64;
264 for i in 0..4 {
265 p += PQPOL[0][i] * tt;
266 q += PQPOL[1][i] * tt;
267 tt *= t;
268 }
269
270 let p = p * ERFA_DAS2R;
272 let q = q * ERFA_DAS2R;
273
274 let mut wv = 1.0 - p * p - q * q;
276 wv = if wv < 0.0 { 0.0 } else { wv.sqrt() };
277 let (s0, c0) = EPS0.sin_cos();
278
279 Ok([p, -q * c0 - wv * s0, -q * s0 + wv * c0])
280}
281
282pub fn eraLtpequ_safe(epj: f64) -> ErfaResult<[f64; 3]> {
287 const XYPOL: [[f64; 4]; 2] = [
289 [5_453.282_155, 0.425_284_1, -0.000_371_73, -0.000_000_152],
290 [-73_750.930_350, -0.767_545_2, -0.000_187_25, 0.000_000_231],
291 ];
292
293 const XYPER: [[f64; 5]; 14] = [
295 [
296 256.75,
297 -819.940_624,
298 75_004.344_875,
299 81_491.287_984,
300 1_558.515_853,
301 ],
302 [
303 708.15,
304 -8_444.676_815,
305 624.033_993,
306 787.163_481,
307 7_774.939_698,
308 ],
309 [
310 274.20,
311 2_600.009_459,
312 1_251.136_893,
313 1_251.296_102,
314 -2_219.534_038,
315 ],
316 [
317 241.45,
318 2_755.175_630,
319 -1_102.212_834,
320 -1_257.950_837,
321 -2_523.969_396,
322 ],
323 [
324 2_309.00,
325 -167.659_835,
326 -2_660.664_980,
327 -2_966.799_730,
328 247.850_422,
329 ],
330 [492.20, 871.855_056, 699.291_817, 639.744_522, -846.485_643],
331 [396.10, 44.769_698, 153.167_220, 131.600_209, -1_393.124_055],
332 [
333 288.90,
334 -512.313_065,
335 -950.865_637,
336 -445.040_117,
337 368.526_116,
338 ],
339 [231.10, -819.415_595, 499.754_645, 584.522_874, 749.045_012],
340 [
341 1_610.00,
342 -538.071_099,
343 -145.188_210,
344 -89.756_563,
345 444.704_518,
346 ],
347 [620.00, -189.793_622, 558.116_553, 524.429_630, 235.934_465],
348 [157.87, -402.922_932, -23.923_029, -13.549_067, 374.049_623],
349 [
350 220.30,
351 179.516_345,
352 -165.405_086,
353 -210.157_124,
354 -171.330_180,
355 ],
356 [1_200.00, -9.814_756, 9.344_131, -44.919_798, -22.899_655],
357 ];
358
359 let t = (epj - 2000.0) / 100.0;
360
361 let mut x = 0.0_f64;
363 let mut y = 0.0_f64;
364 let w = ERFA_D2PI * t;
365 for coeff in XYPER {
366 let a = w / coeff[0];
367 let (s, c) = a.sin_cos();
368 x += c * coeff[1] + s * coeff[3];
369 y += c * coeff[2] + s * coeff[4];
370 }
371
372 let mut tt = 1.0_f64;
374 for i in 0..4 {
375 x += XYPOL[0][i] * tt;
376 y += XYPOL[1][i] * tt;
377 tt *= t;
378 }
379
380 let x = x * ERFA_DAS2R;
382 let y = y * ERFA_DAS2R;
383 let wv = 1.0 - x * x - y * y;
384 let z = if wv < 0.0 { 0.0 } else { wv.sqrt() };
385 Ok([x, y, z])
386}