@neilberkman/sidereon 0.9.0 → 0.9.1

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.
@@ -3317,6 +3317,72 @@ class Ephemeris {
3317
3317
  if (Symbol.dispose) Ephemeris.prototype[Symbol.dispose] = Ephemeris.prototype.free;
3318
3318
  exports.Ephemeris = Ephemeris;
3319
3319
 
3320
+ /**
3321
+ * A confidence ellipse from a 2x2 covariance block: semi-axes scaled by the
3322
+ * two-degree-of-freedom chi-square quantile `-2 ln(1 - confidence)`.
3323
+ */
3324
+ class ErrorEllipse2 {
3325
+ static __wrap(ptr) {
3326
+ const obj = Object.create(ErrorEllipse2.prototype);
3327
+ obj.__wbg_ptr = ptr;
3328
+ ErrorEllipse2Finalization.register(obj, obj.__wbg_ptr, obj);
3329
+ return obj;
3330
+ }
3331
+ __destroy_into_raw() {
3332
+ const ptr = this.__wbg_ptr;
3333
+ this.__wbg_ptr = 0;
3334
+ ErrorEllipse2Finalization.unregister(this);
3335
+ return ptr;
3336
+ }
3337
+ free() {
3338
+ const ptr = this.__destroy_into_raw();
3339
+ wasm.__wbg_errorellipse2_free(ptr, 0);
3340
+ }
3341
+ /**
3342
+ * Two-degree-of-freedom chi-square scale `-2 ln(1 - confidence)`.
3343
+ * @returns {number}
3344
+ */
3345
+ get chiSquareScale() {
3346
+ const ret = wasm.errorellipse2_chiSquareScale(this.__wbg_ptr);
3347
+ return ret;
3348
+ }
3349
+ /**
3350
+ * Requested confidence probability in `(0, 1)`.
3351
+ * @returns {number}
3352
+ */
3353
+ get confidence() {
3354
+ const ret = wasm.errorellipse2_confidence(this.__wbg_ptr);
3355
+ return ret;
3356
+ }
3357
+ /**
3358
+ * Semi-major-axis orientation in radians, from the first (row/col 0) axis
3359
+ * toward the second (row/col 1) axis.
3360
+ * @returns {number}
3361
+ */
3362
+ get orientationRad() {
3363
+ const ret = wasm.errorellipse2_orientationRad(this.__wbg_ptr);
3364
+ return ret;
3365
+ }
3366
+ /**
3367
+ * Semi-major axis length (same unit as the square root of the covariance).
3368
+ * @returns {number}
3369
+ */
3370
+ get semiMajor() {
3371
+ const ret = wasm.errorellipse2_semiMajor(this.__wbg_ptr);
3372
+ return ret;
3373
+ }
3374
+ /**
3375
+ * Semi-minor axis length.
3376
+ * @returns {number}
3377
+ */
3378
+ get semiMinor() {
3379
+ const ret = wasm.errorellipse2_semiMinor(this.__wbg_ptr);
3380
+ return ret;
3381
+ }
3382
+ }
3383
+ if (Symbol.dispose) ErrorEllipse2.prototype[Symbol.dispose] = ErrorEllipse2.prototype.free;
3384
+ exports.ErrorEllipse2 = ErrorEllipse2;
3385
+
3320
3386
  /**
3321
3387
  * A fault-detection-and-exclusion result: the surviving solution, the excluded
3322
3388
  * satellites in exclusion order, and the number of exclusions performed.
@@ -5324,6 +5390,203 @@ class LeapSecondTable {
5324
5390
  if (Symbol.dispose) LeapSecondTable.prototype[Symbol.dispose] = LeapSecondTable.prototype.free;
5325
5391
  exports.LeapSecondTable = LeapSecondTable;
5326
5392
 
5393
+ /**
5394
+ * A serial leave-one-out sweep: the base solve over all rows plus one re-solve
5395
+ * per masked row, with the per-row optimum-cost shift.
5396
+ */
5397
+ class LeastSquaresDropOneReport {
5398
+ static __wrap(ptr) {
5399
+ const obj = Object.create(LeastSquaresDropOneReport.prototype);
5400
+ obj.__wbg_ptr = ptr;
5401
+ LeastSquaresDropOneReportFinalization.register(obj, obj.__wbg_ptr, obj);
5402
+ return obj;
5403
+ }
5404
+ __destroy_into_raw() {
5405
+ const ptr = this.__wbg_ptr;
5406
+ this.__wbg_ptr = 0;
5407
+ LeastSquaresDropOneReportFinalization.unregister(this);
5408
+ return ptr;
5409
+ }
5410
+ free() {
5411
+ const ptr = this.__destroy_into_raw();
5412
+ wasm.__wbg_leastsquaresdroponereport_free(ptr, 0);
5413
+ }
5414
+ /**
5415
+ * The solve over the full residual.
5416
+ * @returns {LeastSquaresResult}
5417
+ */
5418
+ get base() {
5419
+ const ret = wasm.leastsquaresdroponereport_base(this.__wbg_ptr);
5420
+ return LeastSquaresResult.__wrap(ret);
5421
+ }
5422
+ /**
5423
+ * `costDeltas[i] = dropAt(i).cost - base.cost`: how much the optimum cost
5424
+ * moves when row `i` is removed. `Float64Array` of length `count`.
5425
+ * @returns {Float64Array}
5426
+ */
5427
+ get costDeltas() {
5428
+ const ret = wasm.leastsquaresdroponereport_costDeltas(this.__wbg_ptr);
5429
+ var v1 = getArrayF64FromWasm0(ret[0], ret[1]).slice();
5430
+ wasm.__wbindgen_free(ret[0], ret[1] * 8, 8);
5431
+ return v1;
5432
+ }
5433
+ /**
5434
+ * Number of masked-row re-solves (equals the residual-row count `m`).
5435
+ * @returns {number}
5436
+ */
5437
+ get count() {
5438
+ const ret = wasm.leastsquaresdroponereport_count(this.__wbg_ptr);
5439
+ return ret >>> 0;
5440
+ }
5441
+ /**
5442
+ * The solve with residual row `index` masked out. Throws a `RangeError` for
5443
+ * an out-of-range index.
5444
+ * @param {number} index
5445
+ * @returns {LeastSquaresResult}
5446
+ */
5447
+ dropAt(index) {
5448
+ const ret = wasm.leastsquaresdroponereport_dropAt(this.__wbg_ptr, index);
5449
+ if (ret[2]) {
5450
+ throw takeFromExternrefTable0(ret[1]);
5451
+ }
5452
+ return LeastSquaresResult.__wrap(ret[0]);
5453
+ }
5454
+ }
5455
+ if (Symbol.dispose) LeastSquaresDropOneReport.prototype[Symbol.dispose] = LeastSquaresDropOneReport.prototype.free;
5456
+ exports.LeastSquaresDropOneReport = LeastSquaresDropOneReport;
5457
+
5458
+ /**
5459
+ * The outcome of one trust-region least-squares solve, mirroring the fields of
5460
+ * `scipy.optimize.least_squares`'s `OptimizeResult`.
5461
+ */
5462
+ class LeastSquaresResult {
5463
+ static __wrap(ptr) {
5464
+ const obj = Object.create(LeastSquaresResult.prototype);
5465
+ obj.__wbg_ptr = ptr;
5466
+ LeastSquaresResultFinalization.register(obj, obj.__wbg_ptr, obj);
5467
+ return obj;
5468
+ }
5469
+ __destroy_into_raw() {
5470
+ const ptr = this.__wbg_ptr;
5471
+ this.__wbg_ptr = 0;
5472
+ LeastSquaresResultFinalization.unregister(this);
5473
+ return ptr;
5474
+ }
5475
+ free() {
5476
+ const ptr = this.__destroy_into_raw();
5477
+ wasm.__wbg_leastsquaresresult_free(ptr, 0);
5478
+ }
5479
+ /**
5480
+ * Optimal cost `0.5 * sum(residual^2)` (after robust reweighting when a
5481
+ * non-linear loss is used).
5482
+ * @returns {number}
5483
+ */
5484
+ get cost() {
5485
+ const ret = wasm.leastsquaresresult_cost(this.__wbg_ptr);
5486
+ return ret;
5487
+ }
5488
+ /**
5489
+ * Residual vector at the solution, `Float64Array` of length `m`.
5490
+ * @returns {Float64Array}
5491
+ */
5492
+ get fun() {
5493
+ const ret = wasm.leastsquaresresult_fun(this.__wbg_ptr);
5494
+ var v1 = getArrayF64FromWasm0(ret[0], ret[1]).slice();
5495
+ wasm.__wbindgen_free(ret[0], ret[1] * 8, 8);
5496
+ return v1;
5497
+ }
5498
+ /**
5499
+ * Gradient `J^T f` at the solution, `Float64Array` of length `n`.
5500
+ * @returns {Float64Array}
5501
+ */
5502
+ get grad() {
5503
+ const ret = wasm.leastsquaresresult_grad(this.__wbg_ptr);
5504
+ var v1 = getArrayF64FromWasm0(ret[0], ret[1]).slice();
5505
+ wasm.__wbindgen_free(ret[0], ret[1] * 8, 8);
5506
+ return v1;
5507
+ }
5508
+ /**
5509
+ * Row-major `m`-by-`n` Jacobian at the solution, flat `Float64Array` of
5510
+ * length `m * n`.
5511
+ * @returns {Float64Array}
5512
+ */
5513
+ get jac() {
5514
+ const ret = wasm.leastsquaresresult_jac(this.__wbg_ptr);
5515
+ var v1 = getArrayF64FromWasm0(ret[0], ret[1]).slice();
5516
+ wasm.__wbindgen_free(ret[0], ret[1] * 8, 8);
5517
+ return v1;
5518
+ }
5519
+ /**
5520
+ * Residual row count `m`.
5521
+ * @returns {number}
5522
+ */
5523
+ get m() {
5524
+ const ret = wasm.leastsquaresresult_m(this.__wbg_ptr);
5525
+ return ret >>> 0;
5526
+ }
5527
+ /**
5528
+ * Parameter count `n`.
5529
+ * @returns {number}
5530
+ */
5531
+ get n() {
5532
+ const ret = wasm.leastsquaresresult_n(this.__wbg_ptr);
5533
+ return ret >>> 0;
5534
+ }
5535
+ /**
5536
+ * Number of residual evaluations.
5537
+ * @returns {number}
5538
+ */
5539
+ get nfev() {
5540
+ const ret = wasm.leastsquaresresult_nfev(this.__wbg_ptr);
5541
+ return ret >>> 0;
5542
+ }
5543
+ /**
5544
+ * Number of Jacobian evaluations.
5545
+ * @returns {number}
5546
+ */
5547
+ get njev() {
5548
+ const ret = wasm.leastsquaresresult_njev(this.__wbg_ptr);
5549
+ return ret >>> 0;
5550
+ }
5551
+ /**
5552
+ * First-order optimality `||J^T f||_inf` at the solution.
5553
+ * @returns {number}
5554
+ */
5555
+ get optimality() {
5556
+ const ret = wasm.leastsquaresresult_optimality(this.__wbg_ptr);
5557
+ return ret;
5558
+ }
5559
+ /**
5560
+ * SciPy-compatible termination status: `0` max evaluations, `1` gtol,
5561
+ * `2` ftol, `3` xtol, `4` both ftol and xtol.
5562
+ * @returns {number}
5563
+ */
5564
+ get status() {
5565
+ const ret = wasm.leastsquaresresult_status(this.__wbg_ptr);
5566
+ return ret;
5567
+ }
5568
+ /**
5569
+ * Whether the solve converged (`status > 0`).
5570
+ * @returns {boolean}
5571
+ */
5572
+ get success() {
5573
+ const ret = wasm.leastsquaresresult_success(this.__wbg_ptr);
5574
+ return ret !== 0;
5575
+ }
5576
+ /**
5577
+ * Solution parameter vector, `Float64Array` of length `n`.
5578
+ * @returns {Float64Array}
5579
+ */
5580
+ get x() {
5581
+ const ret = wasm.leastsquaresresult_x(this.__wbg_ptr);
5582
+ var v1 = getArrayF64FromWasm0(ret[0], ret[1]).slice();
5583
+ wasm.__wbindgen_free(ret[0], ret[1] * 8, 8);
5584
+ return v1;
5585
+ }
5586
+ }
5587
+ if (Symbol.dispose) LeastSquaresResult.prototype[Symbol.dispose] = LeastSquaresResult.prototype.free;
5588
+ exports.LeastSquaresResult = LeastSquaresResult;
5589
+
5327
5590
  /**
5328
5591
  * Link-budget inputs for [`LinkBudget.margin`].
5329
5592
  */
@@ -5826,6 +6089,119 @@ class MappingFactors {
5826
6089
  if (Symbol.dispose) MappingFactors.prototype[Symbol.dispose] = MappingFactors.prototype.free;
5827
6090
  exports.MappingFactors = MappingFactors;
5828
6091
 
6092
+ /**
6093
+ * One refined Moon elevation threshold crossing (moonrise / moonset).
6094
+ */
6095
+ class MoonElevationCrossing {
6096
+ static __wrap(ptr) {
6097
+ const obj = Object.create(MoonElevationCrossing.prototype);
6098
+ obj.__wbg_ptr = ptr;
6099
+ MoonElevationCrossingFinalization.register(obj, obj.__wbg_ptr, obj);
6100
+ return obj;
6101
+ }
6102
+ __destroy_into_raw() {
6103
+ const ptr = this.__wbg_ptr;
6104
+ this.__wbg_ptr = 0;
6105
+ MoonElevationCrossingFinalization.unregister(this);
6106
+ return ptr;
6107
+ }
6108
+ free() {
6109
+ const ptr = this.__destroy_into_raw();
6110
+ wasm.__wbg_moonelevationcrossing_free(ptr, 0);
6111
+ }
6112
+ /**
6113
+ * Topocentric Moon elevation at the refined instant, degrees.
6114
+ * @returns {number}
6115
+ */
6116
+ get elevationDeg() {
6117
+ const ret = wasm.moonelevationcrossing_elevationDeg(this.__wbg_ptr);
6118
+ return ret;
6119
+ }
6120
+ /**
6121
+ * Crossing direction: `"rising"` (moonrise) or `"setting"` (moonset).
6122
+ * @returns {string}
6123
+ */
6124
+ get kind() {
6125
+ let deferred1_0;
6126
+ let deferred1_1;
6127
+ try {
6128
+ const ret = wasm.moonelevationcrossing_kind(this.__wbg_ptr);
6129
+ deferred1_0 = ret[0];
6130
+ deferred1_1 = ret[1];
6131
+ return getStringFromWasm0(ret[0], ret[1]);
6132
+ } finally {
6133
+ wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
6134
+ }
6135
+ }
6136
+ /**
6137
+ * Refined crossing instant, unix microseconds.
6138
+ * @returns {bigint}
6139
+ */
6140
+ get timeUnixUs() {
6141
+ const ret = wasm.moonelevationcrossing_timeUnixUs(this.__wbg_ptr);
6142
+ return ret;
6143
+ }
6144
+ }
6145
+ if (Symbol.dispose) MoonElevationCrossing.prototype[Symbol.dispose] = MoonElevationCrossing.prototype.free;
6146
+ exports.MoonElevationCrossing = MoonElevationCrossing;
6147
+
6148
+ /**
6149
+ * One refined Moon meridian transit (culmination).
6150
+ */
6151
+ class MoonTransit {
6152
+ static __wrap(ptr) {
6153
+ const obj = Object.create(MoonTransit.prototype);
6154
+ obj.__wbg_ptr = ptr;
6155
+ MoonTransitFinalization.register(obj, obj.__wbg_ptr, obj);
6156
+ return obj;
6157
+ }
6158
+ __destroy_into_raw() {
6159
+ const ptr = this.__wbg_ptr;
6160
+ this.__wbg_ptr = 0;
6161
+ MoonTransitFinalization.unregister(this);
6162
+ return ptr;
6163
+ }
6164
+ free() {
6165
+ const ptr = this.__destroy_into_raw();
6166
+ wasm.__wbg_moontransit_free(ptr, 0);
6167
+ }
6168
+ /**
6169
+ * Topocentric Moon elevation at the refined instant, degrees.
6170
+ * @returns {number}
6171
+ */
6172
+ get elevationDeg() {
6173
+ const ret = wasm.moontransit_elevationDeg(this.__wbg_ptr);
6174
+ return ret;
6175
+ }
6176
+ /**
6177
+ * Culmination kind: `"upper"` (due south, highest) or `"lower"` (due north,
6178
+ * lowest).
6179
+ * @returns {string}
6180
+ */
6181
+ get kind() {
6182
+ let deferred1_0;
6183
+ let deferred1_1;
6184
+ try {
6185
+ const ret = wasm.moontransit_kind(this.__wbg_ptr);
6186
+ deferred1_0 = ret[0];
6187
+ deferred1_1 = ret[1];
6188
+ return getStringFromWasm0(ret[0], ret[1]);
6189
+ } finally {
6190
+ wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
6191
+ }
6192
+ }
6193
+ /**
6194
+ * Refined culmination instant, unix microseconds.
6195
+ * @returns {bigint}
6196
+ */
6197
+ get timeUnixUs() {
6198
+ const ret = wasm.moontransit_timeUnixUs(this.__wbg_ptr);
6199
+ return ret;
6200
+ }
6201
+ }
6202
+ if (Symbol.dispose) MoonTransit.prototype[Symbol.dispose] = MoonTransit.prototype.free;
6203
+ exports.MoonTransit = MoonTransit;
6204
+
5829
6205
  /**
5830
6206
  * One solved moving-baseline epoch.
5831
6207
  */
@@ -8850,28 +9226,108 @@ if (Symbol.dispose) PppFloatSolution.prototype[Symbol.dispose] = PppFloatSolutio
8850
9226
  exports.PppFloatSolution = PppFloatSolution;
8851
9227
 
8852
9228
  /**
8853
- * Predicted GNSS observables for one satellite at one receive epoch. Every
8854
- * field is computed by `sidereon_core::observables::predict`.
9229
+ * The per-request results of a batch observable prediction, index-aligned to
9230
+ * the input requests. Each request independently either produced observables or
9231
+ * failed; query a request with [`PredictBatch.isOk`] /
9232
+ * [`PredictBatch.observables`] / [`PredictBatch.error`].
8855
9233
  */
8856
- class PredictedObservables {
9234
+ class PredictBatch {
8857
9235
  static __wrap(ptr) {
8858
- const obj = Object.create(PredictedObservables.prototype);
9236
+ const obj = Object.create(PredictBatch.prototype);
8859
9237
  obj.__wbg_ptr = ptr;
8860
- PredictedObservablesFinalization.register(obj, obj.__wbg_ptr, obj);
9238
+ PredictBatchFinalization.register(obj, obj.__wbg_ptr, obj);
8861
9239
  return obj;
8862
9240
  }
8863
9241
  __destroy_into_raw() {
8864
9242
  const ptr = this.__wbg_ptr;
8865
9243
  this.__wbg_ptr = 0;
8866
- PredictedObservablesFinalization.unregister(this);
9244
+ PredictBatchFinalization.unregister(this);
8867
9245
  return ptr;
8868
9246
  }
8869
9247
  free() {
8870
9248
  const ptr = this.__destroy_into_raw();
8871
- wasm.__wbg_predictedobservables_free(ptr, 0);
9249
+ wasm.__wbg_predictbatch_free(ptr, 0);
8872
9250
  }
8873
9251
  /**
8874
- * Topocentric azimuth in `[0, 360)`, degrees.
9252
+ * Number of requests in the batch.
9253
+ * @returns {number}
9254
+ */
9255
+ get count() {
9256
+ const ret = wasm.predictbatch_count(this.__wbg_ptr);
9257
+ return ret >>> 0;
9258
+ }
9259
+ /**
9260
+ * The failure message for request `index`, or `undefined` when it
9261
+ * succeeded. Throws a `RangeError` for an out-of-range index.
9262
+ * @param {number} index
9263
+ * @returns {string | undefined}
9264
+ */
9265
+ error(index) {
9266
+ const ret = wasm.predictbatch_error(this.__wbg_ptr, index);
9267
+ if (ret[3]) {
9268
+ throw takeFromExternrefTable0(ret[2]);
9269
+ }
9270
+ let v1;
9271
+ if (ret[0] !== 0) {
9272
+ v1 = getStringFromWasm0(ret[0], ret[1]).slice();
9273
+ wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
9274
+ }
9275
+ return v1;
9276
+ }
9277
+ /**
9278
+ * Whether request `index` produced observables. Throws a `RangeError` for
9279
+ * an out-of-range index.
9280
+ * @param {number} index
9281
+ * @returns {boolean}
9282
+ */
9283
+ isOk(index) {
9284
+ const ret = wasm.predictbatch_isOk(this.__wbg_ptr, index);
9285
+ if (ret[2]) {
9286
+ throw takeFromExternrefTable0(ret[1]);
9287
+ }
9288
+ return ret[0] !== 0;
9289
+ }
9290
+ /**
9291
+ * The observables for request `index`. Throws a `RangeError` for an
9292
+ * out-of-range index and an `Error` carrying that request's failure message
9293
+ * when the prediction failed (check [`PredictBatch.isOk`] first).
9294
+ * @param {number} index
9295
+ * @returns {PredictedObservables}
9296
+ */
9297
+ observables(index) {
9298
+ const ret = wasm.predictbatch_observables(this.__wbg_ptr, index);
9299
+ if (ret[2]) {
9300
+ throw takeFromExternrefTable0(ret[1]);
9301
+ }
9302
+ return PredictedObservables.__wrap(ret[0]);
9303
+ }
9304
+ }
9305
+ if (Symbol.dispose) PredictBatch.prototype[Symbol.dispose] = PredictBatch.prototype.free;
9306
+ exports.PredictBatch = PredictBatch;
9307
+
9308
+ /**
9309
+ * Predicted GNSS observables for one satellite at one receive epoch. Every
9310
+ * field is computed by `sidereon_core::observables::predict`.
9311
+ */
9312
+ class PredictedObservables {
9313
+ static __wrap(ptr) {
9314
+ const obj = Object.create(PredictedObservables.prototype);
9315
+ obj.__wbg_ptr = ptr;
9316
+ PredictedObservablesFinalization.register(obj, obj.__wbg_ptr, obj);
9317
+ return obj;
9318
+ }
9319
+ __destroy_into_raw() {
9320
+ const ptr = this.__wbg_ptr;
9321
+ this.__wbg_ptr = 0;
9322
+ PredictedObservablesFinalization.unregister(this);
9323
+ return ptr;
9324
+ }
9325
+ free() {
9326
+ const ptr = this.__destroy_into_raw();
9327
+ wasm.__wbg_predictedobservables_free(ptr, 0);
9328
+ }
9329
+ /**
9330
+ * Topocentric azimuth in `[0, 360)`, degrees.
8875
9331
  * @returns {number}
8876
9332
  */
8877
9333
  get azimuthDeg() {
@@ -12740,6 +13196,37 @@ function correlate(iq, prn, options) {
12740
13196
  }
12741
13197
  exports.correlate = correlate;
12742
13198
 
13199
+ /**
13200
+ * Fitted parameter covariance from a converged solve, scaling `(J^T J)^-1` by
13201
+ * the post-fit reduced chi-square `s_sq = 2 * cost / (m - n)` (the same scale
13202
+ * `scipy.optimize.curve_fit` applies to its `pcov`).
13203
+ *
13204
+ * `jacobian` is a flat row-major `(m, n)` `Float64Array` (the Jacobian at the
13205
+ * solution), and `cost` is the solve's optimal cost `0.5 * sum(residual^2)`;
13206
+ * the degrees of freedom `m - n` (taken from the Jacobian's own shape) must be
13207
+ * positive. Pairs naturally with a [`crate::LeastSquaresResult`] (`result.jac`,
13208
+ * `result.m`, `result.n`, `result.cost`). Returns the `n`-by-`n` covariance as
13209
+ * a flat row-major `Float64Array`. Delegates to
13210
+ * `sidereon_core::astro::math::least_squares::covariance_from_jacobian`.
13211
+ * @param {Float64Array} jacobian
13212
+ * @param {number} m
13213
+ * @param {number} n
13214
+ * @param {number} cost
13215
+ * @returns {Float64Array}
13216
+ */
13217
+ function covarianceFromJacobian(jacobian, m, n, cost) {
13218
+ const ptr0 = passArrayF64ToWasm0(jacobian, wasm.__wbindgen_malloc);
13219
+ const len0 = WASM_VECTOR_LEN;
13220
+ const ret = wasm.covarianceFromJacobian(ptr0, len0, m, n, cost);
13221
+ if (ret[3]) {
13222
+ throw takeFromExternrefTable0(ret[2]);
13223
+ }
13224
+ var v2 = getArrayF64FromWasm0(ret[0], ret[1]).slice();
13225
+ wasm.__wbindgen_free(ret[0], ret[1] * 8, 8);
13226
+ return v2;
13227
+ }
13228
+ exports.covarianceFromJacobian = covarianceFromJacobian;
13229
+
12743
13230
  /**
12744
13231
  * Whether a 3x3 covariance (flat row-major length 9) is symmetric positive
12745
13232
  * semidefinite within the engine tolerance.
@@ -13002,6 +13489,38 @@ function dishGain(diameter_m, frequency_hz, efficiency) {
13002
13489
  }
13003
13490
  exports.dishGain = dishGain;
13004
13491
 
13492
+ /**
13493
+ * GNSS dilution of precision with an explicit ENU convention for the
13494
+ * horizontal/vertical split.
13495
+ *
13496
+ * `lineOfSight` is a flat row-major `(n, 3)` `Float64Array` of ECEF unit
13497
+ * vectors, `weights` a positive `Float64Array` of length `n`, and `convention`
13498
+ * is `"geodeticNormal"` (the GNSS-standard default, matching [`gnssDop`]) or
13499
+ * `"geocentricRadial"` (radial up). Only HDOP/VDOP differ between conventions
13500
+ * (by ~`1e-3` relative); GDOP/PDOP/TDOP are identical. Delegates to
13501
+ * `sidereon_core::geometry::dop_with_convention`.
13502
+ * @param {Float64Array} line_of_sight
13503
+ * @param {Float64Array} weights
13504
+ * @param {Wgs84Geodetic} receiver
13505
+ * @param {string} convention
13506
+ * @returns {Dop}
13507
+ */
13508
+ function dopWithConvention(line_of_sight, weights, receiver, convention) {
13509
+ const ptr0 = passArrayF64ToWasm0(line_of_sight, wasm.__wbindgen_malloc);
13510
+ const len0 = WASM_VECTOR_LEN;
13511
+ const ptr1 = passArrayF64ToWasm0(weights, wasm.__wbindgen_malloc);
13512
+ const len1 = WASM_VECTOR_LEN;
13513
+ _assertClass(receiver, Wgs84Geodetic);
13514
+ const ptr2 = passStringToWasm0(convention, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
13515
+ const len2 = WASM_VECTOR_LEN;
13516
+ const ret = wasm.dopWithConvention(ptr0, len0, ptr1, len1, receiver.__wbg_ptr, ptr2, len2);
13517
+ if (ret[2]) {
13518
+ throw takeFromExternrefTable0(ret[1]);
13519
+ }
13520
+ return Dop.__wrap(ret[0]);
13521
+ }
13522
+ exports.dopWithConvention = dopWithConvention;
13523
+
13005
13524
  /**
13006
13525
  * Range rate and dimensionless Doppler ratio from a GCRS state.
13007
13526
  *
@@ -13149,6 +13668,56 @@ function eclipseStatus(satellite_position_km, sun_position_km) {
13149
13668
  }
13150
13669
  exports.eclipseStatus = eclipseStatus;
13151
13670
 
13671
+ /**
13672
+ * Ellipsoidal height `h = H + N` (metres above the WGS84 ellipsoid) from an
13673
+ * orthometric height and a geodetic position in radians, using the embedded
13674
+ * genuine EGM96 1-degree model. Delegates to
13675
+ * `sidereon_core::geoid::egm96_ellipsoidal_height_m`.
13676
+ * @param {number} orthometric_height_m
13677
+ * @param {number} lat_rad
13678
+ * @param {number} lon_rad
13679
+ * @returns {number}
13680
+ */
13681
+ function egm96EllipsoidalHeightM(orthometric_height_m, lat_rad, lon_rad) {
13682
+ const ret = wasm.egm96EllipsoidalHeightM(orthometric_height_m, lat_rad, lon_rad);
13683
+ return ret;
13684
+ }
13685
+ exports.egm96EllipsoidalHeightM = egm96EllipsoidalHeightM;
13686
+
13687
+ /**
13688
+ * Orthometric height `H = h - N` (metres above mean sea level) from an
13689
+ * ellipsoidal height and a geodetic position in radians, using the embedded
13690
+ * genuine EGM96 1-degree model. Delegates to
13691
+ * `sidereon_core::geoid::egm96_orthometric_height_m`.
13692
+ * @param {number} ellipsoidal_height_m
13693
+ * @param {number} lat_rad
13694
+ * @param {number} lon_rad
13695
+ * @returns {number}
13696
+ */
13697
+ function egm96OrthometricHeightM(ellipsoidal_height_m, lat_rad, lon_rad) {
13698
+ const ret = wasm.egm96OrthometricHeightM(ellipsoidal_height_m, lat_rad, lon_rad);
13699
+ return ret;
13700
+ }
13701
+ exports.egm96OrthometricHeightM = egm96OrthometricHeightM;
13702
+
13703
+ /**
13704
+ * Geoid undulation `N` (metres above the WGS84 ellipsoid) at a geodetic
13705
+ * position in radians, from the embedded GENUINE EGM96 1-degree global grid.
13706
+ * Latitude is positive north, longitude positive east. This is the recommended
13707
+ * zero-setup default for metre-class datum work (its bilinear lookup agrees
13708
+ * with the full 15-arcminute EGM96 grid to ~0.4 m RMS); the coarse
13709
+ * [`geoidUndulation`] is only suitable for sanity checks. Delegates to
13710
+ * `sidereon_core::geoid::egm96_undulation`.
13711
+ * @param {number} lat_rad
13712
+ * @param {number} lon_rad
13713
+ * @returns {number}
13714
+ */
13715
+ function egm96Undulation(lat_rad, lon_rad) {
13716
+ const ret = wasm.egm96Undulation(lat_rad, lon_rad);
13717
+ return ret;
13718
+ }
13719
+ exports.egm96Undulation = egm96Undulation;
13720
+
13152
13721
  /**
13153
13722
  * Effective isotropic radiated power, dBW.
13154
13723
  * @param {number} tx_power_dbm
@@ -13307,6 +13876,84 @@ function encounterPlaneCovariance(frame, covariance_km2) {
13307
13876
  }
13308
13877
  exports.encounterPlaneCovariance = encounterPlaneCovariance;
13309
13878
 
13879
+ /**
13880
+ * Confidence ellipse from an arbitrary 2x2 covariance block.
13881
+ *
13882
+ * `covariance` is a flat row-major length-4 `Float64Array` (`[c00, c01, c10,
13883
+ * c11]`); `confidence` is in `(0, 1)`. The semi-axes are the eigenvalues of the
13884
+ * symmetrized block scaled by the chi-square(2) quantile. Throws a `RangeError`
13885
+ * for a non-positive-semidefinite block or an out-of-range confidence.
13886
+ * Delegates to `sidereon_core::geometry::error_ellipse_2x2`.
13887
+ * @param {Float64Array} covariance
13888
+ * @param {number} confidence
13889
+ * @returns {ErrorEllipse2}
13890
+ */
13891
+ function errorEllipse2(covariance, confidence) {
13892
+ const ptr0 = passArrayF64ToWasm0(covariance, wasm.__wbindgen_malloc);
13893
+ const len0 = WASM_VECTOR_LEN;
13894
+ const ret = wasm.errorEllipse2(ptr0, len0, confidence);
13895
+ if (ret[2]) {
13896
+ throw takeFromExternrefTable0(ret[1]);
13897
+ }
13898
+ return ErrorEllipse2.__wrap(ret[0]);
13899
+ }
13900
+ exports.errorEllipse2 = errorEllipse2;
13901
+
13902
+ /**
13903
+ * Find Moon elevation threshold crossings (moonrise / moonset) over a UTC
13904
+ * window.
13905
+ *
13906
+ * The station is geodetic (`latitudeDeg`, `longitudeDeg`, `altitudeKm`);
13907
+ * `startUnixUs` / `endUnixUs` bound the window in unix microseconds. `options`
13908
+ * is `{ elevationThresholdDeg?, stepSeconds?, timeToleranceSeconds? }`.
13909
+ * Delegates to `sidereon_core::astro::bodies::find_moon_elevation_crossings`.
13910
+ * @param {number} latitude_deg
13911
+ * @param {number} longitude_deg
13912
+ * @param {number} altitude_km
13913
+ * @param {bigint} start_unix_us
13914
+ * @param {bigint} end_unix_us
13915
+ * @param {any} options
13916
+ * @returns {MoonElevationCrossing[]}
13917
+ */
13918
+ function findMoonElevationCrossings(latitude_deg, longitude_deg, altitude_km, start_unix_us, end_unix_us, options) {
13919
+ const ret = wasm.findMoonElevationCrossings(latitude_deg, longitude_deg, altitude_km, start_unix_us, end_unix_us, options);
13920
+ if (ret[3]) {
13921
+ throw takeFromExternrefTable0(ret[2]);
13922
+ }
13923
+ var v1 = getArrayJsValueFromWasm0(ret[0], ret[1]).slice();
13924
+ wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
13925
+ return v1;
13926
+ }
13927
+ exports.findMoonElevationCrossings = findMoonElevationCrossings;
13928
+
13929
+ /**
13930
+ * Find Moon meridian transits (upper and lower culminations) over a UTC window.
13931
+ *
13932
+ * The station is geodetic (`latitudeDeg`, `longitudeDeg`, `altitudeKm`);
13933
+ * `startUnixUs` / `endUnixUs` bound the window in unix microseconds.
13934
+ * `stepSeconds` is the uniform scan step and `timeToleranceSeconds` the
13935
+ * refinement tolerance. Delegates to
13936
+ * `sidereon_core::astro::bodies::find_moon_transits`.
13937
+ * @param {number} latitude_deg
13938
+ * @param {number} longitude_deg
13939
+ * @param {number} altitude_km
13940
+ * @param {bigint} start_unix_us
13941
+ * @param {bigint} end_unix_us
13942
+ * @param {number} step_seconds
13943
+ * @param {number} time_tolerance_seconds
13944
+ * @returns {MoonTransit[]}
13945
+ */
13946
+ function findMoonTransits(latitude_deg, longitude_deg, altitude_km, start_unix_us, end_unix_us, step_seconds, time_tolerance_seconds) {
13947
+ const ret = wasm.findMoonTransits(latitude_deg, longitude_deg, altitude_km, start_unix_us, end_unix_us, step_seconds, time_tolerance_seconds);
13948
+ if (ret[3]) {
13949
+ throw takeFromExternrefTable0(ret[2]);
13950
+ }
13951
+ var v1 = getArrayJsValueFromWasm0(ret[0], ret[1]).slice();
13952
+ wasm.__wbindgen_free(ret[0], ret[1] * 4, 4);
13953
+ return v1;
13954
+ }
13955
+ exports.findMoonTransits = findMoonTransits;
13956
+
13310
13957
  /**
13311
13958
  * Find local TCA candidates between two satellites over a UTC window.
13312
13959
  *
@@ -14050,6 +14697,45 @@ function gnssVisible(sp3, station_ecef_m, j2000_seconds, options) {
14050
14697
  }
14051
14698
  exports.gnssVisible = gnssVisible;
14052
14699
 
14700
+ /**
14701
+ * GPS - UTC (the GNSS leap-second offset since the GPS epoch) on a UTC calendar
14702
+ * date: the IS-GPS-200 quantity broadcast in the navigation message (18 s from
14703
+ * 2017-01-01). Equals `taiUtcOffsetS - 19`. Use this, not [`taiUtcOffsetS`],
14704
+ * whenever you mean the leap seconds a GPS receiver applies. Delegates to
14705
+ * `sidereon_core::astro::time::scales::gps_utc_offset_s`.
14706
+ * @param {number} year
14707
+ * @param {number} month
14708
+ * @param {number} day
14709
+ * @returns {number}
14710
+ */
14711
+ function gpsUtcOffsetS(year, month, day) {
14712
+ const ret = wasm.gpsUtcOffsetS(year, month, day);
14713
+ return ret;
14714
+ }
14715
+ exports.gpsUtcOffsetS = gpsUtcOffsetS;
14716
+
14717
+ /**
14718
+ * Trace of the Gauss-Newton Hessian approximation `J^T J`: the sum of the
14719
+ * squared column norms of the Jacobian, with no inverse formed.
14720
+ *
14721
+ * `jacobian` is a flat row-major `(m, n)` `Float64Array`. Delegates to
14722
+ * `sidereon_core::astro::math::least_squares::hessian_trace`.
14723
+ * @param {Float64Array} jacobian
14724
+ * @param {number} m
14725
+ * @param {number} n
14726
+ * @returns {number}
14727
+ */
14728
+ function hessianTrace(jacobian, m, n) {
14729
+ const ptr0 = passArrayF64ToWasm0(jacobian, wasm.__wbindgen_malloc);
14730
+ const len0 = WASM_VECTOR_LEN;
14731
+ const ret = wasm.hessianTrace(ptr0, len0, m, n);
14732
+ if (ret[2]) {
14733
+ throw takeFromExternrefTable0(ret[1]);
14734
+ }
14735
+ return ret[0];
14736
+ }
14737
+ exports.hessianTrace = hessianTrace;
14738
+
14053
14739
  /**
14054
14740
  * Gauss angles-only orbit determination.
14055
14741
  *
@@ -14257,6 +14943,28 @@ function j2000SecondsToCivil(seconds) {
14257
14943
  }
14258
14944
  exports.j2000SecondsToCivil = j2000SecondsToCivil;
14259
14945
 
14946
+ /**
14947
+ * Jarque-Bera normality test on a residual set.
14948
+ *
14949
+ * `x` is a `Float64Array` (at least two values). Returns
14950
+ * `{ statistic, pValue }` with `statistic = n/6 (S^2 + K^2/4)` (biased moments)
14951
+ * and the chi-square(2) survival `pValue = exp(-statistic/2)`, matching
14952
+ * `scipy.stats.jarque_bera`. Delegates to
14953
+ * `sidereon_core::quality::normality::jarque_bera`.
14954
+ * @param {Float64Array} x
14955
+ * @returns {any}
14956
+ */
14957
+ function jarqueBera(x) {
14958
+ const ptr0 = passArrayF64ToWasm0(x, wasm.__wbindgen_malloc);
14959
+ const len0 = WASM_VECTOR_LEN;
14960
+ const ret = wasm.jarqueBera(ptr0, len0);
14961
+ if (ret[2]) {
14962
+ throw takeFromExternrefTable0(ret[1]);
14963
+ }
14964
+ return takeFromExternrefTable0(ret[0]);
14965
+ }
14966
+ exports.jarqueBera = jarqueBera;
14967
+
14260
14968
  /**
14261
14969
  * GPS broadcast Klobuchar ionospheric group delay in the model's native units
14262
14970
  * (positive metres).
@@ -14293,6 +15001,30 @@ function klobucharDelay(alpha, beta, lat_deg, lon_deg, azimuth_deg, elevation_de
14293
15001
  }
14294
15002
  exports.klobucharDelay = klobucharDelay;
14295
15003
 
15004
+ /**
15005
+ * Sample kurtosis of a residual set.
15006
+ *
15007
+ * `x` is a `Float64Array`. `fisher` (default `true`) returns the excess
15008
+ * kurtosis `m4 / m2^2 - 3` (Gaussian -> 0, `scipy.stats.kurtosis`); `false`
15009
+ * returns the Pearson kurtosis (Gaussian -> 3). `bias` (default `true`); pass
15010
+ * `false` for the sample correction (needs at least four values). Delegates to
15011
+ * `sidereon_core::quality::normality::kurtosis`.
15012
+ * @param {Float64Array} x
15013
+ * @param {boolean | null} [fisher]
15014
+ * @param {boolean | null} [bias]
15015
+ * @returns {number}
15016
+ */
15017
+ function kurtosis(x, fisher, bias) {
15018
+ const ptr0 = passArrayF64ToWasm0(x, wasm.__wbindgen_malloc);
15019
+ const len0 = WASM_VECTOR_LEN;
15020
+ const ret = wasm.kurtosis(ptr0, len0, isLikeNone(fisher) ? 0xFFFFFF : fisher ? 1 : 0, isLikeNone(bias) ? 0xFFFFFF : bias ? 1 : 0);
15021
+ if (ret[2]) {
15022
+ throw takeFromExternrefTable0(ret[1]);
15023
+ }
15024
+ return ret[0];
15025
+ }
15026
+ exports.kurtosis = kurtosis;
15027
+
14296
15028
  /**
14297
15029
  * Resolve integer ambiguities with the LAMBDA method (RTKLIB `lambda()` port).
14298
15030
  *
@@ -14400,6 +15132,49 @@ function leapSecondsBatch(dates) {
14400
15132
  }
14401
15133
  exports.leapSecondsBatch = leapSecondsBatch;
14402
15134
 
15135
+ /**
15136
+ * Solve a generic data-driven least-squares problem.
15137
+ *
15138
+ * `request` is a `DataProblemInput` object: a `kind` (`"linear"`,
15139
+ * `"polynomial"`, `"exponential"`) carrying its data arrays, the `x0` starting
15140
+ * point, and the SciPy `least_squares` options. The whole trust-region
15141
+ * iteration runs in Rust through
15142
+ * `trust_region_least_squares::data::solve_data_problem` (the serial entry, the
15143
+ * default in-crate SVD backend); no rayon thread pool is entered.
15144
+ * @param {any} request
15145
+ * @returns {LeastSquaresResult}
15146
+ */
15147
+ function leastSquares(request) {
15148
+ const ret = wasm.leastSquares(request);
15149
+ if (ret[2]) {
15150
+ throw takeFromExternrefTable0(ret[1]);
15151
+ }
15152
+ return LeastSquaresResult.__wrap(ret[0]);
15153
+ }
15154
+ exports.leastSquares = leastSquares;
15155
+
15156
+ /**
15157
+ * Serial leave-one-out (jackknife) over a data-driven least-squares problem.
15158
+ *
15159
+ * Delegates to the core's serial leave-one-out entry
15160
+ * `trust_region_least_squares::batch::solve_data_problem_drop_one_serial`: the
15161
+ * full problem is solved once, then re-solved with each residual row masked in
15162
+ * turn. The core's default `solve_data_problem_drop_one` fans these re-solves
15163
+ * across a rayon pool that wasm has no threads for, so this binding takes the
15164
+ * serial twin, which runs the identical re-solves one row at a time and is
15165
+ * byte-identical to the parallel version.
15166
+ * @param {any} request
15167
+ * @returns {LeastSquaresDropOneReport}
15168
+ */
15169
+ function leastSquaresDropOne(request) {
15170
+ const ret = wasm.leastSquaresDropOne(request);
15171
+ if (ret[2]) {
15172
+ throw takeFromExternrefTable0(ret[1]);
15173
+ }
15174
+ return LeastSquaresDropOneReport.__wrap(ret[0]);
15175
+ }
15176
+ exports.leastSquaresDropOne = leastSquaresDropOne;
15177
+
14403
15178
  /**
14404
15179
  * Decode LNAV subframes 1-3 back into engineering-unit parameters.
14405
15180
  *
@@ -14728,6 +15503,30 @@ function mergeSp3(sources, options) {
14728
15503
  }
14729
15504
  exports.mergeSp3 = mergeSp3;
14730
15505
 
15506
+ /**
15507
+ * Mean, variance, skewness, and excess kurtosis of a residual set in one pass.
15508
+ *
15509
+ * `x` is a `Float64Array`; `fisher` and `bias` select the kurtosis convention
15510
+ * and the bias correction exactly as in [`skewness`] / [`kurtosis`] (both
15511
+ * default `true`). Returns `{ mean, variance, skewness, kurtosisExcess }`; the
15512
+ * variance is the biased second central moment. Delegates to
15513
+ * `sidereon_core::quality::normality::moments`.
15514
+ * @param {Float64Array} x
15515
+ * @param {boolean | null} [fisher]
15516
+ * @param {boolean | null} [bias]
15517
+ * @returns {any}
15518
+ */
15519
+ function moments(x, fisher, bias) {
15520
+ const ptr0 = passArrayF64ToWasm0(x, wasm.__wbindgen_malloc);
15521
+ const len0 = WASM_VECTOR_LEN;
15522
+ const ret = wasm.moments(ptr0, len0, isLikeNone(fisher) ? 0xFFFFFF : fisher ? 1 : 0, isLikeNone(bias) ? 0xFFFFFF : bias ? 1 : 0);
15523
+ if (ret[2]) {
15524
+ throw takeFromExternrefTable0(ret[1]);
15525
+ }
15526
+ return takeFromExternrefTable0(ret[0]);
15527
+ }
15528
+ exports.moments = moments;
15529
+
14731
15530
  /**
14732
15531
  * Angle in degrees between satellite nadir and the Moon direction.
14733
15532
  * @param {Float64Array} satellite_position_km
@@ -14749,6 +15548,67 @@ function moonAngle(satellite_position_km, moon_position_km) {
14749
15548
  }
14750
15549
  exports.moonAngle = moonAngle;
14751
15550
 
15551
+ /**
15552
+ * Topocentric azimuth/elevation/range of the Moon from a ground site,
15553
+ * including the diurnal parallax. See [`sunAzEl`] for the argument shapes.
15554
+ * Delegates to `sidereon_core::astro::bodies::moon_az_el`.
15555
+ * @param {number} latitude_deg
15556
+ * @param {number} longitude_deg
15557
+ * @param {number} altitude_km
15558
+ * @param {bigint} epoch_unix_us
15559
+ * @returns {any}
15560
+ */
15561
+ function moonAzEl(latitude_deg, longitude_deg, altitude_km, epoch_unix_us) {
15562
+ const ret = wasm.moonAzEl(latitude_deg, longitude_deg, altitude_km, epoch_unix_us);
15563
+ if (ret[2]) {
15564
+ throw takeFromExternrefTable0(ret[1]);
15565
+ }
15566
+ return takeFromExternrefTable0(ret[0]);
15567
+ }
15568
+ exports.moonAzEl = moonAzEl;
15569
+
15570
+ /**
15571
+ * Topocentric geometric Moon (disk-center) elevation from a ground site,
15572
+ * degrees. See [`sunAzEl`] for the argument shapes. Delegates to
15573
+ * `sidereon_core::astro::bodies::moon_az_el` and returns its `elevationDeg`: the
15574
+ * core `moon_elevation_deg` convenience wrapper `expect`s on the geometry, so a
15575
+ * valid-shaped but out-of-range station (e.g. latitude 120) would panic the
15576
+ * wasm module; going through `moon_az_el` surfaces that as a thrown JS error.
15577
+ * @param {number} latitude_deg
15578
+ * @param {number} longitude_deg
15579
+ * @param {number} altitude_km
15580
+ * @param {bigint} epoch_unix_us
15581
+ * @returns {number}
15582
+ */
15583
+ function moonElevationDeg(latitude_deg, longitude_deg, altitude_km, epoch_unix_us) {
15584
+ const ret = wasm.moonElevationDeg(latitude_deg, longitude_deg, altitude_km, epoch_unix_us);
15585
+ if (ret[2]) {
15586
+ throw takeFromExternrefTable0(ret[1]);
15587
+ }
15588
+ return ret[0];
15589
+ }
15590
+ exports.moonElevationDeg = moonElevationDeg;
15591
+
15592
+ /**
15593
+ * Illuminated fraction of the Moon as seen from a ground site. Returns
15594
+ * `{ illuminatedFraction, phaseAngleDeg }` (0 = new, 1 = full). See [`sunAzEl`]
15595
+ * for the argument shapes. Delegates to
15596
+ * `sidereon_core::astro::bodies::moon_illumination`.
15597
+ * @param {number} latitude_deg
15598
+ * @param {number} longitude_deg
15599
+ * @param {number} altitude_km
15600
+ * @param {bigint} epoch_unix_us
15601
+ * @returns {any}
15602
+ */
15603
+ function moonIllumination(latitude_deg, longitude_deg, altitude_km, epoch_unix_us) {
15604
+ const ret = wasm.moonIllumination(latitude_deg, longitude_deg, altitude_km, epoch_unix_us);
15605
+ if (ret[2]) {
15606
+ throw takeFromExternrefTable0(ret[1]);
15607
+ }
15608
+ return takeFromExternrefTable0(ret[0]);
15609
+ }
15610
+ exports.moonIllumination = moonIllumination;
15611
+
14752
15612
  /**
14753
15613
  * Narrow-lane code combination, metres.
14754
15614
  * @param {number} p1_m
@@ -14846,6 +15706,37 @@ function noiseAmplification(f1_hz, f2_hz) {
14846
15706
  }
14847
15707
  exports.noiseAmplification = noiseAmplification;
14848
15708
 
15709
+ /**
15710
+ * Parameter covariance from a design (Jacobian) matrix via the Gauss-Newton
15711
+ * normal equations `varianceScale * (J^T J)^-1`, formed from the thin SVD of
15712
+ * `J` (not by inverting `J^T J`, so the condition number is not squared).
15713
+ *
15714
+ * `jacobian` is a flat row-major `(m, n)` `Float64Array` with `m >= n`;
15715
+ * `varianceScale` (`sigma^2`, non-negative) scales the bare cofactor (pass the
15716
+ * post-fit reduced chi-square for the fitted covariance, or `1.0` for
15717
+ * `(J^T J)^-1`). Returns the `n`-by-`n` covariance as a flat row-major
15718
+ * `Float64Array` of length `n * n`. Throws an `Error` for a rank-deficient
15719
+ * Jacobian. Delegates to
15720
+ * `sidereon_core::astro::math::least_squares::normal_covariance`.
15721
+ * @param {Float64Array} jacobian
15722
+ * @param {number} m
15723
+ * @param {number} n
15724
+ * @param {number} variance_scale
15725
+ * @returns {Float64Array}
15726
+ */
15727
+ function normalCovariance(jacobian, m, n, variance_scale) {
15728
+ const ptr0 = passArrayF64ToWasm0(jacobian, wasm.__wbindgen_malloc);
15729
+ const len0 = WASM_VECTOR_LEN;
15730
+ const ret = wasm.normalCovariance(ptr0, len0, m, n, variance_scale);
15731
+ if (ret[3]) {
15732
+ throw takeFromExternrefTable0(ret[2]);
15733
+ }
15734
+ var v2 = getArrayF64FromWasm0(ret[0], ret[1]).slice();
15735
+ wasm.__wbindgen_free(ret[0], ret[1] * 8, 8);
15736
+ return v2;
15737
+ }
15738
+ exports.normalCovariance = normalCovariance;
15739
+
14849
15740
  /**
14850
15741
  * Predict observables for one satellite from a broadcast ephemeris store.
14851
15742
  * Delegates to `sidereon_core::observables::predict`.
@@ -15381,6 +16272,67 @@ function pppCorrections(sp3, epochs, receiver_ecef_m, options) {
15381
16272
  }
15382
16273
  exports.pppCorrections = pppCorrections;
15383
16274
 
16275
+ /**
16276
+ * Predict observables for many `(satellite, receiver, epoch)` requests from a
16277
+ * broadcast ephemeris store, serially. See [`predictBatchSp3`] for the argument
16278
+ * shapes. Delegates to the serial `sidereon_core::observables::predict_batch`.
16279
+ * @param {BroadcastEphemeris} broadcast
16280
+ * @param {string[]} satellites
16281
+ * @param {Float64Array} receivers_ecef_m
16282
+ * @param {Float64Array} epochs_j2000_s
16283
+ * @param {any} options
16284
+ * @returns {PredictBatch}
16285
+ */
16286
+ function predictBatchBroadcast(broadcast, satellites, receivers_ecef_m, epochs_j2000_s, options) {
16287
+ _assertClass(broadcast, BroadcastEphemeris);
16288
+ const ptr0 = passArrayJsValueToWasm0(satellites, wasm.__wbindgen_malloc);
16289
+ const len0 = WASM_VECTOR_LEN;
16290
+ const ptr1 = passArrayF64ToWasm0(receivers_ecef_m, wasm.__wbindgen_malloc);
16291
+ const len1 = WASM_VECTOR_LEN;
16292
+ const ptr2 = passArrayF64ToWasm0(epochs_j2000_s, wasm.__wbindgen_malloc);
16293
+ const len2 = WASM_VECTOR_LEN;
16294
+ const ret = wasm.predictBatchBroadcast(broadcast.__wbg_ptr, ptr0, len0, ptr1, len1, ptr2, len2, options);
16295
+ if (ret[2]) {
16296
+ throw takeFromExternrefTable0(ret[1]);
16297
+ }
16298
+ return PredictBatch.__wrap(ret[0]);
16299
+ }
16300
+ exports.predictBatchBroadcast = predictBatchBroadcast;
16301
+
16302
+ /**
16303
+ * Predict observables for many `(satellite, receiver, epoch)` requests from an
16304
+ * SP3 precise product, serially.
16305
+ *
16306
+ * `satellites` is an array of satellite tokens, `receiversEcefM` a flat
16307
+ * row-major `(n, 3)` `Float64Array` of receiver ECEF positions (metres), and
16308
+ * `epochsJ2000S` a `Float64Array` of receive epochs (seconds since J2000); all
16309
+ * three are index-aligned and length `n`. Element `i` of the result corresponds
16310
+ * to request `i`. Delegates to the serial reference kernel
16311
+ * `sidereon_core::observables::predict_batch`; the binding never spawns the
16312
+ * rayon thread pool the parallel variant uses.
16313
+ * @param {Sp3} sp3
16314
+ * @param {string[]} satellites
16315
+ * @param {Float64Array} receivers_ecef_m
16316
+ * @param {Float64Array} epochs_j2000_s
16317
+ * @param {any} options
16318
+ * @returns {PredictBatch}
16319
+ */
16320
+ function predictBatchSp3(sp3, satellites, receivers_ecef_m, epochs_j2000_s, options) {
16321
+ _assertClass(sp3, Sp3);
16322
+ const ptr0 = passArrayJsValueToWasm0(satellites, wasm.__wbindgen_malloc);
16323
+ const len0 = WASM_VECTOR_LEN;
16324
+ const ptr1 = passArrayF64ToWasm0(receivers_ecef_m, wasm.__wbindgen_malloc);
16325
+ const len1 = WASM_VECTOR_LEN;
16326
+ const ptr2 = passArrayF64ToWasm0(epochs_j2000_s, wasm.__wbindgen_malloc);
16327
+ const len2 = WASM_VECTOR_LEN;
16328
+ const ret = wasm.predictBatchSp3(sp3.__wbg_ptr, ptr0, len0, ptr1, len1, ptr2, len2, options);
16329
+ if (ret[2]) {
16330
+ throw takeFromExternrefTable0(ret[1]);
16331
+ }
16332
+ return PredictBatch.__wrap(ret[0]);
16333
+ }
16334
+ exports.predictBatchSp3 = predictBatchSp3;
16335
+
15384
16336
  /**
15385
16337
  * Prepare ionosphere-free single-frequency RTK arc inputs from a
15386
16338
  * dual-frequency arc and fixed wide-lane ambiguities.
@@ -15843,6 +16795,27 @@ function shadowFraction(satellite_position_km, sun_position_km) {
15843
16795
  }
15844
16796
  exports.shadowFraction = shadowFraction;
15845
16797
 
16798
+ /**
16799
+ * Shapiro-Wilk normality test on a residual set.
16800
+ *
16801
+ * `x` is a `Float64Array` (at least three values). Returns `{ w, pValue }`,
16802
+ * Royston's AS R94 port that `scipy.stats.shapiro` uses; `w` is in `(0, 1]`
16803
+ * (closer to one is more Gaussian). Delegates to
16804
+ * `sidereon_core::quality::normality::shapiro_wilk`.
16805
+ * @param {Float64Array} x
16806
+ * @returns {any}
16807
+ */
16808
+ function shapiroWilk(x) {
16809
+ const ptr0 = passArrayF64ToWasm0(x, wasm.__wbindgen_malloc);
16810
+ const len0 = WASM_VECTOR_LEN;
16811
+ const ret = wasm.shapiroWilk(ptr0, len0);
16812
+ if (ret[2]) {
16813
+ throw takeFromExternrefTable0(ret[1]);
16814
+ }
16815
+ return takeFromExternrefTable0(ret[0]);
16816
+ }
16817
+ exports.shapiroWilk = shapiroWilk;
16818
+
15846
16819
  /**
15847
16820
  * Build satellite-keyed pseudorange sigmas in metres from `{ satelliteId,
15848
16821
  * elevationDeg, cn0Dbhz? }` entries. Invalid entries are dropped by the core.
@@ -15859,6 +16832,28 @@ function sigmas(entries, options) {
15859
16832
  }
15860
16833
  exports.sigmas = sigmas;
15861
16834
 
16835
+ /**
16836
+ * Sample skewness of a residual set.
16837
+ *
16838
+ * `x` is a `Float64Array`. `bias` (default `true`) selects the Fisher-Pearson
16839
+ * coefficient `g1 = m3 / m2^(3/2)` (`scipy.stats.skew`); `false` applies the
16840
+ * sample correction (`scipy.stats.skew(bias=False)`, needs at least three
16841
+ * values). Delegates to `sidereon_core::quality::normality::skewness`.
16842
+ * @param {Float64Array} x
16843
+ * @param {boolean | null} [bias]
16844
+ * @returns {number}
16845
+ */
16846
+ function skewness(x, bias) {
16847
+ const ptr0 = passArrayF64ToWasm0(x, wasm.__wbindgen_malloc);
16848
+ const len0 = WASM_VECTOR_LEN;
16849
+ const ret = wasm.skewness(ptr0, len0, isLikeNone(bias) ? 0xFFFFFF : bias ? 1 : 0);
16850
+ if (ret[2]) {
16851
+ throw takeFromExternrefTable0(ret[1]);
16852
+ }
16853
+ return ret[0];
16854
+ }
16855
+ exports.skewness = skewness;
16856
+
15862
16857
  /**
15863
16858
  * Stable lower-case label for a slip reason.
15864
16859
  * @param {SlipReason} reason
@@ -16343,6 +17338,28 @@ function sunAngle(satellite_position_km, sun_position_km) {
16343
17338
  }
16344
17339
  exports.sunAngle = sunAngle;
16345
17340
 
17341
+ /**
17342
+ * Topocentric azimuth/elevation/range of the Sun from a ground site.
17343
+ *
17344
+ * The station is geodetic (`latitudeDeg`, `longitudeDeg`, `altitudeKm`);
17345
+ * `epochUnixUs` is the UTC instant as unix microseconds. Returns
17346
+ * `{ azimuthDeg, elevationDeg, rangeKm }` (azimuth clockwise from north).
17347
+ * Delegates to `sidereon_core::astro::bodies::sun_az_el`.
17348
+ * @param {number} latitude_deg
17349
+ * @param {number} longitude_deg
17350
+ * @param {number} altitude_km
17351
+ * @param {bigint} epoch_unix_us
17352
+ * @returns {any}
17353
+ */
17354
+ function sunAzEl(latitude_deg, longitude_deg, altitude_km, epoch_unix_us) {
17355
+ const ret = wasm.sunAzEl(latitude_deg, longitude_deg, altitude_km, epoch_unix_us);
17356
+ if (ret[2]) {
17357
+ throw takeFromExternrefTable0(ret[1]);
17358
+ }
17359
+ return takeFromExternrefTable0(ret[0]);
17360
+ }
17361
+ exports.sunAzEl = sunAzEl;
17362
+
16346
17363
  /**
16347
17364
  * Sun elevation in degrees above the satellite local horizontal plane.
16348
17365
  * @param {Float64Array} satellite_position_km
@@ -16398,6 +17415,23 @@ function sunMoonEci(epochs_unix_us) {
16398
17415
  }
16399
17416
  exports.sunMoonEci = sunMoonEci;
16400
17417
 
17418
+ /**
17419
+ * TAI-UTC (cumulative leap seconds) in effect on a UTC calendar date.
17420
+ *
17421
+ * This is **not** the GNSS "GPS - UTC" offset; for the quantity a GPS receiver
17422
+ * applies use [`gpsUtcOffsetS`] (they differ by a constant 19 s). Delegates to
17423
+ * `sidereon_core::astro::time::scales::tai_utc_offset_s`.
17424
+ * @param {number} year
17425
+ * @param {number} month
17426
+ * @param {number} day
17427
+ * @returns {number}
17428
+ */
17429
+ function taiUtcOffsetS(year, month, day) {
17430
+ const ret = wasm.taiUtcOffsetS(year, month, day);
17431
+ return ret;
17432
+ }
17433
+ exports.taiUtcOffsetS = taiUtcOffsetS;
17434
+
16401
17435
  /**
16402
17436
  * Transform a batch of TEME states to GCRS, each at its own epoch.
16403
17437
  *
@@ -16494,8 +17528,8 @@ exports.timescaleOffsetAtS = timescaleOffsetAtS;
16494
17528
  *
16495
17529
  * Covers the atomic scales (TAI/TT/GPST/GST/QZSST/BDT), whose mutual offsets
16496
17530
  * are constants fixed by their ICDs. Throws a `RangeError` when either scale is
16497
- * UTC-based (`Utc`/`Glonasst`) those carry leap seconds, so their offset is
16498
- * epoch-dependent and needs [`timescaleOffsetAtS`] or for `Tdb` (no fixed
17531
+ * UTC-based (`Utc`/`Glonasst`): those carry leap seconds, so their offset is
17532
+ * epoch-dependent and needs [`timescaleOffsetAtS`], or for `Tdb` (no fixed
16499
17533
  * offset; resolve it through an `Instant`).
16500
17534
  * @param {TimeScale} from
16501
17535
  * @param {TimeScale} to
@@ -16996,6 +18030,14 @@ function __wbg_get_imports() {
16996
18030
  const ret = LookAngles.__wrap(arg0);
16997
18031
  return ret;
16998
18032
  },
18033
+ __wbg_moonelevationcrossing_new: function(arg0) {
18034
+ const ret = MoonElevationCrossing.__wrap(arg0);
18035
+ return ret;
18036
+ },
18037
+ __wbg_moontransit_new: function(arg0) {
18038
+ const ret = MoonTransit.__wrap(arg0);
18039
+ return ret;
18040
+ },
16999
18041
  __wbg_movingbaselinesolution_new: function(arg0) {
17000
18042
  const ret = MovingBaselineSolution.__wrap(arg0);
17001
18043
  return ret;
@@ -17280,6 +18322,9 @@ const EncounterFrameFinalization = (typeof FinalizationRegistry === 'undefined')
17280
18322
  const EphemerisFinalization = (typeof FinalizationRegistry === 'undefined')
17281
18323
  ? { register: () => {}, unregister: () => {} }
17282
18324
  : new FinalizationRegistry(ptr => wasm.__wbg_ephemeris_free(ptr, 1));
18325
+ const ErrorEllipse2Finalization = (typeof FinalizationRegistry === 'undefined')
18326
+ ? { register: () => {}, unregister: () => {} }
18327
+ : new FinalizationRegistry(ptr => wasm.__wbg_errorellipse2_free(ptr, 1));
17283
18328
  const FdeSolutionFinalization = (typeof FinalizationRegistry === 'undefined')
17284
18329
  ? { register: () => {}, unregister: () => {} }
17285
18330
  : new FinalizationRegistry(ptr => wasm.__wbg_fdesolution_free(ptr, 1));
@@ -17358,6 +18403,12 @@ const LambertTransferFinalization = (typeof FinalizationRegistry === 'undefined'
17358
18403
  const LeapSecondTableFinalization = (typeof FinalizationRegistry === 'undefined')
17359
18404
  ? { register: () => {}, unregister: () => {} }
17360
18405
  : new FinalizationRegistry(ptr => wasm.__wbg_leapsecondtable_free(ptr, 1));
18406
+ const LeastSquaresDropOneReportFinalization = (typeof FinalizationRegistry === 'undefined')
18407
+ ? { register: () => {}, unregister: () => {} }
18408
+ : new FinalizationRegistry(ptr => wasm.__wbg_leastsquaresdroponereport_free(ptr, 1));
18409
+ const LeastSquaresResultFinalization = (typeof FinalizationRegistry === 'undefined')
18410
+ ? { register: () => {}, unregister: () => {} }
18411
+ : new FinalizationRegistry(ptr => wasm.__wbg_leastsquaresresult_free(ptr, 1));
17361
18412
  const LinkBudgetFinalization = (typeof FinalizationRegistry === 'undefined')
17362
18413
  ? { register: () => {}, unregister: () => {} }
17363
18414
  : new FinalizationRegistry(ptr => wasm.__wbg_linkbudget_free(ptr, 1));
@@ -17373,6 +18424,12 @@ const LookAnglesFinalization = (typeof FinalizationRegistry === 'undefined')
17373
18424
  const MappingFactorsFinalization = (typeof FinalizationRegistry === 'undefined')
17374
18425
  ? { register: () => {}, unregister: () => {} }
17375
18426
  : new FinalizationRegistry(ptr => wasm.__wbg_mappingfactors_free(ptr, 1));
18427
+ const MoonElevationCrossingFinalization = (typeof FinalizationRegistry === 'undefined')
18428
+ ? { register: () => {}, unregister: () => {} }
18429
+ : new FinalizationRegistry(ptr => wasm.__wbg_moonelevationcrossing_free(ptr, 1));
18430
+ const MoonTransitFinalization = (typeof FinalizationRegistry === 'undefined')
18431
+ ? { register: () => {}, unregister: () => {} }
18432
+ : new FinalizationRegistry(ptr => wasm.__wbg_moontransit_free(ptr, 1));
17376
18433
  const MovingBaselineSolutionFinalization = (typeof FinalizationRegistry === 'undefined')
17377
18434
  ? { register: () => {}, unregister: () => {} }
17378
18435
  : new FinalizationRegistry(ptr => wasm.__wbg_movingbaselinesolution_free(ptr, 1));
@@ -17454,6 +18511,9 @@ const PppFixedSolutionFinalization = (typeof FinalizationRegistry === 'undefined
17454
18511
  const PppFloatSolutionFinalization = (typeof FinalizationRegistry === 'undefined')
17455
18512
  ? { register: () => {}, unregister: () => {} }
17456
18513
  : new FinalizationRegistry(ptr => wasm.__wbg_pppfloatsolution_free(ptr, 1));
18514
+ const PredictBatchFinalization = (typeof FinalizationRegistry === 'undefined')
18515
+ ? { register: () => {}, unregister: () => {} }
18516
+ : new FinalizationRegistry(ptr => wasm.__wbg_predictbatch_free(ptr, 1));
17457
18517
  const PredictedObservablesFinalization = (typeof FinalizationRegistry === 'undefined')
17458
18518
  ? { register: () => {}, unregister: () => {} }
17459
18519
  : new FinalizationRegistry(ptr => wasm.__wbg_predictedobservables_free(ptr, 1));