@cj-tech-master/excelts 9.3.1 → 9.4.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 (109) hide show
  1. package/dist/browser/index.d.ts +1 -0
  2. package/dist/browser/index.js +2 -0
  3. package/dist/browser/modules/excel/cell.d.ts +18 -0
  4. package/dist/browser/modules/excel/cell.js +21 -0
  5. package/dist/browser/modules/excel/utils/cell-format.js +85 -13
  6. package/dist/browser/modules/excel/workbook.browser.d.ts +57 -0
  7. package/dist/browser/modules/excel/workbook.browser.js +49 -0
  8. package/dist/browser/modules/excel/xlsx/defaultnumformats.js +3 -3
  9. package/dist/browser/modules/formula/compile/binder.js +48 -6
  10. package/dist/browser/modules/formula/compile/bound-ast.d.ts +16 -2
  11. package/dist/browser/modules/formula/compile/bound-ast.js +1 -0
  12. package/dist/browser/modules/formula/compile/compiled-formula.js +41 -8
  13. package/dist/browser/modules/formula/functions/_shared.d.ts +19 -0
  14. package/dist/browser/modules/formula/functions/_shared.js +47 -0
  15. package/dist/browser/modules/formula/functions/conditional.js +103 -22
  16. package/dist/browser/modules/formula/functions/date.js +105 -23
  17. package/dist/browser/modules/formula/functions/dynamic-array.js +173 -69
  18. package/dist/browser/modules/formula/functions/engineering.d.ts +2 -2
  19. package/dist/browser/modules/formula/functions/engineering.js +103 -151
  20. package/dist/browser/modules/formula/functions/financial.js +210 -184
  21. package/dist/browser/modules/formula/functions/lookup.js +224 -157
  22. package/dist/browser/modules/formula/functions/math.d.ts +26 -0
  23. package/dist/browser/modules/formula/functions/math.js +249 -69
  24. package/dist/browser/modules/formula/functions/statistical.js +221 -171
  25. package/dist/browser/modules/formula/functions/text.js +112 -52
  26. package/dist/browser/modules/formula/integration/calculate-formulas-impl.js +20 -1
  27. package/dist/browser/modules/formula/materialize/build-writeback-plan.js +10 -6
  28. package/dist/browser/modules/formula/materialize/types.d.ts +15 -0
  29. package/dist/browser/modules/formula/runtime/evaluator.d.ts +8 -0
  30. package/dist/browser/modules/formula/runtime/evaluator.js +582 -162
  31. package/dist/browser/modules/formula/runtime/function-registry.d.ts +5 -0
  32. package/dist/browser/modules/formula/runtime/function-registry.js +59 -13
  33. package/dist/browser/modules/formula/runtime/values.d.ts +13 -0
  34. package/dist/browser/modules/formula/runtime/values.js +20 -2
  35. package/dist/browser/modules/formula/syntax/ast.d.ts +14 -2
  36. package/dist/browser/modules/formula/syntax/ast.js +1 -0
  37. package/dist/browser/modules/formula/syntax/parser.js +29 -7
  38. package/dist/browser/modules/formula/syntax/token-types.d.ts +4 -0
  39. package/dist/browser/modules/formula/syntax/token-types.js +9 -0
  40. package/dist/browser/modules/formula/syntax/tokenizer.js +76 -19
  41. package/dist/cjs/index.js +7 -2
  42. package/dist/cjs/modules/excel/cell.js +21 -0
  43. package/dist/cjs/modules/excel/utils/cell-format.js +85 -13
  44. package/dist/cjs/modules/excel/workbook.browser.js +49 -0
  45. package/dist/cjs/modules/excel/xlsx/defaultnumformats.js +3 -3
  46. package/dist/cjs/modules/formula/compile/binder.js +48 -6
  47. package/dist/cjs/modules/formula/compile/compiled-formula.js +41 -8
  48. package/dist/cjs/modules/formula/functions/_shared.js +48 -0
  49. package/dist/cjs/modules/formula/functions/conditional.js +103 -22
  50. package/dist/cjs/modules/formula/functions/date.js +104 -22
  51. package/dist/cjs/modules/formula/functions/dynamic-array.js +173 -69
  52. package/dist/cjs/modules/formula/functions/engineering.js +109 -157
  53. package/dist/cjs/modules/formula/functions/financial.js +209 -183
  54. package/dist/cjs/modules/formula/functions/lookup.js +224 -157
  55. package/dist/cjs/modules/formula/functions/math.js +254 -70
  56. package/dist/cjs/modules/formula/functions/statistical.js +222 -172
  57. package/dist/cjs/modules/formula/functions/text.js +112 -52
  58. package/dist/cjs/modules/formula/integration/calculate-formulas-impl.js +20 -1
  59. package/dist/cjs/modules/formula/materialize/build-writeback-plan.js +10 -6
  60. package/dist/cjs/modules/formula/runtime/evaluator.js +581 -161
  61. package/dist/cjs/modules/formula/runtime/function-registry.js +57 -11
  62. package/dist/cjs/modules/formula/runtime/values.js +21 -2
  63. package/dist/cjs/modules/formula/syntax/parser.js +29 -7
  64. package/dist/cjs/modules/formula/syntax/token-types.js +9 -0
  65. package/dist/cjs/modules/formula/syntax/tokenizer.js +76 -19
  66. package/dist/esm/index.js +2 -0
  67. package/dist/esm/modules/excel/cell.js +21 -0
  68. package/dist/esm/modules/excel/utils/cell-format.js +85 -13
  69. package/dist/esm/modules/excel/workbook.browser.js +49 -0
  70. package/dist/esm/modules/excel/xlsx/defaultnumformats.js +3 -3
  71. package/dist/esm/modules/formula/compile/binder.js +48 -6
  72. package/dist/esm/modules/formula/compile/bound-ast.js +1 -0
  73. package/dist/esm/modules/formula/compile/compiled-formula.js +41 -8
  74. package/dist/esm/modules/formula/functions/_shared.js +47 -0
  75. package/dist/esm/modules/formula/functions/conditional.js +103 -22
  76. package/dist/esm/modules/formula/functions/date.js +105 -23
  77. package/dist/esm/modules/formula/functions/dynamic-array.js +173 -69
  78. package/dist/esm/modules/formula/functions/engineering.js +103 -151
  79. package/dist/esm/modules/formula/functions/financial.js +210 -184
  80. package/dist/esm/modules/formula/functions/lookup.js +224 -157
  81. package/dist/esm/modules/formula/functions/math.js +249 -69
  82. package/dist/esm/modules/formula/functions/statistical.js +221 -171
  83. package/dist/esm/modules/formula/functions/text.js +112 -52
  84. package/dist/esm/modules/formula/integration/calculate-formulas-impl.js +20 -1
  85. package/dist/esm/modules/formula/materialize/build-writeback-plan.js +10 -6
  86. package/dist/esm/modules/formula/runtime/evaluator.js +582 -162
  87. package/dist/esm/modules/formula/runtime/function-registry.js +59 -13
  88. package/dist/esm/modules/formula/runtime/values.js +20 -2
  89. package/dist/esm/modules/formula/syntax/ast.js +1 -0
  90. package/dist/esm/modules/formula/syntax/parser.js +29 -7
  91. package/dist/esm/modules/formula/syntax/token-types.js +9 -0
  92. package/dist/esm/modules/formula/syntax/tokenizer.js +76 -19
  93. package/dist/iife/excelts.iife.js +1502 -1379
  94. package/dist/iife/excelts.iife.js.map +1 -1
  95. package/dist/iife/excelts.iife.min.js +26 -26
  96. package/dist/types/index.d.ts +1 -0
  97. package/dist/types/modules/excel/cell.d.ts +18 -0
  98. package/dist/types/modules/excel/workbook.browser.d.ts +57 -0
  99. package/dist/types/modules/formula/compile/bound-ast.d.ts +16 -2
  100. package/dist/types/modules/formula/functions/_shared.d.ts +19 -0
  101. package/dist/types/modules/formula/functions/engineering.d.ts +2 -2
  102. package/dist/types/modules/formula/functions/math.d.ts +26 -0
  103. package/dist/types/modules/formula/materialize/types.d.ts +15 -0
  104. package/dist/types/modules/formula/runtime/evaluator.d.ts +8 -0
  105. package/dist/types/modules/formula/runtime/function-registry.d.ts +5 -0
  106. package/dist/types/modules/formula/runtime/values.d.ts +13 -0
  107. package/dist/types/modules/formula/syntax/ast.d.ts +14 -2
  108. package/dist/types/modules/formula/syntax/token-types.d.ts +4 -0
  109. package/package.json +1 -1
@@ -3,160 +3,105 @@
3
3
  * Engineering Functions — Native RuntimeValue implementation.
4
4
  */
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.fnBITLSHIFT = exports.fnBITXOR = exports.fnBITOR = exports.fnBITAND = exports.fnIMCOTH = exports.fnIMSECH = exports.fnIMCSCH = exports.fnIMTANH = exports.fnIMCOSH = exports.fnIMSINH = exports.fnIMCOT = exports.fnIMSEC = exports.fnIMCSC = exports.fnIMTAN = exports.fnIMCOS = exports.fnIMSIN = exports.fnIMEXP = exports.fnIMLOG10 = exports.fnIMLOG2 = exports.fnIMLN = exports.fnIMSQRT = exports.fnIMPOWER = exports.fnIMDIV = exports.fnIMPRODUCT = exports.fnIMSUB = exports.fnIMSUM = exports.fnIMCONJUGATE = exports.fnIMARGUMENT = exports.fnIMABS = exports.fnIMAGINARY = exports.fnIMREAL = exports.fnCOMPLEX = exports.fnGESTEP = exports.fnDELTA = exports.fnBESSELY = exports.fnBESSELK = exports.fnBESSELI = exports.fnBESSELJ = exports.fnOCT2HEX = exports.fnOCT2BIN = exports.fnHEX2OCT = exports.fnHEX2BIN = exports.fnBIN2OCT = exports.fnBIN2HEX = exports.fnDEC2OCT = exports.fnOCT2DEC = exports.fnDEC2HEX = exports.fnHEX2DEC = exports.fnDEC2BIN = exports.fnBIN2DEC = void 0;
6
+ exports.fnBITLSHIFT = exports.fnBITXOR = exports.fnBITOR = exports.fnBITAND = exports.fnIMCOTH = exports.fnIMSECH = exports.fnIMCSCH = exports.fnIMTANH = exports.fnIMCOSH = exports.fnIMSINH = exports.fnIMCOT = exports.fnIMSEC = exports.fnIMCSC = exports.fnIMTAN = exports.fnIMCOS = exports.fnIMSIN = exports.fnIMEXP = exports.fnIMLOG10 = exports.fnIMLOG2 = exports.fnIMLN = exports.fnIMSQRT = exports.fnIMPOWER = exports.fnIMDIV = exports.fnIMPRODUCT = exports.fnIMSUB = exports.fnIMSUM = exports.fnIMCONJUGATE = exports.fnIMARGUMENT = exports.fnIMABS = exports.fnIMAGINARY = exports.fnIMREAL = exports.fnCOMPLEX = exports.fnGESTEP = exports.fnDELTA = exports.fnBESSELY = exports.fnBESSELK = exports.fnBESSELI = exports.fnBESSELJ = exports.fnOCT2HEX = exports.fnOCT2BIN = exports.fnHEX2OCT = exports.fnHEX2BIN = exports.fnBIN2OCT = exports.fnBIN2HEX = exports.fnOCT2DEC = exports.fnHEX2DEC = exports.fnDEC2OCT = exports.fnDEC2HEX = exports.fnDEC2BIN = exports.fnBIN2DEC = void 0;
7
7
  exports.fnBITRSHIFT = void 0;
8
8
  const values_1 = require("../runtime/values");
9
9
  const _shared_1 = require("./_shared");
10
10
  // ============================================================================
11
11
  // Base Conversion Functions
12
12
  // ============================================================================
13
- const fnBIN2DEC = args => {
14
- const err = (0, _shared_1.checkError)(args[0]);
15
- if (err) {
16
- return err;
17
- }
18
- const s = (0, values_1.toStringRV)(args[0]);
19
- if (!/^[01]{1,10}$/.test(s)) {
20
- return values_1.ERRORS.NUM;
21
- }
22
- // 10-bit two's complement
23
- if (s.length === 10 && s[0] === "1") {
24
- return (0, values_1.rvNumber)(parseInt(s.slice(1), 2) - 512);
25
- }
26
- return (0, values_1.rvNumber)(parseInt(s, 2));
27
- };
13
+ const fnBIN2DEC = args => baseToDec(args, 2, /^[01]{1,10}$/);
28
14
  exports.fnBIN2DEC = fnBIN2DEC;
29
- const fnDEC2BIN = args => {
30
- const nRV = (0, values_1.toNumberRV)(args[0]);
15
+ const fnDEC2BIN = args => decToBase(args, 2, -512, 511);
16
+ exports.fnDEC2BIN = fnDEC2BIN;
17
+ const fnDEC2HEX = args => decToBase(args, 16, -549755813888, 549755813887);
18
+ exports.fnDEC2HEX = fnDEC2HEX;
19
+ const fnDEC2OCT = args => decToBase(args, 8, -536870912, 536870911);
20
+ exports.fnDEC2OCT = fnDEC2OCT;
21
+ /**
22
+ * Shared implementation of `DEC2BIN`, `DEC2HEX`, `DEC2OCT`.
23
+ *
24
+ * Excel's three numeric-to-base converters differ only in the target
25
+ * base, the signed range they accept, and whether the output is
26
+ * uppercased (hex). The `places` semantics (1..10, validated only when
27
+ * supplied and the input is non-negative) are identical across all three.
28
+ *
29
+ * Factored here so the three converters share a single source of truth —
30
+ * when the Excel rules are refined (e.g. additional validations or a new
31
+ * `places` upper bound), all three stay in lockstep.
32
+ */
33
+ function decToBase(args, base, minValue, maxValue) {
34
+ const nRV = (0, values_1.toNumberRV)((0, values_1.topLeft)(args[0]));
31
35
  if ((0, values_1.isError)(nRV)) {
32
36
  return nRV;
33
37
  }
34
38
  // Excel's DEC→BASE family truncates toward zero, so negative fractions
35
39
  // become `0`, not `-1` as `Math.floor` would produce.
36
40
  const n = Math.trunc(nRV.value);
37
- if (n < -512 || n > 511) {
41
+ if (n < minValue || n > maxValue) {
38
42
  return values_1.ERRORS.NUM;
39
43
  }
40
44
  // `places` is only meaningful when supplied and the input is non-negative.
41
- // Excel restricts it to the [1, 10] range and returns #NUM! otherwise.
42
- // For negative inputs Excel ignores `places` entirely, so we validate it
43
- // only on the non-negative branch below.
45
+ // Excel restricts it to [1, 10] and returns #NUM! outside that range.
46
+ // Negative inputs ignore `places` entirely we validate it only when
47
+ // we've confirmed the input is non-negative.
44
48
  const hasPlaces = args.length > 1 && args[1].kind !== 0 /* RVKind.Blank */;
45
- const placesRV = hasPlaces ? (0, values_1.toNumberRV)(args[1]) : (0, values_1.rvNumber)(0);
49
+ const placesRV = hasPlaces ? (0, values_1.toNumberRV)((0, values_1.topLeft)(args[1])) : (0, values_1.rvNumber)(0);
46
50
  if ((0, values_1.isError)(placesRV)) {
47
51
  return placesRV;
48
52
  }
49
53
  const places = Math.trunc(placesRV.value);
54
+ const toUpper = base === 16;
50
55
  if (n < 0) {
51
- return (0, values_1.rvString)((n + 1024).toString(2));
56
+ const raw = (n + Math.pow(base, 10)).toString(base);
57
+ return (0, values_1.rvString)(toUpper ? raw.toUpperCase() : raw);
52
58
  }
53
59
  if (hasPlaces && (places < 1 || places > 10)) {
54
60
  return values_1.ERRORS.NUM;
55
61
  }
56
- const result = n.toString(2);
57
- return (0, values_1.rvString)(places > 0 ? result.padStart(places, "0") : result);
58
- };
59
- exports.fnDEC2BIN = fnDEC2BIN;
60
- const fnHEX2DEC = args => {
61
- const err = (0, _shared_1.checkError)(args[0]);
62
- if (err) {
63
- return err;
64
- }
65
- const s = (0, values_1.toStringRV)(args[0]);
66
- if (!/^[0-9A-Fa-f]{1,10}$/.test(s)) {
62
+ const raw = n.toString(base);
63
+ const result = toUpper ? raw.toUpperCase() : raw;
64
+ // When `places` is supplied but smaller than the natural representation,
65
+ // Excel returns `#NUM!` rather than silently ignoring the width. `padStart`
66
+ // alone would leave the wider result unchanged — a soft deviation.
67
+ if (hasPlaces && places > 0 && result.length > places) {
67
68
  return values_1.ERRORS.NUM;
68
69
  }
69
- const num = parseInt(s, 16);
70
- // 10-digit hex: 40-bit two's complement
71
- if (s.length === 10 && parseInt(s[0], 16) >= 8) {
72
- return (0, values_1.rvNumber)(num - Math.pow(16, 10));
73
- }
74
- return (0, values_1.rvNumber)(num);
75
- };
76
- exports.fnHEX2DEC = fnHEX2DEC;
77
- const fnDEC2HEX = args => {
78
- const nRV = (0, values_1.toNumberRV)(args[0]);
79
- if ((0, values_1.isError)(nRV)) {
80
- return nRV;
81
- }
82
- // Excel's DEC→BASE family truncates toward zero, so negative fractions
83
- // become `0`, not `-1` as `Math.floor` would produce.
84
- const n = Math.trunc(nRV.value);
85
- // Excel rejects anything outside the 40-bit signed range.
86
- // Without this check, inputs like 1e14 produce a 13-digit hex string
87
- // and inputs below -2^39 wrap into spurious positive values prefixed
88
- // with `-`. See R6-P0-1.
89
- if (n < -549755813888 || n > 549755813887) {
90
- return values_1.ERRORS.NUM;
91
- }
92
- // Same places semantics as DEC2BIN: validate only when `places` is
93
- // supplied and the input is non-negative; Excel ignores `places` for
94
- // negative numbers.
95
- const hasPlaces = args.length > 1 && args[1].kind !== 0 /* RVKind.Blank */;
96
- const placesRV = hasPlaces ? (0, values_1.toNumberRV)(args[1]) : (0, values_1.rvNumber)(0);
97
- if ((0, values_1.isError)(placesRV)) {
98
- return placesRV;
99
- }
100
- const places = Math.trunc(placesRV.value);
101
- if (n < 0) {
102
- return (0, values_1.rvString)((n + Math.pow(16, 10)).toString(16).toUpperCase());
103
- }
104
- if (hasPlaces && (places < 1 || places > 10)) {
105
- return values_1.ERRORS.NUM;
106
- }
107
- const result = n.toString(16).toUpperCase();
108
70
  return (0, values_1.rvString)(places > 0 ? result.padStart(places, "0") : result);
109
- };
110
- exports.fnDEC2HEX = fnDEC2HEX;
111
- const fnOCT2DEC = args => {
71
+ }
72
+ const fnHEX2DEC = args => baseToDec(args, 16, /^[0-9A-Fa-f]{1,10}$/);
73
+ exports.fnHEX2DEC = fnHEX2DEC;
74
+ const fnOCT2DEC = args => baseToDec(args, 8, /^[0-7]{1,10}$/);
75
+ exports.fnOCT2DEC = fnOCT2DEC;
76
+ /**
77
+ * Shared implementation of `BIN2DEC`, `OCT2DEC`, `HEX2DEC`.
78
+ *
79
+ * Each source base has the same "string of up to 10 digits, 10th digit
80
+ * sets the sign bit for two's-complement" semantics. The only
81
+ * differences are the allowed digit alphabet (passed as `pattern`) and
82
+ * the base (passed as `base`). The `isNegativeMsd` helper detects the
83
+ * sign bit by re-parsing the top digit; it works for binary (MSD=1),
84
+ * octal (MSD>=4) and hex (MSD>=8).
85
+ */
86
+ function baseToDec(args, base, pattern) {
112
87
  const err = (0, _shared_1.checkError)(args[0]);
113
88
  if (err) {
114
89
  return err;
115
90
  }
116
- const s = (0, values_1.toStringRV)(args[0]);
117
- if (!/^[0-7]{1,10}$/.test(s)) {
91
+ const s = (0, values_1.toStringRV)((0, values_1.topLeft)(args[0]));
92
+ if (!pattern.test(s)) {
118
93
  return values_1.ERRORS.NUM;
119
94
  }
120
- const num = parseInt(s, 8);
121
- if (s.length === 10 && parseInt(s[0]) >= 4) {
122
- return (0, values_1.rvNumber)(num - Math.pow(8, 10));
95
+ const num = parseInt(s, base);
96
+ // 10-digit form triggers two's-complement interpretation. The sign bit
97
+ // is the top bit of the top digit — for binary that's the literal MSD,
98
+ // for octal it's `>= 4`, for hex it's `>= 8`. We compute the threshold
99
+ // from the base instead of hard-coding it.
100
+ if (s.length === 10 && parseInt(s[0], base) >= base / 2) {
101
+ return (0, values_1.rvNumber)(num - Math.pow(base, 10));
123
102
  }
124
103
  return (0, values_1.rvNumber)(num);
125
- };
126
- exports.fnOCT2DEC = fnOCT2DEC;
127
- const fnDEC2OCT = args => {
128
- const nRV = (0, values_1.toNumberRV)(args[0]);
129
- if ((0, values_1.isError)(nRV)) {
130
- return nRV;
131
- }
132
- // Excel's DEC→BASE family truncates toward zero, so negative fractions
133
- // become `0`, not `-1` as `Math.floor` would produce.
134
- const n = Math.trunc(nRV.value);
135
- // Excel's DEC2OCT range is the 30-bit signed range (-2^29 .. 2^29-1).
136
- // Values outside this range are #NUM! in Excel; we silently wrapped
137
- // into bogus sign-prefixed strings without this guard. See R6-P0-1.
138
- if (n < -536870912 || n > 536870911) {
139
- return values_1.ERRORS.NUM;
140
- }
141
- // Same places semantics as DEC2BIN: validate only when `places` is
142
- // supplied and the input is non-negative; Excel ignores `places` for
143
- // negative numbers.
144
- const hasPlaces = args.length > 1 && args[1].kind !== 0 /* RVKind.Blank */;
145
- const placesRV = hasPlaces ? (0, values_1.toNumberRV)(args[1]) : (0, values_1.rvNumber)(0);
146
- if ((0, values_1.isError)(placesRV)) {
147
- return placesRV;
148
- }
149
- const places = Math.trunc(placesRV.value);
150
- if (n < 0) {
151
- return (0, values_1.rvString)((n + Math.pow(8, 10)).toString(8));
152
- }
153
- if (hasPlaces && (places < 1 || places > 10)) {
154
- return values_1.ERRORS.NUM;
155
- }
156
- const result = n.toString(8);
157
- return (0, values_1.rvString)(places > 0 ? result.padStart(places, "0") : result);
158
- };
159
- exports.fnDEC2OCT = fnDEC2OCT;
104
+ }
160
105
  /**
161
106
  * Generic helper for the X2Y conversion family (BIN2HEX, HEX2BIN, …).
162
107
  *
@@ -172,13 +117,13 @@ function convertBase(args, parseNInput, format) {
172
117
  if (err) {
173
118
  return err;
174
119
  }
175
- const s = (0, values_1.toStringRV)(args[0]);
120
+ const s = (0, values_1.toStringRV)((0, values_1.topLeft)(args[0]));
176
121
  const n = parseNInput(s);
177
122
  if (typeof n !== "number") {
178
123
  return n;
179
124
  }
180
125
  const hasPlaces = args.length > 1 && args[1].kind !== 0 /* RVKind.Blank */;
181
- const placesRV = hasPlaces ? (0, values_1.toNumberRV)(args[1]) : (0, values_1.rvNumber)(0);
126
+ const placesRV = hasPlaces ? (0, values_1.toNumberRV)((0, values_1.topLeft)(args[1])) : (0, values_1.rvNumber)(0);
182
127
  if ((0, values_1.isError)(placesRV)) {
183
128
  return placesRV;
184
129
  }
@@ -217,6 +162,11 @@ function formatToBase(n, base, maxDigits, places, hasPlaces) {
217
162
  return values_1.ERRORS.NUM;
218
163
  }
219
164
  const result = n.toString(base).toUpperCase();
165
+ // `places` smaller than the natural representation is a #NUM! in Excel —
166
+ // `padStart` alone would silently emit the wider form.
167
+ if (hasPlaces && places > 0 && result.length > places) {
168
+ return values_1.ERRORS.NUM;
169
+ }
220
170
  return (0, values_1.rvString)(places > 0 ? result.padStart(places, "0") : result);
221
171
  }
222
172
  const fnBIN2HEX = args => convertBase(args, parseBinInput, (n, places, hasPlaces) => formatToBase(n, 16, 10, places, hasPlaces));
@@ -478,11 +428,11 @@ function besselK(n, x) {
478
428
  }
479
429
  /** Common validation + dispatch for the four BESSEL* functions. */
480
430
  function bessel(args, compute, allowZeroX) {
481
- const xRV = (0, values_1.toNumberRV)(args[0]);
431
+ const xRV = (0, values_1.toNumberRV)((0, values_1.topLeft)(args[0]));
482
432
  if ((0, values_1.isError)(xRV)) {
483
433
  return xRV;
484
434
  }
485
- const nRV = (0, values_1.toNumberRV)(args[1]);
435
+ const nRV = (0, values_1.toNumberRV)((0, values_1.topLeft)(args[1]));
486
436
  if ((0, values_1.isError)(nRV)) {
487
437
  return nRV;
488
438
  }
@@ -511,11 +461,11 @@ exports.fnBESSELK = fnBESSELK;
511
461
  const fnBESSELY = args => bessel(args, besselY, false);
512
462
  exports.fnBESSELY = fnBESSELY;
513
463
  const fnDELTA = args => {
514
- const n1 = (0, values_1.toNumberRV)(args[0]);
464
+ const n1 = (0, values_1.toNumberRV)((0, values_1.topLeft)(args[0]));
515
465
  if ((0, values_1.isError)(n1)) {
516
466
  return n1;
517
467
  }
518
- const n2 = args.length > 1 ? (0, values_1.toNumberRV)(args[1]) : (0, values_1.rvNumber)(0);
468
+ const n2 = args.length > 1 ? (0, values_1.toNumberRV)((0, values_1.topLeft)(args[1])) : (0, values_1.rvNumber)(0);
519
469
  if ((0, values_1.isError)(n2)) {
520
470
  return n2;
521
471
  }
@@ -523,11 +473,11 @@ const fnDELTA = args => {
523
473
  };
524
474
  exports.fnDELTA = fnDELTA;
525
475
  const fnGESTEP = args => {
526
- const n = (0, values_1.toNumberRV)(args[0]);
476
+ const n = (0, values_1.toNumberRV)((0, values_1.topLeft)(args[0]));
527
477
  if ((0, values_1.isError)(n)) {
528
478
  return n;
529
479
  }
530
- const step = args.length > 1 ? (0, values_1.toNumberRV)(args[1]) : (0, values_1.rvNumber)(0);
480
+ const step = args.length > 1 ? (0, values_1.toNumberRV)((0, values_1.topLeft)(args[1])) : (0, values_1.rvNumber)(0);
531
481
  if ((0, values_1.isError)(step)) {
532
482
  return step;
533
483
  }
@@ -610,22 +560,24 @@ function formatComplex(re, im, suffix = "i") {
610
560
  return re + imStr;
611
561
  }
612
562
  const fnCOMPLEX = args => {
613
- const re = (0, values_1.toNumberRV)(args[0]);
563
+ const re = (0, values_1.toNumberRV)((0, values_1.topLeft)(args[0]));
614
564
  if ((0, values_1.isError)(re)) {
615
565
  return re;
616
566
  }
617
- const im = (0, values_1.toNumberRV)(args[1]);
567
+ const im = (0, values_1.toNumberRV)((0, values_1.topLeft)(args[1]));
618
568
  if ((0, values_1.isError)(im)) {
619
569
  return im;
620
570
  }
621
571
  let suffix = "i";
622
- if (args.length > 2) {
572
+ if (args.length > 2 && args[2].kind !== 0 /* RVKind.Blank */) {
623
573
  const e2 = (0, _shared_1.checkError)(args[2]);
624
574
  if (e2) {
625
575
  return e2;
626
576
  }
627
- suffix = (0, values_1.toStringRV)(args[2]);
577
+ suffix = (0, values_1.toStringRV)((0, values_1.topLeft)(args[2]));
628
578
  }
579
+ // Blank 3rd arg → default "i". Previously a blank coerced to empty
580
+ // string then tripped the `suffix !== "i"` validation.
629
581
  if (suffix !== "i" && suffix !== "j") {
630
582
  return values_1.ERRORS.VALUE;
631
583
  }
@@ -637,7 +589,7 @@ const fnIMREAL = args => {
637
589
  if (err) {
638
590
  return err;
639
591
  }
640
- const c = parseComplex((0, values_1.toStringRV)(args[0]));
592
+ const c = parseComplex((0, values_1.toStringRV)((0, values_1.topLeft)(args[0])));
641
593
  return c ? (0, values_1.rvNumber)(c[0]) : values_1.ERRORS.NUM;
642
594
  };
643
595
  exports.fnIMREAL = fnIMREAL;
@@ -646,7 +598,7 @@ const fnIMAGINARY = args => {
646
598
  if (err) {
647
599
  return err;
648
600
  }
649
- const c = parseComplex((0, values_1.toStringRV)(args[0]));
601
+ const c = parseComplex((0, values_1.toStringRV)((0, values_1.topLeft)(args[0])));
650
602
  return c ? (0, values_1.rvNumber)(c[1]) : values_1.ERRORS.NUM;
651
603
  };
652
604
  exports.fnIMAGINARY = fnIMAGINARY;
@@ -655,7 +607,7 @@ const fnIMABS = args => {
655
607
  if (err) {
656
608
  return err;
657
609
  }
658
- const c = parseComplex((0, values_1.toStringRV)(args[0]));
610
+ const c = parseComplex((0, values_1.toStringRV)((0, values_1.topLeft)(args[0])));
659
611
  if (!c) {
660
612
  return values_1.ERRORS.NUM;
661
613
  }
@@ -667,7 +619,7 @@ const fnIMARGUMENT = args => {
667
619
  if (err) {
668
620
  return err;
669
621
  }
670
- const c = parseComplex((0, values_1.toStringRV)(args[0]));
622
+ const c = parseComplex((0, values_1.toStringRV)((0, values_1.topLeft)(args[0])));
671
623
  if (!c) {
672
624
  return values_1.ERRORS.NUM;
673
625
  }
@@ -682,7 +634,7 @@ const fnIMCONJUGATE = args => {
682
634
  if (err) {
683
635
  return err;
684
636
  }
685
- const c = parseComplex((0, values_1.toStringRV)(args[0]));
637
+ const c = parseComplex((0, values_1.toStringRV)((0, values_1.topLeft)(args[0])));
686
638
  if (!c) {
687
639
  return values_1.ERRORS.NUM;
688
640
  }
@@ -764,8 +716,8 @@ const fnIMSUB = args => {
764
716
  if (e1) {
765
717
  return e1;
766
718
  }
767
- const c1 = parseComplex((0, values_1.toStringRV)(args[0]));
768
- const c2 = parseComplex((0, values_1.toStringRV)(args[1]));
719
+ const c1 = parseComplex((0, values_1.toStringRV)((0, values_1.topLeft)(args[0])));
720
+ const c2 = parseComplex((0, values_1.toStringRV)((0, values_1.topLeft)(args[1])));
769
721
  if (!c1 || !c2) {
770
722
  return values_1.ERRORS.NUM;
771
723
  }
@@ -802,8 +754,8 @@ const fnIMDIV = args => {
802
754
  if (e1) {
803
755
  return e1;
804
756
  }
805
- const c1 = parseComplex((0, values_1.toStringRV)(args[0]));
806
- const c2 = parseComplex((0, values_1.toStringRV)(args[1]));
757
+ const c1 = parseComplex((0, values_1.toStringRV)((0, values_1.topLeft)(args[0])));
758
+ const c2 = parseComplex((0, values_1.toStringRV)((0, values_1.topLeft)(args[1])));
807
759
  if (!c1 || !c2) {
808
760
  return values_1.ERRORS.NUM;
809
761
  }
@@ -824,11 +776,11 @@ const fnIMPOWER = args => {
824
776
  if (err) {
825
777
  return err;
826
778
  }
827
- const c = parseComplex((0, values_1.toStringRV)(args[0]));
779
+ const c = parseComplex((0, values_1.toStringRV)((0, values_1.topLeft)(args[0])));
828
780
  if (!c) {
829
781
  return values_1.ERRORS.NUM;
830
782
  }
831
- const n = (0, values_1.toNumberRV)(args[1]);
783
+ const n = (0, values_1.toNumberRV)((0, values_1.topLeft)(args[1]));
832
784
  if ((0, values_1.isError)(n)) {
833
785
  return n;
834
786
  }
@@ -843,7 +795,7 @@ const fnIMSQRT = args => {
843
795
  if (err) {
844
796
  return err;
845
797
  }
846
- const c = parseComplex((0, values_1.toStringRV)(args[0]));
798
+ const c = parseComplex((0, values_1.toStringRV)((0, values_1.topLeft)(args[0])));
847
799
  if (!c) {
848
800
  return values_1.ERRORS.NUM;
849
801
  }
@@ -858,7 +810,7 @@ const fnIMLN = args => {
858
810
  if (err) {
859
811
  return err;
860
812
  }
861
- const c = parseComplex((0, values_1.toStringRV)(args[0]));
813
+ const c = parseComplex((0, values_1.toStringRV)((0, values_1.topLeft)(args[0])));
862
814
  if (!c) {
863
815
  return values_1.ERRORS.NUM;
864
816
  }
@@ -874,7 +826,7 @@ const fnIMLOG2 = args => {
874
826
  if (err) {
875
827
  return err;
876
828
  }
877
- const c = parseComplex((0, values_1.toStringRV)(args[0]));
829
+ const c = parseComplex((0, values_1.toStringRV)((0, values_1.topLeft)(args[0])));
878
830
  if (!c) {
879
831
  return values_1.ERRORS.NUM;
880
832
  }
@@ -891,7 +843,7 @@ const fnIMLOG10 = args => {
891
843
  if (err) {
892
844
  return err;
893
845
  }
894
- const c = parseComplex((0, values_1.toStringRV)(args[0]));
846
+ const c = parseComplex((0, values_1.toStringRV)((0, values_1.topLeft)(args[0])));
895
847
  if (!c) {
896
848
  return values_1.ERRORS.NUM;
897
849
  }
@@ -908,7 +860,7 @@ const fnIMEXP = args => {
908
860
  if (err) {
909
861
  return err;
910
862
  }
911
- const c = parseComplex((0, values_1.toStringRV)(args[0]));
863
+ const c = parseComplex((0, values_1.toStringRV)((0, values_1.topLeft)(args[0])));
912
864
  if (!c) {
913
865
  return values_1.ERRORS.NUM;
914
866
  }
@@ -921,7 +873,7 @@ const fnIMSIN = args => {
921
873
  if (err) {
922
874
  return err;
923
875
  }
924
- const c = parseComplex((0, values_1.toStringRV)(args[0]));
876
+ const c = parseComplex((0, values_1.toStringRV)((0, values_1.topLeft)(args[0])));
925
877
  if (!c) {
926
878
  return values_1.ERRORS.NUM;
927
879
  }
@@ -933,7 +885,7 @@ const fnIMCOS = args => {
933
885
  if (err) {
934
886
  return err;
935
887
  }
936
- const c = parseComplex((0, values_1.toStringRV)(args[0]));
888
+ const c = parseComplex((0, values_1.toStringRV)((0, values_1.topLeft)(args[0])));
937
889
  if (!c) {
938
890
  return values_1.ERRORS.NUM;
939
891
  }
@@ -1074,11 +1026,11 @@ function validateBitOperand(v) {
1074
1026
  return v;
1075
1027
  }
1076
1028
  const fnBITAND = args => {
1077
- const a = (0, values_1.toNumberRV)(args[0]);
1029
+ const a = (0, values_1.toNumberRV)((0, values_1.topLeft)(args[0]));
1078
1030
  if ((0, values_1.isError)(a)) {
1079
1031
  return a;
1080
1032
  }
1081
- const b = (0, values_1.toNumberRV)(args[1]);
1033
+ const b = (0, values_1.toNumberRV)((0, values_1.topLeft)(args[1]));
1082
1034
  if ((0, values_1.isError)(b)) {
1083
1035
  return b;
1084
1036
  }
@@ -1094,11 +1046,11 @@ const fnBITAND = args => {
1094
1046
  };
1095
1047
  exports.fnBITAND = fnBITAND;
1096
1048
  const fnBITOR = args => {
1097
- const a = (0, values_1.toNumberRV)(args[0]);
1049
+ const a = (0, values_1.toNumberRV)((0, values_1.topLeft)(args[0]));
1098
1050
  if ((0, values_1.isError)(a)) {
1099
1051
  return a;
1100
1052
  }
1101
- const b = (0, values_1.toNumberRV)(args[1]);
1053
+ const b = (0, values_1.toNumberRV)((0, values_1.topLeft)(args[1]));
1102
1054
  if ((0, values_1.isError)(b)) {
1103
1055
  return b;
1104
1056
  }
@@ -1114,11 +1066,11 @@ const fnBITOR = args => {
1114
1066
  };
1115
1067
  exports.fnBITOR = fnBITOR;
1116
1068
  const fnBITXOR = args => {
1117
- const a = (0, values_1.toNumberRV)(args[0]);
1069
+ const a = (0, values_1.toNumberRV)((0, values_1.topLeft)(args[0]));
1118
1070
  if ((0, values_1.isError)(a)) {
1119
1071
  return a;
1120
1072
  }
1121
- const b = (0, values_1.toNumberRV)(args[1]);
1073
+ const b = (0, values_1.toNumberRV)((0, values_1.topLeft)(args[1]));
1122
1074
  if ((0, values_1.isError)(b)) {
1123
1075
  return b;
1124
1076
  }
@@ -1134,11 +1086,11 @@ const fnBITXOR = args => {
1134
1086
  };
1135
1087
  exports.fnBITXOR = fnBITXOR;
1136
1088
  const fnBITLSHIFT = args => {
1137
- const num = (0, values_1.toNumberRV)(args[0]);
1089
+ const num = (0, values_1.toNumberRV)((0, values_1.topLeft)(args[0]));
1138
1090
  if ((0, values_1.isError)(num)) {
1139
1091
  return num;
1140
1092
  }
1141
- const shift = (0, values_1.toNumberRV)(args[1]);
1093
+ const shift = (0, values_1.toNumberRV)((0, values_1.topLeft)(args[1]));
1142
1094
  if ((0, values_1.isError)(shift)) {
1143
1095
  return shift;
1144
1096
  }
@@ -1158,11 +1110,11 @@ const fnBITLSHIFT = args => {
1158
1110
  };
1159
1111
  exports.fnBITLSHIFT = fnBITLSHIFT;
1160
1112
  const fnBITRSHIFT = args => {
1161
- const num = (0, values_1.toNumberRV)(args[0]);
1113
+ const num = (0, values_1.toNumberRV)((0, values_1.topLeft)(args[0]));
1162
1114
  if ((0, values_1.isError)(num)) {
1163
1115
  return num;
1164
1116
  }
1165
- const shift = (0, values_1.toNumberRV)(args[1]);
1117
+ const shift = (0, values_1.toNumberRV)((0, values_1.topLeft)(args[1]));
1166
1118
  if ((0, values_1.isError)(shift)) {
1167
1119
  return shift;
1168
1120
  }