@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.
- package/dist/browser/index.d.ts +1 -0
- package/dist/browser/index.js +2 -0
- package/dist/browser/modules/excel/cell.d.ts +18 -0
- package/dist/browser/modules/excel/cell.js +21 -0
- package/dist/browser/modules/excel/utils/cell-format.js +85 -13
- package/dist/browser/modules/excel/workbook.browser.d.ts +57 -0
- package/dist/browser/modules/excel/workbook.browser.js +49 -0
- package/dist/browser/modules/excel/xlsx/defaultnumformats.js +3 -3
- package/dist/browser/modules/formula/compile/binder.js +48 -6
- package/dist/browser/modules/formula/compile/bound-ast.d.ts +16 -2
- package/dist/browser/modules/formula/compile/bound-ast.js +1 -0
- package/dist/browser/modules/formula/compile/compiled-formula.js +41 -8
- package/dist/browser/modules/formula/functions/_shared.d.ts +19 -0
- package/dist/browser/modules/formula/functions/_shared.js +47 -0
- package/dist/browser/modules/formula/functions/conditional.js +103 -22
- package/dist/browser/modules/formula/functions/date.js +105 -23
- package/dist/browser/modules/formula/functions/dynamic-array.js +173 -69
- package/dist/browser/modules/formula/functions/engineering.d.ts +2 -2
- package/dist/browser/modules/formula/functions/engineering.js +103 -151
- package/dist/browser/modules/formula/functions/financial.js +210 -184
- package/dist/browser/modules/formula/functions/lookup.js +224 -157
- package/dist/browser/modules/formula/functions/math.d.ts +26 -0
- package/dist/browser/modules/formula/functions/math.js +249 -69
- package/dist/browser/modules/formula/functions/statistical.js +221 -171
- package/dist/browser/modules/formula/functions/text.js +112 -52
- package/dist/browser/modules/formula/integration/calculate-formulas-impl.js +20 -1
- package/dist/browser/modules/formula/materialize/build-writeback-plan.js +10 -6
- package/dist/browser/modules/formula/materialize/types.d.ts +15 -0
- package/dist/browser/modules/formula/runtime/evaluator.d.ts +8 -0
- package/dist/browser/modules/formula/runtime/evaluator.js +582 -162
- package/dist/browser/modules/formula/runtime/function-registry.d.ts +5 -0
- package/dist/browser/modules/formula/runtime/function-registry.js +59 -13
- package/dist/browser/modules/formula/runtime/values.d.ts +13 -0
- package/dist/browser/modules/formula/runtime/values.js +20 -2
- package/dist/browser/modules/formula/syntax/ast.d.ts +14 -2
- package/dist/browser/modules/formula/syntax/ast.js +1 -0
- package/dist/browser/modules/formula/syntax/parser.js +29 -7
- package/dist/browser/modules/formula/syntax/token-types.d.ts +4 -0
- package/dist/browser/modules/formula/syntax/token-types.js +9 -0
- package/dist/browser/modules/formula/syntax/tokenizer.js +76 -19
- package/dist/cjs/index.js +7 -2
- package/dist/cjs/modules/excel/cell.js +21 -0
- package/dist/cjs/modules/excel/utils/cell-format.js +85 -13
- package/dist/cjs/modules/excel/workbook.browser.js +49 -0
- package/dist/cjs/modules/excel/xlsx/defaultnumformats.js +3 -3
- package/dist/cjs/modules/formula/compile/binder.js +48 -6
- package/dist/cjs/modules/formula/compile/compiled-formula.js +41 -8
- package/dist/cjs/modules/formula/functions/_shared.js +48 -0
- package/dist/cjs/modules/formula/functions/conditional.js +103 -22
- package/dist/cjs/modules/formula/functions/date.js +104 -22
- package/dist/cjs/modules/formula/functions/dynamic-array.js +173 -69
- package/dist/cjs/modules/formula/functions/engineering.js +109 -157
- package/dist/cjs/modules/formula/functions/financial.js +209 -183
- package/dist/cjs/modules/formula/functions/lookup.js +224 -157
- package/dist/cjs/modules/formula/functions/math.js +254 -70
- package/dist/cjs/modules/formula/functions/statistical.js +222 -172
- package/dist/cjs/modules/formula/functions/text.js +112 -52
- package/dist/cjs/modules/formula/integration/calculate-formulas-impl.js +20 -1
- package/dist/cjs/modules/formula/materialize/build-writeback-plan.js +10 -6
- package/dist/cjs/modules/formula/runtime/evaluator.js +581 -161
- package/dist/cjs/modules/formula/runtime/function-registry.js +57 -11
- package/dist/cjs/modules/formula/runtime/values.js +21 -2
- package/dist/cjs/modules/formula/syntax/parser.js +29 -7
- package/dist/cjs/modules/formula/syntax/token-types.js +9 -0
- package/dist/cjs/modules/formula/syntax/tokenizer.js +76 -19
- package/dist/esm/index.js +2 -0
- package/dist/esm/modules/excel/cell.js +21 -0
- package/dist/esm/modules/excel/utils/cell-format.js +85 -13
- package/dist/esm/modules/excel/workbook.browser.js +49 -0
- package/dist/esm/modules/excel/xlsx/defaultnumformats.js +3 -3
- package/dist/esm/modules/formula/compile/binder.js +48 -6
- package/dist/esm/modules/formula/compile/bound-ast.js +1 -0
- package/dist/esm/modules/formula/compile/compiled-formula.js +41 -8
- package/dist/esm/modules/formula/functions/_shared.js +47 -0
- package/dist/esm/modules/formula/functions/conditional.js +103 -22
- package/dist/esm/modules/formula/functions/date.js +105 -23
- package/dist/esm/modules/formula/functions/dynamic-array.js +173 -69
- package/dist/esm/modules/formula/functions/engineering.js +103 -151
- package/dist/esm/modules/formula/functions/financial.js +210 -184
- package/dist/esm/modules/formula/functions/lookup.js +224 -157
- package/dist/esm/modules/formula/functions/math.js +249 -69
- package/dist/esm/modules/formula/functions/statistical.js +221 -171
- package/dist/esm/modules/formula/functions/text.js +112 -52
- package/dist/esm/modules/formula/integration/calculate-formulas-impl.js +20 -1
- package/dist/esm/modules/formula/materialize/build-writeback-plan.js +10 -6
- package/dist/esm/modules/formula/runtime/evaluator.js +582 -162
- package/dist/esm/modules/formula/runtime/function-registry.js +59 -13
- package/dist/esm/modules/formula/runtime/values.js +20 -2
- package/dist/esm/modules/formula/syntax/ast.js +1 -0
- package/dist/esm/modules/formula/syntax/parser.js +29 -7
- package/dist/esm/modules/formula/syntax/token-types.js +9 -0
- package/dist/esm/modules/formula/syntax/tokenizer.js +76 -19
- package/dist/iife/excelts.iife.js +1502 -1379
- package/dist/iife/excelts.iife.js.map +1 -1
- package/dist/iife/excelts.iife.min.js +26 -26
- package/dist/types/index.d.ts +1 -0
- package/dist/types/modules/excel/cell.d.ts +18 -0
- package/dist/types/modules/excel/workbook.browser.d.ts +57 -0
- package/dist/types/modules/formula/compile/bound-ast.d.ts +16 -2
- package/dist/types/modules/formula/functions/_shared.d.ts +19 -0
- package/dist/types/modules/formula/functions/engineering.d.ts +2 -2
- package/dist/types/modules/formula/functions/math.d.ts +26 -0
- package/dist/types/modules/formula/materialize/types.d.ts +15 -0
- package/dist/types/modules/formula/runtime/evaluator.d.ts +8 -0
- package/dist/types/modules/formula/runtime/function-registry.d.ts +5 -0
- package/dist/types/modules/formula/runtime/values.d.ts +13 -0
- package/dist/types/modules/formula/syntax/ast.d.ts +14 -2
- package/dist/types/modules/formula/syntax/token-types.d.ts +4 -0
- package/package.json +1 -1
|
@@ -6,147 +6,92 @@ import { checkError } from "./_shared.js";
|
|
|
6
6
|
// ============================================================================
|
|
7
7
|
// Base Conversion Functions
|
|
8
8
|
// ============================================================================
|
|
9
|
-
export const fnBIN2DEC = args => {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
9
|
+
export const fnBIN2DEC = args => baseToDec(args, 2, /^[01]{1,10}$/);
|
|
10
|
+
export const fnDEC2BIN = args => decToBase(args, 2, -512, 511);
|
|
11
|
+
export const fnDEC2HEX = args => decToBase(args, 16, -549755813888, 549755813887);
|
|
12
|
+
export const fnDEC2OCT = args => decToBase(args, 8, -536870912, 536870911);
|
|
13
|
+
/**
|
|
14
|
+
* Shared implementation of `DEC2BIN`, `DEC2HEX`, `DEC2OCT`.
|
|
15
|
+
*
|
|
16
|
+
* Excel's three numeric-to-base converters differ only in the target
|
|
17
|
+
* base, the signed range they accept, and whether the output is
|
|
18
|
+
* uppercased (hex). The `places` semantics (1..10, validated only when
|
|
19
|
+
* supplied and the input is non-negative) are identical across all three.
|
|
20
|
+
*
|
|
21
|
+
* Factored here so the three converters share a single source of truth —
|
|
22
|
+
* when the Excel rules are refined (e.g. additional validations or a new
|
|
23
|
+
* `places` upper bound), all three stay in lockstep.
|
|
24
|
+
*/
|
|
25
|
+
function decToBase(args, base, minValue, maxValue) {
|
|
26
|
+
const nRV = toNumberRV(topLeft(args[0]));
|
|
26
27
|
if (isError(nRV)) {
|
|
27
28
|
return nRV;
|
|
28
29
|
}
|
|
29
30
|
// Excel's DEC→BASE family truncates toward zero, so negative fractions
|
|
30
31
|
// become `0`, not `-1` as `Math.floor` would produce.
|
|
31
32
|
const n = Math.trunc(nRV.value);
|
|
32
|
-
if (n <
|
|
33
|
+
if (n < minValue || n > maxValue) {
|
|
33
34
|
return ERRORS.NUM;
|
|
34
35
|
}
|
|
35
36
|
// `places` is only meaningful when supplied and the input is non-negative.
|
|
36
|
-
// Excel restricts it to
|
|
37
|
-
//
|
|
38
|
-
//
|
|
37
|
+
// Excel restricts it to [1, 10] and returns #NUM! outside that range.
|
|
38
|
+
// Negative inputs ignore `places` entirely — we validate it only when
|
|
39
|
+
// we've confirmed the input is non-negative.
|
|
39
40
|
const hasPlaces = args.length > 1 && args[1].kind !== RVKind.Blank;
|
|
40
|
-
const placesRV = hasPlaces ? toNumberRV(args[1]) : rvNumber(0);
|
|
41
|
+
const placesRV = hasPlaces ? toNumberRV(topLeft(args[1])) : rvNumber(0);
|
|
41
42
|
if (isError(placesRV)) {
|
|
42
43
|
return placesRV;
|
|
43
44
|
}
|
|
44
45
|
const places = Math.trunc(placesRV.value);
|
|
46
|
+
const toUpper = base === 16;
|
|
45
47
|
if (n < 0) {
|
|
46
|
-
|
|
48
|
+
const raw = (n + Math.pow(base, 10)).toString(base);
|
|
49
|
+
return rvString(toUpper ? raw.toUpperCase() : raw);
|
|
47
50
|
}
|
|
48
51
|
if (hasPlaces && (places < 1 || places > 10)) {
|
|
49
52
|
return ERRORS.NUM;
|
|
50
53
|
}
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (
|
|
57
|
-
return err;
|
|
58
|
-
}
|
|
59
|
-
const s = toStringRV(args[0]);
|
|
60
|
-
if (!/^[0-9A-Fa-f]{1,10}$/.test(s)) {
|
|
61
|
-
return ERRORS.NUM;
|
|
62
|
-
}
|
|
63
|
-
const num = parseInt(s, 16);
|
|
64
|
-
// 10-digit hex: 40-bit two's complement
|
|
65
|
-
if (s.length === 10 && parseInt(s[0], 16) >= 8) {
|
|
66
|
-
return rvNumber(num - Math.pow(16, 10));
|
|
67
|
-
}
|
|
68
|
-
return rvNumber(num);
|
|
69
|
-
};
|
|
70
|
-
export const fnDEC2HEX = args => {
|
|
71
|
-
const nRV = toNumberRV(args[0]);
|
|
72
|
-
if (isError(nRV)) {
|
|
73
|
-
return nRV;
|
|
74
|
-
}
|
|
75
|
-
// Excel's DEC→BASE family truncates toward zero, so negative fractions
|
|
76
|
-
// become `0`, not `-1` as `Math.floor` would produce.
|
|
77
|
-
const n = Math.trunc(nRV.value);
|
|
78
|
-
// Excel rejects anything outside the 40-bit signed range.
|
|
79
|
-
// Without this check, inputs like 1e14 produce a 13-digit hex string
|
|
80
|
-
// and inputs below -2^39 wrap into spurious positive values prefixed
|
|
81
|
-
// with `-`. See R6-P0-1.
|
|
82
|
-
if (n < -549755813888 || n > 549755813887) {
|
|
54
|
+
const raw = n.toString(base);
|
|
55
|
+
const result = toUpper ? raw.toUpperCase() : raw;
|
|
56
|
+
// When `places` is supplied but smaller than the natural representation,
|
|
57
|
+
// Excel returns `#NUM!` rather than silently ignoring the width. `padStart`
|
|
58
|
+
// alone would leave the wider result unchanged — a soft deviation.
|
|
59
|
+
if (hasPlaces && places > 0 && result.length > places) {
|
|
83
60
|
return ERRORS.NUM;
|
|
84
61
|
}
|
|
85
|
-
// Same places semantics as DEC2BIN: validate only when `places` is
|
|
86
|
-
// supplied and the input is non-negative; Excel ignores `places` for
|
|
87
|
-
// negative numbers.
|
|
88
|
-
const hasPlaces = args.length > 1 && args[1].kind !== RVKind.Blank;
|
|
89
|
-
const placesRV = hasPlaces ? toNumberRV(args[1]) : rvNumber(0);
|
|
90
|
-
if (isError(placesRV)) {
|
|
91
|
-
return placesRV;
|
|
92
|
-
}
|
|
93
|
-
const places = Math.trunc(placesRV.value);
|
|
94
|
-
if (n < 0) {
|
|
95
|
-
return rvString((n + Math.pow(16, 10)).toString(16).toUpperCase());
|
|
96
|
-
}
|
|
97
|
-
if (hasPlaces && (places < 1 || places > 10)) {
|
|
98
|
-
return ERRORS.NUM;
|
|
99
|
-
}
|
|
100
|
-
const result = n.toString(16).toUpperCase();
|
|
101
62
|
return rvString(places > 0 ? result.padStart(places, "0") : result);
|
|
102
|
-
}
|
|
103
|
-
export const
|
|
63
|
+
}
|
|
64
|
+
export const fnHEX2DEC = args => baseToDec(args, 16, /^[0-9A-Fa-f]{1,10}$/);
|
|
65
|
+
export const fnOCT2DEC = args => baseToDec(args, 8, /^[0-7]{1,10}$/);
|
|
66
|
+
/**
|
|
67
|
+
* Shared implementation of `BIN2DEC`, `OCT2DEC`, `HEX2DEC`.
|
|
68
|
+
*
|
|
69
|
+
* Each source base has the same "string of up to 10 digits, 10th digit
|
|
70
|
+
* sets the sign bit for two's-complement" semantics. The only
|
|
71
|
+
* differences are the allowed digit alphabet (passed as `pattern`) and
|
|
72
|
+
* the base (passed as `base`). The `isNegativeMsd` helper detects the
|
|
73
|
+
* sign bit by re-parsing the top digit; it works for binary (MSD=1),
|
|
74
|
+
* octal (MSD>=4) and hex (MSD>=8).
|
|
75
|
+
*/
|
|
76
|
+
function baseToDec(args, base, pattern) {
|
|
104
77
|
const err = checkError(args[0]);
|
|
105
78
|
if (err) {
|
|
106
79
|
return err;
|
|
107
80
|
}
|
|
108
|
-
const s = toStringRV(args[0]);
|
|
109
|
-
if (
|
|
81
|
+
const s = toStringRV(topLeft(args[0]));
|
|
82
|
+
if (!pattern.test(s)) {
|
|
110
83
|
return ERRORS.NUM;
|
|
111
84
|
}
|
|
112
|
-
const num = parseInt(s,
|
|
113
|
-
|
|
114
|
-
|
|
85
|
+
const num = parseInt(s, base);
|
|
86
|
+
// 10-digit form triggers two's-complement interpretation. The sign bit
|
|
87
|
+
// is the top bit of the top digit — for binary that's the literal MSD,
|
|
88
|
+
// for octal it's `>= 4`, for hex it's `>= 8`. We compute the threshold
|
|
89
|
+
// from the base instead of hard-coding it.
|
|
90
|
+
if (s.length === 10 && parseInt(s[0], base) >= base / 2) {
|
|
91
|
+
return rvNumber(num - Math.pow(base, 10));
|
|
115
92
|
}
|
|
116
93
|
return rvNumber(num);
|
|
117
|
-
}
|
|
118
|
-
export const fnDEC2OCT = args => {
|
|
119
|
-
const nRV = toNumberRV(args[0]);
|
|
120
|
-
if (isError(nRV)) {
|
|
121
|
-
return nRV;
|
|
122
|
-
}
|
|
123
|
-
// Excel's DEC→BASE family truncates toward zero, so negative fractions
|
|
124
|
-
// become `0`, not `-1` as `Math.floor` would produce.
|
|
125
|
-
const n = Math.trunc(nRV.value);
|
|
126
|
-
// Excel's DEC2OCT range is the 30-bit signed range (-2^29 .. 2^29-1).
|
|
127
|
-
// Values outside this range are #NUM! in Excel; we silently wrapped
|
|
128
|
-
// into bogus sign-prefixed strings without this guard. See R6-P0-1.
|
|
129
|
-
if (n < -536870912 || n > 536870911) {
|
|
130
|
-
return ERRORS.NUM;
|
|
131
|
-
}
|
|
132
|
-
// Same places semantics as DEC2BIN: validate only when `places` is
|
|
133
|
-
// supplied and the input is non-negative; Excel ignores `places` for
|
|
134
|
-
// negative numbers.
|
|
135
|
-
const hasPlaces = args.length > 1 && args[1].kind !== RVKind.Blank;
|
|
136
|
-
const placesRV = hasPlaces ? toNumberRV(args[1]) : rvNumber(0);
|
|
137
|
-
if (isError(placesRV)) {
|
|
138
|
-
return placesRV;
|
|
139
|
-
}
|
|
140
|
-
const places = Math.trunc(placesRV.value);
|
|
141
|
-
if (n < 0) {
|
|
142
|
-
return rvString((n + Math.pow(8, 10)).toString(8));
|
|
143
|
-
}
|
|
144
|
-
if (hasPlaces && (places < 1 || places > 10)) {
|
|
145
|
-
return ERRORS.NUM;
|
|
146
|
-
}
|
|
147
|
-
const result = n.toString(8);
|
|
148
|
-
return rvString(places > 0 ? result.padStart(places, "0") : result);
|
|
149
|
-
};
|
|
94
|
+
}
|
|
150
95
|
/**
|
|
151
96
|
* Generic helper for the X2Y conversion family (BIN2HEX, HEX2BIN, …).
|
|
152
97
|
*
|
|
@@ -162,13 +107,13 @@ function convertBase(args, parseNInput, format) {
|
|
|
162
107
|
if (err) {
|
|
163
108
|
return err;
|
|
164
109
|
}
|
|
165
|
-
const s = toStringRV(args[0]);
|
|
110
|
+
const s = toStringRV(topLeft(args[0]));
|
|
166
111
|
const n = parseNInput(s);
|
|
167
112
|
if (typeof n !== "number") {
|
|
168
113
|
return n;
|
|
169
114
|
}
|
|
170
115
|
const hasPlaces = args.length > 1 && args[1].kind !== RVKind.Blank;
|
|
171
|
-
const placesRV = hasPlaces ? toNumberRV(args[1]) : rvNumber(0);
|
|
116
|
+
const placesRV = hasPlaces ? toNumberRV(topLeft(args[1])) : rvNumber(0);
|
|
172
117
|
if (isError(placesRV)) {
|
|
173
118
|
return placesRV;
|
|
174
119
|
}
|
|
@@ -207,6 +152,11 @@ function formatToBase(n, base, maxDigits, places, hasPlaces) {
|
|
|
207
152
|
return ERRORS.NUM;
|
|
208
153
|
}
|
|
209
154
|
const result = n.toString(base).toUpperCase();
|
|
155
|
+
// `places` smaller than the natural representation is a #NUM! in Excel —
|
|
156
|
+
// `padStart` alone would silently emit the wider form.
|
|
157
|
+
if (hasPlaces && places > 0 && result.length > places) {
|
|
158
|
+
return ERRORS.NUM;
|
|
159
|
+
}
|
|
210
160
|
return rvString(places > 0 ? result.padStart(places, "0") : result);
|
|
211
161
|
}
|
|
212
162
|
export const fnBIN2HEX = args => convertBase(args, parseBinInput, (n, places, hasPlaces) => formatToBase(n, 16, 10, places, hasPlaces));
|
|
@@ -462,11 +412,11 @@ function besselK(n, x) {
|
|
|
462
412
|
}
|
|
463
413
|
/** Common validation + dispatch for the four BESSEL* functions. */
|
|
464
414
|
function bessel(args, compute, allowZeroX) {
|
|
465
|
-
const xRV = toNumberRV(args[0]);
|
|
415
|
+
const xRV = toNumberRV(topLeft(args[0]));
|
|
466
416
|
if (isError(xRV)) {
|
|
467
417
|
return xRV;
|
|
468
418
|
}
|
|
469
|
-
const nRV = toNumberRV(args[1]);
|
|
419
|
+
const nRV = toNumberRV(topLeft(args[1]));
|
|
470
420
|
if (isError(nRV)) {
|
|
471
421
|
return nRV;
|
|
472
422
|
}
|
|
@@ -491,22 +441,22 @@ export const fnBESSELI = args => bessel(args, besselI, true);
|
|
|
491
441
|
export const fnBESSELK = args => bessel(args, besselK, false);
|
|
492
442
|
export const fnBESSELY = args => bessel(args, besselY, false);
|
|
493
443
|
export const fnDELTA = args => {
|
|
494
|
-
const n1 = toNumberRV(args[0]);
|
|
444
|
+
const n1 = toNumberRV(topLeft(args[0]));
|
|
495
445
|
if (isError(n1)) {
|
|
496
446
|
return n1;
|
|
497
447
|
}
|
|
498
|
-
const n2 = args.length > 1 ? toNumberRV(args[1]) : rvNumber(0);
|
|
448
|
+
const n2 = args.length > 1 ? toNumberRV(topLeft(args[1])) : rvNumber(0);
|
|
499
449
|
if (isError(n2)) {
|
|
500
450
|
return n2;
|
|
501
451
|
}
|
|
502
452
|
return rvNumber(n1.value === n2.value ? 1 : 0);
|
|
503
453
|
};
|
|
504
454
|
export const fnGESTEP = args => {
|
|
505
|
-
const n = toNumberRV(args[0]);
|
|
455
|
+
const n = toNumberRV(topLeft(args[0]));
|
|
506
456
|
if (isError(n)) {
|
|
507
457
|
return n;
|
|
508
458
|
}
|
|
509
|
-
const step = args.length > 1 ? toNumberRV(args[1]) : rvNumber(0);
|
|
459
|
+
const step = args.length > 1 ? toNumberRV(topLeft(args[1])) : rvNumber(0);
|
|
510
460
|
if (isError(step)) {
|
|
511
461
|
return step;
|
|
512
462
|
}
|
|
@@ -588,22 +538,24 @@ function formatComplex(re, im, suffix = "i") {
|
|
|
588
538
|
return re + imStr;
|
|
589
539
|
}
|
|
590
540
|
export const fnCOMPLEX = args => {
|
|
591
|
-
const re = toNumberRV(args[0]);
|
|
541
|
+
const re = toNumberRV(topLeft(args[0]));
|
|
592
542
|
if (isError(re)) {
|
|
593
543
|
return re;
|
|
594
544
|
}
|
|
595
|
-
const im = toNumberRV(args[1]);
|
|
545
|
+
const im = toNumberRV(topLeft(args[1]));
|
|
596
546
|
if (isError(im)) {
|
|
597
547
|
return im;
|
|
598
548
|
}
|
|
599
549
|
let suffix = "i";
|
|
600
|
-
if (args.length > 2) {
|
|
550
|
+
if (args.length > 2 && args[2].kind !== RVKind.Blank) {
|
|
601
551
|
const e2 = checkError(args[2]);
|
|
602
552
|
if (e2) {
|
|
603
553
|
return e2;
|
|
604
554
|
}
|
|
605
|
-
suffix = toStringRV(args[2]);
|
|
555
|
+
suffix = toStringRV(topLeft(args[2]));
|
|
606
556
|
}
|
|
557
|
+
// Blank 3rd arg → default "i". Previously a blank coerced to empty
|
|
558
|
+
// string then tripped the `suffix !== "i"` validation.
|
|
607
559
|
if (suffix !== "i" && suffix !== "j") {
|
|
608
560
|
return ERRORS.VALUE;
|
|
609
561
|
}
|
|
@@ -614,7 +566,7 @@ export const fnIMREAL = args => {
|
|
|
614
566
|
if (err) {
|
|
615
567
|
return err;
|
|
616
568
|
}
|
|
617
|
-
const c = parseComplex(toStringRV(args[0]));
|
|
569
|
+
const c = parseComplex(toStringRV(topLeft(args[0])));
|
|
618
570
|
return c ? rvNumber(c[0]) : ERRORS.NUM;
|
|
619
571
|
};
|
|
620
572
|
export const fnIMAGINARY = args => {
|
|
@@ -622,7 +574,7 @@ export const fnIMAGINARY = args => {
|
|
|
622
574
|
if (err) {
|
|
623
575
|
return err;
|
|
624
576
|
}
|
|
625
|
-
const c = parseComplex(toStringRV(args[0]));
|
|
577
|
+
const c = parseComplex(toStringRV(topLeft(args[0])));
|
|
626
578
|
return c ? rvNumber(c[1]) : ERRORS.NUM;
|
|
627
579
|
};
|
|
628
580
|
export const fnIMABS = args => {
|
|
@@ -630,7 +582,7 @@ export const fnIMABS = args => {
|
|
|
630
582
|
if (err) {
|
|
631
583
|
return err;
|
|
632
584
|
}
|
|
633
|
-
const c = parseComplex(toStringRV(args[0]));
|
|
585
|
+
const c = parseComplex(toStringRV(topLeft(args[0])));
|
|
634
586
|
if (!c) {
|
|
635
587
|
return ERRORS.NUM;
|
|
636
588
|
}
|
|
@@ -641,7 +593,7 @@ export const fnIMARGUMENT = args => {
|
|
|
641
593
|
if (err) {
|
|
642
594
|
return err;
|
|
643
595
|
}
|
|
644
|
-
const c = parseComplex(toStringRV(args[0]));
|
|
596
|
+
const c = parseComplex(toStringRV(topLeft(args[0])));
|
|
645
597
|
if (!c) {
|
|
646
598
|
return ERRORS.NUM;
|
|
647
599
|
}
|
|
@@ -655,7 +607,7 @@ export const fnIMCONJUGATE = args => {
|
|
|
655
607
|
if (err) {
|
|
656
608
|
return err;
|
|
657
609
|
}
|
|
658
|
-
const c = parseComplex(toStringRV(args[0]));
|
|
610
|
+
const c = parseComplex(toStringRV(topLeft(args[0])));
|
|
659
611
|
if (!c) {
|
|
660
612
|
return ERRORS.NUM;
|
|
661
613
|
}
|
|
@@ -735,8 +687,8 @@ export const fnIMSUB = args => {
|
|
|
735
687
|
if (e1) {
|
|
736
688
|
return e1;
|
|
737
689
|
}
|
|
738
|
-
const c1 = parseComplex(toStringRV(args[0]));
|
|
739
|
-
const c2 = parseComplex(toStringRV(args[1]));
|
|
690
|
+
const c1 = parseComplex(toStringRV(topLeft(args[0])));
|
|
691
|
+
const c2 = parseComplex(toStringRV(topLeft(args[1])));
|
|
740
692
|
if (!c1 || !c2) {
|
|
741
693
|
return ERRORS.NUM;
|
|
742
694
|
}
|
|
@@ -771,8 +723,8 @@ export const fnIMDIV = args => {
|
|
|
771
723
|
if (e1) {
|
|
772
724
|
return e1;
|
|
773
725
|
}
|
|
774
|
-
const c1 = parseComplex(toStringRV(args[0]));
|
|
775
|
-
const c2 = parseComplex(toStringRV(args[1]));
|
|
726
|
+
const c1 = parseComplex(toStringRV(topLeft(args[0])));
|
|
727
|
+
const c2 = parseComplex(toStringRV(topLeft(args[1])));
|
|
776
728
|
if (!c1 || !c2) {
|
|
777
729
|
return ERRORS.NUM;
|
|
778
730
|
}
|
|
@@ -792,11 +744,11 @@ export const fnIMPOWER = args => {
|
|
|
792
744
|
if (err) {
|
|
793
745
|
return err;
|
|
794
746
|
}
|
|
795
|
-
const c = parseComplex(toStringRV(args[0]));
|
|
747
|
+
const c = parseComplex(toStringRV(topLeft(args[0])));
|
|
796
748
|
if (!c) {
|
|
797
749
|
return ERRORS.NUM;
|
|
798
750
|
}
|
|
799
|
-
const n = toNumberRV(args[1]);
|
|
751
|
+
const n = toNumberRV(topLeft(args[1]));
|
|
800
752
|
if (isError(n)) {
|
|
801
753
|
return n;
|
|
802
754
|
}
|
|
@@ -810,7 +762,7 @@ export const fnIMSQRT = args => {
|
|
|
810
762
|
if (err) {
|
|
811
763
|
return err;
|
|
812
764
|
}
|
|
813
|
-
const c = parseComplex(toStringRV(args[0]));
|
|
765
|
+
const c = parseComplex(toStringRV(topLeft(args[0])));
|
|
814
766
|
if (!c) {
|
|
815
767
|
return ERRORS.NUM;
|
|
816
768
|
}
|
|
@@ -824,7 +776,7 @@ export const fnIMLN = args => {
|
|
|
824
776
|
if (err) {
|
|
825
777
|
return err;
|
|
826
778
|
}
|
|
827
|
-
const c = parseComplex(toStringRV(args[0]));
|
|
779
|
+
const c = parseComplex(toStringRV(topLeft(args[0])));
|
|
828
780
|
if (!c) {
|
|
829
781
|
return ERRORS.NUM;
|
|
830
782
|
}
|
|
@@ -839,7 +791,7 @@ export const fnIMLOG2 = args => {
|
|
|
839
791
|
if (err) {
|
|
840
792
|
return err;
|
|
841
793
|
}
|
|
842
|
-
const c = parseComplex(toStringRV(args[0]));
|
|
794
|
+
const c = parseComplex(toStringRV(topLeft(args[0])));
|
|
843
795
|
if (!c) {
|
|
844
796
|
return ERRORS.NUM;
|
|
845
797
|
}
|
|
@@ -855,7 +807,7 @@ export const fnIMLOG10 = args => {
|
|
|
855
807
|
if (err) {
|
|
856
808
|
return err;
|
|
857
809
|
}
|
|
858
|
-
const c = parseComplex(toStringRV(args[0]));
|
|
810
|
+
const c = parseComplex(toStringRV(topLeft(args[0])));
|
|
859
811
|
if (!c) {
|
|
860
812
|
return ERRORS.NUM;
|
|
861
813
|
}
|
|
@@ -871,7 +823,7 @@ export const fnIMEXP = args => {
|
|
|
871
823
|
if (err) {
|
|
872
824
|
return err;
|
|
873
825
|
}
|
|
874
|
-
const c = parseComplex(toStringRV(args[0]));
|
|
826
|
+
const c = parseComplex(toStringRV(topLeft(args[0])));
|
|
875
827
|
if (!c) {
|
|
876
828
|
return ERRORS.NUM;
|
|
877
829
|
}
|
|
@@ -883,7 +835,7 @@ export const fnIMSIN = args => {
|
|
|
883
835
|
if (err) {
|
|
884
836
|
return err;
|
|
885
837
|
}
|
|
886
|
-
const c = parseComplex(toStringRV(args[0]));
|
|
838
|
+
const c = parseComplex(toStringRV(topLeft(args[0])));
|
|
887
839
|
if (!c) {
|
|
888
840
|
return ERRORS.NUM;
|
|
889
841
|
}
|
|
@@ -894,7 +846,7 @@ export const fnIMCOS = args => {
|
|
|
894
846
|
if (err) {
|
|
895
847
|
return err;
|
|
896
848
|
}
|
|
897
|
-
const c = parseComplex(toStringRV(args[0]));
|
|
849
|
+
const c = parseComplex(toStringRV(topLeft(args[0])));
|
|
898
850
|
if (!c) {
|
|
899
851
|
return ERRORS.NUM;
|
|
900
852
|
}
|
|
@@ -1024,11 +976,11 @@ function validateBitOperand(v) {
|
|
|
1024
976
|
return v;
|
|
1025
977
|
}
|
|
1026
978
|
export const fnBITAND = args => {
|
|
1027
|
-
const a = toNumberRV(args[0]);
|
|
979
|
+
const a = toNumberRV(topLeft(args[0]));
|
|
1028
980
|
if (isError(a)) {
|
|
1029
981
|
return a;
|
|
1030
982
|
}
|
|
1031
|
-
const b = toNumberRV(args[1]);
|
|
983
|
+
const b = toNumberRV(topLeft(args[1]));
|
|
1032
984
|
if (isError(b)) {
|
|
1033
985
|
return b;
|
|
1034
986
|
}
|
|
@@ -1043,11 +995,11 @@ export const fnBITAND = args => {
|
|
|
1043
995
|
return rvNumber(bitAnd48(av, bv));
|
|
1044
996
|
};
|
|
1045
997
|
export const fnBITOR = args => {
|
|
1046
|
-
const a = toNumberRV(args[0]);
|
|
998
|
+
const a = toNumberRV(topLeft(args[0]));
|
|
1047
999
|
if (isError(a)) {
|
|
1048
1000
|
return a;
|
|
1049
1001
|
}
|
|
1050
|
-
const b = toNumberRV(args[1]);
|
|
1002
|
+
const b = toNumberRV(topLeft(args[1]));
|
|
1051
1003
|
if (isError(b)) {
|
|
1052
1004
|
return b;
|
|
1053
1005
|
}
|
|
@@ -1062,11 +1014,11 @@ export const fnBITOR = args => {
|
|
|
1062
1014
|
return rvNumber(bitOr48(av, bv));
|
|
1063
1015
|
};
|
|
1064
1016
|
export const fnBITXOR = args => {
|
|
1065
|
-
const a = toNumberRV(args[0]);
|
|
1017
|
+
const a = toNumberRV(topLeft(args[0]));
|
|
1066
1018
|
if (isError(a)) {
|
|
1067
1019
|
return a;
|
|
1068
1020
|
}
|
|
1069
|
-
const b = toNumberRV(args[1]);
|
|
1021
|
+
const b = toNumberRV(topLeft(args[1]));
|
|
1070
1022
|
if (isError(b)) {
|
|
1071
1023
|
return b;
|
|
1072
1024
|
}
|
|
@@ -1081,11 +1033,11 @@ export const fnBITXOR = args => {
|
|
|
1081
1033
|
return rvNumber(bitXor48(av, bv));
|
|
1082
1034
|
};
|
|
1083
1035
|
export const fnBITLSHIFT = args => {
|
|
1084
|
-
const num = toNumberRV(args[0]);
|
|
1036
|
+
const num = toNumberRV(topLeft(args[0]));
|
|
1085
1037
|
if (isError(num)) {
|
|
1086
1038
|
return num;
|
|
1087
1039
|
}
|
|
1088
|
-
const shift = toNumberRV(args[1]);
|
|
1040
|
+
const shift = toNumberRV(topLeft(args[1]));
|
|
1089
1041
|
if (isError(shift)) {
|
|
1090
1042
|
return shift;
|
|
1091
1043
|
}
|
|
@@ -1104,11 +1056,11 @@ export const fnBITLSHIFT = args => {
|
|
|
1104
1056
|
return rvNumber(result);
|
|
1105
1057
|
};
|
|
1106
1058
|
export const fnBITRSHIFT = args => {
|
|
1107
|
-
const num = toNumberRV(args[0]);
|
|
1059
|
+
const num = toNumberRV(topLeft(args[0]));
|
|
1108
1060
|
if (isError(num)) {
|
|
1109
1061
|
return num;
|
|
1110
1062
|
}
|
|
1111
|
-
const shift = toNumberRV(args[1]);
|
|
1063
|
+
const shift = toNumberRV(topLeft(args[1]));
|
|
1112
1064
|
if (isError(shift)) {
|
|
1113
1065
|
return shift;
|
|
1114
1066
|
}
|