@photivra/engine 2.5.0 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/CHANGELOG.md +129 -1
  2. package/CITATION.cff +1 -1
  3. package/README.md +6 -6
  4. package/SECURITY.md +1 -1
  5. package/THIRD_PARTY.md +1 -0
  6. package/dist/capture/native-environment-lean.d.ts +1 -1
  7. package/dist/capture/native-environment-lean.js +17 -3
  8. package/dist/capture/native-environment-lean.js.map +1 -1
  9. package/dist/capture/native-environment-raw.d.ts +0 -4
  10. package/dist/capture/native-environment-raw.js +6 -2
  11. package/dist/capture/native-environment-raw.js.map +1 -1
  12. package/dist/color/illuminants.d.ts +15 -0
  13. package/dist/color/illuminants.js +81 -24
  14. package/dist/color/illuminants.js.map +1 -1
  15. package/dist/color/srgb-transfer.d.ts +6 -0
  16. package/dist/color/srgb-transfer.js +9 -0
  17. package/dist/color/srgb-transfer.js.map +1 -1
  18. package/dist/color/white-balance.d.ts +6 -0
  19. package/dist/color/white-balance.js +15 -2
  20. package/dist/color/white-balance.js.map +1 -1
  21. package/dist/core/internal-radiance-evaluator.d.ts +6 -0
  22. package/dist/core/internal-radiance-evaluator.js +33 -0
  23. package/dist/core/internal-radiance-evaluator.js.map +1 -0
  24. package/dist/core/portable-math.d.ts +33 -0
  25. package/dist/core/portable-math.js +342 -0
  26. package/dist/core/portable-math.js.map +1 -1
  27. package/dist/core/version.d.ts +1 -1
  28. package/dist/core/version.js +1 -1
  29. package/dist/core/version.js.map +1 -1
  30. package/dist/facade/chart-radiance-batch.js +3 -2
  31. package/dist/facade/chart-radiance-batch.js.map +1 -1
  32. package/dist/facade/chart-scenes.d.ts +11 -0
  33. package/dist/facade/chart-scenes.js +21 -7
  34. package/dist/facade/chart-scenes.js.map +1 -1
  35. package/dist/facade/diffraction-provider.d.ts +10 -0
  36. package/dist/facade/diffraction-provider.js +38 -17
  37. package/dist/facade/diffraction-provider.js.map +1 -1
  38. package/dist/facade/display-view.d.ts +213 -0
  39. package/dist/facade/display-view.js +1543 -0
  40. package/dist/facade/display-view.js.map +1 -0
  41. package/dist/facade/scene-radiance.d.ts +45 -5
  42. package/dist/facade/scene-radiance.js +97 -28
  43. package/dist/facade/scene-radiance.js.map +1 -1
  44. package/dist/facade/simulate-capture.d.ts +233 -5
  45. package/dist/facade/simulate-capture.js +120 -37
  46. package/dist/facade/simulate-capture.js.map +1 -1
  47. package/dist/facade/simulate-display-view.d.ts +45 -0
  48. package/dist/facade/simulate-display-view.js +214 -0
  49. package/dist/facade/simulate-display-view.js.map +1 -0
  50. package/dist/facade/subject-framing.d.ts +16 -0
  51. package/dist/facade/subject-framing.js +8 -2
  52. package/dist/facade/subject-framing.js.map +1 -1
  53. package/dist/index.d.ts +3 -2
  54. package/dist/index.js +3 -2
  55. package/dist/index.js.map +1 -1
  56. package/dist/optics/diffraction-psf-profile.d.ts +9 -2
  57. package/dist/optics/diffraction-psf-profile.js +33 -4
  58. package/dist/optics/diffraction-psf-profile.js.map +1 -1
  59. package/dist/optics/irradiance-convolution.js +1 -1
  60. package/dist/optics/irradiance-convolution.js.map +1 -1
  61. package/dist/optics/scene-to-sensor-irradiance.d.ts +7 -0
  62. package/dist/optics/scene-to-sensor-irradiance.js +10 -5
  63. package/dist/optics/scene-to-sensor-irradiance.js.map +1 -1
  64. package/dist/output/print-plan.d.ts +8 -1
  65. package/dist/output/print-plan.js +8 -1
  66. package/dist/output/print-plan.js.map +1 -1
  67. package/dist/schema/scene-radiance.d.ts +16 -0
  68. package/dist/schema/scene-radiance.js +25 -4
  69. package/dist/schema/scene-radiance.js.map +1 -1
  70. package/dist/sensor/raw-readout.d.ts +12 -0
  71. package/dist/sensor/raw-readout.js +131 -9
  72. package/dist/sensor/raw-readout.js.map +1 -1
  73. package/dist/sensor/stochastic-seed.d.ts +13 -0
  74. package/dist/sensor/stochastic-seed.js +42 -8
  75. package/dist/sensor/stochastic-seed.js.map +1 -1
  76. package/docs/AGENT_GUIDE.md +1 -0
  77. package/docs/API_REFERENCE.md +19 -1
  78. package/docs/QUICK_START.md +203 -4
  79. package/docs/USAGE.md +15 -0
  80. package/docs/api/core-version.md +1 -1
  81. package/docs/api/exports.json +52 -2
  82. package/docs/api/facade-scene-radiance.md +34 -1
  83. package/docs/api/facade-simulate-capture.md +66 -2
  84. package/docs/api/facade-simulate-display-view.md +57 -0
  85. package/docs/api/facade-subject-framing.md +16 -0
  86. package/docs/api/output-print-plan.md +8 -1
  87. package/package.json +3 -2
@@ -53,4 +53,346 @@ export function equalWithinUlps(a, b, maximumUlps) {
53
53
  return true;
54
54
  return Math.abs(a - b) <= maximumUlps * Number.EPSILON * Math.max(Math.abs(a), Math.abs(b));
55
55
  }
56
+ // ---------------------------------------------------------------------------------------------------------------
57
+ // Portable logarithm, exponential, power, cube root and cosine/sine of 2πu.
58
+ //
59
+ // Each function below is a fixed sequence of correctly rounded binary64 operations (+, −, ×, ÷, exact
60
+ // power-of-two scaling through the IEEE 754 bit pattern, Math.round/Math.floor and integer operations), with
61
+ // every constant written as a decimal literal of at most 17 significant digits (ECMAScript converts these
62
+ // exactly to the nearest double). The bits of every result are therefore the same in every conforming
63
+ // JavaScript engine, unlike Math.pow, Math.exp, Math.log, Math.cbrt and Math.cos, which ECMA-262 leaves
64
+ // "implementation-approximated" (docs/NUMERICAL_CORRECTNESS.md, "Cross-engine determinism").
65
+ //
66
+ // Methods (textbook; no code copied):
67
+ // - Error-free transformations (double-double arithmetic): TwoSum (Knuth, The Art of Computer Programming
68
+ // vol. 2, §4.2.2), FastTwoSum and TwoProduct with Veltkamp's splitting (Dekker, "A floating-point technique
69
+ // for extending the available precision", Numerische Mathematik 18, 1971). Exact barring overflow and
70
+ // underflow, which the arguments here cannot reach.
71
+ // - log2(x): x = m·2^e with m in [√½, √2); ln m = 2·atanh(s) = 2(s + s³/3 + s⁵/5 + …), s = (m − 1)/(m + 1),
72
+ // |s| ≤ 0.1716 (J.-M. Muller, Elementary Functions: Algorithms and Implementation, 3rd ed., 2016, ch. 11).
73
+ // s carries a double-double correction; the series runs to s²³ (truncation below 2^-62 relative).
74
+ // - 2^t: t = n + r with n = round(t), |r| ≤ ½; 2^r = e^(r·ln 2) by its Taylor series to degree 14 (truncation
75
+ // below 2^-57 relative), then an exact scaling by 2^n (Muller, ch. 11, "additive range reduction").
76
+ // - x^y = 2^(y·log2 x) with log2 x and y·log2 x carried as double-double; e^x = 2^(x·log2 e) and
77
+ // ∛x = 2^(log2 x / 3) likewise; ln x = log2 x · ln 2; e^x − 1 by its Taylor series for |x| < 1.
78
+ // - cos(2πu), sin(2πu): u = q/4 + r with q = round(4u) and |r| ≤ ⅛ (exact), then the Taylor series of cos and
79
+ // sin of 2πr to degrees 18 and 19 (truncation below 2^-66).
80
+ //
81
+ // Error bounds (from the operation counts above): portableExp2, portableExp, portableLog, portableLog2 and
82
+ // portableCbrt within 1 ulp; portableExpm1 within 2 ulps; portablePow within 1 ulp for |y| ≤ 4 (the double-double
83
+ // logarithm has relative error below 2^-56, so the error of y·log2 x adds at most |y|·2^-57·ln 2 relative);
84
+ // portableCosTwoPi and portableSinTwoPi within 2 ulps. Checked against 60-digit decimal references (Python decimal)
85
+ // on 2·10⁵ pseudo-random arguments per function (6·10⁵ for portableLog; |y| ≤ 4 and y = 1/2.4, 1.4 for portablePow):
86
+ // largest errors 0.53 ulp (log, log2), 0.86 (exp2), 0.94 (exp, cbrt, pow), 0.97 (pow with y = 1/2.4), 1.59 (cos,
87
+ // sin of 2πu) and 1.66 (e^x − 1); spot values are in test/portable-math.test.ts. These are accuracy bounds;
88
+ // determinism does not depend on them.
89
+ /** Bit access to a double: the high 32-bit word is at index HIGH of the view (detected once, so either byte order works). */
90
+ // The tables and constants below are built by expressions marked pure (/* @__PURE__ */), so a bundler drops them from a
91
+ // bundle that uses none of the functions that read them (a capture-only bundle keeps only portableHypot and equalWithinUlps).
92
+ const BITS = /* @__PURE__ */ new Float64Array(1), WORDS = /* @__PURE__ */ (() => new Uint32Array(BITS.buffer))();
93
+ const HIGH = /* @__PURE__ */ (() => (new Uint8Array(new Uint16Array([1]).buffer)[0] === 1 ? 1 : 0))(), LOW = 1 - HIGH;
94
+ /** 2^k for every integer k in [−1074, 1023] at POW2[k + 1074], built by exact halving and doubling. */
95
+ const POW2 = /* @__PURE__ */ (() => {
96
+ const table = new Float64Array(2098);
97
+ table[1074] = 1;
98
+ for (let k = 1; k <= 1023; k++)
99
+ table[1074 + k] = table[1073 + k] * 2;
100
+ for (let k = 1; k <= 1074; k++)
101
+ table[1074 - k] = table[1075 - k] / 2;
102
+ return table;
103
+ })();
104
+ /** v·2^k for an integer k in [−1100, 1100]: one exact multiplication (a single rounding only when the result is subnormal). */
105
+ function scaleByPowerOfTwo(v, k) {
106
+ if (k > 1023)
107
+ return v * POW2[2097] * POW2[1074 + k - 1023];
108
+ if (k < -1074)
109
+ return v * POW2[1074 + k + 1074] * POW2[0]; // exact first factor (v·2^(k+1074) is normal), one rounding
110
+ return v * POW2[1074 + k];
111
+ }
112
+ // Double-double arithmetic, written out inline below (local variables only, which keeps it fast):
113
+ // - FastTwoSum (|a| ≥ |b| or a = 0): s = a + b, err = b − (s − a), so a + b = s + err exactly;
114
+ // - TwoSum (any a, b): s = a + b, b' = s − a, err = (a − (s − b')) + (b − b');
115
+ // - TwoProduct: p = a·b, err = ((ah·bh − p) + ah·bl + al·bh) + al·bl, with Veltkamp's split
116
+ // ah = c − (c − a), al = a − ah, c = (2^27 + 1)·a (and likewise for b), so a·b = p + err exactly.
117
+ const SPLITTER = 134217729; // 2^27 + 1 (Veltkamp)
118
+ const LN2_HI = 0.6931471805599453, LN2_LO = 2.3190468138462996e-17;
119
+ const LOG2E_HI = 1.4426950408889634, LOG2E_LO = 2.0355273740931033e-17;
120
+ const SQRT2 = 1.4142135623730951, TWO_POW_54 = 18014398509481984, MIN_NORMAL = 2.2250738585072014e-308;
121
+ /** Veltkamp halves of a constant (the same values the split gives at each use). */
122
+ function splitHigh(a) { const c = SPLITTER * a; return c - (c - a); }
123
+ const LN2_HI_H = /* @__PURE__ */ splitHigh(LN2_HI), LN2_HI_L = LN2_HI - LN2_HI_H, LOG2E_HI_H = /* @__PURE__ */ splitHigh(LOG2E_HI), LOG2E_HI_L = LOG2E_HI - LOG2E_HI_H;
124
+ /** The low part of the last double-double result (its high part is the return value). */
125
+ const LOW_PART = /* @__PURE__ */ new Float64Array(1);
126
+ /**
127
+ * log2 m for m in [√½, √2] by the atanh series to s²³ (no table): builds LOG2_TABLE once. Returns the high part, the low
128
+ * part in LOW_PART[0]; relative error below 2^-56.
129
+ */
130
+ function log2SeriesDoubleDouble(x) {
131
+ let e = 0;
132
+ if (x < MIN_NORMAL) {
133
+ x *= TWO_POW_54;
134
+ e = -54;
135
+ }
136
+ BITS[0] = x;
137
+ const high = WORDS[HIGH];
138
+ e += (high >>> 20) - 1023;
139
+ let m = x * POW2[1074 - ((high >>> 20) - 1023)]; // exact: m in [1, 2)
140
+ if (m > SQRT2) {
141
+ m *= 0.5;
142
+ e += 1;
143
+ }
144
+ // s = f/(2 + f) with f = m − 1 (exact), as sHi + sLo: 2 + f = dh + dl exactly (FastTwoSum), then the residual
145
+ // f − sHi·(dh + dl) with sHi·dh = p + pe exactly (TwoProduct).
146
+ const f = m - 1, dh = 2 + f, dl = f - (dh - 2), sHi = f / dh, p = sHi * dh;
147
+ let c = SPLITTER * sHi;
148
+ const ah = c - (c - sHi), al = sHi - ah;
149
+ c = SPLITTER * dh;
150
+ const bh = c - (c - dh), bl = dh - bh, pe = ((ah * bh - p) + ah * bl + al * bh) + al * bl;
151
+ const sLo = (((f - p) - pe) - sHi * dl) / dh;
152
+ const z = sHi * sHi;
153
+ const tail = sHi * z * (0.6666666666666666 + z * (0.4 + z * (0.2857142857142857 + z * (0.2222222222222222 + z * (0.18181818181818182 + z * (0.15384615384615385 +
154
+ z * (0.13333333333333333 + z * (0.11764705882352941 + z * (0.10526315789473684 + z * (0.09523809523809523 + z * 0.08695652173913043))))))))));
155
+ // ln m = 2sHi + (2sLo + tail) = lh + ll (FastTwoSum); times log2 e = LOG2E_HI + LOG2E_LO (TwoProduct of the high parts); plus e (TwoSum).
156
+ const a1 = 2 * sHi, b1 = 2 * sLo + tail, lh = a1 + b1, ll = b1 - (lh - a1), q = lh * LOG2E_HI;
157
+ c = SPLITTER * lh;
158
+ const ch = c - (c - lh), cl = lh - ch, qe = ((ch * LOG2E_HI_H - q) + ch * LOG2E_HI_L + cl * LOG2E_HI_H) + cl * LOG2E_HI_L;
159
+ const pl = qe + (lh * LOG2E_LO + ll * LOG2E_HI);
160
+ const t = e + q, tb = t - e, te = (e - (t - tb)) + (q - tb), b2 = te + pl, hi = t + b2;
161
+ LOW_PART[0] = b2 - (hi - t);
162
+ return hi;
163
+ }
164
+ /** log2(k/128) for k = 90 … 182 (the table's range of k = round(128·m), m in [√½, √2]) as double-doubles. */
165
+ const LOG2_TABLE_LO = /* @__PURE__ */ new Float64Array(183);
166
+ const LOG2_TABLE_HI = /* @__PURE__ */ (() => {
167
+ const table = new Float64Array(183);
168
+ for (let k = 90; k <= 182; k++) {
169
+ table[k] = log2SeriesDoubleDouble(k / 128);
170
+ LOG2_TABLE_LO[k] = LOW_PART[0];
171
+ }
172
+ return table;
173
+ })();
174
+ /**
175
+ * log2 x as a double-double for finite x > 0: returns the high part, the low part in LOW_PART[0]. x = m·2^e with m in
176
+ * [√½, √2]; m = F·(1 + f/F) with F = k/128, k = round(128·m), so log2 m = log2 F (table) + 2·atanh(s)·log2 e with
177
+ * s = f/(m + F), |s| < 2^-8.4, by its series to s⁷ (truncation below 2^-70 relative). Relative error below 2^-56.
178
+ */
179
+ function log2DoubleDouble(x) {
180
+ let e = 0;
181
+ if (x < MIN_NORMAL) {
182
+ x *= TWO_POW_54;
183
+ e = -54;
184
+ }
185
+ BITS[0] = x;
186
+ const high = WORDS[HIGH];
187
+ e += (high >>> 20) - 1023;
188
+ let m = x * POW2[1074 - ((high >>> 20) - 1023)]; // exact: m in [1, 2)
189
+ if (m > SQRT2) {
190
+ m *= 0.5;
191
+ e += 1;
192
+ }
193
+ // F = k/128 (exact) and f = m − F (exact, F/2 ≤ m ≤ 2F); m + F = dh + dl exactly (TwoSum); s = f/(dh + dl) as sHi + sLo
194
+ // from the residual f − sHi·(dh + dl), with sHi·dh = p + pe exactly (TwoProduct).
195
+ const k = Math.round(m * 128), F = k / 128, f = m - F, dh = m + F, db = dh - m, dl = (m - (dh - db)) + (F - db);
196
+ const sHi = f / dh, p = sHi * dh;
197
+ let c = SPLITTER * sHi;
198
+ const ah = c - (c - sHi), al = sHi - ah;
199
+ c = SPLITTER * dh;
200
+ const bh = c - (c - dh), bl = dh - bh, pe = ((ah * bh - p) + ah * bl + al * bh) + al * bl;
201
+ const sLo = (((f - p) - pe) - sHi * dl) / dh, z = sHi * sHi;
202
+ const tail = sHi * z * (0.6666666666666666 + z * (0.4 + z * 0.2857142857142857));
203
+ // ln(m/F) = 2sHi + (2sLo + tail) = lh + ll (FastTwoSum); times log2 e = LOG2E_HI + LOG2E_LO (TwoProduct of the high
204
+ // parts); plus log2 F (TwoSum with the table's high part), then plus e (TwoSum).
205
+ const a1 = 2 * sHi, b1 = 2 * sLo + tail, lh = a1 + b1, ll = b1 - (lh - a1), q = lh * LOG2E_HI;
206
+ c = SPLITTER * lh;
207
+ const ch = c - (c - lh), cl = lh - ch, qe = ((ch * LOG2E_HI_H - q) + ch * LOG2E_HI_L + cl * LOG2E_HI_H) + cl * LOG2E_HI_L;
208
+ const pl = qe + (lh * LOG2E_LO + ll * LOG2E_HI), th = LOG2_TABLE_HI[k];
209
+ const t = th + q, tb = t - th, low = ((th - (t - tb)) + (q - tb)) + (pl + LOG2_TABLE_LO[k]);
210
+ const u = e + t, ub = u - e, b2 = ((e - (u - ub)) + (t - ub)) + low, hi = u + b2;
211
+ LOW_PART[0] = b2 - (hi - u);
212
+ return hi;
213
+ }
214
+ /** 2^(th + tl) for a double-double exponent; within 1 ulp (plus the error the exponent carries). */
215
+ function exp2DoubleDouble(th, tl) {
216
+ if (th !== th)
217
+ return NaN;
218
+ if (th > 1024)
219
+ return Infinity;
220
+ if (th < -1080)
221
+ return 0;
222
+ // th = n + r exactly (|r| ≤ ½); w = r·ln 2 = wh + wl (TwoProduct with LN2_HI, plus r·LN2_LO).
223
+ const n = Math.round(th), r = (th - n) + tl, wh = r * LN2_HI, c = SPLITTER * r, ah = c - (c - r), al = r - ah;
224
+ const wl = (((ah * LN2_HI_H - wh) + ah * LN2_HI_L + al * LN2_HI_H) + al * LN2_HI_L) + r * LN2_LO;
225
+ const q = 0.5 + wh * (0.16666666666666666 + wh * (0.041666666666666664 + wh * (0.008333333333333333 + wh * (0.001388888888888889 + wh * (0.0001984126984126984 +
226
+ wh * (2.48015873015873e-05 + wh * (2.7557319223985893e-06 + wh * (2.755731922398589e-07 + wh * (2.505210838544172e-08 + wh * (2.08767569878681e-09 +
227
+ wh * (1.6059043836821613e-10 + wh * 1.1470745597729725e-11)))))))))));
228
+ return scaleByPowerOfTwo(1 + (wh + (wl + wh * wh * q)), n);
229
+ }
230
+ /** log2 x, bit-identical in every JavaScript engine (within 1 ulp). 0 → −∞; negative or NaN → NaN; +∞ → +∞. */
231
+ export function portableLog2(x) {
232
+ if (!(x > 0))
233
+ return x === 0 ? -Infinity : NaN;
234
+ if (x === Infinity)
235
+ return Infinity;
236
+ const h = log2DoubleDouble(x);
237
+ return h + LOW_PART[0];
238
+ }
239
+ /** ln(k/128) for k = 90 … 182 as double-doubles (log2(k/128)·ln 2, TwoProduct with LN2_HI plus the small products). */
240
+ const LN_TABLE_LO = /* @__PURE__ */ new Float64Array(183);
241
+ const LN_TABLE_HI = /* @__PURE__ */ (() => {
242
+ const table = new Float64Array(183);
243
+ for (let k = 90; k <= 182; k++) {
244
+ const h = LOG2_TABLE_HI[k], l = LOG2_TABLE_LO[k], p = h * LN2_HI, c = SPLITTER * h, ah = c - (c - h), al = h - ah;
245
+ const pe = ((ah * LN2_HI_H - p) + ah * LN2_HI_L + al * LN2_HI_H) + al * LN2_HI_L, lo = pe + (h * LN2_LO + l * LN2_HI), hi = p + lo;
246
+ table[k] = hi;
247
+ LN_TABLE_LO[k] = lo - (hi - p);
248
+ }
249
+ return table;
250
+ })();
251
+ /** ln 2 = LN2_E_HI + LN2_E_LO with the low 32 bits of LN2_E_HI zero, so e·LN2_E_HI is exact for every exponent e here. */
252
+ const LN2_E_HI = /* @__PURE__ */ (() => { BITS[0] = LN2_HI; WORDS[LOW] = 0; return BITS[0]; })(), LN2_E_LO = (LN2_HI - LN2_E_HI) + LN2_LO;
253
+ /**
254
+ * Natural logarithm, bit-identical in every JavaScript engine (within 1 ulp). 0 → −∞; negative or NaN → NaN; +∞ → +∞.
255
+ * x = m·2^e, m in [√½, √2]; ln x = e·ln 2 + ln F (table, F = k/128, k = round(128·m)) + 2·atanh(s), s = (m − F)/(m + F),
256
+ * with s as a double-double and the three terms added with TwoSum.
257
+ */
258
+ export function portableLog(x) {
259
+ if (!(x > 0))
260
+ return x === 0 ? -Infinity : NaN;
261
+ if (x === Infinity)
262
+ return Infinity;
263
+ let e = 0;
264
+ if (x < MIN_NORMAL) {
265
+ x *= TWO_POW_54;
266
+ e = -54;
267
+ }
268
+ BITS[0] = x;
269
+ const high = WORDS[HIGH];
270
+ e += (high >>> 20) - 1023;
271
+ let m = x * POW2[1074 - ((high >>> 20) - 1023)]; // exact: m in [1, 2)
272
+ if (m > SQRT2) {
273
+ m *= 0.5;
274
+ e += 1;
275
+ }
276
+ const k = Math.round(m * 128), F = k / 128, f = m - F, dh = m + F, db = dh - m, dl = (m - (dh - db)) + (F - db);
277
+ const sHi = f / dh, p = sHi * dh;
278
+ let c = SPLITTER * sHi;
279
+ const ah = c - (c - sHi), al = sHi - ah;
280
+ c = SPLITTER * dh;
281
+ const bh = c - (c - dh), bl = dh - bh, pe = ((ah * bh - p) + ah * bl + al * bh) + al * bl;
282
+ const sLo = (((f - p) - pe) - sHi * dl) / dh, z = sHi * sHi;
283
+ const tail = sHi * z * (0.6666666666666666 + z * (0.4 + z * 0.2857142857142857));
284
+ // (e·LN2_E_HI + ln F) + 2sHi with TwoSum errors, then the low parts.
285
+ const A = e * LN2_E_HI, B = LN_TABLE_HI[k], t = A + B, tb = t - A, te = (A - (t - tb)) + (B - tb);
286
+ const a2 = 2 * sHi, u = t + a2, ub = u - t, ue = (t - (u - ub)) + (a2 - ub);
287
+ return u + ((te + ue) + ((e * LN2_E_LO + LN_TABLE_LO[k]) + (2 * sLo + tail)));
288
+ }
289
+ /** 2^x, bit-identical in every JavaScript engine (within 1 ulp). */
290
+ export function portableExp2(x) { return exp2DoubleDouble(x, 0); }
291
+ /** e^x, bit-identical in every JavaScript engine (within 1 ulp). */
292
+ export function portableExp(x) {
293
+ if (x !== x)
294
+ return NaN;
295
+ if (x > 710)
296
+ return Infinity;
297
+ if (x < -746)
298
+ return 0;
299
+ // x·log2 e = th + tl: x·LOG2E_HI = th + te exactly (TwoProduct), plus x·LOG2E_LO.
300
+ const th = x * LOG2E_HI, c = SPLITTER * x, ah = c - (c - x), al = x - ah;
301
+ const te = ((ah * LOG2E_HI_H - th) + ah * LOG2E_HI_L + al * LOG2E_HI_H) + al * LOG2E_HI_L;
302
+ return exp2DoubleDouble(th, te + x * LOG2E_LO);
303
+ }
304
+ /**
305
+ * e^x − 1, bit-identical in every JavaScript engine (within 2 ulps): the Taylor series to degree 20 for |x| < 1
306
+ * (truncation below 2^-60 relative), else portableExp(x) − 1.
307
+ */
308
+ export function portableExpm1(x) {
309
+ if (x !== x)
310
+ return NaN;
311
+ if (x === 0)
312
+ return x;
313
+ if (!(x > -1 && x < 1))
314
+ return portableExp(x) - 1;
315
+ return x + x * x * (0.5 + x * (0.16666666666666666 + x * (0.041666666666666664 + x * (0.008333333333333333 + x * (0.001388888888888889 + x * (0.0001984126984126984 +
316
+ x * (2.48015873015873e-05 + x * (2.7557319223985893e-06 + x * (2.755731922398589e-07 + x * (2.505210838544172e-08 + x * (2.08767569878681e-09 +
317
+ x * (1.6059043836821613e-10 + x * (1.1470745597729725e-11 + x * (7.647163731819816e-13 + x * (4.779477332387385e-14 + x * (2.8114572543455206e-15 +
318
+ x * (1.5619206968586225e-16 + x * (8.22063524662433e-18 + x * 4.110317623312165e-19))))))))))))))))));
319
+ }
320
+ /**
321
+ * x^y for x ≥ 0 and finite y, bit-identical in every JavaScript engine (within 1 ulp for |y| ≤ 4). x = 0 gives 0 for
322
+ * y > 0, 1 for y = 0 and +∞ for y < 0; negative x or a non-finite argument gives NaN (the callers never pass them).
323
+ */
324
+ export function portablePow(x, y) {
325
+ if (!(x >= 0) || !Number.isFinite(x) || !Number.isFinite(y))
326
+ return NaN;
327
+ if (y === 0 || x === 1)
328
+ return 1;
329
+ if (x === 0)
330
+ return y > 0 ? 0 : Infinity;
331
+ // y·(lh + ll): lh·y = p + pe exactly (TwoProduct), then FastTwoSum(p, pe + ll·y).
332
+ const lh = log2DoubleDouble(x), ll = LOW_PART[0], p = lh * y;
333
+ let c = SPLITTER * lh;
334
+ const ah = c - (c - lh), al = lh - ah;
335
+ c = SPLITTER * y;
336
+ const bh = c - (c - y), bl = y - bh, pe = ((ah * bh - p) + ah * bl + al * bh) + al * bl;
337
+ const b = pe + ll * y, th = p + b;
338
+ return exp2DoubleDouble(th, b - (th - p));
339
+ }
340
+ /** ∛(2^r) for r = 0, 1, 2 (only scale the cube root's starting value, so their last bits do not matter). */
341
+ const CBRT_POWERS_OF_TWO = [1, 1.2599210498948732, 1.5874010519681994];
342
+ /**
343
+ * Cube root, bit-identical in every JavaScript engine (within 1 ulp; exact for ±0, ±∞ and cubes of powers of two).
344
+ * |x| = m·2^(3q + r) with m in [1, 2) and r in {0, 1, 2}, w = m·2^r: a cubic fit to ∛m (within 1.7·10⁻⁴) times ∛(2^r),
345
+ * one Halley step y ← y(y³ + 2w)/(2y³ + w) (cubic convergence: below 10⁻¹¹), then one Newton step y + (w − y³)/(3y²)
346
+ * with w − y³ formed exactly (TwoProduct), which leaves only the final rounding and errors near 10⁻²².
347
+ */
348
+ export function portableCbrt(x) {
349
+ if (x === 0 || x !== x || !Number.isFinite(x))
350
+ return x;
351
+ let a = x < 0 ? -x : x, shift = 0;
352
+ if (a < MIN_NORMAL) {
353
+ a *= TWO_POW_54;
354
+ shift = -18;
355
+ }
356
+ BITS[0] = a;
357
+ const high = WORDS[HIGH], e = (high >>> 20) - 1023, q = Math.floor(e / 3), r = e - 3 * q;
358
+ const m = a * POW2[1074 - e], w = m * CBRT_SCALE[r]; // exact: m in [1, 2)
359
+ let y = (0.5561432746078446 + m * (0.5806821751356804 + m * (-0.15894786280039686 + m * 0.022291567104952514))) * CBRT_POWERS_OF_TWO[r];
360
+ const y3 = y * y * y;
361
+ y = y * (y3 + 2 * w) / (2 * y3 + w);
362
+ // y² = p + pe exactly; y³ = p·y + pe·y = t + te (TwoProduct of p and y, plus pe·y); w − y³ = (w − t) − te.
363
+ const p = y * y;
364
+ let c = SPLITTER * y;
365
+ const yh = c - (c - y), yl = y - yh, pe = ((yh * yh - p) + yh * yl + yl * yh) + yl * yl, t = p * y;
366
+ c = SPLITTER * p;
367
+ const ph = c - (c - p), pll = p - ph, te = (((ph * yh - t) + ph * yl + pll * yh) + pll * yl) + pe * y;
368
+ const root = scaleByPowerOfTwo(y + ((w - t) - te) / (3 * p), q + shift);
369
+ return x < 0 ? -root : root;
370
+ }
371
+ /** 2^r for r = 0, 1, 2. */
372
+ const CBRT_SCALE = [1, 2, 4];
373
+ /** cos(2πr) and sin(2πr) for |r| ≤ ⅛ (Taylor series in z = r²). */
374
+ function cosTwoPiReduced(r) {
375
+ const z = r * r;
376
+ return 1 + z * (-19.739208802178716 + z * (64.9393940226683 + z * (-85.45681720669373 + z * (60.24464137187666 + z * (-26.4262567833744 + z * (7.903536371318469 +
377
+ z * (-1.714390711088672 + z * (0.28200596845579123 + z * -0.03638284114254567))))))));
378
+ }
379
+ function sinTwoPiReduced(r) {
380
+ const z = r * r;
381
+ return r * (6.283185307179586 + z * (-41.34170224039976 + z * (81.60524927607506 + z * (-76.70585975306139 + z * (42.058693944897655 + z * (-15.09464257682299 +
382
+ z * (3.819952584848282 + z * (-0.7181223017785006 + z * (0.10422916220813984 + z * -0.012031585942120627)))))))));
383
+ }
384
+ /** cos(2πu) for finite u (u in turns), bit-identical in every JavaScript engine (within 2 ulps). */
385
+ export function portableCosTwoPi(u) {
386
+ if (!Number.isFinite(u))
387
+ return NaN;
388
+ const t = 4 * u, q = Math.round(t), r = (t - q) / 4, quadrant = ((q % 4) + 4) % 4;
389
+ return quadrant === 0 ? cosTwoPiReduced(r) : quadrant === 1 ? -sinTwoPiReduced(r) : quadrant === 2 ? -cosTwoPiReduced(r) : sinTwoPiReduced(r);
390
+ }
391
+ /** sin(2πu) for finite u (u in turns), bit-identical in every JavaScript engine (within 2 ulps). */
392
+ export function portableSinTwoPi(u) {
393
+ if (!Number.isFinite(u))
394
+ return NaN;
395
+ const t = 4 * u, q = Math.round(t), r = (t - q) / 4, quadrant = ((q % 4) + 4) % 4;
396
+ return quadrant === 0 ? sinTwoPiReduced(r) : quadrant === 1 ? cosTwoPiReduced(r) : quadrant === 2 ? -sinTwoPiReduced(r) : -cosTwoPiReduced(r);
397
+ }
56
398
  //# sourceMappingURL=portable-math.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"portable-math.js","sourceRoot":"","sources":["../../src/core/portable-math.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;;;;;;;;;;GAYG;AAEH,MAAM,KAAK,GAAG,CAAC,IAAI,GAAG,CAAC;AACvB,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC;AACxB,MAAM,UAAU,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC;AAC7B,MAAM,QAAQ,GAAG,CAAC,IAAI,GAAG,CAAC;AAE1B;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,GAAG,MAAyB;IACxD,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,CAAC,CAAC,SAAS,IAAI,OAAO,CAAC;YAAE,OAAO,GAAG,SAAS,CAAC;IACnD,CAAC;IACD,IAAI,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAC;IAC/D,MAAM,KAAK,GAAG,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5E,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,KAAK,GAAG,KAAK,CAAC;QAC7B,GAAG,IAAI,MAAM,GAAG,MAAM,CAAC;IACzB,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAChC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,CAAS,EAAE,CAAS,EAAE,WAAmB;IACvE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7D,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACzB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,WAAW,GAAG,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9F,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Floating-point helpers that give bit-identical results in every JavaScript engine.\n *\n * ECMAScript requires `+ - * /` and `Math.sqrt` to be correctly rounded IEEE 754 binary64\n * (double-precision) operations. A fixed sequence of them gives the same bits in every\n * conforming engine. `Math.hypot`, `Math.exp`, `Math.atan`, `Math.cos` and the other\n * transcendental functions are \"implementation-approximated\" (ECMA-262 §21.3.2). They can\n * differ in the last bit between V8, JavaScriptCore and SpiderMonkey.\n *\n * So any value that is stored and later recomputed for an exact identity check must use\n * only the correctly rounded operations.\n * @see docs/NUMERICAL_CORRECTNESS.md §Cross-engine determinism\n */\n\nconst LARGE = 2 ** 500;\nconst SMALL = 2 ** -500;\nconst SCALE_DOWN = 2 ** -600;\nconst SCALE_UP = 2 ** 600;\n\n/**\n * Euclidean norm (vector length) of the components. Unlike `Math.hypot`, it uses only correctly\n * rounded IEEE operations, so the result is bit-identical in every JavaScript engine.\n *\n * Components are summed in argument order. Inputs far from 1 are first rescaled by an exact power\n * of two, so squaring cannot overflow or underflow. Non-finite input gives a non-finite result;\n * callers validate inputs first.\n */\nexport function portableHypot(...values: readonly number[]): number {\n let maximum = 0;\n for (const value of values) {\n const magnitude = Math.abs(value);\n if (!(magnitude <= maximum)) maximum = magnitude;\n }\n if (maximum === 0 || !Number.isFinite(maximum)) return maximum;\n const scale = maximum > LARGE ? SCALE_DOWN : maximum < SMALL ? SCALE_UP : 1;\n let sum = 0;\n for (const value of values) {\n const scaled = value * scale;\n sum += scaled * scaled;\n }\n return Math.sqrt(sum) / scale;\n}\n\n/**\n * True when two finite numbers differ by at most `maximumUlps` ULPs (units in the last place).\n * One ULP here is `Number.EPSILON` times the larger magnitude. Use it to accept an archived value\n * that another engine or an earlier release computed with an implementation-approximated function.\n */\nexport function equalWithinUlps(a: number, b: number, maximumUlps: number): boolean {\n if (!Number.isFinite(a) || !Number.isFinite(b)) return false;\n if (a === b) return true;\n return Math.abs(a - b) <= maximumUlps * Number.EPSILON * Math.max(Math.abs(a), Math.abs(b));\n}\n"]}
1
+ {"version":3,"file":"portable-math.js","sourceRoot":"","sources":["../../src/core/portable-math.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Floating-point helpers that give bit-identical results in every JavaScript engine.\n *\n * ECMAScript requires `+ - * /` and `Math.sqrt` to be correctly rounded IEEE 754 binary64\n * (double-precision) operations. A fixed sequence of them gives the same bits in every\n * conforming engine. `Math.hypot`, `Math.exp`, `Math.atan`, `Math.cos` and the other\n * transcendental functions are \"implementation-approximated\" (ECMA-262 §21.3.2). They can\n * differ in the last bit between V8, JavaScriptCore and SpiderMonkey.\n *\n * So any value that is stored and later recomputed for an exact identity check must use\n * only the correctly rounded operations.\n * @see docs/NUMERICAL_CORRECTNESS.md §Cross-engine determinism\n */\n\nconst LARGE = 2 ** 500;\nconst SMALL = 2 ** -500;\nconst SCALE_DOWN = 2 ** -600;\nconst SCALE_UP = 2 ** 600;\n\n/**\n * Euclidean norm (vector length) of the components. Unlike `Math.hypot`, it uses only correctly\n * rounded IEEE operations, so the result is bit-identical in every JavaScript engine.\n *\n * Components are summed in argument order. Inputs far from 1 are first rescaled by an exact power\n * of two, so squaring cannot overflow or underflow. Non-finite input gives a non-finite result;\n * callers validate inputs first.\n */\nexport function portableHypot(...values: readonly number[]): number {\n let maximum = 0;\n for (const value of values) {\n const magnitude = Math.abs(value);\n if (!(magnitude <= maximum)) maximum = magnitude;\n }\n if (maximum === 0 || !Number.isFinite(maximum)) return maximum;\n const scale = maximum > LARGE ? SCALE_DOWN : maximum < SMALL ? SCALE_UP : 1;\n let sum = 0;\n for (const value of values) {\n const scaled = value * scale;\n sum += scaled * scaled;\n }\n return Math.sqrt(sum) / scale;\n}\n\n/**\n * True when two finite numbers differ by at most `maximumUlps` ULPs (units in the last place).\n * One ULP here is `Number.EPSILON` times the larger magnitude. Use it to accept an archived value\n * that another engine or an earlier release computed with an implementation-approximated function.\n */\nexport function equalWithinUlps(a: number, b: number, maximumUlps: number): boolean {\n if (!Number.isFinite(a) || !Number.isFinite(b)) return false;\n if (a === b) return true;\n return Math.abs(a - b) <= maximumUlps * Number.EPSILON * Math.max(Math.abs(a), Math.abs(b));\n}\n\n// ---------------------------------------------------------------------------------------------------------------\n// Portable logarithm, exponential, power, cube root and cosine/sine of 2πu.\n//\n// Each function below is a fixed sequence of correctly rounded binary64 operations (+, −, ×, ÷, exact\n// power-of-two scaling through the IEEE 754 bit pattern, Math.round/Math.floor and integer operations), with\n// every constant written as a decimal literal of at most 17 significant digits (ECMAScript converts these\n// exactly to the nearest double). The bits of every result are therefore the same in every conforming\n// JavaScript engine, unlike Math.pow, Math.exp, Math.log, Math.cbrt and Math.cos, which ECMA-262 leaves\n// \"implementation-approximated\" (docs/NUMERICAL_CORRECTNESS.md, \"Cross-engine determinism\").\n//\n// Methods (textbook; no code copied):\n// - Error-free transformations (double-double arithmetic): TwoSum (Knuth, The Art of Computer Programming\n// vol. 2, §4.2.2), FastTwoSum and TwoProduct with Veltkamp's splitting (Dekker, \"A floating-point technique\n// for extending the available precision\", Numerische Mathematik 18, 1971). Exact barring overflow and\n// underflow, which the arguments here cannot reach.\n// - log2(x): x = m·2^e with m in [√½, √2); ln m = 2·atanh(s) = 2(s + s³/3 + s⁵/5 + …), s = (m − 1)/(m + 1),\n// |s| ≤ 0.1716 (J.-M. Muller, Elementary Functions: Algorithms and Implementation, 3rd ed., 2016, ch. 11).\n// s carries a double-double correction; the series runs to s²³ (truncation below 2^-62 relative).\n// - 2^t: t = n + r with n = round(t), |r| ≤ ½; 2^r = e^(r·ln 2) by its Taylor series to degree 14 (truncation\n// below 2^-57 relative), then an exact scaling by 2^n (Muller, ch. 11, \"additive range reduction\").\n// - x^y = 2^(y·log2 x) with log2 x and y·log2 x carried as double-double; e^x = 2^(x·log2 e) and\n// ∛x = 2^(log2 x / 3) likewise; ln x = log2 x · ln 2; e^x − 1 by its Taylor series for |x| < 1.\n// - cos(2πu), sin(2πu): u = q/4 + r with q = round(4u) and |r| ≤ ⅛ (exact), then the Taylor series of cos and\n// sin of 2πr to degrees 18 and 19 (truncation below 2^-66).\n//\n// Error bounds (from the operation counts above): portableExp2, portableExp, portableLog, portableLog2 and\n// portableCbrt within 1 ulp; portableExpm1 within 2 ulps; portablePow within 1 ulp for |y| ≤ 4 (the double-double\n// logarithm has relative error below 2^-56, so the error of y·log2 x adds at most |y|·2^-57·ln 2 relative);\n// portableCosTwoPi and portableSinTwoPi within 2 ulps. Checked against 60-digit decimal references (Python decimal)\n// on 2·10⁵ pseudo-random arguments per function (6·10⁵ for portableLog; |y| ≤ 4 and y = 1/2.4, 1.4 for portablePow):\n// largest errors 0.53 ulp (log, log2), 0.86 (exp2), 0.94 (exp, cbrt, pow), 0.97 (pow with y = 1/2.4), 1.59 (cos,\n// sin of 2πu) and 1.66 (e^x − 1); spot values are in test/portable-math.test.ts. These are accuracy bounds;\n// determinism does not depend on them.\n\n/** Bit access to a double: the high 32-bit word is at index HIGH of the view (detected once, so either byte order works). */\n// The tables and constants below are built by expressions marked pure (/* @__PURE__ */), so a bundler drops them from a\n// bundle that uses none of the functions that read them (a capture-only bundle keeps only portableHypot and equalWithinUlps).\nconst BITS = /* @__PURE__ */ new Float64Array(1), WORDS = /* @__PURE__ */ ((): Uint32Array => new Uint32Array(BITS.buffer))();\nconst HIGH = /* @__PURE__ */ ((): number => (new Uint8Array(new Uint16Array([1]).buffer)[0] === 1 ? 1 : 0))(), LOW = 1 - HIGH;\n/** 2^k for every integer k in [−1074, 1023] at POW2[k + 1074], built by exact halving and doubling. */\nconst POW2 = /* @__PURE__ */ ((): Float64Array => {\n const table = new Float64Array(2098);\n table[1074] = 1;\n for (let k = 1; k <= 1023; k++) table[1074 + k] = table[1073 + k]! * 2;\n for (let k = 1; k <= 1074; k++) table[1074 - k] = table[1075 - k]! / 2;\n return table;\n})();\n/** v·2^k for an integer k in [−1100, 1100]: one exact multiplication (a single rounding only when the result is subnormal). */\nfunction scaleByPowerOfTwo(v: number, k: number): number {\n if (k > 1023) return v * POW2[2097]! * POW2[1074 + k - 1023]!;\n if (k < -1074) return v * POW2[1074 + k + 1074]! * POW2[0]!; // exact first factor (v·2^(k+1074) is normal), one rounding\n return v * POW2[1074 + k]!;\n}\n// Double-double arithmetic, written out inline below (local variables only, which keeps it fast):\n// - FastTwoSum (|a| ≥ |b| or a = 0): s = a + b, err = b − (s − a), so a + b = s + err exactly;\n// - TwoSum (any a, b): s = a + b, b' = s − a, err = (a − (s − b')) + (b − b');\n// - TwoProduct: p = a·b, err = ((ah·bh − p) + ah·bl + al·bh) + al·bl, with Veltkamp's split\n// ah = c − (c − a), al = a − ah, c = (2^27 + 1)·a (and likewise for b), so a·b = p + err exactly.\nconst SPLITTER = 134217729; // 2^27 + 1 (Veltkamp)\nconst LN2_HI = 0.6931471805599453, LN2_LO = 2.3190468138462996e-17;\nconst LOG2E_HI = 1.4426950408889634, LOG2E_LO = 2.0355273740931033e-17;\nconst SQRT2 = 1.4142135623730951, TWO_POW_54 = 18014398509481984, MIN_NORMAL = 2.2250738585072014e-308;\n/** Veltkamp halves of a constant (the same values the split gives at each use). */\nfunction splitHigh(a: number): number { const c = SPLITTER * a; return c - (c - a); }\nconst LN2_HI_H = /* @__PURE__ */ splitHigh(LN2_HI), LN2_HI_L = LN2_HI - LN2_HI_H, LOG2E_HI_H = /* @__PURE__ */ splitHigh(LOG2E_HI), LOG2E_HI_L = LOG2E_HI - LOG2E_HI_H;\n/** The low part of the last double-double result (its high part is the return value). */\nconst LOW_PART = /* @__PURE__ */ new Float64Array(1);\n\n/**\n * log2 m for m in [√½, √2] by the atanh series to s²³ (no table): builds LOG2_TABLE once. Returns the high part, the low\n * part in LOW_PART[0]; relative error below 2^-56.\n */\nfunction log2SeriesDoubleDouble(x: number): number {\n let e = 0;\n if (x < MIN_NORMAL) { x *= TWO_POW_54; e = -54; }\n BITS[0] = x;\n const high = WORDS[HIGH]!;\n e += (high >>> 20) - 1023;\n let m = x * POW2[1074 - ((high >>> 20) - 1023)]!; // exact: m in [1, 2)\n if (m > SQRT2) { m *= 0.5; e += 1; }\n // s = f/(2 + f) with f = m − 1 (exact), as sHi + sLo: 2 + f = dh + dl exactly (FastTwoSum), then the residual\n // f − sHi·(dh + dl) with sHi·dh = p + pe exactly (TwoProduct).\n const f = m - 1, dh = 2 + f, dl = f - (dh - 2), sHi = f / dh, p = sHi * dh;\n let c = SPLITTER * sHi;\n const ah = c - (c - sHi), al = sHi - ah;\n c = SPLITTER * dh;\n const bh = c - (c - dh), bl = dh - bh, pe = ((ah * bh - p) + ah * bl + al * bh) + al * bl;\n const sLo = (((f - p) - pe) - sHi * dl) / dh;\n const z = sHi * sHi;\n const tail = sHi * z * (0.6666666666666666 + z * (0.4 + z * (0.2857142857142857 + z * (0.2222222222222222 + z * (0.18181818181818182 + z * (0.15384615384615385 +\n z * (0.13333333333333333 + z * (0.11764705882352941 + z * (0.10526315789473684 + z * (0.09523809523809523 + z * 0.08695652173913043))))))))));\n // ln m = 2sHi + (2sLo + tail) = lh + ll (FastTwoSum); times log2 e = LOG2E_HI + LOG2E_LO (TwoProduct of the high parts); plus e (TwoSum).\n const a1 = 2 * sHi, b1 = 2 * sLo + tail, lh = a1 + b1, ll = b1 - (lh - a1), q = lh * LOG2E_HI;\n c = SPLITTER * lh;\n const ch = c - (c - lh), cl = lh - ch, qe = ((ch * LOG2E_HI_H - q) + ch * LOG2E_HI_L + cl * LOG2E_HI_H) + cl * LOG2E_HI_L;\n const pl = qe + (lh * LOG2E_LO + ll * LOG2E_HI);\n const t = e + q, tb = t - e, te = (e - (t - tb)) + (q - tb), b2 = te + pl, hi = t + b2;\n LOW_PART[0] = b2 - (hi - t);\n return hi;\n}\n/** log2(k/128) for k = 90 … 182 (the table's range of k = round(128·m), m in [√½, √2]) as double-doubles. */\nconst LOG2_TABLE_LO = /* @__PURE__ */ new Float64Array(183);\nconst LOG2_TABLE_HI = /* @__PURE__ */ ((): Float64Array => {\n const table = new Float64Array(183);\n for (let k = 90; k <= 182; k++) { table[k] = log2SeriesDoubleDouble(k / 128); LOG2_TABLE_LO[k] = LOW_PART[0]!; }\n return table;\n})();\n/**\n * log2 x as a double-double for finite x > 0: returns the high part, the low part in LOW_PART[0]. x = m·2^e with m in\n * [√½, √2]; m = F·(1 + f/F) with F = k/128, k = round(128·m), so log2 m = log2 F (table) + 2·atanh(s)·log2 e with\n * s = f/(m + F), |s| < 2^-8.4, by its series to s⁷ (truncation below 2^-70 relative). Relative error below 2^-56.\n */\nfunction log2DoubleDouble(x: number): number {\n let e = 0;\n if (x < MIN_NORMAL) { x *= TWO_POW_54; e = -54; }\n BITS[0] = x;\n const high = WORDS[HIGH]!;\n e += (high >>> 20) - 1023;\n let m = x * POW2[1074 - ((high >>> 20) - 1023)]!; // exact: m in [1, 2)\n if (m > SQRT2) { m *= 0.5; e += 1; }\n // F = k/128 (exact) and f = m − F (exact, F/2 ≤ m ≤ 2F); m + F = dh + dl exactly (TwoSum); s = f/(dh + dl) as sHi + sLo\n // from the residual f − sHi·(dh + dl), with sHi·dh = p + pe exactly (TwoProduct).\n const k = Math.round(m * 128), F = k / 128, f = m - F, dh = m + F, db = dh - m, dl = (m - (dh - db)) + (F - db);\n const sHi = f / dh, p = sHi * dh;\n let c = SPLITTER * sHi;\n const ah = c - (c - sHi), al = sHi - ah;\n c = SPLITTER * dh;\n const bh = c - (c - dh), bl = dh - bh, pe = ((ah * bh - p) + ah * bl + al * bh) + al * bl;\n const sLo = (((f - p) - pe) - sHi * dl) / dh, z = sHi * sHi;\n const tail = sHi * z * (0.6666666666666666 + z * (0.4 + z * 0.2857142857142857));\n // ln(m/F) = 2sHi + (2sLo + tail) = lh + ll (FastTwoSum); times log2 e = LOG2E_HI + LOG2E_LO (TwoProduct of the high\n // parts); plus log2 F (TwoSum with the table's high part), then plus e (TwoSum).\n const a1 = 2 * sHi, b1 = 2 * sLo + tail, lh = a1 + b1, ll = b1 - (lh - a1), q = lh * LOG2E_HI;\n c = SPLITTER * lh;\n const ch = c - (c - lh), cl = lh - ch, qe = ((ch * LOG2E_HI_H - q) + ch * LOG2E_HI_L + cl * LOG2E_HI_H) + cl * LOG2E_HI_L;\n const pl = qe + (lh * LOG2E_LO + ll * LOG2E_HI), th = LOG2_TABLE_HI[k]!;\n const t = th + q, tb = t - th, low = ((th - (t - tb)) + (q - tb)) + (pl + LOG2_TABLE_LO[k]!);\n const u = e + t, ub = u - e, b2 = ((e - (u - ub)) + (t - ub)) + low, hi = u + b2;\n LOW_PART[0] = b2 - (hi - u);\n return hi;\n}\n/** 2^(th + tl) for a double-double exponent; within 1 ulp (plus the error the exponent carries). */\nfunction exp2DoubleDouble(th: number, tl: number): number {\n if (th !== th) return NaN;\n if (th > 1024) return Infinity;\n if (th < -1080) return 0;\n // th = n + r exactly (|r| ≤ ½); w = r·ln 2 = wh + wl (TwoProduct with LN2_HI, plus r·LN2_LO).\n const n = Math.round(th), r = (th - n) + tl, wh = r * LN2_HI, c = SPLITTER * r, ah = c - (c - r), al = r - ah;\n const wl = (((ah * LN2_HI_H - wh) + ah * LN2_HI_L + al * LN2_HI_H) + al * LN2_HI_L) + r * LN2_LO;\n const q = 0.5 + wh * (0.16666666666666666 + wh * (0.041666666666666664 + wh * (0.008333333333333333 + wh * (0.001388888888888889 + wh * (0.0001984126984126984 +\n wh * (2.48015873015873e-05 + wh * (2.7557319223985893e-06 + wh * (2.755731922398589e-07 + wh * (2.505210838544172e-08 + wh * (2.08767569878681e-09 +\n wh * (1.6059043836821613e-10 + wh * 1.1470745597729725e-11)))))))))));\n return scaleByPowerOfTwo(1 + (wh + (wl + wh * wh * q)), n);\n}\n\n/** log2 x, bit-identical in every JavaScript engine (within 1 ulp). 0 → −∞; negative or NaN → NaN; +∞ → +∞. */\nexport function portableLog2(x: number): number {\n if (!(x > 0)) return x === 0 ? -Infinity : NaN;\n if (x === Infinity) return Infinity;\n const h = log2DoubleDouble(x);\n return h + LOW_PART[0]!;\n}\n/** ln(k/128) for k = 90 … 182 as double-doubles (log2(k/128)·ln 2, TwoProduct with LN2_HI plus the small products). */\nconst LN_TABLE_LO = /* @__PURE__ */ new Float64Array(183);\nconst LN_TABLE_HI = /* @__PURE__ */ ((): Float64Array => {\n const table = new Float64Array(183);\n for (let k = 90; k <= 182; k++) {\n const h = LOG2_TABLE_HI[k]!, l = LOG2_TABLE_LO[k]!, p = h * LN2_HI, c = SPLITTER * h, ah = c - (c - h), al = h - ah;\n const pe = ((ah * LN2_HI_H - p) + ah * LN2_HI_L + al * LN2_HI_H) + al * LN2_HI_L, lo = pe + (h * LN2_LO + l * LN2_HI), hi = p + lo;\n table[k] = hi; LN_TABLE_LO[k] = lo - (hi - p);\n }\n return table;\n})();\n/** ln 2 = LN2_E_HI + LN2_E_LO with the low 32 bits of LN2_E_HI zero, so e·LN2_E_HI is exact for every exponent e here. */\nconst LN2_E_HI = /* @__PURE__ */ ((): number => { BITS[0] = LN2_HI; WORDS[LOW] = 0; return BITS[0]!; })(), LN2_E_LO = (LN2_HI - LN2_E_HI) + LN2_LO;\n/**\n * Natural logarithm, bit-identical in every JavaScript engine (within 1 ulp). 0 → −∞; negative or NaN → NaN; +∞ → +∞.\n * x = m·2^e, m in [√½, √2]; ln x = e·ln 2 + ln F (table, F = k/128, k = round(128·m)) + 2·atanh(s), s = (m − F)/(m + F),\n * with s as a double-double and the three terms added with TwoSum.\n */\nexport function portableLog(x: number): number {\n if (!(x > 0)) return x === 0 ? -Infinity : NaN;\n if (x === Infinity) return Infinity;\n let e = 0;\n if (x < MIN_NORMAL) { x *= TWO_POW_54; e = -54; }\n BITS[0] = x;\n const high = WORDS[HIGH]!;\n e += (high >>> 20) - 1023;\n let m = x * POW2[1074 - ((high >>> 20) - 1023)]!; // exact: m in [1, 2)\n if (m > SQRT2) { m *= 0.5; e += 1; }\n const k = Math.round(m * 128), F = k / 128, f = m - F, dh = m + F, db = dh - m, dl = (m - (dh - db)) + (F - db);\n const sHi = f / dh, p = sHi * dh;\n let c = SPLITTER * sHi;\n const ah = c - (c - sHi), al = sHi - ah;\n c = SPLITTER * dh;\n const bh = c - (c - dh), bl = dh - bh, pe = ((ah * bh - p) + ah * bl + al * bh) + al * bl;\n const sLo = (((f - p) - pe) - sHi * dl) / dh, z = sHi * sHi;\n const tail = sHi * z * (0.6666666666666666 + z * (0.4 + z * 0.2857142857142857));\n // (e·LN2_E_HI + ln F) + 2sHi with TwoSum errors, then the low parts.\n const A = e * LN2_E_HI, B = LN_TABLE_HI[k]!, t = A + B, tb = t - A, te = (A - (t - tb)) + (B - tb);\n const a2 = 2 * sHi, u = t + a2, ub = u - t, ue = (t - (u - ub)) + (a2 - ub);\n return u + ((te + ue) + ((e * LN2_E_LO + LN_TABLE_LO[k]!) + (2 * sLo + tail)));\n}\n/** 2^x, bit-identical in every JavaScript engine (within 1 ulp). */\nexport function portableExp2(x: number): number { return exp2DoubleDouble(x, 0); }\n/** e^x, bit-identical in every JavaScript engine (within 1 ulp). */\nexport function portableExp(x: number): number {\n if (x !== x) return NaN;\n if (x > 710) return Infinity;\n if (x < -746) return 0;\n // x·log2 e = th + tl: x·LOG2E_HI = th + te exactly (TwoProduct), plus x·LOG2E_LO.\n const th = x * LOG2E_HI, c = SPLITTER * x, ah = c - (c - x), al = x - ah;\n const te = ((ah * LOG2E_HI_H - th) + ah * LOG2E_HI_L + al * LOG2E_HI_H) + al * LOG2E_HI_L;\n return exp2DoubleDouble(th, te + x * LOG2E_LO);\n}\n/**\n * e^x − 1, bit-identical in every JavaScript engine (within 2 ulps): the Taylor series to degree 20 for |x| < 1\n * (truncation below 2^-60 relative), else portableExp(x) − 1.\n */\nexport function portableExpm1(x: number): number {\n if (x !== x) return NaN;\n if (x === 0) return x;\n if (!(x > -1 && x < 1)) return portableExp(x) - 1;\n return x + x * x * (0.5 + x * (0.16666666666666666 + x * (0.041666666666666664 + x * (0.008333333333333333 + x * (0.001388888888888889 + x * (0.0001984126984126984 +\n x * (2.48015873015873e-05 + x * (2.7557319223985893e-06 + x * (2.755731922398589e-07 + x * (2.505210838544172e-08 + x * (2.08767569878681e-09 +\n x * (1.6059043836821613e-10 + x * (1.1470745597729725e-11 + x * (7.647163731819816e-13 + x * (4.779477332387385e-14 + x * (2.8114572543455206e-15 +\n x * (1.5619206968586225e-16 + x * (8.22063524662433e-18 + x * 4.110317623312165e-19))))))))))))))))));\n}\n/**\n * x^y for x ≥ 0 and finite y, bit-identical in every JavaScript engine (within 1 ulp for |y| ≤ 4). x = 0 gives 0 for\n * y > 0, 1 for y = 0 and +∞ for y < 0; negative x or a non-finite argument gives NaN (the callers never pass them).\n */\nexport function portablePow(x: number, y: number): number {\n if (!(x >= 0) || !Number.isFinite(x) || !Number.isFinite(y)) return NaN;\n if (y === 0 || x === 1) return 1;\n if (x === 0) return y > 0 ? 0 : Infinity;\n // y·(lh + ll): lh·y = p + pe exactly (TwoProduct), then FastTwoSum(p, pe + ll·y).\n const lh = log2DoubleDouble(x), ll = LOW_PART[0]!, p = lh * y;\n let c = SPLITTER * lh;\n const ah = c - (c - lh), al = lh - ah;\n c = SPLITTER * y;\n const bh = c - (c - y), bl = y - bh, pe = ((ah * bh - p) + ah * bl + al * bh) + al * bl;\n const b = pe + ll * y, th = p + b;\n return exp2DoubleDouble(th, b - (th - p));\n}\n/** ∛(2^r) for r = 0, 1, 2 (only scale the cube root's starting value, so their last bits do not matter). */\nconst CBRT_POWERS_OF_TWO = [1, 1.2599210498948732, 1.5874010519681994];\n/**\n * Cube root, bit-identical in every JavaScript engine (within 1 ulp; exact for ±0, ±∞ and cubes of powers of two).\n * |x| = m·2^(3q + r) with m in [1, 2) and r in {0, 1, 2}, w = m·2^r: a cubic fit to ∛m (within 1.7·10⁻⁴) times ∛(2^r),\n * one Halley step y ← y(y³ + 2w)/(2y³ + w) (cubic convergence: below 10⁻¹¹), then one Newton step y + (w − y³)/(3y²)\n * with w − y³ formed exactly (TwoProduct), which leaves only the final rounding and errors near 10⁻²².\n */\nexport function portableCbrt(x: number): number {\n if (x === 0 || x !== x || !Number.isFinite(x)) return x;\n let a = x < 0 ? -x : x, shift = 0;\n if (a < MIN_NORMAL) { a *= TWO_POW_54; shift = -18; }\n BITS[0] = a;\n const high = WORDS[HIGH]!, e = (high >>> 20) - 1023, q = Math.floor(e / 3), r = e - 3 * q;\n const m = a * POW2[1074 - e]!, w = m * CBRT_SCALE[r]!; // exact: m in [1, 2)\n let y = (0.5561432746078446 + m * (0.5806821751356804 + m * (-0.15894786280039686 + m * 0.022291567104952514))) * CBRT_POWERS_OF_TWO[r]!;\n const y3 = y * y * y;\n y = y * (y3 + 2 * w) / (2 * y3 + w);\n // y² = p + pe exactly; y³ = p·y + pe·y = t + te (TwoProduct of p and y, plus pe·y); w − y³ = (w − t) − te.\n const p = y * y;\n let c = SPLITTER * y;\n const yh = c - (c - y), yl = y - yh, pe = ((yh * yh - p) + yh * yl + yl * yh) + yl * yl, t = p * y;\n c = SPLITTER * p;\n const ph = c - (c - p), pll = p - ph, te = (((ph * yh - t) + ph * yl + pll * yh) + pll * yl) + pe * y;\n const root = scaleByPowerOfTwo(y + ((w - t) - te) / (3 * p), q + shift);\n return x < 0 ? -root : root;\n}\n/** 2^r for r = 0, 1, 2. */\nconst CBRT_SCALE = [1, 2, 4];\n/** cos(2πr) and sin(2πr) for |r| ≤ ⅛ (Taylor series in z = r²). */\nfunction cosTwoPiReduced(r: number): number {\n const z = r * r;\n return 1 + z * (-19.739208802178716 + z * (64.9393940226683 + z * (-85.45681720669373 + z * (60.24464137187666 + z * (-26.4262567833744 + z * (7.903536371318469 +\n z * (-1.714390711088672 + z * (0.28200596845579123 + z * -0.03638284114254567))))))));\n}\nfunction sinTwoPiReduced(r: number): number {\n const z = r * r;\n return r * (6.283185307179586 + z * (-41.34170224039976 + z * (81.60524927607506 + z * (-76.70585975306139 + z * (42.058693944897655 + z * (-15.09464257682299 +\n z * (3.819952584848282 + z * (-0.7181223017785006 + z * (0.10422916220813984 + z * -0.012031585942120627)))))))));\n}\n/** cos(2πu) for finite u (u in turns), bit-identical in every JavaScript engine (within 2 ulps). */\nexport function portableCosTwoPi(u: number): number {\n if (!Number.isFinite(u)) return NaN;\n const t = 4 * u, q = Math.round(t), r = (t - q) / 4, quadrant = ((q % 4) + 4) % 4;\n return quadrant === 0 ? cosTwoPiReduced(r) : quadrant === 1 ? -sinTwoPiReduced(r) : quadrant === 2 ? -cosTwoPiReduced(r) : sinTwoPiReduced(r);\n}\n/** sin(2πu) for finite u (u in turns), bit-identical in every JavaScript engine (within 2 ulps). */\nexport function portableSinTwoPi(u: number): number {\n if (!Number.isFinite(u)) return NaN;\n const t = 4 * u, q = Math.round(t), r = (t - q) / 4, quadrant = ((q % 4) + 4) % 4;\n return quadrant === 0 ? sinTwoPiReduced(r) : quadrant === 1 ? cosTwoPiReduced(r) : quadrant === 2 ? -sinTwoPiReduced(r) : -cosTwoPiReduced(r);\n}\n"]}
@@ -6,4 +6,4 @@
6
6
  * own versions. Release checks confirm it matches package.json and the packed package.
7
7
  * @see docs/RELEASE_1_0_1.md
8
8
  */
9
- export declare const ENGINE_API_VERSION: "2.5.0";
9
+ export declare const ENGINE_API_VERSION: "2.7.0";
@@ -7,5 +7,5 @@
7
7
  * own versions. Release checks confirm it matches package.json and the packed package.
8
8
  * @see docs/RELEASE_1_0_1.md
9
9
  */
10
- export const ENGINE_API_VERSION = "2.5.0";
10
+ export const ENGINE_API_VERSION = "2.7.0";
11
11
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/core/version.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,OAAgB,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Version of the engine release. Since 1.0.1 it equals the npm package version.\n *\n * New captures and plans record this version as their creator. Archived records keep the\n * version they were made with. Proof-of-concept (POC), schema and model contracts have their\n * own versions. Release checks confirm it matches package.json and the packed package.\n * @see docs/RELEASE_1_0_1.md\n */\nexport const ENGINE_API_VERSION = \"2.5.0\" as const;\n"]}
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/core/version.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,OAAgB,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Version of the engine release. Since 1.0.1 it equals the npm package version.\n *\n * New captures and plans record this version as their creator. Archived records keep the\n * version they were made with. Proof-of-concept (POC), schema and model contracts have their\n * own versions. Release checks confirm it matches package.json and the packed package.\n * @see docs/RELEASE_1_0_1.md\n */\nexport const ENGINE_API_VERSION = \"2.7.0\" as const;\n"]}
@@ -19,7 +19,7 @@ import { InvalidConfigurationError } from "../core/configuration-error.js";
19
19
  import { requireAllowlistedRecord } from "../core/record-validation.js";
20
20
  import { FULL_RESOLUTION_CEILING_PIXELS, resolveRaisedLimit } from "../core/pixel-limits.js";
21
21
  import { resolveChartScene } from "./chart-scenes.js";
22
- import { buildPlanarSceneRadianceProvider, calculateIlluminantIrradianceScale, resolveCaptureIlluminant } from "./scene-radiance.js";
22
+ import { buildPlanarSceneRadianceProvider, calculateIlluminantIrradianceScale, resolveCaptureIlluminant, tabulatedSpectrum } from "./scene-radiance.js";
23
23
  export const CHART_RADIANCE_BATCH_SCHEMA_VERSION = "0.1.0";
24
24
  /** `maximumQueries` is the default batch limit; a request may raise it with its own `maximumQueries`, up to `ceilingQueries`. */
25
25
  export const CHART_RADIANCE_BATCH_LIMITS = Object.freeze({ maximumQueries: 24_000_000, ceilingQueries: FULL_RESOLUTION_CEILING_PIXELS, maximumWavelengths: 256,
@@ -67,12 +67,13 @@ export function calculateChartRadianceBatchPlan(input) {
67
67
  irradianceScale, geometry: { distanceM: 1, metresPerFrameUnit: 1 }, evidence: [], limitations: [] });
68
68
  const channelWeights = weights === undefined ? null : weights.map(row => Object.freeze([...row]));
69
69
  const nm = Object.freeze([...wavelengths]);
70
+ const shapeAt = tabulatedSpectrum(illuminant.shape);
70
71
  const materialRadiance = (material, wavelength) => {
71
72
  const m = chart.materials[material];
72
73
  const reflectance = m.kind === "neutral" ? m.reflectance : m.spectrum.evaluate(wavelength);
73
74
  if (m.kind === "spectrum" && !(reflectance >= 0 && reflectance <= 1))
74
75
  throw new InvalidConfigurationError("Chart reflectance spectrum left [0, 1].");
75
- return reflectance * irradianceScale * illuminant.shape.evaluate(wavelength) / Math.PI;
76
+ return reflectance * irradianceScale * shapeAt(wavelength) / Math.PI;
76
77
  };
77
78
  return Object.freeze({ chart, illuminant, irradianceScale, queryCount, columns: channelWeights === null ? 1 : channelWeights.length,
78
79
  mode: channelWeights === null ? "radiance" : "spectral-integral", wavelengthsNanometers: nm, channelWeights, materialRadiance,
@@ -1 +1 @@
1
- {"version":3,"file":"chart-radiance-batch.js","sourceRoot":"","sources":["../../src/facade/chart-radiance-batch.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Batched radiance queries for the engine's procedural chart scenes (#277): many frame points in one\n * call, each answered with spectral radiance at a declared wavelength, or with the spectral integral of\n * that radiance against declared channel weights. This is the float64 CPU reference for the\n * `webgpu-f32` chart-radiance stage (`ImageKernelAccelerator.evaluateChartRadiance`).\n *\n * Every value comes from the chart provider's own `radianceAt` (createPlanarSceneRadianceProvider): a\n * Lambertian reflectance ρ(λ) under the scaled illuminant, L = ρ·k·S(λ)/π. The spectral integral of a\n * query is Σ_j w_cj·L(u, v, λ_j), summed in wavelength order. Charts are uniform-illuminant Lambertian\n * patterns, so a query's integral depends only on its material: the GPU stage uses exactly that.\n *\n * The query shape mirrors a batched provider (one call, queries in, results in the same order). Points\n * are frame units (u right, v up; see chart-scenes.ts); `mapEnvironmentDirectionsToChartPoints` converts\n * environment-direction queries exactly as `evaluateRadiance` does.\n * @see docs/WEBGPU.md, \"Scene radiance on the GPU\".\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { requireAllowlistedRecord } from \"../core/record-validation.js\";\nimport { FULL_RESOLUTION_CEILING_PIXELS, resolveRaisedLimit } from \"../core/pixel-limits.js\";\nimport { resolveChartScene, type ChartScene, type ResolvedChartScene } from \"./chart-scenes.js\";\nimport { buildPlanarSceneRadianceProvider, calculateIlluminantIrradianceScale, resolveCaptureIlluminant, type CaptureIlluminant,\n type ResolvedCaptureIlluminant } from \"./scene-radiance.js\";\n\nexport const CHART_RADIANCE_BATCH_SCHEMA_VERSION = \"0.1.0\" as const;\n/** `maximumQueries` is the default batch limit; a request may raise it with its own `maximumQueries`, up to `ceilingQueries`. */\nexport const CHART_RADIANCE_BATCH_LIMITS = Object.freeze({ maximumQueries: 24_000_000, ceilingQueries: FULL_RESOLUTION_CEILING_PIXELS, maximumWavelengths: 256,\n maximumChannels: 4 });\n\nexport interface ChartRadianceBatchInput {\n schemaVersion: typeof CHART_RADIANCE_BATCH_SCHEMA_VERSION;\n /** An engine chart preset (caller scene functions are not supported here). */\n scene: ChartScene;\n illuminant: CaptureIlluminant;\n illuminanceLux: number;\n /** Frame height / width. */\n aspect: number;\n /** Frame points, interleaved [u0, v0, u1, v1, …]. Finite. */\n points: Float32Array | Float64Array;\n /** The wavelengths the queries use, in nanometres (1–256). */\n wavelengthsNanometers: readonly number[];\n /** Radiance queries: one wavelength index per point. Exactly one of this and `channelWeights`. */\n wavelengthIndices?: Uint8Array | Uint16Array;\n /** Spectral integration: per channel (1–4), one finite weight per wavelength. */\n channelWeights?: readonly (readonly number[])[];\n /**\n * Optional opt-in batch limit: an integer from 1 to `CHART_RADIANCE_BATCH_LIMITS.ceilingQueries`. Default\n * `CHART_RADIANCE_BATCH_LIMITS.maximumQueries` (24 000 000). It does not change the values.\n */\n maximumQueries?: number;\n}\n\n/** Validated plan with the resolved chart, illuminant and irradiance scale. Arrays are borrowed. */\nexport interface ChartRadianceBatchPlan {\n chart: ResolvedChartScene;\n illuminant: ResolvedCaptureIlluminant;\n irradianceScale: number;\n queryCount: number;\n /** Output values per query: 1 for radiance queries, the channel count for spectral integration. */\n columns: number;\n mode: \"radiance\" | \"spectral-integral\";\n wavelengthsNanometers: readonly number[];\n channelWeights: readonly (readonly number[])[] | null;\n /** Spectral radiance of one material at a wavelength: the provider's own radianceAt for that material. */\n materialRadiance(material: number, wavelengthNanometers: number): number;\n /** The reference value of one query and output column (radianceAt, and its wavelength-ordered sum). */\n queryValue(points: Float32Array | Float64Array, wavelengthIndices: Uint8Array | Uint16Array | undefined, query: number, column: number): number;\n}\n\nexport function calculateChartRadianceBatchPlan(input: ChartRadianceBatchInput): ChartRadianceBatchPlan {\n const r = requireAllowlistedRecord(input, [\"schemaVersion\", \"scene\", \"illuminant\", \"illuminanceLux\", \"aspect\", \"points\", \"wavelengthsNanometers\",\n \"wavelengthIndices\", \"channelWeights\", \"maximumQueries\"], \"Invalid chart radiance batch input.\");\n if (r.schemaVersion !== CHART_RADIANCE_BATCH_SCHEMA_VERSION) throw new InvalidConfigurationError(\"Unsupported chart radiance batch schema.\");\n if (typeof r.aspect !== \"number\" || !(r.aspect > 0 && r.aspect <= Number.MAX_VALUE)) throw new InvalidConfigurationError(\"aspect must be positive.\");\n const chart = resolveChartScene({ scene: r.scene as ChartScene, aspect: r.aspect });\n const illuminant = resolveCaptureIlluminant(r.illuminant as CaptureIlluminant);\n const irradianceScale = calculateIlluminantIrradianceScale(illuminant.shape, r.illuminanceLux as number);\n const L = CHART_RADIANCE_BATCH_LIMITS, points = r.points;\n const maximumQueries = resolveRaisedLimit(r.maximumQueries, L.maximumQueries, L.ceilingQueries,\n \"Chart radiance batch maximumQueries must be an integer from 1 to \" + L.ceilingQueries + \".\");\n if (!(points instanceof Float32Array || points instanceof Float64Array) || points.length % 2 !== 0 || points.length / 2 > maximumQueries) {\n throw new InvalidConfigurationError(\"points must be an interleaved Float32Array or Float64Array of (u, v) pairs.\");\n }\n for (let i = 0; i < points.length; i++) if (!Number.isFinite(points[i]!)) throw new InvalidConfigurationError(\"Chart points must be finite.\");\n const queryCount = points.length / 2, wavelengths = r.wavelengthsNanometers;\n if (!Array.isArray(wavelengths) || wavelengths.length < 1 || wavelengths.length > L.maximumWavelengths ||\n wavelengths.some(nm => typeof nm !== \"number\" || !Number.isFinite(nm) || nm <= 0)) {\n throw new InvalidConfigurationError(\"wavelengthsNanometers must list 1 to 256 positive wavelengths.\");\n }\n const indices = r.wavelengthIndices, weights = r.channelWeights;\n if ((indices === undefined) === (weights === undefined)) throw new InvalidConfigurationError(\"Give exactly one of wavelengthIndices and channelWeights.\");\n if (indices !== undefined) {\n if (!(indices instanceof Uint8Array || indices instanceof Uint16Array) || indices.length !== queryCount) {\n throw new InvalidConfigurationError(\"wavelengthIndices must hold one index per point.\");\n }\n for (let i = 0; i < queryCount; i++) if (indices[i]! >= wavelengths.length) throw new InvalidConfigurationError(\"A wavelength index is out of range.\");\n } else if (!Array.isArray(weights) || weights.length < 1 || weights.length > L.maximumChannels ||\n weights.some(row => !Array.isArray(row) || row.length !== wavelengths.length || row.some(w => typeof w !== \"number\" || !Number.isFinite(w)))) {\n throw new InvalidConfigurationError(\"channelWeights must hold 1 to 4 rows of one finite weight per wavelength.\");\n }\n // The provider's own radiance function: chart reflectance × scaled illuminant / π, in its float64 order.\n const provider = buildPlanarSceneRadianceProvider({ scene: chart, sceneId: \"chart-radiance-batch\", providerProfileId: \"chart-radiance-batch\", illuminant,\n irradianceScale, geometry: { distanceM: 1, metresPerFrameUnit: 1 }, evidence: [], limitations: [] });\n const channelWeights = weights === undefined ? null : (weights as number[][]).map(row => Object.freeze([...row]));\n const nm = Object.freeze([...(wavelengths as number[])]);\n const materialRadiance = (material: number, wavelength: number): number => {\n const m = chart.materials[material]!;\n const reflectance = m.kind === \"neutral\" ? m.reflectance : m.spectrum.evaluate(wavelength);\n if (m.kind === \"spectrum\" && !(reflectance >= 0 && reflectance <= 1)) throw new InvalidConfigurationError(\"Chart reflectance spectrum left [0, 1].\");\n return reflectance * irradianceScale * illuminant.shape.evaluate(wavelength) / Math.PI;\n };\n return Object.freeze({ chart, illuminant, irradianceScale, queryCount, columns: channelWeights === null ? 1 : channelWeights.length,\n mode: channelWeights === null ? \"radiance\" as const : \"spectral-integral\" as const, wavelengthsNanometers: nm, channelWeights, materialRadiance,\n queryValue(p: Float32Array | Float64Array, w: Uint8Array | Uint16Array | undefined, query: number, column: number): number {\n const u = p[2 * query]!, v = p[2 * query + 1]!;\n if (channelWeights === null) return provider.radianceAt(u, v, nm[w![query]!]!);\n let sum = 0;\n const row = channelWeights[column]!;\n for (let j = 0; j < nm.length; j++) sum += row[j]! * provider.radianceAt(u, v, nm[j]!);\n return sum;\n } });\n}\n\n/** Float64 CPU reference: every query's value(s), row-major (query, column). */\nexport function calculateChartRadianceBatch(input: ChartRadianceBatchInput): { plan: ChartRadianceBatchPlan; values: Float64Array } {\n const plan = calculateChartRadianceBatchPlan(input), values = new Float64Array(plan.queryCount * plan.columns);\n for (let q = 0; q < plan.queryCount; q++) for (let c = 0; c < plan.columns; c++) values[q * plan.columns + c] = plan.queryValue(input.points, input.wavelengthIndices, q, c);\n return { plan, values };\n}\n\n/**\n * Frame points of environment-direction queries on the chart plane, exactly as the planar provider's\n * `evaluateRadiance` computes them: look direction l = −o, plane point l·distance/l.z, in frame units.\n * @param directions - Outgoing unit vectors (scene toward camera), interleaved [x, y, z, …].\n */\nexport function mapEnvironmentDirectionsToChartPoints(input: { directions: Float32Array | Float64Array; distanceM: number; metresPerFrameUnit: number }): Float64Array {\n const r = requireAllowlistedRecord(input, [\"directions\", \"distanceM\", \"metresPerFrameUnit\"], \"Invalid planar direction input.\");\n const d = r.directions, distance = r.distanceM, scale = r.metresPerFrameUnit;\n if (!(d instanceof Float32Array || d instanceof Float64Array) || d.length % 3 !== 0 || typeof distance !== \"number\" || !(distance > 0 && distance <= Number.MAX_VALUE) ||\n typeof scale !== \"number\" || !(scale > 0 && scale <= Number.MAX_VALUE)) {\n throw new InvalidConfigurationError(\"Planar directions need interleaved unit vectors, a positive distance and a positive frame scale.\");\n }\n const points = new Float64Array(d.length / 3 * 2);\n for (let i = 0; i < d.length / 3; i++) {\n const lz = -d[3 * i + 2]!;\n if (!(lz > 0)) throw new InvalidConfigurationError(\"Planar scene query does not point toward the scene plane.\");\n const t = distance / lz;\n const x = -d[3 * i]! * t / scale, y = -d[3 * i + 1]! * t / scale;\n // A grazing direction (lz near 0, e.g. 1e-320) or a non-finite component would give ±Infinity or NaN.\n if (!Number.isFinite(x) || !Number.isFinite(y)) throw new InvalidConfigurationError(\"Planar scene query maps to a non-finite chart point (grazing or non-finite direction).\");\n points[2 * i] = x;\n points[2 * i + 1] = y;\n }\n return points;\n}\n"]}
1
+ {"version":3,"file":"chart-radiance-batch.js","sourceRoot":"","sources":["../../src/facade/chart-radiance-batch.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EAAE,8BAA8B,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7F,OAAO,EAAE,iBAAiB,EAA4C,MAAM,mBAAmB,CAAC;AAChG,OAAO,EAAE,gCAAgC,EAAE,kCAAkC,EAAE,wBAAwB,EAAE,iBAAiB,EACxF,MAAM,qBAAqB,CAAC;AAE9D,MAAM,CAAC,MAAM,mCAAmC,GAAG,OAAgB,CAAC;AACpE,iIAAiI;AACjI,MAAM,CAAC,MAAM,2BAA2B,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,cAAc,EAAE,UAAU,EAAE,cAAc,EAAE,8BAA8B,EAAE,kBAAkB,EAAE,GAAG;IAC5J,eAAe,EAAE,CAAC,EAAE,CAAC,CAAC;AA0CxB,MAAM,UAAU,+BAA+B,CAAC,KAA8B;IAC5E,MAAM,CAAC,GAAG,wBAAwB,CAAC,KAAK,EAAE,CAAC,eAAe,EAAE,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,QAAQ,EAAE,QAAQ,EAAE,uBAAuB;QAC9I,mBAAmB,EAAE,gBAAgB,EAAE,gBAAgB,CAAC,EAAE,qCAAqC,CAAC,CAAC;IACnG,IAAI,CAAC,CAAC,aAAa,KAAK,mCAAmC;QAAE,MAAM,IAAI,yBAAyB,CAAC,0CAA0C,CAAC,CAAC;IAC7I,IAAI,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,IAAI,MAAM,CAAC,SAAS,CAAC;QAAE,MAAM,IAAI,yBAAyB,CAAC,0BAA0B,CAAC,CAAC;IACrJ,MAAM,KAAK,GAAG,iBAAiB,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAmB,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IACpF,MAAM,UAAU,GAAG,wBAAwB,CAAC,CAAC,CAAC,UAA+B,CAAC,CAAC;IAC/E,MAAM,eAAe,GAAG,kCAAkC,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,cAAwB,CAAC,CAAC;IACzG,MAAM,CAAC,GAAG,2BAA2B,EAAE,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;IACzD,MAAM,cAAc,GAAG,kBAAkB,CAAC,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC,cAAc,EAC5F,mEAAmE,GAAG,CAAC,CAAC,cAAc,GAAG,GAAG,CAAC,CAAC;IAChG,IAAI,CAAC,CAAC,MAAM,YAAY,YAAY,IAAI,MAAM,YAAY,YAAY,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,GAAG,cAAc,EAAE,CAAC;QACzI,MAAM,IAAI,yBAAyB,CAAC,6EAA6E,CAAC,CAAC;IACrH,CAAC;IACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC;YAAE,MAAM,IAAI,yBAAyB,CAAC,8BAA8B,CAAC,CAAC;IAC9I,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,WAAW,GAAG,CAAC,CAAC,qBAAqB,CAAC;IAC5E,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,kBAAkB;QAClG,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC;QACtF,MAAM,IAAI,yBAAyB,CAAC,gEAAgE,CAAC,CAAC;IACxG,CAAC;IACD,MAAM,OAAO,GAAG,CAAC,CAAC,iBAAiB,EAAE,OAAO,GAAG,CAAC,CAAC,cAAc,CAAC;IAChE,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC;QAAE,MAAM,IAAI,yBAAyB,CAAC,2DAA2D,CAAC,CAAC;IAC1J,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,IAAI,CAAC,CAAC,OAAO,YAAY,UAAU,IAAI,OAAO,YAAY,WAAW,CAAC,IAAI,OAAO,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YACxG,MAAM,IAAI,yBAAyB,CAAC,kDAAkD,CAAC,CAAC;QAC1F,CAAC;QACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE;YAAE,IAAI,OAAO,CAAC,CAAC,CAAE,IAAI,WAAW,CAAC,MAAM;gBAAE,MAAM,IAAI,yBAAyB,CAAC,qCAAqC,CAAC,CAAC;IACzJ,CAAC;SAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,eAAe;QAC1F,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM,KAAK,WAAW,CAAC,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACjJ,MAAM,IAAI,yBAAyB,CAAC,2EAA2E,CAAC,CAAC;IACnH,CAAC;IACD,yGAAyG;IACzG,MAAM,QAAQ,GAAG,gCAAgC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,UAAU;QACtJ,eAAe,EAAE,QAAQ,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,kBAAkB,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC;IACvG,MAAM,cAAc,GAAG,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAE,OAAsB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IAClH,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAI,WAAwB,CAAC,CAAC,CAAC;IACzD,MAAM,OAAO,GAAG,iBAAiB,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IACpD,MAAM,gBAAgB,GAAG,CAAC,QAAgB,EAAE,UAAkB,EAAU,EAAE;QACxE,MAAM,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAE,CAAC;QACrC,MAAM,WAAW,GAAG,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QAC3F,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,CAAC,WAAW,IAAI,CAAC,IAAI,WAAW,IAAI,CAAC,CAAC;YAAE,MAAM,IAAI,yBAAyB,CAAC,yCAAyC,CAAC,CAAC;QACrJ,OAAO,WAAW,GAAG,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC;IACvE,CAAC,CAAC;IACF,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,EAAE,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,MAAM;QACjI,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC,CAAC,CAAC,UAAmB,CAAC,CAAC,CAAC,mBAA4B,EAAE,qBAAqB,EAAE,EAAE,EAAE,cAAc,EAAE,gBAAgB;QAC/I,UAAU,CAAC,CAA8B,EAAE,CAAuC,EAAE,KAAa,EAAE,MAAc;YAC/G,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,CAAE,CAAC;YAC/C,IAAI,cAAc,KAAK,IAAI;gBAAE,OAAO,QAAQ,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAE,CAAC,KAAK,CAAE,CAAE,CAAC,CAAC;YAC/E,IAAI,GAAG,GAAG,CAAC,CAAC;YACZ,MAAM,GAAG,GAAG,cAAc,CAAC,MAAM,CAAE,CAAC;YACpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE;gBAAE,GAAG,IAAI,GAAG,CAAC,CAAC,CAAE,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAE,CAAC,CAAC;YACvF,OAAO,GAAG,CAAC;QACb,CAAC,EAAE,CAAC,CAAC;AACT,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,2BAA2B,CAAC,KAA8B;IACxE,MAAM,IAAI,GAAG,+BAA+B,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;IAC/G,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE;QAAE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE;YAAE,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,iBAAiB,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7K,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AAC1B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qCAAqC,CAAC,KAAiG;IACrJ,MAAM,CAAC,GAAG,wBAAwB,CAAC,KAAK,EAAE,CAAC,YAAY,EAAE,WAAW,EAAE,oBAAoB,CAAC,EAAE,iCAAiC,CAAC,CAAC;IAChI,MAAM,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,QAAQ,GAAG,CAAC,CAAC,SAAS,EAAE,KAAK,GAAG,CAAC,CAAC,kBAAkB,CAAC;IAC7E,IAAI,CAAC,CAAC,CAAC,YAAY,YAAY,IAAI,CAAC,YAAY,YAAY,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC,QAAQ,GAAG,CAAC,IAAI,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC;QAClK,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3E,MAAM,IAAI,yBAAyB,CAAC,kGAAkG,CAAC,CAAC;IAC1I,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IAClD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAE,CAAC;QAC1B,IAAI,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;YAAE,MAAM,IAAI,yBAAyB,CAAC,2DAA2D,CAAC,CAAC;QAChH,MAAM,CAAC,GAAG,QAAQ,GAAG,EAAE,CAAC;QACxB,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAE,GAAG,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAE,GAAG,CAAC,GAAG,KAAK,CAAC;QACjE,sGAAsG;QACtG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;YAAE,MAAM,IAAI,yBAAyB,CAAC,wFAAwF,CAAC,CAAC;QAC9K,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QAClB,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Batched radiance queries for the engine's procedural chart scenes (#277): many frame points in one\n * call, each answered with spectral radiance at a declared wavelength, or with the spectral integral of\n * that radiance against declared channel weights. This is the float64 CPU reference for the\n * `webgpu-f32` chart-radiance stage (`ImageKernelAccelerator.evaluateChartRadiance`).\n *\n * Every value comes from the chart provider's own `radianceAt` (createPlanarSceneRadianceProvider): a\n * Lambertian reflectance ρ(λ) under the scaled illuminant, L = ρ·k·S(λ)/π. The spectral integral of a\n * query is Σ_j w_cj·L(u, v, λ_j), summed in wavelength order. Charts are uniform-illuminant Lambertian\n * patterns, so a query's integral depends only on its material: the GPU stage uses exactly that.\n *\n * The query shape mirrors a batched provider (one call, queries in, results in the same order). Points\n * are frame units (u right, v up; see chart-scenes.ts); `mapEnvironmentDirectionsToChartPoints` converts\n * environment-direction queries exactly as `evaluateRadiance` does.\n * @see docs/WEBGPU.md, \"Scene radiance on the GPU\".\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { requireAllowlistedRecord } from \"../core/record-validation.js\";\nimport { FULL_RESOLUTION_CEILING_PIXELS, resolveRaisedLimit } from \"../core/pixel-limits.js\";\nimport { resolveChartScene, type ChartScene, type ResolvedChartScene } from \"./chart-scenes.js\";\nimport { buildPlanarSceneRadianceProvider, calculateIlluminantIrradianceScale, resolveCaptureIlluminant, tabulatedSpectrum, type CaptureIlluminant,\n type ResolvedCaptureIlluminant } from \"./scene-radiance.js\";\n\nexport const CHART_RADIANCE_BATCH_SCHEMA_VERSION = \"0.1.0\" as const;\n/** `maximumQueries` is the default batch limit; a request may raise it with its own `maximumQueries`, up to `ceilingQueries`. */\nexport const CHART_RADIANCE_BATCH_LIMITS = Object.freeze({ maximumQueries: 24_000_000, ceilingQueries: FULL_RESOLUTION_CEILING_PIXELS, maximumWavelengths: 256,\n maximumChannels: 4 });\n\nexport interface ChartRadianceBatchInput {\n schemaVersion: typeof CHART_RADIANCE_BATCH_SCHEMA_VERSION;\n /** An engine chart preset (caller scene functions are not supported here). */\n scene: ChartScene;\n illuminant: CaptureIlluminant;\n illuminanceLux: number;\n /** Frame height / width. */\n aspect: number;\n /** Frame points, interleaved [u0, v0, u1, v1, …]. Finite. */\n points: Float32Array | Float64Array;\n /** The wavelengths the queries use, in nanometres (1–256). */\n wavelengthsNanometers: readonly number[];\n /** Radiance queries: one wavelength index per point. Exactly one of this and `channelWeights`. */\n wavelengthIndices?: Uint8Array | Uint16Array;\n /** Spectral integration: per channel (1–4), one finite weight per wavelength. */\n channelWeights?: readonly (readonly number[])[];\n /**\n * Optional opt-in batch limit: an integer from 1 to `CHART_RADIANCE_BATCH_LIMITS.ceilingQueries`. Default\n * `CHART_RADIANCE_BATCH_LIMITS.maximumQueries` (24 000 000). It does not change the values.\n */\n maximumQueries?: number;\n}\n\n/** Validated plan with the resolved chart, illuminant and irradiance scale. Arrays are borrowed. */\nexport interface ChartRadianceBatchPlan {\n chart: ResolvedChartScene;\n illuminant: ResolvedCaptureIlluminant;\n irradianceScale: number;\n queryCount: number;\n /** Output values per query: 1 for radiance queries, the channel count for spectral integration. */\n columns: number;\n mode: \"radiance\" | \"spectral-integral\";\n wavelengthsNanometers: readonly number[];\n channelWeights: readonly (readonly number[])[] | null;\n /** Spectral radiance of one material at a wavelength: the provider's own radianceAt for that material. */\n materialRadiance(material: number, wavelengthNanometers: number): number;\n /** The reference value of one query and output column (radianceAt, and its wavelength-ordered sum). */\n queryValue(points: Float32Array | Float64Array, wavelengthIndices: Uint8Array | Uint16Array | undefined, query: number, column: number): number;\n}\n\nexport function calculateChartRadianceBatchPlan(input: ChartRadianceBatchInput): ChartRadianceBatchPlan {\n const r = requireAllowlistedRecord(input, [\"schemaVersion\", \"scene\", \"illuminant\", \"illuminanceLux\", \"aspect\", \"points\", \"wavelengthsNanometers\",\n \"wavelengthIndices\", \"channelWeights\", \"maximumQueries\"], \"Invalid chart radiance batch input.\");\n if (r.schemaVersion !== CHART_RADIANCE_BATCH_SCHEMA_VERSION) throw new InvalidConfigurationError(\"Unsupported chart radiance batch schema.\");\n if (typeof r.aspect !== \"number\" || !(r.aspect > 0 && r.aspect <= Number.MAX_VALUE)) throw new InvalidConfigurationError(\"aspect must be positive.\");\n const chart = resolveChartScene({ scene: r.scene as ChartScene, aspect: r.aspect });\n const illuminant = resolveCaptureIlluminant(r.illuminant as CaptureIlluminant);\n const irradianceScale = calculateIlluminantIrradianceScale(illuminant.shape, r.illuminanceLux as number);\n const L = CHART_RADIANCE_BATCH_LIMITS, points = r.points;\n const maximumQueries = resolveRaisedLimit(r.maximumQueries, L.maximumQueries, L.ceilingQueries,\n \"Chart radiance batch maximumQueries must be an integer from 1 to \" + L.ceilingQueries + \".\");\n if (!(points instanceof Float32Array || points instanceof Float64Array) || points.length % 2 !== 0 || points.length / 2 > maximumQueries) {\n throw new InvalidConfigurationError(\"points must be an interleaved Float32Array or Float64Array of (u, v) pairs.\");\n }\n for (let i = 0; i < points.length; i++) if (!Number.isFinite(points[i]!)) throw new InvalidConfigurationError(\"Chart points must be finite.\");\n const queryCount = points.length / 2, wavelengths = r.wavelengthsNanometers;\n if (!Array.isArray(wavelengths) || wavelengths.length < 1 || wavelengths.length > L.maximumWavelengths ||\n wavelengths.some(nm => typeof nm !== \"number\" || !Number.isFinite(nm) || nm <= 0)) {\n throw new InvalidConfigurationError(\"wavelengthsNanometers must list 1 to 256 positive wavelengths.\");\n }\n const indices = r.wavelengthIndices, weights = r.channelWeights;\n if ((indices === undefined) === (weights === undefined)) throw new InvalidConfigurationError(\"Give exactly one of wavelengthIndices and channelWeights.\");\n if (indices !== undefined) {\n if (!(indices instanceof Uint8Array || indices instanceof Uint16Array) || indices.length !== queryCount) {\n throw new InvalidConfigurationError(\"wavelengthIndices must hold one index per point.\");\n }\n for (let i = 0; i < queryCount; i++) if (indices[i]! >= wavelengths.length) throw new InvalidConfigurationError(\"A wavelength index is out of range.\");\n } else if (!Array.isArray(weights) || weights.length < 1 || weights.length > L.maximumChannels ||\n weights.some(row => !Array.isArray(row) || row.length !== wavelengths.length || row.some(w => typeof w !== \"number\" || !Number.isFinite(w)))) {\n throw new InvalidConfigurationError(\"channelWeights must hold 1 to 4 rows of one finite weight per wavelength.\");\n }\n // The provider's own radiance function: chart reflectance × scaled illuminant / π, in its float64 order.\n const provider = buildPlanarSceneRadianceProvider({ scene: chart, sceneId: \"chart-radiance-batch\", providerProfileId: \"chart-radiance-batch\", illuminant,\n irradianceScale, geometry: { distanceM: 1, metresPerFrameUnit: 1 }, evidence: [], limitations: [] });\n const channelWeights = weights === undefined ? null : (weights as number[][]).map(row => Object.freeze([...row]));\n const nm = Object.freeze([...(wavelengths as number[])]);\n const shapeAt = tabulatedSpectrum(illuminant.shape);\n const materialRadiance = (material: number, wavelength: number): number => {\n const m = chart.materials[material]!;\n const reflectance = m.kind === \"neutral\" ? m.reflectance : m.spectrum.evaluate(wavelength);\n if (m.kind === \"spectrum\" && !(reflectance >= 0 && reflectance <= 1)) throw new InvalidConfigurationError(\"Chart reflectance spectrum left [0, 1].\");\n return reflectance * irradianceScale * shapeAt(wavelength) / Math.PI;\n };\n return Object.freeze({ chart, illuminant, irradianceScale, queryCount, columns: channelWeights === null ? 1 : channelWeights.length,\n mode: channelWeights === null ? \"radiance\" as const : \"spectral-integral\" as const, wavelengthsNanometers: nm, channelWeights, materialRadiance,\n queryValue(p: Float32Array | Float64Array, w: Uint8Array | Uint16Array | undefined, query: number, column: number): number {\n const u = p[2 * query]!, v = p[2 * query + 1]!;\n if (channelWeights === null) return provider.radianceAt(u, v, nm[w![query]!]!);\n let sum = 0;\n const row = channelWeights[column]!;\n for (let j = 0; j < nm.length; j++) sum += row[j]! * provider.radianceAt(u, v, nm[j]!);\n return sum;\n } });\n}\n\n/** Float64 CPU reference: every query's value(s), row-major (query, column). */\nexport function calculateChartRadianceBatch(input: ChartRadianceBatchInput): { plan: ChartRadianceBatchPlan; values: Float64Array } {\n const plan = calculateChartRadianceBatchPlan(input), values = new Float64Array(plan.queryCount * plan.columns);\n for (let q = 0; q < plan.queryCount; q++) for (let c = 0; c < plan.columns; c++) values[q * plan.columns + c] = plan.queryValue(input.points, input.wavelengthIndices, q, c);\n return { plan, values };\n}\n\n/**\n * Frame points of environment-direction queries on the chart plane, exactly as the planar provider's\n * `evaluateRadiance` computes them: look direction l = −o, plane point l·distance/l.z, in frame units.\n * @param directions - Outgoing unit vectors (scene toward camera), interleaved [x, y, z, …].\n */\nexport function mapEnvironmentDirectionsToChartPoints(input: { directions: Float32Array | Float64Array; distanceM: number; metresPerFrameUnit: number }): Float64Array {\n const r = requireAllowlistedRecord(input, [\"directions\", \"distanceM\", \"metresPerFrameUnit\"], \"Invalid planar direction input.\");\n const d = r.directions, distance = r.distanceM, scale = r.metresPerFrameUnit;\n if (!(d instanceof Float32Array || d instanceof Float64Array) || d.length % 3 !== 0 || typeof distance !== \"number\" || !(distance > 0 && distance <= Number.MAX_VALUE) ||\n typeof scale !== \"number\" || !(scale > 0 && scale <= Number.MAX_VALUE)) {\n throw new InvalidConfigurationError(\"Planar directions need interleaved unit vectors, a positive distance and a positive frame scale.\");\n }\n const points = new Float64Array(d.length / 3 * 2);\n for (let i = 0; i < d.length / 3; i++) {\n const lz = -d[3 * i + 2]!;\n if (!(lz > 0)) throw new InvalidConfigurationError(\"Planar scene query does not point toward the scene plane.\");\n const t = distance / lz;\n const x = -d[3 * i]! * t / scale, y = -d[3 * i + 1]! * t / scale;\n // A grazing direction (lz near 0, e.g. 1e-320) or a non-finite component would give ±Infinity or NaN.\n if (!Number.isFinite(x) || !Number.isFinite(y)) throw new InvalidConfigurationError(\"Planar scene query maps to a non-finite chart point (grazing or non-finite direction).\");\n points[2 * i] = x;\n points[2 * i + 1] = y;\n }\n return points;\n}\n"]}
@@ -348,6 +348,8 @@ export declare const CHART_SPECTRAL_RANGE_NANOMETERS: Readonly<{
348
348
  minimum: 380;
349
349
  maximum: 780;
350
350
  }>;
351
+ /** Internal: validates a chart reflectance input (a neutral number or a reflectance spectrum covering 380–780 nm) as a material. */
352
+ export declare function resolveChartMaterial(value: unknown, name: string): ResolvedChartScene["materials"][number];
351
353
  /**
352
354
  * Internal (not exported from the package): the caller input behind each material of a resolved chart, in
353
355
  * material order (`undefined` for an engine neutral). The facade hashes caller spectra from these inputs.
@@ -361,6 +363,15 @@ export declare function resolveChartScene(input: {
361
363
  scene: ChartScene;
362
364
  aspect: number;
363
365
  }): ResolvedChartScene;
366
+ /**
367
+ * Internal (not exported from the package): {@link resolveChartScene} with the step wedge's geometric levels computed
368
+ * with the portable power (`portablePow`, within 1 ulp) instead of `**`, whose last bit differs between JavaScript
369
+ * engines. Every other value, the geometry and the material order are the same. The display view uses its materials.
370
+ */
371
+ export declare function resolvePortableChartScene(input: {
372
+ scene: ChartScene;
373
+ aspect: number;
374
+ }): ResolvedChartScene;
364
375
  /** An axis-aligned rectangle in chart frame units: u0 ≤ u ≤ u1, v0 ≤ v ≤ v1. */
365
376
  export interface ChartRectangle {
366
377
  u0: number;