1use crate::G1_safe::eraAnp_safe;
19use crate::G33_safe::eraUtctai_safe;
20use crate::H1_safe::{
21 ERFA_DAYSEC, ERFA_DJM0, ERFA_DJM77, ERFA_DS2R, ERFA_ELB, ERFA_ELG, ERFA_TDB0, ERFA_TTMTAI,
22};
23
24pub type ErfaResult<T> = Result<T, ()>;
25
26pub fn eraTaitt_safe(tai1: f64, tai2: f64) -> ErfaResult<((f64, f64), i32)> {
28 const DTAT: f64 = ERFA_TTMTAI / ERFA_DAYSEC;
29 let (tt1, tt2) = if tai1.abs() > tai2.abs() {
30 (tai1, tai2 + DTAT)
31 } else {
32 (tai1 + DTAT, tai2)
33 };
34 Ok(((tt1, tt2), 0))
35}
36
37pub fn eraTaiut1_safe(tai1: f64, tai2: f64, dta: f64) -> ErfaResult<((f64, f64), i32)> {
39 let dtad = dta / ERFA_DAYSEC;
40 let (ut11, ut12) = if tai1.abs() > tai2.abs() {
41 (tai1, tai2 + dtad)
42 } else {
43 (tai1 + dtad, tai2)
44 };
45 Ok(((ut11, ut12), 0))
46}
47
48pub fn eraTaiutc_safe(tai1: f64, tai2: f64) -> ErfaResult<((f64, f64), i32)> {
50 let big1 = tai1.abs() >= tai2.abs();
51 let (a1, a2) = if big1 { (tai1, tai2) } else { (tai2, tai1) };
52
53 let (u1, mut u2) = (a1, a2);
54 let mut j: i32 = 0;
55
56 for _ in 0..3 {
57 let ((g1, g2), jj) = eraUtctai_safe(u1, u2)?;
58 j = jj;
59 if j < 0 {
60 let (utc1, utc2) = if big1 { (u1, u2) } else { (u2, u1) };
61 return Ok(((utc1, utc2), j));
62 }
63 u2 += a1 - g1;
64 u2 += a2 - g2;
65 }
66
67 let (utc1, utc2) = if big1 { (u1, u2) } else { (u2, u1) };
68 Ok(((utc1, utc2), j))
69}
70
71pub fn eraTcbtdb_safe(tcb1: f64, tcb2: f64) -> ErfaResult<((f64, f64), i32)> {
73 const T77TD: f64 = ERFA_DJM0 + ERFA_DJM77;
74 const T77TF: f64 = ERFA_TTMTAI / ERFA_DAYSEC;
75 const TDB0: f64 = ERFA_TDB0 / ERFA_DAYSEC;
76
77 let (tdb1, tdb2) = if tcb1.abs() > tcb2.abs() {
78 let d = tcb1 - T77TD;
79 (tcb1, tcb2 + TDB0 - (d + (tcb2 - T77TF)) * ERFA_ELB)
80 } else {
81 let d = tcb2 - T77TD;
82 (tcb1 + TDB0 - (d + (tcb1 - T77TF)) * ERFA_ELB, tcb2)
83 };
84 Ok(((tdb1, tdb2), 0))
85}
86
87pub fn eraTcgtt_safe(tcg1: f64, tcg2: f64) -> ErfaResult<((f64, f64), i32)> {
89 const T77T: f64 = ERFA_DJM77 + ERFA_TTMTAI / ERFA_DAYSEC;
90 let (tt1, tt2) = if tcg1.abs() > tcg2.abs() {
91 (tcg1, tcg2 - ((tcg1 - ERFA_DJM0) + (tcg2 - T77T)) * ERFA_ELG)
92 } else {
93 (tcg1 - ((tcg2 - ERFA_DJM0) + (tcg1 - T77T)) * ERFA_ELG, tcg2)
94 };
95 Ok(((tt1, tt2), 0))
96}
97
98pub fn eraTdbtcb_safe(tdb1: f64, tdb2: f64) -> ErfaResult<((f64, f64), i32)> {
100 const T77TD: f64 = ERFA_DJM0 + ERFA_DJM77;
101 const T77TF: f64 = ERFA_TTMTAI / ERFA_DAYSEC;
102 const TDB0: f64 = ERFA_TDB0 / ERFA_DAYSEC;
103 const ELBB: f64 = ERFA_ELB / (1.0 - ERFA_ELB);
104
105 let (tcb1, tcb2) = if tdb1.abs() > tdb2.abs() {
106 let d = T77TD - tdb1;
107 let f = tdb2 - TDB0;
108 (tdb1, f - (d - (f - T77TF)) * ELBB)
109 } else {
110 let d = T77TD - tdb2;
111 let f = tdb1 - TDB0;
112 (f - (d - (f - T77TF)) * ELBB, tdb2)
113 };
114 Ok(((tcb1, tcb2), 0))
115}
116
117pub fn eraTdbtt_safe(tdb1: f64, tdb2: f64, dtr: f64) -> ErfaResult<((f64, f64), i32)> {
119 let dtrd = dtr / ERFA_DAYSEC;
120 let (tt1, tt2) = if tdb1.abs() > tdb2.abs() {
121 (tdb1, tdb2 - dtrd)
122 } else {
123 (tdb1 - dtrd, tdb2)
124 };
125 Ok(((tt1, tt2), 0))
126}
127
128pub fn eraTf2a_safe(s: char, ihour: i32, imin: i32, sec: f64) -> ErfaResult<(f64, i32)> {
130 let sign = if s == '-' { -1.0 } else { 1.0 };
131 let rad =
132 sign * (60.0 * (60.0 * (ihour.abs() as f64) + (imin.abs() as f64)) + sec.abs()) * ERFA_DS2R;
133 if ihour < 0 || ihour > 23 {
134 return Ok((rad, 1));
135 }
136 if imin < 0 || imin > 59 {
137 return Ok((rad, 2));
138 }
139 if sec < 0.0 || sec >= 60.0 {
140 return Ok((rad, 3));
141 }
142 Ok((rad, 0))
143}
144
145pub fn eraTf2d_safe(s: char, ihour: i32, imin: i32, sec: f64) -> ErfaResult<(f64, i32)> {
147 let sign = if s == '-' { -1.0 } else { 1.0 };
148 let days = sign * (60.0 * (60.0 * (ihour.abs() as f64) + (imin.abs() as f64)) + sec.abs())
149 / ERFA_DAYSEC;
150 if ihour < 0 || ihour > 23 {
151 return Ok((days, 1));
152 }
153 if imin < 0 || imin > 59 {
154 return Ok((days, 2));
155 }
156 if sec < 0.0 || sec >= 60.0 {
157 return Ok((days, 3));
158 }
159 Ok((days, 0))
160}
161
162pub fn eraTpors_safe(
164 xi: f64,
165 eta: f64,
166 a: f64,
167 b: f64,
168) -> ErfaResult<((f64, f64), (f64, f64), i32)> {
169 let xi2 = xi * xi;
170 let r = (1.0 + xi2 + eta * eta).sqrt();
171 let sb = b.sin();
172 let cb = b.cos();
173 let rsb = r * sb;
174 let rcb = r * cb;
175 let w2 = rcb * rcb - xi2;
176
177 if w2 >= 0.0 {
178 let mut w = w2.sqrt();
179 let mut s = rsb - eta * w;
180 let mut c = rsb * eta + w;
181 if xi == 0.0 && w == 0.0 {
182 w = 1.0;
183 }
184 let a01 = eraAnp_safe(a - xi.atan2(w))?;
185 let b01 = s.atan2(c);
186
187 let w2n = -w;
188 s = rsb - eta * w2n;
189 c = rsb * eta + w2n;
190 let a02 = eraAnp_safe(a - xi.atan2(w2n))?;
191 let b02 = s.atan2(c);
192
193 let j = if rsb.abs() < 1.0 { 1 } else { 2 };
194 Ok(((a01, b01), (a02, b02), j))
195 } else {
196 Ok(((0.0, 0.0), (0.0, 0.0), 0))
197 }
198}
199
200pub fn eraTporv_safe(xi: f64, eta: f64, v: &[f64; 3]) -> ErfaResult<([f64; 3], [f64; 3], i32)> {
202 let x = v[0];
203 let y = v[1];
204 let z = v[2];
205
206 let rxy2 = x * x + y * y;
207 let xi2 = xi * xi;
208 let eta2p1 = eta * eta + 1.0;
209 let r = (xi2 + eta2p1).sqrt();
210 let rsb = r * z;
211 let rcb = r * rxy2.sqrt();
212 let w2 = rcb * rcb - xi2;
213
214 if w2 > 0.0 {
215 let mut w = w2.sqrt();
216 let mut c = (rsb * eta + w) / (eta2p1 * ((rxy2 * (w2 + xi2)).sqrt()));
217 let v01 = [
218 c * (x * w + y * xi),
219 c * (y * w - x * xi),
220 (rsb - eta * w) / eta2p1,
221 ];
222
223 w = -w;
224 c = (rsb * eta + w) / (eta2p1 * ((rxy2 * (w2 + xi2)).sqrt()));
225 let v02 = [
226 c * (x * w + y * xi),
227 c * (y * w - x * xi),
228 (rsb - eta * w) / eta2p1,
229 ];
230
231 let j = if rsb.abs() < 1.0 { 1 } else { 2 };
232 Ok((v01, v02, j))
233 } else {
234 Ok(([0.0; 3], [0.0; 3], 0))
235 }
236}
237
238pub fn eraTpsts_safe(xi: f64, eta: f64, a0: f64, b0: f64) -> ErfaResult<(f64, f64)> {
240 let sb0 = b0.sin();
241 let cb0 = b0.cos();
242 let d = cb0 - eta * sb0;
243 let a = eraAnp_safe(xi.atan2(d) + a0)?;
244 let b = (sb0 + eta * cb0).atan2((xi * xi + d * d).sqrt());
245 Ok((a, b))
246}
247
248pub fn eraTpstv_safe(xi: f64, eta: f64, v0: &[f64; 3]) -> ErfaResult<[f64; 3]> {
250 let mut x = v0[0];
251 let y = v0[1];
252 let z = v0[2];
253
254 let mut r = (x * x + y * y).sqrt();
255 if r == 0.0 {
256 r = 1e-20;
257 x = r;
258 }
259 let f = (1.0 + xi * xi + eta * eta).sqrt();
260
261 let vx = (x - (xi * y + eta * x * z) / r) / f;
262 let vy = (y + (xi * x - eta * y * z) / r) / f;
263 let vz = (z + eta * r) / f;
264
265 Ok([vx, vy, vz])
266}
267
268pub fn eraTpxes_safe(a: f64, b: f64, a0: f64, b0: f64) -> ErfaResult<((f64, f64), i32)> {
270 const TINY: f64 = 1e-6;
271
272 let sb0 = b0.sin();
273 let sb = b.sin();
274 let cb0 = b0.cos();
275 let cb = b.cos();
276 let da = a - a0;
277 let sda = da.sin();
278 let cda = da.cos();
279
280 let mut d = sb * sb0 + cb * cb0 * cda;
281
282 let j = if d > TINY {
283 0
284 } else if d >= 0.0 {
285 d = TINY;
286 1
287 } else if d > -TINY {
288 d = -TINY;
289 2
290 } else {
291 3
292 };
293
294 let xi = cb * sda / d;
295 let eta = (sb * cb0 - cb * sb0 * cda) / d;
296 Ok(((xi, eta), j))
297}
298
299pub fn eraTpxev_safe(v: &[f64; 3], v0: &[f64; 3]) -> ErfaResult<((f64, f64), i32)> {
301 const TINY: f64 = 1e-6;
302
303 let x = v[0];
304 let y = v[1];
305 let z = v[2];
306 let mut x0 = v0[0];
307 let y0 = v0[1];
308 let z0 = v0[2];
309
310 let r2 = x0 * x0 + y0 * y0;
311 let mut r = r2.sqrt();
312 if r == 0.0 {
313 r = 1e-20;
314 x0 = r;
315 }
316
317 let w = x * x0 + y * y0;
318 let mut d = w + z * z0;
319
320 let j = if d > TINY {
321 0
322 } else if d >= 0.0 {
323 d = TINY;
324 1
325 } else if d > -TINY {
326 d = -TINY;
327 2
328 } else {
329 3
330 };
331
332 d *= r;
333 let xi = (y * x0 - x * y0) / d;
334 let eta = (z * r2 - z0 * w) / d;
335 Ok(((xi, eta), j))
336}