@neilberkman/sidereon 0.9.0 → 0.9.2

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.
package/pkg/sidereon.js CHANGED
@@ -3284,6 +3284,71 @@ export class Ephemeris {
3284
3284
  }
3285
3285
  if (Symbol.dispose) Ephemeris.prototype[Symbol.dispose] = Ephemeris.prototype.free;
3286
3286
 
3287
+ /**
3288
+ * A confidence ellipse from a 2x2 covariance block: semi-axes scaled by the
3289
+ * two-degree-of-freedom chi-square quantile `-2 ln(1 - confidence)`.
3290
+ */
3291
+ export class ErrorEllipse2 {
3292
+ static __wrap(ptr) {
3293
+ const obj = Object.create(ErrorEllipse2.prototype);
3294
+ obj.__wbg_ptr = ptr;
3295
+ ErrorEllipse2Finalization.register(obj, obj.__wbg_ptr, obj);
3296
+ return obj;
3297
+ }
3298
+ __destroy_into_raw() {
3299
+ const ptr = this.__wbg_ptr;
3300
+ this.__wbg_ptr = 0;
3301
+ ErrorEllipse2Finalization.unregister(this);
3302
+ return ptr;
3303
+ }
3304
+ free() {
3305
+ const ptr = this.__destroy_into_raw();
3306
+ wasm.__wbg_errorellipse2_free(ptr, 0);
3307
+ }
3308
+ /**
3309
+ * Two-degree-of-freedom chi-square scale `-2 ln(1 - confidence)`.
3310
+ * @returns {number}
3311
+ */
3312
+ get chiSquareScale() {
3313
+ const ret = wasm.errorellipse2_chiSquareScale(this.__wbg_ptr);
3314
+ return ret;
3315
+ }
3316
+ /**
3317
+ * Requested confidence probability in `(0, 1)`.
3318
+ * @returns {number}
3319
+ */
3320
+ get confidence() {
3321
+ const ret = wasm.errorellipse2_confidence(this.__wbg_ptr);
3322
+ return ret;
3323
+ }
3324
+ /**
3325
+ * Semi-major-axis orientation in radians, from the first (row/col 0) axis
3326
+ * toward the second (row/col 1) axis.
3327
+ * @returns {number}
3328
+ */
3329
+ get orientationRad() {
3330
+ const ret = wasm.errorellipse2_orientationRad(this.__wbg_ptr);
3331
+ return ret;
3332
+ }
3333
+ /**
3334
+ * Semi-major axis length (same unit as the square root of the covariance).
3335
+ * @returns {number}
3336
+ */
3337
+ get semiMajor() {
3338
+ const ret = wasm.errorellipse2_semiMajor(this.__wbg_ptr);
3339
+ return ret;
3340
+ }
3341
+ /**
3342
+ * Semi-minor axis length.
3343
+ * @returns {number}
3344
+ */
3345
+ get semiMinor() {
3346
+ const ret = wasm.errorellipse2_semiMinor(this.__wbg_ptr);
3347
+ return ret;
3348
+ }
3349
+ }
3350
+ if (Symbol.dispose) ErrorEllipse2.prototype[Symbol.dispose] = ErrorEllipse2.prototype.free;
3351
+
3287
3352
  /**
3288
3353
  * A fault-detection-and-exclusion result: the surviving solution, the excluded
3289
3354
  * satellites in exclusion order, and the number of exclusions performed.
@@ -5264,6 +5329,201 @@ export class LeapSecondTable {
5264
5329
  }
5265
5330
  if (Symbol.dispose) LeapSecondTable.prototype[Symbol.dispose] = LeapSecondTable.prototype.free;
5266
5331
 
5332
+ /**
5333
+ * A serial leave-one-out sweep: the base solve over all rows plus one re-solve
5334
+ * per masked row, with the per-row optimum-cost shift.
5335
+ */
5336
+ export class LeastSquaresDropOneReport {
5337
+ static __wrap(ptr) {
5338
+ const obj = Object.create(LeastSquaresDropOneReport.prototype);
5339
+ obj.__wbg_ptr = ptr;
5340
+ LeastSquaresDropOneReportFinalization.register(obj, obj.__wbg_ptr, obj);
5341
+ return obj;
5342
+ }
5343
+ __destroy_into_raw() {
5344
+ const ptr = this.__wbg_ptr;
5345
+ this.__wbg_ptr = 0;
5346
+ LeastSquaresDropOneReportFinalization.unregister(this);
5347
+ return ptr;
5348
+ }
5349
+ free() {
5350
+ const ptr = this.__destroy_into_raw();
5351
+ wasm.__wbg_leastsquaresdroponereport_free(ptr, 0);
5352
+ }
5353
+ /**
5354
+ * The solve over the full residual.
5355
+ * @returns {LeastSquaresResult}
5356
+ */
5357
+ get base() {
5358
+ const ret = wasm.leastsquaresdroponereport_base(this.__wbg_ptr);
5359
+ return LeastSquaresResult.__wrap(ret);
5360
+ }
5361
+ /**
5362
+ * `costDeltas[i] = dropAt(i).cost - base.cost`: how much the optimum cost
5363
+ * moves when row `i` is removed. `Float64Array` of length `count`.
5364
+ * @returns {Float64Array}
5365
+ */
5366
+ get costDeltas() {
5367
+ const ret = wasm.leastsquaresdroponereport_costDeltas(this.__wbg_ptr);
5368
+ var v1 = getArrayF64FromWasm0(ret[0], ret[1]).slice();
5369
+ wasm.__wbindgen_free(ret[0], ret[1] * 8, 8);
5370
+ return v1;
5371
+ }
5372
+ /**
5373
+ * Number of masked-row re-solves (equals the residual-row count `m`).
5374
+ * @returns {number}
5375
+ */
5376
+ get count() {
5377
+ const ret = wasm.leastsquaresdroponereport_count(this.__wbg_ptr);
5378
+ return ret >>> 0;
5379
+ }
5380
+ /**
5381
+ * The solve with residual row `index` masked out. Throws a `RangeError` for
5382
+ * an out-of-range index.
5383
+ * @param {number} index
5384
+ * @returns {LeastSquaresResult}
5385
+ */
5386
+ dropAt(index) {
5387
+ const ret = wasm.leastsquaresdroponereport_dropAt(this.__wbg_ptr, index);
5388
+ if (ret[2]) {
5389
+ throw takeFromExternrefTable0(ret[1]);
5390
+ }
5391
+ return LeastSquaresResult.__wrap(ret[0]);
5392
+ }
5393
+ }
5394
+ if (Symbol.dispose) LeastSquaresDropOneReport.prototype[Symbol.dispose] = LeastSquaresDropOneReport.prototype.free;
5395
+
5396
+ /**
5397
+ * The outcome of one trust-region least-squares solve, mirroring the fields of
5398
+ * `scipy.optimize.least_squares`'s `OptimizeResult`.
5399
+ */
5400
+ export class LeastSquaresResult {
5401
+ static __wrap(ptr) {
5402
+ const obj = Object.create(LeastSquaresResult.prototype);
5403
+ obj.__wbg_ptr = ptr;
5404
+ LeastSquaresResultFinalization.register(obj, obj.__wbg_ptr, obj);
5405
+ return obj;
5406
+ }
5407
+ __destroy_into_raw() {
5408
+ const ptr = this.__wbg_ptr;
5409
+ this.__wbg_ptr = 0;
5410
+ LeastSquaresResultFinalization.unregister(this);
5411
+ return ptr;
5412
+ }
5413
+ free() {
5414
+ const ptr = this.__destroy_into_raw();
5415
+ wasm.__wbg_leastsquaresresult_free(ptr, 0);
5416
+ }
5417
+ /**
5418
+ * Optimal cost `0.5 * sum(residual^2)` (after robust reweighting when a
5419
+ * non-linear loss is used).
5420
+ * @returns {number}
5421
+ */
5422
+ get cost() {
5423
+ const ret = wasm.leastsquaresresult_cost(this.__wbg_ptr);
5424
+ return ret;
5425
+ }
5426
+ /**
5427
+ * Residual vector at the solution, `Float64Array` of length `m`.
5428
+ * @returns {Float64Array}
5429
+ */
5430
+ get fun() {
5431
+ const ret = wasm.leastsquaresresult_fun(this.__wbg_ptr);
5432
+ var v1 = getArrayF64FromWasm0(ret[0], ret[1]).slice();
5433
+ wasm.__wbindgen_free(ret[0], ret[1] * 8, 8);
5434
+ return v1;
5435
+ }
5436
+ /**
5437
+ * Gradient `J^T f` at the solution, `Float64Array` of length `n`.
5438
+ * @returns {Float64Array}
5439
+ */
5440
+ get grad() {
5441
+ const ret = wasm.leastsquaresresult_grad(this.__wbg_ptr);
5442
+ var v1 = getArrayF64FromWasm0(ret[0], ret[1]).slice();
5443
+ wasm.__wbindgen_free(ret[0], ret[1] * 8, 8);
5444
+ return v1;
5445
+ }
5446
+ /**
5447
+ * Row-major `m`-by-`n` Jacobian at the solution, flat `Float64Array` of
5448
+ * length `m * n`.
5449
+ * @returns {Float64Array}
5450
+ */
5451
+ get jac() {
5452
+ const ret = wasm.leastsquaresresult_jac(this.__wbg_ptr);
5453
+ var v1 = getArrayF64FromWasm0(ret[0], ret[1]).slice();
5454
+ wasm.__wbindgen_free(ret[0], ret[1] * 8, 8);
5455
+ return v1;
5456
+ }
5457
+ /**
5458
+ * Residual row count `m`.
5459
+ * @returns {number}
5460
+ */
5461
+ get m() {
5462
+ const ret = wasm.leastsquaresresult_m(this.__wbg_ptr);
5463
+ return ret >>> 0;
5464
+ }
5465
+ /**
5466
+ * Parameter count `n`.
5467
+ * @returns {number}
5468
+ */
5469
+ get n() {
5470
+ const ret = wasm.leastsquaresresult_n(this.__wbg_ptr);
5471
+ return ret >>> 0;
5472
+ }
5473
+ /**
5474
+ * Number of residual evaluations.
5475
+ * @returns {number}
5476
+ */
5477
+ get nfev() {
5478
+ const ret = wasm.leastsquaresresult_nfev(this.__wbg_ptr);
5479
+ return ret >>> 0;
5480
+ }
5481
+ /**
5482
+ * Number of Jacobian evaluations.
5483
+ * @returns {number}
5484
+ */
5485
+ get njev() {
5486
+ const ret = wasm.leastsquaresresult_njev(this.__wbg_ptr);
5487
+ return ret >>> 0;
5488
+ }
5489
+ /**
5490
+ * First-order optimality `||J^T f||_inf` at the solution.
5491
+ * @returns {number}
5492
+ */
5493
+ get optimality() {
5494
+ const ret = wasm.leastsquaresresult_optimality(this.__wbg_ptr);
5495
+ return ret;
5496
+ }
5497
+ /**
5498
+ * SciPy-compatible termination status: `0` max evaluations, `1` gtol,
5499
+ * `2` ftol, `3` xtol, `4` both ftol and xtol.
5500
+ * @returns {number}
5501
+ */
5502
+ get status() {
5503
+ const ret = wasm.leastsquaresresult_status(this.__wbg_ptr);
5504
+ return ret;
5505
+ }
5506
+ /**
5507
+ * Whether the solve converged (`status > 0`).
5508
+ * @returns {boolean}
5509
+ */
5510
+ get success() {
5511
+ const ret = wasm.leastsquaresresult_success(this.__wbg_ptr);
5512
+ return ret !== 0;
5513
+ }
5514
+ /**
5515
+ * Solution parameter vector, `Float64Array` of length `n`.
5516
+ * @returns {Float64Array}
5517
+ */
5518
+ get x() {
5519
+ const ret = wasm.leastsquaresresult_x(this.__wbg_ptr);
5520
+ var v1 = getArrayF64FromWasm0(ret[0], ret[1]).slice();
5521
+ wasm.__wbindgen_free(ret[0], ret[1] * 8, 8);
5522
+ return v1;
5523
+ }
5524
+ }
5525
+ if (Symbol.dispose) LeastSquaresResult.prototype[Symbol.dispose] = LeastSquaresResult.prototype.free;
5526
+
5267
5527
  /**
5268
5528
  * Link-budget inputs for [`LinkBudget.margin`].
5269
5529
  */
@@ -5761,6 +6021,117 @@ export class MappingFactors {
5761
6021
  }
5762
6022
  if (Symbol.dispose) MappingFactors.prototype[Symbol.dispose] = MappingFactors.prototype.free;
5763
6023
 
6024
+ /**
6025
+ * One refined Moon elevation threshold crossing (moonrise / moonset).
6026
+ */
6027
+ export class MoonElevationCrossing {
6028
+ static __wrap(ptr) {
6029
+ const obj = Object.create(MoonElevationCrossing.prototype);
6030
+ obj.__wbg_ptr = ptr;
6031
+ MoonElevationCrossingFinalization.register(obj, obj.__wbg_ptr, obj);
6032
+ return obj;
6033
+ }
6034
+ __destroy_into_raw() {
6035
+ const ptr = this.__wbg_ptr;
6036
+ this.__wbg_ptr = 0;
6037
+ MoonElevationCrossingFinalization.unregister(this);
6038
+ return ptr;
6039
+ }
6040
+ free() {
6041
+ const ptr = this.__destroy_into_raw();
6042
+ wasm.__wbg_moonelevationcrossing_free(ptr, 0);
6043
+ }
6044
+ /**
6045
+ * Topocentric Moon elevation at the refined instant, degrees.
6046
+ * @returns {number}
6047
+ */
6048
+ get elevationDeg() {
6049
+ const ret = wasm.moonelevationcrossing_elevationDeg(this.__wbg_ptr);
6050
+ return ret;
6051
+ }
6052
+ /**
6053
+ * Crossing direction: `"rising"` (moonrise) or `"setting"` (moonset).
6054
+ * @returns {string}
6055
+ */
6056
+ get kind() {
6057
+ let deferred1_0;
6058
+ let deferred1_1;
6059
+ try {
6060
+ const ret = wasm.moonelevationcrossing_kind(this.__wbg_ptr);
6061
+ deferred1_0 = ret[0];
6062
+ deferred1_1 = ret[1];
6063
+ return getStringFromWasm0(ret[0], ret[1]);
6064
+ } finally {
6065
+ wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
6066
+ }
6067
+ }
6068
+ /**
6069
+ * Refined crossing instant, unix microseconds.
6070
+ * @returns {bigint}
6071
+ */
6072
+ get timeUnixUs() {
6073
+ const ret = wasm.moonelevationcrossing_timeUnixUs(this.__wbg_ptr);
6074
+ return ret;
6075
+ }
6076
+ }
6077
+ if (Symbol.dispose) MoonElevationCrossing.prototype[Symbol.dispose] = MoonElevationCrossing.prototype.free;
6078
+
6079
+ /**
6080
+ * One refined Moon meridian transit (culmination).
6081
+ */
6082
+ export class MoonTransit {
6083
+ static __wrap(ptr) {
6084
+ const obj = Object.create(MoonTransit.prototype);
6085
+ obj.__wbg_ptr = ptr;
6086
+ MoonTransitFinalization.register(obj, obj.__wbg_ptr, obj);
6087
+ return obj;
6088
+ }
6089
+ __destroy_into_raw() {
6090
+ const ptr = this.__wbg_ptr;
6091
+ this.__wbg_ptr = 0;
6092
+ MoonTransitFinalization.unregister(this);
6093
+ return ptr;
6094
+ }
6095
+ free() {
6096
+ const ptr = this.__destroy_into_raw();
6097
+ wasm.__wbg_moontransit_free(ptr, 0);
6098
+ }
6099
+ /**
6100
+ * Topocentric Moon elevation at the refined instant, degrees.
6101
+ * @returns {number}
6102
+ */
6103
+ get elevationDeg() {
6104
+ const ret = wasm.moontransit_elevationDeg(this.__wbg_ptr);
6105
+ return ret;
6106
+ }
6107
+ /**
6108
+ * Culmination kind: `"upper"` (due south, highest) or `"lower"` (due north,
6109
+ * lowest).
6110
+ * @returns {string}
6111
+ */
6112
+ get kind() {
6113
+ let deferred1_0;
6114
+ let deferred1_1;
6115
+ try {
6116
+ const ret = wasm.moontransit_kind(this.__wbg_ptr);
6117
+ deferred1_0 = ret[0];
6118
+ deferred1_1 = ret[1];
6119
+ return getStringFromWasm0(ret[0], ret[1]);
6120
+ } finally {
6121
+ wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
6122
+ }
6123
+ }
6124
+ /**
6125
+ * Refined culmination instant, unix microseconds.
6126
+ * @returns {bigint}
6127
+ */
6128
+ get timeUnixUs() {
6129
+ const ret = wasm.moontransit_timeUnixUs(this.__wbg_ptr);
6130
+ return ret;
6131
+ }
6132
+ }
6133
+ if (Symbol.dispose) MoonTransit.prototype[Symbol.dispose] = MoonTransit.prototype.free;
6134
+
5764
6135
  /**
5765
6136
  * One solved moving-baseline epoch.
5766
6137
  */
@@ -8756,25 +9127,156 @@ export class PppFloatSolution {
8756
9127
  if (Symbol.dispose) PppFloatSolution.prototype[Symbol.dispose] = PppFloatSolution.prototype.free;
8757
9128
 
8758
9129
  /**
8759
- * Predicted GNSS observables for one satellite at one receive epoch. Every
8760
- * field is computed by `sidereon_core::observables::predict`.
9130
+ * A precise-ephemeris source built from samples rather than parsed SP3 text.
9131
+ *
9132
+ * Implements the same `ObservableEphemerisSource` contract as a parsed [`Sp3`]
9133
+ * product and shares its interpolation substrate, so [`predictRanges`] accepts
9134
+ * either handle. Build one with [`preciseEphemerisSamplesFromSamples`].
8761
9135
  */
8762
- export class PredictedObservables {
9136
+ export class PreciseEphemerisSampleSource {
8763
9137
  static __wrap(ptr) {
8764
- const obj = Object.create(PredictedObservables.prototype);
9138
+ const obj = Object.create(PreciseEphemerisSampleSource.prototype);
8765
9139
  obj.__wbg_ptr = ptr;
8766
- PredictedObservablesFinalization.register(obj, obj.__wbg_ptr, obj);
9140
+ PreciseEphemerisSampleSourceFinalization.register(obj, obj.__wbg_ptr, obj);
8767
9141
  return obj;
8768
9142
  }
8769
9143
  __destroy_into_raw() {
8770
9144
  const ptr = this.__wbg_ptr;
8771
9145
  this.__wbg_ptr = 0;
8772
- PredictedObservablesFinalization.unregister(this);
9146
+ PreciseEphemerisSampleSourceFinalization.unregister(this);
8773
9147
  return ptr;
8774
9148
  }
8775
9149
  free() {
8776
9150
  const ptr = this.__destroy_into_raw();
8777
- wasm.__wbg_predictedobservables_free(ptr, 0);
9151
+ wasm.__wbg_preciseephemerissamplesource_free(ptr, 0);
9152
+ }
9153
+ /**
9154
+ * Predict geometric ranges for many requests in one call. See the shared
9155
+ * [`predictRanges`](crate::precise_samples::predict_ranges_over) contract;
9156
+ * this is the sample-source entry point.
9157
+ * @param {any} requests
9158
+ * @param {any} options
9159
+ * @returns {any}
9160
+ */
9161
+ predictRanges(requests, options) {
9162
+ const ret = wasm.preciseephemerissamplesource_predictRanges(this.__wbg_ptr, requests, options);
9163
+ if (ret[2]) {
9164
+ throw takeFromExternrefTable0(ret[1]);
9165
+ }
9166
+ return takeFromExternrefTable0(ret[0]);
9167
+ }
9168
+ /**
9169
+ * The satellites this source can interpolate (e.g. `"G01"`), ascending.
9170
+ * @returns {string[]}
9171
+ */
9172
+ get satellites() {
9173
+ const ret = wasm.preciseephemerissamplesource_satellites(this.__wbg_ptr);
9174
+ var v1 = getArrayJsValueFromWasm0(ret[0], ret[1]).slice();
9175
+ wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
9176
+ return v1;
9177
+ }
9178
+ }
9179
+ if (Symbol.dispose) PreciseEphemerisSampleSource.prototype[Symbol.dispose] = PreciseEphemerisSampleSource.prototype.free;
9180
+
9181
+ /**
9182
+ * The per-request results of a batch observable prediction, index-aligned to
9183
+ * the input requests. Each request independently either produced observables or
9184
+ * failed; query a request with [`PredictBatch.isOk`] /
9185
+ * [`PredictBatch.observables`] / [`PredictBatch.error`].
9186
+ */
9187
+ export class PredictBatch {
9188
+ static __wrap(ptr) {
9189
+ const obj = Object.create(PredictBatch.prototype);
9190
+ obj.__wbg_ptr = ptr;
9191
+ PredictBatchFinalization.register(obj, obj.__wbg_ptr, obj);
9192
+ return obj;
9193
+ }
9194
+ __destroy_into_raw() {
9195
+ const ptr = this.__wbg_ptr;
9196
+ this.__wbg_ptr = 0;
9197
+ PredictBatchFinalization.unregister(this);
9198
+ return ptr;
9199
+ }
9200
+ free() {
9201
+ const ptr = this.__destroy_into_raw();
9202
+ wasm.__wbg_predictbatch_free(ptr, 0);
9203
+ }
9204
+ /**
9205
+ * Number of requests in the batch.
9206
+ * @returns {number}
9207
+ */
9208
+ get count() {
9209
+ const ret = wasm.predictbatch_count(this.__wbg_ptr);
9210
+ return ret >>> 0;
9211
+ }
9212
+ /**
9213
+ * The failure message for request `index`, or `undefined` when it
9214
+ * succeeded. Throws a `RangeError` for an out-of-range index.
9215
+ * @param {number} index
9216
+ * @returns {string | undefined}
9217
+ */
9218
+ error(index) {
9219
+ const ret = wasm.predictbatch_error(this.__wbg_ptr, index);
9220
+ if (ret[3]) {
9221
+ throw takeFromExternrefTable0(ret[2]);
9222
+ }
9223
+ let v1;
9224
+ if (ret[0] !== 0) {
9225
+ v1 = getStringFromWasm0(ret[0], ret[1]).slice();
9226
+ wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
9227
+ }
9228
+ return v1;
9229
+ }
9230
+ /**
9231
+ * Whether request `index` produced observables. Throws a `RangeError` for
9232
+ * an out-of-range index.
9233
+ * @param {number} index
9234
+ * @returns {boolean}
9235
+ */
9236
+ isOk(index) {
9237
+ const ret = wasm.predictbatch_isOk(this.__wbg_ptr, index);
9238
+ if (ret[2]) {
9239
+ throw takeFromExternrefTable0(ret[1]);
9240
+ }
9241
+ return ret[0] !== 0;
9242
+ }
9243
+ /**
9244
+ * The observables for request `index`. Throws a `RangeError` for an
9245
+ * out-of-range index and an `Error` carrying that request's failure message
9246
+ * when the prediction failed (check [`PredictBatch.isOk`] first).
9247
+ * @param {number} index
9248
+ * @returns {PredictedObservables}
9249
+ */
9250
+ observables(index) {
9251
+ const ret = wasm.predictbatch_observables(this.__wbg_ptr, index);
9252
+ if (ret[2]) {
9253
+ throw takeFromExternrefTable0(ret[1]);
9254
+ }
9255
+ return PredictedObservables.__wrap(ret[0]);
9256
+ }
9257
+ }
9258
+ if (Symbol.dispose) PredictBatch.prototype[Symbol.dispose] = PredictBatch.prototype.free;
9259
+
9260
+ /**
9261
+ * Predicted GNSS observables for one satellite at one receive epoch. Every
9262
+ * field is computed by `sidereon_core::observables::predict`.
9263
+ */
9264
+ export class PredictedObservables {
9265
+ static __wrap(ptr) {
9266
+ const obj = Object.create(PredictedObservables.prototype);
9267
+ obj.__wbg_ptr = ptr;
9268
+ PredictedObservablesFinalization.register(obj, obj.__wbg_ptr, obj);
9269
+ return obj;
9270
+ }
9271
+ __destroy_into_raw() {
9272
+ const ptr = this.__wbg_ptr;
9273
+ this.__wbg_ptr = 0;
9274
+ PredictedObservablesFinalization.unregister(this);
9275
+ return ptr;
9276
+ }
9277
+ free() {
9278
+ const ptr = this.__destroy_into_raw();
9279
+ wasm.__wbg_predictedobservables_free(ptr, 0);
8778
9280
  }
8779
9281
  /**
8780
9282
  * Topocentric azimuth in `[0, 360)`, degrees.
@@ -10278,6 +10780,25 @@ export class Sp3 {
10278
10780
  }
10279
10781
  return Sp3Interpolation.__wrap(ret[0]);
10280
10782
  }
10783
+ /**
10784
+ * Predict geometric ranges for many `(satellite, receiver, epoch)` requests
10785
+ * against this ephemeris in one call. `requests` is an array of
10786
+ * `{ sat, receiverEcefM, tRxJ2000S }`; returns an array of
10787
+ * `{ geometricRangeM, satClockS, transmitTimeJ2000S, satPosEcefM }`
10788
+ * index-aligned to `requests`. The same call shape works on a
10789
+ * `PreciseEphemerisSampleSource`. Delegates to the serial reference kernel
10790
+ * `sidereon_core::observables::predict_ranges`.
10791
+ * @param {any} requests
10792
+ * @param {any} options
10793
+ * @returns {any}
10794
+ */
10795
+ predictRanges(requests, options) {
10796
+ const ret = wasm.sp3_predictRanges(this.__wbg_ptr, requests, options);
10797
+ if (ret[2]) {
10798
+ throw takeFromExternrefTable0(ret[1]);
10799
+ }
10800
+ return takeFromExternrefTable0(ret[0]);
10801
+ }
10281
10802
  /**
10282
10803
  * Satellite tokens present in the product (e.g. `"G01"`), ascending.
10283
10804
  * @returns {string[]}
@@ -12586,6 +13107,36 @@ export function correlate(iq, prn, options) {
12586
13107
  return CorrelationResult.__wrap(ret[0]);
12587
13108
  }
12588
13109
 
13110
+ /**
13111
+ * Fitted parameter covariance from a converged solve, scaling `(J^T J)^-1` by
13112
+ * the post-fit reduced chi-square `s_sq = 2 * cost / (m - n)` (the same scale
13113
+ * `scipy.optimize.curve_fit` applies to its `pcov`).
13114
+ *
13115
+ * `jacobian` is a flat row-major `(m, n)` `Float64Array` (the Jacobian at the
13116
+ * solution), and `cost` is the solve's optimal cost `0.5 * sum(residual^2)`;
13117
+ * the degrees of freedom `m - n` (taken from the Jacobian's own shape) must be
13118
+ * positive. Pairs naturally with a [`crate::LeastSquaresResult`] (`result.jac`,
13119
+ * `result.m`, `result.n`, `result.cost`). Returns the `n`-by-`n` covariance as
13120
+ * a flat row-major `Float64Array`. Delegates to
13121
+ * `sidereon_core::astro::math::least_squares::covariance_from_jacobian`.
13122
+ * @param {Float64Array} jacobian
13123
+ * @param {number} m
13124
+ * @param {number} n
13125
+ * @param {number} cost
13126
+ * @returns {Float64Array}
13127
+ */
13128
+ export function covarianceFromJacobian(jacobian, m, n, cost) {
13129
+ const ptr0 = passArrayF64ToWasm0(jacobian, wasm.__wbindgen_malloc);
13130
+ const len0 = WASM_VECTOR_LEN;
13131
+ const ret = wasm.covarianceFromJacobian(ptr0, len0, m, n, cost);
13132
+ if (ret[3]) {
13133
+ throw takeFromExternrefTable0(ret[2]);
13134
+ }
13135
+ var v2 = getArrayF64FromWasm0(ret[0], ret[1]).slice();
13136
+ wasm.__wbindgen_free(ret[0], ret[1] * 8, 8);
13137
+ return v2;
13138
+ }
13139
+
12589
13140
  /**
12590
13141
  * Whether a 3x3 covariance (flat row-major length 9) is symmetric positive
12591
13142
  * semidefinite within the engine tolerance.
@@ -12834,6 +13385,37 @@ export function dishGain(diameter_m, frequency_hz, efficiency) {
12834
13385
  return ret[0];
12835
13386
  }
12836
13387
 
13388
+ /**
13389
+ * GNSS dilution of precision with an explicit ENU convention for the
13390
+ * horizontal/vertical split.
13391
+ *
13392
+ * `lineOfSight` is a flat row-major `(n, 3)` `Float64Array` of ECEF unit
13393
+ * vectors, `weights` a positive `Float64Array` of length `n`, and `convention`
13394
+ * is `"geodeticNormal"` (the GNSS-standard default, matching [`gnssDop`]) or
13395
+ * `"geocentricRadial"` (radial up). Only HDOP/VDOP differ between conventions
13396
+ * (by ~`1e-3` relative); GDOP/PDOP/TDOP are identical. Delegates to
13397
+ * `sidereon_core::geometry::dop_with_convention`.
13398
+ * @param {Float64Array} line_of_sight
13399
+ * @param {Float64Array} weights
13400
+ * @param {Wgs84Geodetic} receiver
13401
+ * @param {string} convention
13402
+ * @returns {Dop}
13403
+ */
13404
+ export function dopWithConvention(line_of_sight, weights, receiver, convention) {
13405
+ const ptr0 = passArrayF64ToWasm0(line_of_sight, wasm.__wbindgen_malloc);
13406
+ const len0 = WASM_VECTOR_LEN;
13407
+ const ptr1 = passArrayF64ToWasm0(weights, wasm.__wbindgen_malloc);
13408
+ const len1 = WASM_VECTOR_LEN;
13409
+ _assertClass(receiver, Wgs84Geodetic);
13410
+ const ptr2 = passStringToWasm0(convention, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
13411
+ const len2 = WASM_VECTOR_LEN;
13412
+ const ret = wasm.dopWithConvention(ptr0, len0, ptr1, len1, receiver.__wbg_ptr, ptr2, len2);
13413
+ if (ret[2]) {
13414
+ throw takeFromExternrefTable0(ret[1]);
13415
+ }
13416
+ return Dop.__wrap(ret[0]);
13417
+ }
13418
+
12837
13419
  /**
12838
13420
  * Range rate and dimensionless Doppler ratio from a GCRS state.
12839
13421
  *
@@ -12975,6 +13557,53 @@ export function eclipseStatus(satellite_position_km, sun_position_km) {
12975
13557
  return v3;
12976
13558
  }
12977
13559
 
13560
+ /**
13561
+ * Ellipsoidal height `h = H + N` (metres above the WGS84 ellipsoid) from an
13562
+ * orthometric height and a geodetic position in radians, using the embedded
13563
+ * genuine EGM96 1-degree model. Delegates to
13564
+ * `sidereon_core::geoid::egm96_ellipsoidal_height_m`.
13565
+ * @param {number} orthometric_height_m
13566
+ * @param {number} lat_rad
13567
+ * @param {number} lon_rad
13568
+ * @returns {number}
13569
+ */
13570
+ export function egm96EllipsoidalHeightM(orthometric_height_m, lat_rad, lon_rad) {
13571
+ const ret = wasm.egm96EllipsoidalHeightM(orthometric_height_m, lat_rad, lon_rad);
13572
+ return ret;
13573
+ }
13574
+
13575
+ /**
13576
+ * Orthometric height `H = h - N` (metres above mean sea level) from an
13577
+ * ellipsoidal height and a geodetic position in radians, using the embedded
13578
+ * genuine EGM96 1-degree model. Delegates to
13579
+ * `sidereon_core::geoid::egm96_orthometric_height_m`.
13580
+ * @param {number} ellipsoidal_height_m
13581
+ * @param {number} lat_rad
13582
+ * @param {number} lon_rad
13583
+ * @returns {number}
13584
+ */
13585
+ export function egm96OrthometricHeightM(ellipsoidal_height_m, lat_rad, lon_rad) {
13586
+ const ret = wasm.egm96OrthometricHeightM(ellipsoidal_height_m, lat_rad, lon_rad);
13587
+ return ret;
13588
+ }
13589
+
13590
+ /**
13591
+ * Geoid undulation `N` (metres above the WGS84 ellipsoid) at a geodetic
13592
+ * position in radians, from the embedded GENUINE EGM96 1-degree global grid.
13593
+ * Latitude is positive north, longitude positive east. This is the recommended
13594
+ * zero-setup default for metre-class datum work (its bilinear lookup agrees
13595
+ * with the full 15-arcminute EGM96 grid to ~0.4 m RMS); the coarse
13596
+ * [`geoidUndulation`] is only suitable for sanity checks. Delegates to
13597
+ * `sidereon_core::geoid::egm96_undulation`.
13598
+ * @param {number} lat_rad
13599
+ * @param {number} lon_rad
13600
+ * @returns {number}
13601
+ */
13602
+ export function egm96Undulation(lat_rad, lon_rad) {
13603
+ const ret = wasm.egm96Undulation(lat_rad, lon_rad);
13604
+ return ret;
13605
+ }
13606
+
12978
13607
  /**
12979
13608
  * Effective isotropic radiated power, dBW.
12980
13609
  * @param {number} tx_power_dbm
@@ -13126,6 +13755,81 @@ export function encounterPlaneCovariance(frame, covariance_km2) {
13126
13755
  return v2;
13127
13756
  }
13128
13757
 
13758
+ /**
13759
+ * Confidence ellipse from an arbitrary 2x2 covariance block.
13760
+ *
13761
+ * `covariance` is a flat row-major length-4 `Float64Array` (`[c00, c01, c10,
13762
+ * c11]`); `confidence` is in `(0, 1)`. The semi-axes are the eigenvalues of the
13763
+ * symmetrized block scaled by the chi-square(2) quantile. Throws a `RangeError`
13764
+ * for a non-positive-semidefinite block or an out-of-range confidence.
13765
+ * Delegates to `sidereon_core::geometry::error_ellipse_2x2`.
13766
+ * @param {Float64Array} covariance
13767
+ * @param {number} confidence
13768
+ * @returns {ErrorEllipse2}
13769
+ */
13770
+ export function errorEllipse2(covariance, confidence) {
13771
+ const ptr0 = passArrayF64ToWasm0(covariance, wasm.__wbindgen_malloc);
13772
+ const len0 = WASM_VECTOR_LEN;
13773
+ const ret = wasm.errorEllipse2(ptr0, len0, confidence);
13774
+ if (ret[2]) {
13775
+ throw takeFromExternrefTable0(ret[1]);
13776
+ }
13777
+ return ErrorEllipse2.__wrap(ret[0]);
13778
+ }
13779
+
13780
+ /**
13781
+ * Find Moon elevation threshold crossings (moonrise / moonset) over a UTC
13782
+ * window.
13783
+ *
13784
+ * The station is geodetic (`latitudeDeg`, `longitudeDeg`, `altitudeKm`);
13785
+ * `startUnixUs` / `endUnixUs` bound the window in unix microseconds. `options`
13786
+ * is `{ elevationThresholdDeg?, stepSeconds?, timeToleranceSeconds? }`.
13787
+ * Delegates to `sidereon_core::astro::bodies::find_moon_elevation_crossings`.
13788
+ * @param {number} latitude_deg
13789
+ * @param {number} longitude_deg
13790
+ * @param {number} altitude_km
13791
+ * @param {bigint} start_unix_us
13792
+ * @param {bigint} end_unix_us
13793
+ * @param {any} options
13794
+ * @returns {MoonElevationCrossing[]}
13795
+ */
13796
+ export function findMoonElevationCrossings(latitude_deg, longitude_deg, altitude_km, start_unix_us, end_unix_us, options) {
13797
+ const ret = wasm.findMoonElevationCrossings(latitude_deg, longitude_deg, altitude_km, start_unix_us, end_unix_us, options);
13798
+ if (ret[3]) {
13799
+ throw takeFromExternrefTable0(ret[2]);
13800
+ }
13801
+ var v1 = getArrayJsValueFromWasm0(ret[0], ret[1]).slice();
13802
+ wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
13803
+ return v1;
13804
+ }
13805
+
13806
+ /**
13807
+ * Find Moon meridian transits (upper and lower culminations) over a UTC window.
13808
+ *
13809
+ * The station is geodetic (`latitudeDeg`, `longitudeDeg`, `altitudeKm`);
13810
+ * `startUnixUs` / `endUnixUs` bound the window in unix microseconds.
13811
+ * `stepSeconds` is the uniform scan step and `timeToleranceSeconds` the
13812
+ * refinement tolerance. Delegates to
13813
+ * `sidereon_core::astro::bodies::find_moon_transits`.
13814
+ * @param {number} latitude_deg
13815
+ * @param {number} longitude_deg
13816
+ * @param {number} altitude_km
13817
+ * @param {bigint} start_unix_us
13818
+ * @param {bigint} end_unix_us
13819
+ * @param {number} step_seconds
13820
+ * @param {number} time_tolerance_seconds
13821
+ * @returns {MoonTransit[]}
13822
+ */
13823
+ export function findMoonTransits(latitude_deg, longitude_deg, altitude_km, start_unix_us, end_unix_us, step_seconds, time_tolerance_seconds) {
13824
+ const ret = wasm.findMoonTransits(latitude_deg, longitude_deg, altitude_km, start_unix_us, end_unix_us, step_seconds, time_tolerance_seconds);
13825
+ if (ret[3]) {
13826
+ throw takeFromExternrefTable0(ret[2]);
13827
+ }
13828
+ var v1 = getArrayJsValueFromWasm0(ret[0], ret[1]).slice();
13829
+ wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
13830
+ return v1;
13831
+ }
13832
+
13129
13833
  /**
13130
13834
  * Find local TCA candidates between two satellites over a UTC window.
13131
13835
  *
@@ -13837,6 +14541,43 @@ export function gnssVisible(sp3, station_ecef_m, j2000_seconds, options) {
13837
14541
  return v2;
13838
14542
  }
13839
14543
 
14544
+ /**
14545
+ * GPS - UTC (the GNSS leap-second offset since the GPS epoch) on a UTC calendar
14546
+ * date: the IS-GPS-200 quantity broadcast in the navigation message (18 s from
14547
+ * 2017-01-01). Equals `taiUtcOffsetS - 19`. Use this, not [`taiUtcOffsetS`],
14548
+ * whenever you mean the leap seconds a GPS receiver applies. Delegates to
14549
+ * `sidereon_core::astro::time::scales::gps_utc_offset_s`.
14550
+ * @param {number} year
14551
+ * @param {number} month
14552
+ * @param {number} day
14553
+ * @returns {number}
14554
+ */
14555
+ export function gpsUtcOffsetS(year, month, day) {
14556
+ const ret = wasm.gpsUtcOffsetS(year, month, day);
14557
+ return ret;
14558
+ }
14559
+
14560
+ /**
14561
+ * Trace of the Gauss-Newton Hessian approximation `J^T J`: the sum of the
14562
+ * squared column norms of the Jacobian, with no inverse formed.
14563
+ *
14564
+ * `jacobian` is a flat row-major `(m, n)` `Float64Array`. Delegates to
14565
+ * `sidereon_core::astro::math::least_squares::hessian_trace`.
14566
+ * @param {Float64Array} jacobian
14567
+ * @param {number} m
14568
+ * @param {number} n
14569
+ * @returns {number}
14570
+ */
14571
+ export function hessianTrace(jacobian, m, n) {
14572
+ const ptr0 = passArrayF64ToWasm0(jacobian, wasm.__wbindgen_malloc);
14573
+ const len0 = WASM_VECTOR_LEN;
14574
+ const ret = wasm.hessianTrace(ptr0, len0, m, n);
14575
+ if (ret[2]) {
14576
+ throw takeFromExternrefTable0(ret[1]);
14577
+ }
14578
+ return ret[0];
14579
+ }
14580
+
13840
14581
  /**
13841
14582
  * Gauss angles-only orbit determination.
13842
14583
  *
@@ -14034,6 +14775,27 @@ export function j2000SecondsToCivil(seconds) {
14034
14775
  return CivilDateTime.__wrap(ret);
14035
14776
  }
14036
14777
 
14778
+ /**
14779
+ * Jarque-Bera normality test on a residual set.
14780
+ *
14781
+ * `x` is a `Float64Array` (at least two values). Returns
14782
+ * `{ statistic, pValue }` with `statistic = n/6 (S^2 + K^2/4)` (biased moments)
14783
+ * and the chi-square(2) survival `pValue = exp(-statistic/2)`, matching
14784
+ * `scipy.stats.jarque_bera`. Delegates to
14785
+ * `sidereon_core::quality::normality::jarque_bera`.
14786
+ * @param {Float64Array} x
14787
+ * @returns {any}
14788
+ */
14789
+ export function jarqueBera(x) {
14790
+ const ptr0 = passArrayF64ToWasm0(x, wasm.__wbindgen_malloc);
14791
+ const len0 = WASM_VECTOR_LEN;
14792
+ const ret = wasm.jarqueBera(ptr0, len0);
14793
+ if (ret[2]) {
14794
+ throw takeFromExternrefTable0(ret[1]);
14795
+ }
14796
+ return takeFromExternrefTable0(ret[0]);
14797
+ }
14798
+
14037
14799
  /**
14038
14800
  * GPS broadcast Klobuchar ionospheric group delay in the model's native units
14039
14801
  * (positive metres).
@@ -14069,6 +14831,29 @@ export function klobucharDelay(alpha, beta, lat_deg, lon_deg, azimuth_deg, eleva
14069
14831
  return ret[0];
14070
14832
  }
14071
14833
 
14834
+ /**
14835
+ * Sample kurtosis of a residual set.
14836
+ *
14837
+ * `x` is a `Float64Array`. `fisher` (default `true`) returns the excess
14838
+ * kurtosis `m4 / m2^2 - 3` (Gaussian -> 0, `scipy.stats.kurtosis`); `false`
14839
+ * returns the Pearson kurtosis (Gaussian -> 3). `bias` (default `true`); pass
14840
+ * `false` for the sample correction (needs at least four values). Delegates to
14841
+ * `sidereon_core::quality::normality::kurtosis`.
14842
+ * @param {Float64Array} x
14843
+ * @param {boolean | null} [fisher]
14844
+ * @param {boolean | null} [bias]
14845
+ * @returns {number}
14846
+ */
14847
+ export function kurtosis(x, fisher, bias) {
14848
+ const ptr0 = passArrayF64ToWasm0(x, wasm.__wbindgen_malloc);
14849
+ const len0 = WASM_VECTOR_LEN;
14850
+ const ret = wasm.kurtosis(ptr0, len0, isLikeNone(fisher) ? 0xFFFFFF : fisher ? 1 : 0, isLikeNone(bias) ? 0xFFFFFF : bias ? 1 : 0);
14851
+ if (ret[2]) {
14852
+ throw takeFromExternrefTable0(ret[1]);
14853
+ }
14854
+ return ret[0];
14855
+ }
14856
+
14072
14857
  /**
14073
14858
  * Resolve integer ambiguities with the LAMBDA method (RTKLIB `lambda()` port).
14074
14859
  *
@@ -14171,6 +14956,47 @@ export function leapSecondsBatch(dates) {
14171
14956
  return v2;
14172
14957
  }
14173
14958
 
14959
+ /**
14960
+ * Solve a generic data-driven least-squares problem.
14961
+ *
14962
+ * `request` is a `DataProblemInput` object: a `kind` (`"linear"`,
14963
+ * `"polynomial"`, `"exponential"`) carrying its data arrays, the `x0` starting
14964
+ * point, and the SciPy `least_squares` options. The whole trust-region
14965
+ * iteration runs in Rust through
14966
+ * `trust_region_least_squares::data::solve_data_problem` (the serial entry, the
14967
+ * default in-crate SVD backend); no rayon thread pool is entered.
14968
+ * @param {any} request
14969
+ * @returns {LeastSquaresResult}
14970
+ */
14971
+ export function leastSquares(request) {
14972
+ const ret = wasm.leastSquares(request);
14973
+ if (ret[2]) {
14974
+ throw takeFromExternrefTable0(ret[1]);
14975
+ }
14976
+ return LeastSquaresResult.__wrap(ret[0]);
14977
+ }
14978
+
14979
+ /**
14980
+ * Serial leave-one-out (jackknife) over a data-driven least-squares problem.
14981
+ *
14982
+ * Delegates to the core's serial leave-one-out entry
14983
+ * `trust_region_least_squares::batch::solve_data_problem_drop_one_serial`: the
14984
+ * full problem is solved once, then re-solved with each residual row masked in
14985
+ * turn. The core's default `solve_data_problem_drop_one` fans these re-solves
14986
+ * across a rayon pool that wasm has no threads for, so this binding takes the
14987
+ * serial twin, which runs the identical re-solves one row at a time and is
14988
+ * byte-identical to the parallel version.
14989
+ * @param {any} request
14990
+ * @returns {LeastSquaresDropOneReport}
14991
+ */
14992
+ export function leastSquaresDropOne(request) {
14993
+ const ret = wasm.leastSquaresDropOne(request);
14994
+ if (ret[2]) {
14995
+ throw takeFromExternrefTable0(ret[1]);
14996
+ }
14997
+ return LeastSquaresDropOneReport.__wrap(ret[0]);
14998
+ }
14999
+
14174
15000
  /**
14175
15001
  * Decode LNAV subframes 1-3 back into engineering-unit parameters.
14176
15002
  *
@@ -14482,6 +15308,29 @@ export function mergeSp3(sources, options) {
14482
15308
  return Sp3MergeResult.__wrap(ret[0]);
14483
15309
  }
14484
15310
 
15311
+ /**
15312
+ * Mean, variance, skewness, and excess kurtosis of a residual set in one pass.
15313
+ *
15314
+ * `x` is a `Float64Array`; `fisher` and `bias` select the kurtosis convention
15315
+ * and the bias correction exactly as in [`skewness`] / [`kurtosis`] (both
15316
+ * default `true`). Returns `{ mean, variance, skewness, kurtosisExcess }`; the
15317
+ * variance is the biased second central moment. Delegates to
15318
+ * `sidereon_core::quality::normality::moments`.
15319
+ * @param {Float64Array} x
15320
+ * @param {boolean | null} [fisher]
15321
+ * @param {boolean | null} [bias]
15322
+ * @returns {any}
15323
+ */
15324
+ export function moments(x, fisher, bias) {
15325
+ const ptr0 = passArrayF64ToWasm0(x, wasm.__wbindgen_malloc);
15326
+ const len0 = WASM_VECTOR_LEN;
15327
+ const ret = wasm.moments(ptr0, len0, isLikeNone(fisher) ? 0xFFFFFF : fisher ? 1 : 0, isLikeNone(bias) ? 0xFFFFFF : bias ? 1 : 0);
15328
+ if (ret[2]) {
15329
+ throw takeFromExternrefTable0(ret[1]);
15330
+ }
15331
+ return takeFromExternrefTable0(ret[0]);
15332
+ }
15333
+
14485
15334
  /**
14486
15335
  * Angle in degrees between satellite nadir and the Moon direction.
14487
15336
  * @param {Float64Array} satellite_position_km
@@ -14502,6 +15351,64 @@ export function moonAngle(satellite_position_km, moon_position_km) {
14502
15351
  return v3;
14503
15352
  }
14504
15353
 
15354
+ /**
15355
+ * Topocentric azimuth/elevation/range of the Moon from a ground site,
15356
+ * including the diurnal parallax. See [`sunAzEl`] for the argument shapes.
15357
+ * Delegates to `sidereon_core::astro::bodies::moon_az_el`.
15358
+ * @param {number} latitude_deg
15359
+ * @param {number} longitude_deg
15360
+ * @param {number} altitude_km
15361
+ * @param {bigint} epoch_unix_us
15362
+ * @returns {any}
15363
+ */
15364
+ export function moonAzEl(latitude_deg, longitude_deg, altitude_km, epoch_unix_us) {
15365
+ const ret = wasm.moonAzEl(latitude_deg, longitude_deg, altitude_km, epoch_unix_us);
15366
+ if (ret[2]) {
15367
+ throw takeFromExternrefTable0(ret[1]);
15368
+ }
15369
+ return takeFromExternrefTable0(ret[0]);
15370
+ }
15371
+
15372
+ /**
15373
+ * Topocentric geometric Moon (disk-center) elevation from a ground site,
15374
+ * degrees. See [`sunAzEl`] for the argument shapes. Delegates to
15375
+ * `sidereon_core::astro::bodies::moon_az_el` and returns its `elevationDeg`: the
15376
+ * core `moon_elevation_deg` convenience wrapper `expect`s on the geometry, so a
15377
+ * valid-shaped but out-of-range station (e.g. latitude 120) would panic the
15378
+ * wasm module; going through `moon_az_el` surfaces that as a thrown JS error.
15379
+ * @param {number} latitude_deg
15380
+ * @param {number} longitude_deg
15381
+ * @param {number} altitude_km
15382
+ * @param {bigint} epoch_unix_us
15383
+ * @returns {number}
15384
+ */
15385
+ export function moonElevationDeg(latitude_deg, longitude_deg, altitude_km, epoch_unix_us) {
15386
+ const ret = wasm.moonElevationDeg(latitude_deg, longitude_deg, altitude_km, epoch_unix_us);
15387
+ if (ret[2]) {
15388
+ throw takeFromExternrefTable0(ret[1]);
15389
+ }
15390
+ return ret[0];
15391
+ }
15392
+
15393
+ /**
15394
+ * Illuminated fraction of the Moon as seen from a ground site. Returns
15395
+ * `{ illuminatedFraction, phaseAngleDeg }` (0 = new, 1 = full). See [`sunAzEl`]
15396
+ * for the argument shapes. Delegates to
15397
+ * `sidereon_core::astro::bodies::moon_illumination`.
15398
+ * @param {number} latitude_deg
15399
+ * @param {number} longitude_deg
15400
+ * @param {number} altitude_km
15401
+ * @param {bigint} epoch_unix_us
15402
+ * @returns {any}
15403
+ */
15404
+ export function moonIllumination(latitude_deg, longitude_deg, altitude_km, epoch_unix_us) {
15405
+ const ret = wasm.moonIllumination(latitude_deg, longitude_deg, altitude_km, epoch_unix_us);
15406
+ if (ret[2]) {
15407
+ throw takeFromExternrefTable0(ret[1]);
15408
+ }
15409
+ return takeFromExternrefTable0(ret[0]);
15410
+ }
15411
+
14505
15412
  /**
14506
15413
  * Narrow-lane code combination, metres.
14507
15414
  * @param {number} p1_m
@@ -14594,6 +15501,36 @@ export function noiseAmplification(f1_hz, f2_hz) {
14594
15501
  return ret[0];
14595
15502
  }
14596
15503
 
15504
+ /**
15505
+ * Parameter covariance from a design (Jacobian) matrix via the Gauss-Newton
15506
+ * normal equations `varianceScale * (J^T J)^-1`, formed from the thin SVD of
15507
+ * `J` (not by inverting `J^T J`, so the condition number is not squared).
15508
+ *
15509
+ * `jacobian` is a flat row-major `(m, n)` `Float64Array` with `m >= n`;
15510
+ * `varianceScale` (`sigma^2`, non-negative) scales the bare cofactor (pass the
15511
+ * post-fit reduced chi-square for the fitted covariance, or `1.0` for
15512
+ * `(J^T J)^-1`). Returns the `n`-by-`n` covariance as a flat row-major
15513
+ * `Float64Array` of length `n * n`. Throws an `Error` for a rank-deficient
15514
+ * Jacobian. Delegates to
15515
+ * `sidereon_core::astro::math::least_squares::normal_covariance`.
15516
+ * @param {Float64Array} jacobian
15517
+ * @param {number} m
15518
+ * @param {number} n
15519
+ * @param {number} variance_scale
15520
+ * @returns {Float64Array}
15521
+ */
15522
+ export function normalCovariance(jacobian, m, n, variance_scale) {
15523
+ const ptr0 = passArrayF64ToWasm0(jacobian, wasm.__wbindgen_malloc);
15524
+ const len0 = WASM_VECTOR_LEN;
15525
+ const ret = wasm.normalCovariance(ptr0, len0, m, n, variance_scale);
15526
+ if (ret[3]) {
15527
+ throw takeFromExternrefTable0(ret[2]);
15528
+ }
15529
+ var v2 = getArrayF64FromWasm0(ret[0], ret[1]).slice();
15530
+ wasm.__wbindgen_free(ret[0], ret[1] * 8, 8);
15531
+ return v2;
15532
+ }
15533
+
14597
15534
  /**
14598
15535
  * Predict observables for one satellite from a broadcast ephemeris store.
14599
15536
  * Delegates to `sidereon_core::observables::predict`.
@@ -15101,6 +16038,86 @@ export function pppCorrections(sp3, epochs, receiver_ecef_m, options) {
15101
16038
  return takeFromExternrefTable0(ret[0]);
15102
16039
  }
15103
16040
 
16041
+ /**
16042
+ * Build a sample-backed precise-ephemeris source from an array of samples.
16043
+ *
16044
+ * `samples` is an array of `{ sat, epoch, positionEcefM, clockS?, clockEvent? }`
16045
+ * objects (see the sample field docs). Samples are grouped by satellite in their
16046
+ * supplied order; each satellite needs at least two strictly time-increasing
16047
+ * samples. Throws a `TypeError` for a malformed object or bad satellite token
16048
+ * and a `RangeError` for a non-finite epoch or a source validation failure
16049
+ * (empty input, a single-sample satellite, non-monotonic epochs, a non-finite
16050
+ * sample). Delegates to `sidereon_core::sp3::PreciseEphemerisSamples::from_samples`.
16051
+ * @param {any} samples
16052
+ * @returns {PreciseEphemerisSampleSource}
16053
+ */
16054
+ export function preciseEphemerisSamplesFromSamples(samples) {
16055
+ const ret = wasm.preciseEphemerisSamplesFromSamples(samples);
16056
+ if (ret[2]) {
16057
+ throw takeFromExternrefTable0(ret[1]);
16058
+ }
16059
+ return PreciseEphemerisSampleSource.__wrap(ret[0]);
16060
+ }
16061
+
16062
+ /**
16063
+ * Predict observables for many `(satellite, receiver, epoch)` requests from a
16064
+ * broadcast ephemeris store, serially. See [`predictBatchSp3`] for the argument
16065
+ * shapes. Delegates to the serial `sidereon_core::observables::predict_batch`.
16066
+ * @param {BroadcastEphemeris} broadcast
16067
+ * @param {string[]} satellites
16068
+ * @param {Float64Array} receivers_ecef_m
16069
+ * @param {Float64Array} epochs_j2000_s
16070
+ * @param {any} options
16071
+ * @returns {PredictBatch}
16072
+ */
16073
+ export function predictBatchBroadcast(broadcast, satellites, receivers_ecef_m, epochs_j2000_s, options) {
16074
+ _assertClass(broadcast, BroadcastEphemeris);
16075
+ const ptr0 = passArrayJsValueToWasm0(satellites, wasm.__wbindgen_malloc);
16076
+ const len0 = WASM_VECTOR_LEN;
16077
+ const ptr1 = passArrayF64ToWasm0(receivers_ecef_m, wasm.__wbindgen_malloc);
16078
+ const len1 = WASM_VECTOR_LEN;
16079
+ const ptr2 = passArrayF64ToWasm0(epochs_j2000_s, wasm.__wbindgen_malloc);
16080
+ const len2 = WASM_VECTOR_LEN;
16081
+ const ret = wasm.predictBatchBroadcast(broadcast.__wbg_ptr, ptr0, len0, ptr1, len1, ptr2, len2, options);
16082
+ if (ret[2]) {
16083
+ throw takeFromExternrefTable0(ret[1]);
16084
+ }
16085
+ return PredictBatch.__wrap(ret[0]);
16086
+ }
16087
+
16088
+ /**
16089
+ * Predict observables for many `(satellite, receiver, epoch)` requests from an
16090
+ * SP3 precise product, serially.
16091
+ *
16092
+ * `satellites` is an array of satellite tokens, `receiversEcefM` a flat
16093
+ * row-major `(n, 3)` `Float64Array` of receiver ECEF positions (metres), and
16094
+ * `epochsJ2000S` a `Float64Array` of receive epochs (seconds since J2000); all
16095
+ * three are index-aligned and length `n`. Element `i` of the result corresponds
16096
+ * to request `i`. Delegates to the serial reference kernel
16097
+ * `sidereon_core::observables::predict_batch`; the binding never spawns the
16098
+ * rayon thread pool the parallel variant uses.
16099
+ * @param {Sp3} sp3
16100
+ * @param {string[]} satellites
16101
+ * @param {Float64Array} receivers_ecef_m
16102
+ * @param {Float64Array} epochs_j2000_s
16103
+ * @param {any} options
16104
+ * @returns {PredictBatch}
16105
+ */
16106
+ export function predictBatchSp3(sp3, satellites, receivers_ecef_m, epochs_j2000_s, options) {
16107
+ _assertClass(sp3, Sp3);
16108
+ const ptr0 = passArrayJsValueToWasm0(satellites, wasm.__wbindgen_malloc);
16109
+ const len0 = WASM_VECTOR_LEN;
16110
+ const ptr1 = passArrayF64ToWasm0(receivers_ecef_m, wasm.__wbindgen_malloc);
16111
+ const len1 = WASM_VECTOR_LEN;
16112
+ const ptr2 = passArrayF64ToWasm0(epochs_j2000_s, wasm.__wbindgen_malloc);
16113
+ const len2 = WASM_VECTOR_LEN;
16114
+ const ret = wasm.predictBatchSp3(sp3.__wbg_ptr, ptr0, len0, ptr1, len1, ptr2, len2, options);
16115
+ if (ret[2]) {
16116
+ throw takeFromExternrefTable0(ret[1]);
16117
+ }
16118
+ return PredictBatch.__wrap(ret[0]);
16119
+ }
16120
+
15104
16121
  /**
15105
16122
  * Prepare ionosphere-free single-frequency RTK arc inputs from a
15106
16123
  * dual-frequency arc and fixed wide-lane ambiguities.
@@ -15542,6 +16559,26 @@ export function shadowFraction(satellite_position_km, sun_position_km) {
15542
16559
  return v3;
15543
16560
  }
15544
16561
 
16562
+ /**
16563
+ * Shapiro-Wilk normality test on a residual set.
16564
+ *
16565
+ * `x` is a `Float64Array` (at least three values). Returns `{ w, pValue }`,
16566
+ * Royston's AS R94 port that `scipy.stats.shapiro` uses; `w` is in `(0, 1]`
16567
+ * (closer to one is more Gaussian). Delegates to
16568
+ * `sidereon_core::quality::normality::shapiro_wilk`.
16569
+ * @param {Float64Array} x
16570
+ * @returns {any}
16571
+ */
16572
+ export function shapiroWilk(x) {
16573
+ const ptr0 = passArrayF64ToWasm0(x, wasm.__wbindgen_malloc);
16574
+ const len0 = WASM_VECTOR_LEN;
16575
+ const ret = wasm.shapiroWilk(ptr0, len0);
16576
+ if (ret[2]) {
16577
+ throw takeFromExternrefTable0(ret[1]);
16578
+ }
16579
+ return takeFromExternrefTable0(ret[0]);
16580
+ }
16581
+
15545
16582
  /**
15546
16583
  * Build satellite-keyed pseudorange sigmas in metres from `{ satelliteId,
15547
16584
  * elevationDeg, cn0Dbhz? }` entries. Invalid entries are dropped by the core.
@@ -15557,6 +16594,27 @@ export function sigmas(entries, options) {
15557
16594
  return SatelliteVector.__wrap(ret[0]);
15558
16595
  }
15559
16596
 
16597
+ /**
16598
+ * Sample skewness of a residual set.
16599
+ *
16600
+ * `x` is a `Float64Array`. `bias` (default `true`) selects the Fisher-Pearson
16601
+ * coefficient `g1 = m3 / m2^(3/2)` (`scipy.stats.skew`); `false` applies the
16602
+ * sample correction (`scipy.stats.skew(bias=False)`, needs at least three
16603
+ * values). Delegates to `sidereon_core::quality::normality::skewness`.
16604
+ * @param {Float64Array} x
16605
+ * @param {boolean | null} [bias]
16606
+ * @returns {number}
16607
+ */
16608
+ export function skewness(x, bias) {
16609
+ const ptr0 = passArrayF64ToWasm0(x, wasm.__wbindgen_malloc);
16610
+ const len0 = WASM_VECTOR_LEN;
16611
+ const ret = wasm.skewness(ptr0, len0, isLikeNone(bias) ? 0xFFFFFF : bias ? 1 : 0);
16612
+ if (ret[2]) {
16613
+ throw takeFromExternrefTable0(ret[1]);
16614
+ }
16615
+ return ret[0];
16616
+ }
16617
+
15560
16618
  /**
15561
16619
  * Stable lower-case label for a slip reason.
15562
16620
  * @param {SlipReason} reason
@@ -15943,6 +17001,29 @@ export function solveWithFallback(precise, broadcast, request, policy) {
15943
17001
  return SourcedSolution.__wrap(ret[0]);
15944
17002
  }
15945
17003
 
17004
+ /**
17005
+ * Extract a parsed SP3 product as the canonical precise-ephemeris samples, one
17006
+ * per real position record in ascending epoch order.
17007
+ *
17008
+ * Returns an array of `{ sat, epoch, positionEcefM, clockS, clockEvent }`
17009
+ * objects. Round-tripping the result back through
17010
+ * [`preciseEphemerisSamplesFromSamples`] rebuilds an interpolatable source that
17011
+ * reproduces the SP3-parsed source's interpolated states and predicted ranges
17012
+ * to the documented round-trip precision (byte-identical for samples whose
17013
+ * meters are the faithful image of the fit nodes; see the core module docs).
17014
+ * Delegates to `sidereon_core::sp3::Sp3::precise_ephemeris_samples`.
17015
+ * @param {Sp3} sp3
17016
+ * @returns {any}
17017
+ */
17018
+ export function sp3PreciseEphemerisSamples(sp3) {
17019
+ _assertClass(sp3, Sp3);
17020
+ const ret = wasm.sp3PreciseEphemerisSamples(sp3.__wbg_ptr);
17021
+ if (ret[2]) {
17022
+ throw takeFromExternrefTable0(ret[1]);
17023
+ }
17024
+ return takeFromExternrefTable0(ret[0]);
17025
+ }
17026
+
15946
17027
  /**
15947
17028
  * Continuous seconds since J2000 for a split Julian date.
15948
17029
  * @param {number} jd_whole
@@ -16019,6 +17100,27 @@ export function sunAngle(satellite_position_km, sun_position_km) {
16019
17100
  return v3;
16020
17101
  }
16021
17102
 
17103
+ /**
17104
+ * Topocentric azimuth/elevation/range of the Sun from a ground site.
17105
+ *
17106
+ * The station is geodetic (`latitudeDeg`, `longitudeDeg`, `altitudeKm`);
17107
+ * `epochUnixUs` is the UTC instant as unix microseconds. Returns
17108
+ * `{ azimuthDeg, elevationDeg, rangeKm }` (azimuth clockwise from north).
17109
+ * Delegates to `sidereon_core::astro::bodies::sun_az_el`.
17110
+ * @param {number} latitude_deg
17111
+ * @param {number} longitude_deg
17112
+ * @param {number} altitude_km
17113
+ * @param {bigint} epoch_unix_us
17114
+ * @returns {any}
17115
+ */
17116
+ export function sunAzEl(latitude_deg, longitude_deg, altitude_km, epoch_unix_us) {
17117
+ const ret = wasm.sunAzEl(latitude_deg, longitude_deg, altitude_km, epoch_unix_us);
17118
+ if (ret[2]) {
17119
+ throw takeFromExternrefTable0(ret[1]);
17120
+ }
17121
+ return takeFromExternrefTable0(ret[0]);
17122
+ }
17123
+
16022
17124
  /**
16023
17125
  * Sun elevation in degrees above the satellite local horizontal plane.
16024
17126
  * @param {Float64Array} satellite_position_km
@@ -16071,6 +17173,22 @@ export function sunMoonEci(epochs_unix_us) {
16071
17173
  return SunMoon.__wrap(ret[0]);
16072
17174
  }
16073
17175
 
17176
+ /**
17177
+ * TAI-UTC (cumulative leap seconds) in effect on a UTC calendar date.
17178
+ *
17179
+ * This is **not** the GNSS "GPS - UTC" offset; for the quantity a GPS receiver
17180
+ * applies use [`gpsUtcOffsetS`] (they differ by a constant 19 s). Delegates to
17181
+ * `sidereon_core::astro::time::scales::tai_utc_offset_s`.
17182
+ * @param {number} year
17183
+ * @param {number} month
17184
+ * @param {number} day
17185
+ * @returns {number}
17186
+ */
17187
+ export function taiUtcOffsetS(year, month, day) {
17188
+ const ret = wasm.taiUtcOffsetS(year, month, day);
17189
+ return ret;
17190
+ }
17191
+
16074
17192
  /**
16075
17193
  * Transform a batch of TEME states to GCRS, each at its own epoch.
16076
17194
  *
@@ -16163,8 +17281,8 @@ export function timescaleOffsetAtS(from, to, utc_jd) {
16163
17281
  *
16164
17282
  * Covers the atomic scales (TAI/TT/GPST/GST/QZSST/BDT), whose mutual offsets
16165
17283
  * are constants fixed by their ICDs. Throws a `RangeError` when either scale is
16166
- * UTC-based (`Utc`/`Glonasst`) those carry leap seconds, so their offset is
16167
- * epoch-dependent and needs [`timescaleOffsetAtS`] or for `Tdb` (no fixed
17284
+ * UTC-based (`Utc`/`Glonasst`): those carry leap seconds, so their offset is
17285
+ * epoch-dependent and needs [`timescaleOffsetAtS`], or for `Tdb` (no fixed
16168
17286
  * offset; resolve it through an `Instant`).
16169
17287
  * @param {TimeScale} from
16170
17288
  * @param {TimeScale} to
@@ -16651,6 +17769,14 @@ function __wbg_get_imports() {
16651
17769
  const ret = LookAngles.__wrap(arg0);
16652
17770
  return ret;
16653
17771
  },
17772
+ __wbg_moonelevationcrossing_new: function(arg0) {
17773
+ const ret = MoonElevationCrossing.__wrap(arg0);
17774
+ return ret;
17775
+ },
17776
+ __wbg_moontransit_new: function(arg0) {
17777
+ const ret = MoonTransit.__wrap(arg0);
17778
+ return ret;
17779
+ },
16654
17780
  __wbg_movingbaselinesolution_new: function(arg0) {
16655
17781
  const ret = MovingBaselineSolution.__wrap(arg0);
16656
17782
  return ret;
@@ -16935,6 +18061,9 @@ const EncounterFrameFinalization = (typeof FinalizationRegistry === 'undefined')
16935
18061
  const EphemerisFinalization = (typeof FinalizationRegistry === 'undefined')
16936
18062
  ? { register: () => {}, unregister: () => {} }
16937
18063
  : new FinalizationRegistry(ptr => wasm.__wbg_ephemeris_free(ptr, 1));
18064
+ const ErrorEllipse2Finalization = (typeof FinalizationRegistry === 'undefined')
18065
+ ? { register: () => {}, unregister: () => {} }
18066
+ : new FinalizationRegistry(ptr => wasm.__wbg_errorellipse2_free(ptr, 1));
16938
18067
  const FdeSolutionFinalization = (typeof FinalizationRegistry === 'undefined')
16939
18068
  ? { register: () => {}, unregister: () => {} }
16940
18069
  : new FinalizationRegistry(ptr => wasm.__wbg_fdesolution_free(ptr, 1));
@@ -17013,6 +18142,12 @@ const LambertTransferFinalization = (typeof FinalizationRegistry === 'undefined'
17013
18142
  const LeapSecondTableFinalization = (typeof FinalizationRegistry === 'undefined')
17014
18143
  ? { register: () => {}, unregister: () => {} }
17015
18144
  : new FinalizationRegistry(ptr => wasm.__wbg_leapsecondtable_free(ptr, 1));
18145
+ const LeastSquaresDropOneReportFinalization = (typeof FinalizationRegistry === 'undefined')
18146
+ ? { register: () => {}, unregister: () => {} }
18147
+ : new FinalizationRegistry(ptr => wasm.__wbg_leastsquaresdroponereport_free(ptr, 1));
18148
+ const LeastSquaresResultFinalization = (typeof FinalizationRegistry === 'undefined')
18149
+ ? { register: () => {}, unregister: () => {} }
18150
+ : new FinalizationRegistry(ptr => wasm.__wbg_leastsquaresresult_free(ptr, 1));
17016
18151
  const LinkBudgetFinalization = (typeof FinalizationRegistry === 'undefined')
17017
18152
  ? { register: () => {}, unregister: () => {} }
17018
18153
  : new FinalizationRegistry(ptr => wasm.__wbg_linkbudget_free(ptr, 1));
@@ -17028,6 +18163,12 @@ const LookAnglesFinalization = (typeof FinalizationRegistry === 'undefined')
17028
18163
  const MappingFactorsFinalization = (typeof FinalizationRegistry === 'undefined')
17029
18164
  ? { register: () => {}, unregister: () => {} }
17030
18165
  : new FinalizationRegistry(ptr => wasm.__wbg_mappingfactors_free(ptr, 1));
18166
+ const MoonElevationCrossingFinalization = (typeof FinalizationRegistry === 'undefined')
18167
+ ? { register: () => {}, unregister: () => {} }
18168
+ : new FinalizationRegistry(ptr => wasm.__wbg_moonelevationcrossing_free(ptr, 1));
18169
+ const MoonTransitFinalization = (typeof FinalizationRegistry === 'undefined')
18170
+ ? { register: () => {}, unregister: () => {} }
18171
+ : new FinalizationRegistry(ptr => wasm.__wbg_moontransit_free(ptr, 1));
17031
18172
  const MovingBaselineSolutionFinalization = (typeof FinalizationRegistry === 'undefined')
17032
18173
  ? { register: () => {}, unregister: () => {} }
17033
18174
  : new FinalizationRegistry(ptr => wasm.__wbg_movingbaselinesolution_free(ptr, 1));
@@ -17109,6 +18250,12 @@ const PppFixedSolutionFinalization = (typeof FinalizationRegistry === 'undefined
17109
18250
  const PppFloatSolutionFinalization = (typeof FinalizationRegistry === 'undefined')
17110
18251
  ? { register: () => {}, unregister: () => {} }
17111
18252
  : new FinalizationRegistry(ptr => wasm.__wbg_pppfloatsolution_free(ptr, 1));
18253
+ const PreciseEphemerisSampleSourceFinalization = (typeof FinalizationRegistry === 'undefined')
18254
+ ? { register: () => {}, unregister: () => {} }
18255
+ : new FinalizationRegistry(ptr => wasm.__wbg_preciseephemerissamplesource_free(ptr, 1));
18256
+ const PredictBatchFinalization = (typeof FinalizationRegistry === 'undefined')
18257
+ ? { register: () => {}, unregister: () => {} }
18258
+ : new FinalizationRegistry(ptr => wasm.__wbg_predictbatch_free(ptr, 1));
17112
18259
  const PredictedObservablesFinalization = (typeof FinalizationRegistry === 'undefined')
17113
18260
  ? { register: () => {}, unregister: () => {} }
17114
18261
  : new FinalizationRegistry(ptr => wasm.__wbg_predictedobservables_free(ptr, 1));