caelus 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,3 +7,4 @@ export * from "./stars.js";
7
7
  export * from "./eclipses.js";
8
8
  export * from "./query.js";
9
9
  export * from "./derived.js";
10
+ export * from "./turbo.js";
package/dist/src/index.js CHANGED
@@ -7,3 +7,4 @@ export * from "./stars.js";
7
7
  export * from "./eclipses.js";
8
8
  export * from "./query.js";
9
9
  export * from "./derived.js";
10
+ export * from "./turbo.js";
@@ -0,0 +1,20 @@
1
+ export interface TurboBody {
2
+ seg_days: number;
3
+ segments: number[][];
4
+ }
5
+ export interface TurboPack {
6
+ jd0: number;
7
+ jd1: number;
8
+ degree: number;
9
+ zodiac: string;
10
+ bodies: Record<string, TurboBody>;
11
+ }
12
+ export declare class Turbo {
13
+ readonly jd0: number;
14
+ readonly jd1: number;
15
+ private readonly bodies;
16
+ constructor(pack: TurboPack);
17
+ has(body: string): boolean;
18
+ /** Apparent ecliptic longitude (degrees) from the turbo pack. */
19
+ longitude(body: string, jd: number): number;
20
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * astroengine turbo -- fast longitude evaluator for a turbo pack.
3
+ *
4
+ * A turbo pack is a segmented Chebyshev representation of the engine's apparent
5
+ * longitude, fit to the engine itself (see python/astroengine/turbo.py and
6
+ * fit_turbo.py). Evaluating a longitude is a couple of dozen multiply-adds, so
7
+ * a century-scale transit scan that calls it tens of thousands of times runs in
8
+ * milliseconds. The pack is data you mint for your range and bodies; this is
9
+ * the runtime-only evaluator (no fitting, no engine, no I/O).
10
+ *
11
+ * The evaluator mirrors the Python reference exactly, so both reproduce the
12
+ * pack bit-identically.
13
+ */
14
+ import { mod } from "./core.js";
15
+ function clenshaw(coeffs, x) {
16
+ let b0 = 0;
17
+ let b1 = 0;
18
+ for (let i = coeffs.length - 1; i >= 1; i--) {
19
+ const t = 2 * x * b0 - b1 + coeffs[i];
20
+ b1 = b0;
21
+ b0 = t;
22
+ }
23
+ return x * b0 - b1 + coeffs[0];
24
+ }
25
+ export class Turbo {
26
+ jd0;
27
+ jd1;
28
+ bodies;
29
+ constructor(pack) {
30
+ this.jd0 = pack.jd0;
31
+ this.jd1 = pack.jd1;
32
+ this.bodies = pack.bodies;
33
+ }
34
+ has(body) {
35
+ return body in this.bodies;
36
+ }
37
+ /** Apparent ecliptic longitude (degrees) from the turbo pack. */
38
+ longitude(body, jd) {
39
+ const b = this.bodies[body];
40
+ if (!b)
41
+ throw new Error(`turbo: no pack for ${body}`);
42
+ if (jd < this.jd0 || jd > this.jd1) {
43
+ throw new Error(`jd ${jd} outside turbo range ${this.jd0}-${this.jd1}`);
44
+ }
45
+ const seg = b.seg_days;
46
+ const i = Math.min(Math.floor((jd - this.jd0) / seg), b.segments.length - 1);
47
+ const x = 2 * (jd - (this.jd0 + i * seg)) / seg - 1;
48
+ return mod(clenshaw(b.segments[i], x), 360);
49
+ }
50
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "caelus",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Astrological ephemeris engine. MIT, no AGPL, no ephemeris files. Checked against Swiss Ephemeris.",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",