pts 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -43,9 +43,12 @@ const EMPTY: Triangulation = {
43
43
  const EPS = 1.1102230246251565e-16;
44
44
  // Bounds on the rounding error of the determinants below, relative to the sum
45
45
  // of the absolute values of their terms (the classic forward error analysis
46
- // of the orientation and in-circle determinants).
47
- const ORIENT_BOUND = (3 + 16 * EPS) * EPS;
48
- const INCIRCLE_BOUND = (10 + 96 * EPS) * EPS;
46
+ // of the orientation and in-circle determinants). Computed through a function
47
+ // marked pure so bundles that never triangulate drop them: a bundler that
48
+ // turns these consts into vars cannot prove the bare products side-effect free.
49
+ const errorBound = (a: number, b: number) => (a + b * EPS) * EPS;
50
+ const ORIENT_BOUND = /* @__PURE__ */ errorBound(3, 16);
51
+ const INCIRCLE_BOUND = /* @__PURE__ */ errorBound(10, 96);
49
52
  // Coordinates that become integers below 2^31 when scaled by one power of two
50
53
  // (pixel grids, halves, quarters, every Float32 value in a sane range) keep
51
54
  // their differences exact in a double; the products those differences form are
@@ -322,15 +325,28 @@ function _incircleInt(
322
325
  // Exact evaluation: each double is sign * mantissa * 2^exponent with an
323
326
  // integer mantissa, so scaling every input to the smallest exponent gives
324
327
  // exact integers whose determinant has the same sign as the real one.
325
- const _bits = new Float64Array(1);
326
- const _words = new Uint32Array(_bits.buffer);
327
- _bits[0] = 1;
328
- const HI = _words[1] === 0x3ff00000 ? 1 : 0;
329
- const LO = HI ^ 1;
328
+ // Views over one buffer, and the indices of the words holding a double's
329
+ // high bits (sign, exponent, top of the mantissa) and low bits. Every
330
+ // initializer is a call marked pure, so a bundle that never triangulates
331
+ // drops all of it (a bundler cannot prove `HI ^ 1` free of side effects).
332
+ const _buffer = /* @__PURE__ */ new ArrayBuffer(8);
333
+ const _bits = /* @__PURE__ */ new Float64Array(_buffer);
334
+ const _words = /* @__PURE__ */ new Uint32Array(_buffer);
335
+ const HI = /* @__PURE__ */ wordIndex(true);
336
+ const LO = /* @__PURE__ */ wordIndex(false);
337
+
338
+ function wordIndex(high: boolean): number {
339
+ // little-endian hosts store the high word of 1.0 (0x3ff00000) second
340
+ const probe = new Float64Array([1]);
341
+ const highSecond = new Uint32Array(probe.buffer)[1] === 0x3ff00000;
342
+ return high === highSecond ? 1 : 0;
343
+ }
344
+
330
345
  const _mant = new Float64Array(8);
331
346
  const _expo = new Int32Array(8);
332
- // BigInt is only touched inside the exact fallback, so loading this module
333
- // never requires it
347
+ // BigInt is used only when called: by `crossingParameter` (every proper
348
+ // crossing in the polygon overlay) and by the exact predicates below, so
349
+ // loading this module never requires it
334
350
 
335
351
  function _scaled(values: Float64Array, count: number): bigint[] {
336
352
  let minExpo = 0x7fffffff;
@@ -359,6 +375,52 @@ function _scaled(values: Float64Array, count: number): bigint[] {
359
375
  return out;
360
376
  }
361
377
 
378
+ // `Number(bigint)` is finite below 2^1024; shift in whole limbs until then.
379
+ // Created on first use, so loading this module never evaluates BigInt.
380
+ let _finiteLimit: bigint | undefined;
381
+ let _shiftStep: bigint;
382
+
383
+ /**
384
+ * Parameter of a known proper crossing along a→b. Evaluate the determinants
385
+ * exactly before division: shallow crossings can lose most of their digits
386
+ * when two rounded products are subtracted. Used by the polygon overlay.
387
+ */
388
+ export function crossingParameter(
389
+ ax: number,
390
+ ay: number,
391
+ bx: number,
392
+ by: number,
393
+ cx: number,
394
+ cy: number,
395
+ dx: number,
396
+ dy: number,
397
+ ): number {
398
+ _input.set([ax, ay, bx, by, cx, cy, dx, dy]);
399
+ const [a, b, c, d, e, f, g, h] = _scaled(_input, 8);
400
+ const rx = g - e;
401
+ const ry = h - f;
402
+ let numerator = rx * (b - f) - ry * (a - e);
403
+ let denominator = numerator - (rx * (d - f) - ry * (c - e));
404
+ if (denominator < BigInt(0)) {
405
+ numerator = -numerator;
406
+ denominator = -denominator;
407
+ }
408
+ // Keep the conversion finite even when the input doubles span hundreds of
409
+ // binary exponents. The numerator is between zero and the denominator, and
410
+ // a denominator of ordinary size needs no shift at all.
411
+ if (_finiteLimit === undefined) {
412
+ _finiteLimit = BigInt(1) << BigInt(1023);
413
+ _shiftStep = BigInt(64);
414
+ }
415
+ let shift = BigInt(0);
416
+ let scaled = denominator;
417
+ while (scaled >= _finiteLimit) {
418
+ scaled >>= _shiftStep;
419
+ shift += _shiftStep;
420
+ }
421
+ return Number(numerator >> shift) / Number(scaled);
422
+ }
423
+
362
424
  /** Exact orientation, evaluated in BigInt. Used when the fast filter cannot decide. */
363
425
  export function orient2dExact(
364
426
  ax: number,