1use crate::H1_safe::{ERFA_DJ00, ERFA_DJY};
5
6#[path = "data/G13_safe/E0Z.rs"]
7mod e0z_mod;
8use e0z_mod::E0Z;
9#[path = "data/G13_safe/E0X.rs"]
10mod e0x_mod;
11use e0x_mod::E0X;
12#[path = "data/G13_safe/E0Y.rs"]
13mod e0y_mod;
14use e0y_mod::E0Y;
15#[path = "data/G13_safe/E1X.rs"]
16mod e1x_mod;
17use e1x_mod::E1X;
18#[path = "data/G13_safe/E1Y.rs"]
19mod e1y_mod;
20use e1y_mod::E1Y;
21#[path = "data/G13_safe/E1Z.rs"]
22mod e1z_mod;
23use e1z_mod::E1Z;
24#[path = "data/G13_safe/S0X.rs"]
25mod s0x_mod;
26use s0x_mod::S0X;
27#[path = "data/G13_safe/S0Y.rs"]
28mod s0y_mod;
29use s0y_mod::S0Y;
30#[path = "data/G13_safe/S0Z.rs"]
31mod s0z_mod;
32use s0z_mod::S0Z;
33#[path = "data/G13_safe/S1X.rs"]
34mod s1x_mod;
35use s1x_mod::S1X;
36#[path = "data/G13_safe/S1Y.rs"]
37mod s1y_mod;
38use s1y_mod::S1Y;
39#[path = "data/G13_safe/S2Y.rs"]
40mod s2y_mod;
41use s2y_mod::S2Y;
42#[path = "data/G13_safe/S2X.rs"]
43mod s2x_mod;
44use s2x_mod::S2X;
45#[path = "data/G13_safe/S1Z.rs"]
46mod s1z_mod;
47use s1z_mod::S1Z;
48
49pub type ErfaResult<T> = Result<T, ()>;
50
51const AM12: f64 = 0.000000211284;
53const AM13: f64 = -0.000000091603;
54const AM21: f64 = -0.000000230286;
55const AM22: f64 = 0.917482137087;
56const AM23: f64 = -0.397776982902;
57const AM32: f64 = 0.397776982902;
58const AM33: f64 = 0.917482137087;
59
60static E2X: &[f64] = &[
62 -0.4143818297913e-10,
63 0.0000000000000e+00,
64 0.0000000000000e+00,
65 0.2171497694435e-10,
66 0.4398225628264e+01,
67 0.1256615170089e+02,
68 0.9845398442516e-11,
69 0.2079720838384e+00,
70 0.6283075850446e+01,
71 0.9256833552682e-12,
72 0.4191264694361e+01,
73 0.1884922755134e+02,
74 0.1022049384115e-12,
75 0.5381133195658e+01,
76 0.8399684731857e+02,
77];
78static E2Y: &[f64] = &[
79 0.5063375872532e-10,
80 0.0000000000000e+00,
81 0.0000000000000e+00,
82 0.2173815785980e-10,
83 0.2827805833053e+01,
84 0.1256615170089e+02,
85 0.1010231999920e-10,
86 0.4634612377133e+01,
87 0.6283075850446e+01,
88 0.9259745317636e-12,
89 0.2620612076189e+01,
90 0.1884922755134e+02,
91 0.1022202095812e-12,
92 0.3809562326066e+01,
93 0.8399684731857e+02,
94];
95static E2Z: &[f64] = &[
96 0.9722666114891e-10,
97 0.5152219582658e+01,
98 0.6283075850446e+01,
99 -0.3494819171909e-11,
100 0.0000000000000e+00,
101 0.0000000000000e+00,
102 0.6713034376076e-12,
103 0.6440188750495e+00,
104 0.1256615170089e+02,
105];
106
107static S2Z: &[f64] = &[
108 0.3749920358054e-12,
109 0.3230285558668e+01,
110 0.2132990797783e+00,
111 0.2735037220939e-12,
112 0.6154322683046e+01,
113 0.5296909721118e+00,
114];
115
116const CE0: [&[f64]; 3] = [E0X, E0Y, E0Z];
117const CE1: [&[f64]; 3] = [E1X, E1Y, E1Z];
118const CE2: [&[f64]; 3] = [E2X, E2Y, E2Z];
119const CS0: [&[f64]; 3] = [S0X, S0Y, S0Z];
120const CS1: [&[f64]; 3] = [S1X, S1Y, S1Z];
121const CS2: [&[f64]; 3] = [S2X, S2Y, S2Z];
122
123pub fn eraEpv00_safe(date1: f64, date2: f64) -> ErfaResult<([[f64; 3]; 2], [[f64; 3]; 2], i32)> {
126 let t = ((date1 - ERFA_DJ00) + date2) / ERFA_DJY;
128
129 let jstat = if t.abs() <= 100.0 { 0 } else { 1 };
131
132 let mut ph = [0.0_f64; 3];
134 let mut vh = [0.0_f64; 3];
135 let mut pb = [0.0_f64; 3];
136 let mut vb = [0.0_f64; 3];
137
138 for i in 0..3 {
140 let (mut xyz, mut xyzd) = (0.0_f64, 0.0_f64);
141
142 accumulate_component(&mut xyz, &mut xyzd, CE0[i], t, 0);
144 accumulate_component(&mut xyz, &mut xyzd, CE1[i], t, 1);
145 accumulate_component(&mut xyz, &mut xyzd, CE2[i], t, 2);
146
147 ph[i] = xyz;
148 vh[i] = xyzd / ERFA_DJY;
149
150 accumulate_component(&mut xyz, &mut xyzd, CS0[i], t, 0);
152 accumulate_component(&mut xyz, &mut xyzd, CS1[i], t, 1);
153 accumulate_component(&mut xyz, &mut xyzd, CS2[i], t, 2);
154
155 pb[i] = xyz;
156 vb[i] = xyzd / ERFA_DJY;
157 }
158
159 let mut pvh = [[0.0_f64; 3]; 2];
161 let mut pvb = [[0.0_f64; 3]; 2];
162 rotate_xyz(&ph, &mut pvh[0]);
163 rotate_xyz(&vh, &mut pvh[1]);
164 rotate_xyz(&pb, &mut pvb[0]);
165 rotate_xyz(&vb, &mut pvb[1]);
166
167 Ok((pvh, pvb, jstat))
168}
169
170#[inline]
172fn accumulate_component(xyz: &mut f64, xyzd: &mut f64, coeffs: &[f64], t: f64, power: u8) {
173 let nterms = coeffs.len() / 3;
174 for k in (0..nterms).rev() {
175 let a = coeffs[3 * k];
176 let b = coeffs[3 * k + 1];
177 let c = coeffs[3 * k + 2];
178 let ct = c * t;
179 let p = b + ct;
180 let (sp, cp) = p.sin_cos();
181 match power {
182 0 => {
183 *xyz += a * cp;
184 *xyzd -= a * c * sp;
185 }
186 1 => {
187 *xyz += a * t * cp;
188 *xyzd += a * (cp - ct * sp);
189 }
190 2 => {
191 *xyz += a * t * t * cp;
192 *xyzd += a * t * (2.0 * cp - ct * sp);
193 }
194 _ => unreachable!(),
195 }
196 }
197}
198
199#[inline]
201fn rotate_xyz(src: &[f64; 3], dst: &mut [f64; 3]) {
202 let (x, y, z) = (src[0], src[1], src[2]);
203 dst[0] = x + AM12 * y + AM13 * z;
204 dst[1] = AM21 * x + AM22 * y + AM23 * z;
205 dst[2] = AM32 * y + AM33 * z;
206}