@typescriptify/sweph 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/README.md +422 -0
  2. package/ephe/semo_18.se1 +0 -0
  3. package/ephe/sepl_18.se1 +0 -0
  4. package/originalCode/.eslintrc.json +124 -0
  5. package/originalCode/.gitattributes +2 -0
  6. package/originalCode/.github/FUNDING.yml +5 -0
  7. package/originalCode/.github/workflows/test.yml +35 -0
  8. package/originalCode/LICENSE +840 -0
  9. package/originalCode/README.md +91 -0
  10. package/originalCode/binding.gyp +41 -0
  11. package/originalCode/constants.js +366 -0
  12. package/originalCode/docs.gif +0 -0
  13. package/originalCode/index.d.ts +5115 -0
  14. package/originalCode/index.js +7 -0
  15. package/originalCode/index.mjs +109 -0
  16. package/originalCode/package.json +55 -0
  17. package/originalCode/src/functions/azalt.cpp +39 -0
  18. package/originalCode/src/functions/azalt_rev.cpp +35 -0
  19. package/originalCode/src/functions/calc.cpp +29 -0
  20. package/originalCode/src/functions/calc_pctr.cpp +31 -0
  21. package/originalCode/src/functions/calc_ut.cpp +29 -0
  22. package/originalCode/src/functions/close.cpp +6 -0
  23. package/originalCode/src/functions/cotrans.cpp +26 -0
  24. package/originalCode/src/functions/cotrans_sp.cpp +26 -0
  25. package/originalCode/src/functions/cs2degstr.cpp +19 -0
  26. package/originalCode/src/functions/cs2lonlatstr.cpp +23 -0
  27. package/originalCode/src/functions/cs2timestr.cpp +23 -0
  28. package/originalCode/src/functions/csnorm.cpp +15 -0
  29. package/originalCode/src/functions/csroundsec.cpp +15 -0
  30. package/originalCode/src/functions/d2l.cpp +15 -0
  31. package/originalCode/src/functions/date_conversion.cpp +30 -0
  32. package/originalCode/src/functions/day_of_week.cpp +15 -0
  33. package/originalCode/src/functions/degnorm.cpp +15 -0
  34. package/originalCode/src/functions/deltat.cpp +15 -0
  35. package/originalCode/src/functions/deltat_ex.cpp +24 -0
  36. package/originalCode/src/functions/difcs2n.cpp +19 -0
  37. package/originalCode/src/functions/difcsn.cpp +19 -0
  38. package/originalCode/src/functions/difdeg2n.cpp +19 -0
  39. package/originalCode/src/functions/difdegn.cpp +19 -0
  40. package/originalCode/src/functions/fixstar.cpp +32 -0
  41. package/originalCode/src/functions/fixstar2.cpp +32 -0
  42. package/originalCode/src/functions/fixstar2_mag.cpp +28 -0
  43. package/originalCode/src/functions/fixstar2_ut.cpp +32 -0
  44. package/originalCode/src/functions/fixstar_mag.cpp +28 -0
  45. package/originalCode/src/functions/fixstar_ut.cpp +32 -0
  46. package/originalCode/src/functions/gauquelin_sector.cpp +44 -0
  47. package/originalCode/src/functions/get_ayanamsa.cpp +15 -0
  48. package/originalCode/src/functions/get_ayanamsa_ex.cpp +27 -0
  49. package/originalCode/src/functions/get_ayanamsa_ex_ut.cpp +27 -0
  50. package/originalCode/src/functions/get_ayanamsa_name.cpp +19 -0
  51. package/originalCode/src/functions/get_ayanamsa_ut.cpp +15 -0
  52. package/originalCode/src/functions/get_current_file_data.cpp +28 -0
  53. package/originalCode/src/functions/get_library_path.cpp +8 -0
  54. package/originalCode/src/functions/get_orbital_elements.cpp +29 -0
  55. package/originalCode/src/functions/get_planet_name.cpp +19 -0
  56. package/originalCode/src/functions/get_tid_acc.cpp +7 -0
  57. package/originalCode/src/functions/heliacal_pheno_ut.cpp +52 -0
  58. package/originalCode/src/functions/heliacal_ut.cpp +52 -0
  59. package/originalCode/src/functions/helio_cross.cpp +33 -0
  60. package/originalCode/src/functions/helio_cross_ut.cpp +33 -0
  61. package/originalCode/src/functions/house_name.cpp +20 -0
  62. package/originalCode/src/functions/house_pos.cpp +36 -0
  63. package/originalCode/src/functions/houses.cpp +35 -0
  64. package/originalCode/src/functions/houses_armc.cpp +38 -0
  65. package/originalCode/src/functions/houses_armc_ex2.cpp +47 -0
  66. package/originalCode/src/functions/houses_ex.cpp +37 -0
  67. package/originalCode/src/functions/houses_ex2.cpp +46 -0
  68. package/originalCode/src/functions/jdet_to_utc.cpp +38 -0
  69. package/originalCode/src/functions/jdut1_to_utc.cpp +38 -0
  70. package/originalCode/src/functions/julday.cpp +25 -0
  71. package/originalCode/src/functions/lat_to_lmt.cpp +27 -0
  72. package/originalCode/src/functions/lmt_to_lat.cpp +27 -0
  73. package/originalCode/src/functions/lun_eclipse_how.cpp +34 -0
  74. package/originalCode/src/functions/lun_eclipse_when.cpp +31 -0
  75. package/originalCode/src/functions/lun_eclipse_when_loc.cpp +39 -0
  76. package/originalCode/src/functions/lun_occult_when_glob.cpp +35 -0
  77. package/originalCode/src/functions/lun_occult_when_loc.cpp +43 -0
  78. package/originalCode/src/functions/lun_occult_where.cpp +34 -0
  79. package/originalCode/src/functions/mooncross.cpp +26 -0
  80. package/originalCode/src/functions/mooncross_node.cpp +30 -0
  81. package/originalCode/src/functions/mooncross_node_ut.cpp +30 -0
  82. package/originalCode/src/functions/mooncross_ut.cpp +26 -0
  83. package/originalCode/src/functions/nod_aps.cpp +42 -0
  84. package/originalCode/src/functions/nod_aps_ut.cpp +42 -0
  85. package/originalCode/src/functions/orbit_max_min_true_distance.cpp +37 -0
  86. package/originalCode/src/functions/pheno.cpp +29 -0
  87. package/originalCode/src/functions/pheno_ut.cpp +29 -0
  88. package/originalCode/src/functions/radnorm.cpp +15 -0
  89. package/originalCode/src/functions/refrac.cpp +23 -0
  90. package/originalCode/src/functions/refrac_extended.cpp +32 -0
  91. package/originalCode/src/functions/revjul.cpp +33 -0
  92. package/originalCode/src/functions/rise_trans.cpp +44 -0
  93. package/originalCode/src/functions/rise_trans_true_hor.cpp +46 -0
  94. package/originalCode/src/functions/set_delta_t_userdef.cpp +14 -0
  95. package/originalCode/src/functions/set_ephe_path.cpp +14 -0
  96. package/originalCode/src/functions/set_jpl_file.cpp +14 -0
  97. package/originalCode/src/functions/set_sid_mode.cpp +20 -0
  98. package/originalCode/src/functions/set_tid_acc.cpp +14 -0
  99. package/originalCode/src/functions/set_topo.cpp +20 -0
  100. package/originalCode/src/functions/sidtime.cpp +15 -0
  101. package/originalCode/src/functions/sidtime0.cpp +21 -0
  102. package/originalCode/src/functions/sol_eclipse_how.cpp +34 -0
  103. package/originalCode/src/functions/sol_eclipse_when_glob.cpp +31 -0
  104. package/originalCode/src/functions/sol_eclipse_when_loc.cpp +39 -0
  105. package/originalCode/src/functions/sol_eclipse_where.cpp +30 -0
  106. package/originalCode/src/functions/solcross.cpp +26 -0
  107. package/originalCode/src/functions/solcross_ut.cpp +26 -0
  108. package/originalCode/src/functions/split_deg.cpp +35 -0
  109. package/originalCode/src/functions/time_equ.cpp +25 -0
  110. package/originalCode/src/functions/utc_time_zone.cpp +48 -0
  111. package/originalCode/src/functions/utc_to_jd.cpp +37 -0
  112. package/originalCode/src/functions/version.cpp +8 -0
  113. package/originalCode/src/functions/vis_limit_mag.cpp +50 -0
  114. package/originalCode/src/sweph.cpp +150 -0
  115. package/originalCode/src/sweph.h +119 -0
  116. package/originalCode/swisseph/swecl.c +6428 -0
  117. package/originalCode/swisseph/swedate.c +588 -0
  118. package/originalCode/swisseph/swedate.h +81 -0
  119. package/originalCode/swisseph/swehel.c +3511 -0
  120. package/originalCode/swisseph/swehouse.c +3143 -0
  121. package/originalCode/swisseph/swehouse.h +98 -0
  122. package/originalCode/swisseph/swejpl.c +958 -0
  123. package/originalCode/swisseph/swejpl.h +103 -0
  124. package/originalCode/swisseph/swemmoon.c +1930 -0
  125. package/originalCode/swisseph/swemplan.c +967 -0
  126. package/originalCode/swisseph/swemptab.h +10640 -0
  127. package/originalCode/swisseph/swenut2000a.h +2819 -0
  128. package/originalCode/swisseph/sweodef.h +326 -0
  129. package/originalCode/swisseph/sweph.c +8614 -0
  130. package/originalCode/swisseph/sweph.h +849 -0
  131. package/originalCode/swisseph/swephexp.h +1020 -0
  132. package/originalCode/swisseph/swephlib.c +4634 -0
  133. package/originalCode/swisseph/swephlib.h +189 -0
  134. package/package.json +28 -0
  135. package/scripts/gen-swemptab.js +177 -0
  136. package/scripts/gen-swenut2000a.js +106 -0
  137. package/src/SwissEph/README.md +268 -0
  138. package/src/SwissEph/UseCases/Ayanamsa.md +363 -0
  139. package/src/SwissEph/UseCases/AzimuthAltitude.md +408 -0
  140. package/src/SwissEph/UseCases/CoordinateSystems.md +337 -0
  141. package/src/SwissEph/UseCases/DateAndTime.md +368 -0
  142. package/src/SwissEph/UseCases/DeltaT.md +258 -0
  143. package/src/SwissEph/UseCases/EphemerisFiles.md +338 -0
  144. package/src/SwissEph/UseCases/FixedStars.md +300 -0
  145. package/src/SwissEph/UseCases/GauquelinSectors.md +304 -0
  146. package/src/SwissEph/UseCases/HeliacalEvents.md +396 -0
  147. package/src/SwissEph/UseCases/HelioCrossings.md +325 -0
  148. package/src/SwissEph/UseCases/HousePosition.md +254 -0
  149. package/src/SwissEph/UseCases/HouseSystems.md +279 -0
  150. package/src/SwissEph/UseCases/LunarEclipse.md +326 -0
  151. package/src/SwissEph/UseCases/MeridianTransit.md +279 -0
  152. package/src/SwissEph/UseCases/MoonCrossings.md +373 -0
  153. package/src/SwissEph/UseCases/NodesAndApsides.md +307 -0
  154. package/src/SwissEph/UseCases/Occultation.md +352 -0
  155. package/src/SwissEph/UseCases/OrbitalElements.md +469 -0
  156. package/src/SwissEph/UseCases/Phenomena.md +328 -0
  157. package/src/SwissEph/UseCases/PlanetPositions.md +366 -0
  158. package/src/SwissEph/UseCases/Planetocentric.md +278 -0
  159. package/src/SwissEph/UseCases/Refraction.md +314 -0
  160. package/src/SwissEph/UseCases/RiseAndSet.md +433 -0
  161. package/src/SwissEph/UseCases/SiderealTime.md +302 -0
  162. package/src/SwissEph/UseCases/SolarEclipse.md +379 -0
  163. package/src/SwissEph/UseCases/SunCrossings.md +275 -0
  164. package/src/SwissEph/UseCases/TopocentricCorrection.md +335 -0
  165. package/src/SwissEph/errors.ts +10 -0
  166. package/src/SwissEph/index.ts +823 -0
  167. package/src/SwissEph/types.ts +291 -0
  168. package/src/constants.ts +762 -0
  169. package/src/file-reader.ts +147 -0
  170. package/src/index.ts +10 -0
  171. package/src/swecl.ts +4526 -0
  172. package/src/swedate.ts +376 -0
  173. package/src/swehel.ts +1939 -0
  174. package/src/swehouse.ts +2167 -0
  175. package/src/swejpl.ts +470 -0
  176. package/src/swemmoon.ts +1318 -0
  177. package/src/swemplan.ts +585 -0
  178. package/src/swemptab.ts +4448 -0
  179. package/src/swenut2000a.ts +2763 -0
  180. package/src/sweph.ts +3993 -0
  181. package/src/swephlib.ts +2720 -0
  182. package/src/types.ts +490 -0
  183. package/tests/c-style/ayanamsa.test.ts +63 -0
  184. package/tests/c-style/config.test.ts +96 -0
  185. package/tests/c-style/crossings.test.ts +81 -0
  186. package/tests/c-style/date-time.test.ts +114 -0
  187. package/tests/c-style/eclipses.test.ts +84 -0
  188. package/tests/c-style/fixed-stars.test.ts +66 -0
  189. package/tests/c-style/heliacal.test.ts +34 -0
  190. package/tests/c-style/houses.test.ts +135 -0
  191. package/tests/c-style/math-utils.test.ts +160 -0
  192. package/tests/c-style/orbital.test.ts +78 -0
  193. package/tests/c-style/phenomena.test.ts +42 -0
  194. package/tests/c-style/planetocentric.test.ts +26 -0
  195. package/tests/c-style/planets.test.ts +117 -0
  196. package/tests/c-style/rise-set.test.ts +71 -0
  197. package/tests/helpers.ts +21 -0
  198. package/tests/modern/ayanamsa.test.ts +47 -0
  199. package/tests/modern/calc.test.ts +113 -0
  200. package/tests/modern/config.test.ts +46 -0
  201. package/tests/modern/crossings.test.ts +45 -0
  202. package/tests/modern/eclipses.test.ts +81 -0
  203. package/tests/modern/errors.test.ts +71 -0
  204. package/tests/modern/heliacal.test.ts +30 -0
  205. package/tests/modern/houses.test.ts +87 -0
  206. package/tests/modern/orbital.test.ts +79 -0
  207. package/tests/modern/phenomena.test.ts +41 -0
  208. package/tests/modern/rise-set.test.ts +60 -0
  209. package/tests/modern/statics.test.ts +99 -0
  210. package/tests/modern/utilities.test.ts +70 -0
  211. package/tsconfig.json +20 -0
package/src/swejpl.ts ADDED
@@ -0,0 +1,470 @@
1
+ /*************************************************************
2
+ * swejpl.ts — JPL binary ephemeris reader
3
+ * Translated from swejpl.c
4
+ *
5
+ * Reads JPL DE binary files (DE200–DE441). Provides Chebyshev
6
+ * interpolation of planetary positions from JPL ephemeris data.
7
+ *
8
+ * Copyright (C) 1997 - 2021 Astrodienst AG, Switzerland. (AGPL)
9
+ *************************************************************/
10
+
11
+ import { SE1FileReader } from './file-reader';
12
+ import {
13
+ OK, ERR, NOT_AVAILABLE, BEYOND_EPH_LIMITS,
14
+ J_MERCURY, J_VENUS, J_EARTH, J_MARS, J_JUPITER,
15
+ J_SATURN, J_URANUS, J_NEPTUNE, J_PLUTO,
16
+ J_MOON, J_SUN, J_SBARY, J_EMB, J_NUT, J_LIB,
17
+ AS_MAXCH,
18
+ } from './constants';
19
+
20
+ import type { SweData, JplSave } from './types';
21
+ import { createJplSave } from './types';
22
+
23
+ /* ================================================================
24
+ * fsizer: read header and determine record size (ksize)
25
+ * ================================================================ */
26
+ function fsizer(js: JplSave, serr: string[]): number {
27
+ const reader = js.jplReader!;
28
+ reader.seekSet(0);
29
+ /* ttl = ephemeris title (252 bytes) */
30
+ if (reader.length < 252) { serr[0] = 'JPL file too short'; return NOT_AVAILABLE; }
31
+ reader.seekCur(252);
32
+ /* cnam = names of constants (6*400 = 2400 bytes) */
33
+ if (reader.position + 2400 > reader.length) { serr[0] = 'JPL file too short'; return NOT_AVAILABLE; }
34
+ const cnamBytes = reader.readBytes(2400);
35
+ js.chCnam = new TextDecoder('ascii').decode(cnamBytes);
36
+ /* ss[0..2]: start, end, segment size */
37
+ if (reader.position + 24 > reader.length) { serr[0] = 'JPL file too short'; return NOT_AVAILABLE; }
38
+ const ss0 = reader.readFloat64();
39
+ const ss1 = reader.readFloat64();
40
+ const ss2 = reader.readFloat64();
41
+ /* detect endianness from ss[2] (segment size must be 1..200) */
42
+ if (ss2 < 1 || ss2 > 200) {
43
+ /* try opposite endianness */
44
+ reader.setLittleEndian(!reader.isLittleEndian);
45
+ reader.seekSet(252 + 2400);
46
+ const ss0r = reader.readFloat64();
47
+ const ss1r = reader.readFloat64();
48
+ const ss2r = reader.readFloat64();
49
+ if (ss2r < 1 || ss2r > 200) {
50
+ serr[0] = 'alleged ephemeris file has invalid format.';
51
+ return NOT_AVAILABLE;
52
+ }
53
+ js.ehSs[0] = ss0r; js.ehSs[1] = ss1r; js.ehSs[2] = ss2r;
54
+ } else {
55
+ js.ehSs[0] = ss0; js.ehSs[1] = ss1; js.ehSs[2] = ss2;
56
+ }
57
+ /* plausibility check */
58
+ if (js.ehSs[0] < -5583942 || js.ehSs[1] > 9025909 || js.ehSs[2] < 1 || js.ehSs[2] > 200) {
59
+ serr[0] = 'alleged ephemeris file has invalid format.';
60
+ return NOT_AVAILABLE;
61
+ }
62
+ /* ncon */
63
+ if (reader.position + 4 > reader.length) return NOT_AVAILABLE;
64
+ const ncon = reader.readInt32();
65
+ /* au */
66
+ if (reader.position + 8 > reader.length) return NOT_AVAILABLE;
67
+ const au = reader.readFloat64();
68
+ /* emrat */
69
+ if (reader.position + 8 > reader.length) return NOT_AVAILABLE;
70
+ const emrat = reader.readFloat64();
71
+ /* ipt[0..35] */
72
+ if (reader.position + 36 * 4 > reader.length) return NOT_AVAILABLE;
73
+ for (let i = 0; i < 36; i++) js.ehIpt[i] = reader.readInt32();
74
+ /* numde */
75
+ if (reader.position + 4 > reader.length) return NOT_AVAILABLE;
76
+ const numde = reader.readInt32();
77
+ /* lpt[0..2] (librations) */
78
+ if (reader.position + 12 > reader.length) return NOT_AVAILABLE;
79
+ const lpt0 = reader.readInt32();
80
+ const lpt1 = reader.readInt32();
81
+ const lpt2 = reader.readInt32();
82
+ js.ehIpt[36] = lpt0;
83
+ js.ehIpt[37] = lpt1;
84
+ js.ehIpt[38] = lpt2;
85
+ /* compute ksize from pointers */
86
+ let kmx = 0;
87
+ let khi = 0;
88
+ for (let i = 0; i < 13; i++) {
89
+ if (js.ehIpt[i * 3] > kmx) {
90
+ kmx = js.ehIpt[i * 3];
91
+ khi = i + 1;
92
+ }
93
+ }
94
+ const nd = (khi === 12) ? 2 : 3;
95
+ let ksize = (js.ehIpt[khi * 3 - 3] + nd * js.ehIpt[khi * 3 - 2] * js.ehIpt[khi * 3 - 1] - 1) * 2;
96
+ /* de102 fix */
97
+ if (ksize === 1546) ksize = 1652;
98
+ if (ksize < 1000 || ksize > 5000) {
99
+ serr[0] = `JPL ephemeris file does not provide valid ksize (${ksize})`;
100
+ return NOT_AVAILABLE;
101
+ }
102
+ return ksize;
103
+ }
104
+
105
+ /* ================================================================
106
+ * interp: Chebyshev interpolation (position, velocity, acceleration, jerk)
107
+ * ================================================================ */
108
+ function interp(
109
+ buf: Float64Array, bufOff: number,
110
+ t: number, intv: number,
111
+ ncfin: number, ncmin: number, nain: number, ifl: number,
112
+ pv: Float64Array, pvOff: number,
113
+ js: JplSave,
114
+ ): void {
115
+ const pc = js.pc;
116
+ const vc = js.vc;
117
+ const ac = js.ac;
118
+ const jc = js.jc;
119
+ const ncf = ncfin;
120
+ const ncm = ncmin;
121
+ const na = nain;
122
+ /* get correct sub-interval number and normalized chebyshev time */
123
+ const dt1 = t >= 0 ? Math.floor(t) : -Math.floor(-t);
124
+ const temp = na * t;
125
+ const ni = Math.trunc(temp - dt1);
126
+ /* tc is the normalized chebyshev time (-1 <= tc <= 1) */
127
+ const tc = (((temp % 1.0) + 1.0) % 1.0 + dt1) * 2.0 - 1.0;
128
+ /* check if chebyshev time has changed */
129
+ if (tc !== pc[1]) {
130
+ js.interpNp = 2;
131
+ js.interpNv = 3;
132
+ js.interpNac = 4;
133
+ js.interpNjk = 5;
134
+ pc[1] = tc;
135
+ js.interpTwot = tc + tc;
136
+ }
137
+ const twot = js.interpTwot;
138
+ /* evaluate chebyshev polynomials */
139
+ if (js.interpNp < ncf) {
140
+ for (let i = js.interpNp; i < ncf; i++) {
141
+ pc[i] = twot * pc[i - 1] - pc[i - 2];
142
+ }
143
+ js.interpNp = ncf;
144
+ }
145
+ /* interpolate position for each component */
146
+ for (let i = 0; i < ncm; i++) {
147
+ pv[pvOff + i] = 0;
148
+ for (let j = ncf - 1; j >= 0; j--) {
149
+ pv[pvOff + i] += pc[j] * buf[bufOff + j + (i + ni * ncm) * ncf];
150
+ }
151
+ }
152
+ if (ifl <= 1) return;
153
+ /* velocity */
154
+ const bma = (na + na) / intv;
155
+ vc[2] = twot + twot;
156
+ if (js.interpNv < ncf) {
157
+ for (let i = js.interpNv; i < ncf; i++) {
158
+ vc[i] = twot * vc[i - 1] + pc[i - 1] + pc[i - 1] - vc[i - 2];
159
+ }
160
+ js.interpNv = ncf;
161
+ }
162
+ for (let i = 0; i < ncm; i++) {
163
+ pv[pvOff + i + ncm] = 0;
164
+ for (let j = ncf - 1; j >= 1; j--) {
165
+ pv[pvOff + i + ncm] += vc[j] * buf[bufOff + j + (i + ni * ncm) * ncf];
166
+ }
167
+ pv[pvOff + i + ncm] *= bma;
168
+ }
169
+ if (ifl === 2) return;
170
+ /* acceleration */
171
+ const bma2 = bma * bma;
172
+ ac[3] = pc[1] * 24.0;
173
+ if (js.interpNac < ncf) {
174
+ for (let i = js.interpNac; i < ncf; i++) {
175
+ ac[i] = twot * ac[i - 1] + vc[i - 1] * 4.0 - ac[i - 2];
176
+ }
177
+ js.interpNac = ncf;
178
+ }
179
+ for (let i = 0; i < ncm; i++) {
180
+ pv[pvOff + i + ncm * 2] = 0;
181
+ for (let j = ncf - 1; j >= 2; j--) {
182
+ pv[pvOff + i + ncm * 2] += ac[j] * buf[bufOff + j + (i + ni * ncm) * ncf];
183
+ }
184
+ pv[pvOff + i + ncm * 2] *= bma2;
185
+ }
186
+ if (ifl === 3) return;
187
+ /* jerk */
188
+ const bma3 = bma * bma2;
189
+ jc[4] = pc[1] * 192.0;
190
+ if (js.interpNjk < ncf) {
191
+ for (let i = js.interpNjk; i < ncf; i++) {
192
+ jc[i] = twot * jc[i - 1] + ac[i - 1] * 6.0 - jc[i - 2];
193
+ }
194
+ js.interpNjk = ncf;
195
+ }
196
+ for (let i = 0; i < ncm; i++) {
197
+ pv[pvOff + i + ncm * 3] = 0;
198
+ for (let j = ncf - 1; j >= 3; j--) {
199
+ pv[pvOff + i + ncm * 3] += jc[j] * buf[bufOff + j + (i + ni * ncm) * ncf];
200
+ }
201
+ pv[pvOff + i + ncm * 3] *= bma3;
202
+ }
203
+ }
204
+
205
+ /* ================================================================
206
+ * state: main read/interpolate engine
207
+ * ================================================================ */
208
+ function state(
209
+ et: number, list: Int32Array | null, doBary: boolean,
210
+ pv: Float64Array, pvsun: Float64Array, nut: Float64Array | null,
211
+ js: JplSave, serr: string[],
212
+ ): number {
213
+ const reader = js.jplReader!;
214
+ const buf = js.buf;
215
+ const ipt = js.ehIpt;
216
+ if (js.stateIrecsz === 0) {
217
+ /* first call: read header */
218
+ const ksize = fsizer(js, serr);
219
+ if (ksize === NOT_AVAILABLE) return NOT_AVAILABLE;
220
+ const nrecl = 4;
221
+ js.stateIrecsz = nrecl * ksize;
222
+ js.stateNcoeffs = Math.trunc(ksize / 2);
223
+ /* re-read header from beginning */
224
+ reader.seekSet(0);
225
+ /* ttl */
226
+ reader.seekCur(252);
227
+ /* cnam */
228
+ const cnamBytes = reader.readBytes(2400);
229
+ js.chCnam = new TextDecoder('ascii').decode(cnamBytes);
230
+ /* ss */
231
+ js.ehSs[0] = reader.readFloat64();
232
+ js.ehSs[1] = reader.readFloat64();
233
+ js.ehSs[2] = reader.readFloat64();
234
+ /* ncon */
235
+ js.ehNcon = reader.readInt32();
236
+ /* au */
237
+ js.ehAu = reader.readFloat64();
238
+ /* emrat */
239
+ js.ehEmrat = reader.readFloat64();
240
+ /* ipt[0..35] */
241
+ for (let i = 0; i < 36; i++) ipt[i] = reader.readInt32();
242
+ /* denum */
243
+ js.ehDenum = reader.readInt32();
244
+ /* lpt */
245
+ js.stateLpt[0] = reader.readInt32();
246
+ js.stateLpt[1] = reader.readInt32();
247
+ js.stateLpt[2] = reader.readInt32();
248
+ /* cval: constants in second record */
249
+ reader.seekSet(js.stateIrecsz);
250
+ for (let i = 0; i < 400; i++) js.ehCval[i] = reader.readFloat64();
251
+ /* fill librations */
252
+ for (let i = 0; i < 3; i++) ipt[i + 36] = js.stateLpt[i];
253
+ js.stateNrl = 0;
254
+ /* verify file length */
255
+ const flen = reader.length;
256
+ const nseg = Math.trunc((js.ehSs[1] - js.ehSs[0]) / js.ehSs[2]);
257
+ let nb = 0;
258
+ for (let i = 0; i < 13; i++) {
259
+ const k = (i === 11) ? 2 : 3;
260
+ nb += (ipt[i * 3 + 1] * ipt[i * 3 + 2]) * k * nseg;
261
+ }
262
+ nb += 2 * nseg;
263
+ nb *= 8;
264
+ nb += 2 * ksize * nrecl;
265
+ if (flen !== nb && flen - nb !== ksize * nrecl) {
266
+ serr[0] = `JPL ephemeris file is mutilated; length = ${flen} instead of ${nb}.`;
267
+ return NOT_AVAILABLE;
268
+ }
269
+ /* verify start/end dates in segments */
270
+ reader.seekSet(2 * js.stateIrecsz);
271
+ const ts0 = reader.readFloat64();
272
+ reader.readFloat64(); // skip
273
+ reader.seekSet((nseg + 2 - 1) * js.stateIrecsz);
274
+ reader.readFloat64(); // skip
275
+ const ts3 = reader.readFloat64();
276
+ if (ts0 !== js.ehSs[0] || ts3 !== js.ehSs[1]) {
277
+ serr[0] = `JPL ephemeris file is corrupt; start/end date check failed. ${ts0} != ${js.ehSs[0]} || ${ts3} != ${js.ehSs[1]}`;
278
+ return NOT_AVAILABLE;
279
+ }
280
+ }
281
+ if (list === null) return OK;
282
+ const s = et - 0.5;
283
+ const etMn = Math.floor(s) + 0.5;
284
+ const etFr = s - Math.floor(s);
285
+ /* error if out of range */
286
+ if (et < js.ehSs[0] || et > js.ehSs[1]) {
287
+ serr[0] = `jd ${et} outside JPL eph. range ${js.ehSs[0].toFixed(2)} .. ${js.ehSs[1].toFixed(2)};`;
288
+ return BEYOND_EPH_LIMITS;
289
+ }
290
+ /* calculate record number and relative time */
291
+ let nr = Math.trunc((etMn - js.ehSs[0]) / js.ehSs[2]) + 2;
292
+ if (etMn === js.ehSs[1]) nr--;
293
+ const t = (etMn - ((nr - 2) * js.ehSs[2] + js.ehSs[0]) + etFr) / js.ehSs[2];
294
+ /* read correct record if not already in buffer */
295
+ if (nr !== js.stateNrl) {
296
+ js.stateNrl = nr;
297
+ const seekPos = nr * js.stateIrecsz;
298
+ if (seekPos + js.stateNcoeffs * 8 > reader.length) {
299
+ serr[0] = `Read error in JPL eph. at ${et}`;
300
+ return NOT_AVAILABLE;
301
+ }
302
+ reader.seekSet(seekPos);
303
+ for (let k = 0; k < js.stateNcoeffs; k++) {
304
+ buf[k] = reader.readFloat64();
305
+ }
306
+ }
307
+ let aufac: number;
308
+ let intv: number;
309
+ if (js.doKm) {
310
+ intv = js.ehSs[2] * 86400.0;
311
+ aufac = 1.0;
312
+ } else {
313
+ intv = js.ehSs[2];
314
+ aufac = 1.0 / js.ehAu;
315
+ }
316
+ /* interpolate ssbary sun */
317
+ interp(buf, ipt[30] - 1, t, intv, ipt[31], 3, ipt[32], 2, pvsun, 0, js);
318
+ for (let i = 0; i < 6; i++) pvsun[i] *= aufac;
319
+ /* interpolate requested bodies */
320
+ for (let i = 0; i < 10; i++) {
321
+ if (list[i] > 0) {
322
+ interp(buf, ipt[i * 3] - 1, t, intv, ipt[i * 3 + 1], 3,
323
+ ipt[i * 3 + 2], list[i], pv, i * 6, js);
324
+ for (let j = 0; j < 6; j++) {
325
+ if (i < 9 && !doBary) {
326
+ pv[j + i * 6] = pv[j + i * 6] * aufac - pvsun[j];
327
+ } else {
328
+ pv[j + i * 6] *= aufac;
329
+ }
330
+ }
331
+ }
332
+ }
333
+ /* nutations */
334
+ if (nut !== null && list[10] > 0 && ipt[34] > 0) {
335
+ interp(buf, ipt[33] - 1, t, intv, ipt[34], 2, ipt[35], list[10], nut, 0, js);
336
+ }
337
+ /* librations */
338
+ if (list[11] > 0 && ipt[37] > 0) {
339
+ interp(buf, ipt[36] - 1, t, intv, ipt[37], 3, ipt[38], list[1], pv, 60, js);
340
+ }
341
+ return OK;
342
+ }
343
+
344
+ /* ================================================================
345
+ * readConstJpl: initialize header by calling state with null list
346
+ * ================================================================ */
347
+ function readConstJpl(js: JplSave, ss: Float64Array, serr: string[]): number {
348
+ const retc = state(0.0, null, false, js.pv, js.pvsun, null, js, serr);
349
+ if (retc !== OK) return retc;
350
+ for (let i = 0; i < 3; i++) ss[i] = js.ehSs[i];
351
+ return OK;
352
+ }
353
+
354
+ /* ================================================================
355
+ * swiOpenJplFile: open and validate JPL file
356
+ * ================================================================ */
357
+ export function swiOpenJplFile(
358
+ swed: SweData, ss: Float64Array, reader: SE1FileReader, serr: string[],
359
+ ): number {
360
+ /* if already open, return */
361
+ if (swed.jplSave !== null && swed.jplSave.jplReader !== null) return OK;
362
+ const js = createJplSave();
363
+ js.jplReader = reader;
364
+ /* Try little-endian first (most common on modern systems) */
365
+ reader.setLittleEndian(true);
366
+ const retc = readConstJpl(js, ss, serr);
367
+ if (retc !== OK) {
368
+ swed.jplSave = null;
369
+ return retc;
370
+ }
371
+ /* initialize interpolation polynomial basis */
372
+ js.pc[0] = 1;
373
+ js.pc[1] = 2;
374
+ js.vc[1] = 1;
375
+ js.ac[2] = 4;
376
+ js.jc[3] = 24;
377
+ swed.jplSave = js;
378
+ return OK;
379
+ }
380
+
381
+ /* ================================================================
382
+ * swiCloseJplFile: release JPL resources
383
+ * ================================================================ */
384
+ export function swiCloseJplFile(swed: SweData): void {
385
+ swed.jplSave = null;
386
+ }
387
+
388
+ /* ================================================================
389
+ * swiPleph: interpolate position at time et for ntarg relative to ncent
390
+ * ================================================================ */
391
+ export function swiPleph(
392
+ swed: SweData, et: number, ntarg: number, ncent: number,
393
+ rrd: Float64Array, serr: string[],
394
+ ): number {
395
+ const js = swed.jplSave;
396
+ if (js === null) {
397
+ serr[0] = 'JPL ephemeris file not loaded';
398
+ return NOT_AVAILABLE;
399
+ }
400
+ for (let i = 0; i < 6; i++) rrd[i] = 0;
401
+ if (ntarg === ncent) return OK;
402
+ const list = new Int32Array(12);
403
+ /* check for nutation call */
404
+ if (ntarg === J_NUT) {
405
+ if (js.ehIpt[34] > 0) {
406
+ list[10] = 2;
407
+ return state(et, list, false, js.pv, js.pvsun, rrd, js, serr);
408
+ } else {
409
+ serr[0] = 'No nutations on the JPL ephemeris file;';
410
+ return NOT_AVAILABLE;
411
+ }
412
+ }
413
+ if (ntarg === J_LIB) {
414
+ if (js.ehIpt[37] > 0) {
415
+ list[11] = 2;
416
+ const retc = state(et, list, false, js.pv, js.pvsun, rrd, js, serr);
417
+ if (retc !== OK) return retc;
418
+ for (let i = 0; i < 6; i++) rrd[i] = js.pv[i + 60];
419
+ return OK;
420
+ } else {
421
+ serr[0] = 'No librations on the ephemeris file;';
422
+ return NOT_AVAILABLE;
423
+ }
424
+ }
425
+ /* set up list entries */
426
+ if (ntarg < J_SUN) list[ntarg] = 2;
427
+ if (ntarg === J_MOON) list[J_EARTH] = 2;
428
+ if (ntarg === J_EARTH) list[J_MOON] = 2;
429
+ if (ntarg === J_EMB) list[J_EARTH] = 2;
430
+ if (ncent < J_SUN) list[ncent] = 2;
431
+ if (ncent === J_MOON) list[J_EARTH] = 2;
432
+ if (ncent === J_EARTH) list[J_MOON] = 2;
433
+ if (ncent === J_EMB) list[J_EARTH] = 2;
434
+ const pv = js.pv;
435
+ const pvsun = js.pvsun;
436
+ const retc = state(et, list, true, pv, pvsun, rrd, js, serr);
437
+ if (retc !== OK) return retc;
438
+ if (ntarg === J_SUN || ncent === J_SUN) {
439
+ for (let i = 0; i < 6; i++) pv[i + 6 * J_SUN] = pvsun[i];
440
+ }
441
+ if (ntarg === J_SBARY || ncent === J_SBARY) {
442
+ for (let i = 0; i < 6; i++) pv[i + 6 * J_SBARY] = 0;
443
+ }
444
+ if (ntarg === J_EMB || ncent === J_EMB) {
445
+ for (let i = 0; i < 6; i++) pv[i + 6 * J_EMB] = pv[i + 6 * J_EARTH];
446
+ }
447
+ if ((ntarg === J_EARTH && ncent === J_MOON) || (ntarg === J_MOON && ncent === J_EARTH)) {
448
+ for (let i = 0; i < 6; i++) pv[i + 6 * J_EARTH] = 0;
449
+ } else {
450
+ if (list[J_EARTH] === 2) {
451
+ for (let i = 0; i < 6; i++) {
452
+ pv[i + 6 * J_EARTH] -= pv[i + 6 * J_MOON] / (js.ehEmrat + 1.0);
453
+ }
454
+ }
455
+ if (list[J_MOON] === 2) {
456
+ for (let i = 0; i < 6; i++) {
457
+ pv[i + 6 * J_MOON] += pv[i + 6 * J_EARTH];
458
+ }
459
+ }
460
+ }
461
+ for (let i = 0; i < 6; i++) rrd[i] = pv[i + ntarg * 6] - pv[i + ncent * 6];
462
+ return OK;
463
+ }
464
+
465
+ /* ================================================================
466
+ * swiGetJplDenum: return DE number
467
+ * ================================================================ */
468
+ export function swiGetJplDenum(swed: SweData): number {
469
+ return swed.jplSave?.ehDenum ?? 0;
470
+ }