@bldrs-ai/conway 1.599.1551 → 1.603.1553

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.
@@ -30,7 +30,7 @@ var import_node_process = require("node:process");
30
30
  var readline = __toESM(require("node:readline"), 1);
31
31
 
32
32
  // compiled/src/version/version.js
33
- var versionString = "Conway v1.599.1551";
33
+ var versionString = "Conway v1.603.1553";
34
34
 
35
35
  // compiled/dependencies/conway-geom/interface/conway_geometry.js
36
36
  var wasmType = "";
@@ -1401,6 +1401,7 @@ var integerParser = integer_parser_default.Instance;
1401
1401
  var realParser = real_parser_default.Instance;
1402
1402
  var hexParser = hex_parser_default.Instance;
1403
1403
  var RADIX_LUT_SIZE = 64;
1404
+ var RADIX_LUT_MAX_INDEX = RADIX_LUT_SIZE - 1;
1404
1405
  var radixLUT = new Float64Array(RADIX_LUT_SIZE);
1405
1406
  {
1406
1407
  let radixMultiplier = 1;
@@ -1748,12 +1749,12 @@ var ParsingBuffer = class {
1748
1749
  return primary;
1749
1750
  }
1750
1751
  while (decimals < 0) {
1751
- const radixLutEntry = Math.min(-decimals, RADIX_LUT_SIZE);
1752
+ const radixLutEntry = Math.min(-decimals, RADIX_LUT_MAX_INDEX);
1752
1753
  decimals += radixLutEntry;
1753
1754
  primary /= radixLUT[radixLutEntry];
1754
1755
  }
1755
1756
  while (decimals > 0) {
1756
- const radixLutEntry = Math.min(decimals, RADIX_LUT_SIZE);
1757
+ const radixLutEntry = Math.min(decimals, RADIX_LUT_MAX_INDEX);
1757
1758
  decimals -= radixLutEntry;
1758
1759
  primary *= radixLUT[radixLutEntry];
1759
1760
  }
@@ -14985,7 +14985,7 @@ ${t5.join("\n")}` : "";
14985
14985
  var import_process = require("process");
14986
14986
 
14987
14987
  // compiled/src/version/version.js
14988
- var versionString = "Conway v1.599.1551";
14988
+ var versionString = "Conway v1.603.1553";
14989
14989
 
14990
14990
  // compiled/dependencies/conway-geom/interface/conway_geometry.js
14991
14991
  function pThreadsAllowed() {
@@ -17260,6 +17260,7 @@ var integerParser = integer_parser_default.Instance;
17260
17260
  var realParser = real_parser_default.Instance;
17261
17261
  var hexParser = hex_parser_default.Instance;
17262
17262
  var RADIX_LUT_SIZE = 64;
17263
+ var RADIX_LUT_MAX_INDEX = RADIX_LUT_SIZE - 1;
17263
17264
  var radixLUT = new Float64Array(RADIX_LUT_SIZE);
17264
17265
  {
17265
17266
  let radixMultiplier = 1;
@@ -17607,12 +17608,12 @@ var ParsingBuffer = class {
17607
17608
  return primary;
17608
17609
  }
17609
17610
  while (decimals < 0) {
17610
- const radixLutEntry = Math.min(-decimals, RADIX_LUT_SIZE);
17611
+ const radixLutEntry = Math.min(-decimals, RADIX_LUT_MAX_INDEX);
17611
17612
  decimals += radixLutEntry;
17612
17613
  primary /= radixLUT[radixLutEntry];
17613
17614
  }
17614
17615
  while (decimals > 0) {
17615
- const radixLutEntry = Math.min(decimals, RADIX_LUT_SIZE);
17616
+ const radixLutEntry = Math.min(decimals, RADIX_LUT_MAX_INDEX);
17616
17617
  decimals -= radixLutEntry;
17617
17618
  primary *= radixLUT[radixLutEntry];
17618
17619
  }
@@ -15507,6 +15507,7 @@ var integerParser = integer_parser_default.Instance;
15507
15507
  var realParser = real_parser_default.Instance;
15508
15508
  var hexParser = hex_parser_default.Instance;
15509
15509
  var RADIX_LUT_SIZE = 64;
15510
+ var RADIX_LUT_MAX_INDEX = RADIX_LUT_SIZE - 1;
15510
15511
  var radixLUT = new Float64Array(RADIX_LUT_SIZE);
15511
15512
  {
15512
15513
  let radixMultiplier = 1;
@@ -15854,12 +15855,12 @@ var ParsingBuffer = class {
15854
15855
  return primary;
15855
15856
  }
15856
15857
  while (decimals < 0) {
15857
- const radixLutEntry = Math.min(-decimals, RADIX_LUT_SIZE);
15858
+ const radixLutEntry = Math.min(-decimals, RADIX_LUT_MAX_INDEX);
15858
15859
  decimals += radixLutEntry;
15859
15860
  primary /= radixLUT[radixLutEntry];
15860
15861
  }
15861
15862
  while (decimals > 0) {
15862
- const radixLutEntry = Math.min(decimals, RADIX_LUT_SIZE);
15863
+ const radixLutEntry = Math.min(decimals, RADIX_LUT_MAX_INDEX);
15863
15864
  decimals -= radixLutEntry;
15864
15865
  primary *= radixLUT[radixLutEntry];
15865
15866
  }
@@ -15963,7 +15964,7 @@ var ParsingBuffer = class {
15963
15964
  };
15964
15965
 
15965
15966
  // compiled/src/version/version.js
15966
- var versionString = "Conway v1.599.1551";
15967
+ var versionString = "Conway v1.603.1553";
15967
15968
 
15968
15969
  // compiled/dependencies/conway-geom/interface/conway_geometry.js
15969
15970
  function pThreadsAllowed() {
@@ -944,7 +944,7 @@ var EntityTypesIfcCount = 909;
944
944
  var entity_types_ifc_gen_default = EntityTypesIfc;
945
945
 
946
946
  // compiled/src/version/version.js
947
- var versionString = "Conway v1.599.1551";
947
+ var versionString = "Conway v1.603.1553";
948
948
 
949
949
  // compiled/dependencies/conway-geom/interface/conway_geometry.js
950
950
  var wasmType = "";
@@ -2315,6 +2315,7 @@ var integerParser = integer_parser_default.Instance;
2315
2315
  var realParser = real_parser_default.Instance;
2316
2316
  var hexParser = hex_parser_default.Instance;
2317
2317
  var RADIX_LUT_SIZE = 64;
2318
+ var RADIX_LUT_MAX_INDEX = RADIX_LUT_SIZE - 1;
2318
2319
  var radixLUT = new Float64Array(RADIX_LUT_SIZE);
2319
2320
  {
2320
2321
  let radixMultiplier = 1;
@@ -2662,12 +2663,12 @@ var ParsingBuffer = class {
2662
2663
  return primary;
2663
2664
  }
2664
2665
  while (decimals < 0) {
2665
- const radixLutEntry = Math.min(-decimals, RADIX_LUT_SIZE);
2666
+ const radixLutEntry = Math.min(-decimals, RADIX_LUT_MAX_INDEX);
2666
2667
  decimals += radixLutEntry;
2667
2668
  primary /= radixLUT[radixLutEntry];
2668
2669
  }
2669
2670
  while (decimals > 0) {
2670
- const radixLutEntry = Math.min(decimals, RADIX_LUT_SIZE);
2671
+ const radixLutEntry = Math.min(decimals, RADIX_LUT_MAX_INDEX);
2671
2672
  decimals -= radixLutEntry;
2672
2673
  primary *= radixLUT[radixLutEntry];
2673
2674
  }
@@ -1 +1 @@
1
- {"version":3,"file":"parsing_buffer.d.ts","sourceRoot":"","sources":["../../../src/parsing/parsing_buffer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"parsing_buffer.d.ts","sourceRoot":"","sources":["../../../src/parsing/parsing_buffer.ts"],"names":[],"mappings":"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"}
@@ -12,6 +12,8 @@ const integerParser = IntegerParser.Instance;
12
12
  const realParser = RealParser.Instance;
13
13
  const hexParser = HexParser.Instance;
14
14
  const RADIX_LUT_SIZE = 64;
15
+ // Largest index the LUT actually holds; see readReal's scaling loops.
16
+ const RADIX_LUT_MAX_INDEX = RADIX_LUT_SIZE - 1;
15
17
  const radixLUT = new Float64Array(RADIX_LUT_SIZE);
16
18
  {
17
19
  let radixMultiplier = 1;
@@ -478,14 +480,24 @@ export default class ParsingBuffer {
478
480
  return primary;
479
481
  }
480
482
  while (decimals < 0) {
481
- const radixLutEntry = Math.min(-decimals, RADIX_LUT_SIZE);
483
+ // RADIX_LUT_MAX_INDEX, not RADIX_LUT_SIZE: radixLUT is a Float64Array of
484
+ // exactly RADIX_LUT_SIZE entries, so index RADIX_LUT_SIZE is out of
485
+ // bounds and a typed-array read there yields `undefined`, not a throw —
486
+ // `primary /= undefined` is NaN. Any real whose total decimal shift
487
+ // reached 64 (1.0E-63 with one fractional digit, 1.5E308, and 306
488
+ // direction/coordinate literals in Orbiter_v1.1_Gear_7.5.step) parsed
489
+ // as NaN and carried that silently into placements and geometry.
490
+ // Clamping to the last valid entry only changes inputs that used to be
491
+ // NaN: for a shift below 64 both clamps return the shift itself.
492
+ const radixLutEntry = Math.min(-decimals, RADIX_LUT_MAX_INDEX);
482
493
  decimals += radixLutEntry;
483
494
  // Note, we need to use division here not a multiply
484
495
  // by inverse to get the matching rounding mode behaviour.
485
496
  primary /= radixLUT[radixLutEntry];
486
497
  }
487
498
  while (decimals > 0) {
488
- const radixLutEntry = Math.min(decimals, RADIX_LUT_SIZE);
499
+ // See the note on the negative-exponent loop above.
500
+ const radixLutEntry = Math.min(decimals, RADIX_LUT_MAX_INDEX);
489
501
  decimals -= radixLutEntry;
490
502
  primary *= radixLUT[radixLutEntry];
491
503
  }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=parsing_buffer_real.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parsing_buffer_real.test.d.ts","sourceRoot":"","sources":["../../../src/parsing/parsing_buffer_real.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,94 @@
1
+ import { describe, expect, test } from "@jest/globals";
2
+ import ParsingBuffer from "./parsing_buffer.js";
3
+ /**
4
+ * Parse one STEP/IFC real literal through the same entry point the entity
5
+ * parsers use.
6
+ *
7
+ * A trailing space stands in for the delimiter a real always has after it in
8
+ * a STEP file; readReal reads up to it and leaves the cursor there.
9
+ *
10
+ * @param literal The literal to parse, exactly as it appears in a file.
11
+ * @return {number | undefined} What readReal made of it.
12
+ */
13
+ function readReal(literal) {
14
+ const data = new TextEncoder().encode(`${literal} `);
15
+ return new ParsingBuffer(data).readReal();
16
+ }
17
+ /**
18
+ * Relative difference between a parsed value and the runtime's own decimal
19
+ * conversion of the same literal.
20
+ *
21
+ * readReal scales the mantissa against a power-of-ten table rather than
22
+ * deferring to `Number()`, so it is correctly rounded only to within a few
23
+ * ULP. That accuracy contract is long-standing and is not what these tests
24
+ * are about; they are about literals that used to come back NaN.
25
+ *
26
+ * @param literal The literal to parse and to use as the reference.
27
+ * @return {number} The relative error, or Infinity if the parse is not finite.
28
+ */
29
+ function relativeErrorAgainstRuntime(literal) {
30
+ const got = readReal(literal);
31
+ const expected = Number(literal);
32
+ if (typeof got !== "number" || !Number.isFinite(got)) {
33
+ return Infinity;
34
+ }
35
+ if (expected === 0) {
36
+ return Math.abs(got);
37
+ }
38
+ return Math.abs((got - expected) / expected);
39
+ }
40
+ // A total decimal shift of 64 — fractional digits plus exponent, not the
41
+ // exponent alone — is the boundary the radix table's last index sits on.
42
+ // readReal used to clamp the per-iteration shift to RADIX_LUT_SIZE, and
43
+ // radixLUT[RADIX_LUT_SIZE] is one past the end of a Float64Array, which reads
44
+ // `undefined` rather than throwing; dividing by that yields NaN silently. 306
45
+ // direction and coordinate values in Orbiter_v1.1_Gear_7.5.step parsed that
46
+ // way, putting NaN into every placement built from them (bldrs-ai/conway#589).
47
+ const TOLERANCE = 1e-12;
48
+ const IN_RANGE = [
49
+ "0.1",
50
+ "-1.5E-8",
51
+ "1.0E-50",
52
+ "9.86076131526265E-32",
53
+ "4.37905770101505E-47",
54
+ ];
55
+ // '1.0' contributes one fractional digit, so E-63 is a shift of exactly 64:
56
+ // the first literal that used to be NaN. The last four are real values taken
57
+ // from corpus models.
58
+ const PAST_THE_TABLE = [
59
+ "1.0E-63",
60
+ "1.0E-64",
61
+ "1.0E-65",
62
+ "1.33564029830467E-63",
63
+ "-1.94469227207812E-62",
64
+ "3.52475474722604E-62",
65
+ "5.25674630405262E-61",
66
+ ];
67
+ // The positive-exponent loop carries the same clamp, so it had the same
68
+ // boundary: 1.0E+64 was the largest that survived. 5.0E-324 is the smallest
69
+ // denormal, which scaling has to reach without passing through NaN.
70
+ const LARGE_AND_DENORMAL = [
71
+ "1.0E+64",
72
+ "1.0E+65",
73
+ "1.5E308",
74
+ "5.0E-324",
75
+ ];
76
+ describe("ParsingBuffer.readReal", () => {
77
+ test.each([...IN_RANGE, ...PAST_THE_TABLE, ...LARGE_AND_DENORMAL])("parses %s to the same value the runtime does", (literal) => {
78
+ expect(Number.isFinite(readReal(literal))).toBe(true);
79
+ expect(relativeErrorAgainstRuntime(literal))
80
+ .toBeLessThanOrEqual(TOLERANCE);
81
+ });
82
+ test("scales past the radix table in more than one step", () => {
83
+ // A shift of 200 is three trips through the loop, which is what proves
84
+ // the clamp is a chunk size and not a ceiling on the exponent.
85
+ expect(relativeErrorAgainstRuntime("1.0E-200"))
86
+ .toBeLessThanOrEqual(TOLERANCE);
87
+ expect(relativeErrorAgainstRuntime("1.0E+200"))
88
+ .toBeLessThanOrEqual(TOLERANCE);
89
+ });
90
+ test("still overflows and underflows where a double must", () => {
91
+ expect(readReal("1.0E+400")).toBe(Infinity);
92
+ expect(readReal("1.0E-400")).toBe(0);
93
+ });
94
+ });
@@ -5,5 +5,5 @@
5
5
  // only the first segment (major) is meaningful and is the one CI carries forward.
6
6
  // Must stay in `vN.N.N` shape: the CI stamp regex, scripts/updateVersion.mjs, and
7
7
  // statistics.ts all match `v\d+\.\d+\.\d+`.
8
- const versionString = 'Conway v1.599.1551';
8
+ const versionString = 'Conway v1.603.1553';
9
9
  export { versionString };