Skip to main content

empyrean_sys/
bindings.rs

1/* automatically generated by rust-bindgen 0.72.1 */
2
3pub const EMPYREAN_BUILTSYSTEM_OK: u32 = 0;
4pub const EMPYREAN_BUILTSYSTEM_NULL_POINTER: i32 = -1;
5pub const EMPYREAN_BUILTSYSTEM_INVALID_ARGUMENT: i32 = -2;
6pub const EMPYREAN_BUILTSYSTEM_PROPAGATION: i32 = -3;
7pub const EMPYREAN_BUILTSYSTEM_ALLOC: i32 = -5;
8pub const EMPYREAN_BUILTSYSTEM_DATA_MISMATCH: i32 = -20;
9pub const EMPYREAN_BUILTSYSTEM_KEY_MISMATCH_FRAME: i32 = -21;
10pub const EMPYREAN_BUILTSYSTEM_KEY_MISMATCH_FORCE_MODEL: i32 = -22;
11pub const EMPYREAN_BUILTSYSTEM_KEY_MISMATCH_DIVISOR: i32 = -23;
12pub const EMPYREAN_BUILTSYSTEM_STALE: i32 = -24;
13pub const EMPYREAN_BUILTSYSTEM_PANIC: i32 = -99;
14pub const EMPYREAN_KERNEL_KIND_SPK: u32 = 0;
15pub const EMPYREAN_KERNEL_KIND_BPC: u32 = 1;
16pub const EMPYREAN_KERNEL_KIND_TPC: u32 = 2;
17pub const EMPYREAN_KERNEL_KIND_GRAVITY: u32 = 3;
18pub const EMPYREAN_KERNEL_KIND_OBSCODES: u32 = 4;
19pub const EMPYREAN_KERNEL_PROVENANCE_FILE: u32 = 0;
20pub const EMPYREAN_KERNEL_PROVENANCE_IN_MEMORY: u32 = 1;
21pub const EMPYREAN_KERNEL_PROVENANCE_BUILT_IN: u32 = 2;
22pub const EMPYREAN_RADAR_KIND_DELAY: u32 = 0;
23pub const EMPYREAN_RADAR_KIND_DOPPLER: u32 = 1;
24pub const EMPYREAN_COVARIANCE_TRUST_NOT_EVALUATED: i32 = 0;
25pub const EMPYREAN_COVARIANCE_TRUST_TRUSTED: i32 = 1;
26pub const EMPYREAN_COVARIANCE_TRUST_ENCOUNTER_INTERVENES: i32 = 2;
27pub const EMPYREAN_COVARIANCE_TRUST_WEAKLY_DETERMINED_HIGH_N: i32 = 3;
28pub const EMPYREAN_TRUST_EVENT_NONE: i32 = 0;
29pub const EMPYREAN_TRUST_EVENT_CLOSE_APPROACH: i32 = 1;
30pub const EMPYREAN_TRUST_EVENT_HIGH_NONLINEARITY: i32 = 2;
31pub const EMPYREAN_REJECTION_ACCEPTED: u32 = 0;
32pub const EMPYREAN_REJECTION_CHI_SQUARED: u32 = 1;
33pub const EMPYREAN_REJECTION_SIGMA_CLIP: u32 = 2;
34pub const EMPYREAN_REJECTION_COOKS_DISTANCE: u32 = 3;
35pub const EMPYREAN_REJECTION_ADAPTIVE: u32 = 4;
36pub const EMPYREAN_REJECTION_UNSUPPORTED_OBSERVATORY: u32 = 5;
37pub const EMPYREAN_REJECTION_CMC2003: u32 = 6;
38pub const EMPYREAN_REJECTION_RADAR_UNSUPPORTED: u32 = 7;
39pub const EMPYREAN_REJECTION_OCCULTATION_UNSUPPORTED: u32 = 8;
40pub const EMPYREAN_REJECTION_OUTSIDE_ARC: u32 = 9;
41pub const EMPYREAN_REJECTION_NOT_EVALUATED: i32 = -1;
42pub const EMPYREAN_REJECTION_KIND_ADAPTIVE: u32 = 0;
43pub const EMPYREAN_REJECTION_KIND_CMC2003: u32 = 1;
44pub const EMPYREAN_WEIGHTING_PRESET_NONE: u32 = 0;
45pub const EMPYREAN_WEIGHTING_PRESET_VFC17: u32 = 1;
46pub const EMPYREAN_WEIGHTING_PRESET_NEODYS: u32 = 2;
47pub const EMPYREAN_SIGMA_POLICY_DEFAULT_ONLY: u32 = 0;
48pub const EMPYREAN_SIGMA_POLICY_FLOOR: u32 = 1;
49pub const EMPYREAN_WEIGHTING_LAYER_OBSERVATORY_RULE: u32 = 0;
50pub const EMPYREAN_WEIGHTING_LAYER_NIGHTLY_DEWEIGHTING: u32 = 1;
51pub const EMPYREAN_DEBIASING_TABLE_EFCC2020: u32 = 0;
52pub const EMPYREAN_DEBIASING_RESOLUTION_STANDARD: u32 = 0;
53pub const EMPYREAN_DEBIASING_RESOLUTION_HIRES: u32 = 1;
54pub const EMPYREAN_SOLVE_FOR_STATE_ONLY: u32 = 0;
55pub const EMPYREAN_SOLVE_FOR_STATE_AND_NONGRAV: u32 = 1;
56pub const EMPYREAN_SOLVE_FOR_AUTO: u32 = 2;
57pub const EMPYREAN_SOLVE_FOR_EXPLICIT: u32 = 3;
58pub const EMPYREAN_SOLVE_WIDTH: u32 = 20;
59pub const EMPYREAN_SLOT_NONE: u32 = 4294967295;
60pub const EMPYREAN_PHOTOMETRY_MODEL_AUTO: u32 = 0;
61pub const EMPYREAN_PHOTOMETRY_MODEL_HONLY: u32 = 1;
62pub const EMPYREAN_PHOTOMETRY_MODEL_HG: u32 = 2;
63pub const EMPYREAN_PHOTOMETRY_MODEL_HG12: u32 = 3;
64pub const EMPYREAN_PHOTOMETRY_MODEL_HG1G2: u32 = 4;
65pub const EMPYREAN_ABI_VERSION: u32 = 2;
66pub const EMPYREAN_ORIGIN_POLICY_AUTO: u32 = 0;
67pub const EMPYREAN_ORIGIN_POLICY_EXPLICIT: u32 = 1;
68pub const EMPYREAN_OUTPUT_EPOCH_MID_ARC: u32 = 0;
69pub const EMPYREAN_OUTPUT_EPOCH_LAST_OBSERVATION: u32 = 1;
70pub const EMPYREAN_OUTPUT_EPOCH_EXPLICIT: u32 = 2;
71pub const EMPYREAN_OUTPUT_EPOCH_IOD_EPOCH: u32 = 3;
72pub const EMPYREAN_REPRESENTATION_CARTESIAN: u32 = 0;
73pub const EMPYREAN_REPRESENTATION_KEPLERIAN: u32 = 1;
74pub const EMPYREAN_REPRESENTATION_COMETARY: u32 = 2;
75pub const EMPYREAN_REPRESENTATION_SPHERICAL: u32 = 3;
76pub const EMPYREAN_PHASE_FUNCTION_NONE: i32 = -1;
77pub const EMPYREAN_PHASE_FUNCTION_HG: u32 = 0;
78pub const EMPYREAN_PHASE_FUNCTION_HG1G2: u32 = 1;
79pub const EMPYREAN_PHASE_FUNCTION_HG12: u32 = 2;
80pub const EMPYREAN_STEERING_LAW_CONSTANT_RTN: u32 = 0;
81pub const EMPYREAN_STEERING_LAW_VELOCITY_TANGENT: u32 = 1;
82pub const EMPYREAN_STEERING_LAW_INERTIAL_FIXED: u32 = 2;
83pub const EMPYREAN_INTEGRATOR_GR15: u32 = 0;
84pub const EMPYREAN_INTEGRATOR_DOP853: u32 = 1;
85pub const EMPYREAN_ORIGIN_SWITCHING_DEFAULT: u32 = 0;
86pub const EMPYREAN_ORIGIN_SWITCHING_ON: u32 = 1;
87pub const EMPYREAN_ORIGIN_SWITCHING_OFF: u32 = 2;
88pub const EMPYREAN_UNCERTAINTY_FIRST: u32 = 0;
89pub const EMPYREAN_UNCERTAINTY_SECOND: u32 = 1;
90pub const EMPYREAN_UNCERTAINTY_SIGMA_POINT: u32 = 2;
91pub const EMPYREAN_UNCERTAINTY_MONTE_CARLO: u32 = 3;
92pub const EMPYREAN_UNCERTAINTY_AUTO: u32 = 4;
93pub const EMPYREAN_COVARIANCE_KIND_LINEAR: u32 = 0;
94pub const EMPYREAN_COVARIANCE_KIND_SECOND_ORDER: u32 = 1;
95pub const EMPYREAN_COVARIANCE_KIND_THIRD_ORDER: u32 = 2;
96pub const EMPYREAN_COVARIANCE_KIND_MIXTURE: u32 = 3;
97pub const EMPYREAN_COVARIANCE_KIND_MONTE_CARLO: u32 = 4;
98pub const EMPYREAN_COVARIANCE_KIND_SIGMA_POINT: u32 = 5;
99pub const EMPYREAN_COVARIANCE_QUALITY_POSITIVE_DEFINITE: u32 = 0;
100pub const EMPYREAN_COVARIANCE_QUALITY_INDEFINITE: u32 = 1;
101pub const EMPYREAN_COVARIANCE_QUALITY_REPAIRED: u32 = 2;
102pub const EMPYREAN_TARGET_FUNCTIONAL_CARTESIAN_STATE: u32 = 0;
103pub const EMPYREAN_TARGET_FUNCTIONAL_CLOSE_APPROACH_MISS_DISTANCE: u32 = 1;
104pub const EMPYREAN_TAGGED_COV_OK: u32 = 0;
105pub const EMPYREAN_TAGGED_COV_NULL_POINTER: i32 = -1;
106pub const EMPYREAN_TAGGED_COV_ORBIT_INDEX_OUT_OF_RANGE: i32 = -2;
107pub const EMPYREAN_TAGGED_COV_NO_INITIAL_COVARIANCE: i32 = -3;
108pub const EMPYREAN_TAGGED_COV_NO_DENSE_TRAJECTORY: i32 = -4;
109pub const EMPYREAN_TAGGED_COV_STATE_MISSING: i32 = -5;
110pub const EMPYREAN_TAGGED_COV_TRANSFORM: i32 = -6;
111pub const EMPYREAN_TAGGED_COV_UNCERTAINTY: i32 = -7;
112pub const EMPYREAN_TAGGED_COV_EPOCH_INDEX_OUT_OF_RANGE: i32 = -8;
113pub const EMPYREAN_TAGGED_COV_SAMPLE_COVARIANCE_MISSING: i32 = -9;
114pub const EMPYREAN_TAGGED_COV_PANIC: i32 = -99;
115#[repr(C)]
116#[derive(Debug, Copy, Clone)]
117pub struct Context {
118    _unused: [u8; 0],
119}
120#[repr(C)]
121#[derive(Debug, Copy, Clone)]
122pub struct Session {
123    _unused: [u8; 0],
124}
125#[doc = " Opaque handle wrapping a pre-assembled force model plus the\n kernel-identity snapshot taken from the context at construction (so\n [`empyrean_builtsystem_describe`] is self-contained). Construct with\n [`empyrean_builtsystem_new`]; release with [`empyrean_builtsystem_free`].\n\n The handle is `Send + Sync`: hand `&EmpyreanBuiltSystem` (via a `const`\n pointer) to as many threads as you like. It borrows nothing from the\n context after construction."]
126#[repr(C)]
127#[derive(Debug, Copy, Clone)]
128pub struct EmpyreanBuiltSystem {
129    _unused: [u8; 0],
130}
131#[doc = " C FFI opaque handle. Internally an [`empyrean_core::Context`]; the\n C header forward-declares `struct EmpyreanContext` — callers only\n see the pointer."]
132pub type EmpyreanContext = Context;
133#[doc = " Per-crate version strings reported by the empyrean stack.\n\n Mirrors [`empyrean_core::Versions`]. Each pointer is a heap-allocated\n NUL-terminated UTF-8 string owned by [`EmpyreanVersions`]; release\n the whole struct with [`empyrean_versions_free`] (do not free the\n individual fields with [`empyrean_string_free`])."]
134#[repr(C)]
135#[derive(Debug, Copy, Clone)]
136pub struct EmpyreanVersions {
137    #[doc = " `empyrean-core` crate version (semver string from `Cargo.toml`)."]
138    pub empyrean_core: *mut ::std::os::raw::c_char,
139    #[doc = " `villeneuve` crate version (`<tag>+<sha>` git-populated)."]
140    pub villeneuve: *mut ::std::os::raw::c_char,
141    #[doc = " `scott` crate version (`<tag>+<sha>` git-populated)."]
142    pub scott: *mut ::std::os::raw::c_char,
143    #[doc = " `nolan` crate version (`<tag>+<sha>` git-populated)."]
144    pub nolan: *mut ::std::os::raw::c_char,
145}
146#[allow(clippy::unnecessary_operation, clippy::identity_op)]
147const _: () = {
148    ["Size of EmpyreanVersions"][::std::mem::size_of::<EmpyreanVersions>() - 32usize];
149    ["Alignment of EmpyreanVersions"][::std::mem::align_of::<EmpyreanVersions>() - 8usize];
150    ["Offset of field: EmpyreanVersions::empyrean_core"]
151        [::std::mem::offset_of!(EmpyreanVersions, empyrean_core) - 0usize];
152    ["Offset of field: EmpyreanVersions::villeneuve"]
153        [::std::mem::offset_of!(EmpyreanVersions, villeneuve) - 8usize];
154    ["Offset of field: EmpyreanVersions::scott"]
155        [::std::mem::offset_of!(EmpyreanVersions, scott) - 16usize];
156    ["Offset of field: EmpyreanVersions::nolan"]
157        [::std::mem::offset_of!(EmpyreanVersions, nolan) - 24usize];
158};
159impl Default for EmpyreanVersions {
160    fn default() -> Self {
161        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
162        unsafe {
163            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
164            s.assume_init()
165        }
166    }
167}
168#[doc = " Flat C-ABI compatible coordinate state.\n\n Field-identical to [`empyrean_core::convert::CoordinateState`]; the\n duplicate definition exists so cbindgen (which has `parse_deps =\n false`) can emit the matching C struct in `empyrean.h` without\n traversing into the empyrean-core crate."]
169#[repr(C)]
170#[derive(Debug, Default, Copy, Clone)]
171pub struct CoordinateState {
172    pub epoch_mjd_tdb: f64,
173    pub elements: [f64; 6usize],
174    pub covariance: [[f64; 6usize]; 6usize],
175    pub has_covariance: u8,
176    pub representation: i32,
177    pub frame: i32,
178    pub origin: i32,
179}
180#[allow(clippy::unnecessary_operation, clippy::identity_op)]
181const _: () = {
182    ["Size of CoordinateState"][::std::mem::size_of::<CoordinateState>() - 360usize];
183    ["Alignment of CoordinateState"][::std::mem::align_of::<CoordinateState>() - 8usize];
184    ["Offset of field: CoordinateState::epoch_mjd_tdb"]
185        [::std::mem::offset_of!(CoordinateState, epoch_mjd_tdb) - 0usize];
186    ["Offset of field: CoordinateState::elements"]
187        [::std::mem::offset_of!(CoordinateState, elements) - 8usize];
188    ["Offset of field: CoordinateState::covariance"]
189        [::std::mem::offset_of!(CoordinateState, covariance) - 56usize];
190    ["Offset of field: CoordinateState::has_covariance"]
191        [::std::mem::offset_of!(CoordinateState, has_covariance) - 344usize];
192    ["Offset of field: CoordinateState::representation"]
193        [::std::mem::offset_of!(CoordinateState, representation) - 348usize];
194    ["Offset of field: CoordinateState::frame"]
195        [::std::mem::offset_of!(CoordinateState, frame) - 352usize];
196    ["Offset of field: CoordinateState::origin"]
197        [::std::mem::offset_of!(CoordinateState, origin) - 356usize];
198};
199#[doc = " A single continuous-thrust arc, mirroring\n [`empyrean_core::nongrav::ThrustArc`] as a flat `#[repr(C)]` record.\n\n Arcs are supplied through [`EmpyreanOrbit::thrust_arcs`] as a\n caller-owned side array borrowed read-only for the duration of the call.\n\n The acceleration during the arc is\n \\\\[ \\mathbf{a}(t) = \\sigma(t)\\,\\frac{F}{m(t)}\\,\\hat{d} \\\\]\n with a smooth \\\\(\\tanh\\\\) switch \\\\(\\sigma(t)\\\\) of width set by\n `sharpness`, steering direction \\\\(\\hat{d}\\\\) from `steering_law`, and\n mass \\\\(m(t)\\\\) that depletes when `isp_s` is finite."]
200#[repr(C)]
201#[derive(Debug, Default, Copy, Clone)]
202pub struct EmpyreanThrustArc {
203    #[doc = " Arc start epoch (MJD TDB)."]
204    pub start_mjd_tdb: f64,
205    #[doc = " Arc end epoch (MJD TDB)."]
206    pub end_mjd_tdb: f64,
207    #[doc = " Engine thrust force in Newtons."]
208    pub thrust_n: f64,
209    #[doc = " Spacecraft mass at arc start in kilograms."]
210    pub mass_kg: f64,
211    #[doc = " Specific impulse in seconds. Any non-finite value (`NaN` or `±∞`)\n selects constant mass (no depletion); a finite value depletes mass at\n \\\\(\\dot m = F/(I_{sp} g_0)\\\\). This is the `Option<f64>` NaN-sentinel\n convention shared with [`EmpyreanOrbit::non_grav_dt`]."]
212    pub isp_s: f64,
213    #[doc = " Steering-law selector — see the `EMPYREAN_STEERING_LAW_*` tag\n constants. An unrecognized value errors loudly."]
214    pub steering_law: i32,
215    #[doc = " `CONSTANT_RTN` in-plane angle α from radial toward transverse\n (radians). Read only when `steering_law == CONSTANT_RTN`."]
216    pub steering_alpha_rad: f64,
217    #[doc = " `CONSTANT_RTN` out-of-plane angle β toward orbit normal (radians).\n Read only when `steering_law == CONSTANT_RTN`."]
218    pub steering_beta_rad: f64,
219    #[doc = " `INERTIAL_FIXED` direction vector (normalized internally). Read only\n when `steering_law == INERTIAL_FIXED`."]
220    pub steering_direction: [f64; 3usize],
221    #[doc = " \\\\(\\tanh\\\\) switching sharpness (1/days). Higher = sharper on/off."]
222    pub sharpness: f64,
223    #[doc = " Central-body NAIF id for the RTN / velocity-tangent frame reference\n (same encoding as [`EmpyreanOrbit`]'s `state.origin`, e.g. `399` for\n Earth, `10` for the Sun). An unknown NAIF id errors loudly."]
224    pub central_body_naif_id: i32,
225}
226#[allow(clippy::unnecessary_operation, clippy::identity_op)]
227const _: () = {
228    ["Size of EmpyreanThrustArc"][::std::mem::size_of::<EmpyreanThrustArc>() - 104usize];
229    ["Alignment of EmpyreanThrustArc"][::std::mem::align_of::<EmpyreanThrustArc>() - 8usize];
230    ["Offset of field: EmpyreanThrustArc::start_mjd_tdb"]
231        [::std::mem::offset_of!(EmpyreanThrustArc, start_mjd_tdb) - 0usize];
232    ["Offset of field: EmpyreanThrustArc::end_mjd_tdb"]
233        [::std::mem::offset_of!(EmpyreanThrustArc, end_mjd_tdb) - 8usize];
234    ["Offset of field: EmpyreanThrustArc::thrust_n"]
235        [::std::mem::offset_of!(EmpyreanThrustArc, thrust_n) - 16usize];
236    ["Offset of field: EmpyreanThrustArc::mass_kg"]
237        [::std::mem::offset_of!(EmpyreanThrustArc, mass_kg) - 24usize];
238    ["Offset of field: EmpyreanThrustArc::isp_s"]
239        [::std::mem::offset_of!(EmpyreanThrustArc, isp_s) - 32usize];
240    ["Offset of field: EmpyreanThrustArc::steering_law"]
241        [::std::mem::offset_of!(EmpyreanThrustArc, steering_law) - 40usize];
242    ["Offset of field: EmpyreanThrustArc::steering_alpha_rad"]
243        [::std::mem::offset_of!(EmpyreanThrustArc, steering_alpha_rad) - 48usize];
244    ["Offset of field: EmpyreanThrustArc::steering_beta_rad"]
245        [::std::mem::offset_of!(EmpyreanThrustArc, steering_beta_rad) - 56usize];
246    ["Offset of field: EmpyreanThrustArc::steering_direction"]
247        [::std::mem::offset_of!(EmpyreanThrustArc, steering_direction) - 64usize];
248    ["Offset of field: EmpyreanThrustArc::sharpness"]
249        [::std::mem::offset_of!(EmpyreanThrustArc, sharpness) - 88usize];
250    ["Offset of field: EmpyreanThrustArc::central_body_naif_id"]
251        [::std::mem::offset_of!(EmpyreanThrustArc, central_body_naif_id) - 96usize];
252};
253#[doc = " An orbit with optional non-gravitational parameters, continuous-thrust\n arcs, and photometry.\n\n Thrust: when `n_thrust_arcs > 0`, [`thrust_arcs`](Self::thrust_arcs)\n (plus the optional [`dv_corrections`](Self::dv_corrections) /\n [`correction_covariances`](Self::correction_covariances) side arrays)\n build a [`ThrustParams`] for this orbit. All-zero `a1/a2/a3` and\n `n_thrust_arcs == 0` is a pure-gravity orbit.\n\n `a1/a2/a3` are the Marsden–Sekanina RTN coefficients (radial,\n transverse, normal) in AU/day². `ng_alpha … ng_k` parameterize the\n g(r) distance-dependent scaling:\n \\\\[ g(r) = \\alpha \\\\, (r/r_0)^{-m} \\\\, (1 + (r/r_0)^n)^{-k} \\\\].\n All-zeros for the g-function fields selects the inverse-square\n default (Yarkovsky / SRP asteroid case): \\\\(\\alpha = r_0 = 1\\\\),\n \\\\(m = 2\\\\), \\\\(n = k = 0\\\\). Comets typically pass SBDB's\n Marsden water-ice values\n (\\\\(\\alpha = 0.1113, r_0 = 2.808, m = 2.15, n = 5.093, k = 4.6142\\\\)).\n\n Photometry: when `phot_system` is one of the `EMPYREAN_PHASE_FUNCTION_*`\n non-`NONE` constants, ephemeris generation produces apparent magnitude\n using the (`H`, `slope1`, `slope2`) triple per the chosen phase function:\n\n | Model | `H` | `slope1` | `slope2` |\n |-------|-----|----------|----------|\n | `HG`     | absolute magnitude | G    | unused (0)  |\n | `HG1G2`  | absolute magnitude | G₁   | G₂          |\n | `HG12`   | absolute magnitude | G₁₂  | unused (0)  |"]
254#[repr(C)]
255#[derive(Debug, Copy, Clone)]
256pub struct EmpyreanOrbit {
257    pub state: CoordinateState,
258    #[doc = " Caller-supplied orbit identifier — primary key for joining\n outputs (propagated states, events, ephemeris, B-planes, IP) to\n the input row. NUL-terminated UTF-8. A null pointer or empty\n string causes the C ABI to fabricate a positional `\"orbit_{i}\"`\n tag instead — set this whenever you want stable joins.\n\n **Ownership:** read-only borrow from the caller; the C ABI does\n not free it."]
259    pub orbit_id: *const ::std::os::raw::c_char,
260    #[doc = " Caller-supplied object identifier (e.g. SBDB designation).\n Distinct from `orbit_id` so multiple orbit hypotheses for the\n same object can share an `object_id`. NUL-terminated UTF-8.\n Empty string or null = no object identifier.\n\n **Ownership:** read-only borrow from the caller; the C ABI does\n not free it."]
261    pub object_id: *const ::std::os::raw::c_char,
262    #[doc = " Marsden-Sekanina A1 coefficient (radial). 0 ⇒ no non-grav."]
263    pub a1: f64,
264    #[doc = " Marsden-Sekanina A2 coefficient (transverse)."]
265    pub a2: f64,
266    #[doc = " Marsden-Sekanina A3 coefficient (normal)."]
267    pub a3: f64,
268    #[doc = " g(r) normalizing constant α. All-zero g-fields → inverse_square."]
269    pub ng_alpha: f64,
270    #[doc = " g(r) reference distance r₀ (AU)."]
271    pub ng_r0: f64,
272    #[doc = " g(r) inner power-law exponent m."]
273    pub ng_m: f64,
274    #[doc = " g(r) outer power-law exponent n."]
275    pub ng_n: f64,
276    #[doc = " g(r) outer damping exponent k."]
277    pub ng_k: f64,
278    #[doc = " SBDB non-grav time delay in days. Use NaN for no delay (the\n asteroid default and the Marsden water-ice default for comets\n SBDB doesn't fit a delay for). Set to a finite value (positive\n or negative) when SBDB's `model_pars[]` exposes a `DT` field —\n e.g. 67P (+45.7d), 46P/Wirtanen (−14.1d), 2I/Borisov (−65.1d)."]
279    pub non_grav_dt: f64,
280    #[doc = " Prior variance on the non-grav time delay DT (days²). NaN or ≤0 = no\n prior; a finite positive value opens + priors the DT column in a\n StateAndNonGravAndDT fit."]
281    pub non_grav_dt_variance: f64,
282    #[doc = " 1 when `non_grav_covariance` carries a non-grav prior covariance; 0\n otherwise. Set by the OD output path (a fitted orbit) so it re-feeds\n into a StateAndNonGrav refine without losing its non-grav prior;\n leave 0 for hand-built / SBDB / propagate inputs."]
283    pub has_non_grav_covariance: u8,
284    #[doc = " Non-grav 3×3 covariance for (A1, A2, A3), row-major. Only read when\n `has_non_grav_covariance = 1`."]
285    pub non_grav_covariance: [[f64; 3usize]; 3usize],
286    #[doc = " Phase-function model. `EMPYREAN_PHASE_FUNCTION_NONE` disables\n magnitude computation; the other values map to villeneuve's\n `PhaseFunction` enum."]
287    pub phot_system: i32,
288    #[doc = " Absolute magnitude H. Ignored when `phot_system == NONE`."]
289    pub h_mag: f64,
290    #[doc = " Slope parameter slot 1 — G (HG), G₁ (HG1G2), or G₁₂ (HG12)."]
291    pub slope1: f64,
292    #[doc = " Slope parameter slot 2 — G₂ (HG1G2 only); unused (0) for HG / HG12."]
293    pub slope2: f64,
294    #[doc = " Continuous-thrust arcs (variable length). Null / `n_thrust_arcs == 0`\n ⇒ no thrust (gravity + non-grav only).\n\n **Ownership:** caller-owned; borrowed read-only for the duration of\n the call. The C ABI never frees it. A null pointer with\n `n_thrust_arcs > 0` is a loud argument error, not a silent skip; a\n non-null pointer with `n_thrust_arcs == 0` is treated as absent (the\n pointer is not read)."]
295    pub thrust_arcs: *const EmpyreanThrustArc,
296    #[doc = " Number of arcs in [`thrust_arcs`](Self::thrust_arcs)."]
297    pub n_thrust_arcs: usize,
298    #[doc = " Optional per-arc Δv corrections (AU/day), positional with\n [`thrust_arcs`](Self::thrust_arcs). Null / `n_dv_corrections == 0` ⇒\n no targeting corrections. Supplying corrections without any arc is a\n loud argument error.\n\n **Ownership:** caller-owned; borrowed read-only for the call."]
299    pub dv_corrections: *const [f64; 3usize],
300    #[doc = " Number of corrections in [`dv_corrections`](Self::dv_corrections)."]
301    pub n_dv_corrections: usize,
302    #[doc = " Optional 3×3 covariance (AU/day)² per Δv correction, positional with\n [`dv_corrections`](Self::dv_corrections). When non-empty its length\n MUST equal `n_dv_corrections`; a non-empty covariance triggers the\n wide-Jet burn-sensitivity propagation. The engine's higher-order\n (third-order) propagation path does not implement thrust-correction\n covariance and rejects that combination loudly upstream\n (`Not implemented: … ThirdOrder with thrust-correction covariance …`,\n surfaced as a propagation error) rather than silently dropping the\n covariance.\n\n **Ownership:** caller-owned; borrowed read-only for the call."]
303    pub correction_covariances: *const [[f64; 3usize]; 3usize],
304    #[doc = " Number of entries in\n [`correction_covariances`](Self::correction_covariances)."]
305    pub n_correction_covariances: usize,
306    #[doc = " 1 when this orbit carries a solar-radiation-pressure force slot\n (`srp_amrat` + `srp_cr`); 0 otherwise. SRP is **never** value-inferred\n — this explicit switch is the only trigger."]
307    pub has_srp: u8,
308    #[doc = " Area-to-mass ratio AMRAT (m²/kg) — the SRP-effective, fittable\n parameter. Only read when `has_srp == 1`; must be finite and > 0."]
309    pub srp_amrat: f64,
310    #[doc = " Radiation-pressure coefficient Cr. Fixed, never fitted. Only read\n when `has_srp == 1`; must be finite and > 0."]
311    pub srp_cr: f64,
312    #[doc = " Prior variance on AMRAT ((m²/kg)²). NaN or ≤0 = no prior; a finite\n positive value opens + priors the AMRAT column in a StateAndAMRAT /\n StateAndNonGravAndAMRAT fit. Only read when `has_srp == 1`."]
313    pub srp_amrat_variance: f64,
314}
315#[allow(clippy::unnecessary_operation, clippy::identity_op)]
316const _: () = {
317    ["Size of EmpyreanOrbit"][::std::mem::size_of::<EmpyreanOrbit>() - 648usize];
318    ["Alignment of EmpyreanOrbit"][::std::mem::align_of::<EmpyreanOrbit>() - 8usize];
319    ["Offset of field: EmpyreanOrbit::state"]
320        [::std::mem::offset_of!(EmpyreanOrbit, state) - 0usize];
321    ["Offset of field: EmpyreanOrbit::orbit_id"]
322        [::std::mem::offset_of!(EmpyreanOrbit, orbit_id) - 360usize];
323    ["Offset of field: EmpyreanOrbit::object_id"]
324        [::std::mem::offset_of!(EmpyreanOrbit, object_id) - 368usize];
325    ["Offset of field: EmpyreanOrbit::a1"][::std::mem::offset_of!(EmpyreanOrbit, a1) - 376usize];
326    ["Offset of field: EmpyreanOrbit::a2"][::std::mem::offset_of!(EmpyreanOrbit, a2) - 384usize];
327    ["Offset of field: EmpyreanOrbit::a3"][::std::mem::offset_of!(EmpyreanOrbit, a3) - 392usize];
328    ["Offset of field: EmpyreanOrbit::ng_alpha"]
329        [::std::mem::offset_of!(EmpyreanOrbit, ng_alpha) - 400usize];
330    ["Offset of field: EmpyreanOrbit::ng_r0"]
331        [::std::mem::offset_of!(EmpyreanOrbit, ng_r0) - 408usize];
332    ["Offset of field: EmpyreanOrbit::ng_m"]
333        [::std::mem::offset_of!(EmpyreanOrbit, ng_m) - 416usize];
334    ["Offset of field: EmpyreanOrbit::ng_n"]
335        [::std::mem::offset_of!(EmpyreanOrbit, ng_n) - 424usize];
336    ["Offset of field: EmpyreanOrbit::ng_k"]
337        [::std::mem::offset_of!(EmpyreanOrbit, ng_k) - 432usize];
338    ["Offset of field: EmpyreanOrbit::non_grav_dt"]
339        [::std::mem::offset_of!(EmpyreanOrbit, non_grav_dt) - 440usize];
340    ["Offset of field: EmpyreanOrbit::non_grav_dt_variance"]
341        [::std::mem::offset_of!(EmpyreanOrbit, non_grav_dt_variance) - 448usize];
342    ["Offset of field: EmpyreanOrbit::has_non_grav_covariance"]
343        [::std::mem::offset_of!(EmpyreanOrbit, has_non_grav_covariance) - 456usize];
344    ["Offset of field: EmpyreanOrbit::non_grav_covariance"]
345        [::std::mem::offset_of!(EmpyreanOrbit, non_grav_covariance) - 464usize];
346    ["Offset of field: EmpyreanOrbit::phot_system"]
347        [::std::mem::offset_of!(EmpyreanOrbit, phot_system) - 536usize];
348    ["Offset of field: EmpyreanOrbit::h_mag"]
349        [::std::mem::offset_of!(EmpyreanOrbit, h_mag) - 544usize];
350    ["Offset of field: EmpyreanOrbit::slope1"]
351        [::std::mem::offset_of!(EmpyreanOrbit, slope1) - 552usize];
352    ["Offset of field: EmpyreanOrbit::slope2"]
353        [::std::mem::offset_of!(EmpyreanOrbit, slope2) - 560usize];
354    ["Offset of field: EmpyreanOrbit::thrust_arcs"]
355        [::std::mem::offset_of!(EmpyreanOrbit, thrust_arcs) - 568usize];
356    ["Offset of field: EmpyreanOrbit::n_thrust_arcs"]
357        [::std::mem::offset_of!(EmpyreanOrbit, n_thrust_arcs) - 576usize];
358    ["Offset of field: EmpyreanOrbit::dv_corrections"]
359        [::std::mem::offset_of!(EmpyreanOrbit, dv_corrections) - 584usize];
360    ["Offset of field: EmpyreanOrbit::n_dv_corrections"]
361        [::std::mem::offset_of!(EmpyreanOrbit, n_dv_corrections) - 592usize];
362    ["Offset of field: EmpyreanOrbit::correction_covariances"]
363        [::std::mem::offset_of!(EmpyreanOrbit, correction_covariances) - 600usize];
364    ["Offset of field: EmpyreanOrbit::n_correction_covariances"]
365        [::std::mem::offset_of!(EmpyreanOrbit, n_correction_covariances) - 608usize];
366    ["Offset of field: EmpyreanOrbit::has_srp"]
367        [::std::mem::offset_of!(EmpyreanOrbit, has_srp) - 616usize];
368    ["Offset of field: EmpyreanOrbit::srp_amrat"]
369        [::std::mem::offset_of!(EmpyreanOrbit, srp_amrat) - 624usize];
370    ["Offset of field: EmpyreanOrbit::srp_cr"]
371        [::std::mem::offset_of!(EmpyreanOrbit, srp_cr) - 632usize];
372    ["Offset of field: EmpyreanOrbit::srp_amrat_variance"]
373        [::std::mem::offset_of!(EmpyreanOrbit, srp_amrat_variance) - 640usize];
374};
375impl Default for EmpyreanOrbit {
376    fn default() -> Self {
377        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
378        unsafe {
379            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
380            s.assume_init()
381        }
382    }
383}
384#[doc = " Uncertainty-propagation method, mirroring\n [`empyrean_core::propagation::UncertaintyMethod`] as a flat C struct.\n Fields outside the active variant are ignored — set them to zero /\n NaN.\n\n | tag | Variant | Active fields |\n |-----|---------|---------------|\n | 0   | First       | (none) |\n | 1   | Second      | (none) |\n | 2   | SigmaPoint  | `sp_n_sigma`, `sp_samples_per_plane` |\n | 3   | MonteCarlo  | `mc_n_samples`, `mc_seed_some` (1 = use `mc_seed`) |\n | 4   | Auto        | `auto_threshold_first`, `auto_threshold_mixture`, `auto_threshold_ip_skip`, `auto_gmm_max_depth`, `auto_gmm_components_per_split` |"]
385#[repr(C)]
386#[derive(Debug, Default, Copy, Clone)]
387pub struct EmpyreanUncertaintyMethod {
388    #[doc = " Variant tag — see `EMPYREAN_UNCERTAINTY_*` constants."]
389    pub tag: u8,
390    #[doc = " SigmaPoint: number of sigma deviations (default 1.0)."]
391    pub sp_n_sigma: f64,
392    #[doc = " SigmaPoint: points per coordinate-plane pair (default 8 → 120 total)."]
393    pub sp_samples_per_plane: u64,
394    #[doc = " MonteCarlo: number of random samples."]
395    pub mc_n_samples: u64,
396    #[doc = " MonteCarlo: 1 if `mc_seed` is set, 0 to draw from `thread_rng`."]
397    pub mc_seed_some: u8,
398    #[doc = " MonteCarlo: RNG seed when `mc_seed_some == 1`."]
399    pub mc_seed: u64,
400    #[doc = " Auto: first-order regime tuning parameter."]
401    pub auto_threshold_first: f64,
402    #[doc = " Auto: adaptive-mixture regime tuning parameter."]
403    pub auto_threshold_mixture: f64,
404    #[doc = " Auto: impact-probability tuning parameter for the higher-order pass."]
405    pub auto_threshold_ip_skip: f64,
406    #[doc = " Auto: adaptive-Gaussian-mixture maximum recursion depth."]
407    pub auto_gmm_max_depth: u64,
408    #[doc = " Auto: adaptive-Gaussian-mixture components per split (odd)."]
409    pub auto_gmm_components_per_split: u64,
410}
411#[allow(clippy::unnecessary_operation, clippy::identity_op)]
412const _: () = {
413    ["Size of EmpyreanUncertaintyMethod"]
414        [::std::mem::size_of::<EmpyreanUncertaintyMethod>() - 88usize];
415    ["Alignment of EmpyreanUncertaintyMethod"]
416        [::std::mem::align_of::<EmpyreanUncertaintyMethod>() - 8usize];
417    ["Offset of field: EmpyreanUncertaintyMethod::tag"]
418        [::std::mem::offset_of!(EmpyreanUncertaintyMethod, tag) - 0usize];
419    ["Offset of field: EmpyreanUncertaintyMethod::sp_n_sigma"]
420        [::std::mem::offset_of!(EmpyreanUncertaintyMethod, sp_n_sigma) - 8usize];
421    ["Offset of field: EmpyreanUncertaintyMethod::sp_samples_per_plane"]
422        [::std::mem::offset_of!(EmpyreanUncertaintyMethod, sp_samples_per_plane) - 16usize];
423    ["Offset of field: EmpyreanUncertaintyMethod::mc_n_samples"]
424        [::std::mem::offset_of!(EmpyreanUncertaintyMethod, mc_n_samples) - 24usize];
425    ["Offset of field: EmpyreanUncertaintyMethod::mc_seed_some"]
426        [::std::mem::offset_of!(EmpyreanUncertaintyMethod, mc_seed_some) - 32usize];
427    ["Offset of field: EmpyreanUncertaintyMethod::mc_seed"]
428        [::std::mem::offset_of!(EmpyreanUncertaintyMethod, mc_seed) - 40usize];
429    ["Offset of field: EmpyreanUncertaintyMethod::auto_threshold_first"]
430        [::std::mem::offset_of!(EmpyreanUncertaintyMethod, auto_threshold_first) - 48usize];
431    ["Offset of field: EmpyreanUncertaintyMethod::auto_threshold_mixture"]
432        [::std::mem::offset_of!(EmpyreanUncertaintyMethod, auto_threshold_mixture) - 56usize];
433    ["Offset of field: EmpyreanUncertaintyMethod::auto_threshold_ip_skip"]
434        [::std::mem::offset_of!(EmpyreanUncertaintyMethod, auto_threshold_ip_skip) - 64usize];
435    ["Offset of field: EmpyreanUncertaintyMethod::auto_gmm_max_depth"]
436        [::std::mem::offset_of!(EmpyreanUncertaintyMethod, auto_gmm_max_depth) - 72usize];
437    ["Offset of field: EmpyreanUncertaintyMethod::auto_gmm_components_per_split"][::std::mem::offset_of!(
438        EmpyreanUncertaintyMethod,
439        auto_gmm_components_per_split
440    ) - 80usize];
441};
442#[doc = " Event-detection configuration. Mirrors\n [`villeneuve::events::EventConfig`] (less the `enrichment` sub-config,\n which carries internal nested data that doesn't translate cleanly\n through C — it always uses upstream defaults).\n\n `body_filter_naif` is non-owning: caller must keep the array alive\n for the duration of the propagation call. Pass `null` /\n `num_body_filter = 0` to monitor all bodies."]
443#[repr(C)]
444#[derive(Debug, Copy, Clone)]
445pub struct EmpyreanEventConfig {
446    pub close_approaches: u8,
447    pub impacts: u8,
448    pub atmospheric: u8,
449    pub possible_impacts: u8,
450    pub shadow_events: u8,
451    #[doc = " Number of NAIF IDs in [`body_filter_naif`]; 0 = monitor all bodies."]
452    pub num_body_filter: usize,
453    #[doc = " Pointer to `num_body_filter` NAIF IDs to restrict event monitoring."]
454    pub body_filter_naif: *const i32,
455    #[doc = " Insert dense output points around close approaches. 1 = on (auto-enables\n `cache_integrator_steps`), 0 = off (default)."]
456    pub dense_output: u8,
457    #[doc = " Cadence (days) of dense output. 0.0 → upstream default (5 minutes)."]
458    pub dense_output_cadence_days: f64,
459}
460#[allow(clippy::unnecessary_operation, clippy::identity_op)]
461const _: () = {
462    ["Size of EmpyreanEventConfig"][::std::mem::size_of::<EmpyreanEventConfig>() - 40usize];
463    ["Alignment of EmpyreanEventConfig"][::std::mem::align_of::<EmpyreanEventConfig>() - 8usize];
464    ["Offset of field: EmpyreanEventConfig::close_approaches"]
465        [::std::mem::offset_of!(EmpyreanEventConfig, close_approaches) - 0usize];
466    ["Offset of field: EmpyreanEventConfig::impacts"]
467        [::std::mem::offset_of!(EmpyreanEventConfig, impacts) - 1usize];
468    ["Offset of field: EmpyreanEventConfig::atmospheric"]
469        [::std::mem::offset_of!(EmpyreanEventConfig, atmospheric) - 2usize];
470    ["Offset of field: EmpyreanEventConfig::possible_impacts"]
471        [::std::mem::offset_of!(EmpyreanEventConfig, possible_impacts) - 3usize];
472    ["Offset of field: EmpyreanEventConfig::shadow_events"]
473        [::std::mem::offset_of!(EmpyreanEventConfig, shadow_events) - 4usize];
474    ["Offset of field: EmpyreanEventConfig::num_body_filter"]
475        [::std::mem::offset_of!(EmpyreanEventConfig, num_body_filter) - 8usize];
476    ["Offset of field: EmpyreanEventConfig::body_filter_naif"]
477        [::std::mem::offset_of!(EmpyreanEventConfig, body_filter_naif) - 16usize];
478    ["Offset of field: EmpyreanEventConfig::dense_output"]
479        [::std::mem::offset_of!(EmpyreanEventConfig, dense_output) - 24usize];
480    ["Offset of field: EmpyreanEventConfig::dense_output_cadence_days"]
481        [::std::mem::offset_of!(EmpyreanEventConfig, dense_output_cadence_days) - 32usize];
482};
483impl Default for EmpyreanEventConfig {
484    fn default() -> Self {
485        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
486        unsafe {
487            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
488            s.assume_init()
489        }
490    }
491}
492#[doc = " Per-trajectory diagnostic outputs (sensitivity, nonlinearity, …).\n Mirrors [`villeneuve::diagnostics::DiagnosticsConfig`].\n\n All metrics default to off. Sentinel: `0` for `sample_stride` →\n upstream default (1); a NaN threshold means \"no event emission for\n that metric\"."]
493#[repr(C)]
494#[derive(Debug, Default, Copy, Clone)]
495pub struct EmpyreanDiagnosticsConfig {
496    #[doc = " Frobenius norm of position-STM block. 1 = on, 0 = off."]
497    pub sensitivity: u8,
498    #[doc = " Hessian/gradient ratio (Jet2 only). 1 = on, 0 = off."]
499    pub nonlinearity: u8,
500    #[doc = " Finite-time Lyapunov exponent. 1 = on, 0 = off."]
501    pub lyapunov: u8,
502    #[doc = " Keyhole detection at close approaches (Jet1+). 1 = on, 0 = off."]
503    pub keyholes: u8,
504    #[doc = " Bifurcation detection at close approaches (Jet2 only). 1 = on, 0 = off."]
505    pub bifurcations: u8,
506    #[doc = " Timeseries sampling stride: every Nth integration step. 0 → upstream default (1)."]
507    pub sample_stride: usize,
508    #[doc = " Threshold for `HighSensitivity` events. NaN → no emission."]
509    pub sensitivity_threshold: f64,
510    #[doc = " Threshold for `ChaoticRegion` events. NaN → no emission."]
511    pub lyapunov_threshold: f64,
512    #[doc = " Threshold for `HighNonlinearity` events (Jet2 only). NaN → no emission."]
513    pub nonlinearity_threshold: f64,
514}
515#[allow(clippy::unnecessary_operation, clippy::identity_op)]
516const _: () = {
517    ["Size of EmpyreanDiagnosticsConfig"]
518        [::std::mem::size_of::<EmpyreanDiagnosticsConfig>() - 40usize];
519    ["Alignment of EmpyreanDiagnosticsConfig"]
520        [::std::mem::align_of::<EmpyreanDiagnosticsConfig>() - 8usize];
521    ["Offset of field: EmpyreanDiagnosticsConfig::sensitivity"]
522        [::std::mem::offset_of!(EmpyreanDiagnosticsConfig, sensitivity) - 0usize];
523    ["Offset of field: EmpyreanDiagnosticsConfig::nonlinearity"]
524        [::std::mem::offset_of!(EmpyreanDiagnosticsConfig, nonlinearity) - 1usize];
525    ["Offset of field: EmpyreanDiagnosticsConfig::lyapunov"]
526        [::std::mem::offset_of!(EmpyreanDiagnosticsConfig, lyapunov) - 2usize];
527    ["Offset of field: EmpyreanDiagnosticsConfig::keyholes"]
528        [::std::mem::offset_of!(EmpyreanDiagnosticsConfig, keyholes) - 3usize];
529    ["Offset of field: EmpyreanDiagnosticsConfig::bifurcations"]
530        [::std::mem::offset_of!(EmpyreanDiagnosticsConfig, bifurcations) - 4usize];
531    ["Offset of field: EmpyreanDiagnosticsConfig::sample_stride"]
532        [::std::mem::offset_of!(EmpyreanDiagnosticsConfig, sample_stride) - 8usize];
533    ["Offset of field: EmpyreanDiagnosticsConfig::sensitivity_threshold"]
534        [::std::mem::offset_of!(EmpyreanDiagnosticsConfig, sensitivity_threshold) - 16usize];
535    ["Offset of field: EmpyreanDiagnosticsConfig::lyapunov_threshold"]
536        [::std::mem::offset_of!(EmpyreanDiagnosticsConfig, lyapunov_threshold) - 24usize];
537    ["Offset of field: EmpyreanDiagnosticsConfig::nonlinearity_threshold"]
538        [::std::mem::offset_of!(EmpyreanDiagnosticsConfig, nonlinearity_threshold) - 32usize];
539};
540#[doc = " Origin-switching configuration for trajectory splitting at body\n Laplace spheres of influence (Amato/Baù/Bombardelli 2017 §6).\n\n Default **enabled** (the `_DEFAULT` sentinel resolves to\n `enabled = 1`). When enabled, integration switches to a\n body-centric frame inside the SOI of each eligible body and back\n to SSB on exit. Set `enabled = 0` explicitly to opt out.\n\n At the C-ABI surface, the per-body opt-in list (`bodies` in\n villeneuve) is not yet exposed — `EMPYREAN_ORIGIN_SWITCHING_ON`\n selects all monitored bodies. File a request if per-body scoping\n is needed from the C-ABI surface."]
541#[repr(C)]
542#[derive(Debug, Default, Copy, Clone)]
543pub struct EmpyreanOriginSwitchingConfig {
544    #[doc = " Trajectory-splitting policy. Tri-state, see\n `EMPYREAN_ORIGIN_SWITCHING_*` constants:\n - `0 = DEFAULT` — use the upstream default (currently `ON`).\n   This is what `memset(0)` gives, matching the same sentinel\n   convention used for `dt_min` / `dt_initial` / `epsilon` /\n   `hysteresis` etc. — external C consumers can zero-init the\n   config struct and get the right behavior automatically.\n - `1 = ON`  — force trajectory-splitting on (matches the prior\n   semantic for `enabled = 1`, backward-compatible).\n - `2 = OFF` — force trajectory-splitting off. (The prior\n   semantic for `enabled = 0` is now reachable only via this\n   explicit value, since 0 now means DEFAULT.)\n\n Unknown values fall back to the upstream default."]
545    pub enabled: u8,
546    #[doc = " Fractional band around the acceleration-ratio crossover used\n to suppress chatter (default 0.2 = ±20 %). 0.0 → upstream\n default."]
547    pub hysteresis: f64,
548}
549#[allow(clippy::unnecessary_operation, clippy::identity_op)]
550const _: () = {
551    ["Size of EmpyreanOriginSwitchingConfig"]
552        [::std::mem::size_of::<EmpyreanOriginSwitchingConfig>() - 16usize];
553    ["Alignment of EmpyreanOriginSwitchingConfig"]
554        [::std::mem::align_of::<EmpyreanOriginSwitchingConfig>() - 8usize];
555    ["Offset of field: EmpyreanOriginSwitchingConfig::enabled"]
556        [::std::mem::offset_of!(EmpyreanOriginSwitchingConfig, enabled) - 0usize];
557    ["Offset of field: EmpyreanOriginSwitchingConfig::hysteresis"]
558        [::std::mem::offset_of!(EmpyreanOriginSwitchingConfig, hysteresis) - 8usize];
559};
560#[doc = " Integrator tuning. Mirrors\n [`villeneuve::propagation::AdvancedIntegratorConfig`]. The default\n integrator backend is Gauss-Radau 15 (GR15), derived solely from the\n published papers; `epsilon` is interpreted as the relative b₆\n truncation tolerance.\n\n Sentinel rule: `0.0` requests the upstream default for `epsilon` /\n `encounter_timescale_divisor`; `dt_initial` / `dt_min` use NaN to\n mean \"auto-compute\"; `0` requests the upstream defaults for\n `max_steps` and `max_dense_steps`."]
561#[repr(C)]
562#[derive(Debug, Default, Copy, Clone)]
563pub struct EmpyreanAdvancedIntegratorConfig {
564    #[doc = " Integrator backend (0 = GR15 default, 1 = DOP853). See\n `EMPYREAN_INTEGRATOR_*` constants."]
565    pub integrator: i32,
566    #[doc = " Truncation-error tolerance (relative b₆ for GR15, rtol for\n DOP853 paired with a fixed atol = 1e-14). 0.0 → upstream\n default (1e-9)."]
567    pub epsilon: f64,
568    #[doc = " Initial step size in days. NaN → auto from orbital timescale."]
569    pub dt_initial: f64,
570    #[doc = " Minimum allowed step size in days. NaN → auto."]
571    pub dt_min: f64,
572    #[doc = " Encounter dynamical-timescale step floor divisor. 0.0 → upstream default (1000.0)."]
573    pub encounter_timescale_divisor: f64,
574    #[doc = " Maximum integration steps before aborting. 0 → upstream default (10_000_000)."]
575    pub max_steps: usize,
576    #[doc = " Memory cap on the per-step b-coefficient cache. 0 → upstream default (100_000)."]
577    pub max_dense_steps: usize,
578    #[doc = " Cache the integrator's per-step b-coefficients for fast\n interpolation (light-time iteration, dense output around close\n approaches, arbitrary-epoch state queries). 1 = on, 0 = off\n (default)."]
579    pub cache_integrator_steps: u8,
580    #[doc = " Origin-switching trajectory-splitting configuration. Default\n enabled."]
581    pub origin_switching: EmpyreanOriginSwitchingConfig,
582}
583#[allow(clippy::unnecessary_operation, clippy::identity_op)]
584const _: () = {
585    ["Size of EmpyreanAdvancedIntegratorConfig"]
586        [::std::mem::size_of::<EmpyreanAdvancedIntegratorConfig>() - 80usize];
587    ["Alignment of EmpyreanAdvancedIntegratorConfig"]
588        [::std::mem::align_of::<EmpyreanAdvancedIntegratorConfig>() - 8usize];
589    ["Offset of field: EmpyreanAdvancedIntegratorConfig::integrator"]
590        [::std::mem::offset_of!(EmpyreanAdvancedIntegratorConfig, integrator) - 0usize];
591    ["Offset of field: EmpyreanAdvancedIntegratorConfig::epsilon"]
592        [::std::mem::offset_of!(EmpyreanAdvancedIntegratorConfig, epsilon) - 8usize];
593    ["Offset of field: EmpyreanAdvancedIntegratorConfig::dt_initial"]
594        [::std::mem::offset_of!(EmpyreanAdvancedIntegratorConfig, dt_initial) - 16usize];
595    ["Offset of field: EmpyreanAdvancedIntegratorConfig::dt_min"]
596        [::std::mem::offset_of!(EmpyreanAdvancedIntegratorConfig, dt_min) - 24usize];
597    ["Offset of field: EmpyreanAdvancedIntegratorConfig::encounter_timescale_divisor"][::std::mem::offset_of!(
598        EmpyreanAdvancedIntegratorConfig,
599        encounter_timescale_divisor
600    ) - 32usize];
601    ["Offset of field: EmpyreanAdvancedIntegratorConfig::max_steps"]
602        [::std::mem::offset_of!(EmpyreanAdvancedIntegratorConfig, max_steps) - 40usize];
603    ["Offset of field: EmpyreanAdvancedIntegratorConfig::max_dense_steps"]
604        [::std::mem::offset_of!(EmpyreanAdvancedIntegratorConfig, max_dense_steps) - 48usize];
605    ["Offset of field: EmpyreanAdvancedIntegratorConfig::cache_integrator_steps"][::std::mem::offset_of!(
606        EmpyreanAdvancedIntegratorConfig,
607        cache_integrator_steps
608    ) - 56usize];
609    ["Offset of field: EmpyreanAdvancedIntegratorConfig::origin_switching"]
610        [::std::mem::offset_of!(EmpyreanAdvancedIntegratorConfig, origin_switching) - 64usize];
611};
612#[doc = " Propagation configuration.\n\n Mirrors [`villeneuve::propagation::PropagationConfig`] structurally:\n shared scalar fields at the top, nested config bundles for events,\n diagnostics, and integrator tuning. Sentinel rule for primitive\n fields: `0` / `0.0` requests the upstream default; documented\n negative-value sentinels retain their special meanings.\n\n `stop_condition` and `events.enrichment` are not exposed at this\n surface — both carry internal nested data that doesn't translate\n cleanly. They use upstream defaults; reach for empyrean-core's\n Rust API when they need to be overridden."]
613#[repr(C)]
614#[derive(Debug, Copy, Clone)]
615pub struct EmpyreanPropagationConfig {
616    #[doc = " Force-model tier: 0=Approximate, 1=Basic, 2=Standard."]
617    pub force_model: i32,
618    #[doc = " Number of `excluded_perturbers` in [`excluded_perturbers_naif`]; 0 = none."]
619    pub num_excluded_perturbers: usize,
620    #[doc = " NAIF IDs to exclude (self-perturbation avoidance for SB441-N16\n bodies). Non-owning. Pass `null` / count 0 to use the full\n perturber set."]
621    pub excluded_perturbers_naif: *const i32,
622    #[doc = " Uncertainty-propagation method (tag + per-variant params)."]
623    pub uncertainty_method: EmpyreanUncertaintyMethod,
624    #[doc = " Force `Jet1<6>` integration even without input covariance.\n 1 = on, 0 = off (default)."]
625    pub compute_stm: u8,
626    #[doc = " Output reference frame: 0=ICRF, 1=EclipticJ2000."]
627    pub frame: i32,
628    pub events: EmpyreanEventConfig,
629    pub diagnostics: EmpyreanDiagnosticsConfig,
630    #[doc = " Threads for multi-orbit propagation. 0 = use all cores\n (Rayon default); positive N = exactly N cores."]
631    pub num_threads: usize,
632    pub advanced: EmpyreanAdvancedIntegratorConfig,
633}
634#[allow(clippy::unnecessary_operation, clippy::identity_op)]
635const _: () = {
636    ["Size of EmpyreanPropagationConfig"]
637        [::std::mem::size_of::<EmpyreanPropagationConfig>() - 288usize];
638    ["Alignment of EmpyreanPropagationConfig"]
639        [::std::mem::align_of::<EmpyreanPropagationConfig>() - 8usize];
640    ["Offset of field: EmpyreanPropagationConfig::force_model"]
641        [::std::mem::offset_of!(EmpyreanPropagationConfig, force_model) - 0usize];
642    ["Offset of field: EmpyreanPropagationConfig::num_excluded_perturbers"]
643        [::std::mem::offset_of!(EmpyreanPropagationConfig, num_excluded_perturbers) - 8usize];
644    ["Offset of field: EmpyreanPropagationConfig::excluded_perturbers_naif"]
645        [::std::mem::offset_of!(EmpyreanPropagationConfig, excluded_perturbers_naif) - 16usize];
646    ["Offset of field: EmpyreanPropagationConfig::uncertainty_method"]
647        [::std::mem::offset_of!(EmpyreanPropagationConfig, uncertainty_method) - 24usize];
648    ["Offset of field: EmpyreanPropagationConfig::compute_stm"]
649        [::std::mem::offset_of!(EmpyreanPropagationConfig, compute_stm) - 112usize];
650    ["Offset of field: EmpyreanPropagationConfig::frame"]
651        [::std::mem::offset_of!(EmpyreanPropagationConfig, frame) - 116usize];
652    ["Offset of field: EmpyreanPropagationConfig::events"]
653        [::std::mem::offset_of!(EmpyreanPropagationConfig, events) - 120usize];
654    ["Offset of field: EmpyreanPropagationConfig::diagnostics"]
655        [::std::mem::offset_of!(EmpyreanPropagationConfig, diagnostics) - 160usize];
656    ["Offset of field: EmpyreanPropagationConfig::num_threads"]
657        [::std::mem::offset_of!(EmpyreanPropagationConfig, num_threads) - 200usize];
658    ["Offset of field: EmpyreanPropagationConfig::advanced"]
659        [::std::mem::offset_of!(EmpyreanPropagationConfig, advanced) - 208usize];
660};
661impl Default for EmpyreanPropagationConfig {
662    fn default() -> Self {
663        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
664        unsafe {
665            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
666            s.assume_init()
667        }
668    }
669}
670#[doc = " A single propagated Cartesian state."]
671#[repr(C)]
672#[derive(Debug, Default, Copy, Clone)]
673pub struct EmpyreanPropagatedState {
674    pub epoch_mjd_tdb: f64,
675    pub x: f64,
676    pub y: f64,
677    pub z: f64,
678    pub vx: f64,
679    pub vy: f64,
680    pub vz: f64,
681    pub origin: i32,
682    pub frame: i32,
683    pub covariance: [[f64; 6usize]; 6usize],
684    pub has_covariance: u8,
685    #[doc = " State Transition Matrix Φ(t, t₀). Zero-filled when `has_stm` is 0."]
686    pub stm: [[f64; 6usize]; 6usize],
687    pub has_stm: u8,
688    #[doc = " State Transition Tensor Ψ(t, t₀). Zero-filled when `has_stt` is 0."]
689    pub stt: [[[f64; 6usize]; 6usize]; 6usize],
690    pub has_stt: u8,
691    #[doc = " Resolved [`CovarianceKind`](empyrean_core::propagation::CovarianceKind)\n at this output epoch — see `EMPYREAN_COVARIANCE_KIND_*`.\n Defaults to `LINEAR` for non-Auto methods and for Auto epochs\n outside CA windows."]
692    pub resolved_kind: u8,
693}
694#[allow(clippy::unnecessary_operation, clippy::identity_op)]
695const _: () = {
696    ["Size of EmpyreanPropagatedState"]
697        [::std::mem::size_of::<EmpyreanPropagatedState>() - 2392usize];
698    ["Alignment of EmpyreanPropagatedState"]
699        [::std::mem::align_of::<EmpyreanPropagatedState>() - 8usize];
700    ["Offset of field: EmpyreanPropagatedState::epoch_mjd_tdb"]
701        [::std::mem::offset_of!(EmpyreanPropagatedState, epoch_mjd_tdb) - 0usize];
702    ["Offset of field: EmpyreanPropagatedState::x"]
703        [::std::mem::offset_of!(EmpyreanPropagatedState, x) - 8usize];
704    ["Offset of field: EmpyreanPropagatedState::y"]
705        [::std::mem::offset_of!(EmpyreanPropagatedState, y) - 16usize];
706    ["Offset of field: EmpyreanPropagatedState::z"]
707        [::std::mem::offset_of!(EmpyreanPropagatedState, z) - 24usize];
708    ["Offset of field: EmpyreanPropagatedState::vx"]
709        [::std::mem::offset_of!(EmpyreanPropagatedState, vx) - 32usize];
710    ["Offset of field: EmpyreanPropagatedState::vy"]
711        [::std::mem::offset_of!(EmpyreanPropagatedState, vy) - 40usize];
712    ["Offset of field: EmpyreanPropagatedState::vz"]
713        [::std::mem::offset_of!(EmpyreanPropagatedState, vz) - 48usize];
714    ["Offset of field: EmpyreanPropagatedState::origin"]
715        [::std::mem::offset_of!(EmpyreanPropagatedState, origin) - 56usize];
716    ["Offset of field: EmpyreanPropagatedState::frame"]
717        [::std::mem::offset_of!(EmpyreanPropagatedState, frame) - 60usize];
718    ["Offset of field: EmpyreanPropagatedState::covariance"]
719        [::std::mem::offset_of!(EmpyreanPropagatedState, covariance) - 64usize];
720    ["Offset of field: EmpyreanPropagatedState::has_covariance"]
721        [::std::mem::offset_of!(EmpyreanPropagatedState, has_covariance) - 352usize];
722    ["Offset of field: EmpyreanPropagatedState::stm"]
723        [::std::mem::offset_of!(EmpyreanPropagatedState, stm) - 360usize];
724    ["Offset of field: EmpyreanPropagatedState::has_stm"]
725        [::std::mem::offset_of!(EmpyreanPropagatedState, has_stm) - 648usize];
726    ["Offset of field: EmpyreanPropagatedState::stt"]
727        [::std::mem::offset_of!(EmpyreanPropagatedState, stt) - 656usize];
728    ["Offset of field: EmpyreanPropagatedState::has_stt"]
729        [::std::mem::offset_of!(EmpyreanPropagatedState, has_stt) - 2384usize];
730    ["Offset of field: EmpyreanPropagatedState::resolved_kind"]
731        [::std::mem::offset_of!(EmpyreanPropagatedState, resolved_kind) - 2385usize];
732};
733#[doc = " A detected dynamical event from propagation.\n\n For `event_type = \"covariance_regime_change\"` the audit-trail\n fields (`previous_kind`, `resolved_kind`, `kappa`,\n `threshold_below`, `threshold_above`) carry the\n [`CovarianceRegimeChange`](empyrean_core::propagation::events::DynamicalEvent::CovarianceRegimeChange)\n payload and the body / distance / velocity fields are zeroed\n (regime changes don't carry a body or geometry — they're audit\n markers from\n [`UncertaintyMethod::Auto`](empyrean_core::propagation::UncertaintyMethod::Auto)).\n For all other events these fields are sentinel-filled\n (`0xFF` / NaN).\n\n Field names mirror empyrean-core's variant fields for the\n regime-change payload — no per-variant prefix."]
734#[repr(C)]
735#[derive(Debug, Copy, Clone)]
736pub struct EmpyreanEvent {
737    pub event_type: *mut ::std::os::raw::c_char,
738    pub orbit_id: *mut ::std::os::raw::c_char,
739    #[doc = " Object identifier looked up by `orbit_id` from the input batch.\n Empty string when the input had no `object_id`. Owning C string —\n caller frees via `*_result_free`."]
740    pub object_id: *mut ::std::os::raw::c_char,
741    pub body: *mut ::std::os::raw::c_char,
742    pub body_naif_id: i32,
743    pub epoch_mjd_tdb: f64,
744    pub distance_au: f64,
745    pub distance_km: f64,
746    pub relative_velocity_au_day: f64,
747    #[doc = " `CovarianceRegimeChange` payload: previous resolved kind.\n Sentinel `0xFF` for non-regime events."]
748    pub previous_kind: u8,
749    #[doc = " `CovarianceRegimeChange` payload: new resolved kind.\n Sentinel `0xFF` for non-regime events."]
750    pub resolved_kind: u8,
751    #[doc = " `CovarianceRegimeChange` payload: local nonlinearity κ\n recorded at the CA. NaN for non-regime events."]
752    pub kappa: f64,
753    #[doc = " `CovarianceRegimeChange` payload: lower κ value recorded in\n this audit payload. NaN for non-regime events."]
754    pub threshold_below: f64,
755    #[doc = " `CovarianceRegimeChange` payload: upper κ value recorded in\n this audit payload. NaN for non-regime events."]
756    pub threshold_above: f64,
757    #[doc = " `CaptureStart` / `CaptureEnd` payload: two-body energy w.r.t. the\n capturing body (AU²/day²). NaN for non-capture events."]
758    pub two_body_energy: f64,
759    #[doc = " `CaptureStart` / `CaptureEnd` payload: Jacobi constant in the\n CR3BP. NaN for non-capture events or when unavailable."]
760    pub jacobi_constant: f64,
761    #[doc = " `CaptureStart` / `CaptureEnd` payload: 1σ uncertainty on the\n Jacobi constant. NaN when unavailable."]
762    pub jacobi_constant_sigma: f64,
763    #[doc = " `CaptureStart` / `CaptureEnd` payload: Jacobi constant at the L1\n gateway. NaN when unavailable."]
764    pub jacobi_constant_l1: f64,
765    #[doc = " `CaptureStart` / `CaptureEnd` payload: Jacobi constant at the L2\n gateway. NaN when unavailable."]
766    pub jacobi_constant_l2: f64,
767    #[doc = " `CaptureEnd` payload: number of periapsis passages during the\n temporary capture. `-1` sentinel for non-`CaptureEnd` events."]
768    pub n_periapses: i32,
769    #[doc = " `Impact` payload: planetodetic latitude of the surface intercept\n (degrees). NaN for non-impact events or when unresolved."]
770    pub impact_latitude_deg: f64,
771    #[doc = " `Impact` payload: planetodetic longitude of the surface intercept\n (degrees). NaN for non-impact events or when unresolved."]
772    pub impact_longitude_deg: f64,
773    #[doc = " `Impact` payload: altitude of the surface intercept above the\n reference ellipsoid (km). NaN for non-impact events or when\n unresolved."]
774    pub impact_altitude_km: f64,
775    #[doc = " `ShadowEntry` / `ShadowExit` payload: fraction of the Sun's disk\n occulted by the body (0 = none, 1 = full umbra). NaN for\n non-shadow events."]
776    pub shadow_fraction: f64,
777    #[doc = " `ShadowEntry` / `ShadowExit` payload: fraction of incident\n sunlight reaching the particle (1 = full sun, 0 = total eclipse).\n NaN for non-shadow events."]
778    pub illumination: f64,
779    #[doc = " `Periapsis` payload: relative position w.r.t. the approached body\n (AU), components x/y/z. NaN for non-periapsis events."]
780    pub relative_x: f64,
781    pub relative_y: f64,
782    pub relative_z: f64,
783    #[doc = " `Periapsis` payload: relative velocity w.r.t. the approached body\n (AU/day), components vx/vy/vz. NaN for non-periapsis events."]
784    pub relative_vx: f64,
785    pub relative_vy: f64,
786    pub relative_vz: f64,
787    #[doc = " `PossibleImpact` payload: effective capture radius with\n gravitational focusing (AU / km). NaN for non-possible-impact events."]
788    pub effective_radius_au: f64,
789    pub effective_radius_km: f64,
790    #[doc = " `PossibleImpact` payload: 1σ uncertainty along the miss direction\n (AU). NaN for non-possible-impact events."]
791    pub sigma_distance_au: f64,
792    #[doc = " `PossibleImpact` payload: linear (STM-mapped) impact probability.\n NaN for non-possible-impact events."]
793    pub ip_linear: f64,
794    #[doc = " `PossibleImpact` payload: second-order (Edgeworth) impact\n probability. NaN for non-possible-impact / first-order runs."]
795    pub ip_second_order: f64,
796    #[doc = " `PossibleImpact` payload: local nonlinearity κ at the encounter.\n NaN when unavailable."]
797    pub nonlinearity: f64,
798    #[doc = " `PossibleImpact` payload: adaptive-Gaussian-mixture impact\n probability. NaN when not an AGM run."]
799    pub ip_agm: f64,
800    #[doc = " `PossibleImpact` payload: Monte-Carlo impact probability. NaN when\n not a Monte-Carlo run."]
801    pub ip_mc: f64,
802}
803#[allow(clippy::unnecessary_operation, clippy::identity_op)]
804const _: () = {
805    ["Size of EmpyreanEvent"][::std::mem::size_of::<EmpyreanEvent>() - 304usize];
806    ["Alignment of EmpyreanEvent"][::std::mem::align_of::<EmpyreanEvent>() - 8usize];
807    ["Offset of field: EmpyreanEvent::event_type"]
808        [::std::mem::offset_of!(EmpyreanEvent, event_type) - 0usize];
809    ["Offset of field: EmpyreanEvent::orbit_id"]
810        [::std::mem::offset_of!(EmpyreanEvent, orbit_id) - 8usize];
811    ["Offset of field: EmpyreanEvent::object_id"]
812        [::std::mem::offset_of!(EmpyreanEvent, object_id) - 16usize];
813    ["Offset of field: EmpyreanEvent::body"][::std::mem::offset_of!(EmpyreanEvent, body) - 24usize];
814    ["Offset of field: EmpyreanEvent::body_naif_id"]
815        [::std::mem::offset_of!(EmpyreanEvent, body_naif_id) - 32usize];
816    ["Offset of field: EmpyreanEvent::epoch_mjd_tdb"]
817        [::std::mem::offset_of!(EmpyreanEvent, epoch_mjd_tdb) - 40usize];
818    ["Offset of field: EmpyreanEvent::distance_au"]
819        [::std::mem::offset_of!(EmpyreanEvent, distance_au) - 48usize];
820    ["Offset of field: EmpyreanEvent::distance_km"]
821        [::std::mem::offset_of!(EmpyreanEvent, distance_km) - 56usize];
822    ["Offset of field: EmpyreanEvent::relative_velocity_au_day"]
823        [::std::mem::offset_of!(EmpyreanEvent, relative_velocity_au_day) - 64usize];
824    ["Offset of field: EmpyreanEvent::previous_kind"]
825        [::std::mem::offset_of!(EmpyreanEvent, previous_kind) - 72usize];
826    ["Offset of field: EmpyreanEvent::resolved_kind"]
827        [::std::mem::offset_of!(EmpyreanEvent, resolved_kind) - 73usize];
828    ["Offset of field: EmpyreanEvent::kappa"]
829        [::std::mem::offset_of!(EmpyreanEvent, kappa) - 80usize];
830    ["Offset of field: EmpyreanEvent::threshold_below"]
831        [::std::mem::offset_of!(EmpyreanEvent, threshold_below) - 88usize];
832    ["Offset of field: EmpyreanEvent::threshold_above"]
833        [::std::mem::offset_of!(EmpyreanEvent, threshold_above) - 96usize];
834    ["Offset of field: EmpyreanEvent::two_body_energy"]
835        [::std::mem::offset_of!(EmpyreanEvent, two_body_energy) - 104usize];
836    ["Offset of field: EmpyreanEvent::jacobi_constant"]
837        [::std::mem::offset_of!(EmpyreanEvent, jacobi_constant) - 112usize];
838    ["Offset of field: EmpyreanEvent::jacobi_constant_sigma"]
839        [::std::mem::offset_of!(EmpyreanEvent, jacobi_constant_sigma) - 120usize];
840    ["Offset of field: EmpyreanEvent::jacobi_constant_l1"]
841        [::std::mem::offset_of!(EmpyreanEvent, jacobi_constant_l1) - 128usize];
842    ["Offset of field: EmpyreanEvent::jacobi_constant_l2"]
843        [::std::mem::offset_of!(EmpyreanEvent, jacobi_constant_l2) - 136usize];
844    ["Offset of field: EmpyreanEvent::n_periapses"]
845        [::std::mem::offset_of!(EmpyreanEvent, n_periapses) - 144usize];
846    ["Offset of field: EmpyreanEvent::impact_latitude_deg"]
847        [::std::mem::offset_of!(EmpyreanEvent, impact_latitude_deg) - 152usize];
848    ["Offset of field: EmpyreanEvent::impact_longitude_deg"]
849        [::std::mem::offset_of!(EmpyreanEvent, impact_longitude_deg) - 160usize];
850    ["Offset of field: EmpyreanEvent::impact_altitude_km"]
851        [::std::mem::offset_of!(EmpyreanEvent, impact_altitude_km) - 168usize];
852    ["Offset of field: EmpyreanEvent::shadow_fraction"]
853        [::std::mem::offset_of!(EmpyreanEvent, shadow_fraction) - 176usize];
854    ["Offset of field: EmpyreanEvent::illumination"]
855        [::std::mem::offset_of!(EmpyreanEvent, illumination) - 184usize];
856    ["Offset of field: EmpyreanEvent::relative_x"]
857        [::std::mem::offset_of!(EmpyreanEvent, relative_x) - 192usize];
858    ["Offset of field: EmpyreanEvent::relative_y"]
859        [::std::mem::offset_of!(EmpyreanEvent, relative_y) - 200usize];
860    ["Offset of field: EmpyreanEvent::relative_z"]
861        [::std::mem::offset_of!(EmpyreanEvent, relative_z) - 208usize];
862    ["Offset of field: EmpyreanEvent::relative_vx"]
863        [::std::mem::offset_of!(EmpyreanEvent, relative_vx) - 216usize];
864    ["Offset of field: EmpyreanEvent::relative_vy"]
865        [::std::mem::offset_of!(EmpyreanEvent, relative_vy) - 224usize];
866    ["Offset of field: EmpyreanEvent::relative_vz"]
867        [::std::mem::offset_of!(EmpyreanEvent, relative_vz) - 232usize];
868    ["Offset of field: EmpyreanEvent::effective_radius_au"]
869        [::std::mem::offset_of!(EmpyreanEvent, effective_radius_au) - 240usize];
870    ["Offset of field: EmpyreanEvent::effective_radius_km"]
871        [::std::mem::offset_of!(EmpyreanEvent, effective_radius_km) - 248usize];
872    ["Offset of field: EmpyreanEvent::sigma_distance_au"]
873        [::std::mem::offset_of!(EmpyreanEvent, sigma_distance_au) - 256usize];
874    ["Offset of field: EmpyreanEvent::ip_linear"]
875        [::std::mem::offset_of!(EmpyreanEvent, ip_linear) - 264usize];
876    ["Offset of field: EmpyreanEvent::ip_second_order"]
877        [::std::mem::offset_of!(EmpyreanEvent, ip_second_order) - 272usize];
878    ["Offset of field: EmpyreanEvent::nonlinearity"]
879        [::std::mem::offset_of!(EmpyreanEvent, nonlinearity) - 280usize];
880    ["Offset of field: EmpyreanEvent::ip_agm"]
881        [::std::mem::offset_of!(EmpyreanEvent, ip_agm) - 288usize];
882    ["Offset of field: EmpyreanEvent::ip_mc"]
883        [::std::mem::offset_of!(EmpyreanEvent, ip_mc) - 296usize];
884};
885impl Default for EmpyreanEvent {
886    fn default() -> Self {
887        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
888        unsafe {
889            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
890            s.assume_init()
891        }
892    }
893}
894#[doc = " One Gaussian sub-component of an AGM mixture decomposition.\n\n Mirrors\n [`empyrean_core::propagation::MixtureComponent`]. The mean carries\n the *propagated* sub-Gaussian centroid at the CA epoch (f64 from\n the Jet2 integrator); the covariance is the linearly-mapped\n \\\\(\\Phi \\, \\Sigma_k \\, \\Phi^\\top\\\\) over the same propagation\n segment. A consumer can evaluate\n \\\\(\\sum_k w_k \\\\, \\mathcal{N}(x \\mid \\mu_k, \\Sigma_k)\\\\) directly\n at the CA epoch.\n\n Each component is basis-tagged: `frame` / `origin` give the\n reference frame and center body its `mean` and `covariance` are\n expressed in, so the mixture is self-describing rather than relying\n on positional alignment with the propagated states."]
895#[repr(C)]
896#[derive(Debug, Default, Copy, Clone)]
897pub struct EmpyreanMixtureComponent {
898    pub weight: f64,
899    pub mean: [f64; 6usize],
900    pub covariance: [[f64; 6usize]; 6usize],
901    #[doc = " Reference frame `mean` / `covariance` are expressed in — the\n integration frame of the run. Same integer encoding as\n `EmpyreanPropagatedState.frame` (0 = ICRF, 1 = ecliptic J2000,\n 2 = ITRF93)."]
902    pub frame: i32,
903    #[doc = " Origin (center body) `mean` is expressed relative to, as a NAIF\n id — same encoding as `EmpyreanPropagatedState.origin`\n (e.g. 10 = Sun, 399 = Earth). Matches the propagation origin at\n the split's close-approach epoch, so it can differ between CA\n epochs of the same chain when origin switching occurred."]
904    pub origin: i32,
905}
906#[allow(clippy::unnecessary_operation, clippy::identity_op)]
907const _: () = {
908    ["Size of EmpyreanMixtureComponent"]
909        [::std::mem::size_of::<EmpyreanMixtureComponent>() - 352usize];
910    ["Alignment of EmpyreanMixtureComponent"]
911        [::std::mem::align_of::<EmpyreanMixtureComponent>() - 8usize];
912    ["Offset of field: EmpyreanMixtureComponent::weight"]
913        [::std::mem::offset_of!(EmpyreanMixtureComponent, weight) - 0usize];
914    ["Offset of field: EmpyreanMixtureComponent::mean"]
915        [::std::mem::offset_of!(EmpyreanMixtureComponent, mean) - 8usize];
916    ["Offset of field: EmpyreanMixtureComponent::covariance"]
917        [::std::mem::offset_of!(EmpyreanMixtureComponent, covariance) - 56usize];
918    ["Offset of field: EmpyreanMixtureComponent::frame"]
919        [::std::mem::offset_of!(EmpyreanMixtureComponent, frame) - 344usize];
920    ["Offset of field: EmpyreanMixtureComponent::origin"]
921        [::std::mem::offset_of!(EmpyreanMixtureComponent, origin) - 348usize];
922};
923#[doc = " Per-orbit AGM mixture decomposition retained by Auto / Mixture.\n\n Mirrors [`empyrean_core::propagation::MixtureChain`] in flat form.\n `ca_epochs_mjd_tdb` and `components_per_epoch` are\n `num_ca_epochs`-length parallel arrays. Components are flattened\n into a single `components` array — for CA index `k`, the slice is\n `components[components_offset[k] .. components_offset[k] +\n components_per_epoch[k]]`. `components_offset[k]` is the\n prefix-sum of `components_per_epoch[0..k]` (so\n `components_offset[0] == 0`).\n\n Only orbits whose AGM splits actually fired carry a chain;\n non-mixture orbits get one entry whose `num_ca_epochs == 0` and\n whose pointers are null."]
924#[repr(C)]
925#[derive(Debug, Copy, Clone)]
926pub struct EmpyreanMixtureChain {
927    #[doc = " Owning C string — caller frees via `*_result_free`."]
928    pub orbit_id: *mut ::std::os::raw::c_char,
929    #[doc = " `num_ca_epochs`-length array of CA epochs (mjd_tdb)."]
930    pub ca_epochs_mjd_tdb: *mut f64,
931    pub num_ca_epochs: usize,
932    #[doc = " `num_ca_epochs`-length array of per-epoch component counts."]
933    pub components_per_epoch: *mut usize,
934    #[doc = " `num_ca_epochs`-length array of starting offsets into the\n flattened `components` array. `components_offset[k]` is the\n prefix-sum of `components_per_epoch[0..k]`."]
935    pub components_offset: *mut usize,
936    #[doc = " Flattened components — total length =\n sum(components_per_epoch)."]
937    pub components: *mut EmpyreanMixtureComponent,
938    pub num_components_total: usize,
939}
940#[allow(clippy::unnecessary_operation, clippy::identity_op)]
941const _: () = {
942    ["Size of EmpyreanMixtureChain"][::std::mem::size_of::<EmpyreanMixtureChain>() - 56usize];
943    ["Alignment of EmpyreanMixtureChain"][::std::mem::align_of::<EmpyreanMixtureChain>() - 8usize];
944    ["Offset of field: EmpyreanMixtureChain::orbit_id"]
945        [::std::mem::offset_of!(EmpyreanMixtureChain, orbit_id) - 0usize];
946    ["Offset of field: EmpyreanMixtureChain::ca_epochs_mjd_tdb"]
947        [::std::mem::offset_of!(EmpyreanMixtureChain, ca_epochs_mjd_tdb) - 8usize];
948    ["Offset of field: EmpyreanMixtureChain::num_ca_epochs"]
949        [::std::mem::offset_of!(EmpyreanMixtureChain, num_ca_epochs) - 16usize];
950    ["Offset of field: EmpyreanMixtureChain::components_per_epoch"]
951        [::std::mem::offset_of!(EmpyreanMixtureChain, components_per_epoch) - 24usize];
952    ["Offset of field: EmpyreanMixtureChain::components_offset"]
953        [::std::mem::offset_of!(EmpyreanMixtureChain, components_offset) - 32usize];
954    ["Offset of field: EmpyreanMixtureChain::components"]
955        [::std::mem::offset_of!(EmpyreanMixtureChain, components) - 40usize];
956    ["Offset of field: EmpyreanMixtureChain::num_components_total"]
957        [::std::mem::offset_of!(EmpyreanMixtureChain, num_components_total) - 48usize];
958};
959impl Default for EmpyreanMixtureChain {
960    fn default() -> Self {
961        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
962        unsafe {
963            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
964            s.assume_init()
965        }
966    }
967}
968#[doc = " Propagation result containing states, events, and object identifiers.\n\n `mixtures` parallels `object_ids` only when populated — it is\n per-orbit (not per-state), so its length is the distinct orbit\n count, not `num_states`."]
969#[repr(C)]
970#[derive(Debug, Copy, Clone)]
971pub struct EmpyreanPropagationResult {
972    pub states: *mut EmpyreanPropagatedState,
973    pub num_states: usize,
974    pub object_ids: *mut *mut ::std::os::raw::c_char,
975    pub events: *mut EmpyreanEvent,
976    pub num_events: usize,
977    #[doc = " One [`EmpyreanMixtureChain`] per input orbit (positional with\n the input orbit batch). Empty / null when no orbits produced\n mixtures (the typical case for FirstOrder / SecondOrder /\n SigmaPoint / MonteCarlo)."]
978    pub mixtures: *mut EmpyreanMixtureChain,
979    pub num_mixtures: usize,
980    #[doc = " Opaque retained handle to the rich propagation result, enabling\n the on-demand tagged-covariance accessors\n (`empyrean_propagation_covariance_series_cartesian` /\n `_covariance_at_cartesian`). **Do not dereference from C** — it is\n freed by `empyrean_propagation_result_free`. Null when the\n propagation produced no retainable result."]
981    pub lazy_handle: *mut ::std::os::raw::c_void,
982}
983#[allow(clippy::unnecessary_operation, clippy::identity_op)]
984const _: () = {
985    ["Size of EmpyreanPropagationResult"]
986        [::std::mem::size_of::<EmpyreanPropagationResult>() - 64usize];
987    ["Alignment of EmpyreanPropagationResult"]
988        [::std::mem::align_of::<EmpyreanPropagationResult>() - 8usize];
989    ["Offset of field: EmpyreanPropagationResult::states"]
990        [::std::mem::offset_of!(EmpyreanPropagationResult, states) - 0usize];
991    ["Offset of field: EmpyreanPropagationResult::num_states"]
992        [::std::mem::offset_of!(EmpyreanPropagationResult, num_states) - 8usize];
993    ["Offset of field: EmpyreanPropagationResult::object_ids"]
994        [::std::mem::offset_of!(EmpyreanPropagationResult, object_ids) - 16usize];
995    ["Offset of field: EmpyreanPropagationResult::events"]
996        [::std::mem::offset_of!(EmpyreanPropagationResult, events) - 24usize];
997    ["Offset of field: EmpyreanPropagationResult::num_events"]
998        [::std::mem::offset_of!(EmpyreanPropagationResult, num_events) - 32usize];
999    ["Offset of field: EmpyreanPropagationResult::mixtures"]
1000        [::std::mem::offset_of!(EmpyreanPropagationResult, mixtures) - 40usize];
1001    ["Offset of field: EmpyreanPropagationResult::num_mixtures"]
1002        [::std::mem::offset_of!(EmpyreanPropagationResult, num_mixtures) - 48usize];
1003    ["Offset of field: EmpyreanPropagationResult::lazy_handle"]
1004        [::std::mem::offset_of!(EmpyreanPropagationResult, lazy_handle) - 56usize];
1005};
1006impl Default for EmpyreanPropagationResult {
1007    fn default() -> Self {
1008        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
1009        unsafe {
1010            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
1011            s.assume_init()
1012        }
1013    }
1014}
1015#[doc = " A single observer state for the C API."]
1016#[repr(C)]
1017#[derive(Debug, Default, Copy, Clone)]
1018pub struct EmpyreanObserver {
1019    #[doc = " MPC 3-character code, null-terminated (4 bytes)."]
1020    pub obs_code: [u8; 4usize],
1021    #[doc = " Epoch as MJD TDB."]
1022    pub epoch_mjd_tdb: f64,
1023    #[doc = " Position in ICRF relative to SSB (AU)."]
1024    pub x: f64,
1025    pub y: f64,
1026    pub z: f64,
1027    #[doc = " Velocity in ICRF relative to SSB (AU/day)."]
1028    pub vx: f64,
1029    pub vy: f64,
1030    pub vz: f64,
1031    #[doc = " Observing night as YYYYMMDD integer, or -1 if unavailable."]
1032    pub observing_night: i32,
1033}
1034#[allow(clippy::unnecessary_operation, clippy::identity_op)]
1035const _: () = {
1036    ["Size of EmpyreanObserver"][::std::mem::size_of::<EmpyreanObserver>() - 72usize];
1037    ["Alignment of EmpyreanObserver"][::std::mem::align_of::<EmpyreanObserver>() - 8usize];
1038    ["Offset of field: EmpyreanObserver::obs_code"]
1039        [::std::mem::offset_of!(EmpyreanObserver, obs_code) - 0usize];
1040    ["Offset of field: EmpyreanObserver::epoch_mjd_tdb"]
1041        [::std::mem::offset_of!(EmpyreanObserver, epoch_mjd_tdb) - 8usize];
1042    ["Offset of field: EmpyreanObserver::x"][::std::mem::offset_of!(EmpyreanObserver, x) - 16usize];
1043    ["Offset of field: EmpyreanObserver::y"][::std::mem::offset_of!(EmpyreanObserver, y) - 24usize];
1044    ["Offset of field: EmpyreanObserver::z"][::std::mem::offset_of!(EmpyreanObserver, z) - 32usize];
1045    ["Offset of field: EmpyreanObserver::vx"]
1046        [::std::mem::offset_of!(EmpyreanObserver, vx) - 40usize];
1047    ["Offset of field: EmpyreanObserver::vy"]
1048        [::std::mem::offset_of!(EmpyreanObserver, vy) - 48usize];
1049    ["Offset of field: EmpyreanObserver::vz"]
1050        [::std::mem::offset_of!(EmpyreanObserver, vz) - 56usize];
1051    ["Offset of field: EmpyreanObserver::observing_night"]
1052        [::std::mem::offset_of!(EmpyreanObserver, observing_night) - 64usize];
1053};
1054#[doc = " Ephemeris-generation configuration.\n\n Wraps the inner [`EmpyreanPropagationConfig`] (force model,\n uncertainty method, output frame) plus the light-time iteration\n controls and a diagnostics toggle. The propagation runs internally\n to bring each orbit to its observation epoch, so every\n propagation-level knob applies here too."]
1055#[repr(C)]
1056#[derive(Debug, Copy, Clone)]
1057pub struct EmpyreanEphemerisConfig {
1058    #[doc = " Inner propagation configuration applied to the trajectory that\n brings each orbit to its observation epoch."]
1059    pub propagation: EmpyreanPropagationConfig,
1060    #[doc = " Maximum iterations for light-time convergence. 0 → use the\n upstream default (3)."]
1061    pub max_light_time_iterations: usize,
1062    #[doc = " Tolerance (days) for light-time convergence. 0.0 → upstream\n default (1e-10)."]
1063    pub light_time_tolerance_days: f64,
1064    #[doc = " 1 = compute phase angle / elongation / heliocentric distance /\n apparent magnitude. 0 = skip (faster; appropriate for OD inner\n loops that only need RA/Dec)."]
1065    pub compute_diagnostics: u8,
1066}
1067#[allow(clippy::unnecessary_operation, clippy::identity_op)]
1068const _: () = {
1069    ["Size of EmpyreanEphemerisConfig"]
1070        [::std::mem::size_of::<EmpyreanEphemerisConfig>() - 312usize];
1071    ["Alignment of EmpyreanEphemerisConfig"]
1072        [::std::mem::align_of::<EmpyreanEphemerisConfig>() - 8usize];
1073    ["Offset of field: EmpyreanEphemerisConfig::propagation"]
1074        [::std::mem::offset_of!(EmpyreanEphemerisConfig, propagation) - 0usize];
1075    ["Offset of field: EmpyreanEphemerisConfig::max_light_time_iterations"]
1076        [::std::mem::offset_of!(EmpyreanEphemerisConfig, max_light_time_iterations) - 288usize];
1077    ["Offset of field: EmpyreanEphemerisConfig::light_time_tolerance_days"]
1078        [::std::mem::offset_of!(EmpyreanEphemerisConfig, light_time_tolerance_days) - 296usize];
1079    ["Offset of field: EmpyreanEphemerisConfig::compute_diagnostics"]
1080        [::std::mem::offset_of!(EmpyreanEphemerisConfig, compute_diagnostics) - 304usize];
1081};
1082impl Default for EmpyreanEphemerisConfig {
1083    fn default() -> Self {
1084        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
1085        unsafe {
1086            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
1087            s.assume_init()
1088        }
1089    }
1090}
1091#[doc = " A single predicted ephemeris entry."]
1092#[repr(C)]
1093#[derive(Debug, Copy, Clone)]
1094pub struct EmpyreanEphemerisEntry {
1095    #[doc = " Orbit identifier (heap-allocated, freed by empyrean_ephemeris_result_free)."]
1096    pub orbit_id: *mut ::std::os::raw::c_char,
1097    #[doc = " Epoch as MJD TDB."]
1098    pub epoch_mjd_tdb: f64,
1099    #[doc = " Right ascension (degrees)."]
1100    pub ra_deg: f64,
1101    #[doc = " Declination (degrees)."]
1102    pub dec_deg: f64,
1103    #[doc = " Topocentric distance (AU)."]
1104    pub rho_au: f64,
1105    #[doc = " Radial velocity (AU/day)."]
1106    pub vrho_au_day: f64,
1107    #[doc = " RA rate (deg/day)."]
1108    pub vra_deg_day: f64,
1109    #[doc = " Dec rate (deg/day)."]
1110    pub vdec_deg_day: f64,
1111    #[doc = " One-way light time (days). NaN if unavailable."]
1112    pub light_time_days: f64,
1113    #[doc = " Phase angle (degrees). NaN if unavailable."]
1114    pub phase_angle_deg: f64,
1115    #[doc = " Solar elongation (degrees). NaN if unavailable."]
1116    pub elongation_deg: f64,
1117    #[doc = " Heliocentric distance (AU). NaN if unavailable."]
1118    pub heliocentric_distance_au: f64,
1119    #[doc = " Predicted apparent magnitude. NaN if unavailable."]
1120    pub mag: f64,
1121    #[doc = " Magnitude uncertainty (1σ). Finite iff photometry is enabled AND\n the input orbit carried a state covariance; NaN otherwise. Today\n this reflects the state contribution only — an H-magnitude\n uncertainty is not yet an input, so `mag_sigma` under-reports σ_V\n when the H uncertainty is significant."]
1122    pub mag_sigma: f64,
1123    #[doc = " Topocentric zenith angle (degrees). NaN if unavailable (e.g. no\n observer geodetic position)."]
1124    pub zenith_angle_deg: f64,
1125    #[doc = " Topocentric azimuth, East of North (degrees). NaN if unavailable."]
1126    pub azimuth_deg: f64,
1127    #[doc = " Local hour angle (degrees). NaN if unavailable."]
1128    pub hour_angle_deg: f64,
1129    #[doc = " Angular separation from the Moon (degrees). NaN if unavailable."]
1130    pub lunar_elongation_deg: f64,
1131    #[doc = " Position angle of motion, East of North (degrees). NaN if unavailable."]
1132    pub position_angle_deg: f64,
1133    #[doc = " Total apparent sky-plane rate of motion (degrees/day). NaN if\n unavailable."]
1134    pub sky_rate_deg_day: f64,
1135    #[doc = " Observer code, null-terminated (4 bytes)."]
1136    pub obs_code: [u8; 4usize],
1137    #[doc = " 1 when `covariance` / `aberrated_state` / `aberrated_covariance`\n below are populated — i.e. the input orbit carried a state\n covariance and the STM/uncertainty path ran; 0 otherwise."]
1138    pub has_covariance: u8,
1139    #[doc = " 6×6 sky-plane covariance over (rho, RA, Dec, vrho, vRA, vDec) in\n (AU, deg) units, row-major. All-NaN when `has_covariance == 0`."]
1140    pub covariance: [[f64; 6usize]; 6usize],
1141    #[doc = " Aberrated (light-time corrected) barycentric ICRF Cartesian state\n `[x, y, z, vx, vy, vz]` (AU, AU/day) at the photon-emission epoch\n (`epoch_mjd_tdb - light_time_days`). Populated independently of\n covariance; NaN-filled in the (never-observed-today) case where\n the engine produced no aberrated state for the row."]
1142    pub aberrated_state: [f64; 6usize],
1143    #[doc = " 1 when `aberrated_covariance` is populated; 0 otherwise."]
1144    pub has_aberrated_covariance: u8,
1145    #[doc = " 6×6 Cartesian covariance of the aberrated state, row-major.\n All-NaN when `has_aberrated_covariance == 0`."]
1146    pub aberrated_covariance: [[f64; 6usize]; 6usize],
1147}
1148#[allow(clippy::unnecessary_operation, clippy::identity_op)]
1149const _: () = {
1150    ["Size of EmpyreanEphemerisEntry"][::std::mem::size_of::<EmpyreanEphemerisEntry>() - 800usize];
1151    ["Alignment of EmpyreanEphemerisEntry"]
1152        [::std::mem::align_of::<EmpyreanEphemerisEntry>() - 8usize];
1153    ["Offset of field: EmpyreanEphemerisEntry::orbit_id"]
1154        [::std::mem::offset_of!(EmpyreanEphemerisEntry, orbit_id) - 0usize];
1155    ["Offset of field: EmpyreanEphemerisEntry::epoch_mjd_tdb"]
1156        [::std::mem::offset_of!(EmpyreanEphemerisEntry, epoch_mjd_tdb) - 8usize];
1157    ["Offset of field: EmpyreanEphemerisEntry::ra_deg"]
1158        [::std::mem::offset_of!(EmpyreanEphemerisEntry, ra_deg) - 16usize];
1159    ["Offset of field: EmpyreanEphemerisEntry::dec_deg"]
1160        [::std::mem::offset_of!(EmpyreanEphemerisEntry, dec_deg) - 24usize];
1161    ["Offset of field: EmpyreanEphemerisEntry::rho_au"]
1162        [::std::mem::offset_of!(EmpyreanEphemerisEntry, rho_au) - 32usize];
1163    ["Offset of field: EmpyreanEphemerisEntry::vrho_au_day"]
1164        [::std::mem::offset_of!(EmpyreanEphemerisEntry, vrho_au_day) - 40usize];
1165    ["Offset of field: EmpyreanEphemerisEntry::vra_deg_day"]
1166        [::std::mem::offset_of!(EmpyreanEphemerisEntry, vra_deg_day) - 48usize];
1167    ["Offset of field: EmpyreanEphemerisEntry::vdec_deg_day"]
1168        [::std::mem::offset_of!(EmpyreanEphemerisEntry, vdec_deg_day) - 56usize];
1169    ["Offset of field: EmpyreanEphemerisEntry::light_time_days"]
1170        [::std::mem::offset_of!(EmpyreanEphemerisEntry, light_time_days) - 64usize];
1171    ["Offset of field: EmpyreanEphemerisEntry::phase_angle_deg"]
1172        [::std::mem::offset_of!(EmpyreanEphemerisEntry, phase_angle_deg) - 72usize];
1173    ["Offset of field: EmpyreanEphemerisEntry::elongation_deg"]
1174        [::std::mem::offset_of!(EmpyreanEphemerisEntry, elongation_deg) - 80usize];
1175    ["Offset of field: EmpyreanEphemerisEntry::heliocentric_distance_au"]
1176        [::std::mem::offset_of!(EmpyreanEphemerisEntry, heliocentric_distance_au) - 88usize];
1177    ["Offset of field: EmpyreanEphemerisEntry::mag"]
1178        [::std::mem::offset_of!(EmpyreanEphemerisEntry, mag) - 96usize];
1179    ["Offset of field: EmpyreanEphemerisEntry::mag_sigma"]
1180        [::std::mem::offset_of!(EmpyreanEphemerisEntry, mag_sigma) - 104usize];
1181    ["Offset of field: EmpyreanEphemerisEntry::zenith_angle_deg"]
1182        [::std::mem::offset_of!(EmpyreanEphemerisEntry, zenith_angle_deg) - 112usize];
1183    ["Offset of field: EmpyreanEphemerisEntry::azimuth_deg"]
1184        [::std::mem::offset_of!(EmpyreanEphemerisEntry, azimuth_deg) - 120usize];
1185    ["Offset of field: EmpyreanEphemerisEntry::hour_angle_deg"]
1186        [::std::mem::offset_of!(EmpyreanEphemerisEntry, hour_angle_deg) - 128usize];
1187    ["Offset of field: EmpyreanEphemerisEntry::lunar_elongation_deg"]
1188        [::std::mem::offset_of!(EmpyreanEphemerisEntry, lunar_elongation_deg) - 136usize];
1189    ["Offset of field: EmpyreanEphemerisEntry::position_angle_deg"]
1190        [::std::mem::offset_of!(EmpyreanEphemerisEntry, position_angle_deg) - 144usize];
1191    ["Offset of field: EmpyreanEphemerisEntry::sky_rate_deg_day"]
1192        [::std::mem::offset_of!(EmpyreanEphemerisEntry, sky_rate_deg_day) - 152usize];
1193    ["Offset of field: EmpyreanEphemerisEntry::obs_code"]
1194        [::std::mem::offset_of!(EmpyreanEphemerisEntry, obs_code) - 160usize];
1195    ["Offset of field: EmpyreanEphemerisEntry::has_covariance"]
1196        [::std::mem::offset_of!(EmpyreanEphemerisEntry, has_covariance) - 164usize];
1197    ["Offset of field: EmpyreanEphemerisEntry::covariance"]
1198        [::std::mem::offset_of!(EmpyreanEphemerisEntry, covariance) - 168usize];
1199    ["Offset of field: EmpyreanEphemerisEntry::aberrated_state"]
1200        [::std::mem::offset_of!(EmpyreanEphemerisEntry, aberrated_state) - 456usize];
1201    ["Offset of field: EmpyreanEphemerisEntry::has_aberrated_covariance"]
1202        [::std::mem::offset_of!(EmpyreanEphemerisEntry, has_aberrated_covariance) - 504usize];
1203    ["Offset of field: EmpyreanEphemerisEntry::aberrated_covariance"]
1204        [::std::mem::offset_of!(EmpyreanEphemerisEntry, aberrated_covariance) - 512usize];
1205};
1206impl Default for EmpyreanEphemerisEntry {
1207    fn default() -> Self {
1208        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
1209        unsafe {
1210            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
1211            s.assume_init()
1212        }
1213    }
1214}
1215#[doc = " One observation-sensitivity row — the partial derivatives of the\n sky-plane observable w.r.t. the input state, for a single\n `(orbit, observer, epoch)`. One row per observation epoch within each\n `(orbit_id, obs_code)` chain. Owning struct: free\n the whole result with [`empyrean_ephemeris_result_free`].\n\n The Jacobian composes d(obs)/d(state at t_obs) * Phi(t_obs, t0) and\n omits the light-time terms (the -v * dtau/dx partial; the STM is\n sampled at t_obs rather than emission t_obs - tau): both are O(tau),\n landing in the velocity columns of the angle rows with fractional\n error ~ tau/dt (tau ~ 0.006-0.017 d) — negligible for multi-night\n arcs, growing as the arc shrinks toward intra-night."]
1216#[repr(C)]
1217#[derive(Debug, Copy, Clone)]
1218pub struct EmpyreanObservationSensitivity {
1219    #[doc = " Orbit identifier. Owning C string."]
1220    pub orbit_id: *mut ::std::os::raw::c_char,
1221    #[doc = " Object identifier (owning C string) or null when absent."]
1222    pub object_id: *mut ::std::os::raw::c_char,
1223    #[doc = " MPC observatory code, null-terminated (4 bytes)."]
1224    pub obs_code: [u8; 4usize],
1225    #[doc = " Observation epoch (MJD TDB)."]
1226    pub epoch_mjd_tdb: f64,
1227    #[doc = " Solved-parameter dimension: 6 (state) or 9 (state + non-grav)."]
1228    pub n_params: u8,
1229    #[doc = " Jacobian ∂(observable)/∂(input), row-major `[6][n_params]` flattened\n (length `6 * n_params`). Null when this epoch carries no Jacobian."]
1230    pub jacobian: *mut f64,
1231    #[doc = " Length of `jacobian` (`6 * n_params`), 0 when null."]
1232    pub jacobian_len: usize,
1233    #[doc = " Hessian ∂²(observable)/∂(input)², row-major `[6][n_params][n_params]`\n flattened (length `6 * n_params * n_params`). Null unless a\n second-order method (Jet2) ran."]
1234    pub hessian: *mut f64,
1235    #[doc = " Length of `hessian` (`6 * n_params²`), 0 when null."]
1236    pub hessian_len: usize,
1237    #[doc = " Frame of the input axis (Frame enum as int)."]
1238    pub frame: i32,
1239    #[doc = " Origin of the input axis (NAIF id)."]
1240    pub origin: i32,
1241}
1242#[allow(clippy::unnecessary_operation, clippy::identity_op)]
1243const _: () = {
1244    ["Size of EmpyreanObservationSensitivity"]
1245        [::std::mem::size_of::<EmpyreanObservationSensitivity>() - 80usize];
1246    ["Alignment of EmpyreanObservationSensitivity"]
1247        [::std::mem::align_of::<EmpyreanObservationSensitivity>() - 8usize];
1248    ["Offset of field: EmpyreanObservationSensitivity::orbit_id"]
1249        [::std::mem::offset_of!(EmpyreanObservationSensitivity, orbit_id) - 0usize];
1250    ["Offset of field: EmpyreanObservationSensitivity::object_id"]
1251        [::std::mem::offset_of!(EmpyreanObservationSensitivity, object_id) - 8usize];
1252    ["Offset of field: EmpyreanObservationSensitivity::obs_code"]
1253        [::std::mem::offset_of!(EmpyreanObservationSensitivity, obs_code) - 16usize];
1254    ["Offset of field: EmpyreanObservationSensitivity::epoch_mjd_tdb"]
1255        [::std::mem::offset_of!(EmpyreanObservationSensitivity, epoch_mjd_tdb) - 24usize];
1256    ["Offset of field: EmpyreanObservationSensitivity::n_params"]
1257        [::std::mem::offset_of!(EmpyreanObservationSensitivity, n_params) - 32usize];
1258    ["Offset of field: EmpyreanObservationSensitivity::jacobian"]
1259        [::std::mem::offset_of!(EmpyreanObservationSensitivity, jacobian) - 40usize];
1260    ["Offset of field: EmpyreanObservationSensitivity::jacobian_len"]
1261        [::std::mem::offset_of!(EmpyreanObservationSensitivity, jacobian_len) - 48usize];
1262    ["Offset of field: EmpyreanObservationSensitivity::hessian"]
1263        [::std::mem::offset_of!(EmpyreanObservationSensitivity, hessian) - 56usize];
1264    ["Offset of field: EmpyreanObservationSensitivity::hessian_len"]
1265        [::std::mem::offset_of!(EmpyreanObservationSensitivity, hessian_len) - 64usize];
1266    ["Offset of field: EmpyreanObservationSensitivity::frame"]
1267        [::std::mem::offset_of!(EmpyreanObservationSensitivity, frame) - 72usize];
1268    ["Offset of field: EmpyreanObservationSensitivity::origin"]
1269        [::std::mem::offset_of!(EmpyreanObservationSensitivity, origin) - 76usize];
1270};
1271impl Default for EmpyreanObservationSensitivity {
1272    fn default() -> Self {
1273        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
1274        unsafe {
1275            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
1276            s.assume_init()
1277        }
1278    }
1279}
1280#[doc = " Result containing an array of ephemeris entries and, when an\n uncertainty method traced the STM, the observation-sensitivity chains."]
1281#[repr(C)]
1282#[derive(Debug, Copy, Clone)]
1283pub struct EmpyreanEphemerisResult {
1284    pub entries: *mut EmpyreanEphemerisEntry,
1285    pub num_entries: usize,
1286    #[doc = " Per-`(orbit, observer, epoch)` sensitivity rows. Null / 0 when no\n STM was traced (e.g. an f64-only path)."]
1287    pub sensitivity: *mut EmpyreanObservationSensitivity,
1288    pub num_sensitivity: usize,
1289    #[doc = " Non-fatal generation warnings: heap array of `num_warnings`\n NUL-terminated UTF-8 strings. Null when `num_warnings == 0` (a\n clean run). One list per call, not per row; each message names the\n affected orbit id, observatory code, and epoch (MJD TDB) where\n applicable. Freed by `empyrean_ephemeris_result_free`."]
1290    pub warnings: *mut *mut ::std::os::raw::c_char,
1291    #[doc = " Number of warning strings. 0 when the run had nothing to report."]
1292    pub num_warnings: usize,
1293}
1294#[allow(clippy::unnecessary_operation, clippy::identity_op)]
1295const _: () = {
1296    ["Size of EmpyreanEphemerisResult"][::std::mem::size_of::<EmpyreanEphemerisResult>() - 48usize];
1297    ["Alignment of EmpyreanEphemerisResult"]
1298        [::std::mem::align_of::<EmpyreanEphemerisResult>() - 8usize];
1299    ["Offset of field: EmpyreanEphemerisResult::entries"]
1300        [::std::mem::offset_of!(EmpyreanEphemerisResult, entries) - 0usize];
1301    ["Offset of field: EmpyreanEphemerisResult::num_entries"]
1302        [::std::mem::offset_of!(EmpyreanEphemerisResult, num_entries) - 8usize];
1303    ["Offset of field: EmpyreanEphemerisResult::sensitivity"]
1304        [::std::mem::offset_of!(EmpyreanEphemerisResult, sensitivity) - 16usize];
1305    ["Offset of field: EmpyreanEphemerisResult::num_sensitivity"]
1306        [::std::mem::offset_of!(EmpyreanEphemerisResult, num_sensitivity) - 24usize];
1307    ["Offset of field: EmpyreanEphemerisResult::warnings"]
1308        [::std::mem::offset_of!(EmpyreanEphemerisResult, warnings) - 32usize];
1309    ["Offset of field: EmpyreanEphemerisResult::num_warnings"]
1310        [::std::mem::offset_of!(EmpyreanEphemerisResult, num_warnings) - 40usize];
1311};
1312impl Default for EmpyreanEphemerisResult {
1313    fn default() -> Self {
1314        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
1315        unsafe {
1316            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
1317            s.assume_init()
1318        }
1319    }
1320}
1321#[doc = " One entry of the kernel-identity manifest captured by a handle.\n\n Names the provenance of each loaded data file — never any tuning\n rationale. Free the owning [`EmpyreanSystemDescription`] with\n [`empyrean_builtsystem_description_free`]; do not free these fields\n individually."]
1322#[repr(C)]
1323#[derive(Debug, Copy, Clone)]
1324pub struct EmpyreanKernelRecord {
1325    #[doc = " Category of the entry (`EMPYREAN_KERNEL_KIND_*`)."]
1326    pub kind: i32,
1327    #[doc = " Where the entry came from (`EMPYREAN_KERNEL_PROVENANCE_*`)."]
1328    pub provenance: i32,
1329    #[doc = " Absolute path the kernel was loaded from. Non-null only for a\n `FILE` provenance; null otherwise. NUL-terminated UTF-8."]
1330    pub path: *mut ::std::os::raw::c_char,
1331    #[doc = " Lowercase-hex SHA-256 of the file's bytes (64 chars). Non-null only\n for a `FILE` provenance; null otherwise. NUL-terminated UTF-8."]
1332    pub sha256: *mut ::std::os::raw::c_char,
1333    #[doc = " Hashed file size in bytes. 0 unless `FILE` provenance."]
1334    pub bytes: u64,
1335    #[doc = " Human-readable model name. Non-null only for a `BUILT_IN`\n provenance; null otherwise. NUL-terminated UTF-8."]
1336    pub name: *mut ::std::os::raw::c_char,
1337}
1338#[allow(clippy::unnecessary_operation, clippy::identity_op)]
1339const _: () = {
1340    ["Size of EmpyreanKernelRecord"][::std::mem::size_of::<EmpyreanKernelRecord>() - 40usize];
1341    ["Alignment of EmpyreanKernelRecord"][::std::mem::align_of::<EmpyreanKernelRecord>() - 8usize];
1342    ["Offset of field: EmpyreanKernelRecord::kind"]
1343        [::std::mem::offset_of!(EmpyreanKernelRecord, kind) - 0usize];
1344    ["Offset of field: EmpyreanKernelRecord::provenance"]
1345        [::std::mem::offset_of!(EmpyreanKernelRecord, provenance) - 4usize];
1346    ["Offset of field: EmpyreanKernelRecord::path"]
1347        [::std::mem::offset_of!(EmpyreanKernelRecord, path) - 8usize];
1348    ["Offset of field: EmpyreanKernelRecord::sha256"]
1349        [::std::mem::offset_of!(EmpyreanKernelRecord, sha256) - 16usize];
1350    ["Offset of field: EmpyreanKernelRecord::bytes"]
1351        [::std::mem::offset_of!(EmpyreanKernelRecord, bytes) - 24usize];
1352    ["Offset of field: EmpyreanKernelRecord::name"]
1353        [::std::mem::offset_of!(EmpyreanKernelRecord, name) - 32usize];
1354};
1355impl Default for EmpyreanKernelRecord {
1356    fn default() -> Self {
1357        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
1358        unsafe {
1359            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
1360            s.assume_init()
1361        }
1362    }
1363}
1364#[doc = " A reproducibility summary of a handle's frozen force model plus its\n captured kernel-identity manifest.\n\n Populated in full by [`empyrean_builtsystem_describe`] — every field\n reflects the assembled system; nothing is defaulted. Names the citable\n menu (tier, frame, GR, perturbers, BPC, kernel hashes) — never selection\n logic or tuning rationale. Release the heap-owned arrays with\n [`empyrean_builtsystem_description_free`]."]
1365#[repr(C)]
1366#[derive(Debug, Copy, Clone)]
1367pub struct EmpyreanSystemDescription {
1368    #[doc = " Force-model tier: 0=Approximate, 1=Basic, 2=Standard."]
1369    pub force_model: i32,
1370    #[doc = " Integration/output frame: 0=ICRF, 1=EclipticJ2000, 2=ITRF93."]
1371    pub frame: i32,
1372    #[doc = " The frozen encounter-timescale divisor."]
1373    pub encounter_timescale_divisor: f64,
1374    #[doc = " 1 if the post-Newtonian (EIH) GR correction is enabled, else 0."]
1375    pub relativistic: u8,
1376    #[doc = " 1 if the N16 asteroid perturbers are included, else 0."]
1377    pub asteroids: u8,
1378    #[doc = " 1 if a BPC (body-fixed rotation) kernel is loaded, else 0."]
1379    pub has_bpc: u8,
1380    #[doc = " Heap array of perturbing-body NAIF ids (length `num_perturbers`).\n Null when `num_perturbers == 0`."]
1381    pub perturber_origins: *mut i32,
1382    #[doc = " Number of entries in [`perturber_origins`](Self::perturber_origins)."]
1383    pub num_perturbers: usize,
1384    #[doc = " Heap array of kernel-identity records (length `num_kernels`). Null\n when `num_kernels == 0`."]
1385    pub kernels: *mut EmpyreanKernelRecord,
1386    #[doc = " Number of entries in [`kernels`](Self::kernels)."]
1387    pub num_kernels: usize,
1388}
1389#[allow(clippy::unnecessary_operation, clippy::identity_op)]
1390const _: () = {
1391    ["Size of EmpyreanSystemDescription"]
1392        [::std::mem::size_of::<EmpyreanSystemDescription>() - 56usize];
1393    ["Alignment of EmpyreanSystemDescription"]
1394        [::std::mem::align_of::<EmpyreanSystemDescription>() - 8usize];
1395    ["Offset of field: EmpyreanSystemDescription::force_model"]
1396        [::std::mem::offset_of!(EmpyreanSystemDescription, force_model) - 0usize];
1397    ["Offset of field: EmpyreanSystemDescription::frame"]
1398        [::std::mem::offset_of!(EmpyreanSystemDescription, frame) - 4usize];
1399    ["Offset of field: EmpyreanSystemDescription::encounter_timescale_divisor"]
1400        [::std::mem::offset_of!(EmpyreanSystemDescription, encounter_timescale_divisor) - 8usize];
1401    ["Offset of field: EmpyreanSystemDescription::relativistic"]
1402        [::std::mem::offset_of!(EmpyreanSystemDescription, relativistic) - 16usize];
1403    ["Offset of field: EmpyreanSystemDescription::asteroids"]
1404        [::std::mem::offset_of!(EmpyreanSystemDescription, asteroids) - 17usize];
1405    ["Offset of field: EmpyreanSystemDescription::has_bpc"]
1406        [::std::mem::offset_of!(EmpyreanSystemDescription, has_bpc) - 18usize];
1407    ["Offset of field: EmpyreanSystemDescription::perturber_origins"]
1408        [::std::mem::offset_of!(EmpyreanSystemDescription, perturber_origins) - 24usize];
1409    ["Offset of field: EmpyreanSystemDescription::num_perturbers"]
1410        [::std::mem::offset_of!(EmpyreanSystemDescription, num_perturbers) - 32usize];
1411    ["Offset of field: EmpyreanSystemDescription::kernels"]
1412        [::std::mem::offset_of!(EmpyreanSystemDescription, kernels) - 40usize];
1413    ["Offset of field: EmpyreanSystemDescription::num_kernels"]
1414        [::std::mem::offset_of!(EmpyreanSystemDescription, num_kernels) - 48usize];
1415};
1416impl Default for EmpyreanSystemDescription {
1417    fn default() -> Self {
1418        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
1419        unsafe {
1420            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
1421            s.assume_init()
1422        }
1423    }
1424}
1425#[doc = " One impact-probability record emitted by\n [`empyrean_compute_impact_probabilities`]. Mirrors\n [`empyrean_core::impact::ImpactProbability`] flattened to primitives;\n nullable fields use NaN sentinels (Option<f64>) or 0 / null\n (Option<usize>).\n\n `method_tag` matches the `EMPYREAN_UNCERTAINTY_*` constants in\n `propagate.rs` and identifies which propagation produced this row."]
1426#[repr(C)]
1427#[derive(Debug, Copy, Clone)]
1428pub struct EmpyreanImpactProbability {
1429    #[doc = " Variant tag of the [`UncertaintyMethod`] that produced this row."]
1430    pub method_tag: u8,
1431    #[doc = " Owning C string — caller frees via `*_result_free`."]
1432    pub orbit_id: *mut ::std::os::raw::c_char,
1433    pub object_id: *mut ::std::os::raw::c_char,
1434    pub body: *mut ::std::os::raw::c_char,
1435    pub body_naif_id: i32,
1436    pub epoch_mjd_tdb: f64,
1437    pub miss_distance_au: f64,
1438    pub miss_distance_km: f64,
1439    pub effective_radius_au: f64,
1440    pub effective_radius_km: f64,
1441    pub sigma_distance_au: f64,
1442    pub sigma_distance_km: f64,
1443    pub ip_linear: f64,
1444    pub relative_velocity_au_day: f64,
1445    #[doc = " `ip_second_order`, NaN when not available."]
1446    pub ip_second_order: f64,
1447    #[doc = " Jet2 nonlinearity κ, NaN when not available."]
1448    pub nonlinearity: f64,
1449    #[doc = " AGM-mixed IP, NaN when not available."]
1450    pub ip_agm: f64,
1451    #[doc = " MC-sampled IP, NaN when not available."]
1452    pub ip_mc: f64,
1453    #[doc = " Number of MC samples drawn (0 when MC was not used)."]
1454    pub mc_n_samples: u64,
1455    #[doc = " Number of MC samples that impacted (0 when MC was not used)."]
1456    pub mc_n_impacts: u64,
1457    #[doc = " Geodetic latitude of the closest-approach surface point on the\n body's reference ellipsoid (degrees, north positive). NaN when no\n surface projection is available for this encounter."]
1458    pub impact_latitude_deg: f64,
1459    #[doc = " Geodetic longitude of the closest-approach surface point\n (degrees, east positive, [-180, 180]). NaN when unavailable."]
1460    pub impact_longitude_deg: f64,
1461    #[doc = " Altitude of the closest-approach point above the reference\n ellipsoid (km). NaN when unavailable."]
1462    pub impact_altitude_km: f64,
1463    #[doc = " Half-width of the 95% binomial confidence interval on `ip_mc`.\n The interval is `ip_mc ± mc_confidence_interval`. NaN when the\n producing method was not Monte Carlo."]
1464    pub mc_confidence_interval: f64,
1465    #[doc = " Second-order corrected mean miss distance (AU). On Monte-Carlo\n rows carries the sample-mean miss distance instead. NaN when the\n producing method computed neither."]
1466    pub mean_distance_second_order_au: f64,
1467    #[doc = " Second-order corrected 1σ miss-distance uncertainty (AU). NaN\n when the producing method carried no second-order derivatives."]
1468    pub sigma_distance_second_order_au: f64,
1469    #[doc = " Skewness γ₁ of the miss-distance distribution under the\n second-order expansion (dimensionless). NaN when not computed."]
1470    pub skewness: f64,
1471    #[doc = " Gradient ∂d/∂x₀ of the closest-approach distance w.r.t. the\n initial Cartesian state. All-zero on Monte-Carlo rows and on\n degenerate zero-miss encounters."]
1472    pub gradient: [f64; 6usize],
1473    #[doc = " Second derivatives ∂²d/∂x₀ᵢ∂x₀ⱼ of the closest-approach distance\n (6×6 symmetric). Every entry NaN when the producing method carried\n no second-order derivatives."]
1474    pub distance_hessian: [[f64; 6usize]; 6usize],
1475    #[doc = " Number of mixture components used by the adaptive\n Gaussian-mixture IP refinement. 0 when the refinement did not run\n (matches `ip_agm` = NaN)."]
1476    pub agm_components: u64,
1477}
1478#[allow(clippy::unnecessary_operation, clippy::identity_op)]
1479const _: () = {
1480    ["Size of EmpyreanImpactProbability"]
1481        [::std::mem::size_of::<EmpyreanImpactProbability>() - 560usize];
1482    ["Alignment of EmpyreanImpactProbability"]
1483        [::std::mem::align_of::<EmpyreanImpactProbability>() - 8usize];
1484    ["Offset of field: EmpyreanImpactProbability::method_tag"]
1485        [::std::mem::offset_of!(EmpyreanImpactProbability, method_tag) - 0usize];
1486    ["Offset of field: EmpyreanImpactProbability::orbit_id"]
1487        [::std::mem::offset_of!(EmpyreanImpactProbability, orbit_id) - 8usize];
1488    ["Offset of field: EmpyreanImpactProbability::object_id"]
1489        [::std::mem::offset_of!(EmpyreanImpactProbability, object_id) - 16usize];
1490    ["Offset of field: EmpyreanImpactProbability::body"]
1491        [::std::mem::offset_of!(EmpyreanImpactProbability, body) - 24usize];
1492    ["Offset of field: EmpyreanImpactProbability::body_naif_id"]
1493        [::std::mem::offset_of!(EmpyreanImpactProbability, body_naif_id) - 32usize];
1494    ["Offset of field: EmpyreanImpactProbability::epoch_mjd_tdb"]
1495        [::std::mem::offset_of!(EmpyreanImpactProbability, epoch_mjd_tdb) - 40usize];
1496    ["Offset of field: EmpyreanImpactProbability::miss_distance_au"]
1497        [::std::mem::offset_of!(EmpyreanImpactProbability, miss_distance_au) - 48usize];
1498    ["Offset of field: EmpyreanImpactProbability::miss_distance_km"]
1499        [::std::mem::offset_of!(EmpyreanImpactProbability, miss_distance_km) - 56usize];
1500    ["Offset of field: EmpyreanImpactProbability::effective_radius_au"]
1501        [::std::mem::offset_of!(EmpyreanImpactProbability, effective_radius_au) - 64usize];
1502    ["Offset of field: EmpyreanImpactProbability::effective_radius_km"]
1503        [::std::mem::offset_of!(EmpyreanImpactProbability, effective_radius_km) - 72usize];
1504    ["Offset of field: EmpyreanImpactProbability::sigma_distance_au"]
1505        [::std::mem::offset_of!(EmpyreanImpactProbability, sigma_distance_au) - 80usize];
1506    ["Offset of field: EmpyreanImpactProbability::sigma_distance_km"]
1507        [::std::mem::offset_of!(EmpyreanImpactProbability, sigma_distance_km) - 88usize];
1508    ["Offset of field: EmpyreanImpactProbability::ip_linear"]
1509        [::std::mem::offset_of!(EmpyreanImpactProbability, ip_linear) - 96usize];
1510    ["Offset of field: EmpyreanImpactProbability::relative_velocity_au_day"]
1511        [::std::mem::offset_of!(EmpyreanImpactProbability, relative_velocity_au_day) - 104usize];
1512    ["Offset of field: EmpyreanImpactProbability::ip_second_order"]
1513        [::std::mem::offset_of!(EmpyreanImpactProbability, ip_second_order) - 112usize];
1514    ["Offset of field: EmpyreanImpactProbability::nonlinearity"]
1515        [::std::mem::offset_of!(EmpyreanImpactProbability, nonlinearity) - 120usize];
1516    ["Offset of field: EmpyreanImpactProbability::ip_agm"]
1517        [::std::mem::offset_of!(EmpyreanImpactProbability, ip_agm) - 128usize];
1518    ["Offset of field: EmpyreanImpactProbability::ip_mc"]
1519        [::std::mem::offset_of!(EmpyreanImpactProbability, ip_mc) - 136usize];
1520    ["Offset of field: EmpyreanImpactProbability::mc_n_samples"]
1521        [::std::mem::offset_of!(EmpyreanImpactProbability, mc_n_samples) - 144usize];
1522    ["Offset of field: EmpyreanImpactProbability::mc_n_impacts"]
1523        [::std::mem::offset_of!(EmpyreanImpactProbability, mc_n_impacts) - 152usize];
1524    ["Offset of field: EmpyreanImpactProbability::impact_latitude_deg"]
1525        [::std::mem::offset_of!(EmpyreanImpactProbability, impact_latitude_deg) - 160usize];
1526    ["Offset of field: EmpyreanImpactProbability::impact_longitude_deg"]
1527        [::std::mem::offset_of!(EmpyreanImpactProbability, impact_longitude_deg) - 168usize];
1528    ["Offset of field: EmpyreanImpactProbability::impact_altitude_km"]
1529        [::std::mem::offset_of!(EmpyreanImpactProbability, impact_altitude_km) - 176usize];
1530    ["Offset of field: EmpyreanImpactProbability::mc_confidence_interval"]
1531        [::std::mem::offset_of!(EmpyreanImpactProbability, mc_confidence_interval) - 184usize];
1532    ["Offset of field: EmpyreanImpactProbability::mean_distance_second_order_au"]
1533        [::std::mem::offset_of!(EmpyreanImpactProbability, mean_distance_second_order_au)
1534            - 192usize];
1535    ["Offset of field: EmpyreanImpactProbability::sigma_distance_second_order_au"]
1536        [::std::mem::offset_of!(EmpyreanImpactProbability, sigma_distance_second_order_au)
1537            - 200usize];
1538    ["Offset of field: EmpyreanImpactProbability::skewness"]
1539        [::std::mem::offset_of!(EmpyreanImpactProbability, skewness) - 208usize];
1540    ["Offset of field: EmpyreanImpactProbability::gradient"]
1541        [::std::mem::offset_of!(EmpyreanImpactProbability, gradient) - 216usize];
1542    ["Offset of field: EmpyreanImpactProbability::distance_hessian"]
1543        [::std::mem::offset_of!(EmpyreanImpactProbability, distance_hessian) - 264usize];
1544    ["Offset of field: EmpyreanImpactProbability::agm_components"]
1545        [::std::mem::offset_of!(EmpyreanImpactProbability, agm_components) - 552usize];
1546};
1547impl Default for EmpyreanImpactProbability {
1548    fn default() -> Self {
1549        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
1550        unsafe {
1551            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
1552            s.assume_init()
1553        }
1554    }
1555}
1556#[repr(C)]
1557#[derive(Debug, Copy, Clone)]
1558pub struct EmpyreanImpactProbabilitiesResult {
1559    pub records: *mut EmpyreanImpactProbability,
1560    pub num_records: usize,
1561}
1562#[allow(clippy::unnecessary_operation, clippy::identity_op)]
1563const _: () = {
1564    ["Size of EmpyreanImpactProbabilitiesResult"]
1565        [::std::mem::size_of::<EmpyreanImpactProbabilitiesResult>() - 16usize];
1566    ["Alignment of EmpyreanImpactProbabilitiesResult"]
1567        [::std::mem::align_of::<EmpyreanImpactProbabilitiesResult>() - 8usize];
1568    ["Offset of field: EmpyreanImpactProbabilitiesResult::records"]
1569        [::std::mem::offset_of!(EmpyreanImpactProbabilitiesResult, records) - 0usize];
1570    ["Offset of field: EmpyreanImpactProbabilitiesResult::num_records"]
1571        [::std::mem::offset_of!(EmpyreanImpactProbabilitiesResult, num_records) - 8usize];
1572};
1573impl Default for EmpyreanImpactProbabilitiesResult {
1574    fn default() -> Self {
1575        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
1576        unsafe {
1577            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
1578            s.assume_init()
1579        }
1580    }
1581}
1582#[doc = " One B-plane breakdown emitted by [`empyrean_compute_b_planes`].\n Mirrors [`empyrean_core::impact::BPlaneData`] flattened to primitives.\n Nullable f64 fields use NaN sentinels."]
1583#[repr(C)]
1584#[derive(Debug, Copy, Clone)]
1585pub struct EmpyreanBPlane {
1586    #[doc = " Variant tag of the [`UncertaintyMethod`] that produced this row."]
1587    pub method_tag: u8,
1588    #[doc = " Owning C string — caller frees via `*_result_free`."]
1589    pub body: *mut ::std::os::raw::c_char,
1590    pub epoch_mjd_tdb: f64,
1591    pub b_dot_t_km: f64,
1592    pub b_dot_r_km: f64,
1593    pub b_mag_km: f64,
1594    pub v_inf_km_s: f64,
1595    pub effective_radius_km: f64,
1596    pub body_radius_km: f64,
1597    #[doc = " `[σ_TT, σ_TR, σ_RR]` covariance elements (km²); NaN when no\n projected covariance is available."]
1598    pub cov_b_plane: [f64; 3usize],
1599    pub semi_major_3sig_km: f64,
1600    pub semi_minor_3sig_km: f64,
1601    pub ellipse_angle_rad: f64,
1602    pub ip_linear: f64,
1603}
1604#[allow(clippy::unnecessary_operation, clippy::identity_op)]
1605const _: () = {
1606    ["Size of EmpyreanBPlane"][::std::mem::size_of::<EmpyreanBPlane>() - 128usize];
1607    ["Alignment of EmpyreanBPlane"][::std::mem::align_of::<EmpyreanBPlane>() - 8usize];
1608    ["Offset of field: EmpyreanBPlane::method_tag"]
1609        [::std::mem::offset_of!(EmpyreanBPlane, method_tag) - 0usize];
1610    ["Offset of field: EmpyreanBPlane::body"]
1611        [::std::mem::offset_of!(EmpyreanBPlane, body) - 8usize];
1612    ["Offset of field: EmpyreanBPlane::epoch_mjd_tdb"]
1613        [::std::mem::offset_of!(EmpyreanBPlane, epoch_mjd_tdb) - 16usize];
1614    ["Offset of field: EmpyreanBPlane::b_dot_t_km"]
1615        [::std::mem::offset_of!(EmpyreanBPlane, b_dot_t_km) - 24usize];
1616    ["Offset of field: EmpyreanBPlane::b_dot_r_km"]
1617        [::std::mem::offset_of!(EmpyreanBPlane, b_dot_r_km) - 32usize];
1618    ["Offset of field: EmpyreanBPlane::b_mag_km"]
1619        [::std::mem::offset_of!(EmpyreanBPlane, b_mag_km) - 40usize];
1620    ["Offset of field: EmpyreanBPlane::v_inf_km_s"]
1621        [::std::mem::offset_of!(EmpyreanBPlane, v_inf_km_s) - 48usize];
1622    ["Offset of field: EmpyreanBPlane::effective_radius_km"]
1623        [::std::mem::offset_of!(EmpyreanBPlane, effective_radius_km) - 56usize];
1624    ["Offset of field: EmpyreanBPlane::body_radius_km"]
1625        [::std::mem::offset_of!(EmpyreanBPlane, body_radius_km) - 64usize];
1626    ["Offset of field: EmpyreanBPlane::cov_b_plane"]
1627        [::std::mem::offset_of!(EmpyreanBPlane, cov_b_plane) - 72usize];
1628    ["Offset of field: EmpyreanBPlane::semi_major_3sig_km"]
1629        [::std::mem::offset_of!(EmpyreanBPlane, semi_major_3sig_km) - 96usize];
1630    ["Offset of field: EmpyreanBPlane::semi_minor_3sig_km"]
1631        [::std::mem::offset_of!(EmpyreanBPlane, semi_minor_3sig_km) - 104usize];
1632    ["Offset of field: EmpyreanBPlane::ellipse_angle_rad"]
1633        [::std::mem::offset_of!(EmpyreanBPlane, ellipse_angle_rad) - 112usize];
1634    ["Offset of field: EmpyreanBPlane::ip_linear"]
1635        [::std::mem::offset_of!(EmpyreanBPlane, ip_linear) - 120usize];
1636};
1637impl Default for EmpyreanBPlane {
1638    fn default() -> Self {
1639        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
1640        unsafe {
1641            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
1642            s.assume_init()
1643        }
1644    }
1645}
1646#[repr(C)]
1647#[derive(Debug, Copy, Clone)]
1648pub struct EmpyreanBPlanesResult {
1649    pub records: *mut EmpyreanBPlane,
1650    pub num_records: usize,
1651}
1652#[allow(clippy::unnecessary_operation, clippy::identity_op)]
1653const _: () = {
1654    ["Size of EmpyreanBPlanesResult"][::std::mem::size_of::<EmpyreanBPlanesResult>() - 16usize];
1655    ["Alignment of EmpyreanBPlanesResult"]
1656        [::std::mem::align_of::<EmpyreanBPlanesResult>() - 8usize];
1657    ["Offset of field: EmpyreanBPlanesResult::records"]
1658        [::std::mem::offset_of!(EmpyreanBPlanesResult, records) - 0usize];
1659    ["Offset of field: EmpyreanBPlanesResult::num_records"]
1660        [::std::mem::offset_of!(EmpyreanBPlanesResult, num_records) - 8usize];
1661};
1662impl Default for EmpyreanBPlanesResult {
1663    fn default() -> Self {
1664        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
1665        unsafe {
1666            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
1667            s.assume_init()
1668        }
1669    }
1670}
1671#[doc = " A batch of orbits with their identifiers.\n\n Returned by every `empyrean_orbits_read_*` and consumed by every\n `empyrean_orbits_write_*`. `orbit_ids` and `object_ids` are parallel\n to `orbits` (same length); each `object_ids[i]` may be null when the\n underlying orbit had no object designation.\n\n Free with [`empyrean_orbits_batch_free`] when done."]
1672#[repr(C)]
1673#[derive(Debug, Copy, Clone)]
1674pub struct EmpyreanOrbitBatch {
1675    #[doc = " Heap-allocated array of `EmpyreanOrbit`. Null when `num_orbits == 0`."]
1676    pub orbits: *mut EmpyreanOrbit,
1677    #[doc = " Heap-allocated array of orbit identifiers (null-terminated UTF-8).\n Each `orbit_ids[i]` is non-null when `i < num_orbits`."]
1678    pub orbit_ids: *mut *mut ::std::os::raw::c_char,
1679    #[doc = " Heap-allocated array of optional object identifiers\n (null-terminated UTF-8 or null pointer when absent)."]
1680    pub object_ids: *mut *mut ::std::os::raw::c_char,
1681    #[doc = " Number of orbits in the batch."]
1682    pub num_orbits: usize,
1683}
1684#[allow(clippy::unnecessary_operation, clippy::identity_op)]
1685const _: () = {
1686    ["Size of EmpyreanOrbitBatch"][::std::mem::size_of::<EmpyreanOrbitBatch>() - 32usize];
1687    ["Alignment of EmpyreanOrbitBatch"][::std::mem::align_of::<EmpyreanOrbitBatch>() - 8usize];
1688    ["Offset of field: EmpyreanOrbitBatch::orbits"]
1689        [::std::mem::offset_of!(EmpyreanOrbitBatch, orbits) - 0usize];
1690    ["Offset of field: EmpyreanOrbitBatch::orbit_ids"]
1691        [::std::mem::offset_of!(EmpyreanOrbitBatch, orbit_ids) - 8usize];
1692    ["Offset of field: EmpyreanOrbitBatch::object_ids"]
1693        [::std::mem::offset_of!(EmpyreanOrbitBatch, object_ids) - 16usize];
1694    ["Offset of field: EmpyreanOrbitBatch::num_orbits"]
1695        [::std::mem::offset_of!(EmpyreanOrbitBatch, num_orbits) - 24usize];
1696};
1697impl Default for EmpyreanOrbitBatch {
1698    fn default() -> Self {
1699        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
1700        unsafe {
1701            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
1702            s.assume_init()
1703        }
1704    }
1705}
1706#[doc = " Per-observation result from orbit determination or evaluation.\n\n Mirrors scott's [`ObservationResult`](scott::results::ObservationResult)\n — every field upstream produces is carried across the C ABI. NaN /\n `EMPYREAN_REJECTION_NOT_EVALUATED` mark fields that aren't populated\n for the call type (e.g. evaluate doesn't compute rejection or\n influence diagnostics).\n\n `obs_id` is a heap-allocated NUL-terminated UTF-8 string; the\n pointer is freed by [`empyrean_od_result_free`] /\n [`empyrean_evaluate_result_free`] when the parent array is freed.\n Do NOT free it manually."]
1707#[repr(C)]
1708#[derive(Debug, Copy, Clone)]
1709pub struct EmpyreanObservationResult {
1710    #[doc = " ADES `obsID` (or scott auto-assigned). Owned by the parent array\n — freed by the matching `*_result_free` call."]
1711    pub obs_id: *mut ::std::os::raw::c_char,
1712    #[doc = " MPC observatory code (3-byte + NUL)."]
1713    pub obs_code: [u8; 4usize],
1714    #[doc = " Star catalog used for astrometric reduction (ADES `astCat`).\n Heap-allocated; null when ADES did not carry one. Freed with the array."]
1715    pub ast_cat: *mut ::std::os::raw::c_char,
1716    #[doc = " Observation epoch (MJD TDB)."]
1717    pub epoch_mjd_tdb: f64,
1718    #[doc = " RA·cosδ residual (observed - predicted), arcsec."]
1719    pub ra_residual_arcsec: f64,
1720    #[doc = " Dec residual, arcsec."]
1721    pub dec_residual_arcsec: f64,
1722    #[doc = " Mahalanobis χ² of this observation. NaN if covariance unavailable."]
1723    pub chi2: f64,
1724    #[doc = " Degrees of freedom (number of non-NaN residual dimensions)."]
1725    pub dof: u32,
1726    #[doc = " χ² survival probability."]
1727    pub probability: f64,
1728    #[doc = " Whether this observation was used in the fit (1 = yes, 0 = no)."]
1729    pub selected: u8,
1730    #[doc = " Combined obs+predicted RA covariance (arcsec²). NaN if absent."]
1731    pub residual_cov_ra: f64,
1732    #[doc = " Combined obs+predicted Dec covariance (arcsec²). NaN if absent."]
1733    pub residual_cov_dec: f64,
1734    #[doc = " Off-diagonal correlation coefficient (dimensionless, [-1, 1]). NaN if absent."]
1735    pub residual_cov_corr: f64,
1736    #[doc = " Reason this observation was kept / rejected. One of the\n `EMPYREAN_REJECTION_*` codes; `EMPYREAN_REJECTION_NOT_EVALUATED`\n when the call did not run rejection (e.g. `empyrean_evaluate`)."]
1737    pub rejection_reason: i32,
1738    #[doc = " Criterion value (chi², Cook's D, …) tested against the threshold. NaN if not evaluated."]
1739    pub rejection_criterion: f64,
1740    #[doc = " Static threshold the criterion was compared against. NaN if not evaluated."]
1741    pub rejection_threshold: f64,
1742    #[doc = " Effective threshold for adaptive rejection (Layer 3). NaN otherwise."]
1743    pub rejection_effective_threshold: f64,
1744    #[doc = " D-optimality information loss from removing this observation. NaN if not computed."]
1745    pub rejection_information_loss: f64,
1746    #[doc = " Cook's distance. NaN if no influence pass was run."]
1747    pub cooks_distance: f64,
1748    #[doc = " Scalar leverage h_ii ∈ [0, 2]. NaN if no influence pass."]
1749    pub leverage: f64,
1750    #[doc = " D-optimality fractional information contribution\n `f_i = tr(N⁻¹ I_i)`. NaN if no influence pass."]
1751    pub fractional_information: f64,
1752    #[doc = " Along-track residual (arcsec). NaN if no sky-motion rates."]
1753    pub along_track_arcsec: f64,
1754    #[doc = " Cross-track residual (arcsec). NaN if no sky-motion rates."]
1755    pub cross_track_arcsec: f64,
1756    #[doc = " Along-track 1σ (arcsec). NaN if unavailable."]
1757    pub along_track_error_arcsec: f64,
1758    #[doc = " Cross-track 1σ (arcsec). NaN if unavailable."]
1759    pub cross_track_error_arcsec: f64,
1760    #[doc = " Position angle of sky motion (degrees, East of North). NaN if unavailable."]
1761    pub track_position_angle_deg: f64,
1762    #[doc = " D-optimality information loss on removal, from the influence
1763 pass: logdet(N) − logdet(N − I_i). NaN if no influence pass was
1764 run, or if removing this observation makes the normal matrix
1765 singular (the observation is indispensable)."]
1766    pub influence_information_loss: f64,
1767    #[doc = " Off-diagonal covariance of the (along-track, cross-track)
1768 residual pair (arcsec²). Symmetric 2×2: the diagonal is
1769 `along_track_error_arcsec`² / `cross_track_error_arcsec`².
1770 NaN when the AT/CT covariance is unavailable."]
1771    pub along_cross_covariance_arcsec2: f64,
1772    #[doc = " Radar (delay/Doppler) residual: observed − predicted. Seconds
1773 for delay, hertz for Doppler (see `radar_kind`). NaN when
1774 `has_radar == 0`."]
1775    pub radar_residual: f64,
1776    #[doc = " χ² of the radar residual. NaN when `has_radar == 0`."]
1777    pub radar_chi2: f64,
1778    #[doc = " χ² survival probability of the radar residual. NaN when
1779 `has_radar == 0`."]
1780    pub radar_probability: f64,
1781    #[doc = " Combined observed+predicted radar residual variance (s² for
1782 delay, Hz² for Doppler). NaN when unavailable or
1783 `has_radar == 0`."]
1784    pub radar_variance: f64,
1785    #[doc = " Degrees of freedom of the radar residual (1 for radar). 0 when
1786 `has_radar == 0`."]
1787    pub radar_dof: u32,
1788    #[doc = " 1 when this row is a radar observation and the `radar_*` fields
1789 are live. The optical RA/Dec residual fields are NaN on radar
1790 rows."]
1791    pub has_radar: u8,
1792    #[doc = " `EMPYREAN_RADAR_KIND_DELAY` (0) or `EMPYREAN_RADAR_KIND_DOPPLER`
1793 (1). Only meaningful when `has_radar == 1`."]
1794    pub radar_kind: u8,
1795}
1796#[allow(clippy::unnecessary_operation, clippy::identity_op)]
1797const _: () = {
1798    ["Size of EmpyreanObservationResult"]
1799        [::std::mem::size_of::<EmpyreanObservationResult>() - 264usize];
1800    ["Alignment of EmpyreanObservationResult"]
1801        [::std::mem::align_of::<EmpyreanObservationResult>() - 8usize];
1802    ["Offset of field: EmpyreanObservationResult::obs_id"]
1803        [::std::mem::offset_of!(EmpyreanObservationResult, obs_id) - 0usize];
1804    ["Offset of field: EmpyreanObservationResult::obs_code"]
1805        [::std::mem::offset_of!(EmpyreanObservationResult, obs_code) - 8usize];
1806    ["Offset of field: EmpyreanObservationResult::ast_cat"]
1807        [::std::mem::offset_of!(EmpyreanObservationResult, ast_cat) - 16usize];
1808    ["Offset of field: EmpyreanObservationResult::epoch_mjd_tdb"]
1809        [::std::mem::offset_of!(EmpyreanObservationResult, epoch_mjd_tdb) - 24usize];
1810    ["Offset of field: EmpyreanObservationResult::ra_residual_arcsec"]
1811        [::std::mem::offset_of!(EmpyreanObservationResult, ra_residual_arcsec) - 32usize];
1812    ["Offset of field: EmpyreanObservationResult::dec_residual_arcsec"]
1813        [::std::mem::offset_of!(EmpyreanObservationResult, dec_residual_arcsec) - 40usize];
1814    ["Offset of field: EmpyreanObservationResult::chi2"]
1815        [::std::mem::offset_of!(EmpyreanObservationResult, chi2) - 48usize];
1816    ["Offset of field: EmpyreanObservationResult::dof"]
1817        [::std::mem::offset_of!(EmpyreanObservationResult, dof) - 56usize];
1818    ["Offset of field: EmpyreanObservationResult::probability"]
1819        [::std::mem::offset_of!(EmpyreanObservationResult, probability) - 64usize];
1820    ["Offset of field: EmpyreanObservationResult::selected"]
1821        [::std::mem::offset_of!(EmpyreanObservationResult, selected) - 72usize];
1822    ["Offset of field: EmpyreanObservationResult::residual_cov_ra"]
1823        [::std::mem::offset_of!(EmpyreanObservationResult, residual_cov_ra) - 80usize];
1824    ["Offset of field: EmpyreanObservationResult::residual_cov_dec"]
1825        [::std::mem::offset_of!(EmpyreanObservationResult, residual_cov_dec) - 88usize];
1826    ["Offset of field: EmpyreanObservationResult::residual_cov_corr"]
1827        [::std::mem::offset_of!(EmpyreanObservationResult, residual_cov_corr) - 96usize];
1828    ["Offset of field: EmpyreanObservationResult::rejection_reason"]
1829        [::std::mem::offset_of!(EmpyreanObservationResult, rejection_reason) - 104usize];
1830    ["Offset of field: EmpyreanObservationResult::rejection_criterion"]
1831        [::std::mem::offset_of!(EmpyreanObservationResult, rejection_criterion) - 112usize];
1832    ["Offset of field: EmpyreanObservationResult::rejection_threshold"]
1833        [::std::mem::offset_of!(EmpyreanObservationResult, rejection_threshold) - 120usize];
1834    ["Offset of field: EmpyreanObservationResult::rejection_effective_threshold"][::std::mem::offset_of!(
1835        EmpyreanObservationResult,
1836        rejection_effective_threshold
1837    ) - 128usize];
1838    ["Offset of field: EmpyreanObservationResult::rejection_information_loss"]
1839        [::std::mem::offset_of!(EmpyreanObservationResult, rejection_information_loss) - 136usize];
1840    ["Offset of field: EmpyreanObservationResult::cooks_distance"]
1841        [::std::mem::offset_of!(EmpyreanObservationResult, cooks_distance) - 144usize];
1842    ["Offset of field: EmpyreanObservationResult::leverage"]
1843        [::std::mem::offset_of!(EmpyreanObservationResult, leverage) - 152usize];
1844    ["Offset of field: EmpyreanObservationResult::fractional_information"]
1845        [::std::mem::offset_of!(EmpyreanObservationResult, fractional_information) - 160usize];
1846    ["Offset of field: EmpyreanObservationResult::along_track_arcsec"]
1847        [::std::mem::offset_of!(EmpyreanObservationResult, along_track_arcsec) - 168usize];
1848    ["Offset of field: EmpyreanObservationResult::cross_track_arcsec"]
1849        [::std::mem::offset_of!(EmpyreanObservationResult, cross_track_arcsec) - 176usize];
1850    ["Offset of field: EmpyreanObservationResult::along_track_error_arcsec"]
1851        [::std::mem::offset_of!(EmpyreanObservationResult, along_track_error_arcsec) - 184usize];
1852    ["Offset of field: EmpyreanObservationResult::cross_track_error_arcsec"]
1853        [::std::mem::offset_of!(EmpyreanObservationResult, cross_track_error_arcsec) - 192usize];
1854    ["Offset of field: EmpyreanObservationResult::track_position_angle_deg"]
1855        [::std::mem::offset_of!(EmpyreanObservationResult, track_position_angle_deg) - 200usize];
1856    ["Offset of field: EmpyreanObservationResult::influence_information_loss"]
1857        [::std::mem::offset_of!(EmpyreanObservationResult, influence_information_loss) - 208usize];
1858    ["Offset of field: EmpyreanObservationResult::along_cross_covariance_arcsec2"]
1859        [::std::mem::offset_of!(EmpyreanObservationResult, along_cross_covariance_arcsec2)
1860            - 216usize];
1861    ["Offset of field: EmpyreanObservationResult::radar_residual"]
1862        [::std::mem::offset_of!(EmpyreanObservationResult, radar_residual) - 224usize];
1863    ["Offset of field: EmpyreanObservationResult::radar_chi2"]
1864        [::std::mem::offset_of!(EmpyreanObservationResult, radar_chi2) - 232usize];
1865    ["Offset of field: EmpyreanObservationResult::radar_probability"]
1866        [::std::mem::offset_of!(EmpyreanObservationResult, radar_probability) - 240usize];
1867    ["Offset of field: EmpyreanObservationResult::radar_variance"]
1868        [::std::mem::offset_of!(EmpyreanObservationResult, radar_variance) - 248usize];
1869    ["Offset of field: EmpyreanObservationResult::radar_dof"]
1870        [::std::mem::offset_of!(EmpyreanObservationResult, radar_dof) - 256usize];
1871    ["Offset of field: EmpyreanObservationResult::has_radar"]
1872        [::std::mem::offset_of!(EmpyreanObservationResult, has_radar) - 260usize];
1873    ["Offset of field: EmpyreanObservationResult::radar_kind"]
1874        [::std::mem::offset_of!(EmpyreanObservationResult, radar_kind) - 261usize];
1875};
1876impl Default for EmpyreanObservationResult {
1877    fn default() -> Self {
1878        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
1879        unsafe {
1880            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
1881            s.assume_init()
1882        }
1883    }
1884}
1885#[doc = " Result containing an array of observer states."]
1886#[repr(C)]
1887#[derive(Debug, Copy, Clone)]
1888pub struct EmpyreanObserverResult {
1889    pub observers: *mut EmpyreanObserver,
1890    pub num_observers: usize,
1891}
1892#[allow(clippy::unnecessary_operation, clippy::identity_op)]
1893const _: () = {
1894    ["Size of EmpyreanObserverResult"][::std::mem::size_of::<EmpyreanObserverResult>() - 16usize];
1895    ["Alignment of EmpyreanObserverResult"]
1896        [::std::mem::align_of::<EmpyreanObserverResult>() - 8usize];
1897    ["Offset of field: EmpyreanObserverResult::observers"]
1898        [::std::mem::offset_of!(EmpyreanObserverResult, observers) - 0usize];
1899    ["Offset of field: EmpyreanObserverResult::num_observers"]
1900        [::std::mem::offset_of!(EmpyreanObserverResult, num_observers) - 8usize];
1901};
1902impl Default for EmpyreanObserverResult {
1903    fn default() -> Self {
1904        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
1905        unsafe {
1906            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
1907            s.assume_init()
1908        }
1909    }
1910}
1911#[doc = " A single optical observation for orbit determination — full ADES schema.\n\n String fields are nullable (`null` pointer = absent). Float fields\n use NaN as the absent sentinel. The `n_stars` integer uses `-1` as\n the absent sentinel (since `u32::MAX` is a valid count). The\n `obs_code` is fixed-size 4-byte null-padded to keep the common case\n allocation-free.\n\n Mirrors scott's `OpticalObservation` field-for-field — every named\n PSV column round-trips losslessly except for ADES extension fields\n not yet in the upstream schema."]
1912#[repr(C)]
1913#[derive(Debug, Copy, Clone)]
1914pub struct EmpyreanObservation {
1915    #[doc = " IAU permanent designation (nullable)."]
1916    pub perm_id: *mut ::std::os::raw::c_char,
1917    #[doc = " MPC provisional designation (nullable)."]
1918    pub prov_id: *mut ::std::os::raw::c_char,
1919    #[doc = " Observer-assigned tracklet identifier (nullable)."]
1920    pub trk_sub: *mut ::std::os::raw::c_char,
1921    #[doc = " MPC-assigned observation identifier (`obsid`, nullable)."]
1922    pub obs_id: *mut ::std::os::raw::c_char,
1923    #[doc = " Observer-assigned sub-identifier (`obsSubID`, nullable)."]
1924    pub obs_sub_id: *mut ::std::os::raw::c_char,
1925    #[doc = " Track identifier (`trkID`, nullable)."]
1926    pub trk_id: *mut ::std::os::raw::c_char,
1927    #[doc = " MPC observatory code, null-padded to 4 bytes."]
1928    pub obs_code: [u8; 4usize],
1929    #[doc = " Observation mode (CCD, CMOS, etc.) (nullable)."]
1930    pub mode: *mut ::std::os::raw::c_char,
1931    #[doc = " MPC program code (nullable)."]
1932    pub prog: *mut ::std::os::raw::c_char,
1933    #[doc = " Coordinate system for observer position (nullable)."]
1934    pub sys: *mut ::std::os::raw::c_char,
1935    #[doc = " Center body NAIF ID. NaN if unset."]
1936    pub ctr: f64,
1937    #[doc = " Position component 1 (lon for WGS84, X for ICRF_KM). NaN if unset."]
1938    pub pos1: f64,
1939    #[doc = " Position component 2 (lat for WGS84, Y for ICRF_KM). NaN if unset."]
1940    pub pos2: f64,
1941    #[doc = " Position component 3 (alt for WGS84, Z for ICRF_KM). NaN if unset."]
1942    pub pos3: f64,
1943    #[doc = " Observation time as ISO 8601 UTC string."]
1944    pub obs_time: *mut ::std::os::raw::c_char,
1945    #[doc = " Right ascension (degrees)."]
1946    pub ra_deg: f64,
1947    #[doc = " Declination (degrees)."]
1948    pub dec_deg: f64,
1949    #[doc = " RA·cos(Dec) uncertainty (arcseconds). NaN if unavailable."]
1950    pub rms_ra_arcsec: f64,
1951    #[doc = " Dec uncertainty (arcseconds). NaN if unavailable."]
1952    pub rms_dec_arcsec: f64,
1953    #[doc = " RA-Dec correlation coefficient [-1, 1]. NaN if unavailable."]
1954    pub rms_corr: f64,
1955    #[doc = " Star catalog used for astrometric reduction (nullable)."]
1956    pub ast_cat: *mut ::std::os::raw::c_char,
1957    #[doc = " Apparent magnitude. NaN if unavailable."]
1958    pub mag: f64,
1959    #[doc = " Magnitude uncertainty. NaN if unavailable."]
1960    pub rms_mag: f64,
1961    #[doc = " Photometric passband (nullable)."]
1962    pub band: *mut ::std::os::raw::c_char,
1963    #[doc = " Photometric catalog (nullable)."]
1964    pub phot_cat: *mut ::std::os::raw::c_char,
1965    #[doc = " Photometric aperture (arcseconds). NaN if unavailable."]
1966    pub phot_ap: f64,
1967    #[doc = " log10(SNR) of the detection. NaN if unavailable."]
1968    pub log_snr: f64,
1969    #[doc = " Seeing FWHM (arcseconds). NaN if unavailable."]
1970    pub seeing: f64,
1971    #[doc = " Exposure time (seconds). NaN if unavailable."]
1972    pub exp: f64,
1973    #[doc = " RMS of astrometric fit (arcseconds). NaN if unavailable."]
1974    pub rms_fit: f64,
1975    #[doc = " Number of reference stars in astrometric fit. -1 if unavailable."]
1976    pub n_stars: i32,
1977    #[doc = " MPC note flags (nullable)."]
1978    pub notes: *mut ::std::os::raw::c_char,
1979    #[doc = " Free-text observer remarks (nullable)."]
1980    pub remarks: *mut ::std::os::raw::c_char,
1981}
1982#[allow(clippy::unnecessary_operation, clippy::identity_op)]
1983const _: () = {
1984    ["Size of EmpyreanObservation"][::std::mem::size_of::<EmpyreanObservation>() - 264usize];
1985    ["Alignment of EmpyreanObservation"][::std::mem::align_of::<EmpyreanObservation>() - 8usize];
1986    ["Offset of field: EmpyreanObservation::perm_id"]
1987        [::std::mem::offset_of!(EmpyreanObservation, perm_id) - 0usize];
1988    ["Offset of field: EmpyreanObservation::prov_id"]
1989        [::std::mem::offset_of!(EmpyreanObservation, prov_id) - 8usize];
1990    ["Offset of field: EmpyreanObservation::trk_sub"]
1991        [::std::mem::offset_of!(EmpyreanObservation, trk_sub) - 16usize];
1992    ["Offset of field: EmpyreanObservation::obs_id"]
1993        [::std::mem::offset_of!(EmpyreanObservation, obs_id) - 24usize];
1994    ["Offset of field: EmpyreanObservation::obs_sub_id"]
1995        [::std::mem::offset_of!(EmpyreanObservation, obs_sub_id) - 32usize];
1996    ["Offset of field: EmpyreanObservation::trk_id"]
1997        [::std::mem::offset_of!(EmpyreanObservation, trk_id) - 40usize];
1998    ["Offset of field: EmpyreanObservation::obs_code"]
1999        [::std::mem::offset_of!(EmpyreanObservation, obs_code) - 48usize];
2000    ["Offset of field: EmpyreanObservation::mode"]
2001        [::std::mem::offset_of!(EmpyreanObservation, mode) - 56usize];
2002    ["Offset of field: EmpyreanObservation::prog"]
2003        [::std::mem::offset_of!(EmpyreanObservation, prog) - 64usize];
2004    ["Offset of field: EmpyreanObservation::sys"]
2005        [::std::mem::offset_of!(EmpyreanObservation, sys) - 72usize];
2006    ["Offset of field: EmpyreanObservation::ctr"]
2007        [::std::mem::offset_of!(EmpyreanObservation, ctr) - 80usize];
2008    ["Offset of field: EmpyreanObservation::pos1"]
2009        [::std::mem::offset_of!(EmpyreanObservation, pos1) - 88usize];
2010    ["Offset of field: EmpyreanObservation::pos2"]
2011        [::std::mem::offset_of!(EmpyreanObservation, pos2) - 96usize];
2012    ["Offset of field: EmpyreanObservation::pos3"]
2013        [::std::mem::offset_of!(EmpyreanObservation, pos3) - 104usize];
2014    ["Offset of field: EmpyreanObservation::obs_time"]
2015        [::std::mem::offset_of!(EmpyreanObservation, obs_time) - 112usize];
2016    ["Offset of field: EmpyreanObservation::ra_deg"]
2017        [::std::mem::offset_of!(EmpyreanObservation, ra_deg) - 120usize];
2018    ["Offset of field: EmpyreanObservation::dec_deg"]
2019        [::std::mem::offset_of!(EmpyreanObservation, dec_deg) - 128usize];
2020    ["Offset of field: EmpyreanObservation::rms_ra_arcsec"]
2021        [::std::mem::offset_of!(EmpyreanObservation, rms_ra_arcsec) - 136usize];
2022    ["Offset of field: EmpyreanObservation::rms_dec_arcsec"]
2023        [::std::mem::offset_of!(EmpyreanObservation, rms_dec_arcsec) - 144usize];
2024    ["Offset of field: EmpyreanObservation::rms_corr"]
2025        [::std::mem::offset_of!(EmpyreanObservation, rms_corr) - 152usize];
2026    ["Offset of field: EmpyreanObservation::ast_cat"]
2027        [::std::mem::offset_of!(EmpyreanObservation, ast_cat) - 160usize];
2028    ["Offset of field: EmpyreanObservation::mag"]
2029        [::std::mem::offset_of!(EmpyreanObservation, mag) - 168usize];
2030    ["Offset of field: EmpyreanObservation::rms_mag"]
2031        [::std::mem::offset_of!(EmpyreanObservation, rms_mag) - 176usize];
2032    ["Offset of field: EmpyreanObservation::band"]
2033        [::std::mem::offset_of!(EmpyreanObservation, band) - 184usize];
2034    ["Offset of field: EmpyreanObservation::phot_cat"]
2035        [::std::mem::offset_of!(EmpyreanObservation, phot_cat) - 192usize];
2036    ["Offset of field: EmpyreanObservation::phot_ap"]
2037        [::std::mem::offset_of!(EmpyreanObservation, phot_ap) - 200usize];
2038    ["Offset of field: EmpyreanObservation::log_snr"]
2039        [::std::mem::offset_of!(EmpyreanObservation, log_snr) - 208usize];
2040    ["Offset of field: EmpyreanObservation::seeing"]
2041        [::std::mem::offset_of!(EmpyreanObservation, seeing) - 216usize];
2042    ["Offset of field: EmpyreanObservation::exp"]
2043        [::std::mem::offset_of!(EmpyreanObservation, exp) - 224usize];
2044    ["Offset of field: EmpyreanObservation::rms_fit"]
2045        [::std::mem::offset_of!(EmpyreanObservation, rms_fit) - 232usize];
2046    ["Offset of field: EmpyreanObservation::n_stars"]
2047        [::std::mem::offset_of!(EmpyreanObservation, n_stars) - 240usize];
2048    ["Offset of field: EmpyreanObservation::notes"]
2049        [::std::mem::offset_of!(EmpyreanObservation, notes) - 248usize];
2050    ["Offset of field: EmpyreanObservation::remarks"]
2051        [::std::mem::offset_of!(EmpyreanObservation, remarks) - 256usize];
2052};
2053impl Default for EmpyreanObservation {
2054    fn default() -> Self {
2055        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
2056        unsafe {
2057            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
2058            s.assume_init()
2059        }
2060    }
2061}
2062#[doc = " A single radar (delay or Doppler) observation for orbit determination —\n the ADES `<radar>` schema.\n\n ADES models radar astrometry as its own top-level table, parallel to\n `<optical>` (not as an optical `mode`). A record carries a round-trip\n time **delay** *or* a **Doppler** shift (the ADES `RadarValue` is an\n XSD `<choice>`), referred to a transmitting (`trx`) and receiving\n (`rcv`) station — equal for a monostatic observation, distinct for a\n bistatic one.\n\n **Units are ADES-native through this FFI — the C ABI performs ZERO unit\n conversion.** The delay *value* is in **seconds** while its uncertainty\n `rms_delay_microseconds` is in **microseconds** (this asymmetry is\n intentional in the ADES schema, verified against the IAU-ADES\n `a4179_radar` reference data and the JPL SSD radar API); Doppler value\n and uncertainty are both in **Hz**; `frq_mhz` is in **MHz**. The single\n SI normalisation happens once downstream in scott's\n `Observation::from_radar`, never here.\n\n String fields are nullable (`null` pointer = absent). The `trx`/`rcv`\n station codes are fixed-size 4-byte null-padded (like `obs_code`).\n Absent f64 fields use `f64::NAN`. The `com` flag is a tri-state `i8`.\n No field is silently zeroed or defaulted.\n\n Mirrors scott's `RadarObservation` field-for-field."]
2063#[repr(C)]
2064#[derive(Debug, Copy, Clone)]
2065pub struct EmpyreanRadarObservation {
2066    #[doc = " IAU permanent designation (nullable)."]
2067    pub perm_id: *mut ::std::os::raw::c_char,
2068    #[doc = " MPC provisional designation (nullable)."]
2069    pub prov_id: *mut ::std::os::raw::c_char,
2070    #[doc = " Observer-assigned tracklet identifier (nullable)."]
2071    pub trk_sub: *mut ::std::os::raw::c_char,
2072    #[doc = " MPC station code of the **transmitting** antenna (ADES `trx`),\n null-padded to 4 bytes."]
2073    pub trx: [u8; 4usize],
2074    #[doc = " MPC station code of the **receiving** antenna (ADES `rcv`),\n null-padded to 4 bytes. Equal to `trx` for a monostatic\n observation; differs for a bistatic one."]
2075    pub rcv: [u8; 4usize],
2076    #[doc = " Observation epoch as an ISO 8601 UTC string. For radar this is the\n **receive** epoch (the time the returned signal is recorded).\n Required, non-null."]
2077    pub obs_time: *mut ::std::os::raw::c_char,
2078    #[doc = " Measurement kind: `EMPYREAN_RADAR_KIND_DELAY` (0) or\n `EMPYREAN_RADAR_KIND_DOPPLER` (1). Selects which value pair is live."]
2079    pub kind: u8,
2080    #[doc = " Round-trip time delay in **seconds** (ADES-native). Valid iff\n `kind == EMPYREAN_RADAR_KIND_DELAY`, else `f64::NAN`."]
2081    pub delay_seconds: f64,
2082    #[doc = " 1σ uncertainty of the delay in **microseconds** (ADES-native; the\n asymmetry vs `delay_seconds` is intentional). Valid iff\n `kind == EMPYREAN_RADAR_KIND_DELAY`, else `f64::NAN`."]
2083    pub rms_delay_microseconds: f64,
2084    #[doc = " Doppler shift in **Hz** (ADES-native, signed). Valid iff\n `kind == EMPYREAN_RADAR_KIND_DOPPLER`, else `f64::NAN`."]
2085    pub doppler_hz: f64,
2086    #[doc = " 1σ uncertainty of the Doppler shift in **Hz** (ADES-native). Valid\n iff `kind == EMPYREAN_RADAR_KIND_DOPPLER`, else `f64::NAN`."]
2087    pub rms_doppler_hz: f64,
2088    #[doc = " Transmit carrier reference frequency in **MHz** (ADES `frq`).\n Required; relates a Doppler shift to a range rate."]
2089    pub frq_mhz: f64,
2090    #[doc = " Center-of-mass flag (ADES `com`), tri-state: `-1` = absent,\n `0` = false (peak-power / leading-edge reduction), `1` = true\n (reduced to target center of mass). Mirrors `Option<bool>`; a\n missing flag MUST map to `-1` (never `0`) — the ADES center-of-mass\n default is applied explicitly downstream, not silently here."]
2091    pub com: i8,
2092    #[doc = " log10(SNR) of the echo, if reported. `f64::NAN` if absent."]
2093    pub log_snr: f64,
2094    #[doc = " Free-text observer remarks (nullable)."]
2095    pub remarks: *mut ::std::os::raw::c_char,
2096}
2097#[allow(clippy::unnecessary_operation, clippy::identity_op)]
2098const _: () = {
2099    ["Size of EmpyreanRadarObservation"]
2100        [::std::mem::size_of::<EmpyreanRadarObservation>() - 112usize];
2101    ["Alignment of EmpyreanRadarObservation"]
2102        [::std::mem::align_of::<EmpyreanRadarObservation>() - 8usize];
2103    ["Offset of field: EmpyreanRadarObservation::perm_id"]
2104        [::std::mem::offset_of!(EmpyreanRadarObservation, perm_id) - 0usize];
2105    ["Offset of field: EmpyreanRadarObservation::prov_id"]
2106        [::std::mem::offset_of!(EmpyreanRadarObservation, prov_id) - 8usize];
2107    ["Offset of field: EmpyreanRadarObservation::trk_sub"]
2108        [::std::mem::offset_of!(EmpyreanRadarObservation, trk_sub) - 16usize];
2109    ["Offset of field: EmpyreanRadarObservation::trx"]
2110        [::std::mem::offset_of!(EmpyreanRadarObservation, trx) - 24usize];
2111    ["Offset of field: EmpyreanRadarObservation::rcv"]
2112        [::std::mem::offset_of!(EmpyreanRadarObservation, rcv) - 28usize];
2113    ["Offset of field: EmpyreanRadarObservation::obs_time"]
2114        [::std::mem::offset_of!(EmpyreanRadarObservation, obs_time) - 32usize];
2115    ["Offset of field: EmpyreanRadarObservation::kind"]
2116        [::std::mem::offset_of!(EmpyreanRadarObservation, kind) - 40usize];
2117    ["Offset of field: EmpyreanRadarObservation::delay_seconds"]
2118        [::std::mem::offset_of!(EmpyreanRadarObservation, delay_seconds) - 48usize];
2119    ["Offset of field: EmpyreanRadarObservation::rms_delay_microseconds"]
2120        [::std::mem::offset_of!(EmpyreanRadarObservation, rms_delay_microseconds) - 56usize];
2121    ["Offset of field: EmpyreanRadarObservation::doppler_hz"]
2122        [::std::mem::offset_of!(EmpyreanRadarObservation, doppler_hz) - 64usize];
2123    ["Offset of field: EmpyreanRadarObservation::rms_doppler_hz"]
2124        [::std::mem::offset_of!(EmpyreanRadarObservation, rms_doppler_hz) - 72usize];
2125    ["Offset of field: EmpyreanRadarObservation::frq_mhz"]
2126        [::std::mem::offset_of!(EmpyreanRadarObservation, frq_mhz) - 80usize];
2127    ["Offset of field: EmpyreanRadarObservation::com"]
2128        [::std::mem::offset_of!(EmpyreanRadarObservation, com) - 88usize];
2129    ["Offset of field: EmpyreanRadarObservation::log_snr"]
2130        [::std::mem::offset_of!(EmpyreanRadarObservation, log_snr) - 96usize];
2131    ["Offset of field: EmpyreanRadarObservation::remarks"]
2132        [::std::mem::offset_of!(EmpyreanRadarObservation, remarks) - 104usize];
2133};
2134impl Default for EmpyreanRadarObservation {
2135    fn default() -> Self {
2136        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
2137        unsafe {
2138            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
2139            s.assume_init()
2140        }
2141    }
2142}
2143#[doc = " One element of [`EmpyreanWeightingConfig::additional_layers`].\n Tagged-union shape: the active fields depend on `kind`."]
2144#[repr(C)]
2145#[derive(Debug, Default, Copy, Clone)]
2146pub struct EmpyreanWeightingLayer {
2147    #[doc = " Layer kind discriminator — one of\n `EMPYREAN_WEIGHTING_LAYER_*`."]
2148    pub kind: i32,
2149    #[doc = " MPC observatory code, null-padded to 4 bytes."]
2150    pub obs_code: [u8; 4usize],
2151    #[doc = " 1σ RA·cos(δ) in arcsec."]
2152    pub sigma_ra_arcsec: f64,
2153    #[doc = " 1σ Dec in arcsec."]
2154    pub sigma_dec_arcsec: f64,
2155    #[doc = " Start of applicable time range (MJD TDB). NaN = unbounded."]
2156    pub start_epoch_mjd_tdb: f64,
2157    #[doc = " End of applicable time range (MJD TDB). NaN = unbounded."]
2158    pub end_epoch_mjd_tdb: f64,
2159    #[doc = " Scale factor on the resulting weight. 0.0 → upstream default (1.0)."]
2160    pub scale: f64,
2161    #[doc = " Maximum gap between observations to count as the same night\n (days). 0.0 → upstream default (0.5)."]
2162    pub max_gap_days: f64,
2163}
2164#[allow(clippy::unnecessary_operation, clippy::identity_op)]
2165const _: () = {
2166    ["Size of EmpyreanWeightingLayer"][::std::mem::size_of::<EmpyreanWeightingLayer>() - 56usize];
2167    ["Alignment of EmpyreanWeightingLayer"]
2168        [::std::mem::align_of::<EmpyreanWeightingLayer>() - 8usize];
2169    ["Offset of field: EmpyreanWeightingLayer::kind"]
2170        [::std::mem::offset_of!(EmpyreanWeightingLayer, kind) - 0usize];
2171    ["Offset of field: EmpyreanWeightingLayer::obs_code"]
2172        [::std::mem::offset_of!(EmpyreanWeightingLayer, obs_code) - 4usize];
2173    ["Offset of field: EmpyreanWeightingLayer::sigma_ra_arcsec"]
2174        [::std::mem::offset_of!(EmpyreanWeightingLayer, sigma_ra_arcsec) - 8usize];
2175    ["Offset of field: EmpyreanWeightingLayer::sigma_dec_arcsec"]
2176        [::std::mem::offset_of!(EmpyreanWeightingLayer, sigma_dec_arcsec) - 16usize];
2177    ["Offset of field: EmpyreanWeightingLayer::start_epoch_mjd_tdb"]
2178        [::std::mem::offset_of!(EmpyreanWeightingLayer, start_epoch_mjd_tdb) - 24usize];
2179    ["Offset of field: EmpyreanWeightingLayer::end_epoch_mjd_tdb"]
2180        [::std::mem::offset_of!(EmpyreanWeightingLayer, end_epoch_mjd_tdb) - 32usize];
2181    ["Offset of field: EmpyreanWeightingLayer::scale"]
2182        [::std::mem::offset_of!(EmpyreanWeightingLayer, scale) - 40usize];
2183    ["Offset of field: EmpyreanWeightingLayer::max_gap_days"]
2184        [::std::mem::offset_of!(EmpyreanWeightingLayer, max_gap_days) - 48usize];
2185};
2186#[doc = " Weighting configuration. Mirrors\n [`scott::weighting::WeightingConfig`] structurally; extends it\n with an `enabled` toggle and a preset selector for the common\n case of \"use the production preset\" without constructing layers\n by hand.\n\n `enabled = 0` runs OD with uniform 1″ weighting (the old\n `use_weighting = 0` behavior). `enabled = 1` activates the\n pipeline; the resulting layer chain is the preset's layers\n followed by `additional_layers` (allows e.g. VFC17 + per-survey\n override)."]
2187#[repr(C)]
2188#[derive(Debug, Copy, Clone)]
2189pub struct EmpyreanWeightingConfig {
2190    #[doc = " 1 = enabled (default), 0 = uniform 1″ weighting."]
2191    pub enabled: u8,
2192    #[doc = " Preset selector. One of `EMPYREAN_WEIGHTING_PRESET_*`.\n Default `0` (NONE) means \"use additional_layers only\";\n when `enabled = 1` and zero-init, the conversion code\n substitutes `VFC17` so default-zero structs keep the\n production behavior."]
2193    pub preset: u8,
2194    #[doc = " Default 1σ used when no rule applies (arcsec). 0.0 →\n upstream default (1.0). Ignored when preset != NONE."]
2195    pub default_sigma_arcsec: f64,
2196    #[doc = " Sigma combination policy. -1 = use the preset's policy;\n otherwise one of `EMPYREAN_SIGMA_POLICY_*`."]
2197    pub sigma_policy: i32,
2198    #[doc = " Pointer to additional layers appended to the preset's chain.\n Non-owning — caller keeps the array alive for the OD call."]
2199    pub additional_layers: *const EmpyreanWeightingLayer,
2200    pub num_additional_layers: usize,
2201}
2202#[allow(clippy::unnecessary_operation, clippy::identity_op)]
2203const _: () = {
2204    ["Size of EmpyreanWeightingConfig"][::std::mem::size_of::<EmpyreanWeightingConfig>() - 40usize];
2205    ["Alignment of EmpyreanWeightingConfig"]
2206        [::std::mem::align_of::<EmpyreanWeightingConfig>() - 8usize];
2207    ["Offset of field: EmpyreanWeightingConfig::enabled"]
2208        [::std::mem::offset_of!(EmpyreanWeightingConfig, enabled) - 0usize];
2209    ["Offset of field: EmpyreanWeightingConfig::preset"]
2210        [::std::mem::offset_of!(EmpyreanWeightingConfig, preset) - 1usize];
2211    ["Offset of field: EmpyreanWeightingConfig::default_sigma_arcsec"]
2212        [::std::mem::offset_of!(EmpyreanWeightingConfig, default_sigma_arcsec) - 8usize];
2213    ["Offset of field: EmpyreanWeightingConfig::sigma_policy"]
2214        [::std::mem::offset_of!(EmpyreanWeightingConfig, sigma_policy) - 16usize];
2215    ["Offset of field: EmpyreanWeightingConfig::additional_layers"]
2216        [::std::mem::offset_of!(EmpyreanWeightingConfig, additional_layers) - 24usize];
2217    ["Offset of field: EmpyreanWeightingConfig::num_additional_layers"]
2218        [::std::mem::offset_of!(EmpyreanWeightingConfig, num_additional_layers) - 32usize];
2219};
2220impl Default for EmpyreanWeightingConfig {
2221    fn default() -> Self {
2222        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
2223        unsafe {
2224            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
2225            s.assume_init()
2226        }
2227    }
2228}
2229#[doc = " Catalog-bias-correction configuration. Mirrors scott's\n `Option<Arc<DebiasingTable>>` field on `ODConfig`.\n\n `enabled = 0` runs OD with no catalog debiasing (matches the old\n `use_debiasing = 0` behavior). `enabled = 1` activates the\n EFCC2020 pipeline; the table is loaded from `bias_dat_path` if\n non-NULL, otherwise from the DataManager-default location at the\n requested `resolution`."]
2230#[repr(C)]
2231#[derive(Debug, Copy, Clone)]
2232pub struct EmpyreanDebiasingConfig {
2233    #[doc = " 1 = on (default), 0 = no debiasing."]
2234    pub enabled: u8,
2235    #[doc = " Table identity. Currently `EFCC2020` only."]
2236    pub table_id: i32,
2237    #[doc = " `EMPYREAN_DEBIASING_RESOLUTION_*` — Standard (~35 MB) or Hires (~567 MB)."]
2238    pub resolution: i32,
2239    #[doc = " Optional path to the bias.dat file. NULL = DataManager default.\n Non-owning."]
2240    pub bias_dat_path: *const ::std::os::raw::c_char,
2241}
2242#[allow(clippy::unnecessary_operation, clippy::identity_op)]
2243const _: () = {
2244    ["Size of EmpyreanDebiasingConfig"][::std::mem::size_of::<EmpyreanDebiasingConfig>() - 24usize];
2245    ["Alignment of EmpyreanDebiasingConfig"]
2246        [::std::mem::align_of::<EmpyreanDebiasingConfig>() - 8usize];
2247    ["Offset of field: EmpyreanDebiasingConfig::enabled"]
2248        [::std::mem::offset_of!(EmpyreanDebiasingConfig, enabled) - 0usize];
2249    ["Offset of field: EmpyreanDebiasingConfig::table_id"]
2250        [::std::mem::offset_of!(EmpyreanDebiasingConfig, table_id) - 4usize];
2251    ["Offset of field: EmpyreanDebiasingConfig::resolution"]
2252        [::std::mem::offset_of!(EmpyreanDebiasingConfig, resolution) - 8usize];
2253    ["Offset of field: EmpyreanDebiasingConfig::bias_dat_path"]
2254        [::std::mem::offset_of!(EmpyreanDebiasingConfig, bias_dat_path) - 16usize];
2255};
2256impl Default for EmpyreanDebiasingConfig {
2257    fn default() -> Self {
2258        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
2259        unsafe {
2260            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
2261            s.assume_init()
2262        }
2263    }
2264}
2265#[doc = " Origin-policy selector for the OD pipeline (mirrors\n [`OriginPolicy`]).\n\n `policy = EMPYREAN_ORIGIN_POLICY_AUTO` ignores `explicit_naif`;\n `_EXPLICIT` interprets the field as the NAIF body ID of the central\n body to pin to (e.g. 10 = Sun, 399 = Earth, 4 = Mars-barycenter)."]
2266#[repr(C)]
2267#[derive(Debug, Default, Copy, Clone)]
2268pub struct EmpyreanOriginPolicy {
2269    pub policy: i32,
2270    pub explicit_naif: i32,
2271}
2272#[allow(clippy::unnecessary_operation, clippy::identity_op)]
2273const _: () = {
2274    ["Size of EmpyreanOriginPolicy"][::std::mem::size_of::<EmpyreanOriginPolicy>() - 8usize];
2275    ["Alignment of EmpyreanOriginPolicy"][::std::mem::align_of::<EmpyreanOriginPolicy>() - 4usize];
2276    ["Offset of field: EmpyreanOriginPolicy::policy"]
2277        [::std::mem::offset_of!(EmpyreanOriginPolicy, policy) - 0usize];
2278    ["Offset of field: EmpyreanOriginPolicy::explicit_naif"]
2279        [::std::mem::offset_of!(EmpyreanOriginPolicy, explicit_naif) - 4usize];
2280};
2281#[doc = " IOD ranging tuning (mirrors the IOD section of [`scott::od::ODConfig`]).\n\n Nested rather than flattened so callers can pass the bundle around\n as a single value and zero-init pulls the upstream defaults\n uniformly. Sentinel rule: `0` / `0.0` requests the upstream default;\n `opposition_gap_days < 0` disables opposition splitting."]
2282#[repr(C)]
2283#[derive(Debug, Default, Copy, Clone)]
2284pub struct EmpyreanIODConfig {
2285    pub max_triplet_attempts: u32,
2286    pub max_triplet_span_days: f64,
2287    #[doc = " `-1.0` disables opposition splitting; `0.0` uses upstream default (90)."]
2288    pub opposition_gap_days: f64,
2289    pub max_iod_arc_days: f64,
2290    pub curvature_snr_threshold: f64,
2291    pub max_iod_fractional_sigma_a: f64,
2292}
2293#[allow(clippy::unnecessary_operation, clippy::identity_op)]
2294const _: () = {
2295    ["Size of EmpyreanIODConfig"][::std::mem::size_of::<EmpyreanIODConfig>() - 48usize];
2296    ["Alignment of EmpyreanIODConfig"][::std::mem::align_of::<EmpyreanIODConfig>() - 8usize];
2297    ["Offset of field: EmpyreanIODConfig::max_triplet_attempts"]
2298        [::std::mem::offset_of!(EmpyreanIODConfig, max_triplet_attempts) - 0usize];
2299    ["Offset of field: EmpyreanIODConfig::max_triplet_span_days"]
2300        [::std::mem::offset_of!(EmpyreanIODConfig, max_triplet_span_days) - 8usize];
2301    ["Offset of field: EmpyreanIODConfig::opposition_gap_days"]
2302        [::std::mem::offset_of!(EmpyreanIODConfig, opposition_gap_days) - 16usize];
2303    ["Offset of field: EmpyreanIODConfig::max_iod_arc_days"]
2304        [::std::mem::offset_of!(EmpyreanIODConfig, max_iod_arc_days) - 24usize];
2305    ["Offset of field: EmpyreanIODConfig::curvature_snr_threshold"]
2306        [::std::mem::offset_of!(EmpyreanIODConfig, curvature_snr_threshold) - 32usize];
2307    ["Offset of field: EmpyreanIODConfig::max_iod_fractional_sigma_a"]
2308        [::std::mem::offset_of!(EmpyreanIODConfig, max_iod_fractional_sigma_a) - 40usize];
2309};
2310#[doc = " Output epoch specification (mirrors [`OutputEpoch`]).\n\n The `mode` field determines which variant is active:\n `EMPYREAN_OUTPUT_EPOCH_MID_ARC` / `_LAST_OBSERVATION` / `_IOD_EPOCH`\n ignore `explicit_mjd_tdb`; `_EXPLICIT` reads the field as MJD TDB."]
2311#[repr(C)]
2312#[derive(Debug, Default, Copy, Clone)]
2313pub struct EmpyreanOutputEpoch {
2314    pub mode: i32,
2315    pub explicit_mjd_tdb: f64,
2316}
2317#[allow(clippy::unnecessary_operation, clippy::identity_op)]
2318const _: () = {
2319    ["Size of EmpyreanOutputEpoch"][::std::mem::size_of::<EmpyreanOutputEpoch>() - 16usize];
2320    ["Alignment of EmpyreanOutputEpoch"][::std::mem::align_of::<EmpyreanOutputEpoch>() - 8usize];
2321    ["Offset of field: EmpyreanOutputEpoch::mode"]
2322        [::std::mem::offset_of!(EmpyreanOutputEpoch, mode) - 0usize];
2323    ["Offset of field: EmpyreanOutputEpoch::explicit_mjd_tdb"]
2324        [::std::mem::offset_of!(EmpyreanOutputEpoch, explicit_mjd_tdb) - 8usize];
2325};
2326#[doc = " Auto-escalation policy for [`SolveForParams::Auto`]\n (mirrors [`scott::od::AutoEscalationPolicy`]). Sentinel: `0` /\n `0.0` → upstream default."]
2327#[repr(C)]
2328#[derive(Debug, Default, Copy, Clone)]
2329pub struct EmpyreanAutoEscalationPolicy {
2330    pub reduced_chi2: f64,
2331    pub at_ct_ratio: f64,
2332    pub min_arc_days: f64,
2333    pub min_n_obs: u32,
2334}
2335#[allow(clippy::unnecessary_operation, clippy::identity_op)]
2336const _: () = {
2337    ["Size of EmpyreanAutoEscalationPolicy"]
2338        [::std::mem::size_of::<EmpyreanAutoEscalationPolicy>() - 32usize];
2339    ["Alignment of EmpyreanAutoEscalationPolicy"]
2340        [::std::mem::align_of::<EmpyreanAutoEscalationPolicy>() - 8usize];
2341    ["Offset of field: EmpyreanAutoEscalationPolicy::reduced_chi2"]
2342        [::std::mem::offset_of!(EmpyreanAutoEscalationPolicy, reduced_chi2) - 0usize];
2343    ["Offset of field: EmpyreanAutoEscalationPolicy::at_ct_ratio"]
2344        [::std::mem::offset_of!(EmpyreanAutoEscalationPolicy, at_ct_ratio) - 8usize];
2345    ["Offset of field: EmpyreanAutoEscalationPolicy::min_arc_days"]
2346        [::std::mem::offset_of!(EmpyreanAutoEscalationPolicy, min_arc_days) - 16usize];
2347    ["Offset of field: EmpyreanAutoEscalationPolicy::min_n_obs"]
2348        [::std::mem::offset_of!(EmpyreanAutoEscalationPolicy, min_n_obs) - 24usize];
2349};
2350#[doc = " Acceptability thresholds for the post-DC fit-quality checks\n (mirrors [`scott::od::AcceptabilityThresholds`]). Sentinel: `0.0` →\n upstream default."]
2351#[repr(C)]
2352#[derive(Debug, Default, Copy, Clone)]
2353pub struct EmpyreanAcceptabilityThresholds {
2354    pub reduced_chi2: f64,
2355    pub rms_arcsec: f64,
2356    pub at_ct_ratio: f64,
2357    pub min_arc_days: f64,
2358    pub fractional_sigma_a: f64,
2359}
2360#[allow(clippy::unnecessary_operation, clippy::identity_op)]
2361const _: () = {
2362    ["Size of EmpyreanAcceptabilityThresholds"]
2363        [::std::mem::size_of::<EmpyreanAcceptabilityThresholds>() - 40usize];
2364    ["Alignment of EmpyreanAcceptabilityThresholds"]
2365        [::std::mem::align_of::<EmpyreanAcceptabilityThresholds>() - 8usize];
2366    ["Offset of field: EmpyreanAcceptabilityThresholds::reduced_chi2"]
2367        [::std::mem::offset_of!(EmpyreanAcceptabilityThresholds, reduced_chi2) - 0usize];
2368    ["Offset of field: EmpyreanAcceptabilityThresholds::rms_arcsec"]
2369        [::std::mem::offset_of!(EmpyreanAcceptabilityThresholds, rms_arcsec) - 8usize];
2370    ["Offset of field: EmpyreanAcceptabilityThresholds::at_ct_ratio"]
2371        [::std::mem::offset_of!(EmpyreanAcceptabilityThresholds, at_ct_ratio) - 16usize];
2372    ["Offset of field: EmpyreanAcceptabilityThresholds::min_arc_days"]
2373        [::std::mem::offset_of!(EmpyreanAcceptabilityThresholds, min_arc_days) - 24usize];
2374    ["Offset of field: EmpyreanAcceptabilityThresholds::fractional_sigma_a"]
2375        [::std::mem::offset_of!(EmpyreanAcceptabilityThresholds, fractional_sigma_a) - 32usize];
2376};
2377#[doc = " Per-station RA/Dec bias-fit configuration (mirrors\n [`scott::nuisance::BiasKind::StationRaDec`]).\n\n Activated by [`EmpyreanODConfig::fit_station_biases`]. Per-station\n sigma overrides and `BiasScope` filtering aren't carried across the\n C ABI yet — every active station uses `sigma_prior_arcsec` and the\n scope is always [`BiasScope::AllStations`]. Reach for the\n empyrean-core Rust API when you need finer control."]
2378#[repr(C)]
2379#[derive(Debug, Default, Copy, Clone)]
2380pub struct EmpyreanStationRaDecConfig {
2381    #[doc = " Default 1-sigma prior on the RA / Dec offset (arcsec). Default = 0.3."]
2382    pub sigma_prior_arcsec: f64,
2383    #[doc = " Minimum observations per station for a bias parameter to be\n allocated. Stations below this threshold contribute observations\n at face value. 0 → upstream default (5)."]
2384    pub min_obs_per_station: usize,
2385}
2386#[allow(clippy::unnecessary_operation, clippy::identity_op)]
2387const _: () = {
2388    ["Size of EmpyreanStationRaDecConfig"]
2389        [::std::mem::size_of::<EmpyreanStationRaDecConfig>() - 16usize];
2390    ["Alignment of EmpyreanStationRaDecConfig"]
2391        [::std::mem::align_of::<EmpyreanStationRaDecConfig>() - 8usize];
2392    ["Offset of field: EmpyreanStationRaDecConfig::sigma_prior_arcsec"]
2393        [::std::mem::offset_of!(EmpyreanStationRaDecConfig, sigma_prior_arcsec) - 0usize];
2394    ["Offset of field: EmpyreanStationRaDecConfig::min_obs_per_station"]
2395        [::std::mem::offset_of!(EmpyreanStationRaDecConfig, min_obs_per_station) - 8usize];
2396};
2397#[doc = " Outlier rejection configuration. Selects between two strategies via\n the [`kind`](Self::kind) discriminator:\n\n - `kind = EMPYREAN_REJECTION_KIND_ADAPTIVE` (default): mirrors\n   [`scott::rejection::AdaptiveRejectionConfig`]. Reads\n   `chi2_base` / `lambda` / `max_threshold`. Sentinels:\n   `chi2_base = 0.0` → 9.21, `lambda < 0` → 1.0,\n   `max_threshold = 0.0` → 100.0.\n - `kind = EMPYREAN_REJECTION_KIND_CMC2003`: mirrors\n   [`scott::rejection::CMC2003Config`]. Reads `chi2_rej` / `chi2_rec`\n   (the upper / lower hysteresis thresholds). Sentinels:\n   `chi2_rej = 0.0` → 8.0, `chi2_rec = 0.0` → 7.0.\n\n `enabled = 0` runs OD without any rejection pass — the strategy\n fields are ignored. `enabled = 1` activates rejection."]
2398#[repr(C)]
2399#[derive(Debug, Default, Copy, Clone)]
2400pub struct EmpyreanRejectionConfig {
2401    #[doc = " 1 = run rejection (default), 0 = skip."]
2402    pub enabled: u8,
2403    #[doc = " Strategy selector — one of the `EMPYREAN_REJECTION_KIND_*`\n constants. Default `0` (Adaptive) keeps existing C callers\n working without code changes."]
2404    pub kind: u8,
2405    pub chi2_base: f64,
2406    #[doc = " `-1.0` selects the upstream default (1.0); negative values are\n otherwise valid and disable adaptation when 0.0."]
2407    pub lambda: f64,
2408    pub max_threshold: f64,
2409    #[doc = " CMC2003 upper threshold (reject when χ² > chi2_rej). 0.0 →\n upstream default (8.0). Ignored unless `kind ==\n EMPYREAN_REJECTION_KIND_CMC2003`."]
2410    pub chi2_rej: f64,
2411    #[doc = " CMC2003 lower threshold (recover when χ² < chi2_rec). 0.0 →\n upstream default (7.0). Must be strictly less than `chi2_rej`\n for hysteresis to break cycles. Ignored unless `kind ==\n EMPYREAN_REJECTION_KIND_CMC2003`."]
2412    pub chi2_rec: f64,
2413    #[doc = " Maximum rejection-refit passes. 0 → upstream default (3)."]
2414    pub max_passes: u32,
2415}
2416#[allow(clippy::unnecessary_operation, clippy::identity_op)]
2417const _: () = {
2418    ["Size of EmpyreanRejectionConfig"][::std::mem::size_of::<EmpyreanRejectionConfig>() - 56usize];
2419    ["Alignment of EmpyreanRejectionConfig"]
2420        [::std::mem::align_of::<EmpyreanRejectionConfig>() - 8usize];
2421    ["Offset of field: EmpyreanRejectionConfig::enabled"]
2422        [::std::mem::offset_of!(EmpyreanRejectionConfig, enabled) - 0usize];
2423    ["Offset of field: EmpyreanRejectionConfig::kind"]
2424        [::std::mem::offset_of!(EmpyreanRejectionConfig, kind) - 1usize];
2425    ["Offset of field: EmpyreanRejectionConfig::chi2_base"]
2426        [::std::mem::offset_of!(EmpyreanRejectionConfig, chi2_base) - 8usize];
2427    ["Offset of field: EmpyreanRejectionConfig::lambda"]
2428        [::std::mem::offset_of!(EmpyreanRejectionConfig, lambda) - 16usize];
2429    ["Offset of field: EmpyreanRejectionConfig::max_threshold"]
2430        [::std::mem::offset_of!(EmpyreanRejectionConfig, max_threshold) - 24usize];
2431    ["Offset of field: EmpyreanRejectionConfig::chi2_rej"]
2432        [::std::mem::offset_of!(EmpyreanRejectionConfig, chi2_rej) - 32usize];
2433    ["Offset of field: EmpyreanRejectionConfig::chi2_rec"]
2434        [::std::mem::offset_of!(EmpyreanRejectionConfig, chi2_rec) - 40usize];
2435    ["Offset of field: EmpyreanRejectionConfig::max_passes"]
2436        [::std::mem::offset_of!(EmpyreanRejectionConfig, max_passes) - 48usize];
2437};
2438#[doc = " Result of orbit determination (determine or refine).\n\n Per-axis solve-for flags (mirrors scott's `SolveFor`). Read only when\n [`EmpyreanODConfig::solve_for`] is [`EMPYREAN_SOLVE_FOR_EXPLICIT`]; the\n three coarse `EMPYREAN_SOLVE_FOR_*` codes cover the common shapes\n without it. Each flag turns on a wide-STM axis, subject to its own\n precondition (a declared prior on the orbit) enforced by scott."]
2439#[repr(C)]
2440#[derive(Debug, Default, Copy, Clone)]
2441pub struct EmpyreanSolveFor {
2442    #[doc = " Solve the Marsden A1/A2/A3 block (requires a non-grav covariance)."]
2443    pub marsden: u8,
2444    #[doc = " Solve the non-grav time delay DT (requires `marsden` + a DT prior)."]
2445    pub dt: u8,
2446    #[doc = " Solve the SRP AMRAT (requires an SRP AMRAT prior)."]
2447    pub amrat: u8,
2448    #[doc = " Number of thrust Δv segments to solve (3 columns each; 0 = none)."]
2449    pub thrust_segments: u32,
2450}
2451#[allow(clippy::unnecessary_operation, clippy::identity_op)]
2452const _: () = {
2453    ["Size of EmpyreanSolveFor"][::std::mem::size_of::<EmpyreanSolveFor>() - 8usize];
2454    ["Alignment of EmpyreanSolveFor"][::std::mem::align_of::<EmpyreanSolveFor>() - 4usize];
2455    ["Offset of field: EmpyreanSolveFor::marsden"]
2456        [::std::mem::offset_of!(EmpyreanSolveFor, marsden) - 0usize];
2457    ["Offset of field: EmpyreanSolveFor::dt"]
2458        [::std::mem::offset_of!(EmpyreanSolveFor, dt) - 1usize];
2459    ["Offset of field: EmpyreanSolveFor::amrat"]
2460        [::std::mem::offset_of!(EmpyreanSolveFor, amrat) - 2usize];
2461    ["Offset of field: EmpyreanSolveFor::thrust_segments"]
2462        [::std::mem::offset_of!(EmpyreanSolveFor, thrust_segments) - 4usize];
2463};
2464#[doc = " Post-OD photometric-fit request (mirrors scott's `PhotometryConfig`).\n Enabled by [`EmpyreanODConfig::has_photometry`]; the fit runs after the\n orbit is solved and never touches the state (photometry has no\n astrometric partials). Zero-init reproduces scott's defaults."]
2465#[repr(C)]
2466#[derive(Debug, Default, Copy, Clone)]
2467pub struct EmpyreanPhotometryConfig {
2468    #[doc = " Model to fit (`EMPYREAN_PHOTOMETRY_MODEL_*`). Default = Auto (0)."]
2469    pub model: i32,
2470    #[doc = " 1σ lightcurve scatter floor (mag). 0.0 → upstream default (0.2)."]
2471    pub sigma_lightcurve: f64,
2472    #[doc = " Include astrometrically-rejected observations' magnitudes. 0 = off."]
2473    pub include_rejected: u8,
2474    #[doc = " Max Huber-IRLS iterations. 0 → upstream default (30)."]
2475    pub max_irls_iterations: u32,
2476    #[doc = " Huber tuning constant. 0.0 → upstream default (1.5)."]
2477    pub huber_k: f64,
2478}
2479#[allow(clippy::unnecessary_operation, clippy::identity_op)]
2480const _: () = {
2481    ["Size of EmpyreanPhotometryConfig"]
2482        [::std::mem::size_of::<EmpyreanPhotometryConfig>() - 32usize];
2483    ["Alignment of EmpyreanPhotometryConfig"]
2484        [::std::mem::align_of::<EmpyreanPhotometryConfig>() - 8usize];
2485    ["Offset of field: EmpyreanPhotometryConfig::model"]
2486        [::std::mem::offset_of!(EmpyreanPhotometryConfig, model) - 0usize];
2487    ["Offset of field: EmpyreanPhotometryConfig::sigma_lightcurve"]
2488        [::std::mem::offset_of!(EmpyreanPhotometryConfig, sigma_lightcurve) - 8usize];
2489    ["Offset of field: EmpyreanPhotometryConfig::include_rejected"]
2490        [::std::mem::offset_of!(EmpyreanPhotometryConfig, include_rejected) - 16usize];
2491    ["Offset of field: EmpyreanPhotometryConfig::max_irls_iterations"]
2492        [::std::mem::offset_of!(EmpyreanPhotometryConfig, max_irls_iterations) - 20usize];
2493    ["Offset of field: EmpyreanPhotometryConfig::huber_k"]
2494        [::std::mem::offset_of!(EmpyreanPhotometryConfig, huber_k) - 24usize];
2495};
2496#[doc = " Orbit-determination configuration.\n\n Drives `empyrean_determine`, `empyrean_evaluate`, and `empyrean_refine`.\n Mirrors [`scott::od::ODConfig`](scott::od::ODConfig) **structurally** —\n where scott has a nested config (e.g. `auto_escalation`,\n `acceptability`), this surface keeps the same nesting via\n [`EmpyreanAutoEscalationPolicy`], [`EmpyreanAcceptabilityThresholds`],\n etc., so the C-side caller's mental model matches the upstream Rust\n type. Sentinel rule for primitive fields: `0` / `0.0` requests the\n upstream default; only the few fields documented inline (e.g.\n `opposition_gap_days < 0`, `lambda < 0`) carry their own special\n values.\n\n IOD strategy configs (Gauss / Herget / SystematicRanging /\n Refinement) are not exposed here — those are tens of internal\n tuning fields that don't translate cleanly. They always run with\n their upstream defaults; reach for the empyrean-core Rust API when\n you need to override them."]
2497#[repr(C)]
2498#[derive(Debug, Copy, Clone)]
2499pub struct EmpyreanODConfig {
2500    #[doc = " Force-model tier: 0=Approximate, 1=Basic, 2=Standard."]
2501    pub force_model: i32,
2502    #[doc = " Integrator truncation-error tolerance (interpreted by the\n active integrator backend — for the default GR15 this is the\n relative b₆ truncation tolerance). 0.0 → upstream default\n (1e-9)."]
2503    pub epsilon: f64,
2504    #[doc = " Maximum light-time iterations. 0 → upstream default (3)."]
2505    pub max_light_time_iterations: usize,
2506    #[doc = " Threads for batch operations. 0 → all available cores."]
2507    pub num_threads: usize,
2508    #[doc = " Output reference frame: 0=ICRF, 1=EclipticJ2000."]
2509    pub frame: i32,
2510    #[doc = " Observation weighting pipeline configuration. Zero-init = the\n production default (VFC17 + nightly de-weighting at floor-σ\n policy). See [`EmpyreanWeightingConfig`]."]
2511    pub weighting: EmpyreanWeightingConfig,
2512    #[doc = " Catalog-bias-correction configuration. Zero-init = the\n production default (EFCC2020 standard resolution, loaded from\n the DataManager default path). See [`EmpyreanDebiasingConfig`]."]
2513    pub debiasing: EmpyreanDebiasingConfig,
2514    #[doc = " Number of `excluded_perturbers` in [`excluded_perturbers_naif`]; 0 = none."]
2515    pub num_excluded_perturbers: usize,
2516    #[doc = " Pointer to `num_excluded_perturbers` NAIF body IDs to exclude\n from the perturber set (for self-determination of SB441-N16\n bodies). Non-owning — caller must keep the array alive for the\n duration of the OD call."]
2517    pub excluded_perturbers_naif: *const i32,
2518    #[doc = " Origin-policy selector. Zero-init = `Auto` (heliocentric → geo-\n centric Earth cascade). See [`EmpyreanOriginPolicy`]."]
2519    pub origin: EmpyreanOriginPolicy,
2520    pub iod: EmpyreanIODConfig,
2521    pub output_epoch: EmpyreanOutputEpoch,
2522    #[doc = " Maximum DC iterations. 0 → upstream default (100)."]
2523    pub max_iterations: u32,
2524    #[doc = " DC convergence tolerance on Δx^T N Δx. 0.0 → upstream default (0.1)."]
2525    pub convergence_tol: f64,
2526    #[doc = " Use STM-cached ephemeris updates for iterations 2+. 1 = on (default)."]
2527    pub use_stm_cache: u8,
2528    #[doc = " Solve-for parameter set (`EMPYREAN_SOLVE_FOR_*`). Default = Auto."]
2529    pub solve_for: i32,
2530    pub auto_escalation: EmpyreanAutoEscalationPolicy,
2531    pub acceptability: EmpyreanAcceptabilityThresholds,
2532    #[doc = " Schur-eliminate per-station RA/Dec biases. 1 = enable, 0 = off (default)."]
2533    pub fit_station_biases: u8,
2534    #[doc = " Per-station RA/Dec bias config. Honored only when\n [`fit_station_biases`] is non-zero."]
2535    pub station_radec: EmpyreanStationRaDecConfig,
2536    #[doc = " Use span-grouped Jacobian reuse on cache iterations. 0 = off (default)."]
2537    pub use_span_grouping: u8,
2538    pub rejection: EmpyreanRejectionConfig,
2539    #[doc = " Auto-select force-model tier from IOD elements. 0 = off (default)."]
2540    pub auto_force_model: u8,
2541    #[doc = " Output coordinate representation for the fitted orbit + covariance\n (`EMPYREAN_REPRESENTATION_*`). Default = Cartesian."]
2542    pub output_representation: i32,
2543    #[doc = " Per-axis solve-for flags, read ONLY when\n [`solve_for`](EmpyreanODConfig::solve_for) is\n [`EMPYREAN_SOLVE_FOR_EXPLICIT`]. The three coarse `solve_for` codes\n ignore this field."]
2544    pub solve_for_flags: EmpyreanSolveFor,
2545    #[doc = " Permit solving a thrust Δv segment whose burn window is not\n bracketed by observations (degenerate with the state; the Gates\n prior then carries it). 0 = refuse loudly (default)."]
2546    pub allow_unbracketed_maneuvers: u8,
2547    #[doc = " 1 to run the post-OD photometric fit; 0 = off (default). When 0,\n [`photometry`](EmpyreanODConfig::photometry) is ignored."]
2548    pub has_photometry: u8,
2549    #[doc = " Post-OD photometric-fit configuration. Honored only when\n [`has_photometry`](EmpyreanODConfig::has_photometry) is non-zero."]
2550    pub photometry: EmpyreanPhotometryConfig,
2551}
2552#[allow(clippy::unnecessary_operation, clippy::identity_op)]
2553const _: () = {
2554    ["Size of EmpyreanODConfig"][::std::mem::size_of::<EmpyreanODConfig>() - 432usize];
2555    ["Alignment of EmpyreanODConfig"][::std::mem::align_of::<EmpyreanODConfig>() - 8usize];
2556    ["Offset of field: EmpyreanODConfig::force_model"]
2557        [::std::mem::offset_of!(EmpyreanODConfig, force_model) - 0usize];
2558    ["Offset of field: EmpyreanODConfig::epsilon"]
2559        [::std::mem::offset_of!(EmpyreanODConfig, epsilon) - 8usize];
2560    ["Offset of field: EmpyreanODConfig::max_light_time_iterations"]
2561        [::std::mem::offset_of!(EmpyreanODConfig, max_light_time_iterations) - 16usize];
2562    ["Offset of field: EmpyreanODConfig::num_threads"]
2563        [::std::mem::offset_of!(EmpyreanODConfig, num_threads) - 24usize];
2564    ["Offset of field: EmpyreanODConfig::frame"]
2565        [::std::mem::offset_of!(EmpyreanODConfig, frame) - 32usize];
2566    ["Offset of field: EmpyreanODConfig::weighting"]
2567        [::std::mem::offset_of!(EmpyreanODConfig, weighting) - 40usize];
2568    ["Offset of field: EmpyreanODConfig::debiasing"]
2569        [::std::mem::offset_of!(EmpyreanODConfig, debiasing) - 80usize];
2570    ["Offset of field: EmpyreanODConfig::num_excluded_perturbers"]
2571        [::std::mem::offset_of!(EmpyreanODConfig, num_excluded_perturbers) - 104usize];
2572    ["Offset of field: EmpyreanODConfig::excluded_perturbers_naif"]
2573        [::std::mem::offset_of!(EmpyreanODConfig, excluded_perturbers_naif) - 112usize];
2574    ["Offset of field: EmpyreanODConfig::origin"]
2575        [::std::mem::offset_of!(EmpyreanODConfig, origin) - 120usize];
2576    ["Offset of field: EmpyreanODConfig::iod"]
2577        [::std::mem::offset_of!(EmpyreanODConfig, iod) - 128usize];
2578    ["Offset of field: EmpyreanODConfig::output_epoch"]
2579        [::std::mem::offset_of!(EmpyreanODConfig, output_epoch) - 176usize];
2580    ["Offset of field: EmpyreanODConfig::max_iterations"]
2581        [::std::mem::offset_of!(EmpyreanODConfig, max_iterations) - 192usize];
2582    ["Offset of field: EmpyreanODConfig::convergence_tol"]
2583        [::std::mem::offset_of!(EmpyreanODConfig, convergence_tol) - 200usize];
2584    ["Offset of field: EmpyreanODConfig::use_stm_cache"]
2585        [::std::mem::offset_of!(EmpyreanODConfig, use_stm_cache) - 208usize];
2586    ["Offset of field: EmpyreanODConfig::solve_for"]
2587        [::std::mem::offset_of!(EmpyreanODConfig, solve_for) - 212usize];
2588    ["Offset of field: EmpyreanODConfig::auto_escalation"]
2589        [::std::mem::offset_of!(EmpyreanODConfig, auto_escalation) - 216usize];
2590    ["Offset of field: EmpyreanODConfig::acceptability"]
2591        [::std::mem::offset_of!(EmpyreanODConfig, acceptability) - 248usize];
2592    ["Offset of field: EmpyreanODConfig::fit_station_biases"]
2593        [::std::mem::offset_of!(EmpyreanODConfig, fit_station_biases) - 288usize];
2594    ["Offset of field: EmpyreanODConfig::station_radec"]
2595        [::std::mem::offset_of!(EmpyreanODConfig, station_radec) - 296usize];
2596    ["Offset of field: EmpyreanODConfig::use_span_grouping"]
2597        [::std::mem::offset_of!(EmpyreanODConfig, use_span_grouping) - 312usize];
2598    ["Offset of field: EmpyreanODConfig::rejection"]
2599        [::std::mem::offset_of!(EmpyreanODConfig, rejection) - 320usize];
2600    ["Offset of field: EmpyreanODConfig::auto_force_model"]
2601        [::std::mem::offset_of!(EmpyreanODConfig, auto_force_model) - 376usize];
2602    ["Offset of field: EmpyreanODConfig::output_representation"]
2603        [::std::mem::offset_of!(EmpyreanODConfig, output_representation) - 380usize];
2604    ["Offset of field: EmpyreanODConfig::solve_for_flags"]
2605        [::std::mem::offset_of!(EmpyreanODConfig, solve_for_flags) - 384usize];
2606    ["Offset of field: EmpyreanODConfig::allow_unbracketed_maneuvers"]
2607        [::std::mem::offset_of!(EmpyreanODConfig, allow_unbracketed_maneuvers) - 392usize];
2608    ["Offset of field: EmpyreanODConfig::has_photometry"]
2609        [::std::mem::offset_of!(EmpyreanODConfig, has_photometry) - 393usize];
2610    ["Offset of field: EmpyreanODConfig::photometry"]
2611        [::std::mem::offset_of!(EmpyreanODConfig, photometry) - 400usize];
2612};
2613impl Default for EmpyreanODConfig {
2614    fn default() -> Self {
2615        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
2616        unsafe {
2617            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
2618            s.assume_init()
2619        }
2620    }
2621}
2622#[doc = " Aggregate residual statistics.\n\n All angular quantities in arcseconds. NaN entries indicate the stat\n could not be computed (e.g. AT/CT RMS when no sky-motion rates were\n available, or weighted RMS when no weighting layer was active)."]
2623#[repr(C)]
2624#[derive(Debug, Default, Copy, Clone)]
2625pub struct EmpyreanResidualSummary {
2626    pub num_obs: usize,
2627    pub num_selected: usize,
2628    pub num_rejected: usize,
2629    #[doc = " Total χ² over selected observations."]
2630    pub chi2: f64,
2631    #[doc = " Effective degrees of freedom (after subtracting solve-for params)."]
2632    pub dof: usize,
2633    #[doc = " Reduced χ² = chi2 / dof. NaN when dof ≤ 0."]
2634    pub reduced_chi2: f64,
2635    pub rms_ra_arcsec: f64,
2636    pub rms_dec_arcsec: f64,
2637    #[doc = " Combined RA·cosδ + Dec residual RMS (arcsec). Matches the\n find_orb / OrbFit `rms` reporting convention — a single\n number directly comparable across tools."]
2638    pub rms_combined_arcsec: f64,
2639    #[doc = " RMS weighted by the per-observation σ (matches scott's `weighted_rms`)."]
2640    pub weighted_rms_ra_arcsec: f64,
2641    pub weighted_rms_dec_arcsec: f64,
2642    #[doc = " Combined weighted RA·cosδ + Dec residual RMS (arcsec)."]
2643    pub weighted_rms_combined_arcsec: f64,
2644    pub mean_ra_arcsec: f64,
2645    pub mean_dec_arcsec: f64,
2646    pub std_ra_arcsec: f64,
2647    pub std_dec_arcsec: f64,
2648    #[doc = " RMS along-track residual (arcsec). NaN if no AT/CT data."]
2649    pub rms_along_track_arcsec: f64,
2650    #[doc = " RMS cross-track residual (arcsec). NaN if no AT/CT data."]
2651    pub rms_cross_track_arcsec: f64,
2652}
2653#[allow(clippy::unnecessary_operation, clippy::identity_op)]
2654const _: () = {
2655    ["Size of EmpyreanResidualSummary"]
2656        [::std::mem::size_of::<EmpyreanResidualSummary>() - 144usize];
2657    ["Alignment of EmpyreanResidualSummary"]
2658        [::std::mem::align_of::<EmpyreanResidualSummary>() - 8usize];
2659    ["Offset of field: EmpyreanResidualSummary::num_obs"]
2660        [::std::mem::offset_of!(EmpyreanResidualSummary, num_obs) - 0usize];
2661    ["Offset of field: EmpyreanResidualSummary::num_selected"]
2662        [::std::mem::offset_of!(EmpyreanResidualSummary, num_selected) - 8usize];
2663    ["Offset of field: EmpyreanResidualSummary::num_rejected"]
2664        [::std::mem::offset_of!(EmpyreanResidualSummary, num_rejected) - 16usize];
2665    ["Offset of field: EmpyreanResidualSummary::chi2"]
2666        [::std::mem::offset_of!(EmpyreanResidualSummary, chi2) - 24usize];
2667    ["Offset of field: EmpyreanResidualSummary::dof"]
2668        [::std::mem::offset_of!(EmpyreanResidualSummary, dof) - 32usize];
2669    ["Offset of field: EmpyreanResidualSummary::reduced_chi2"]
2670        [::std::mem::offset_of!(EmpyreanResidualSummary, reduced_chi2) - 40usize];
2671    ["Offset of field: EmpyreanResidualSummary::rms_ra_arcsec"]
2672        [::std::mem::offset_of!(EmpyreanResidualSummary, rms_ra_arcsec) - 48usize];
2673    ["Offset of field: EmpyreanResidualSummary::rms_dec_arcsec"]
2674        [::std::mem::offset_of!(EmpyreanResidualSummary, rms_dec_arcsec) - 56usize];
2675    ["Offset of field: EmpyreanResidualSummary::rms_combined_arcsec"]
2676        [::std::mem::offset_of!(EmpyreanResidualSummary, rms_combined_arcsec) - 64usize];
2677    ["Offset of field: EmpyreanResidualSummary::weighted_rms_ra_arcsec"]
2678        [::std::mem::offset_of!(EmpyreanResidualSummary, weighted_rms_ra_arcsec) - 72usize];
2679    ["Offset of field: EmpyreanResidualSummary::weighted_rms_dec_arcsec"]
2680        [::std::mem::offset_of!(EmpyreanResidualSummary, weighted_rms_dec_arcsec) - 80usize];
2681    ["Offset of field: EmpyreanResidualSummary::weighted_rms_combined_arcsec"]
2682        [::std::mem::offset_of!(EmpyreanResidualSummary, weighted_rms_combined_arcsec) - 88usize];
2683    ["Offset of field: EmpyreanResidualSummary::mean_ra_arcsec"]
2684        [::std::mem::offset_of!(EmpyreanResidualSummary, mean_ra_arcsec) - 96usize];
2685    ["Offset of field: EmpyreanResidualSummary::mean_dec_arcsec"]
2686        [::std::mem::offset_of!(EmpyreanResidualSummary, mean_dec_arcsec) - 104usize];
2687    ["Offset of field: EmpyreanResidualSummary::std_ra_arcsec"]
2688        [::std::mem::offset_of!(EmpyreanResidualSummary, std_ra_arcsec) - 112usize];
2689    ["Offset of field: EmpyreanResidualSummary::std_dec_arcsec"]
2690        [::std::mem::offset_of!(EmpyreanResidualSummary, std_dec_arcsec) - 120usize];
2691    ["Offset of field: EmpyreanResidualSummary::rms_along_track_arcsec"]
2692        [::std::mem::offset_of!(EmpyreanResidualSummary, rms_along_track_arcsec) - 128usize];
2693    ["Offset of field: EmpyreanResidualSummary::rms_cross_track_arcsec"]
2694        [::std::mem::offset_of!(EmpyreanResidualSummary, rms_cross_track_arcsec) - 136usize];
2695};
2696#[doc = " The fitted orbit's absolute solar-radiation-pressure slot, flattened\n for the C ABI. Mirrors the SRP fields the input `EmpyreanOrbit` carries\n so a fitted orbit's SRP force re-feeds off [`EmpyreanODResult::srp`] with\n no loss."]
2697#[repr(C)]
2698#[derive(Debug, Default, Copy, Clone)]
2699pub struct EmpyreanSRPParams {
2700    #[doc = " Absolute area-to-mass ratio AMRAT (m²/kg) — the input prior plus any\n fitted correction."]
2701    pub amrat: f64,
2702    #[doc = " Radiation-pressure coefficient Cr, carried through unchanged."]
2703    pub cr: f64,
2704    #[doc = " 1 when `amrat_variance` carries a meaningful AMRAT variance; 0 otherwise."]
2705    pub has_amrat_variance: u8,
2706    #[doc = " AMRAT variance ((m²/kg)²). Only meaningful when `has_amrat_variance = 1`."]
2707    pub amrat_variance: f64,
2708}
2709#[allow(clippy::unnecessary_operation, clippy::identity_op)]
2710const _: () = {
2711    ["Size of EmpyreanSRPParams"][::std::mem::size_of::<EmpyreanSRPParams>() - 32usize];
2712    ["Alignment of EmpyreanSRPParams"][::std::mem::align_of::<EmpyreanSRPParams>() - 8usize];
2713    ["Offset of field: EmpyreanSRPParams::amrat"]
2714        [::std::mem::offset_of!(EmpyreanSRPParams, amrat) - 0usize];
2715    ["Offset of field: EmpyreanSRPParams::cr"][::std::mem::offset_of!(EmpyreanSRPParams, cr) - 8usize];
2716    ["Offset of field: EmpyreanSRPParams::has_amrat_variance"]
2717        [::std::mem::offset_of!(EmpyreanSRPParams, has_amrat_variance) - 16usize];
2718    ["Offset of field: EmpyreanSRPParams::amrat_variance"]
2719        [::std::mem::offset_of!(EmpyreanSRPParams, amrat_variance) - 24usize];
2720};
2721#[doc = " A complete non-gravitational acceleration model, flattened for the C ABI.\n\n Mirrors the fields the input [`EmpyreanOrbit`] carries, so a fitted orbit's\n non-grav can be read back off [`EmpyreanODResult::non_grav`] and re-applied\n to an `EmpyreanOrbit` with no loss: the radial/transverse/normal\n coefficients (A1/A2/A3, AU/day²), the Marsden–Sekanina g(r) exponents\n (`ng_alpha`..`ng_k`; all-zero = inverse-square default), and the optional\n thermal-lag delay `non_grav_dt` (days, valid only when `has_dt = 1`)."]
2722#[repr(C)]
2723#[derive(Debug, Default, Copy, Clone)]
2724pub struct EmpyreanNonGravParams {
2725    pub a1: f64,
2726    pub a2: f64,
2727    pub a3: f64,
2728    pub ng_alpha: f64,
2729    pub ng_r0: f64,
2730    pub ng_m: f64,
2731    pub ng_n: f64,
2732    pub ng_k: f64,
2733    #[doc = " 1 when `non_grav_dt` carries a thermal-lag delay; 0 otherwise."]
2734    pub has_dt: u8,
2735    #[doc = " g(r) evaluation time delay (days); only meaningful when `has_dt = 1`."]
2736    pub non_grav_dt: f64,
2737    #[doc = " 1 when `covariance` carries the fitted non-grav covariance; 0 otherwise."]
2738    pub has_covariance: u8,
2739    #[doc = " Fitted non-grav 3×3 covariance for (A1, A2, A3), row-major. Only\n meaningful when `has_covariance = 1`. Re-feeding it onto an input\n orbit lets a fitted orbit flow into a StateAndNonGrav refine without\n losing its non-grav prior."]
2740    pub covariance: [[f64; 3usize]; 3usize],
2741}
2742#[allow(clippy::unnecessary_operation, clippy::identity_op)]
2743const _: () = {
2744    ["Size of EmpyreanNonGravParams"][::std::mem::size_of::<EmpyreanNonGravParams>() - 160usize];
2745    ["Alignment of EmpyreanNonGravParams"]
2746        [::std::mem::align_of::<EmpyreanNonGravParams>() - 8usize];
2747    ["Offset of field: EmpyreanNonGravParams::a1"]
2748        [::std::mem::offset_of!(EmpyreanNonGravParams, a1) - 0usize];
2749    ["Offset of field: EmpyreanNonGravParams::a2"]
2750        [::std::mem::offset_of!(EmpyreanNonGravParams, a2) - 8usize];
2751    ["Offset of field: EmpyreanNonGravParams::a3"]
2752        [::std::mem::offset_of!(EmpyreanNonGravParams, a3) - 16usize];
2753    ["Offset of field: EmpyreanNonGravParams::ng_alpha"]
2754        [::std::mem::offset_of!(EmpyreanNonGravParams, ng_alpha) - 24usize];
2755    ["Offset of field: EmpyreanNonGravParams::ng_r0"]
2756        [::std::mem::offset_of!(EmpyreanNonGravParams, ng_r0) - 32usize];
2757    ["Offset of field: EmpyreanNonGravParams::ng_m"]
2758        [::std::mem::offset_of!(EmpyreanNonGravParams, ng_m) - 40usize];
2759    ["Offset of field: EmpyreanNonGravParams::ng_n"]
2760        [::std::mem::offset_of!(EmpyreanNonGravParams, ng_n) - 48usize];
2761    ["Offset of field: EmpyreanNonGravParams::ng_k"]
2762        [::std::mem::offset_of!(EmpyreanNonGravParams, ng_k) - 56usize];
2763    ["Offset of field: EmpyreanNonGravParams::has_dt"]
2764        [::std::mem::offset_of!(EmpyreanNonGravParams, has_dt) - 64usize];
2765    ["Offset of field: EmpyreanNonGravParams::non_grav_dt"]
2766        [::std::mem::offset_of!(EmpyreanNonGravParams, non_grav_dt) - 72usize];
2767    ["Offset of field: EmpyreanNonGravParams::has_covariance"]
2768        [::std::mem::offset_of!(EmpyreanNonGravParams, has_covariance) - 80usize];
2769    ["Offset of field: EmpyreanNonGravParams::covariance"]
2770        [::std::mem::offset_of!(EmpyreanNonGravParams, covariance) - 88usize];
2771};
2772#[doc = " Acceptability sub-checks computed post-DC.\n\n Mirrors scott's [`AcceptabilityReport`](scott::od::AcceptabilityReport).\n Boolean fields are encoded as `u8` (0/1). When a value is unavailable\n (e.g. AT/CT ratio with no sky-motion rates), the `_value` is NaN and\n the corresponding `_ok` flag is 0. Always populated on\n [`EmpyreanODResult`]; on [`EmpyreanEvaluateResult`] the report is\n filled with NaN/0 because evaluate does not produce a fitted orbit."]
2773#[repr(C)]
2774#[derive(Debug, Default, Copy, Clone)]
2775pub struct EmpyreanAcceptabilityReport {
2776    pub fit_acceptable: u8,
2777    pub extrapolation_acceptable: u8,
2778    pub converged_ok: u8,
2779    pub reduced_chi2_ok: u8,
2780    pub reduced_chi2_value: f64,
2781    pub reduced_chi2_threshold: f64,
2782    pub rms_ok: u8,
2783    pub rms_value_arcsec: f64,
2784    pub rms_threshold_arcsec: f64,
2785    pub residual_isotropy_ok: u8,
2786    pub at_ct_ratio_value: f64,
2787    pub at_ct_ratio_threshold: f64,
2788    pub covariance_ok: u8,
2789    pub arc_coverage_ok: u8,
2790    pub arc_days_value: f64,
2791    pub arc_days_threshold: f64,
2792    pub fractional_sigma_a_ok: u8,
2793    pub fractional_sigma_a_value: f64,
2794    pub fractional_sigma_a_threshold: f64,
2795}
2796#[allow(clippy::unnecessary_operation, clippy::identity_op)]
2797const _: () = {
2798    ["Size of EmpyreanAcceptabilityReport"]
2799        [::std::mem::size_of::<EmpyreanAcceptabilityReport>() - 120usize];
2800    ["Alignment of EmpyreanAcceptabilityReport"]
2801        [::std::mem::align_of::<EmpyreanAcceptabilityReport>() - 8usize];
2802    ["Offset of field: EmpyreanAcceptabilityReport::fit_acceptable"]
2803        [::std::mem::offset_of!(EmpyreanAcceptabilityReport, fit_acceptable) - 0usize];
2804    ["Offset of field: EmpyreanAcceptabilityReport::extrapolation_acceptable"]
2805        [::std::mem::offset_of!(EmpyreanAcceptabilityReport, extrapolation_acceptable) - 1usize];
2806    ["Offset of field: EmpyreanAcceptabilityReport::converged_ok"]
2807        [::std::mem::offset_of!(EmpyreanAcceptabilityReport, converged_ok) - 2usize];
2808    ["Offset of field: EmpyreanAcceptabilityReport::reduced_chi2_ok"]
2809        [::std::mem::offset_of!(EmpyreanAcceptabilityReport, reduced_chi2_ok) - 3usize];
2810    ["Offset of field: EmpyreanAcceptabilityReport::reduced_chi2_value"]
2811        [::std::mem::offset_of!(EmpyreanAcceptabilityReport, reduced_chi2_value) - 8usize];
2812    ["Offset of field: EmpyreanAcceptabilityReport::reduced_chi2_threshold"]
2813        [::std::mem::offset_of!(EmpyreanAcceptabilityReport, reduced_chi2_threshold) - 16usize];
2814    ["Offset of field: EmpyreanAcceptabilityReport::rms_ok"]
2815        [::std::mem::offset_of!(EmpyreanAcceptabilityReport, rms_ok) - 24usize];
2816    ["Offset of field: EmpyreanAcceptabilityReport::rms_value_arcsec"]
2817        [::std::mem::offset_of!(EmpyreanAcceptabilityReport, rms_value_arcsec) - 32usize];
2818    ["Offset of field: EmpyreanAcceptabilityReport::rms_threshold_arcsec"]
2819        [::std::mem::offset_of!(EmpyreanAcceptabilityReport, rms_threshold_arcsec) - 40usize];
2820    ["Offset of field: EmpyreanAcceptabilityReport::residual_isotropy_ok"]
2821        [::std::mem::offset_of!(EmpyreanAcceptabilityReport, residual_isotropy_ok) - 48usize];
2822    ["Offset of field: EmpyreanAcceptabilityReport::at_ct_ratio_value"]
2823        [::std::mem::offset_of!(EmpyreanAcceptabilityReport, at_ct_ratio_value) - 56usize];
2824    ["Offset of field: EmpyreanAcceptabilityReport::at_ct_ratio_threshold"]
2825        [::std::mem::offset_of!(EmpyreanAcceptabilityReport, at_ct_ratio_threshold) - 64usize];
2826    ["Offset of field: EmpyreanAcceptabilityReport::covariance_ok"]
2827        [::std::mem::offset_of!(EmpyreanAcceptabilityReport, covariance_ok) - 72usize];
2828    ["Offset of field: EmpyreanAcceptabilityReport::arc_coverage_ok"]
2829        [::std::mem::offset_of!(EmpyreanAcceptabilityReport, arc_coverage_ok) - 73usize];
2830    ["Offset of field: EmpyreanAcceptabilityReport::arc_days_value"]
2831        [::std::mem::offset_of!(EmpyreanAcceptabilityReport, arc_days_value) - 80usize];
2832    ["Offset of field: EmpyreanAcceptabilityReport::arc_days_threshold"]
2833        [::std::mem::offset_of!(EmpyreanAcceptabilityReport, arc_days_threshold) - 88usize];
2834    ["Offset of field: EmpyreanAcceptabilityReport::fractional_sigma_a_ok"]
2835        [::std::mem::offset_of!(EmpyreanAcceptabilityReport, fractional_sigma_a_ok) - 96usize];
2836    ["Offset of field: EmpyreanAcceptabilityReport::fractional_sigma_a_value"]
2837        [::std::mem::offset_of!(EmpyreanAcceptabilityReport, fractional_sigma_a_value) - 104usize];
2838    ["Offset of field: EmpyreanAcceptabilityReport::fractional_sigma_a_threshold"][::std::mem::offset_of!(
2839        EmpyreanAcceptabilityReport,
2840        fractional_sigma_a_threshold
2841    ) - 112usize];
2842};
2843#[doc = " One per-station bias estimate from a Schur-eliminated nuisance fit.\n\n Mirrors [`scott::results::StationBias`]. Populated rows in the\n returned array correspond to stations that met the\n `min_obs_per_station` threshold; under-observed stations are absent.\n Timing fields are populated only when a `BiasKind::StationTiming`\n nuisance was active (currently no surface to enable it from the C\n ABI; reserved for a planned follow-up).\n\n `obs_code` is heap-allocated and owned by the parent array — freed\n by [`empyrean_od_result_free`] when the result is freed. Don't free\n it manually."]
2844#[repr(C)]
2845#[derive(Debug, Copy, Clone)]
2846pub struct EmpyreanStationBias {
2847    pub obs_code: *mut ::std::os::raw::c_char,
2848    #[doc = " Pre-rejection observation count from this station."]
2849    pub n_obs: usize,
2850    pub bias_ra_arcsec: f64,
2851    pub sigma_ra_arcsec: f64,
2852    pub bias_dec_arcsec: f64,
2853    pub sigma_dec_arcsec: f64,
2854    #[doc = " 1 when the timing bias is populated; 0 otherwise. Reserved for\n the planned `BiasKind::StationTiming` follow-up."]
2855    pub has_timing: u8,
2856    pub bias_timing_sec: f64,
2857    pub sigma_timing_sec: f64,
2858    #[doc = " Scalar significance: max of |bᵢ|/σᵢ across populated components."]
2859    pub significance: f64,
2860}
2861#[allow(clippy::unnecessary_operation, clippy::identity_op)]
2862const _: () = {
2863    ["Size of EmpyreanStationBias"][::std::mem::size_of::<EmpyreanStationBias>() - 80usize];
2864    ["Alignment of EmpyreanStationBias"][::std::mem::align_of::<EmpyreanStationBias>() - 8usize];
2865    ["Offset of field: EmpyreanStationBias::obs_code"]
2866        [::std::mem::offset_of!(EmpyreanStationBias, obs_code) - 0usize];
2867    ["Offset of field: EmpyreanStationBias::n_obs"]
2868        [::std::mem::offset_of!(EmpyreanStationBias, n_obs) - 8usize];
2869    ["Offset of field: EmpyreanStationBias::bias_ra_arcsec"]
2870        [::std::mem::offset_of!(EmpyreanStationBias, bias_ra_arcsec) - 16usize];
2871    ["Offset of field: EmpyreanStationBias::sigma_ra_arcsec"]
2872        [::std::mem::offset_of!(EmpyreanStationBias, sigma_ra_arcsec) - 24usize];
2873    ["Offset of field: EmpyreanStationBias::bias_dec_arcsec"]
2874        [::std::mem::offset_of!(EmpyreanStationBias, bias_dec_arcsec) - 32usize];
2875    ["Offset of field: EmpyreanStationBias::sigma_dec_arcsec"]
2876        [::std::mem::offset_of!(EmpyreanStationBias, sigma_dec_arcsec) - 40usize];
2877    ["Offset of field: EmpyreanStationBias::has_timing"]
2878        [::std::mem::offset_of!(EmpyreanStationBias, has_timing) - 48usize];
2879    ["Offset of field: EmpyreanStationBias::bias_timing_sec"]
2880        [::std::mem::offset_of!(EmpyreanStationBias, bias_timing_sec) - 56usize];
2881    ["Offset of field: EmpyreanStationBias::sigma_timing_sec"]
2882        [::std::mem::offset_of!(EmpyreanStationBias, sigma_timing_sec) - 64usize];
2883    ["Offset of field: EmpyreanStationBias::significance"]
2884        [::std::mem::offset_of!(EmpyreanStationBias, significance) - 72usize];
2885};
2886impl Default for EmpyreanStationBias {
2887    fn default() -> Self {
2888        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
2889        unsafe {
2890            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
2891            s.assume_init()
2892        }
2893    }
2894}
2895#[doc = " Full solved-parameter covariance at the ABI-frozen width\n [`EMPYREAN_SOLVE_WIDTH`] (mirrors scott's `SolvedCovariance`\n tag-for-tag). The leading `width × width` block is meaningful; rows and\n columns beyond `width` are zero (RESERVED, not defaulted covariance).\n Consumers MUST read the slot tags to locate a parameter — the width\n alone is ambiguous (width 9 is Marsden OR a one-segment thrust). An\n absent tag carries [`EMPYREAN_SLOT_NONE`]."]
2896#[repr(C)]
2897#[derive(Debug, Default, Copy, Clone)]
2898pub struct EmpyreanSolvedCovariance {
2899    #[doc = " Covariance at fixed storage width; leading `width×width` meaningful."]
2900    pub matrix: [[f64; 20usize]; 20usize],
2901    #[doc = " Real solved width — 6..=17 under scott v1.14.0 (`MAX_SOLVE_WIDTH`);\n the struct reserves storage to 20. The leading `width × width`\n block is meaningful."]
2902    pub width: u32,
2903    #[doc = " Slot of the first Marsden coefficient, or [`EMPYREAN_SLOT_NONE`]."]
2904    pub marsden_slot: u32,
2905    #[doc = " Slot of the DT scalar, or [`EMPYREAN_SLOT_NONE`]."]
2906    pub dt_slot: u32,
2907    #[doc = " Slot of the AMRAT scalar, or [`EMPYREAN_SLOT_NONE`]."]
2908    pub amrat_slot: u32,
2909    #[doc = " Slots of each fitted thrust Δv segment (3 wide each); entries\n `0..thrust_count` meaningful. Δv axes are INTEGRATION-frame\n components (see [`EmpyreanODResult::dv_frame`])."]
2910    pub thrust_slots: [[u32; 3usize]; 3usize],
2911    #[doc = " Number of fitted thrust segments (0..=3)."]
2912    pub thrust_count: u32,
2913}
2914#[allow(clippy::unnecessary_operation, clippy::identity_op)]
2915const _: () = {
2916    ["Size of EmpyreanSolvedCovariance"]
2917        [::std::mem::size_of::<EmpyreanSolvedCovariance>() - 3256usize];
2918    ["Alignment of EmpyreanSolvedCovariance"]
2919        [::std::mem::align_of::<EmpyreanSolvedCovariance>() - 8usize];
2920    ["Offset of field: EmpyreanSolvedCovariance::matrix"]
2921        [::std::mem::offset_of!(EmpyreanSolvedCovariance, matrix) - 0usize];
2922    ["Offset of field: EmpyreanSolvedCovariance::width"]
2923        [::std::mem::offset_of!(EmpyreanSolvedCovariance, width) - 3200usize];
2924    ["Offset of field: EmpyreanSolvedCovariance::marsden_slot"]
2925        [::std::mem::offset_of!(EmpyreanSolvedCovariance, marsden_slot) - 3204usize];
2926    ["Offset of field: EmpyreanSolvedCovariance::dt_slot"]
2927        [::std::mem::offset_of!(EmpyreanSolvedCovariance, dt_slot) - 3208usize];
2928    ["Offset of field: EmpyreanSolvedCovariance::amrat_slot"]
2929        [::std::mem::offset_of!(EmpyreanSolvedCovariance, amrat_slot) - 3212usize];
2930    ["Offset of field: EmpyreanSolvedCovariance::thrust_slots"]
2931        [::std::mem::offset_of!(EmpyreanSolvedCovariance, thrust_slots) - 3216usize];
2932    ["Offset of field: EmpyreanSolvedCovariance::thrust_count"]
2933        [::std::mem::offset_of!(EmpyreanSolvedCovariance, thrust_count) - 3252usize];
2934};
2935#[doc = " Per-band photometric statistics (mirrors scott's `BandStat`). Owned\n heap entry, freed by [`empyrean_od_result_free`]."]
2936#[repr(C)]
2937#[derive(Debug, Copy, Clone)]
2938pub struct EmpyreanBandStat {
2939    #[doc = " Photometric band tag (owned C string)."]
2940    pub band: *mut ::std::os::raw::c_char,
2941    #[doc = " Number of observations in this band."]
2942    pub n: usize,
2943    #[doc = " Band→V offset applied (mag)."]
2944    pub offset_applied: f64,
2945    #[doc = " Mean residual in V (mag)."]
2946    pub mean_residual: f64,
2947    #[doc = " RMS residual in V (mag)."]
2948    pub rms: f64,
2949}
2950#[allow(clippy::unnecessary_operation, clippy::identity_op)]
2951const _: () = {
2952    ["Size of EmpyreanBandStat"][::std::mem::size_of::<EmpyreanBandStat>() - 40usize];
2953    ["Alignment of EmpyreanBandStat"][::std::mem::align_of::<EmpyreanBandStat>() - 8usize];
2954    ["Offset of field: EmpyreanBandStat::band"]
2955        [::std::mem::offset_of!(EmpyreanBandStat, band) - 0usize];
2956    ["Offset of field: EmpyreanBandStat::n"][::std::mem::offset_of!(EmpyreanBandStat, n) - 8usize];
2957    ["Offset of field: EmpyreanBandStat::offset_applied"]
2958        [::std::mem::offset_of!(EmpyreanBandStat, offset_applied) - 16usize];
2959    ["Offset of field: EmpyreanBandStat::mean_residual"]
2960        [::std::mem::offset_of!(EmpyreanBandStat, mean_residual) - 24usize];
2961    ["Offset of field: EmpyreanBandStat::rms"]
2962        [::std::mem::offset_of!(EmpyreanBandStat, rms) - 32usize];
2963};
2964impl Default for EmpyreanBandStat {
2965    fn default() -> Self {
2966        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
2967        unsafe {
2968            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
2969            s.assume_init()
2970        }
2971    }
2972}
2973#[doc = " One model-ladder gate decision (mirrors scott's `GateRecord`). Owned\n heap entry, freed by [`empyrean_od_result_free`]."]
2974#[repr(C)]
2975#[derive(Debug, Copy, Clone)]
2976pub struct EmpyreanGateRecord {
2977    #[doc = " Model the gate evaluated (`EMPYREAN_PHOTOMETRY_MODEL_*`, fitted)."]
2978    pub model: i32,
2979    #[doc = " 1 if the model was admitted."]
2980    pub passed: u8,
2981    #[doc = " Human-readable gate reason (owned C string)."]
2982    pub reason: *mut ::std::os::raw::c_char,
2983}
2984#[allow(clippy::unnecessary_operation, clippy::identity_op)]
2985const _: () = {
2986    ["Size of EmpyreanGateRecord"][::std::mem::size_of::<EmpyreanGateRecord>() - 16usize];
2987    ["Alignment of EmpyreanGateRecord"][::std::mem::align_of::<EmpyreanGateRecord>() - 8usize];
2988    ["Offset of field: EmpyreanGateRecord::model"]
2989        [::std::mem::offset_of!(EmpyreanGateRecord, model) - 0usize];
2990    ["Offset of field: EmpyreanGateRecord::passed"]
2991        [::std::mem::offset_of!(EmpyreanGateRecord, passed) - 4usize];
2992    ["Offset of field: EmpyreanGateRecord::reason"]
2993        [::std::mem::offset_of!(EmpyreanGateRecord, reason) - 8usize];
2994};
2995impl Default for EmpyreanGateRecord {
2996    fn default() -> Self {
2997        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
2998        unsafe {
2999            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
3000            s.assume_init()
3001        }
3002    }
3003}
3004#[doc = " Post-OD photometric solution (mirrors scott's `PhotometryResult`).\n Present only when photometry was requested and ran\n ([`EmpyreanODResult::has_photometry`]). H carries honest σ via the\n [`covariance`](EmpyreanODPhotometryResult::covariance) block."]
3005#[repr(C)]
3006#[derive(Debug, Copy, Clone)]
3007pub struct EmpyreanODPhotometryResult {
3008    #[doc = " Fitted absolute magnitude H (mag)."]
3009    pub h: f64,
3010    #[doc = " First slope parameter (G / G12 / G1 by model)."]
3011    pub slope1: f64,
3012    #[doc = " Second slope parameter (G2 for HG1G2; unused otherwise)."]
3013    pub slope2: f64,
3014    #[doc = " 1 when [`covariance`](EmpyreanODPhotometryResult::covariance) is populated."]
3015    pub has_covariance: u8,
3016    #[doc = " Parameter covariance (H, slope1, slope2 order)."]
3017    pub covariance: [[f64; 3usize]; 3usize],
3018    #[doc = " Model actually fitted (`EMPYREAN_PHOTOMETRY_MODEL_*`; never Auto)."]
3019    pub model_used: i32,
3020    #[doc = " Reduced χ² of the photometric fit over its used magnitudes."]
3021    pub reduced_chi2: f64,
3022    #[doc = " 1 when a simplex constraint was active on the fitted slopes."]
3023    pub constraint_active: u8,
3024    #[doc = " Magnitudes used in the fit."]
3025    pub n_mags_used: usize,
3026    #[doc = " Magnitudes rejected by the photometric outlier pass."]
3027    pub n_mags_rejected_photometric: usize,
3028    #[doc = " Observations carrying no magnitude."]
3029    pub n_obs_without_mags: usize,
3030    #[doc = " Magnitudes drawn from astrometrically-selected observations."]
3031    pub n_mags_from_astrometric_selected: usize,
3032    #[doc = " Magnitudes drawn from astrometrically-rejected observations."]
3033    pub n_mags_from_astrometric_rejected: usize,
3034    #[doc = " Phase-angle coverage of the fitted magnitudes (deg)."]
3035    pub alpha_min_deg: f64,
3036    pub alpha_max_deg: f64,
3037    pub alpha_span_deg: f64,
3038    #[doc = " Owned per-band statistics array; freed by [`empyrean_od_result_free`]."]
3039    pub per_band: *mut EmpyreanBandStat,
3040    pub num_per_band: usize,
3041    #[doc = " Owned model-ladder gate records; freed by [`empyrean_od_result_free`]."]
3042    pub gates: *mut EmpyreanGateRecord,
3043    pub num_gates: usize,
3044    #[doc = " Magnitudes excluded from the fit because their photometric band
3045 has no adopted V-band conversion (unknown/unspecified band
3046 codes, comet total/nuclear magnitudes). Never silent: each
3047 exclusion is counted here and the distinct offending band codes
3048 are listed in `dropped_bands`. The observations' astrometry is
3049 unaffected."]
3050    pub n_mags_dropped_unconvertible: usize,
3051    #[doc = " Distinct band codes that were dropped (owned array of owned C
3052 strings, sorted). Freed by `empyrean_od_result_free`. Null when
3053 `num_dropped_bands == 0`."]
3054    pub dropped_bands: *mut *mut ::std::os::raw::c_char,
3055    #[doc = " Number of entries in `dropped_bands` (0 when null)."]
3056    pub num_dropped_bands: usize,
3057}
3058#[allow(clippy::unnecessary_operation, clippy::identity_op)]
3059const _: () = {
3060    ["Size of EmpyreanODPhotometryResult"]
3061        [::std::mem::size_of::<EmpyreanODPhotometryResult>() - 248usize];
3062    ["Alignment of EmpyreanODPhotometryResult"]
3063        [::std::mem::align_of::<EmpyreanODPhotometryResult>() - 8usize];
3064    ["Offset of field: EmpyreanODPhotometryResult::h"]
3065        [::std::mem::offset_of!(EmpyreanODPhotometryResult, h) - 0usize];
3066    ["Offset of field: EmpyreanODPhotometryResult::slope1"]
3067        [::std::mem::offset_of!(EmpyreanODPhotometryResult, slope1) - 8usize];
3068    ["Offset of field: EmpyreanODPhotometryResult::slope2"]
3069        [::std::mem::offset_of!(EmpyreanODPhotometryResult, slope2) - 16usize];
3070    ["Offset of field: EmpyreanODPhotometryResult::has_covariance"]
3071        [::std::mem::offset_of!(EmpyreanODPhotometryResult, has_covariance) - 24usize];
3072    ["Offset of field: EmpyreanODPhotometryResult::covariance"]
3073        [::std::mem::offset_of!(EmpyreanODPhotometryResult, covariance) - 32usize];
3074    ["Offset of field: EmpyreanODPhotometryResult::model_used"]
3075        [::std::mem::offset_of!(EmpyreanODPhotometryResult, model_used) - 104usize];
3076    ["Offset of field: EmpyreanODPhotometryResult::reduced_chi2"]
3077        [::std::mem::offset_of!(EmpyreanODPhotometryResult, reduced_chi2) - 112usize];
3078    ["Offset of field: EmpyreanODPhotometryResult::constraint_active"]
3079        [::std::mem::offset_of!(EmpyreanODPhotometryResult, constraint_active) - 120usize];
3080    ["Offset of field: EmpyreanODPhotometryResult::n_mags_used"]
3081        [::std::mem::offset_of!(EmpyreanODPhotometryResult, n_mags_used) - 128usize];
3082    ["Offset of field: EmpyreanODPhotometryResult::n_mags_rejected_photometric"][::std::mem::offset_of!(
3083        EmpyreanODPhotometryResult,
3084        n_mags_rejected_photometric
3085    ) - 136usize];
3086    ["Offset of field: EmpyreanODPhotometryResult::n_obs_without_mags"]
3087        [::std::mem::offset_of!(EmpyreanODPhotometryResult, n_obs_without_mags) - 144usize];
3088    ["Offset of field: EmpyreanODPhotometryResult::n_mags_from_astrometric_selected"][::std::mem::offset_of!(
3089        EmpyreanODPhotometryResult,
3090        n_mags_from_astrometric_selected
3091    ) - 152usize];
3092    ["Offset of field: EmpyreanODPhotometryResult::n_mags_from_astrometric_rejected"][::std::mem::offset_of!(
3093        EmpyreanODPhotometryResult,
3094        n_mags_from_astrometric_rejected
3095    ) - 160usize];
3096    ["Offset of field: EmpyreanODPhotometryResult::alpha_min_deg"]
3097        [::std::mem::offset_of!(EmpyreanODPhotometryResult, alpha_min_deg) - 168usize];
3098    ["Offset of field: EmpyreanODPhotometryResult::alpha_max_deg"]
3099        [::std::mem::offset_of!(EmpyreanODPhotometryResult, alpha_max_deg) - 176usize];
3100    ["Offset of field: EmpyreanODPhotometryResult::alpha_span_deg"]
3101        [::std::mem::offset_of!(EmpyreanODPhotometryResult, alpha_span_deg) - 184usize];
3102    ["Offset of field: EmpyreanODPhotometryResult::per_band"]
3103        [::std::mem::offset_of!(EmpyreanODPhotometryResult, per_band) - 192usize];
3104    ["Offset of field: EmpyreanODPhotometryResult::num_per_band"]
3105        [::std::mem::offset_of!(EmpyreanODPhotometryResult, num_per_band) - 200usize];
3106    ["Offset of field: EmpyreanODPhotometryResult::gates"]
3107        [::std::mem::offset_of!(EmpyreanODPhotometryResult, gates) - 208usize];
3108    ["Offset of field: EmpyreanODPhotometryResult::num_gates"]
3109        [::std::mem::offset_of!(EmpyreanODPhotometryResult, num_gates) - 216usize];
3110    ["Offset of field: EmpyreanODPhotometryResult::n_mags_dropped_unconvertible"]
3111        [::std::mem::offset_of!(EmpyreanODPhotometryResult, n_mags_dropped_unconvertible)
3112            - 224usize];
3113    ["Offset of field: EmpyreanODPhotometryResult::dropped_bands"]
3114        [::std::mem::offset_of!(EmpyreanODPhotometryResult, dropped_bands) - 232usize];
3115    ["Offset of field: EmpyreanODPhotometryResult::num_dropped_bands"]
3116        [::std::mem::offset_of!(EmpyreanODPhotometryResult, num_dropped_bands) - 240usize];
3117};
3118impl Default for EmpyreanODPhotometryResult {
3119    fn default() -> Self {
3120        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
3121        unsafe {
3122            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
3123            s.assume_init()
3124        }
3125    }
3126}
3127#[doc = " Mirrors scott's [`ODResult`](scott::od::ODResult). Carries the fitted\n orbit, the 6×6 (or 9×9 when non-grav was solved) formal covariance,\n the per-observation result array, the summary, the structured\n acceptability report, and the per-station nuisance-bias array\n when `fit_station_biases` was active.\n\n The fitted **absolute** non-gravitational model (when one was solved\n or carried) is exposed via [`has_non_grav`](EmpyreanODResult::has_non_grav)\n / [`non_grav`](EmpyreanODResult::non_grav) so the orbit can be re-fed into\n propagation / evaluate / refine without losing the force model. This is\n distinct from [`non_grav_delta`](EmpyreanODResult::non_grav_delta), which\n is the *cumulative correction* the fit applied and is kept for inspection."]
3128#[repr(C)]
3129#[derive(Debug, Copy, Clone)]
3130pub struct EmpyreanODResult {
3131    pub orbit: EmpyreanPropagatedState,
3132    pub observations: *mut EmpyreanObservationResult,
3133    pub num_observations: usize,
3134    pub summary: EmpyreanResidualSummary,
3135    pub iterations: u32,
3136    #[doc = " Convergence metric at the final DC iteration (Δx^T N Δx)."]
3137    pub update_norm: f64,
3138    #[doc = " Solver reached its stopping criterion (1 = yes).\n Equivalent to `acceptability.converged_ok`; kept for backwards\n compatibility with the v0.7.0 surface that pre-dated the\n structured acceptability report."]
3139    pub converged: u8,
3140    #[doc = " Fitted 6×6 state covariance in [`covariance_representation`]."]
3141    pub covariance: [[f64; 6usize]; 6usize],
3142    #[doc = " Coordinate basis the 6×6 / 9×9 covariance is reported in\n (`EMPYREAN_REPRESENTATION_*`)."]
3143    pub covariance_representation: i32,
3144    #[doc = " 1 when [`covariance_9x9`] is populated (non-grav was solved)."]
3145    pub has_covariance_9x9: u8,
3146    #[doc = " Full 9×9 covariance over (state, A1, A2, A3) when solving for non-grav."]
3147    pub covariance_9x9: [[f64; 9usize]; 9usize],
3148    #[doc = " 1 when [`non_grav_delta`] is populated."]
3149    pub has_non_grav_delta: u8,
3150    #[doc = " Cumulative non-grav parameter corrections (ΔA1, ΔA2, ΔA3) when solving for non-grav."]
3151    pub non_grav_delta: [f64; 3usize],
3152    #[doc = " 1 when [`non_grav`] carries a fitted/absolute non-gravitational model."]
3153    pub has_non_grav: u8,
3154    #[doc = " The fitted orbit's **absolute** non-gravitational model (A1/A2/A3 +\n g(r) exponents + optional thermal-lag `dt`). Re-feed this onto the\n orbit for propagation / evaluate / refine. Zeroed when the orbit is\n gravity-only (`has_non_grav = 0`)."]
3155    pub non_grav: EmpyreanNonGravParams,
3156    #[doc = " Number of rejection/refit passes performed."]
3157    pub rejection_passes: u32,
3158    #[doc = " Number of oppositions successfully fit."]
3159    pub num_oppositions_fit: u32,
3160    #[doc = " Force model tier actually used (0=Approximate, 1=Basic, 2=Standard)."]
3161    pub force_model_used: i32,
3162    #[doc = " Solve-for parameter set requested on the driving config\n (`EMPYREAN_SOLVE_FOR_*`). Together with `has_covariance_9x9`\n disambiguates Auto outcomes."]
3163    pub solve_for_used: i32,
3164    #[doc = " Structured fit-quality verdict. The `acceptable` flags can be\n checked directly; per-check values + thresholds are exposed for\n reporting and downstream sub-classification."]
3165    pub acceptability: EmpyreanAcceptabilityReport,
3166    #[doc = " Per-station fitted nuisance biases when [`EmpyreanODConfig::fit_station_biases`]\n was set. Owned heap allocation; freed by [`empyrean_od_result_free`].\n Null + `num_station_biases = 0` when no bias fit was configured."]
3167    pub station_biases: *mut EmpyreanStationBias,
3168    pub num_station_biases: usize,
3169    #[doc = " 1 when [`solved_covariance`](EmpyreanODResult::solved_covariance)\n is populated (any solved width > 6). 0 for a pure state-only fit."]
3170    pub has_solved_covariance: u8,
3171    #[doc = " Full tagged solved-parameter covariance at the frozen width. The\n go-forward field for ALL solved widths (including 9); the legacy\n `covariance_9x9` remains for one deprecation window."]
3172    pub solved_covariance: EmpyreanSolvedCovariance,
3173    #[doc = " 1 when [`dt_delta`](EmpyreanODResult::dt_delta) is populated (DT solved)."]
3174    pub has_dt_delta: u8,
3175    #[doc = " Cumulative non-grav time-delay correction ΔDT (days)."]
3176    pub dt_delta: f64,
3177    #[doc = " 1 when [`amrat_delta`](EmpyreanODResult::amrat_delta) is populated (AMRAT solved)."]
3178    pub has_amrat_delta: u8,
3179    #[doc = " Cumulative SRP AMRAT correction (m²/kg)."]
3180    pub amrat_delta: f64,
3181    #[doc = " Number of fitted thrust Δv segments (0..=3); 0 = no thrust solve."]
3182    pub thrust_delta_count: u32,
3183    #[doc = " Per-segment fitted Δv in m/s, expressed in\n [`dv_frame`](EmpyreanODResult::dv_frame). Entries\n `0..thrust_delta_count` meaningful."]
3184    pub thrust_delta_m_per_s: [[f64; 3usize]; 3usize],
3185    #[doc = " Integration frame the Δv components are expressed in (0=ICRF,\n 1=EclipticJ2000). Only meaningful when `thrust_delta_count > 0`."]
3186    pub dv_frame: i32,
3187    #[doc = " 1 when [`photometry`](EmpyreanODResult::photometry) carries a fitted H/G solution."]
3188    pub has_photometry: u8,
3189    #[doc = " Post-OD photometric solution when photometry was requested + ran.\n Owns its per-band / gate arrays (freed by `empyrean_od_result_free`)."]
3190    pub photometry: EmpyreanODPhotometryResult,
3191    #[doc = " 1 when [`srp`] carries a fitted/carried absolute SRP slot."]
3192    pub has_srp: u8,
3193    #[doc = " The fitted orbit's absolute SRP slot (AMRAT + Cr + optional AMRAT\n variance). Re-feed this onto the orbit (`has_srp = 1`) so a fitted orbit\n never silently drops its SRP force. Zeroed when `has_srp = 0`."]
3194    pub srp: EmpyreanSRPParams,
3195    #[doc = " Event-aware trust verdict on the delivered covariance
3196 (`EMPYREAN_COVARIANCE_TRUST_*`). `NOT_EVALUATED` (0) means the
3197 call path ran no gate — absence of a verdict is not trust."]
3198    pub covariance_trust: i32,
3199    #[doc = " Intervening-event kind (`EMPYREAN_TRUST_EVENT_*`); `NONE` unless
3200 `covariance_trust == ENCOUNTER_INTERVENES`."]
3201    pub trust_event_kind: i32,
3202    #[doc = " Event epoch (MJD TDB). NaN when no event."]
3203    pub trust_event_epoch_mjd_tdb: f64,
3204    #[doc = " Close-approach distance (AU). NaN unless
3205 `trust_event_kind == CLOSE_APPROACH`."]
3206    pub trust_event_distance_au: f64,
3207    #[doc = " Nonlinearity ratio at the crossing. NaN unless
3208 `trust_event_kind == HIGH_NONLINEARITY`."]
3209    pub trust_event_nonlinearity: f64,
3210    #[doc = " Threshold the nonlinearity exceeded. NaN unless
3211 `trust_event_kind == HIGH_NONLINEARITY`."]
3212    pub trust_event_threshold: f64,
3213    #[doc = " Name of the approached body (owned C string; freed by
3214 `empyrean_od_result_free`). Null unless
3215 `trust_event_kind == CLOSE_APPROACH`."]
3216    pub trust_event_body: *mut ::std::os::raw::c_char,
3217    #[doc = " Solved-for width N of the fit the verdict refers to. 0 when the
3218 verdict carries no width (`TRUSTED` / `NOT_EVALUATED`)."]
3219    pub trust_solved_width: u32,
3220    #[doc = " 1 when a second-order (state-only) correction can recover the
3221 encounter (solved width 6); 0 otherwise. Meaningful only for
3222 `ENCOUNTER_INTERVENES`."]
3223    pub trust_second_order_recoverable: u8,
3224}
3225#[allow(clippy::unnecessary_operation, clippy::identity_op)]
3226const _: () = {
3227    ["Size of EmpyreanODResult"][::std::mem::size_of::<EmpyreanODResult>() - 7600usize];
3228    ["Alignment of EmpyreanODResult"][::std::mem::align_of::<EmpyreanODResult>() - 8usize];
3229    ["Offset of field: EmpyreanODResult::orbit"]
3230        [::std::mem::offset_of!(EmpyreanODResult, orbit) - 0usize];
3231    ["Offset of field: EmpyreanODResult::observations"]
3232        [::std::mem::offset_of!(EmpyreanODResult, observations) - 2392usize];
3233    ["Offset of field: EmpyreanODResult::num_observations"]
3234        [::std::mem::offset_of!(EmpyreanODResult, num_observations) - 2400usize];
3235    ["Offset of field: EmpyreanODResult::summary"]
3236        [::std::mem::offset_of!(EmpyreanODResult, summary) - 2408usize];
3237    ["Offset of field: EmpyreanODResult::iterations"]
3238        [::std::mem::offset_of!(EmpyreanODResult, iterations) - 2552usize];
3239    ["Offset of field: EmpyreanODResult::update_norm"]
3240        [::std::mem::offset_of!(EmpyreanODResult, update_norm) - 2560usize];
3241    ["Offset of field: EmpyreanODResult::converged"]
3242        [::std::mem::offset_of!(EmpyreanODResult, converged) - 2568usize];
3243    ["Offset of field: EmpyreanODResult::covariance"]
3244        [::std::mem::offset_of!(EmpyreanODResult, covariance) - 2576usize];
3245    ["Offset of field: EmpyreanODResult::covariance_representation"]
3246        [::std::mem::offset_of!(EmpyreanODResult, covariance_representation) - 2864usize];
3247    ["Offset of field: EmpyreanODResult::has_covariance_9x9"]
3248        [::std::mem::offset_of!(EmpyreanODResult, has_covariance_9x9) - 2868usize];
3249    ["Offset of field: EmpyreanODResult::covariance_9x9"]
3250        [::std::mem::offset_of!(EmpyreanODResult, covariance_9x9) - 2872usize];
3251    ["Offset of field: EmpyreanODResult::has_non_grav_delta"]
3252        [::std::mem::offset_of!(EmpyreanODResult, has_non_grav_delta) - 3520usize];
3253    ["Offset of field: EmpyreanODResult::non_grav_delta"]
3254        [::std::mem::offset_of!(EmpyreanODResult, non_grav_delta) - 3528usize];
3255    ["Offset of field: EmpyreanODResult::has_non_grav"]
3256        [::std::mem::offset_of!(EmpyreanODResult, has_non_grav) - 3552usize];
3257    ["Offset of field: EmpyreanODResult::non_grav"]
3258        [::std::mem::offset_of!(EmpyreanODResult, non_grav) - 3560usize];
3259    ["Offset of field: EmpyreanODResult::rejection_passes"]
3260        [::std::mem::offset_of!(EmpyreanODResult, rejection_passes) - 3720usize];
3261    ["Offset of field: EmpyreanODResult::num_oppositions_fit"]
3262        [::std::mem::offset_of!(EmpyreanODResult, num_oppositions_fit) - 3724usize];
3263    ["Offset of field: EmpyreanODResult::force_model_used"]
3264        [::std::mem::offset_of!(EmpyreanODResult, force_model_used) - 3728usize];
3265    ["Offset of field: EmpyreanODResult::solve_for_used"]
3266        [::std::mem::offset_of!(EmpyreanODResult, solve_for_used) - 3732usize];
3267    ["Offset of field: EmpyreanODResult::acceptability"]
3268        [::std::mem::offset_of!(EmpyreanODResult, acceptability) - 3736usize];
3269    ["Offset of field: EmpyreanODResult::station_biases"]
3270        [::std::mem::offset_of!(EmpyreanODResult, station_biases) - 3856usize];
3271    ["Offset of field: EmpyreanODResult::num_station_biases"]
3272        [::std::mem::offset_of!(EmpyreanODResult, num_station_biases) - 3864usize];
3273    ["Offset of field: EmpyreanODResult::has_solved_covariance"]
3274        [::std::mem::offset_of!(EmpyreanODResult, has_solved_covariance) - 3872usize];
3275    ["Offset of field: EmpyreanODResult::solved_covariance"]
3276        [::std::mem::offset_of!(EmpyreanODResult, solved_covariance) - 3880usize];
3277    ["Offset of field: EmpyreanODResult::has_dt_delta"]
3278        [::std::mem::offset_of!(EmpyreanODResult, has_dt_delta) - 7136usize];
3279    ["Offset of field: EmpyreanODResult::dt_delta"]
3280        [::std::mem::offset_of!(EmpyreanODResult, dt_delta) - 7144usize];
3281    ["Offset of field: EmpyreanODResult::has_amrat_delta"]
3282        [::std::mem::offset_of!(EmpyreanODResult, has_amrat_delta) - 7152usize];
3283    ["Offset of field: EmpyreanODResult::amrat_delta"]
3284        [::std::mem::offset_of!(EmpyreanODResult, amrat_delta) - 7160usize];
3285    ["Offset of field: EmpyreanODResult::thrust_delta_count"]
3286        [::std::mem::offset_of!(EmpyreanODResult, thrust_delta_count) - 7168usize];
3287    ["Offset of field: EmpyreanODResult::thrust_delta_m_per_s"]
3288        [::std::mem::offset_of!(EmpyreanODResult, thrust_delta_m_per_s) - 7176usize];
3289    ["Offset of field: EmpyreanODResult::dv_frame"]
3290        [::std::mem::offset_of!(EmpyreanODResult, dv_frame) - 7248usize];
3291    ["Offset of field: EmpyreanODResult::has_photometry"]
3292        [::std::mem::offset_of!(EmpyreanODResult, has_photometry) - 7252usize];
3293    ["Offset of field: EmpyreanODResult::photometry"]
3294        [::std::mem::offset_of!(EmpyreanODResult, photometry) - 7256usize];
3295    ["Offset of field: EmpyreanODResult::has_srp"]
3296        [::std::mem::offset_of!(EmpyreanODResult, has_srp) - 7504usize];
3297    ["Offset of field: EmpyreanODResult::srp"]
3298        [::std::mem::offset_of!(EmpyreanODResult, srp) - 7512usize];
3299    ["Offset of field: EmpyreanODResult::covariance_trust"]
3300        [::std::mem::offset_of!(EmpyreanODResult, covariance_trust) - 7544usize];
3301    ["Offset of field: EmpyreanODResult::trust_event_kind"]
3302        [::std::mem::offset_of!(EmpyreanODResult, trust_event_kind) - 7548usize];
3303    ["Offset of field: EmpyreanODResult::trust_event_epoch_mjd_tdb"]
3304        [::std::mem::offset_of!(EmpyreanODResult, trust_event_epoch_mjd_tdb) - 7552usize];
3305    ["Offset of field: EmpyreanODResult::trust_event_distance_au"]
3306        [::std::mem::offset_of!(EmpyreanODResult, trust_event_distance_au) - 7560usize];
3307    ["Offset of field: EmpyreanODResult::trust_event_nonlinearity"]
3308        [::std::mem::offset_of!(EmpyreanODResult, trust_event_nonlinearity) - 7568usize];
3309    ["Offset of field: EmpyreanODResult::trust_event_threshold"]
3310        [::std::mem::offset_of!(EmpyreanODResult, trust_event_threshold) - 7576usize];
3311    ["Offset of field: EmpyreanODResult::trust_event_body"]
3312        [::std::mem::offset_of!(EmpyreanODResult, trust_event_body) - 7584usize];
3313    ["Offset of field: EmpyreanODResult::trust_solved_width"]
3314        [::std::mem::offset_of!(EmpyreanODResult, trust_solved_width) - 7592usize];
3315    ["Offset of field: EmpyreanODResult::trust_second_order_recoverable"]
3316        [::std::mem::offset_of!(EmpyreanODResult, trust_second_order_recoverable) - 7596usize];
3317};
3318impl Default for EmpyreanODResult {
3319    fn default() -> Self {
3320        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
3321        unsafe {
3322            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
3323            s.assume_init()
3324        }
3325    }
3326}
3327#[doc = " Result of orbit evaluation (residuals without fitting).\n\n Same per-observation surface as [`EmpyreanODResult`] (rejection +\n influence fields are NaN / `NOT_EVALUATED` because evaluate does\n not run rejection or influence passes), but no fitted orbit or\n acceptability report."]
3328#[repr(C)]
3329#[derive(Debug, Copy, Clone)]
3330pub struct EmpyreanEvaluateResult {
3331    pub observations: *mut EmpyreanObservationResult,
3332    pub num_observations: usize,
3333    pub summary: EmpyreanResidualSummary,
3334}
3335#[allow(clippy::unnecessary_operation, clippy::identity_op)]
3336const _: () = {
3337    ["Size of EmpyreanEvaluateResult"][::std::mem::size_of::<EmpyreanEvaluateResult>() - 160usize];
3338    ["Alignment of EmpyreanEvaluateResult"]
3339        [::std::mem::align_of::<EmpyreanEvaluateResult>() - 8usize];
3340    ["Offset of field: EmpyreanEvaluateResult::observations"]
3341        [::std::mem::offset_of!(EmpyreanEvaluateResult, observations) - 0usize];
3342    ["Offset of field: EmpyreanEvaluateResult::num_observations"]
3343        [::std::mem::offset_of!(EmpyreanEvaluateResult, num_observations) - 8usize];
3344    ["Offset of field: EmpyreanEvaluateResult::summary"]
3345        [::std::mem::offset_of!(EmpyreanEvaluateResult, summary) - 16usize];
3346};
3347impl Default for EmpyreanEvaluateResult {
3348    fn default() -> Self {
3349        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
3350        unsafe {
3351            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
3352            s.assume_init()
3353        }
3354    }
3355}
3356#[doc = " A single planned (candidate) observation: an epoch plus either an optical or\n a radar measurement spec. Optical fields are read when `kind == 0`, radar\n fields when `kind == 1`; absent optional radar target properties use NaN\n (the link budget refuses, rather than silently defaults, a missing value)."]
3357#[repr(C)]
3358#[derive(Debug, Copy, Clone)]
3359pub struct EmpyreanPlannedObservation {
3360    #[doc = " Planned (receive, for radar) epoch — MJD, TDB."]
3361    pub epoch_mjd_tdb: f64,
3362    #[doc = " 0 = optical, 1 = radar."]
3363    pub kind: u8,
3364    #[doc = " Optical: registered MPC station code (null-terminated UTF-8)."]
3365    pub optical_code: *const ::std::os::raw::c_char,
3366    #[doc = " Optical 1σ (RA·cosδ) uncertainty (arcsec)."]
3367    pub optical_sigma_ra_arcsec: f64,
3368    #[doc = " Optical 1σ Dec uncertainty (arcsec)."]
3369    pub optical_sigma_dec_arcsec: f64,
3370    #[doc = " Radar transmit dish preset: 0 = Goldstone DSS-14, 1 = Green Bank\n (receive-only), 2 = Arecibo (defunct — rejected loudly, never scheduled)."]
3371    pub radar_transmit_station: u8,
3372    #[doc = " Radar receive dish preset (same encoding; equal to transmit = monostatic)."]
3373    pub radar_receive_station: u8,
3374    #[doc = " Radar mode: 0 = Delay, 1 = Doppler, 2 = Both."]
3375    pub radar_mode: u8,
3376    #[doc = " Waveform bandwidth (Hz) — sets the delay (range) σ."]
3377    pub radar_bandwidth_hz: f64,
3378    #[doc = " Doppler frequency resolution (Hz) — sets the Doppler (range-rate) σ."]
3379    pub radar_freq_resolution_hz: f64,
3380    #[doc = " Supplied effective SNR (linear, not dB). NaN → compute from the link\n budget using the target properties + integration time below."]
3381    pub radar_snr: f64,
3382    #[doc = " Link-budget target absolute magnitude H (mag). NaN = absent."]
3383    pub radar_target_h_mag: f64,
3384    #[doc = " Link-budget target visual geometric albedo. NaN = absent."]
3385    pub radar_target_visual_albedo: f64,
3386    #[doc = " Link-budget target radar (OC) albedo. NaN = absent."]
3387    pub radar_target_radar_albedo: f64,
3388    #[doc = " Link-budget target effective diameter (km). NaN = absent."]
3389    pub radar_target_diameter_km: f64,
3390    #[doc = " Link-budget target rotation period (hours), caps coherent integration.\n NaN = absent."]
3391    pub radar_target_spin_period_hours: f64,
3392    #[doc = " Coherent integration time (s) for the link-budget SNR."]
3393    pub radar_integration_s: f64,
3394}
3395#[allow(clippy::unnecessary_operation, clippy::identity_op)]
3396const _: () = {
3397    ["Size of EmpyreanPlannedObservation"]
3398        [::std::mem::size_of::<EmpyreanPlannedObservation>() - 120usize];
3399    ["Alignment of EmpyreanPlannedObservation"]
3400        [::std::mem::align_of::<EmpyreanPlannedObservation>() - 8usize];
3401    ["Offset of field: EmpyreanPlannedObservation::epoch_mjd_tdb"]
3402        [::std::mem::offset_of!(EmpyreanPlannedObservation, epoch_mjd_tdb) - 0usize];
3403    ["Offset of field: EmpyreanPlannedObservation::kind"]
3404        [::std::mem::offset_of!(EmpyreanPlannedObservation, kind) - 8usize];
3405    ["Offset of field: EmpyreanPlannedObservation::optical_code"]
3406        [::std::mem::offset_of!(EmpyreanPlannedObservation, optical_code) - 16usize];
3407    ["Offset of field: EmpyreanPlannedObservation::optical_sigma_ra_arcsec"]
3408        [::std::mem::offset_of!(EmpyreanPlannedObservation, optical_sigma_ra_arcsec) - 24usize];
3409    ["Offset of field: EmpyreanPlannedObservation::optical_sigma_dec_arcsec"]
3410        [::std::mem::offset_of!(EmpyreanPlannedObservation, optical_sigma_dec_arcsec) - 32usize];
3411    ["Offset of field: EmpyreanPlannedObservation::radar_transmit_station"]
3412        [::std::mem::offset_of!(EmpyreanPlannedObservation, radar_transmit_station) - 40usize];
3413    ["Offset of field: EmpyreanPlannedObservation::radar_receive_station"]
3414        [::std::mem::offset_of!(EmpyreanPlannedObservation, radar_receive_station) - 41usize];
3415    ["Offset of field: EmpyreanPlannedObservation::radar_mode"]
3416        [::std::mem::offset_of!(EmpyreanPlannedObservation, radar_mode) - 42usize];
3417    ["Offset of field: EmpyreanPlannedObservation::radar_bandwidth_hz"]
3418        [::std::mem::offset_of!(EmpyreanPlannedObservation, radar_bandwidth_hz) - 48usize];
3419    ["Offset of field: EmpyreanPlannedObservation::radar_freq_resolution_hz"]
3420        [::std::mem::offset_of!(EmpyreanPlannedObservation, radar_freq_resolution_hz) - 56usize];
3421    ["Offset of field: EmpyreanPlannedObservation::radar_snr"]
3422        [::std::mem::offset_of!(EmpyreanPlannedObservation, radar_snr) - 64usize];
3423    ["Offset of field: EmpyreanPlannedObservation::radar_target_h_mag"]
3424        [::std::mem::offset_of!(EmpyreanPlannedObservation, radar_target_h_mag) - 72usize];
3425    ["Offset of field: EmpyreanPlannedObservation::radar_target_visual_albedo"]
3426        [::std::mem::offset_of!(EmpyreanPlannedObservation, radar_target_visual_albedo) - 80usize];
3427    ["Offset of field: EmpyreanPlannedObservation::radar_target_radar_albedo"]
3428        [::std::mem::offset_of!(EmpyreanPlannedObservation, radar_target_radar_albedo) - 88usize];
3429    ["Offset of field: EmpyreanPlannedObservation::radar_target_diameter_km"]
3430        [::std::mem::offset_of!(EmpyreanPlannedObservation, radar_target_diameter_km) - 96usize];
3431    ["Offset of field: EmpyreanPlannedObservation::radar_target_spin_period_hours"][::std::mem::offset_of!(
3432        EmpyreanPlannedObservation,
3433        radar_target_spin_period_hours
3434    ) - 104usize];
3435    ["Offset of field: EmpyreanPlannedObservation::radar_integration_s"]
3436        [::std::mem::offset_of!(EmpyreanPlannedObservation, radar_integration_s) - 112usize];
3437};
3438impl Default for EmpyreanPlannedObservation {
3439    fn default() -> Self {
3440        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
3441        unsafe {
3442            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
3443            s.assume_init()
3444        }
3445    }
3446}
3447#[doc = " Per-observatory assumptions: astrometric σ + observability filters."]
3448#[repr(C)]
3449#[derive(Debug, Copy, Clone)]
3450pub struct EmpyreanObservatoryConfig {
3451    #[doc = " MPC observatory code (null-terminated UTF-8)."]
3452    pub obs_code: *const ::std::os::raw::c_char,
3453    #[doc = " 1σ (RA·cosδ) astrometric uncertainty (arcsec)."]
3454    pub sigma_ra_arcsec: f64,
3455    #[doc = " 1σ Dec astrometric uncertainty (arcsec)."]
3456    pub sigma_dec_arcsec: f64,
3457    #[doc = " Limiting apparent magnitude."]
3458    pub max_apparent_mag: f64,
3459    #[doc = " Minimum solar elongation (degrees)."]
3460    pub min_elongation_deg: f64,
3461}
3462#[allow(clippy::unnecessary_operation, clippy::identity_op)]
3463const _: () = {
3464    ["Size of EmpyreanObservatoryConfig"]
3465        [::std::mem::size_of::<EmpyreanObservatoryConfig>() - 40usize];
3466    ["Alignment of EmpyreanObservatoryConfig"]
3467        [::std::mem::align_of::<EmpyreanObservatoryConfig>() - 8usize];
3468    ["Offset of field: EmpyreanObservatoryConfig::obs_code"]
3469        [::std::mem::offset_of!(EmpyreanObservatoryConfig, obs_code) - 0usize];
3470    ["Offset of field: EmpyreanObservatoryConfig::sigma_ra_arcsec"]
3471        [::std::mem::offset_of!(EmpyreanObservatoryConfig, sigma_ra_arcsec) - 8usize];
3472    ["Offset of field: EmpyreanObservatoryConfig::sigma_dec_arcsec"]
3473        [::std::mem::offset_of!(EmpyreanObservatoryConfig, sigma_dec_arcsec) - 16usize];
3474    ["Offset of field: EmpyreanObservatoryConfig::max_apparent_mag"]
3475        [::std::mem::offset_of!(EmpyreanObservatoryConfig, max_apparent_mag) - 24usize];
3476    ["Offset of field: EmpyreanObservatoryConfig::min_elongation_deg"]
3477        [::std::mem::offset_of!(EmpyreanObservatoryConfig, min_elongation_deg) - 32usize];
3478};
3479impl Default for EmpyreanObservatoryConfig {
3480    fn default() -> Self {
3481        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
3482        unsafe {
3483            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
3484            s.assume_init()
3485        }
3486    }
3487}
3488#[doc = " Planning configuration: force model, integration tolerance, the\n per-observatory astrometric assumptions, and threading."]
3489#[repr(C)]
3490#[derive(Debug, Copy, Clone)]
3491pub struct EmpyreanPlanningConfig {
3492    #[doc = " Force-model tier: 0 = Approximate, 1 = Basic, 2 = Standard."]
3493    pub force_model: i32,
3494    #[doc = " GR15 / IAS15 integration tolerance."]
3495    pub epsilon: f64,
3496    #[doc = " Per-observatory config array."]
3497    pub observatories: *const EmpyreanObservatoryConfig,
3498    #[doc = " Number of entries in `observatories`."]
3499    pub num_observatories: usize,
3500    #[doc = " Threads for batch operations; -1 = all CPUs."]
3501    pub num_threads: i32,
3502}
3503#[allow(clippy::unnecessary_operation, clippy::identity_op)]
3504const _: () = {
3505    ["Size of EmpyreanPlanningConfig"][::std::mem::size_of::<EmpyreanPlanningConfig>() - 40usize];
3506    ["Alignment of EmpyreanPlanningConfig"]
3507        [::std::mem::align_of::<EmpyreanPlanningConfig>() - 8usize];
3508    ["Offset of field: EmpyreanPlanningConfig::force_model"]
3509        [::std::mem::offset_of!(EmpyreanPlanningConfig, force_model) - 0usize];
3510    ["Offset of field: EmpyreanPlanningConfig::epsilon"]
3511        [::std::mem::offset_of!(EmpyreanPlanningConfig, epsilon) - 8usize];
3512    ["Offset of field: EmpyreanPlanningConfig::observatories"]
3513        [::std::mem::offset_of!(EmpyreanPlanningConfig, observatories) - 16usize];
3514    ["Offset of field: EmpyreanPlanningConfig::num_observatories"]
3515        [::std::mem::offset_of!(EmpyreanPlanningConfig, num_observatories) - 24usize];
3516    ["Offset of field: EmpyreanPlanningConfig::num_threads"]
3517        [::std::mem::offset_of!(EmpyreanPlanningConfig, num_threads) - 32usize];
3518};
3519impl Default for EmpyreanPlanningConfig {
3520    fn default() -> Self {
3521        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
3522        unsafe {
3523            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
3524            s.assume_init()
3525        }
3526    }
3527}
3528#[doc = " Covariance summary metrics (prior, posterior, or per-candidate cumulative)."]
3529#[repr(C)]
3530#[derive(Debug, Default, Copy, Clone)]
3531pub struct EmpyreanCovarianceMetrics {
3532    #[doc = " RSS position 1σ (km)."]
3533    pub position_sigma_km: f64,
3534    #[doc = " RSS velocity 1σ (m/s) — the rendezvous-Δv-knowledge term."]
3535    pub velocity_sigma_m_s: f64,
3536    #[doc = " Semi-major axis of the 1σ position ellipsoid (km)."]
3537    pub semi_major_km: f64,
3538    #[doc = " Semi-minor axis of the 1σ position ellipsoid (km)."]
3539    pub semi_minor_km: f64,
3540    #[doc = " ln(det(Σ)) — D-optimality criterion."]
3541    pub log_det: f64,
3542}
3543#[allow(clippy::unnecessary_operation, clippy::identity_op)]
3544const _: () = {
3545    ["Size of EmpyreanCovarianceMetrics"]
3546        [::std::mem::size_of::<EmpyreanCovarianceMetrics>() - 40usize];
3547    ["Alignment of EmpyreanCovarianceMetrics"]
3548        [::std::mem::align_of::<EmpyreanCovarianceMetrics>() - 8usize];
3549    ["Offset of field: EmpyreanCovarianceMetrics::position_sigma_km"]
3550        [::std::mem::offset_of!(EmpyreanCovarianceMetrics, position_sigma_km) - 0usize];
3551    ["Offset of field: EmpyreanCovarianceMetrics::velocity_sigma_m_s"]
3552        [::std::mem::offset_of!(EmpyreanCovarianceMetrics, velocity_sigma_m_s) - 8usize];
3553    ["Offset of field: EmpyreanCovarianceMetrics::semi_major_km"]
3554        [::std::mem::offset_of!(EmpyreanCovarianceMetrics, semi_major_km) - 16usize];
3555    ["Offset of field: EmpyreanCovarianceMetrics::semi_minor_km"]
3556        [::std::mem::offset_of!(EmpyreanCovarianceMetrics, semi_minor_km) - 24usize];
3557    ["Offset of field: EmpyreanCovarianceMetrics::log_det"]
3558        [::std::mem::offset_of!(EmpyreanCovarianceMetrics, log_det) - 32usize];
3559};
3560#[doc = " One predicted sky-plane point of the plan's optical ephemeris: the\n target's predicted topocentric right ascension and declination\n (degrees, ICRF) at an optical candidate's epoch (MJD, TDB)."]
3561#[repr(C)]
3562#[derive(Debug, Default, Copy, Clone)]
3563pub struct EmpyreanPlanEphemerisPoint {
3564    #[doc = " Epoch — MJD, TDB."]
3565    pub epoch_mjd_tdb: f64,
3566    #[doc = " Predicted topocentric right ascension (degrees, ICRF)."]
3567    pub ra_deg: f64,
3568    #[doc = " Predicted topocentric declination (degrees, ICRF)."]
3569    pub dec_deg: f64,
3570}
3571#[allow(clippy::unnecessary_operation, clippy::identity_op)]
3572const _: () = {
3573    ["Size of EmpyreanPlanEphemerisPoint"]
3574        [::std::mem::size_of::<EmpyreanPlanEphemerisPoint>() - 24usize];
3575    ["Alignment of EmpyreanPlanEphemerisPoint"]
3576        [::std::mem::align_of::<EmpyreanPlanEphemerisPoint>() - 8usize];
3577    ["Offset of field: EmpyreanPlanEphemerisPoint::epoch_mjd_tdb"]
3578        [::std::mem::offset_of!(EmpyreanPlanEphemerisPoint, epoch_mjd_tdb) - 0usize];
3579    ["Offset of field: EmpyreanPlanEphemerisPoint::ra_deg"]
3580        [::std::mem::offset_of!(EmpyreanPlanEphemerisPoint, ra_deg) - 8usize];
3581    ["Offset of field: EmpyreanPlanEphemerisPoint::dec_deg"]
3582        [::std::mem::offset_of!(EmpyreanPlanEphemerisPoint, dec_deg) - 16usize];
3583};
3584#[doc = " Per-candidate information-gain analysis."]
3585#[repr(C)]
3586#[derive(Debug, Copy, Clone)]
3587pub struct EmpyreanPlanCandidate {
3588    #[doc = " Index into the planned-observation list."]
3589    pub index: usize,
3590    #[doc = " Observatory / receive-station code (owned; freed by\n `empyrean_plan_result_free`)."]
3591    pub obs_code: *mut ::std::os::raw::c_char,
3592    #[doc = " 0 = optical, 1 = radar."]
3593    pub kind: u8,
3594    #[doc = " 1 if observable at this epoch (passes the filters / has positive SNR)."]
3595    pub observable: u8,
3596    #[doc = " Sky-plane along-track 1σ (arcsec) — optical geometry (NaN for radar)."]
3597    pub along_track_sigma_arcsec: f64,
3598    #[doc = " Sky-plane cross-track 1σ (arcsec)."]
3599    pub cross_track_sigma_arcsec: f64,
3600    #[doc = " Predicted RA·cosδ 1σ (arcsec)."]
3601    pub ra_sigma_arcsec: f64,
3602    #[doc = " Predicted Dec 1σ (arcsec)."]
3603    pub dec_sigma_arcsec: f64,
3604    #[doc = " Position angle of the sky-plane uncertainty ellipse (degrees)."]
3605    pub position_angle_deg: f64,
3606    #[doc = " Marginal covariance-volume reduction factor from this observation (≤ 1)."]
3607    pub marginal_volume_reduction: f64,
3608    #[doc = " Fractional position-σ improvement from this observation (∈ [0, 1])."]
3609    pub marginal_position_improvement: f64,
3610    #[doc = " Post-observation along-track 1σ (arcsec)."]
3611    pub post_along_track_sigma_arcsec: f64,
3612    #[doc = " Post-observation cross-track 1σ (arcsec)."]
3613    pub post_cross_track_sigma_arcsec: f64,
3614    #[doc = " Covariance metrics after folding this observation and all prior ones."]
3615    pub cumulative: EmpyreanCovarianceMetrics,
3616    #[doc = " Active solve-for width (6 = state-only)."]
3617    pub active_width: usize,
3618    #[doc = " Radar only: effective signal-to-noise ratio used for the\n delay/Doppler measurement uncertainty (linear power ratio, not\n dB). Always finite and positive for a radar candidate; NaN for\n an optical candidate."]
3619    pub radar_snr: f64,
3620    #[doc = " Radar only: one-way topocentric range to the target at the\n receive epoch (km), derived from the predicted round-trip delay.\n NaN for an optical candidate."]
3621    pub radar_range_km: f64,
3622    #[doc = " Radar only: human-readable notes recording assumptions made\n while deriving the SNR from the link budget. Owned,\n null-terminated UTF-8 strings, freed by\n `empyrean_plan_result_free`. Null/0 when there are no notes."]
3623    pub radar_provenance: *mut *mut ::std::os::raw::c_char,
3624    #[doc = " Number of entries in `radar_provenance` (0 when null)."]
3625    pub num_radar_provenance: usize,
3626    #[doc = " Radar only: measurement mode — 0 = delay, 1 = Doppler,\n 2 = both. -1 for an optical candidate."]
3627    pub radar_mode: i32,
3628}
3629#[allow(clippy::unnecessary_operation, clippy::identity_op)]
3630const _: () = {
3631    ["Size of EmpyreanPlanCandidate"][::std::mem::size_of::<EmpyreanPlanCandidate>() - 184usize];
3632    ["Alignment of EmpyreanPlanCandidate"]
3633        [::std::mem::align_of::<EmpyreanPlanCandidate>() - 8usize];
3634    ["Offset of field: EmpyreanPlanCandidate::index"]
3635        [::std::mem::offset_of!(EmpyreanPlanCandidate, index) - 0usize];
3636    ["Offset of field: EmpyreanPlanCandidate::obs_code"]
3637        [::std::mem::offset_of!(EmpyreanPlanCandidate, obs_code) - 8usize];
3638    ["Offset of field: EmpyreanPlanCandidate::kind"]
3639        [::std::mem::offset_of!(EmpyreanPlanCandidate, kind) - 16usize];
3640    ["Offset of field: EmpyreanPlanCandidate::observable"]
3641        [::std::mem::offset_of!(EmpyreanPlanCandidate, observable) - 17usize];
3642    ["Offset of field: EmpyreanPlanCandidate::along_track_sigma_arcsec"]
3643        [::std::mem::offset_of!(EmpyreanPlanCandidate, along_track_sigma_arcsec) - 24usize];
3644    ["Offset of field: EmpyreanPlanCandidate::cross_track_sigma_arcsec"]
3645        [::std::mem::offset_of!(EmpyreanPlanCandidate, cross_track_sigma_arcsec) - 32usize];
3646    ["Offset of field: EmpyreanPlanCandidate::ra_sigma_arcsec"]
3647        [::std::mem::offset_of!(EmpyreanPlanCandidate, ra_sigma_arcsec) - 40usize];
3648    ["Offset of field: EmpyreanPlanCandidate::dec_sigma_arcsec"]
3649        [::std::mem::offset_of!(EmpyreanPlanCandidate, dec_sigma_arcsec) - 48usize];
3650    ["Offset of field: EmpyreanPlanCandidate::position_angle_deg"]
3651        [::std::mem::offset_of!(EmpyreanPlanCandidate, position_angle_deg) - 56usize];
3652    ["Offset of field: EmpyreanPlanCandidate::marginal_volume_reduction"]
3653        [::std::mem::offset_of!(EmpyreanPlanCandidate, marginal_volume_reduction) - 64usize];
3654    ["Offset of field: EmpyreanPlanCandidate::marginal_position_improvement"]
3655        [::std::mem::offset_of!(EmpyreanPlanCandidate, marginal_position_improvement) - 72usize];
3656    ["Offset of field: EmpyreanPlanCandidate::post_along_track_sigma_arcsec"]
3657        [::std::mem::offset_of!(EmpyreanPlanCandidate, post_along_track_sigma_arcsec) - 80usize];
3658    ["Offset of field: EmpyreanPlanCandidate::post_cross_track_sigma_arcsec"]
3659        [::std::mem::offset_of!(EmpyreanPlanCandidate, post_cross_track_sigma_arcsec) - 88usize];
3660    ["Offset of field: EmpyreanPlanCandidate::cumulative"]
3661        [::std::mem::offset_of!(EmpyreanPlanCandidate, cumulative) - 96usize];
3662    ["Offset of field: EmpyreanPlanCandidate::active_width"]
3663        [::std::mem::offset_of!(EmpyreanPlanCandidate, active_width) - 136usize];
3664    ["Offset of field: EmpyreanPlanCandidate::radar_snr"]
3665        [::std::mem::offset_of!(EmpyreanPlanCandidate, radar_snr) - 144usize];
3666    ["Offset of field: EmpyreanPlanCandidate::radar_range_km"]
3667        [::std::mem::offset_of!(EmpyreanPlanCandidate, radar_range_km) - 152usize];
3668    ["Offset of field: EmpyreanPlanCandidate::radar_provenance"]
3669        [::std::mem::offset_of!(EmpyreanPlanCandidate, radar_provenance) - 160usize];
3670    ["Offset of field: EmpyreanPlanCandidate::num_radar_provenance"]
3671        [::std::mem::offset_of!(EmpyreanPlanCandidate, num_radar_provenance) - 168usize];
3672    ["Offset of field: EmpyreanPlanCandidate::radar_mode"]
3673        [::std::mem::offset_of!(EmpyreanPlanCandidate, radar_mode) - 176usize];
3674};
3675impl Default for EmpyreanPlanCandidate {
3676    fn default() -> Self {
3677        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
3678        unsafe {
3679            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
3680            s.assume_init()
3681        }
3682    }
3683}
3684#[doc = " Result of a plan evaluation. The caller allocates the struct; the\n `orbit_id` string and the `candidates` array (with their `obs_code`\n strings) are heap-allocated here and must be released with\n [`empyrean_plan_result_free`]."]
3685#[repr(C)]
3686#[derive(Debug, Copy, Clone)]
3687pub struct EmpyreanPlanResult {
3688    #[doc = " Orbit identifier (owned)."]
3689    pub orbit_id: *mut ::std::os::raw::c_char,
3690    #[doc = " Prior (pre-observation) covariance metrics."]
3691    pub prior: EmpyreanCovarianceMetrics,
3692    #[doc = " Posterior (all candidates folded) covariance metrics."]
3693    pub posterior: EmpyreanCovarianceMetrics,
3694    #[doc = " Per-candidate analysis array (owned)."]
3695    pub candidates: *mut EmpyreanPlanCandidate,
3696    #[doc = " Number of entries in `candidates`."]
3697    pub num_candidates: usize,
3698    #[doc = " Active solve-for width (6 = state-only)."]
3699    pub active_width: usize,
3700    #[doc = " Predicted optical ephemeris, one point per optical candidate in\n chronological order; an optical candidate's `index` field gives\n its row in this array (radar candidates carry no sky-plane\n prediction). Owned; freed by `empyrean_plan_result_free`. Null\n with count 0 for a radar-only plan."]
3701    pub ephemeris: *mut EmpyreanPlanEphemerisPoint,
3702    #[doc = " Number of entries in `ephemeris` (0 when null)."]
3703    pub num_ephemeris: usize,
3704}
3705#[allow(clippy::unnecessary_operation, clippy::identity_op)]
3706const _: () = {
3707    ["Size of EmpyreanPlanResult"][::std::mem::size_of::<EmpyreanPlanResult>() - 128usize];
3708    ["Alignment of EmpyreanPlanResult"][::std::mem::align_of::<EmpyreanPlanResult>() - 8usize];
3709    ["Offset of field: EmpyreanPlanResult::orbit_id"]
3710        [::std::mem::offset_of!(EmpyreanPlanResult, orbit_id) - 0usize];
3711    ["Offset of field: EmpyreanPlanResult::prior"]
3712        [::std::mem::offset_of!(EmpyreanPlanResult, prior) - 8usize];
3713    ["Offset of field: EmpyreanPlanResult::posterior"]
3714        [::std::mem::offset_of!(EmpyreanPlanResult, posterior) - 48usize];
3715    ["Offset of field: EmpyreanPlanResult::candidates"]
3716        [::std::mem::offset_of!(EmpyreanPlanResult, candidates) - 88usize];
3717    ["Offset of field: EmpyreanPlanResult::num_candidates"]
3718        [::std::mem::offset_of!(EmpyreanPlanResult, num_candidates) - 96usize];
3719    ["Offset of field: EmpyreanPlanResult::active_width"]
3720        [::std::mem::offset_of!(EmpyreanPlanResult, active_width) - 104usize];
3721    ["Offset of field: EmpyreanPlanResult::ephemeris"]
3722        [::std::mem::offset_of!(EmpyreanPlanResult, ephemeris) - 112usize];
3723    ["Offset of field: EmpyreanPlanResult::num_ephemeris"]
3724        [::std::mem::offset_of!(EmpyreanPlanResult, num_ephemeris) - 120usize];
3725};
3726impl Default for EmpyreanPlanResult {
3727    fn default() -> Self {
3728        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
3729        unsafe {
3730            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
3731            s.assume_init()
3732        }
3733    }
3734}
3735#[doc = " Flattened, owned form of `empyrean_core::propagation::TaggedCovariance`\n (villeneuve's provenance-tagged covariance). Self-describing: the 6×6\n matrix together with the co-located nominal state, how the covariance\n was derived, its definiteness, its basis, the solved-for parameters,\n and the functional it describes — so a consumer can never read a\n second-order CA ellipsoid as a linear one.\n\n NOTE on the `_cartesian` accessor's reachable range: that accessor\n classifies but never repairs (`quality` ∈ {POSITIVE_DEFINITE,\n INDEFINITE}), is always state-only (`solved_width == 6`,\n `target_functional == CARTESIAN_STATE`, `has_mean_shift_input == 0`),\n and resolves Monte-Carlo epochs to an error rather than a row. The\n constant fields are carried for the future element-space / off-grid /\n CA-window accessors that *do* vary them."]
3736#[repr(C)]
3737#[derive(Debug, Default, Copy, Clone)]
3738pub struct EmpyreanTaggedCovariance {
3739    #[doc = " Epoch of this covariance (TDB)."]
3740    pub epoch_mjd_tdb: f64,
3741    #[doc = " Propagated nominal state [x, y, z, vx, vy, vz] (AU, AU/day),\n co-located engine-side. The CORRECTED mean is\n `state + (has_mean_shift_prop ? mean_shift_prop : 0)\n        + (has_mean_shift_input ? mean_shift_input : 0)`."]
3742    pub state: [f64; 6usize],
3743    #[doc = " The 6×6 covariance (AU², AU²/day, AU²/day² blocks)."]
3744    pub matrix: [[f64; 6usize]; 6usize],
3745    #[doc = " `EMPYREAN_COVARIANCE_KIND_*`."]
3746    pub kind: u8,
3747    #[doc = " RNG seed — valid iff `has_mc_seed == 1` (kind == MONTE_CARLO)."]
3748    pub mc_seed: u64,
3749    #[doc = " Disambiguates a real `mc_seed == 0` from \"no seed\". 0 on the\n `_cartesian` accessor (MC resolves to an error there)."]
3750    pub has_mc_seed: u8,
3751    #[doc = " Second-order propagation mean shift δμ_prop (zero at t₀).\n Zero-filled when `has_mean_shift_prop == 0`."]
3752    pub mean_shift_prop: [f64; 6usize],
3753    pub has_mean_shift_prop: u8,
3754    #[doc = " OD-estimator mean shift δμ₀ (nonzero at t₀). Zero-filled when\n `has_mean_shift_input == 0` (always 0 on the `_cartesian` accessor)."]
3755    pub mean_shift_input: [f64; 6usize],
3756    pub has_mean_shift_input: u8,
3757    #[doc = " `EMPYREAN_COVARIANCE_QUALITY_*`."]
3758    pub quality: u8,
3759    #[doc = " `min_eig` for INDEFINITE / REPAIRED; `f64::NAN` for\n POSITIVE_DEFINITE. **Read-only provenance** — `isnan`-guard before\n any arithmetic; never feed to a clamp."]
3760    pub quality_min_eig: f64,
3761    #[doc = " `EMPYREAN_REPRESENTATION_*` (always CARTESIAN=0 on this accessor)."]
3762    pub representation: i32,
3763    #[doc = " Frame, same encoding as `EmpyreanPropagatedState.frame`."]
3764    pub frame: i32,
3765    #[doc = " Origin NAIF id, same encoding as `EmpyreanPropagatedState.origin`."]
3766    pub origin: i32,
3767    #[doc = " [A1, A2, A3] non-grav solved flags (0/1). The returned 6×6 is the\n MARGINALIZED state block of a possibly-wider fit."]
3768    pub non_grav: [u8; 3usize],
3769    #[doc = " Thrust Δv segments solved for."]
3770    pub thrust_segments: u32,
3771    #[doc = " `TaggedCovariance::solved_width()` (6 / 9 / 12 / …) — the scalar\n IP consumers key on (6 on this accessor)."]
3772    pub solved_width: u32,
3773    #[doc = " `EMPYREAN_TARGET_FUNCTIONAL_*` (always CARTESIAN_STATE on this accessor)."]
3774    pub target_functional: u8,
3775}
3776#[allow(clippy::unnecessary_operation, clippy::identity_op)]
3777const _: () = {
3778    ["Size of EmpyreanTaggedCovariance"]
3779        [::std::mem::size_of::<EmpyreanTaggedCovariance>() - 520usize];
3780    ["Alignment of EmpyreanTaggedCovariance"]
3781        [::std::mem::align_of::<EmpyreanTaggedCovariance>() - 8usize];
3782    ["Offset of field: EmpyreanTaggedCovariance::epoch_mjd_tdb"]
3783        [::std::mem::offset_of!(EmpyreanTaggedCovariance, epoch_mjd_tdb) - 0usize];
3784    ["Offset of field: EmpyreanTaggedCovariance::state"]
3785        [::std::mem::offset_of!(EmpyreanTaggedCovariance, state) - 8usize];
3786    ["Offset of field: EmpyreanTaggedCovariance::matrix"]
3787        [::std::mem::offset_of!(EmpyreanTaggedCovariance, matrix) - 56usize];
3788    ["Offset of field: EmpyreanTaggedCovariance::kind"]
3789        [::std::mem::offset_of!(EmpyreanTaggedCovariance, kind) - 344usize];
3790    ["Offset of field: EmpyreanTaggedCovariance::mc_seed"]
3791        [::std::mem::offset_of!(EmpyreanTaggedCovariance, mc_seed) - 352usize];
3792    ["Offset of field: EmpyreanTaggedCovariance::has_mc_seed"]
3793        [::std::mem::offset_of!(EmpyreanTaggedCovariance, has_mc_seed) - 360usize];
3794    ["Offset of field: EmpyreanTaggedCovariance::mean_shift_prop"]
3795        [::std::mem::offset_of!(EmpyreanTaggedCovariance, mean_shift_prop) - 368usize];
3796    ["Offset of field: EmpyreanTaggedCovariance::has_mean_shift_prop"]
3797        [::std::mem::offset_of!(EmpyreanTaggedCovariance, has_mean_shift_prop) - 416usize];
3798    ["Offset of field: EmpyreanTaggedCovariance::mean_shift_input"]
3799        [::std::mem::offset_of!(EmpyreanTaggedCovariance, mean_shift_input) - 424usize];
3800    ["Offset of field: EmpyreanTaggedCovariance::has_mean_shift_input"]
3801        [::std::mem::offset_of!(EmpyreanTaggedCovariance, has_mean_shift_input) - 472usize];
3802    ["Offset of field: EmpyreanTaggedCovariance::quality"]
3803        [::std::mem::offset_of!(EmpyreanTaggedCovariance, quality) - 473usize];
3804    ["Offset of field: EmpyreanTaggedCovariance::quality_min_eig"]
3805        [::std::mem::offset_of!(EmpyreanTaggedCovariance, quality_min_eig) - 480usize];
3806    ["Offset of field: EmpyreanTaggedCovariance::representation"]
3807        [::std::mem::offset_of!(EmpyreanTaggedCovariance, representation) - 488usize];
3808    ["Offset of field: EmpyreanTaggedCovariance::frame"]
3809        [::std::mem::offset_of!(EmpyreanTaggedCovariance, frame) - 492usize];
3810    ["Offset of field: EmpyreanTaggedCovariance::origin"]
3811        [::std::mem::offset_of!(EmpyreanTaggedCovariance, origin) - 496usize];
3812    ["Offset of field: EmpyreanTaggedCovariance::non_grav"]
3813        [::std::mem::offset_of!(EmpyreanTaggedCovariance, non_grav) - 500usize];
3814    ["Offset of field: EmpyreanTaggedCovariance::thrust_segments"]
3815        [::std::mem::offset_of!(EmpyreanTaggedCovariance, thrust_segments) - 504usize];
3816    ["Offset of field: EmpyreanTaggedCovariance::solved_width"]
3817        [::std::mem::offset_of!(EmpyreanTaggedCovariance, solved_width) - 508usize];
3818    ["Offset of field: EmpyreanTaggedCovariance::target_functional"]
3819        [::std::mem::offset_of!(EmpyreanTaggedCovariance, target_functional) - 512usize];
3820};
3821#[doc = " Owned series of [`EmpyreanTaggedCovariance`], one entry per output\n epoch. Free with [`empyrean_tagged_covariance_series_free`]."]
3822#[repr(C)]
3823#[derive(Debug, Copy, Clone)]
3824pub struct EmpyreanTaggedCovarianceSeries {
3825    pub entries: *mut EmpyreanTaggedCovariance,
3826    pub num_entries: usize,
3827}
3828#[allow(clippy::unnecessary_operation, clippy::identity_op)]
3829const _: () = {
3830    ["Size of EmpyreanTaggedCovarianceSeries"]
3831        [::std::mem::size_of::<EmpyreanTaggedCovarianceSeries>() - 16usize];
3832    ["Alignment of EmpyreanTaggedCovarianceSeries"]
3833        [::std::mem::align_of::<EmpyreanTaggedCovarianceSeries>() - 8usize];
3834    ["Offset of field: EmpyreanTaggedCovarianceSeries::entries"]
3835        [::std::mem::offset_of!(EmpyreanTaggedCovarianceSeries, entries) - 0usize];
3836    ["Offset of field: EmpyreanTaggedCovarianceSeries::num_entries"]
3837        [::std::mem::offset_of!(EmpyreanTaggedCovarianceSeries, num_entries) - 8usize];
3838};
3839impl Default for EmpyreanTaggedCovarianceSeries {
3840    fn default() -> Self {
3841        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
3842        unsafe {
3843            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
3844            s.assume_init()
3845        }
3846    }
3847}
3848#[doc = " Opaque handle to an `empyrean_core::determination::Session`.\n\n Owns observations, the mask state, and the fit history. Construct\n with [`empyrean_session_new`]; release with\n [`empyrean_session_free`]. The handle is **not** thread-safe — do\n not share between threads without external synchronization."]
3849pub type EmpyreanSession = Session;
3850#[doc = " Pairwise diagnostic returned by [`empyrean_session_diff`]."]
3851#[repr(C)]
3852#[derive(Debug, Default, Copy, Clone)]
3853pub struct EmpyreanSessionDiff {
3854    #[doc = " Δ reduced χ² (positive ⇒ current fit is worse than prior)."]
3855    pub reduced_chi2_delta: f64,
3856    #[doc = " Δ iteration count."]
3857    pub iterations_delta: i64,
3858    #[doc = " Δ number of observations used (negative ⇒ observations were\n masked between prior and current)."]
3859    pub n_observations_delta: i64,
3860    #[doc = " Final update-norm convergence metric on the current fit."]
3861    pub update_norm_current: f64,
3862    #[doc = " Final update-norm convergence metric on the prior fit."]
3863    pub update_norm_prior: f64,
3864}
3865#[allow(clippy::unnecessary_operation, clippy::identity_op)]
3866const _: () = {
3867    ["Size of EmpyreanSessionDiff"][::std::mem::size_of::<EmpyreanSessionDiff>() - 40usize];
3868    ["Alignment of EmpyreanSessionDiff"][::std::mem::align_of::<EmpyreanSessionDiff>() - 8usize];
3869    ["Offset of field: EmpyreanSessionDiff::reduced_chi2_delta"]
3870        [::std::mem::offset_of!(EmpyreanSessionDiff, reduced_chi2_delta) - 0usize];
3871    ["Offset of field: EmpyreanSessionDiff::iterations_delta"]
3872        [::std::mem::offset_of!(EmpyreanSessionDiff, iterations_delta) - 8usize];
3873    ["Offset of field: EmpyreanSessionDiff::n_observations_delta"]
3874        [::std::mem::offset_of!(EmpyreanSessionDiff, n_observations_delta) - 16usize];
3875    ["Offset of field: EmpyreanSessionDiff::update_norm_current"]
3876        [::std::mem::offset_of!(EmpyreanSessionDiff, update_norm_current) - 24usize];
3877    ["Offset of field: EmpyreanSessionDiff::update_norm_prior"]
3878        [::std::mem::offset_of!(EmpyreanSessionDiff, update_norm_prior) - 32usize];
3879};
3880#[doc = " A single body state for the C API."]
3881#[repr(C)]
3882#[derive(Debug, Default, Copy, Clone)]
3883pub struct EmpyreanState {
3884    #[doc = " Epoch as MJD TDB."]
3885    pub epoch_mjd_tdb: f64,
3886    #[doc = " Position (AU)."]
3887    pub x: f64,
3888    pub y: f64,
3889    pub z: f64,
3890    #[doc = " Velocity (AU/day)."]
3891    pub vx: f64,
3892    pub vy: f64,
3893    pub vz: f64,
3894    #[doc = " Reference frame (EMPYREAN_FRAME_*)."]
3895    pub frame: i32,
3896    #[doc = " Center body NAIF ID."]
3897    pub origin: i32,
3898}
3899#[allow(clippy::unnecessary_operation, clippy::identity_op)]
3900const _: () = {
3901    ["Size of EmpyreanState"][::std::mem::size_of::<EmpyreanState>() - 64usize];
3902    ["Alignment of EmpyreanState"][::std::mem::align_of::<EmpyreanState>() - 8usize];
3903    ["Offset of field: EmpyreanState::epoch_mjd_tdb"]
3904        [::std::mem::offset_of!(EmpyreanState, epoch_mjd_tdb) - 0usize];
3905    ["Offset of field: EmpyreanState::x"][::std::mem::offset_of!(EmpyreanState, x) - 8usize];
3906    ["Offset of field: EmpyreanState::y"][::std::mem::offset_of!(EmpyreanState, y) - 16usize];
3907    ["Offset of field: EmpyreanState::z"][::std::mem::offset_of!(EmpyreanState, z) - 24usize];
3908    ["Offset of field: EmpyreanState::vx"][::std::mem::offset_of!(EmpyreanState, vx) - 32usize];
3909    ["Offset of field: EmpyreanState::vy"][::std::mem::offset_of!(EmpyreanState, vy) - 40usize];
3910    ["Offset of field: EmpyreanState::vz"][::std::mem::offset_of!(EmpyreanState, vz) - 48usize];
3911    ["Offset of field: EmpyreanState::frame"]
3912        [::std::mem::offset_of!(EmpyreanState, frame) - 56usize];
3913    ["Offset of field: EmpyreanState::origin"]
3914        [::std::mem::offset_of!(EmpyreanState, origin) - 60usize];
3915};
3916#[doc = " Result containing an array of body states."]
3917#[repr(C)]
3918#[derive(Debug, Copy, Clone)]
3919pub struct EmpyreanStateResult {
3920    pub states: *mut EmpyreanState,
3921    pub num_states: usize,
3922}
3923#[allow(clippy::unnecessary_operation, clippy::identity_op)]
3924const _: () = {
3925    ["Size of EmpyreanStateResult"][::std::mem::size_of::<EmpyreanStateResult>() - 16usize];
3926    ["Alignment of EmpyreanStateResult"][::std::mem::align_of::<EmpyreanStateResult>() - 8usize];
3927    ["Offset of field: EmpyreanStateResult::states"]
3928        [::std::mem::offset_of!(EmpyreanStateResult, states) - 0usize];
3929    ["Offset of field: EmpyreanStateResult::num_states"]
3930        [::std::mem::offset_of!(EmpyreanStateResult, num_states) - 8usize];
3931};
3932impl Default for EmpyreanStateResult {
3933    fn default() -> Self {
3934        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
3935        unsafe {
3936            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
3937            s.assume_init()
3938        }
3939    }
3940}
3941pub struct EmpyreanLib {
3942    __library: ::libloading::Library,
3943    pub empyrean_last_error: unsafe extern "C" fn() -> *const ::std::os::raw::c_char,
3944    pub empyrean_context_new_minimal: unsafe extern "C" fn(
3945        de440_path: *const ::std::os::raw::c_char,
3946        gm_path: *const ::std::os::raw::c_char,
3947    ) -> *mut EmpyreanContext,
3948    pub empyrean_context_with_spk: unsafe extern "C" fn(
3949        ctx: *mut EmpyreanContext,
3950        spk_path: *const ::std::os::raw::c_char,
3951    ) -> i32,
3952    pub empyrean_context_from_data_dir:
3953        unsafe extern "C" fn(data_dir: *const ::std::os::raw::c_char) -> *mut EmpyreanContext,
3954    pub empyrean_context_free: unsafe extern "C" fn(ctx: *mut EmpyreanContext),
3955    pub empyrean_default_data_dir: unsafe extern "C" fn() -> *mut ::std::os::raw::c_char,
3956    pub empyrean_string_free: unsafe extern "C" fn(s: *mut ::std::os::raw::c_char),
3957    pub empyrean_version_string: unsafe extern "C" fn() -> *mut ::std::os::raw::c_char,
3958    pub empyrean_versions: unsafe extern "C" fn(out: *mut EmpyreanVersions) -> i32,
3959    pub empyrean_versions_free: unsafe extern "C" fn(versions: *mut EmpyreanVersions),
3960    pub empyrean_builtsystem_new: unsafe extern "C" fn(
3961        ctx: *const EmpyreanContext,
3962        force_model: i32,
3963        frame: i32,
3964        encounter_timescale_divisor: f64,
3965        out: *mut *mut EmpyreanBuiltSystem,
3966    ) -> i32,
3967    pub empyrean_builtsystem_free: unsafe extern "C" fn(handle: *mut EmpyreanBuiltSystem),
3968    pub empyrean_builtsystem_propagate: unsafe extern "C" fn(
3969        handle: *const EmpyreanBuiltSystem,
3970        ctx: *const EmpyreanContext,
3971        orbits_ptr: *const EmpyreanOrbit,
3972        num_orbits: usize,
3973        times_ptr: *const f64,
3974        num_times: usize,
3975        config: *const EmpyreanPropagationConfig,
3976        result_out: *mut EmpyreanPropagationResult,
3977    ) -> i32,
3978    pub empyrean_builtsystem_generate_ephemeris: unsafe extern "C" fn(
3979        handle: *const EmpyreanBuiltSystem,
3980        ctx: *const EmpyreanContext,
3981        orbits_ptr: *const EmpyreanOrbit,
3982        num_orbits: usize,
3983        observers_ptr: *const EmpyreanObserver,
3984        num_observers: usize,
3985        config: *const EmpyreanEphemerisConfig,
3986        result_out: *mut EmpyreanEphemerisResult,
3987    ) -> i32,
3988    pub empyrean_builtsystem_describe: unsafe extern "C" fn(
3989        handle: *const EmpyreanBuiltSystem,
3990        out: *mut EmpyreanSystemDescription,
3991    ) -> i32,
3992    pub empyrean_builtsystem_description_free:
3993        unsafe extern "C" fn(desc: *mut EmpyreanSystemDescription),
3994    pub empyrean_generate_ephemeris: unsafe extern "C" fn(
3995        ctx: *const EmpyreanContext,
3996        orbits_ptr: *const EmpyreanOrbit,
3997        num_orbits: usize,
3998        observers_ptr: *const EmpyreanObserver,
3999        num_observers: usize,
4000        config: *const EmpyreanEphemerisConfig,
4001        result_out: *mut EmpyreanEphemerisResult,
4002    ) -> i32,
4003    pub empyrean_ephemeris_result_free: unsafe extern "C" fn(result: *mut EmpyreanEphemerisResult),
4004    pub empyrean_compute_impact_probabilities: unsafe extern "C" fn(
4005        ctx: *const EmpyreanContext,
4006        orbits_ptr: *const EmpyreanOrbit,
4007        num_orbits: usize,
4008        end_mjd_tdb: f64,
4009        methods_ptr: *const EmpyreanUncertaintyMethod,
4010        num_methods: usize,
4011        body_filter_naif: *const i32,
4012        num_body_filter: usize,
4013        result_out: *mut EmpyreanImpactProbabilitiesResult,
4014    ) -> i32,
4015    pub empyrean_compute_impact_probabilities_result_free:
4016        unsafe extern "C" fn(result: *mut EmpyreanImpactProbabilitiesResult),
4017    pub empyrean_compute_b_planes: unsafe extern "C" fn(
4018        ctx: *const EmpyreanContext,
4019        orbits_ptr: *const EmpyreanOrbit,
4020        num_orbits: usize,
4021        end_mjd_tdb: f64,
4022        methods_ptr: *const EmpyreanUncertaintyMethod,
4023        num_methods: usize,
4024        body_filter_naif: *const i32,
4025        num_body_filter: usize,
4026        result_out: *mut EmpyreanBPlanesResult,
4027    ) -> i32,
4028    pub empyrean_compute_b_planes_result_free:
4029        unsafe extern "C" fn(result: *mut EmpyreanBPlanesResult),
4030    pub empyrean_orbits_batch_free: unsafe extern "C" fn(batch: *mut EmpyreanOrbitBatch),
4031    pub empyrean_orbits_read_parquet: unsafe extern "C" fn(
4032        path: *const ::std::os::raw::c_char,
4033        out: *mut EmpyreanOrbitBatch,
4034    ) -> i32,
4035    pub empyrean_orbits_write_parquet: unsafe extern "C" fn(
4036        path: *const ::std::os::raw::c_char,
4037        batch: *const EmpyreanOrbitBatch,
4038    ) -> i32,
4039    pub empyrean_orbits_read_json: unsafe extern "C" fn(
4040        path: *const ::std::os::raw::c_char,
4041        out: *mut EmpyreanOrbitBatch,
4042    ) -> i32,
4043    pub empyrean_orbits_write_json: unsafe extern "C" fn(
4044        path: *const ::std::os::raw::c_char,
4045        batch: *const EmpyreanOrbitBatch,
4046    ) -> i32,
4047    pub empyrean_orbits_read_csv: unsafe extern "C" fn(
4048        path: *const ::std::os::raw::c_char,
4049        out: *mut EmpyreanOrbitBatch,
4050    ) -> i32,
4051    pub empyrean_orbits_write_csv: unsafe extern "C" fn(
4052        path: *const ::std::os::raw::c_char,
4053        batch: *const EmpyreanOrbitBatch,
4054    ) -> i32,
4055    pub empyrean_ephemeris_write_parquet: unsafe extern "C" fn(
4056        path: *const ::std::os::raw::c_char,
4057        entries_ptr: *const EmpyreanEphemerisEntry,
4058        num_entries: usize,
4059    ) -> i32,
4060    pub empyrean_ephemeris_write_json: unsafe extern "C" fn(
4061        path: *const ::std::os::raw::c_char,
4062        entries_ptr: *const EmpyreanEphemerisEntry,
4063        num_entries: usize,
4064    ) -> i32,
4065    pub empyrean_ephemeris_write_csv: unsafe extern "C" fn(
4066        path: *const ::std::os::raw::c_char,
4067        entries_ptr: *const EmpyreanEphemerisEntry,
4068        num_entries: usize,
4069    ) -> i32,
4070    pub empyrean_events_write_parquet: unsafe extern "C" fn(
4071        path: *const ::std::os::raw::c_char,
4072        events_ptr: *const EmpyreanEvent,
4073        num_events: usize,
4074    ) -> i32,
4075    pub empyrean_events_write_json: unsafe extern "C" fn(
4076        path: *const ::std::os::raw::c_char,
4077        events_ptr: *const EmpyreanEvent,
4078        num_events: usize,
4079    ) -> i32,
4080    pub empyrean_events_write_csv: unsafe extern "C" fn(
4081        path: *const ::std::os::raw::c_char,
4082        events_ptr: *const EmpyreanEvent,
4083        num_events: usize,
4084    ) -> i32,
4085    pub empyrean_residuals_write_parquet: unsafe extern "C" fn(
4086        path: *const ::std::os::raw::c_char,
4087        obs_ptr: *const EmpyreanObservationResult,
4088        num_obs: usize,
4089    ) -> i32,
4090    pub empyrean_residuals_write_json: unsafe extern "C" fn(
4091        path: *const ::std::os::raw::c_char,
4092        obs_ptr: *const EmpyreanObservationResult,
4093        num_obs: usize,
4094    ) -> i32,
4095    pub empyrean_residuals_write_csv: unsafe extern "C" fn(
4096        path: *const ::std::os::raw::c_char,
4097        obs_ptr: *const EmpyreanObservationResult,
4098        num_obs: usize,
4099    ) -> i32,
4100    pub empyrean_eigenvector_max_6x6: unsafe extern "C" fn(
4101        matrix: *const [[f64; 6usize]; 6usize],
4102        eigenvalue_out: *mut f64,
4103        eigenvector_out: *mut [f64; 6usize],
4104    ) -> i32,
4105    pub empyrean_split_gaussian: unsafe extern "C" fn(
4106        mean: *const [f64; 6usize],
4107        covariance: *const [[f64; 6usize]; 6usize],
4108        k: usize,
4109        weights_out: *mut f64,
4110        means_out: *mut [f64; 6usize],
4111        covariances_out: *mut [[f64; 6usize]; 6usize],
4112    ) -> i32,
4113    pub empyrean_get_observers: unsafe extern "C" fn(
4114        ctx: *const EmpyreanContext,
4115        obs_codes: *const *const ::std::os::raw::c_char,
4116        num_codes: usize,
4117        epochs_mjd_tdb: *const f64,
4118        num_epochs: usize,
4119        result_out: *mut EmpyreanObserverResult,
4120    ) -> i32,
4121    pub empyrean_observer_result_free: unsafe extern "C" fn(result: *mut EmpyreanObserverResult),
4122    pub empyrean_abi_version: unsafe extern "C" fn() -> u32,
4123    pub empyrean_read_ades: unsafe extern "C" fn(
4124        content: *const ::std::os::raw::c_char,
4125        observations_out: *mut *mut EmpyreanObservation,
4126        num_observations_out: *mut usize,
4127        radar_out: *mut *mut EmpyreanRadarObservation,
4128        num_radar_out: *mut usize,
4129    ) -> i32,
4130    pub empyrean_observations_from_array: unsafe extern "C" fn(
4131        input: *const EmpyreanObservation,
4132        num: usize,
4133        out_ptr: *mut *mut EmpyreanObservation,
4134        out_num: *mut usize,
4135    ) -> i32,
4136    pub empyrean_observations_free:
4137        unsafe extern "C" fn(observations: *mut EmpyreanObservation, num: usize),
4138    pub empyrean_radar_observations_from_array: unsafe extern "C" fn(
4139        input: *const EmpyreanRadarObservation,
4140        num: usize,
4141        out_ptr: *mut *mut EmpyreanRadarObservation,
4142        out_num: *mut usize,
4143    ) -> i32,
4144    pub empyrean_radar_observations_free:
4145        unsafe extern "C" fn(observations: *mut EmpyreanRadarObservation, num: usize),
4146    pub empyrean_determine: unsafe extern "C" fn(
4147        ctx: *const EmpyreanContext,
4148        observations: *const EmpyreanObservation,
4149        num_observations: usize,
4150        radar: *const EmpyreanRadarObservation,
4151        num_radar: usize,
4152        initial_orbits: *const EmpyreanOrbit,
4153        num_initial_orbits: usize,
4154        config: *const EmpyreanODConfig,
4155        result_out: *mut EmpyreanODResult,
4156    ) -> i32,
4157    pub empyrean_od_result_free: unsafe extern "C" fn(result: *mut EmpyreanODResult),
4158    pub empyrean_evaluate: unsafe extern "C" fn(
4159        ctx: *const EmpyreanContext,
4160        orbit: *const EmpyreanOrbit,
4161        observations: *const EmpyreanObservation,
4162        num_observations: usize,
4163        config: *const EmpyreanODConfig,
4164        result_out: *mut EmpyreanEvaluateResult,
4165    ) -> i32,
4166    pub empyrean_evaluate_result_free: unsafe extern "C" fn(result: *mut EmpyreanEvaluateResult),
4167    pub empyrean_refine: unsafe extern "C" fn(
4168        ctx: *const EmpyreanContext,
4169        orbit: *const EmpyreanOrbit,
4170        observations: *const EmpyreanObservation,
4171        num_observations: usize,
4172        config: *const EmpyreanODConfig,
4173        result_out: *mut EmpyreanODResult,
4174    ) -> i32,
4175    pub empyrean_evaluate_plan: unsafe extern "C" fn(
4176        ctx: *const EmpyreanContext,
4177        orbit: *const EmpyreanOrbit,
4178        orbit_id: *const ::std::os::raw::c_char,
4179        planned: *const EmpyreanPlannedObservation,
4180        num_planned: usize,
4181        config: *const EmpyreanPlanningConfig,
4182        result_out: *mut EmpyreanPlanResult,
4183    ) -> i32,
4184    pub empyrean_plan_result_free: unsafe extern "C" fn(result: *mut EmpyreanPlanResult),
4185    pub empyrean_propagate: unsafe extern "C" fn(
4186        ctx: *const EmpyreanContext,
4187        orbits_ptr: *const EmpyreanOrbit,
4188        num_orbits: usize,
4189        times_ptr: *const f64,
4190        num_times: usize,
4191        config: *const EmpyreanPropagationConfig,
4192        result_out: *mut EmpyreanPropagationResult,
4193    ) -> i32,
4194    pub empyrean_propagation_result_free:
4195        unsafe extern "C" fn(result: *mut EmpyreanPropagationResult),
4196    pub empyrean_propagation_covariance_series_cartesian: unsafe extern "C" fn(
4197        result: *const EmpyreanPropagationResult,
4198        orbit_index: usize,
4199        out_series: *mut *mut EmpyreanTaggedCovarianceSeries,
4200    ) -> i32,
4201    pub empyrean_propagation_covariance_at_cartesian: unsafe extern "C" fn(
4202        result: *const EmpyreanPropagationResult,
4203        orbit_index: usize,
4204        epoch_index: usize,
4205        out: *mut EmpyreanTaggedCovariance,
4206    ) -> i32,
4207    pub empyrean_tagged_covariance_series_free:
4208        unsafe extern "C" fn(series: *mut EmpyreanTaggedCovarianceSeries),
4209    pub empyrean_query_sbdb: unsafe extern "C" fn(
4210        object_ids: *const *const ::std::os::raw::c_char,
4211        num_object_ids: usize,
4212        cache_dir: *const ::std::os::raw::c_char,
4213        out: *mut EmpyreanOrbitBatch,
4214    ) -> i32,
4215    pub empyrean_query_horizons: unsafe extern "C" fn(
4216        object_ids: *const *const ::std::os::raw::c_char,
4217        num_object_ids: usize,
4218        obs_code: *const ::std::os::raw::c_char,
4219        times_mjd_tdb: *const f64,
4220        num_times: usize,
4221        cache_dir: *const ::std::os::raw::c_char,
4222        out: *mut EmpyreanEphemerisResult,
4223    ) -> i32,
4224    pub empyrean_query_horizons_vectors: unsafe extern "C" fn(
4225        command: *const ::std::os::raw::c_char,
4226        epoch_mjd_tdb: f64,
4227        cache_dir: *const ::std::os::raw::c_char,
4228        out_pos: *mut f64,
4229        out_vel: *mut f64,
4230    ) -> i32,
4231    pub empyrean_query_observations: unsafe extern "C" fn(
4232        designations: *const *const ::std::os::raw::c_char,
4233        num_designations: usize,
4234        cache_dir: *const ::std::os::raw::c_char,
4235        out_ptr: *mut *mut EmpyreanObservation,
4236        out_num: *mut usize,
4237    ) -> i32,
4238    pub empyrean_query_radar: unsafe extern "C" fn(
4239        designations: *const *const ::std::os::raw::c_char,
4240        num_designations: usize,
4241        cache_dir: *const ::std::os::raw::c_char,
4242        out_ptr: *mut *mut EmpyreanRadarObservation,
4243        out_num: *mut usize,
4244    ) -> i32,
4245    pub empyrean_session_new: unsafe extern "C" fn(
4246        observations: *const EmpyreanObservation,
4247        num_observations: usize,
4248        config: *const EmpyreanODConfig,
4249    ) -> *mut EmpyreanSession,
4250    pub empyrean_session_free: unsafe extern "C" fn(session: *mut EmpyreanSession),
4251    pub empyrean_session_n_observations:
4252        unsafe extern "C" fn(session: *const EmpyreanSession) -> usize,
4253    pub empyrean_session_n_masked: unsafe extern "C" fn(session: *const EmpyreanSession) -> usize,
4254    pub empyrean_session_n_active: unsafe extern "C" fn(session: *const EmpyreanSession) -> usize,
4255    pub empyrean_session_mask:
4256        unsafe extern "C" fn(session: *mut EmpyreanSession, idx: usize) -> i32,
4257    pub empyrean_session_unmask:
4258        unsafe extern "C" fn(session: *mut EmpyreanSession, idx: usize) -> i32,
4259    pub empyrean_session_unmask_all: unsafe extern "C" fn(session: *mut EmpyreanSession) -> i32,
4260    pub empyrean_session_is_masked:
4261        unsafe extern "C" fn(session: *const EmpyreanSession, idx: usize) -> u8,
4262    pub empyrean_session_refine: unsafe extern "C" fn(
4263        session: *mut EmpyreanSession,
4264        ctx: *const EmpyreanContext,
4265        result_out: *mut EmpyreanODResult,
4266    ) -> i32,
4267    pub empyrean_session_history_len:
4268        unsafe extern "C" fn(session: *const EmpyreanSession) -> usize,
4269    pub empyrean_session_get_history: unsafe extern "C" fn(
4270        session: *const EmpyreanSession,
4271        idx: usize,
4272        result_out: *mut EmpyreanODResult,
4273    ) -> i32,
4274    pub empyrean_session_diff: unsafe extern "C" fn(
4275        session: *const EmpyreanSession,
4276        prior_idx: usize,
4277        diff_out: *mut EmpyreanSessionDiff,
4278    ) -> i32,
4279    pub empyrean_get_states: unsafe extern "C" fn(
4280        ctx: *const EmpyreanContext,
4281        target_naif_id: i32,
4282        center_naif_id: i32,
4283        epochs_mjd_tdb: *const f64,
4284        num_epochs: usize,
4285        frame: i32,
4286        result_out: *mut EmpyreanStateResult,
4287    ) -> i32,
4288    pub empyrean_state_result_free: unsafe extern "C" fn(result: *mut EmpyreanStateResult),
4289    pub empyrean_iso_to_mjd: unsafe extern "C" fn(
4290        iso: *const ::std::os::raw::c_char,
4291        scale: i32,
4292        out_mjd: *mut f64,
4293    ) -> i32,
4294    pub empyrean_mjd_to_iso: unsafe extern "C" fn(
4295        mjd: f64,
4296        scale: i32,
4297        out_buf: *mut ::std::os::raw::c_char,
4298        buf_len: usize,
4299    ) -> i32,
4300    pub empyrean_transform_coordinates: unsafe extern "C" fn(
4301        ctx: *const EmpyreanContext,
4302        input: *const CoordinateState,
4303        target_representation: i32,
4304        target_frame: i32,
4305        target_origin: i32,
4306        output: *mut CoordinateState,
4307    ) -> i32,
4308}
4309impl EmpyreanLib {
4310    pub unsafe fn new<P>(path: P) -> Result<Self, ::libloading::Error>
4311    where
4312        P: AsRef<::std::ffi::OsStr>,
4313    {
4314        let library = ::libloading::Library::new(path)?;
4315        Self::from_library(library)
4316    }
4317    pub unsafe fn from_library<L>(library: L) -> Result<Self, ::libloading::Error>
4318    where
4319        L: Into<::libloading::Library>,
4320    {
4321        let __library = library.into();
4322        let empyrean_last_error = __library.get(b"empyrean_last_error\0").map(|sym| *sym)?;
4323        let empyrean_context_new_minimal = __library
4324            .get(b"empyrean_context_new_minimal\0")
4325            .map(|sym| *sym)?;
4326        let empyrean_context_with_spk = __library
4327            .get(b"empyrean_context_with_spk\0")
4328            .map(|sym| *sym)?;
4329        let empyrean_context_from_data_dir = __library
4330            .get(b"empyrean_context_from_data_dir\0")
4331            .map(|sym| *sym)?;
4332        let empyrean_context_free = __library.get(b"empyrean_context_free\0").map(|sym| *sym)?;
4333        let empyrean_default_data_dir = __library
4334            .get(b"empyrean_default_data_dir\0")
4335            .map(|sym| *sym)?;
4336        let empyrean_string_free = __library.get(b"empyrean_string_free\0").map(|sym| *sym)?;
4337        let empyrean_version_string = __library
4338            .get(b"empyrean_version_string\0")
4339            .map(|sym| *sym)?;
4340        let empyrean_versions = __library.get(b"empyrean_versions\0").map(|sym| *sym)?;
4341        let empyrean_versions_free = __library.get(b"empyrean_versions_free\0").map(|sym| *sym)?;
4342        let empyrean_builtsystem_new = __library
4343            .get(b"empyrean_builtsystem_new\0")
4344            .map(|sym| *sym)?;
4345        let empyrean_builtsystem_free = __library
4346            .get(b"empyrean_builtsystem_free\0")
4347            .map(|sym| *sym)?;
4348        let empyrean_builtsystem_propagate = __library
4349            .get(b"empyrean_builtsystem_propagate\0")
4350            .map(|sym| *sym)?;
4351        let empyrean_builtsystem_generate_ephemeris = __library
4352            .get(b"empyrean_builtsystem_generate_ephemeris\0")
4353            .map(|sym| *sym)?;
4354        let empyrean_builtsystem_describe = __library
4355            .get(b"empyrean_builtsystem_describe\0")
4356            .map(|sym| *sym)?;
4357        let empyrean_builtsystem_description_free = __library
4358            .get(b"empyrean_builtsystem_description_free\0")
4359            .map(|sym| *sym)?;
4360        let empyrean_generate_ephemeris = __library
4361            .get(b"empyrean_generate_ephemeris\0")
4362            .map(|sym| *sym)?;
4363        let empyrean_ephemeris_result_free = __library
4364            .get(b"empyrean_ephemeris_result_free\0")
4365            .map(|sym| *sym)?;
4366        let empyrean_compute_impact_probabilities = __library
4367            .get(b"empyrean_compute_impact_probabilities\0")
4368            .map(|sym| *sym)?;
4369        let empyrean_compute_impact_probabilities_result_free = __library
4370            .get(b"empyrean_compute_impact_probabilities_result_free\0")
4371            .map(|sym| *sym)?;
4372        let empyrean_compute_b_planes = __library
4373            .get(b"empyrean_compute_b_planes\0")
4374            .map(|sym| *sym)?;
4375        let empyrean_compute_b_planes_result_free = __library
4376            .get(b"empyrean_compute_b_planes_result_free\0")
4377            .map(|sym| *sym)?;
4378        let empyrean_orbits_batch_free = __library
4379            .get(b"empyrean_orbits_batch_free\0")
4380            .map(|sym| *sym)?;
4381        let empyrean_orbits_read_parquet = __library
4382            .get(b"empyrean_orbits_read_parquet\0")
4383            .map(|sym| *sym)?;
4384        let empyrean_orbits_write_parquet = __library
4385            .get(b"empyrean_orbits_write_parquet\0")
4386            .map(|sym| *sym)?;
4387        let empyrean_orbits_read_json = __library
4388            .get(b"empyrean_orbits_read_json\0")
4389            .map(|sym| *sym)?;
4390        let empyrean_orbits_write_json = __library
4391            .get(b"empyrean_orbits_write_json\0")
4392            .map(|sym| *sym)?;
4393        let empyrean_orbits_read_csv = __library
4394            .get(b"empyrean_orbits_read_csv\0")
4395            .map(|sym| *sym)?;
4396        let empyrean_orbits_write_csv = __library
4397            .get(b"empyrean_orbits_write_csv\0")
4398            .map(|sym| *sym)?;
4399        let empyrean_ephemeris_write_parquet = __library
4400            .get(b"empyrean_ephemeris_write_parquet\0")
4401            .map(|sym| *sym)?;
4402        let empyrean_ephemeris_write_json = __library
4403            .get(b"empyrean_ephemeris_write_json\0")
4404            .map(|sym| *sym)?;
4405        let empyrean_ephemeris_write_csv = __library
4406            .get(b"empyrean_ephemeris_write_csv\0")
4407            .map(|sym| *sym)?;
4408        let empyrean_events_write_parquet = __library
4409            .get(b"empyrean_events_write_parquet\0")
4410            .map(|sym| *sym)?;
4411        let empyrean_events_write_json = __library
4412            .get(b"empyrean_events_write_json\0")
4413            .map(|sym| *sym)?;
4414        let empyrean_events_write_csv = __library
4415            .get(b"empyrean_events_write_csv\0")
4416            .map(|sym| *sym)?;
4417        let empyrean_residuals_write_parquet = __library
4418            .get(b"empyrean_residuals_write_parquet\0")
4419            .map(|sym| *sym)?;
4420        let empyrean_residuals_write_json = __library
4421            .get(b"empyrean_residuals_write_json\0")
4422            .map(|sym| *sym)?;
4423        let empyrean_residuals_write_csv = __library
4424            .get(b"empyrean_residuals_write_csv\0")
4425            .map(|sym| *sym)?;
4426        let empyrean_eigenvector_max_6x6 = __library
4427            .get(b"empyrean_eigenvector_max_6x6\0")
4428            .map(|sym| *sym)?;
4429        let empyrean_split_gaussian = __library
4430            .get(b"empyrean_split_gaussian\0")
4431            .map(|sym| *sym)?;
4432        let empyrean_get_observers = __library.get(b"empyrean_get_observers\0").map(|sym| *sym)?;
4433        let empyrean_observer_result_free = __library
4434            .get(b"empyrean_observer_result_free\0")
4435            .map(|sym| *sym)?;
4436        let empyrean_abi_version = __library.get(b"empyrean_abi_version\0").map(|sym| *sym)?;
4437        let empyrean_read_ades = __library.get(b"empyrean_read_ades\0").map(|sym| *sym)?;
4438        let empyrean_observations_from_array = __library
4439            .get(b"empyrean_observations_from_array\0")
4440            .map(|sym| *sym)?;
4441        let empyrean_observations_free = __library
4442            .get(b"empyrean_observations_free\0")
4443            .map(|sym| *sym)?;
4444        let empyrean_radar_observations_from_array = __library
4445            .get(b"empyrean_radar_observations_from_array\0")
4446            .map(|sym| *sym)?;
4447        let empyrean_radar_observations_free = __library
4448            .get(b"empyrean_radar_observations_free\0")
4449            .map(|sym| *sym)?;
4450        let empyrean_determine = __library.get(b"empyrean_determine\0").map(|sym| *sym)?;
4451        let empyrean_od_result_free = __library
4452            .get(b"empyrean_od_result_free\0")
4453            .map(|sym| *sym)?;
4454        let empyrean_evaluate = __library.get(b"empyrean_evaluate\0").map(|sym| *sym)?;
4455        let empyrean_evaluate_result_free = __library
4456            .get(b"empyrean_evaluate_result_free\0")
4457            .map(|sym| *sym)?;
4458        let empyrean_refine = __library.get(b"empyrean_refine\0").map(|sym| *sym)?;
4459        let empyrean_evaluate_plan = __library.get(b"empyrean_evaluate_plan\0").map(|sym| *sym)?;
4460        let empyrean_plan_result_free = __library
4461            .get(b"empyrean_plan_result_free\0")
4462            .map(|sym| *sym)?;
4463        let empyrean_propagate = __library.get(b"empyrean_propagate\0").map(|sym| *sym)?;
4464        let empyrean_propagation_result_free = __library
4465            .get(b"empyrean_propagation_result_free\0")
4466            .map(|sym| *sym)?;
4467        let empyrean_propagation_covariance_series_cartesian = __library
4468            .get(b"empyrean_propagation_covariance_series_cartesian\0")
4469            .map(|sym| *sym)?;
4470        let empyrean_propagation_covariance_at_cartesian = __library
4471            .get(b"empyrean_propagation_covariance_at_cartesian\0")
4472            .map(|sym| *sym)?;
4473        let empyrean_tagged_covariance_series_free = __library
4474            .get(b"empyrean_tagged_covariance_series_free\0")
4475            .map(|sym| *sym)?;
4476        let empyrean_query_sbdb = __library.get(b"empyrean_query_sbdb\0").map(|sym| *sym)?;
4477        let empyrean_query_horizons = __library
4478            .get(b"empyrean_query_horizons\0")
4479            .map(|sym| *sym)?;
4480        let empyrean_query_horizons_vectors = __library
4481            .get(b"empyrean_query_horizons_vectors\0")
4482            .map(|sym| *sym)?;
4483        let empyrean_query_observations = __library
4484            .get(b"empyrean_query_observations\0")
4485            .map(|sym| *sym)?;
4486        let empyrean_query_radar = __library.get(b"empyrean_query_radar\0").map(|sym| *sym)?;
4487        let empyrean_session_new = __library.get(b"empyrean_session_new\0").map(|sym| *sym)?;
4488        let empyrean_session_free = __library.get(b"empyrean_session_free\0").map(|sym| *sym)?;
4489        let empyrean_session_n_observations = __library
4490            .get(b"empyrean_session_n_observations\0")
4491            .map(|sym| *sym)?;
4492        let empyrean_session_n_masked = __library
4493            .get(b"empyrean_session_n_masked\0")
4494            .map(|sym| *sym)?;
4495        let empyrean_session_n_active = __library
4496            .get(b"empyrean_session_n_active\0")
4497            .map(|sym| *sym)?;
4498        let empyrean_session_mask = __library.get(b"empyrean_session_mask\0").map(|sym| *sym)?;
4499        let empyrean_session_unmask = __library
4500            .get(b"empyrean_session_unmask\0")
4501            .map(|sym| *sym)?;
4502        let empyrean_session_unmask_all = __library
4503            .get(b"empyrean_session_unmask_all\0")
4504            .map(|sym| *sym)?;
4505        let empyrean_session_is_masked = __library
4506            .get(b"empyrean_session_is_masked\0")
4507            .map(|sym| *sym)?;
4508        let empyrean_session_refine = __library
4509            .get(b"empyrean_session_refine\0")
4510            .map(|sym| *sym)?;
4511        let empyrean_session_history_len = __library
4512            .get(b"empyrean_session_history_len\0")
4513            .map(|sym| *sym)?;
4514        let empyrean_session_get_history = __library
4515            .get(b"empyrean_session_get_history\0")
4516            .map(|sym| *sym)?;
4517        let empyrean_session_diff = __library.get(b"empyrean_session_diff\0").map(|sym| *sym)?;
4518        let empyrean_get_states = __library.get(b"empyrean_get_states\0").map(|sym| *sym)?;
4519        let empyrean_state_result_free = __library
4520            .get(b"empyrean_state_result_free\0")
4521            .map(|sym| *sym)?;
4522        let empyrean_iso_to_mjd = __library.get(b"empyrean_iso_to_mjd\0").map(|sym| *sym)?;
4523        let empyrean_mjd_to_iso = __library.get(b"empyrean_mjd_to_iso\0").map(|sym| *sym)?;
4524        let empyrean_transform_coordinates = __library
4525            .get(b"empyrean_transform_coordinates\0")
4526            .map(|sym| *sym)?;
4527        Ok(EmpyreanLib {
4528            __library,
4529            empyrean_last_error,
4530            empyrean_context_new_minimal,
4531            empyrean_context_with_spk,
4532            empyrean_context_from_data_dir,
4533            empyrean_context_free,
4534            empyrean_default_data_dir,
4535            empyrean_string_free,
4536            empyrean_version_string,
4537            empyrean_versions,
4538            empyrean_versions_free,
4539            empyrean_builtsystem_new,
4540            empyrean_builtsystem_free,
4541            empyrean_builtsystem_propagate,
4542            empyrean_builtsystem_generate_ephemeris,
4543            empyrean_builtsystem_describe,
4544            empyrean_builtsystem_description_free,
4545            empyrean_generate_ephemeris,
4546            empyrean_ephemeris_result_free,
4547            empyrean_compute_impact_probabilities,
4548            empyrean_compute_impact_probabilities_result_free,
4549            empyrean_compute_b_planes,
4550            empyrean_compute_b_planes_result_free,
4551            empyrean_orbits_batch_free,
4552            empyrean_orbits_read_parquet,
4553            empyrean_orbits_write_parquet,
4554            empyrean_orbits_read_json,
4555            empyrean_orbits_write_json,
4556            empyrean_orbits_read_csv,
4557            empyrean_orbits_write_csv,
4558            empyrean_ephemeris_write_parquet,
4559            empyrean_ephemeris_write_json,
4560            empyrean_ephemeris_write_csv,
4561            empyrean_events_write_parquet,
4562            empyrean_events_write_json,
4563            empyrean_events_write_csv,
4564            empyrean_residuals_write_parquet,
4565            empyrean_residuals_write_json,
4566            empyrean_residuals_write_csv,
4567            empyrean_eigenvector_max_6x6,
4568            empyrean_split_gaussian,
4569            empyrean_get_observers,
4570            empyrean_observer_result_free,
4571            empyrean_abi_version,
4572            empyrean_read_ades,
4573            empyrean_observations_from_array,
4574            empyrean_observations_free,
4575            empyrean_radar_observations_from_array,
4576            empyrean_radar_observations_free,
4577            empyrean_determine,
4578            empyrean_od_result_free,
4579            empyrean_evaluate,
4580            empyrean_evaluate_result_free,
4581            empyrean_refine,
4582            empyrean_evaluate_plan,
4583            empyrean_plan_result_free,
4584            empyrean_propagate,
4585            empyrean_propagation_result_free,
4586            empyrean_propagation_covariance_series_cartesian,
4587            empyrean_propagation_covariance_at_cartesian,
4588            empyrean_tagged_covariance_series_free,
4589            empyrean_query_sbdb,
4590            empyrean_query_horizons,
4591            empyrean_query_horizons_vectors,
4592            empyrean_query_observations,
4593            empyrean_query_radar,
4594            empyrean_session_new,
4595            empyrean_session_free,
4596            empyrean_session_n_observations,
4597            empyrean_session_n_masked,
4598            empyrean_session_n_active,
4599            empyrean_session_mask,
4600            empyrean_session_unmask,
4601            empyrean_session_unmask_all,
4602            empyrean_session_is_masked,
4603            empyrean_session_refine,
4604            empyrean_session_history_len,
4605            empyrean_session_get_history,
4606            empyrean_session_diff,
4607            empyrean_get_states,
4608            empyrean_state_result_free,
4609            empyrean_iso_to_mjd,
4610            empyrean_mjd_to_iso,
4611            empyrean_transform_coordinates,
4612        })
4613    }
4614    #[doc = " Return a pointer to the last error message (thread-local, null-terminated).\n\n The pointer is valid until the next call that sets an error on the same\n thread."]
4615    pub unsafe fn empyrean_last_error(&self) -> *const ::std::os::raw::c_char {
4616        (self.empyrean_last_error)()
4617    }
4618    #[doc = " Create a **minimal** `EmpyreanContext` from a DE440 SPK file and a\n GM TPC file.\n\n Loads ONLY the planetary ephemeris and gravitational parameters —\n no Earth/Moon BPC kernels, no SB441-N16 asteroid perturbers, no\n MPC observatory codes, no Earth gravity field. This is sufficient\n for coordinate transforms and basic propagation under the\n `Approximate` force model, but is **not** enough for production\n orbit propagation, orbit determination, or topocentric ephemeris\n generation. Most callers should use\n [`empyrean_context_from_data_dir`] instead, which loads the full\n Standard-tier kernel set (downloading any missing files).\n\n Use [`empyrean_context_with_spk`] to chain additional SPK kernels\n (e.g. SB441-N16) onto a context built by this function.\n\n Returns a heap-allocated pointer on success, or null on error.\n Call `empyrean_last_error()` to retrieve the error message when null is\n returned.  The caller owns the returned pointer and must free it with\n `empyrean_context_free()`."]
4619    pub unsafe fn empyrean_context_new_minimal(
4620        &self,
4621        de440_path: *const ::std::os::raw::c_char,
4622        gm_path: *const ::std::os::raw::c_char,
4623    ) -> *mut EmpyreanContext {
4624        (self.empyrean_context_new_minimal)(de440_path, gm_path)
4625    }
4626    #[doc = " Load an additional SPK kernel into an existing context, in place.\n\n Useful for layering SB441-N16 asteroid perturbers or spacecraft\n SPK kernels (JWST, Gaia, custom probes) on top of a context built\n by [`empyrean_context_new_minimal`] or [`empyrean_context_from_data_dir`].\n The merged context picks up the new kernel's body coverage on top\n of what was already loaded.\n\n Returns 0 on success; negative error code on failure. The context\n pointer remains valid and unchanged when this function returns\n non-zero — failure does not invalidate `ctx`."]
4627    pub unsafe fn empyrean_context_with_spk(
4628        &self,
4629        ctx: *mut EmpyreanContext,
4630        spk_path: *const ::std::os::raw::c_char,
4631    ) -> i32 {
4632        (self.empyrean_context_with_spk)(ctx, spk_path)
4633    }
4634    #[doc = " Create a new `EmpyreanContext` from a data directory.\n\n Loads the full Standard-tier kernel set (DE440, SB441-N16, Earth/Moon\n BPCs, GM, MPC observatory codes) from `data_dir`, downloading any\n missing files. Pass null for `data_dir` to use the platform data\n directory (`~/.local/share/empyrean/data` on Linux,\n `~/Library/Application Support/empyrean/data` on macOS).\n\n Returns a heap-allocated pointer on success, or null on error.\n Call `empyrean_last_error()` to retrieve the error message when null is\n returned. The caller owns the returned pointer and must free it with\n `empyrean_context_free()`."]
4635    pub unsafe fn empyrean_context_from_data_dir(
4636        &self,
4637        data_dir: *const ::std::os::raw::c_char,
4638    ) -> *mut EmpyreanContext {
4639        (self.empyrean_context_from_data_dir)(data_dir)
4640    }
4641    #[doc = " Free an `EmpyreanContext` previously returned by `empyrean_context_new()`.\n\n Passing null is a no-op."]
4642    pub unsafe fn empyrean_context_free(&self, ctx: *mut EmpyreanContext) {
4643        (self.empyrean_context_free)(ctx)
4644    }
4645    #[doc = " Return the platform XDG-compliant default data directory as a\n heap-allocated, NUL-terminated UTF-8 string.\n\n Mirrors villeneuve's [`DataManager::new`] resolution: honors\n `EMPYREAN_DATA_DIR` first, then falls back to `dirs::data_dir()` —\n `~/.local/share/empyrean/data/` on Linux, `~/Library/Application\n Support/empyrean/data/` on macOS, `%APPDATA%\\empyrean\\data\\` on\n Windows. Cheap (no filesystem I/O).\n\n Returns null on failure (non-UTF-8 path, NUL byte in path, panic).\n Call `empyrean_last_error()` for details.\n\n **The caller owns the returned pointer and must release it with\n [`empyrean_string_free`].**"]
4646    pub unsafe fn empyrean_default_data_dir(&self) -> *mut ::std::os::raw::c_char {
4647        (self.empyrean_default_data_dir)()
4648    }
4649    #[doc = " Free a string returned by an empyrean C API function (e.g.,\n [`empyrean_default_data_dir`], [`empyrean_version_string`]).\n\n Passing null is a no-op. Passing any pointer not obtained from an\n empyrean string-returning function is undefined behavior."]
4650    pub unsafe fn empyrean_string_free(&self, s: *mut ::std::os::raw::c_char) {
4651        (self.empyrean_string_free)(s)
4652    }
4653    #[doc = " Multi-line version report — `empyrean-core <ver>\\nvilleneuve <ver>\\n…`.\n\n Mirrors [`empyrean_core::version_string`]. Useful for `--version`-style\n output and for verifying the build provenance of a deployed cdylib.\n Returns null on allocation failure (extremely unlikely — the strings\n are short and `&'static` underneath); call `empyrean_last_error()` if\n it does.\n\n **The caller owns the returned pointer and must release it with\n [`empyrean_string_free`].**"]
4654    pub unsafe fn empyrean_version_string(&self) -> *mut ::std::os::raw::c_char {
4655        (self.empyrean_version_string)()
4656    }
4657    #[doc = " Populate `out` with the per-crate versions of the empyrean stack.\n\n Returns 0 on success, non-zero on failure (`empyrean_last_error()`\n has the details). On failure `out` is left zero-initialized — no\n allocation needs freeing.\n\n **The caller owns the strings inside `out` and must release the\n whole struct with [`empyrean_versions_free`] when done.**"]
4658    pub unsafe fn empyrean_versions(&self, out: *mut EmpyreanVersions) -> i32 {
4659        (self.empyrean_versions)(out)
4660    }
4661    #[doc = " Free the version strings inside `versions` (each was heap-allocated\n by a previous successful [`empyrean_versions`] call). After this\n returns, `versions` itself is zero-initialized — safe to drop on\n the caller's stack.\n\n Passing null is a no-op. Calling this twice on the same struct, or\n passing a struct that wasn't populated by [`empyrean_versions`], is\n undefined behavior."]
4662    pub unsafe fn empyrean_versions_free(&self, versions: *mut EmpyreanVersions) {
4663        (self.empyrean_versions_free)(versions)
4664    }
4665    #[doc = " Assemble a reusable force-model handle for `(force_model, frame)` from\n `ctx`, freezing `encounter_timescale_divisor` into its key.\n\n - `force_model`: tier code (0=Approximate, 1=Basic, 2=Standard).\n - `frame`: output/integration frame code (0=ICRF, 1=EclipticJ2000, 2=ITRF93).\n - `encounter_timescale_divisor`: pass `0.0` to freeze the engine default;\n   any positive value freezes that divisor into the key *before* it is\n   used to validate calls.\n - `out`: receives the heap-allocated handle on success.\n\n The handle snapshots `ctx`'s kernel manifest at construction so\n [`empyrean_builtsystem_describe`] is self-contained. After you load any\n additional kernel into `ctx`, rebuild the handle — a stale handle is\n rejected loudly by every forward-model call, never silently reused.\n\n Returns [`EMPYREAN_BUILTSYSTEM_OK`] on success; on error, `out` is left\n untouched and `empyrean_last_error()` carries the message. The caller\n owns the returned handle and must free it with\n [`empyrean_builtsystem_free`]."]
4666    pub unsafe fn empyrean_builtsystem_new(
4667        &self,
4668        ctx: *const EmpyreanContext,
4669        force_model: i32,
4670        frame: i32,
4671        encounter_timescale_divisor: f64,
4672        out: *mut *mut EmpyreanBuiltSystem,
4673    ) -> i32 {
4674        (self.empyrean_builtsystem_new)(ctx, force_model, frame, encounter_timescale_divisor, out)
4675    }
4676    #[doc = " Free a handle previously returned by [`empyrean_builtsystem_new`].\n Passing null is a no-op."]
4677    pub unsafe fn empyrean_builtsystem_free(&self, handle: *mut EmpyreanBuiltSystem) {
4678        (self.empyrean_builtsystem_free)(handle)
4679    }
4680    #[doc = " Propagate `orbits` to `times` through the pre-built handle.\n\n Signature parallels the one-shot\n [`empyrean_propagate`](crate::propagate::empyrean_propagate) but takes\n `(handle, ctx, ...)`. Before dispatch the identity guard runs: the handle\n must have been built from `ctx`'s ephemeris data\n ([`EMPYREAN_BUILTSYSTEM_DATA_MISMATCH`]); the config must match the frozen\n key ([`EMPYREAN_BUILTSYSTEM_KEY_MISMATCH_FRAME`] /\n `_FORCE_MODEL` / `_DIVISOR`); and the data must be unmutated since build\n ([`EMPYREAN_BUILTSYSTEM_STALE`]). On pass, the result is bit-identical to\n the one-shot with the same config.\n\n On success populates `result_out`; free it with\n [`empyrean_propagation_result_free`](crate::propagate::empyrean_propagation_result_free)."]
4681    pub unsafe fn empyrean_builtsystem_propagate(
4682        &self,
4683        handle: *const EmpyreanBuiltSystem,
4684        ctx: *const EmpyreanContext,
4685        orbits_ptr: *const EmpyreanOrbit,
4686        num_orbits: usize,
4687        times_ptr: *const f64,
4688        num_times: usize,
4689        config: *const EmpyreanPropagationConfig,
4690        result_out: *mut EmpyreanPropagationResult,
4691    ) -> i32 {
4692        (self.empyrean_builtsystem_propagate)(
4693            handle, ctx, orbits_ptr, num_orbits, times_ptr, num_times, config, result_out,
4694        )
4695    }
4696    #[doc = " Generate predicted ephemeris for `orbits` and `observers` through the\n pre-built handle.\n\n Signature parallels the one-shot\n [`empyrean_generate_ephemeris`](crate::ephemeris::empyrean_generate_ephemeris)\n but takes `(handle, ctx, ...)`. Runs the same identity guard as\n [`empyrean_builtsystem_propagate`] before dispatch; on pass the result is\n bit-identical to the one-shot. Note the C-ABI ephemeris config carries no\n divisor knob, so a handle frozen at a non-default divisor is rejected here\n with [`EMPYREAN_BUILTSYSTEM_KEY_MISMATCH_DIVISOR`] rather than served under\n the wrong dynamics — build the handle with the default divisor for\n ephemeris reuse.\n\n On success populates `result_out`; free it with\n [`empyrean_ephemeris_result_free`](crate::ephemeris::empyrean_ephemeris_result_free)."]
4697    pub unsafe fn empyrean_builtsystem_generate_ephemeris(
4698        &self,
4699        handle: *const EmpyreanBuiltSystem,
4700        ctx: *const EmpyreanContext,
4701        orbits_ptr: *const EmpyreanOrbit,
4702        num_orbits: usize,
4703        observers_ptr: *const EmpyreanObserver,
4704        num_observers: usize,
4705        config: *const EmpyreanEphemerisConfig,
4706        result_out: *mut EmpyreanEphemerisResult,
4707    ) -> i32 {
4708        (self.empyrean_builtsystem_generate_ephemeris)(
4709            handle,
4710            ctx,
4711            orbits_ptr,
4712            num_orbits,
4713            observers_ptr,
4714            num_observers,
4715            config,
4716            result_out,
4717        )
4718    }
4719    #[doc = " Populate `out` with a full reproducibility summary of the handle's frozen\n force model and its captured kernel manifest.\n\n Every field is populated from the system description and the manifest\n snapshot — no field is left defaulted. Returns\n [`EMPYREAN_BUILTSYSTEM_OK`] on success. The caller owns the heap arrays\n inside `out` and must release them with\n [`empyrean_builtsystem_description_free`]."]
4720    pub unsafe fn empyrean_builtsystem_describe(
4721        &self,
4722        handle: *const EmpyreanBuiltSystem,
4723        out: *mut EmpyreanSystemDescription,
4724    ) -> i32 {
4725        (self.empyrean_builtsystem_describe)(handle, out)
4726    }
4727    #[doc = " Free the heap arrays inside a description populated by\n [`empyrean_builtsystem_describe`] (the perturber-id array and the kernel\n records with their C strings). After this returns `desc` is\n zero-initialized — safe to drop on the caller's stack. Passing null is a\n no-op."]
4728    pub unsafe fn empyrean_builtsystem_description_free(
4729        &self,
4730        desc: *mut EmpyreanSystemDescription,
4731    ) {
4732        (self.empyrean_builtsystem_description_free)(desc)
4733    }
4734    #[doc = " Generate predicted ephemeris for orbits and observers.\n\n Returns 0 on success, negative error code on failure.\n On success, `result_out` is populated with ephemeris entries:\n `num_orbits * num_observers` rows, orbit-major, and within each orbit\n in **observer-input order** (sensitivity rows follow the same order).\n Each observer carries its own epoch, so positional pairing against\n the input observers is safe within an orbit block.\n The caller must free the result with `empyrean_ephemeris_result_free()`."]
4735    pub unsafe fn empyrean_generate_ephemeris(
4736        &self,
4737        ctx: *const EmpyreanContext,
4738        orbits_ptr: *const EmpyreanOrbit,
4739        num_orbits: usize,
4740        observers_ptr: *const EmpyreanObserver,
4741        num_observers: usize,
4742        config: *const EmpyreanEphemerisConfig,
4743        result_out: *mut EmpyreanEphemerisResult,
4744    ) -> i32 {
4745        (self.empyrean_generate_ephemeris)(
4746            ctx,
4747            orbits_ptr,
4748            num_orbits,
4749            observers_ptr,
4750            num_observers,
4751            config,
4752            result_out,
4753        )
4754    }
4755    #[doc = " Free an ephemeris result previously returned by `empyrean_generate_ephemeris()`."]
4756    pub unsafe fn empyrean_ephemeris_result_free(&self, result: *mut EmpyreanEphemerisResult) {
4757        (self.empyrean_ephemeris_result_free)(result)
4758    }
4759    #[doc = " Run [`empyrean_core::impact::compute_impact_probabilities`] over a\n caller-supplied set of [`UncertaintyMethod`] variants and return\n the flattened IP records tagged by method.\n\n Caller is responsible for freeing the result via\n [`empyrean_compute_impact_probabilities_result_free`].\n\n # Returns\n `0` on success, negative on failure (see [`crate::set_last_error`]).\n\n # Safety\n All non-null pointer arguments must point to valid arrays of the\n indicated length for the duration of the call. The output struct\n is allocated by the caller; pointer fields inside it are allocated\n here and owned by the result."]
4760    pub unsafe fn empyrean_compute_impact_probabilities(
4761        &self,
4762        ctx: *const EmpyreanContext,
4763        orbits_ptr: *const EmpyreanOrbit,
4764        num_orbits: usize,
4765        end_mjd_tdb: f64,
4766        methods_ptr: *const EmpyreanUncertaintyMethod,
4767        num_methods: usize,
4768        body_filter_naif: *const i32,
4769        num_body_filter: usize,
4770        result_out: *mut EmpyreanImpactProbabilitiesResult,
4771    ) -> i32 {
4772        (self.empyrean_compute_impact_probabilities)(
4773            ctx,
4774            orbits_ptr,
4775            num_orbits,
4776            end_mjd_tdb,
4777            methods_ptr,
4778            num_methods,
4779            body_filter_naif,
4780            num_body_filter,
4781            result_out,
4782        )
4783    }
4784    #[doc = " Free the records array allocated by\n [`empyrean_compute_impact_probabilities`]. After calling, the\n struct's `records` is reset to null and `num_records` to 0."]
4785    pub unsafe fn empyrean_compute_impact_probabilities_result_free(
4786        &self,
4787        result: *mut EmpyreanImpactProbabilitiesResult,
4788    ) {
4789        (self.empyrean_compute_impact_probabilities_result_free)(result)
4790    }
4791    #[doc = " Run [`empyrean_core::impact::compute_b_planes`] over a caller-\n supplied set of [`UncertaintyMethod`] variants and return the\n flattened B-plane records tagged by method.\n\n Caller is responsible for freeing the result via\n [`empyrean_compute_b_planes_result_free`].\n\n # Safety\n Same contract as\n [`empyrean_compute_impact_probabilities`]."]
4792    pub unsafe fn empyrean_compute_b_planes(
4793        &self,
4794        ctx: *const EmpyreanContext,
4795        orbits_ptr: *const EmpyreanOrbit,
4796        num_orbits: usize,
4797        end_mjd_tdb: f64,
4798        methods_ptr: *const EmpyreanUncertaintyMethod,
4799        num_methods: usize,
4800        body_filter_naif: *const i32,
4801        num_body_filter: usize,
4802        result_out: *mut EmpyreanBPlanesResult,
4803    ) -> i32 {
4804        (self.empyrean_compute_b_planes)(
4805            ctx,
4806            orbits_ptr,
4807            num_orbits,
4808            end_mjd_tdb,
4809            methods_ptr,
4810            num_methods,
4811            body_filter_naif,
4812            num_body_filter,
4813            result_out,
4814        )
4815    }
4816    #[doc = " Free the records array allocated by [`empyrean_compute_b_planes`]."]
4817    pub unsafe fn empyrean_compute_b_planes_result_free(&self, result: *mut EmpyreanBPlanesResult) {
4818        (self.empyrean_compute_b_planes_result_free)(result)
4819    }
4820    #[doc = " Free a batch previously returned by an `empyrean_orbits_read_*`\n function. Passing null is a no-op."]
4821    pub unsafe fn empyrean_orbits_batch_free(&self, batch: *mut EmpyreanOrbitBatch) {
4822        (self.empyrean_orbits_batch_free)(batch)
4823    }
4824    #[doc = " Read an orbits parquet file. Caller frees the result with\n [`empyrean_orbits_batch_free`]."]
4825    pub unsafe fn empyrean_orbits_read_parquet(
4826        &self,
4827        path: *const ::std::os::raw::c_char,
4828        out: *mut EmpyreanOrbitBatch,
4829    ) -> i32 {
4830        (self.empyrean_orbits_read_parquet)(path, out)
4831    }
4832    #[doc = " Write an orbit batch to a parquet file."]
4833    pub unsafe fn empyrean_orbits_write_parquet(
4834        &self,
4835        path: *const ::std::os::raw::c_char,
4836        batch: *const EmpyreanOrbitBatch,
4837    ) -> i32 {
4838        (self.empyrean_orbits_write_parquet)(path, batch)
4839    }
4840    #[doc = " Read an orbits JSON file (array of orbit-row objects). Caller frees\n with [`empyrean_orbits_batch_free`]."]
4841    pub unsafe fn empyrean_orbits_read_json(
4842        &self,
4843        path: *const ::std::os::raw::c_char,
4844        out: *mut EmpyreanOrbitBatch,
4845    ) -> i32 {
4846        (self.empyrean_orbits_read_json)(path, out)
4847    }
4848    #[doc = " Write an orbit batch to JSON."]
4849    pub unsafe fn empyrean_orbits_write_json(
4850        &self,
4851        path: *const ::std::os::raw::c_char,
4852        batch: *const EmpyreanOrbitBatch,
4853    ) -> i32 {
4854        (self.empyrean_orbits_write_json)(path, batch)
4855    }
4856    #[doc = " Read an orbits CSV file.\n\n CSV does not carry covariance (use parquet for covariance round-trip)."]
4857    pub unsafe fn empyrean_orbits_read_csv(
4858        &self,
4859        path: *const ::std::os::raw::c_char,
4860        out: *mut EmpyreanOrbitBatch,
4861    ) -> i32 {
4862        (self.empyrean_orbits_read_csv)(path, out)
4863    }
4864    #[doc = " Write an orbit batch to CSV."]
4865    pub unsafe fn empyrean_orbits_write_csv(
4866        &self,
4867        path: *const ::std::os::raw::c_char,
4868        batch: *const EmpyreanOrbitBatch,
4869    ) -> i32 {
4870        (self.empyrean_orbits_write_csv)(path, batch)
4871    }
4872    #[doc = " Write ephemeris entries to parquet using the villeneuve schema."]
4873    pub unsafe fn empyrean_ephemeris_write_parquet(
4874        &self,
4875        path: *const ::std::os::raw::c_char,
4876        entries_ptr: *const EmpyreanEphemerisEntry,
4877        num_entries: usize,
4878    ) -> i32 {
4879        (self.empyrean_ephemeris_write_parquet)(path, entries_ptr, num_entries)
4880    }
4881    #[doc = " Write ephemeris entries to JSON."]
4882    pub unsafe fn empyrean_ephemeris_write_json(
4883        &self,
4884        path: *const ::std::os::raw::c_char,
4885        entries_ptr: *const EmpyreanEphemerisEntry,
4886        num_entries: usize,
4887    ) -> i32 {
4888        (self.empyrean_ephemeris_write_json)(path, entries_ptr, num_entries)
4889    }
4890    #[doc = " Write ephemeris entries to CSV."]
4891    pub unsafe fn empyrean_ephemeris_write_csv(
4892        &self,
4893        path: *const ::std::os::raw::c_char,
4894        entries_ptr: *const EmpyreanEphemerisEntry,
4895        num_entries: usize,
4896    ) -> i32 {
4897        (self.empyrean_ephemeris_write_csv)(path, entries_ptr, num_entries)
4898    }
4899    #[doc = " Write events to parquet."]
4900    pub unsafe fn empyrean_events_write_parquet(
4901        &self,
4902        path: *const ::std::os::raw::c_char,
4903        events_ptr: *const EmpyreanEvent,
4904        num_events: usize,
4905    ) -> i32 {
4906        (self.empyrean_events_write_parquet)(path, events_ptr, num_events)
4907    }
4908    #[doc = " Write events to JSON."]
4909    pub unsafe fn empyrean_events_write_json(
4910        &self,
4911        path: *const ::std::os::raw::c_char,
4912        events_ptr: *const EmpyreanEvent,
4913        num_events: usize,
4914    ) -> i32 {
4915        (self.empyrean_events_write_json)(path, events_ptr, num_events)
4916    }
4917    #[doc = " Write events to CSV."]
4918    pub unsafe fn empyrean_events_write_csv(
4919        &self,
4920        path: *const ::std::os::raw::c_char,
4921        events_ptr: *const EmpyreanEvent,
4922        num_events: usize,
4923    ) -> i32 {
4924        (self.empyrean_events_write_csv)(path, events_ptr, num_events)
4925    }
4926    #[doc = " Write OD residuals to parquet."]
4927    pub unsafe fn empyrean_residuals_write_parquet(
4928        &self,
4929        path: *const ::std::os::raw::c_char,
4930        obs_ptr: *const EmpyreanObservationResult,
4931        num_obs: usize,
4932    ) -> i32 {
4933        (self.empyrean_residuals_write_parquet)(path, obs_ptr, num_obs)
4934    }
4935    #[doc = " Write OD residuals to JSON."]
4936    pub unsafe fn empyrean_residuals_write_json(
4937        &self,
4938        path: *const ::std::os::raw::c_char,
4939        obs_ptr: *const EmpyreanObservationResult,
4940        num_obs: usize,
4941    ) -> i32 {
4942        (self.empyrean_residuals_write_json)(path, obs_ptr, num_obs)
4943    }
4944    #[doc = " Write OD residuals to CSV."]
4945    pub unsafe fn empyrean_residuals_write_csv(
4946        &self,
4947        path: *const ::std::os::raw::c_char,
4948        obs_ptr: *const EmpyreanObservationResult,
4949        num_obs: usize,
4950    ) -> i32 {
4951        (self.empyrean_residuals_write_csv)(path, obs_ptr, num_obs)
4952    }
4953    #[doc = " Find the dominant eigenvalue and eigenvector of a 6x6 symmetric matrix.\n\n Returns 0 on success. `eigenvalue_out` receives the eigenvalue,\n `eigenvector_out` receives the 6-element eigenvector."]
4954    pub unsafe fn empyrean_eigenvector_max_6x6(
4955        &self,
4956        matrix: *const [[f64; 6usize]; 6usize],
4957        eigenvalue_out: *mut f64,
4958        eigenvector_out: *mut [f64; 6usize],
4959    ) -> i32 {
4960        (self.empyrean_eigenvector_max_6x6)(matrix, eigenvalue_out, eigenvector_out)
4961    }
4962    #[doc = " Split a 6D Gaussian into K weighted components along the dominant\n eigenvector of the covariance.\n\n `weights_out`, `means_out`, `covariances_out` must point to arrays\n of size K, K×6, and K×6×6 respectively. Returns 0 on success."]
4963    pub unsafe fn empyrean_split_gaussian(
4964        &self,
4965        mean: *const [f64; 6usize],
4966        covariance: *const [[f64; 6usize]; 6usize],
4967        k: usize,
4968        weights_out: *mut f64,
4969        means_out: *mut [f64; 6usize],
4970        covariances_out: *mut [[f64; 6usize]; 6usize],
4971    ) -> i32 {
4972        (self.empyrean_split_gaussian)(mean, covariance, k, weights_out, means_out, covariances_out)
4973    }
4974    #[doc = " Compute observer states for given observatory codes and epochs.\n\n Returns 0 on success, negative error code on failure.\n On success, `result_out` is populated with observer states.\n The caller must free the result with `empyrean_observer_result_free()`."]
4975    pub unsafe fn empyrean_get_observers(
4976        &self,
4977        ctx: *const EmpyreanContext,
4978        obs_codes: *const *const ::std::os::raw::c_char,
4979        num_codes: usize,
4980        epochs_mjd_tdb: *const f64,
4981        num_epochs: usize,
4982        result_out: *mut EmpyreanObserverResult,
4983    ) -> i32 {
4984        (self.empyrean_get_observers)(
4985            ctx,
4986            obs_codes,
4987            num_codes,
4988            epochs_mjd_tdb,
4989            num_epochs,
4990            result_out,
4991        )
4992    }
4993    #[doc = " Free an observer result previously returned by `empyrean_get_observers()`.\n\n Passing a zeroed/null result is a no-op."]
4994    pub unsafe fn empyrean_observer_result_free(&self, result: *mut EmpyreanObserverResult) {
4995        (self.empyrean_observer_result_free)(result)
4996    }
4997    #[doc = " Runtime accessor for [`EMPYREAN_ABI_VERSION`] — lets a dynamically\n linked consumer confirm the loaded library's frozen-shape contract\n matches what it compiled against."]
4998    pub unsafe fn empyrean_abi_version(&self) -> u32 {
4999        (self.empyrean_abi_version)()
5000    }
5001    #[doc = " Read ADES PSV / MPC80 data from a string and pack into the C array.\n\n `path_or_content` is a null-terminated UTF-8 string with the ADES\n content directly (not a file path)."]
5002    pub unsafe fn empyrean_read_ades(
5003        &self,
5004        content: *const ::std::os::raw::c_char,
5005        observations_out: *mut *mut EmpyreanObservation,
5006        num_observations_out: *mut usize,
5007        radar_out: *mut *mut EmpyreanRadarObservation,
5008        num_radar_out: *mut usize,
5009    ) -> i32 {
5010        (self.empyrean_read_ades)(
5011            content,
5012            observations_out,
5013            num_observations_out,
5014            radar_out,
5015            num_radar_out,
5016        )
5017    }
5018    #[doc = " Free an observation array previously returned by `empyrean_read_ades()`.\n Copy a caller-owned array of [`EmpyreanObservation`] into a fresh\n allocation that matches the layout produced by\n [`empyrean_read_ades`].\n\n The strings on the input observations (`perm_id` / `prov_id` /\n `obs_time`) are duplicated into freshly-allocated `CString`s so the\n returned array owns its own memory independent of the input.\n\n On success populates `*out_ptr` with the new array and `*out_num`\n with its length, both freeable with [`empyrean_observations_free`].\n\n Returns 0 on success; negative error code on failure."]
5019    pub unsafe fn empyrean_observations_from_array(
5020        &self,
5021        input: *const EmpyreanObservation,
5022        num: usize,
5023        out_ptr: *mut *mut EmpyreanObservation,
5024        out_num: *mut usize,
5025    ) -> i32 {
5026        (self.empyrean_observations_from_array)(input, num, out_ptr, out_num)
5027    }
5028    pub unsafe fn empyrean_observations_free(
5029        &self,
5030        observations: *mut EmpyreanObservation,
5031        num: usize,
5032    ) {
5033        (self.empyrean_observations_free)(observations, num)
5034    }
5035    #[doc = " Copy a caller-owned array of [`EmpyreanRadarObservation`] into a fresh\n allocation matching the layout produced by [`empyrean_read_ades`].\n\n The nullable `*mut c_char` fields (`perm_id` / `prov_id` / `trk_sub` /\n `obs_time` / `remarks`) are duplicated into freshly-allocated\n `CString`s so the returned array owns its own memory independent of the\n input. All scalar fields (including the ADES-native delay/Doppler\n values) are copied verbatim — no unit conversion, nothing zeroed.\n\n On success populates `*out_ptr` with the new array and `*out_num` with\n its length, both freeable with [`empyrean_radar_observations_free`].\n\n Returns 0 on success; negative error code on failure."]
5036    pub unsafe fn empyrean_radar_observations_from_array(
5037        &self,
5038        input: *const EmpyreanRadarObservation,
5039        num: usize,
5040        out_ptr: *mut *mut EmpyreanRadarObservation,
5041        out_num: *mut usize,
5042    ) -> i32 {
5043        (self.empyrean_radar_observations_from_array)(input, num, out_ptr, out_num)
5044    }
5045    #[doc = " Free a radar observation array previously returned by\n [`empyrean_read_ades`] or [`empyrean_radar_observations_from_array`]."]
5046    pub unsafe fn empyrean_radar_observations_free(
5047        &self,
5048        observations: *mut EmpyreanRadarObservation,
5049        num: usize,
5050    ) {
5051        (self.empyrean_radar_observations_free)(observations, num)
5052    }
5053    #[doc = " Run the full orbit determination pipeline.\n\n When `num_initial_orbits > 0`, the supplied orbits are used as DC\n seeds (one per ADES object_id encountered in `observations`,\n matched by orbit index). Pass `null, 0` to let the IOD pipeline\n produce its own seeds."]
5054    pub unsafe fn empyrean_determine(
5055        &self,
5056        ctx: *const EmpyreanContext,
5057        observations: *const EmpyreanObservation,
5058        num_observations: usize,
5059        radar: *const EmpyreanRadarObservation,
5060        num_radar: usize,
5061        initial_orbits: *const EmpyreanOrbit,
5062        num_initial_orbits: usize,
5063        config: *const EmpyreanODConfig,
5064        result_out: *mut EmpyreanODResult,
5065    ) -> i32 {
5066        (self.empyrean_determine)(
5067            ctx,
5068            observations,
5069            num_observations,
5070            radar,
5071            num_radar,
5072            initial_orbits,
5073            num_initial_orbits,
5074            config,
5075            result_out,
5076        )
5077    }
5078    #[doc = " Free an OD result previously returned by `empyrean_determine()` or `empyrean_refine()`."]
5079    pub unsafe fn empyrean_od_result_free(&self, result: *mut EmpyreanODResult) {
5080        (self.empyrean_od_result_free)(result)
5081    }
5082    #[doc = " Evaluate residuals for a single orbit against observations."]
5083    pub unsafe fn empyrean_evaluate(
5084        &self,
5085        ctx: *const EmpyreanContext,
5086        orbit: *const EmpyreanOrbit,
5087        observations: *const EmpyreanObservation,
5088        num_observations: usize,
5089        config: *const EmpyreanODConfig,
5090        result_out: *mut EmpyreanEvaluateResult,
5091    ) -> i32 {
5092        (self.empyrean_evaluate)(
5093            ctx,
5094            orbit,
5095            observations,
5096            num_observations,
5097            config,
5098            result_out,
5099        )
5100    }
5101    #[doc = " Free an evaluate result previously returned by `empyrean_evaluate()`."]
5102    pub unsafe fn empyrean_evaluate_result_free(&self, result: *mut EmpyreanEvaluateResult) {
5103        (self.empyrean_evaluate_result_free)(result)
5104    }
5105    #[doc = " Refine a single orbit estimate with new observations using a\n Bayesian prior."]
5106    pub unsafe fn empyrean_refine(
5107        &self,
5108        ctx: *const EmpyreanContext,
5109        orbit: *const EmpyreanOrbit,
5110        observations: *const EmpyreanObservation,
5111        num_observations: usize,
5112        config: *const EmpyreanODConfig,
5113        result_out: *mut EmpyreanODResult,
5114    ) -> i32 {
5115        (self.empyrean_refine)(
5116            ctx,
5117            orbit,
5118            observations,
5119            num_observations,
5120            config,
5121            result_out,
5122        )
5123    }
5124    #[doc = " Evaluate an observation plan: how much each candidate observation would\n tighten the prior orbit covariance.\n\n `orbit` must carry a 6×6 Cartesian covariance (e.g. a `determine` result).\n `planned` is an array of `num_planned` candidate observations. `orbit_id`\n may be null (defaults to `\"orbit_0\"`). On success populates `*result_out`\n (caller-allocated); free with [`empyrean_plan_result_free`].\n\n Returns 0 on success, -1 for a null/invalid argument, -3 if planning fails\n (missing/singular prior covariance, an infeasible or invalid candidate, an\n ephemeris-generation error), -99 on an internal panic. The error message is\n retrievable via `empyrean_last_error()`."]
5125    pub unsafe fn empyrean_evaluate_plan(
5126        &self,
5127        ctx: *const EmpyreanContext,
5128        orbit: *const EmpyreanOrbit,
5129        orbit_id: *const ::std::os::raw::c_char,
5130        planned: *const EmpyreanPlannedObservation,
5131        num_planned: usize,
5132        config: *const EmpyreanPlanningConfig,
5133        result_out: *mut EmpyreanPlanResult,
5134    ) -> i32 {
5135        (self.empyrean_evaluate_plan)(
5136            ctx,
5137            orbit,
5138            orbit_id,
5139            planned,
5140            num_planned,
5141            config,
5142            result_out,
5143        )
5144    }
5145    #[doc = " Free the heap allocations inside a plan result populated by\n [`empyrean_evaluate_plan`]. Does not free the caller-allocated struct."]
5146    pub unsafe fn empyrean_plan_result_free(&self, result: *mut EmpyreanPlanResult) {
5147        (self.empyrean_plan_result_free)(result)
5148    }
5149    #[doc = " Propagate orbits to the requested target times.\n\n Returns 0 on success, negative error code on failure.\n On success, `result_out` is populated with the propagated states.\n The caller must free the result with `empyrean_propagation_result_free()`.\n\n States are flat in orbit-major order; within each orbit, rows are in\n **ascending epoch order, always** (engine guarantee since villeneuve\n v1.18.0), regardless of request order. Positional pairing against an\n ascending, duplicate-free request grid is exact; for any other\n request shape, join on `epoch_mjd_tdb`."]
5150    pub unsafe fn empyrean_propagate(
5151        &self,
5152        ctx: *const EmpyreanContext,
5153        orbits_ptr: *const EmpyreanOrbit,
5154        num_orbits: usize,
5155        times_ptr: *const f64,
5156        num_times: usize,
5157        config: *const EmpyreanPropagationConfig,
5158        result_out: *mut EmpyreanPropagationResult,
5159    ) -> i32 {
5160        (self.empyrean_propagate)(
5161            ctx, orbits_ptr, num_orbits, times_ptr, num_times, config, result_out,
5162        )
5163    }
5164    #[doc = " Free a propagation result previously returned by `empyrean_propagate()`."]
5165    pub unsafe fn empyrean_propagation_result_free(&self, result: *mut EmpyreanPropagationResult) {
5166        (self.empyrean_propagation_result_free)(result)
5167    }
5168    #[doc = " Resolved-kind tagged covariance at every output epoch for one orbit,\n Cartesian basis. On success `out_series` owns the array; free with\n [`empyrean_tagged_covariance_series_free`]. On error `out_series` is\n left null and the detail is on `empyrean_last_error()`.\n\n # Safety\n `result` must be a valid pointer returned by `empyrean_propagate`;\n `out_series` must be a valid pointer to write the result into."]
5169    pub unsafe fn empyrean_propagation_covariance_series_cartesian(
5170        &self,
5171        result: *const EmpyreanPropagationResult,
5172        orbit_index: usize,
5173        out_series: *mut *mut EmpyreanTaggedCovarianceSeries,
5174    ) -> i32 {
5175        (self.empyrean_propagation_covariance_series_cartesian)(result, orbit_index, out_series)
5176    }
5177    #[doc = " Resolved-kind tagged covariance at a single `(orbit_index,\n epoch_index)`, Cartesian basis (the gm-free point query). `out` is\n written on success.\n\n # Safety\n `result` and `out` must be valid pointers; `result` from `empyrean_propagate`."]
5178    pub unsafe fn empyrean_propagation_covariance_at_cartesian(
5179        &self,
5180        result: *const EmpyreanPropagationResult,
5181        orbit_index: usize,
5182        epoch_index: usize,
5183        out: *mut EmpyreanTaggedCovariance,
5184    ) -> i32 {
5185        (self.empyrean_propagation_covariance_at_cartesian)(result, orbit_index, epoch_index, out)
5186    }
5187    #[doc = " Free a series returned by\n [`empyrean_propagation_covariance_series_cartesian`].\n\n # Safety\n `series` must be null or a pointer returned by that accessor, freed once."]
5188    pub unsafe fn empyrean_tagged_covariance_series_free(
5189        &self,
5190        series: *mut EmpyreanTaggedCovarianceSeries,
5191    ) {
5192        (self.empyrean_tagged_covariance_series_free)(series)
5193    }
5194    #[doc = " Query the JPL Small-Body Database for one or more orbits.\n\n `object_ids` is an array of `num_object_ids` null-terminated UTF-8\n designations / names / SPK IDs (e.g. `\"apophis\"`, `\"99942\"`,\n `\"2024 YR4\"`, `\"67P\"`). `cache_dir` may be null to skip caching, or\n a directory path where SBDB JSON responses are cached on disk.\n\n On success the populated [`EmpyreanOrbitBatch`] must be released with\n [`empyrean_orbits_batch_free`](crate::io::empyrean_orbits_batch_free)."]
5195    pub unsafe fn empyrean_query_sbdb(
5196        &self,
5197        object_ids: *const *const ::std::os::raw::c_char,
5198        num_object_ids: usize,
5199        cache_dir: *const ::std::os::raw::c_char,
5200        out: *mut EmpyreanOrbitBatch,
5201    ) -> i32 {
5202        (self.empyrean_query_sbdb)(object_ids, num_object_ids, cache_dir, out)
5203    }
5204    #[doc = " Query JPL Horizons for predicted ephemeris records.\n\n `object_ids` is an array of `num_object_ids` null-terminated UTF-8\n designations / names / SPK IDs. `obs_code` is the MPC observatory\n code as a null-terminated string. `times_mjd_tdb` carries\n `num_times` epochs in MJD TDB.\n\n On success populates an [`EmpyreanEphemerisResult`] with one entry\n per `(object_id × epoch)`. Free with\n [`empyrean_ephemeris_result_free`](crate::ephemeris::empyrean_ephemeris_result_free).\n\n All angular values are converted to **degrees** at the FFI boundary\n (Horizons natively returns radians)."]
5205    pub unsafe fn empyrean_query_horizons(
5206        &self,
5207        object_ids: *const *const ::std::os::raw::c_char,
5208        num_object_ids: usize,
5209        obs_code: *const ::std::os::raw::c_char,
5210        times_mjd_tdb: *const f64,
5211        num_times: usize,
5212        cache_dir: *const ::std::os::raw::c_char,
5213        out: *mut EmpyreanEphemerisResult,
5214    ) -> i32 {
5215        (self.empyrean_query_horizons)(
5216            object_ids,
5217            num_object_ids,
5218            obs_code,
5219            times_mjd_tdb,
5220            num_times,
5221            cache_dir,
5222            out,
5223        )
5224    }
5225    #[doc = " Query JPL Horizons for a Cartesian state vector at a single epoch.\n\n `command` is the Horizons COMMAND string as a null-terminated UTF-8\n string (e.g. `\"99942;\"`, `\"DES=C/2019 Q4;\"`). `epoch_mjd_tdb` is\n the epoch in MJD TDB. `cache_dir` may be null to skip caching, or\n a directory path where Horizons JSON responses are cached on disk.\n\n On success writes the position (AU) to `out_pos` (length 3) and the\n velocity (AU/day) to `out_vel` (length 3) — both solar-system\n barycenter (SSB) centered, ICRF."]
5226    pub unsafe fn empyrean_query_horizons_vectors(
5227        &self,
5228        command: *const ::std::os::raw::c_char,
5229        epoch_mjd_tdb: f64,
5230        cache_dir: *const ::std::os::raw::c_char,
5231        out_pos: *mut f64,
5232        out_vel: *mut f64,
5233    ) -> i32 {
5234        (self.empyrean_query_horizons_vectors)(command, epoch_mjd_tdb, cache_dir, out_pos, out_vel)
5235    }
5236    #[doc = " Query the MPC observations API for ADES records of one or more\n designations.\n\n `designations` is an array of `num_designations` null-terminated\n UTF-8 designations (e.g. `\"99942\"`, `\"2024 YR4\"`, `\"67P\"`). The\n MPC API returns ADES_DF JSON; this function parses each row into\n the C-ABI [`EmpyreanObservation`] struct, filling the full ADES\n schema (perm_id / prov_id / trk_sub / mode / sys / ctr / pos1-3 /\n rms_corr / mag / rms_mag / band / ast_cat / phot_cat / phot_ap /\n log_snr / seeing / exp / rms_fit / n_stars / notes / remarks) when\n present in the JSON.\n\n On success `*out_ptr` carries a heap-allocated array of length\n `*out_num`. Free with\n [`empyrean_observations_free`](crate::od::empyrean_observations_free)."]
5237    pub unsafe fn empyrean_query_observations(
5238        &self,
5239        designations: *const *const ::std::os::raw::c_char,
5240        num_designations: usize,
5241        cache_dir: *const ::std::os::raw::c_char,
5242        out_ptr: *mut *mut EmpyreanObservation,
5243        out_num: *mut usize,
5244    ) -> i32 {
5245        (self.empyrean_query_observations)(
5246            designations,
5247            num_designations,
5248            cache_dir,
5249            out_ptr,
5250            out_num,
5251        )
5252    }
5253    #[doc = " Query the JPL `sb_radar` API for delay/Doppler radar astrometry of one\n or more designations.\n\n `designations` is an array of `num_designations` null-terminated UTF-8\n designations (e.g. `\"99942\"`, `\"2024 YR4\"`). Asteroid radar astrometry\n is a JPL SSD product — it is **not** served by the MPC observations API\n (`empyrean_query_observations` returns only optical / occultation\n records), so radar ships as its own live-query entry point. JPL\n `sb_radar` JSON records are converted to ADES-native scott\n `RadarObservation`s and packed into the C-ABI\n [`EmpyreanRadarObservation`] struct (the same layout\n [`empyrean_read_ades`](crate::od::empyrean_read_ades) emits): the delay\n value is in seconds, its σ in microseconds, Doppler in Hz, frequency in\n MHz, and the `com` flag is a tri-state i8. `cache_dir` may be null to\n skip caching, or a directory path where `sb_radar` JSON responses are\n cached on disk.\n\n An object with no radar astrometry contributes no records (it is not an\n error). A JPL record that fails to parse (missing required field, or an\n unrecognised DSN station code) is rejected loudly rather than silently\n dropped — the whole call fails so no radar quietly goes missing.\n\n On success `*out_ptr` carries a heap-allocated array of length\n `*out_num`. Free with\n [`empyrean_radar_observations_free`](crate::od::empyrean_radar_observations_free)."]
5254    pub unsafe fn empyrean_query_radar(
5255        &self,
5256        designations: *const *const ::std::os::raw::c_char,
5257        num_designations: usize,
5258        cache_dir: *const ::std::os::raw::c_char,
5259        out_ptr: *mut *mut EmpyreanRadarObservation,
5260        out_num: *mut usize,
5261    ) -> i32 {
5262        (self.empyrean_query_radar)(designations, num_designations, cache_dir, out_ptr, out_num)
5263    }
5264    #[doc = " Construct a new orbit-determination session over a fixed\n observation set.\n\n Returns a heap-allocated handle on success, or null on error.\n The caller owns the returned pointer and must free it with\n [`empyrean_session_free`]."]
5265    pub unsafe fn empyrean_session_new(
5266        &self,
5267        observations: *const EmpyreanObservation,
5268        num_observations: usize,
5269        config: *const EmpyreanODConfig,
5270    ) -> *mut EmpyreanSession {
5271        (self.empyrean_session_new)(observations, num_observations, config)
5272    }
5273    #[doc = " Free a session previously returned by [`empyrean_session_new`].\n Passing null is a no-op."]
5274    pub unsafe fn empyrean_session_free(&self, session: *mut EmpyreanSession) {
5275        (self.empyrean_session_free)(session)
5276    }
5277    #[doc = " Total number of observations in the session (masked or not).\n Returns 0 if `session` is null."]
5278    pub unsafe fn empyrean_session_n_observations(&self, session: *const EmpyreanSession) -> usize {
5279        (self.empyrean_session_n_observations)(session)
5280    }
5281    #[doc = " Number of observations currently masked."]
5282    pub unsafe fn empyrean_session_n_masked(&self, session: *const EmpyreanSession) -> usize {
5283        (self.empyrean_session_n_masked)(session)
5284    }
5285    #[doc = " Number of observations active (not masked) in the next refine."]
5286    pub unsafe fn empyrean_session_n_active(&self, session: *const EmpyreanSession) -> usize {
5287        (self.empyrean_session_n_active)(session)
5288    }
5289    #[doc = " Mask the observation at `idx`. Returns 0 on success, -1 on null\n or out-of-bounds."]
5290    pub unsafe fn empyrean_session_mask(&self, session: *mut EmpyreanSession, idx: usize) -> i32 {
5291        (self.empyrean_session_mask)(session, idx)
5292    }
5293    #[doc = " Unmask the observation at `idx`. Returns 0 on success, -1 on null\n or out-of-bounds."]
5294    pub unsafe fn empyrean_session_unmask(&self, session: *mut EmpyreanSession, idx: usize) -> i32 {
5295        (self.empyrean_session_unmask)(session, idx)
5296    }
5297    #[doc = " Clear all masks. Returns 0 on success, -1 on null."]
5298    pub unsafe fn empyrean_session_unmask_all(&self, session: *mut EmpyreanSession) -> i32 {
5299        (self.empyrean_session_unmask_all)(session)
5300    }
5301    #[doc = " Whether the observation at `idx` is masked. Returns 1 = masked,\n 0 = active, 255 (-1 cast) on null/out-of-bounds."]
5302    pub unsafe fn empyrean_session_is_masked(
5303        &self,
5304        session: *const EmpyreanSession,
5305        idx: usize,
5306    ) -> u8 {
5307        (self.empyrean_session_is_masked)(session, idx)
5308    }
5309    #[doc = " Run an OD refine using the current mask state.\n\n On the first call, runs the full IOD → DC pipeline. On subsequent\n calls, uses the previously-fit orbit as the IOD seed (skipping the\n IOD step). Pushes the new fit onto the session's history.\n\n On success populates `result_out` with the latest fit. The caller\n must free `result_out` with [`empyrean_od_result_free`](crate::od::empyrean_od_result_free)."]
5310    pub unsafe fn empyrean_session_refine(
5311        &self,
5312        session: *mut EmpyreanSession,
5313        ctx: *const EmpyreanContext,
5314        result_out: *mut EmpyreanODResult,
5315    ) -> i32 {
5316        (self.empyrean_session_refine)(session, ctx, result_out)
5317    }
5318    #[doc = " Number of fits in the session history."]
5319    pub unsafe fn empyrean_session_history_len(&self, session: *const EmpyreanSession) -> usize {
5320        (self.empyrean_session_history_len)(session)
5321    }
5322    #[doc = " Copy the i-th history entry into `result_out`. Returns 0 on\n success, -1 on null/out-of-bounds. Caller frees `result_out` with\n [`empyrean_od_result_free`](crate::od::empyrean_od_result_free)."]
5323    pub unsafe fn empyrean_session_get_history(
5324        &self,
5325        session: *const EmpyreanSession,
5326        idx: usize,
5327        result_out: *mut EmpyreanODResult,
5328    ) -> i32 {
5329        (self.empyrean_session_get_history)(session, idx, result_out)
5330    }
5331    #[doc = " Diff the current fit against an earlier history entry. Returns 0\n on success, -1 if there is no current fit or `prior_idx` is out\n of bounds."]
5332    pub unsafe fn empyrean_session_diff(
5333        &self,
5334        session: *const EmpyreanSession,
5335        prior_idx: usize,
5336        diff_out: *mut EmpyreanSessionDiff,
5337    ) -> i32 {
5338        (self.empyrean_session_diff)(session, prior_idx, diff_out)
5339    }
5340    #[doc = " Query body states relative to a center body at given epochs.\n\n Returns 0 on success, negative error code on failure.\n On success, `result_out` is populated with body states.\n The caller must free the result with `empyrean_state_result_free()`."]
5341    pub unsafe fn empyrean_get_states(
5342        &self,
5343        ctx: *const EmpyreanContext,
5344        target_naif_id: i32,
5345        center_naif_id: i32,
5346        epochs_mjd_tdb: *const f64,
5347        num_epochs: usize,
5348        frame: i32,
5349        result_out: *mut EmpyreanStateResult,
5350    ) -> i32 {
5351        (self.empyrean_get_states)(
5352            ctx,
5353            target_naif_id,
5354            center_naif_id,
5355            epochs_mjd_tdb,
5356            num_epochs,
5357            frame,
5358            result_out,
5359        )
5360    }
5361    #[doc = " Free a state result previously returned by `empyrean_get_states()`.\n\n Passing a zeroed/null result is a no-op."]
5362    pub unsafe fn empyrean_state_result_free(&self, result: *mut EmpyreanStateResult) {
5363        (self.empyrean_state_result_free)(result)
5364    }
5365    #[doc = " Parse an ISO 8601 UTC string (e.g. ``\"2024-08-01T00:00:00.000Z\"``)\n to MJD in the requested target scale.\n\n `scale` is `0` for UTC, `1` for TDB.\n\n On success writes the MJD value to `*out_mjd` and returns 0.\n On failure returns a negative code; consult\n [`empyrean_last_error`](crate::empyrean_last_error)."]
5366    pub unsafe fn empyrean_iso_to_mjd(
5367        &self,
5368        iso: *const ::std::os::raw::c_char,
5369        scale: i32,
5370        out_mjd: *mut f64,
5371    ) -> i32 {
5372        (self.empyrean_iso_to_mjd)(iso, scale, out_mjd)
5373    }
5374    #[doc = " Format an MJD value (in the given scale) as an ISO 8601 UTC string.\n\n `scale` is `0` for UTC, `1` for TDB. Writes a null-terminated\n string of length ≤ `buf_len-1` into `out_buf`. A 32-byte buffer is\n always sufficient (typical output is 24 bytes:\n ``\"2024-08-01T00:00:00.000Z\"``).\n\n Returns 0 on success; negative on failure."]
5375    pub unsafe fn empyrean_mjd_to_iso(
5376        &self,
5377        mjd: f64,
5378        scale: i32,
5379        out_buf: *mut ::std::os::raw::c_char,
5380        buf_len: usize,
5381    ) -> i32 {
5382        (self.empyrean_mjd_to_iso)(mjd, scale, out_buf, buf_len)
5383    }
5384    #[doc = " Transform a coordinate state to a new representation, frame, and/or origin.\n\n Returns 0 on success or a negative error code on failure.\n Call `empyrean_last_error()` to retrieve the error message on failure."]
5385    pub unsafe fn empyrean_transform_coordinates(
5386        &self,
5387        ctx: *const EmpyreanContext,
5388        input: *const CoordinateState,
5389        target_representation: i32,
5390        target_frame: i32,
5391        target_origin: i32,
5392        output: *mut CoordinateState,
5393    ) -> i32 {
5394        (self.empyrean_transform_coordinates)(
5395            ctx,
5396            input,
5397            target_representation,
5398            target_frame,
5399            target_origin,
5400            output,
5401        )
5402    }
5403}