1use std::os::raw::{c_char, c_double, c_int};
15
16pub const SE_SUN: c_int = 0;
20pub const SE_MOON: c_int = 1;
21pub const SE_MERCURY: c_int = 2;
22pub const SE_VENUS: c_int = 3;
23pub const SE_MARS: c_int = 4;
24pub const SE_JUPITER: c_int = 5;
25pub const SE_SATURN: c_int = 6;
26pub const SE_URANUS: c_int = 7;
27pub const SE_NEPTUNE: c_int = 8;
28pub const SE_PLUTO: c_int = 9;
29pub const SE_MEAN_NODE: c_int = 10;
30pub const SE_TRUE_NODE: c_int = 11;
31pub const SE_MEAN_APOG: c_int = 12;
32pub const SE_OSCU_APOG: c_int = 13;
33pub const SE_EARTH: c_int = 14;
34pub const SE_CHIRON: c_int = 15;
35pub const SE_PHOLUS: c_int = 16;
36pub const SE_CERES: c_int = 17;
37pub const SE_PALLAS: c_int = 18;
38pub const SE_JUNO: c_int = 19;
39pub const SE_VESTA: c_int = 20;
40pub const SE_AST_OFFSET: c_int = 10000;
43
44pub const SE_JUL_CAL: c_int = 0;
48pub const SE_GREG_CAL: c_int = 1;
49
50pub const SEFLG_JPLEPH: c_int = 1;
54pub const SEFLG_SWIEPH: c_int = 2;
55pub const SEFLG_MOSEPH: c_int = 4;
56pub const SEFLG_EPHMASK: c_int = SEFLG_JPLEPH | SEFLG_SWIEPH | SEFLG_MOSEPH;
60pub const SEFLG_HELCTR: c_int = 8;
61pub const SEFLG_TRUEPOS: c_int = 16;
62pub const SEFLG_J2000: c_int = 32;
63pub const SEFLG_NONUT: c_int = 64;
64pub const SEFLG_SPEED3: c_int = 128;
65pub const SEFLG_SPEED: c_int = 256;
66pub const SEFLG_NOGDEFL: c_int = 512;
67pub const SEFLG_NOABERR: c_int = 1024;
68pub const SEFLG_ASTROMETRIC: c_int = SEFLG_NOABERR | SEFLG_NOGDEFL;
69pub const SEFLG_EQUATORIAL: c_int = 2048;
70pub const SEFLG_XYZ: c_int = 4096;
71pub const SEFLG_RADIANS: c_int = 8192;
72pub const SEFLG_BARYCTR: c_int = 16384;
73pub const SEFLG_TOPOCTR: c_int = 32768;
74pub const SEFLG_SIDEREAL: c_int = 65536;
75
76pub const SE_SIDM_FAGAN_BRADLEY: c_int = 0;
80pub const SE_SIDM_LAHIRI: c_int = 1;
81pub const SE_SIDM_DELUCE: c_int = 2;
82pub const SE_SIDM_RAMAN: c_int = 3;
83pub const SE_SIDM_KRISHNAMURTI: c_int = 5;
84
85pub const SE_ECL_CENTRAL: c_int = 1;
89pub const SE_ECL_NONCENTRAL: c_int = 2;
90pub const SE_ECL_TOTAL: c_int = 4;
91pub const SE_ECL_ANNULAR: c_int = 8;
92pub const SE_ECL_PARTIAL: c_int = 16;
93pub const SE_ECL_ANNULAR_TOTAL: c_int = 32;
94pub const SE_ECL_PENUMBRAL: c_int = 64;
95
96pub const SE_MAX_STNAME: usize = 256;
98
99extern "C" {
100 pub fn swe_set_ephe_path(path: *const c_char);
101 pub fn swe_close();
102 pub fn swe_version(svers: *mut c_char) -> *mut c_char;
103
104 pub fn swe_calc_ut(
105 tjd_ut: c_double,
106 ipl: c_int,
107 iflag: c_int,
108 xx: *mut c_double,
109 serr: *mut c_char,
110 ) -> c_int;
111
112 pub fn swe_calc(
113 tjd_et: c_double,
114 ipl: c_int,
115 iflag: c_int,
116 xx: *mut c_double,
117 serr: *mut c_char,
118 ) -> c_int;
119
120 pub fn swe_get_planet_name(ipl: c_int, name: *mut c_char) -> *mut c_char;
121
122 pub fn swe_julday(
123 year: c_int,
124 month: c_int,
125 day: c_int,
126 hour: c_double,
127 gregflag: c_int,
128 ) -> c_double;
129
130 pub fn swe_revjul(
131 jd: c_double,
132 gregflag: c_int,
133 jyear: *mut c_int,
134 jmon: *mut c_int,
135 jday: *mut c_int,
136 jut: *mut c_double,
137 );
138
139 pub fn swe_utc_to_jd(
140 iyear: c_int,
141 imonth: c_int,
142 iday: c_int,
143 ihour: c_int,
144 imin: c_int,
145 dsec: c_double,
146 gregflag: c_int,
147 dret: *mut c_double,
148 serr: *mut c_char,
149 ) -> c_int;
150
151 pub fn swe_deltat(tjd: c_double) -> c_double;
152
153 pub fn swe_houses(
154 tjd_ut: c_double,
155 geolat: c_double,
156 geolon: c_double,
157 hsys: c_int,
158 cusps: *mut c_double,
159 ascmc: *mut c_double,
160 ) -> c_int;
161
162 pub fn swe_houses_ex(
163 tjd_ut: c_double,
164 iflag: c_int,
165 geolat: c_double,
166 geolon: c_double,
167 hsys: c_int,
168 cusps: *mut c_double,
169 ascmc: *mut c_double,
170 ) -> c_int;
171
172 pub fn swe_house_name(hsys: c_int) -> *const c_char;
173
174 pub fn swe_set_topo(geolon: c_double, geolat: c_double, geoalt: c_double);
175
176 pub fn swe_set_sid_mode(sid_mode: c_int, t0: c_double, ayan_t0: c_double);
177
178 pub fn swe_get_ayanamsa_ex_ut(
179 tjd_ut: c_double,
180 iflag: c_int,
181 daya: *mut c_double,
182 serr: *mut c_char,
183 ) -> c_int;
184
185 pub fn swe_sol_eclipse_when_glob(
186 tjd_start: c_double,
187 ifl: c_int,
188 ifltype: c_int,
189 tret: *mut c_double,
190 backward: c_int,
191 serr: *mut c_char,
192 ) -> c_int;
193
194 pub fn swe_lun_eclipse_when(
195 tjd_start: c_double,
196 ifl: c_int,
197 ifltype: c_int,
198 tret: *mut c_double,
199 backward: c_int,
200 serr: *mut c_char,
201 ) -> c_int;
202}
203
204#[cfg(test)]
205mod tests {
206 use super::*;
207
208 static TEST_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());
212
213 #[test]
214 fn julday_j2000() {
215 let _guard = TEST_LOCK.lock().unwrap();
216 let jd = unsafe { swe_julday(2000, 1, 1, 12.0, SE_GREG_CAL) };
217 assert!((jd - 2451545.0).abs() < 0.0001, "JD was {jd}");
218 }
219
220 #[test]
221 fn calc_sun_position() {
222 let _guard = TEST_LOCK.lock().unwrap();
223 unsafe {
224 let jd = swe_julday(2000, 1, 1, 12.0, SE_GREG_CAL);
225 let mut xx = [0.0_f64; 6];
226 let mut serr = [0i8; SE_MAX_STNAME];
227 let ret = swe_calc_ut(
228 jd,
229 SE_SUN,
230 SEFLG_SPEED | SEFLG_SWIEPH,
231 xx.as_mut_ptr(),
232 serr.as_mut_ptr().cast(),
233 );
234 assert!(ret >= 0, "swe_calc_ut failed: {ret}");
235 let sun_lon = xx[0];
236 assert!(
237 sun_lon > 270.0 && sun_lon < 290.0,
238 "Sun longitude was {sun_lon}"
239 );
240 }
241 }
242
243 #[test]
244 fn version_string() {
245 let _guard = TEST_LOCK.lock().unwrap();
246 let mut buf = [0i8; SE_MAX_STNAME];
247 let s = unsafe {
248 swe_version(buf.as_mut_ptr().cast());
249 std::ffi::CStr::from_ptr(buf.as_ptr().cast())
250 .to_string_lossy()
251 .into_owned()
252 };
253 assert!(s.starts_with("2.10"), "unexpected version: {s}");
254 }
255}