@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
@@ -2,7 +2,7 @@
2
2
  * Financial Functions — Native RuntimeValue implementation.
3
3
  */
4
4
  import { excelToDate } from "../../../utils/utils.base.js";
5
- import { RVKind, ERRORS, isError, isArray, toNumberRV, toBooleanRV, rvNumber, rvBoolean } from "../runtime/values.js";
5
+ import { RVKind, ERRORS, isError, isArray, toNumberRV, toBooleanRV, topLeft, rvNumber, rvBoolean } from "../runtime/values.js";
6
6
  import { isDate1904 } from "./_date-context.js";
7
7
  import { flattenNumbers, firstError } from "./_shared.js";
8
8
  /**
@@ -20,23 +20,23 @@ function toDate(serial) {
20
20
  // Financial Functions
21
21
  // ============================================================================
22
22
  export const fnPMT = args => {
23
- const rate = toNumberRV(args[0]);
23
+ const rate = toNumberRV(topLeft(args[0]));
24
24
  if (isError(rate)) {
25
25
  return rate;
26
26
  }
27
- const nper = toNumberRV(args[1]);
27
+ const nper = toNumberRV(topLeft(args[1]));
28
28
  if (isError(nper)) {
29
29
  return nper;
30
30
  }
31
- const pv = toNumberRV(args[2]);
31
+ const pv = toNumberRV(topLeft(args[2]));
32
32
  if (isError(pv)) {
33
33
  return pv;
34
34
  }
35
- const fv = args.length > 3 ? toNumberRV(args[3]) : rvNumber(0);
35
+ const fv = args.length > 3 ? toNumberRV(topLeft(args[3])) : rvNumber(0);
36
36
  if (isError(fv)) {
37
37
  return fv;
38
38
  }
39
- const type = args.length > 4 ? toNumberRV(args[4]) : rvNumber(0);
39
+ const type = args.length > 4 ? toNumberRV(topLeft(args[4])) : rvNumber(0);
40
40
  if (isError(type)) {
41
41
  return type;
42
42
  }
@@ -62,23 +62,23 @@ export const fnPMT = args => {
62
62
  return rvNumber(-(rate.value * (pv.value * pvif + fv.value)) / (pvif - 1) / (1 + rate.value * typeBit));
63
63
  };
64
64
  export const fnFV = args => {
65
- const rate = toNumberRV(args[0]);
65
+ const rate = toNumberRV(topLeft(args[0]));
66
66
  if (isError(rate)) {
67
67
  return rate;
68
68
  }
69
- const nper = toNumberRV(args[1]);
69
+ const nper = toNumberRV(topLeft(args[1]));
70
70
  if (isError(nper)) {
71
71
  return nper;
72
72
  }
73
- const pmt = toNumberRV(args[2]);
73
+ const pmt = toNumberRV(topLeft(args[2]));
74
74
  if (isError(pmt)) {
75
75
  return pmt;
76
76
  }
77
- const pv = args.length > 3 ? toNumberRV(args[3]) : rvNumber(0);
77
+ const pv = args.length > 3 ? toNumberRV(topLeft(args[3])) : rvNumber(0);
78
78
  if (isError(pv)) {
79
79
  return pv;
80
80
  }
81
- const type = args.length > 4 ? toNumberRV(args[4]) : rvNumber(0);
81
+ const type = args.length > 4 ? toNumberRV(topLeft(args[4])) : rvNumber(0);
82
82
  if (isError(type)) {
83
83
  return type;
84
84
  }
@@ -97,23 +97,23 @@ export const fnFV = args => {
97
97
  return rvNumber(-(pv.value * pvif + pmt.value * (1 + rate.value * typeBit) * ((pvif - 1) / rate.value)));
98
98
  };
99
99
  export const fnPV = args => {
100
- const rate = toNumberRV(args[0]);
100
+ const rate = toNumberRV(topLeft(args[0]));
101
101
  if (isError(rate)) {
102
102
  return rate;
103
103
  }
104
- const nper = toNumberRV(args[1]);
104
+ const nper = toNumberRV(topLeft(args[1]));
105
105
  if (isError(nper)) {
106
106
  return nper;
107
107
  }
108
- const pmt = toNumberRV(args[2]);
108
+ const pmt = toNumberRV(topLeft(args[2]));
109
109
  if (isError(pmt)) {
110
110
  return pmt;
111
111
  }
112
- const fv = args.length > 3 ? toNumberRV(args[3]) : rvNumber(0);
112
+ const fv = args.length > 3 ? toNumberRV(topLeft(args[3])) : rvNumber(0);
113
113
  if (isError(fv)) {
114
114
  return fv;
115
115
  }
116
- const type = args.length > 4 ? toNumberRV(args[4]) : rvNumber(0);
116
+ const type = args.length > 4 ? toNumberRV(topLeft(args[4])) : rvNumber(0);
117
117
  if (isError(type)) {
118
118
  return type;
119
119
  }
@@ -131,7 +131,7 @@ export const fnPV = args => {
131
131
  return rvNumber(-(fv.value + pmt.value * (1 + rate.value * typeBit) * ((pvif - 1) / rate.value)) / pvif);
132
132
  };
133
133
  export const fnNPV = args => {
134
- const rate = toNumberRV(args[0]);
134
+ const rate = toNumberRV(topLeft(args[0]));
135
135
  if (isError(rate)) {
136
136
  return rate;
137
137
  }
@@ -148,6 +148,12 @@ export const fnNPV = args => {
148
148
  if (isArray(a)) {
149
149
  for (const row of a.rows) {
150
150
  for (const cell of row) {
151
+ // Propagate errors encountered inside the cash-flow range —
152
+ // previously silently filtered, hiding `#N/A` / `#DIV/0!`
153
+ // that should surface as the NPV result.
154
+ if (cell.kind === RVKind.Error) {
155
+ return cell;
156
+ }
151
157
  if (cell.kind === RVKind.Number) {
152
158
  values.push(cell.value);
153
159
  }
@@ -206,7 +212,13 @@ export const fnIRR = args => {
206
212
  if (!hasPos || !hasNeg) {
207
213
  return ERRORS.NUM;
208
214
  }
209
- const guessRV = args.length > 1 ? toNumberRV(args[1]) : rvNumber(0.1);
215
+ // Excel's `guess` argument defaults to 0.1 when omitted. A user-supplied
216
+ // BLANK (e.g. `IRR(B2:B6, )` with an empty second slot) should also fall
217
+ // back to 0.1 — without this the Newton scan starts at `g = 0`, which
218
+ // sits exactly at the discount-factor singularity of several cash-flow
219
+ // shapes and can fail to converge. Genuine numeric guesses (including 0
220
+ // explicitly supplied as a number) are honoured as given.
221
+ const guessRV = args.length > 1 && args[1].kind !== RVKind.Blank ? toNumberRV(topLeft(args[1])) : rvNumber(0.1);
210
222
  if (isError(guessRV)) {
211
223
  return guessRV;
212
224
  }
@@ -283,23 +295,23 @@ export const fnIRR = args => {
283
295
  return ERRORS.NUM;
284
296
  };
285
297
  export const fnNPER = args => {
286
- const rate = toNumberRV(args[0]);
298
+ const rate = toNumberRV(topLeft(args[0]));
287
299
  if (isError(rate)) {
288
300
  return rate;
289
301
  }
290
- const pmt = toNumberRV(args[1]);
302
+ const pmt = toNumberRV(topLeft(args[1]));
291
303
  if (isError(pmt)) {
292
304
  return pmt;
293
305
  }
294
- const pv = toNumberRV(args[2]);
306
+ const pv = toNumberRV(topLeft(args[2]));
295
307
  if (isError(pv)) {
296
308
  return pv;
297
309
  }
298
- const fv = args.length > 3 ? toNumberRV(args[3]) : rvNumber(0);
310
+ const fv = args.length > 3 ? toNumberRV(topLeft(args[3])) : rvNumber(0);
299
311
  if (isError(fv)) {
300
312
  return fv;
301
313
  }
302
- const type = args.length > 4 ? toNumberRV(args[4]) : rvNumber(0);
314
+ const type = args.length > 4 ? toNumberRV(topLeft(args[4])) : rvNumber(0);
303
315
  if (isError(type)) {
304
316
  return type;
305
317
  }
@@ -329,27 +341,30 @@ export const fnNPER = args => {
329
341
  return rvNumber(result);
330
342
  };
331
343
  export const fnRATE = args => {
332
- const nper = toNumberRV(args[0]);
344
+ const nper = toNumberRV(topLeft(args[0]));
333
345
  if (isError(nper)) {
334
346
  return nper;
335
347
  }
336
- const pmt = toNumberRV(args[1]);
348
+ const pmt = toNumberRV(topLeft(args[1]));
337
349
  if (isError(pmt)) {
338
350
  return pmt;
339
351
  }
340
- const pv = toNumberRV(args[2]);
352
+ const pv = toNumberRV(topLeft(args[2]));
341
353
  if (isError(pv)) {
342
354
  return pv;
343
355
  }
344
- const fv = args.length > 3 ? toNumberRV(args[3]) : rvNumber(0);
356
+ const fv = args.length > 3 ? toNumberRV(topLeft(args[3])) : rvNumber(0);
345
357
  if (isError(fv)) {
346
358
  return fv;
347
359
  }
348
- const type = args.length > 4 ? toNumberRV(args[4]) : rvNumber(0);
360
+ const type = args.length > 4 ? toNumberRV(topLeft(args[4])) : rvNumber(0);
349
361
  if (isError(type)) {
350
362
  return type;
351
363
  }
352
- const guess = args.length > 5 ? toNumberRV(args[5]) : rvNumber(0.1);
364
+ // Blank default 0.1 (see IRR / XIRR for rationale). For `fv` and
365
+ // `type` a blank coerces to 0 via `toNumberRV`, which matches Excel's
366
+ // documented defaults, so those are left as-is.
367
+ const guess = args.length > 5 && args[5].kind !== RVKind.Blank ? toNumberRV(topLeft(args[5])) : rvNumber(0.1);
353
368
  if (isError(guess)) {
354
369
  return guess;
355
370
  }
@@ -414,15 +429,15 @@ export const fnRATE = args => {
414
429
  return ERRORS.NUM;
415
430
  };
416
431
  export const fnSLN = args => {
417
- const cost = toNumberRV(args[0]);
432
+ const cost = toNumberRV(topLeft(args[0]));
418
433
  if (isError(cost)) {
419
434
  return cost;
420
435
  }
421
- const salvage = toNumberRV(args[1]);
436
+ const salvage = toNumberRV(topLeft(args[1]));
422
437
  if (isError(salvage)) {
423
438
  return salvage;
424
439
  }
425
- const life = toNumberRV(args[2]);
440
+ const life = toNumberRV(topLeft(args[2]));
426
441
  if (isError(life)) {
427
442
  return life;
428
443
  }
@@ -441,19 +456,19 @@ export const fnSLN = args => {
441
456
  * Excel rejects `life = 0` and period outside [1, life] with #NUM!.
442
457
  */
443
458
  export const fnSYD = args => {
444
- const cost = toNumberRV(args[0]);
459
+ const cost = toNumberRV(topLeft(args[0]));
445
460
  if (isError(cost)) {
446
461
  return cost;
447
462
  }
448
- const salvage = toNumberRV(args[1]);
463
+ const salvage = toNumberRV(topLeft(args[1]));
449
464
  if (isError(salvage)) {
450
465
  return salvage;
451
466
  }
452
- const life = toNumberRV(args[2]);
467
+ const life = toNumberRV(topLeft(args[2]));
453
468
  if (isError(life)) {
454
469
  return life;
455
470
  }
456
- const per = toNumberRV(args[3]);
471
+ const per = toNumberRV(topLeft(args[3]));
457
472
  if (isError(per)) {
458
473
  return per;
459
474
  }
@@ -476,31 +491,33 @@ export const fnSYD = args => {
476
491
  * periods.
477
492
  */
478
493
  export const fnVDB = args => {
479
- const cost = toNumberRV(args[0]);
494
+ const cost = toNumberRV(topLeft(args[0]));
480
495
  if (isError(cost)) {
481
496
  return cost;
482
497
  }
483
- const salvage = toNumberRV(args[1]);
498
+ const salvage = toNumberRV(topLeft(args[1]));
484
499
  if (isError(salvage)) {
485
500
  return salvage;
486
501
  }
487
- const life = toNumberRV(args[2]);
502
+ const life = toNumberRV(topLeft(args[2]));
488
503
  if (isError(life)) {
489
504
  return life;
490
505
  }
491
- const start = toNumberRV(args[3]);
506
+ const start = toNumberRV(topLeft(args[3]));
492
507
  if (isError(start)) {
493
508
  return start;
494
509
  }
495
- const end = toNumberRV(args[4]);
510
+ const end = toNumberRV(topLeft(args[4]));
496
511
  if (isError(end)) {
497
512
  return end;
498
513
  }
499
- const factorRV = args.length > 5 ? toNumberRV(args[5]) : rvNumber(2);
514
+ const factorRV = args.length > 5 && args[5].kind !== RVKind.Blank ? toNumberRV(topLeft(args[5])) : rvNumber(2);
500
515
  if (isError(factorRV)) {
501
516
  return factorRV;
502
517
  }
503
- const noSwitchRV = args.length > 6 ? toBooleanRV(args[6]) : rvBoolean(false);
518
+ const noSwitchRV = args.length > 6 && args[6].kind !== RVKind.Blank
519
+ ? toBooleanRV(topLeft(args[6]))
520
+ : rvBoolean(false);
504
521
  if (isError(noSwitchRV)) {
505
522
  return noSwitchRV;
506
523
  }
@@ -564,23 +581,27 @@ export const fnVDB = args => {
564
581
  return rvNumber(total);
565
582
  };
566
583
  export const fnDB = args => {
567
- const cost = toNumberRV(args[0]);
584
+ const cost = toNumberRV(topLeft(args[0]));
568
585
  if (isError(cost)) {
569
586
  return cost;
570
587
  }
571
- const salvage = toNumberRV(args[1]);
588
+ const salvage = toNumberRV(topLeft(args[1]));
572
589
  if (isError(salvage)) {
573
590
  return salvage;
574
591
  }
575
- const life = toNumberRV(args[2]);
592
+ const life = toNumberRV(topLeft(args[2]));
576
593
  if (isError(life)) {
577
594
  return life;
578
595
  }
579
- const period = toNumberRV(args[3]);
596
+ const period = toNumberRV(topLeft(args[3]));
580
597
  if (isError(period)) {
581
598
  return period;
582
599
  }
583
- const month = args.length > 4 ? toNumberRV(args[4]) : rvNumber(12);
600
+ // Blank `month` Excel default 12 (full first year). Without the
601
+ // blank guard, `toNumberRV(BLANK)` coerces to 0 which then trips the
602
+ // `month < 1` validation below, silently surfacing #NUM! for
603
+ // `DB(cost, salvage, life, period, )`.
604
+ const month = args.length > 4 && args[4].kind !== RVKind.Blank ? toNumberRV(topLeft(args[4])) : rvNumber(12);
584
605
  if (isError(month)) {
585
606
  return month;
586
607
  }
@@ -623,23 +644,25 @@ export const fnDB = args => {
623
644
  return rvNumber(depn);
624
645
  };
625
646
  export const fnDDB = args => {
626
- const cost = toNumberRV(args[0]);
647
+ const cost = toNumberRV(topLeft(args[0]));
627
648
  if (isError(cost)) {
628
649
  return cost;
629
650
  }
630
- const salvage = toNumberRV(args[1]);
651
+ const salvage = toNumberRV(topLeft(args[1]));
631
652
  if (isError(salvage)) {
632
653
  return salvage;
633
654
  }
634
- const life = toNumberRV(args[2]);
655
+ const life = toNumberRV(topLeft(args[2]));
635
656
  if (isError(life)) {
636
657
  return life;
637
658
  }
638
- const period = toNumberRV(args[3]);
659
+ const period = toNumberRV(topLeft(args[3]));
639
660
  if (isError(period)) {
640
661
  return period;
641
662
  }
642
- const factor = args.length > 4 ? toNumberRV(args[4]) : rvNumber(2);
663
+ // Blank `factor` Excel default 2 (double declining). See DB/IRR for
664
+ // why blank must be distinguished from an explicit 0.
665
+ const factor = args.length > 4 && args[4].kind !== RVKind.Blank ? toNumberRV(topLeft(args[4])) : rvNumber(2);
643
666
  if (isError(factor)) {
644
667
  return factor;
645
668
  }
@@ -697,54 +720,54 @@ function ipmtRaw(rate, per, nper, pv, fv, type) {
697
720
  return type === 1 ? ipmt / (1 + rate) : ipmt;
698
721
  }
699
722
  export const fnIPMT = args => {
700
- const rate = toNumberRV(args[0]);
723
+ const rate = toNumberRV(topLeft(args[0]));
701
724
  if (isError(rate)) {
702
725
  return rate;
703
726
  }
704
- const per = toNumberRV(args[1]);
727
+ const per = toNumberRV(topLeft(args[1]));
705
728
  if (isError(per)) {
706
729
  return per;
707
730
  }
708
- const nper = toNumberRV(args[2]);
731
+ const nper = toNumberRV(topLeft(args[2]));
709
732
  if (isError(nper)) {
710
733
  return nper;
711
734
  }
712
- const pv = toNumberRV(args[3]);
735
+ const pv = toNumberRV(topLeft(args[3]));
713
736
  if (isError(pv)) {
714
737
  return pv;
715
738
  }
716
- const fv = args.length > 4 ? toNumberRV(args[4]) : rvNumber(0);
739
+ const fv = args.length > 4 ? toNumberRV(topLeft(args[4])) : rvNumber(0);
717
740
  if (isError(fv)) {
718
741
  return fv;
719
742
  }
720
- const type = args.length > 5 ? toNumberRV(args[5]) : rvNumber(0);
743
+ const type = args.length > 5 ? toNumberRV(topLeft(args[5])) : rvNumber(0);
721
744
  if (isError(type)) {
722
745
  return type;
723
746
  }
724
747
  return rvNumber(ipmtRaw(rate.value, per.value, nper.value, pv.value, fv.value, type.value));
725
748
  };
726
749
  export const fnPPMT = args => {
727
- const rate = toNumberRV(args[0]);
750
+ const rate = toNumberRV(topLeft(args[0]));
728
751
  if (isError(rate)) {
729
752
  return rate;
730
753
  }
731
- const per = toNumberRV(args[1]);
754
+ const per = toNumberRV(topLeft(args[1]));
732
755
  if (isError(per)) {
733
756
  return per;
734
757
  }
735
- const nper = toNumberRV(args[2]);
758
+ const nper = toNumberRV(topLeft(args[2]));
736
759
  if (isError(nper)) {
737
760
  return nper;
738
761
  }
739
- const pv = toNumberRV(args[3]);
762
+ const pv = toNumberRV(topLeft(args[3]));
740
763
  if (isError(pv)) {
741
764
  return pv;
742
765
  }
743
- const fv = args.length > 4 ? toNumberRV(args[4]) : rvNumber(0);
766
+ const fv = args.length > 4 ? toNumberRV(topLeft(args[4])) : rvNumber(0);
744
767
  if (isError(fv)) {
745
768
  return fv;
746
769
  }
747
- const type = args.length > 5 ? toNumberRV(args[5]) : rvNumber(0);
770
+ const type = args.length > 5 ? toNumberRV(topLeft(args[5])) : rvNumber(0);
748
771
  if (isError(type)) {
749
772
  return type;
750
773
  }
@@ -764,7 +787,7 @@ export const fnPPMT = args => {
764
787
  * propagates any error it encounters. Text values produce #VALUE!.
765
788
  */
766
789
  export const fnFVSCHEDULE = args => {
767
- const principal = toNumberRV(args[0]);
790
+ const principal = toNumberRV(topLeft(args[0]));
768
791
  if (isError(principal)) {
769
792
  return principal;
770
793
  }
@@ -815,15 +838,15 @@ export const fnFVSCHEDULE = args => {
815
838
  * Excel requires `rate > 0` and `pv, fv > 0`.
816
839
  */
817
840
  export const fnPDURATION = args => {
818
- const rate = toNumberRV(args[0]);
841
+ const rate = toNumberRV(topLeft(args[0]));
819
842
  if (isError(rate)) {
820
843
  return rate;
821
844
  }
822
- const pv = toNumberRV(args[1]);
845
+ const pv = toNumberRV(topLeft(args[1]));
823
846
  if (isError(pv)) {
824
847
  return pv;
825
848
  }
826
- const fv = toNumberRV(args[2]);
849
+ const fv = toNumberRV(topLeft(args[2]));
827
850
  if (isError(fv)) {
828
851
  return fv;
829
852
  }
@@ -840,15 +863,15 @@ export const fnPDURATION = args => {
840
863
  * Excel requires `nper > 0`, `pv > 0`, `fv >= 0`.
841
864
  */
842
865
  export const fnRRI = args => {
843
- const nper = toNumberRV(args[0]);
866
+ const nper = toNumberRV(topLeft(args[0]));
844
867
  if (isError(nper)) {
845
868
  return nper;
846
869
  }
847
- const pv = toNumberRV(args[1]);
870
+ const pv = toNumberRV(topLeft(args[1]));
848
871
  if (isError(pv)) {
849
872
  return pv;
850
873
  }
851
- const fv = toNumberRV(args[2]);
874
+ const fv = toNumberRV(topLeft(args[2]));
852
875
  if (isError(fv)) {
853
876
  return fv;
854
877
  }
@@ -858,11 +881,11 @@ export const fnRRI = args => {
858
881
  return rvNumber(Math.pow(fv.value / pv.value, 1 / nper.value) - 1);
859
882
  };
860
883
  export const fnEFFECT = args => {
861
- const nomRate = toNumberRV(args[0]);
884
+ const nomRate = toNumberRV(topLeft(args[0]));
862
885
  if (isError(nomRate)) {
863
886
  return nomRate;
864
887
  }
865
- const npery = toNumberRV(args[1]);
888
+ const npery = toNumberRV(topLeft(args[1]));
866
889
  if (isError(npery)) {
867
890
  return npery;
868
891
  }
@@ -872,11 +895,11 @@ export const fnEFFECT = args => {
872
895
  return rvNumber(Math.pow(1 + nomRate.value / Math.floor(npery.value), Math.floor(npery.value)) - 1);
873
896
  };
874
897
  export const fnNOMINAL = args => {
875
- const effRate = toNumberRV(args[0]);
898
+ const effRate = toNumberRV(topLeft(args[0]));
876
899
  if (isError(effRate)) {
877
900
  return effRate;
878
901
  }
879
- const npery = toNumberRV(args[1]);
902
+ const npery = toNumberRV(topLeft(args[1]));
880
903
  if (isError(npery)) {
881
904
  return npery;
882
905
  }
@@ -887,7 +910,7 @@ export const fnNOMINAL = args => {
887
910
  return rvNumber(np * (Math.pow(effRate.value + 1, 1 / np) - 1));
888
911
  };
889
912
  export const fnXNPV = args => {
890
- const rate = toNumberRV(args[0]);
913
+ const rate = toNumberRV(topLeft(args[0]));
891
914
  if (isError(rate)) {
892
915
  return rate;
893
916
  }
@@ -957,7 +980,8 @@ export const fnXIRR = args => {
957
980
  if (!xHasPos || !xHasNeg) {
958
981
  return ERRORS.NUM;
959
982
  }
960
- const guessRV = args.length > 2 ? toNumberRV(args[2]) : rvNumber(0.1);
983
+ // Blank third slot → default 0.1, same rationale as IRR above.
984
+ const guessRV = args.length > 2 && args[2].kind !== RVKind.Blank ? toNumberRV(topLeft(args[2])) : rvNumber(0.1);
961
985
  if (isError(guessRV)) {
962
986
  return guessRV;
963
987
  }
@@ -1043,11 +1067,11 @@ export const fnMIRR = args => {
1043
1067
  return valuesErr;
1044
1068
  }
1045
1069
  const values = rawValues.map(n => n.value);
1046
- const financeRate = toNumberRV(args[1]);
1070
+ const financeRate = toNumberRV(topLeft(args[1]));
1047
1071
  if (isError(financeRate)) {
1048
1072
  return financeRate;
1049
1073
  }
1050
- const reinvestRate = toNumberRV(args[2]);
1074
+ const reinvestRate = toNumberRV(topLeft(args[2]));
1051
1075
  if (isError(reinvestRate)) {
1052
1076
  return reinvestRate;
1053
1077
  }
@@ -1076,19 +1100,19 @@ export const fnMIRR = args => {
1076
1100
  return rvNumber(Math.pow(-npvPos / npvNeg, 1 / (n - 1)) - 1);
1077
1101
  };
1078
1102
  export const fnISPMT = args => {
1079
- const rate = toNumberRV(args[0]);
1103
+ const rate = toNumberRV(topLeft(args[0]));
1080
1104
  if (isError(rate)) {
1081
1105
  return rate;
1082
1106
  }
1083
- const per = toNumberRV(args[1]);
1107
+ const per = toNumberRV(topLeft(args[1]));
1084
1108
  if (isError(per)) {
1085
1109
  return per;
1086
1110
  }
1087
- const nper = toNumberRV(args[2]);
1111
+ const nper = toNumberRV(topLeft(args[2]));
1088
1112
  if (isError(nper)) {
1089
1113
  return nper;
1090
1114
  }
1091
- const pv = toNumberRV(args[3]);
1115
+ const pv = toNumberRV(topLeft(args[3]));
1092
1116
  if (isError(pv)) {
1093
1117
  return pv;
1094
1118
  }
@@ -1100,27 +1124,27 @@ export const fnISPMT = args => {
1100
1124
  return rvNumber(pv.value * rate.value * (per.value / nper.value - 1));
1101
1125
  };
1102
1126
  export const fnCUMPRINC = args => {
1103
- const rate = toNumberRV(args[0]);
1127
+ const rate = toNumberRV(topLeft(args[0]));
1104
1128
  if (isError(rate)) {
1105
1129
  return rate;
1106
1130
  }
1107
- const nper = toNumberRV(args[1]);
1131
+ const nper = toNumberRV(topLeft(args[1]));
1108
1132
  if (isError(nper)) {
1109
1133
  return nper;
1110
1134
  }
1111
- const pv = toNumberRV(args[2]);
1135
+ const pv = toNumberRV(topLeft(args[2]));
1112
1136
  if (isError(pv)) {
1113
1137
  return pv;
1114
1138
  }
1115
- const startPeriod = toNumberRV(args[3]);
1139
+ const startPeriod = toNumberRV(topLeft(args[3]));
1116
1140
  if (isError(startPeriod)) {
1117
1141
  return startPeriod;
1118
1142
  }
1119
- const endPeriod = toNumberRV(args[4]);
1143
+ const endPeriod = toNumberRV(topLeft(args[4]));
1120
1144
  if (isError(endPeriod)) {
1121
1145
  return endPeriod;
1122
1146
  }
1123
- const type = toNumberRV(args[5]);
1147
+ const type = toNumberRV(topLeft(args[5]));
1124
1148
  if (isError(type)) {
1125
1149
  return type;
1126
1150
  }
@@ -1138,35 +1162,37 @@ export const fnCUMPRINC = args => {
1138
1162
  return ERRORS.NUM;
1139
1163
  }
1140
1164
  let cumPrinc = 0;
1165
+ // PMT is constant across all periods — hoist it out of the loop
1166
+ // rather than recomputing the same value `e - s + 1` times.
1167
+ const pmtVal = pmtRaw(rate.value, nper.value, pv.value, 0, type.value);
1141
1168
  for (let p = s; p <= e; p++) {
1142
- const pmtVal = pmtRaw(rate.value, nper.value, pv.value, 0, type.value);
1143
1169
  const ipmtVal = ipmtRaw(rate.value, p, nper.value, pv.value, 0, type.value);
1144
1170
  cumPrinc += pmtVal - ipmtVal;
1145
1171
  }
1146
1172
  return rvNumber(cumPrinc);
1147
1173
  };
1148
1174
  export const fnCUMIPMT = args => {
1149
- const rate = toNumberRV(args[0]);
1175
+ const rate = toNumberRV(topLeft(args[0]));
1150
1176
  if (isError(rate)) {
1151
1177
  return rate;
1152
1178
  }
1153
- const nper = toNumberRV(args[1]);
1179
+ const nper = toNumberRV(topLeft(args[1]));
1154
1180
  if (isError(nper)) {
1155
1181
  return nper;
1156
1182
  }
1157
- const pv = toNumberRV(args[2]);
1183
+ const pv = toNumberRV(topLeft(args[2]));
1158
1184
  if (isError(pv)) {
1159
1185
  return pv;
1160
1186
  }
1161
- const startPeriod = toNumberRV(args[3]);
1187
+ const startPeriod = toNumberRV(topLeft(args[3]));
1162
1188
  if (isError(startPeriod)) {
1163
1189
  return startPeriod;
1164
1190
  }
1165
- const endPeriod = toNumberRV(args[4]);
1191
+ const endPeriod = toNumberRV(topLeft(args[4]));
1166
1192
  if (isError(endPeriod)) {
1167
1193
  return endPeriod;
1168
1194
  }
1169
- const type = toNumberRV(args[5]);
1195
+ const type = toNumberRV(topLeft(args[5]));
1170
1196
  if (isError(type)) {
1171
1197
  return type;
1172
1198
  }
@@ -1189,11 +1215,11 @@ export const fnCUMIPMT = args => {
1189
1215
  return rvNumber(cumIpmt);
1190
1216
  };
1191
1217
  export const fnDOLLARDE = args => {
1192
- const fractionalDollar = toNumberRV(args[0]);
1218
+ const fractionalDollar = toNumberRV(topLeft(args[0]));
1193
1219
  if (isError(fractionalDollar)) {
1194
1220
  return fractionalDollar;
1195
1221
  }
1196
- const fraction = toNumberRV(args[1]);
1222
+ const fraction = toNumberRV(topLeft(args[1]));
1197
1223
  if (isError(fraction)) {
1198
1224
  return fraction;
1199
1225
  }
@@ -1216,11 +1242,11 @@ export const fnDOLLARDE = args => {
1216
1242
  return rvNumber(sign * (Math.abs(intPart) + numerator / f));
1217
1243
  };
1218
1244
  export const fnDOLLARFR = args => {
1219
- const decimalDollar = toNumberRV(args[0]);
1245
+ const decimalDollar = toNumberRV(topLeft(args[0]));
1220
1246
  if (isError(decimalDollar)) {
1221
1247
  return decimalDollar;
1222
1248
  }
1223
- const fraction = toNumberRV(args[1]);
1249
+ const fraction = toNumberRV(topLeft(args[1]));
1224
1250
  if (isError(fraction)) {
1225
1251
  return fraction;
1226
1252
  }
@@ -1256,23 +1282,23 @@ function validateBasis(basis) {
1256
1282
  return null;
1257
1283
  }
1258
1284
  export const fnDISC = args => {
1259
- const settlement = toNumberRV(args[0]);
1285
+ const settlement = toNumberRV(topLeft(args[0]));
1260
1286
  if (isError(settlement)) {
1261
1287
  return settlement;
1262
1288
  }
1263
- const maturity = toNumberRV(args[1]);
1289
+ const maturity = toNumberRV(topLeft(args[1]));
1264
1290
  if (isError(maturity)) {
1265
1291
  return maturity;
1266
1292
  }
1267
- const pr = toNumberRV(args[2]);
1293
+ const pr = toNumberRV(topLeft(args[2]));
1268
1294
  if (isError(pr)) {
1269
1295
  return pr;
1270
1296
  }
1271
- const redemption = toNumberRV(args[3]);
1297
+ const redemption = toNumberRV(topLeft(args[3]));
1272
1298
  if (isError(redemption)) {
1273
1299
  return redemption;
1274
1300
  }
1275
- const basis = args.length > 4 ? toNumberRV(args[4]) : rvNumber(0);
1301
+ const basis = args.length > 4 ? toNumberRV(topLeft(args[4])) : rvNumber(0);
1276
1302
  if (isError(basis)) {
1277
1303
  return basis;
1278
1304
  }
@@ -1293,23 +1319,23 @@ export const fnDISC = args => {
1293
1319
  return rvNumber((redemption.value - pr.value) / redemption.value / dcf);
1294
1320
  };
1295
1321
  export const fnPRICEDISC = args => {
1296
- const settlement = toNumberRV(args[0]);
1322
+ const settlement = toNumberRV(topLeft(args[0]));
1297
1323
  if (isError(settlement)) {
1298
1324
  return settlement;
1299
1325
  }
1300
- const maturity = toNumberRV(args[1]);
1326
+ const maturity = toNumberRV(topLeft(args[1]));
1301
1327
  if (isError(maturity)) {
1302
1328
  return maturity;
1303
1329
  }
1304
- const disc = toNumberRV(args[2]);
1330
+ const disc = toNumberRV(topLeft(args[2]));
1305
1331
  if (isError(disc)) {
1306
1332
  return disc;
1307
1333
  }
1308
- const redemption = toNumberRV(args[3]);
1334
+ const redemption = toNumberRV(topLeft(args[3]));
1309
1335
  if (isError(redemption)) {
1310
1336
  return redemption;
1311
1337
  }
1312
- const basis = args.length > 4 ? toNumberRV(args[4]) : rvNumber(0);
1338
+ const basis = args.length > 4 ? toNumberRV(topLeft(args[4])) : rvNumber(0);
1313
1339
  if (isError(basis)) {
1314
1340
  return basis;
1315
1341
  }
@@ -1324,23 +1350,23 @@ export const fnPRICEDISC = args => {
1324
1350
  return rvNumber(redemption.value - disc.value * redemption.value * dcf);
1325
1351
  };
1326
1352
  export const fnYIELDDISC = args => {
1327
- const settlement = toNumberRV(args[0]);
1353
+ const settlement = toNumberRV(topLeft(args[0]));
1328
1354
  if (isError(settlement)) {
1329
1355
  return settlement;
1330
1356
  }
1331
- const maturity = toNumberRV(args[1]);
1357
+ const maturity = toNumberRV(topLeft(args[1]));
1332
1358
  if (isError(maturity)) {
1333
1359
  return maturity;
1334
1360
  }
1335
- const pr = toNumberRV(args[2]);
1361
+ const pr = toNumberRV(topLeft(args[2]));
1336
1362
  if (isError(pr)) {
1337
1363
  return pr;
1338
1364
  }
1339
- const redemption = toNumberRV(args[3]);
1365
+ const redemption = toNumberRV(topLeft(args[3]));
1340
1366
  if (isError(redemption)) {
1341
1367
  return redemption;
1342
1368
  }
1343
- const basis = args.length > 4 ? toNumberRV(args[4]) : rvNumber(0);
1369
+ const basis = args.length > 4 ? toNumberRV(topLeft(args[4])) : rvNumber(0);
1344
1370
  if (isError(basis)) {
1345
1371
  return basis;
1346
1372
  }
@@ -1358,23 +1384,23 @@ export const fnYIELDDISC = args => {
1358
1384
  return rvNumber((redemption.value - pr.value) / pr.value / dcf);
1359
1385
  };
1360
1386
  export const fnRECEIVED = args => {
1361
- const settlement = toNumberRV(args[0]);
1387
+ const settlement = toNumberRV(topLeft(args[0]));
1362
1388
  if (isError(settlement)) {
1363
1389
  return settlement;
1364
1390
  }
1365
- const maturity = toNumberRV(args[1]);
1391
+ const maturity = toNumberRV(topLeft(args[1]));
1366
1392
  if (isError(maturity)) {
1367
1393
  return maturity;
1368
1394
  }
1369
- const investment = toNumberRV(args[2]);
1395
+ const investment = toNumberRV(topLeft(args[2]));
1370
1396
  if (isError(investment)) {
1371
1397
  return investment;
1372
1398
  }
1373
- const disc = toNumberRV(args[3]);
1399
+ const disc = toNumberRV(topLeft(args[3]));
1374
1400
  if (isError(disc)) {
1375
1401
  return disc;
1376
1402
  }
1377
- const basis = args.length > 4 ? toNumberRV(args[4]) : rvNumber(0);
1403
+ const basis = args.length > 4 ? toNumberRV(topLeft(args[4])) : rvNumber(0);
1378
1404
  if (isError(basis)) {
1379
1405
  return basis;
1380
1406
  }
@@ -1393,23 +1419,23 @@ export const fnRECEIVED = args => {
1393
1419
  return rvNumber(investment.value / denom);
1394
1420
  };
1395
1421
  export const fnINTRATE = args => {
1396
- const settlement = toNumberRV(args[0]);
1422
+ const settlement = toNumberRV(topLeft(args[0]));
1397
1423
  if (isError(settlement)) {
1398
1424
  return settlement;
1399
1425
  }
1400
- const maturity = toNumberRV(args[1]);
1426
+ const maturity = toNumberRV(topLeft(args[1]));
1401
1427
  if (isError(maturity)) {
1402
1428
  return maturity;
1403
1429
  }
1404
- const investment = toNumberRV(args[2]);
1430
+ const investment = toNumberRV(topLeft(args[2]));
1405
1431
  if (isError(investment)) {
1406
1432
  return investment;
1407
1433
  }
1408
- const redemption = toNumberRV(args[3]);
1434
+ const redemption = toNumberRV(topLeft(args[3]));
1409
1435
  if (isError(redemption)) {
1410
1436
  return redemption;
1411
1437
  }
1412
- const basis = args.length > 4 ? toNumberRV(args[4]) : rvNumber(0);
1438
+ const basis = args.length > 4 ? toNumberRV(topLeft(args[4])) : rvNumber(0);
1413
1439
  if (isError(basis)) {
1414
1440
  return basis;
1415
1441
  }
@@ -1626,31 +1652,31 @@ function validateBondBasis(frequency, basis) {
1626
1652
  * A = days from beginning of coupon period to settlement
1627
1653
  */
1628
1654
  export const fnPRICE = args => {
1629
- const settlementRV = toNumberRV(args[0]);
1655
+ const settlementRV = toNumberRV(topLeft(args[0]));
1630
1656
  if (isError(settlementRV)) {
1631
1657
  return settlementRV;
1632
1658
  }
1633
- const maturityRV = toNumberRV(args[1]);
1659
+ const maturityRV = toNumberRV(topLeft(args[1]));
1634
1660
  if (isError(maturityRV)) {
1635
1661
  return maturityRV;
1636
1662
  }
1637
- const rateRV = toNumberRV(args[2]);
1663
+ const rateRV = toNumberRV(topLeft(args[2]));
1638
1664
  if (isError(rateRV)) {
1639
1665
  return rateRV;
1640
1666
  }
1641
- const yieldRV = toNumberRV(args[3]);
1667
+ const yieldRV = toNumberRV(topLeft(args[3]));
1642
1668
  if (isError(yieldRV)) {
1643
1669
  return yieldRV;
1644
1670
  }
1645
- const redemptionRV = toNumberRV(args[4]);
1671
+ const redemptionRV = toNumberRV(topLeft(args[4]));
1646
1672
  if (isError(redemptionRV)) {
1647
1673
  return redemptionRV;
1648
1674
  }
1649
- const frequencyRV = toNumberRV(args[5]);
1675
+ const frequencyRV = toNumberRV(topLeft(args[5]));
1650
1676
  if (isError(frequencyRV)) {
1651
1677
  return frequencyRV;
1652
1678
  }
1653
- const basisRV = args.length > 6 ? toNumberRV(args[6]) : rvNumber(0);
1679
+ const basisRV = args.length > 6 ? toNumberRV(topLeft(args[6])) : rvNumber(0);
1654
1680
  if (isError(basisRV)) {
1655
1681
  return basisRV;
1656
1682
  }
@@ -1700,31 +1726,31 @@ export const fnPRICE = args => {
1700
1726
  * realistic bond scenarios) followed by a light Newton polish.
1701
1727
  */
1702
1728
  export const fnYIELD = args => {
1703
- const settlementRV = toNumberRV(args[0]);
1729
+ const settlementRV = toNumberRV(topLeft(args[0]));
1704
1730
  if (isError(settlementRV)) {
1705
1731
  return settlementRV;
1706
1732
  }
1707
- const maturityRV = toNumberRV(args[1]);
1733
+ const maturityRV = toNumberRV(topLeft(args[1]));
1708
1734
  if (isError(maturityRV)) {
1709
1735
  return maturityRV;
1710
1736
  }
1711
- const rateRV = toNumberRV(args[2]);
1737
+ const rateRV = toNumberRV(topLeft(args[2]));
1712
1738
  if (isError(rateRV)) {
1713
1739
  return rateRV;
1714
1740
  }
1715
- const prRV = toNumberRV(args[3]);
1741
+ const prRV = toNumberRV(topLeft(args[3]));
1716
1742
  if (isError(prRV)) {
1717
1743
  return prRV;
1718
1744
  }
1719
- const redemptionRV = toNumberRV(args[4]);
1745
+ const redemptionRV = toNumberRV(topLeft(args[4]));
1720
1746
  if (isError(redemptionRV)) {
1721
1747
  return redemptionRV;
1722
1748
  }
1723
- const frequencyRV = toNumberRV(args[5]);
1749
+ const frequencyRV = toNumberRV(topLeft(args[5]));
1724
1750
  if (isError(frequencyRV)) {
1725
1751
  return frequencyRV;
1726
1752
  }
1727
- const basisRV = args.length > 6 ? toNumberRV(args[6]) : rvNumber(0);
1753
+ const basisRV = args.length > 6 ? toNumberRV(topLeft(args[6])) : rvNumber(0);
1728
1754
  if (isError(basisRV)) {
1729
1755
  return basisRV;
1730
1756
  }
@@ -1787,27 +1813,27 @@ export const fnYIELD = args => {
1787
1813
  * weighted by present value. Expressed in years.
1788
1814
  */
1789
1815
  export const fnDURATION = args => {
1790
- const settlementRV = toNumberRV(args[0]);
1816
+ const settlementRV = toNumberRV(topLeft(args[0]));
1791
1817
  if (isError(settlementRV)) {
1792
1818
  return settlementRV;
1793
1819
  }
1794
- const maturityRV = toNumberRV(args[1]);
1820
+ const maturityRV = toNumberRV(topLeft(args[1]));
1795
1821
  if (isError(maturityRV)) {
1796
1822
  return maturityRV;
1797
1823
  }
1798
- const couponRV = toNumberRV(args[2]);
1824
+ const couponRV = toNumberRV(topLeft(args[2]));
1799
1825
  if (isError(couponRV)) {
1800
1826
  return couponRV;
1801
1827
  }
1802
- const yieldRV = toNumberRV(args[3]);
1828
+ const yieldRV = toNumberRV(topLeft(args[3]));
1803
1829
  if (isError(yieldRV)) {
1804
1830
  return yieldRV;
1805
1831
  }
1806
- const frequencyRV = toNumberRV(args[4]);
1832
+ const frequencyRV = toNumberRV(topLeft(args[4]));
1807
1833
  if (isError(frequencyRV)) {
1808
1834
  return frequencyRV;
1809
1835
  }
1810
- const basisRV = args.length > 5 ? toNumberRV(args[5]) : rvNumber(0);
1836
+ const basisRV = args.length > 5 ? toNumberRV(topLeft(args[5])) : rvNumber(0);
1811
1837
  if (isError(basisRV)) {
1812
1838
  return basisRV;
1813
1839
  }
@@ -1854,11 +1880,11 @@ export const fnMDURATION = args => {
1854
1880
  if (dur.kind !== RVKind.Number) {
1855
1881
  return dur;
1856
1882
  }
1857
- const yieldRV = toNumberRV(args[3]);
1883
+ const yieldRV = toNumberRV(topLeft(args[3]));
1858
1884
  if (isError(yieldRV)) {
1859
1885
  return yieldRV;
1860
1886
  }
1861
- const frequencyRV = toNumberRV(args[4]);
1887
+ const frequencyRV = toNumberRV(topLeft(args[4]));
1862
1888
  if (isError(frequencyRV)) {
1863
1889
  return frequencyRV;
1864
1890
  }
@@ -1872,28 +1898,28 @@ export const fnMDURATION = args => {
1872
1898
  * accrued interest from issue to settlement as par * rate * dcf(issue, settlement, basis).
1873
1899
  */
1874
1900
  export const fnACCRINT = args => {
1875
- const issueRV = toNumberRV(args[0]);
1901
+ const issueRV = toNumberRV(topLeft(args[0]));
1876
1902
  if (isError(issueRV)) {
1877
1903
  return issueRV;
1878
1904
  }
1879
1905
  // first_interest (args[1]) is unused in the simplified implementation.
1880
- const settlementRV = toNumberRV(args[2]);
1906
+ const settlementRV = toNumberRV(topLeft(args[2]));
1881
1907
  if (isError(settlementRV)) {
1882
1908
  return settlementRV;
1883
1909
  }
1884
- const rateRV = toNumberRV(args[3]);
1910
+ const rateRV = toNumberRV(topLeft(args[3]));
1885
1911
  if (isError(rateRV)) {
1886
1912
  return rateRV;
1887
1913
  }
1888
- const parRV = toNumberRV(args[4]);
1914
+ const parRV = toNumberRV(topLeft(args[4]));
1889
1915
  if (isError(parRV)) {
1890
1916
  return parRV;
1891
1917
  }
1892
- const frequencyRV = toNumberRV(args[5]);
1918
+ const frequencyRV = toNumberRV(topLeft(args[5]));
1893
1919
  if (isError(frequencyRV)) {
1894
1920
  return frequencyRV;
1895
1921
  }
1896
- const basisRV = args.length > 6 ? toNumberRV(args[6]) : rvNumber(0);
1922
+ const basisRV = args.length > 6 ? toNumberRV(topLeft(args[6])) : rvNumber(0);
1897
1923
  if (isError(basisRV)) {
1898
1924
  return basisRV;
1899
1925
  }
@@ -1919,23 +1945,23 @@ export const fnACCRINT = args => {
1919
1945
  * result = par × rate × dayCountFraction(issue, settlement, basis)
1920
1946
  */
1921
1947
  export const fnACCRINTM = args => {
1922
- const issueRV = toNumberRV(args[0]);
1948
+ const issueRV = toNumberRV(topLeft(args[0]));
1923
1949
  if (isError(issueRV)) {
1924
1950
  return issueRV;
1925
1951
  }
1926
- const settlementRV = toNumberRV(args[1]);
1952
+ const settlementRV = toNumberRV(topLeft(args[1]));
1927
1953
  if (isError(settlementRV)) {
1928
1954
  return settlementRV;
1929
1955
  }
1930
- const rateRV = toNumberRV(args[2]);
1956
+ const rateRV = toNumberRV(topLeft(args[2]));
1931
1957
  if (isError(rateRV)) {
1932
1958
  return rateRV;
1933
1959
  }
1934
- const parRV = toNumberRV(args[3]);
1960
+ const parRV = toNumberRV(topLeft(args[3]));
1935
1961
  if (isError(parRV)) {
1936
1962
  return parRV;
1937
1963
  }
1938
- const basisRV = args.length > 4 ? toNumberRV(args[4]) : rvNumber(0);
1964
+ const basisRV = args.length > 4 ? toNumberRV(topLeft(args[4])) : rvNumber(0);
1939
1965
  if (isError(basisRV)) {
1940
1966
  return basisRV;
1941
1967
  }
@@ -1957,15 +1983,15 @@ export const fnACCRINTM = args => {
1957
1983
  * where DSM is days from settlement to maturity.
1958
1984
  */
1959
1985
  export const fnTBILLPRICE = args => {
1960
- const settlementRV = toNumberRV(args[0]);
1986
+ const settlementRV = toNumberRV(topLeft(args[0]));
1961
1987
  if (isError(settlementRV)) {
1962
1988
  return settlementRV;
1963
1989
  }
1964
- const maturityRV = toNumberRV(args[1]);
1990
+ const maturityRV = toNumberRV(topLeft(args[1]));
1965
1991
  if (isError(maturityRV)) {
1966
1992
  return maturityRV;
1967
1993
  }
1968
- const discountRV = toNumberRV(args[2]);
1994
+ const discountRV = toNumberRV(topLeft(args[2]));
1969
1995
  if (isError(discountRV)) {
1970
1996
  return discountRV;
1971
1997
  }
@@ -1991,15 +2017,15 @@ export const fnTBILLPRICE = args => {
1991
2017
  * yield = (100 - pr) / pr × (360 / DSM)
1992
2018
  */
1993
2019
  export const fnTBILLYIELD = args => {
1994
- const settlementRV = toNumberRV(args[0]);
2020
+ const settlementRV = toNumberRV(topLeft(args[0]));
1995
2021
  if (isError(settlementRV)) {
1996
2022
  return settlementRV;
1997
2023
  }
1998
- const maturityRV = toNumberRV(args[1]);
2024
+ const maturityRV = toNumberRV(topLeft(args[1]));
1999
2025
  if (isError(maturityRV)) {
2000
2026
  return maturityRV;
2001
2027
  }
2002
- const prRV = toNumberRV(args[2]);
2028
+ const prRV = toNumberRV(topLeft(args[2]));
2003
2029
  if (isError(prRV)) {
2004
2030
  return prRV;
2005
2031
  }
@@ -2020,15 +2046,15 @@ export const fnTBILLYIELD = args => {
2020
2046
  * TBILLEQ = (365 × discount) / (360 - discount × DSM)
2021
2047
  */
2022
2048
  export const fnTBILLEQ = args => {
2023
- const settlementRV = toNumberRV(args[0]);
2049
+ const settlementRV = toNumberRV(topLeft(args[0]));
2024
2050
  if (isError(settlementRV)) {
2025
2051
  return settlementRV;
2026
2052
  }
2027
- const maturityRV = toNumberRV(args[1]);
2053
+ const maturityRV = toNumberRV(topLeft(args[1]));
2028
2054
  if (isError(maturityRV)) {
2029
2055
  return maturityRV;
2030
2056
  }
2031
- const discountRV = toNumberRV(args[2]);
2057
+ const discountRV = toNumberRV(topLeft(args[2]));
2032
2058
  if (isError(discountRV)) {
2033
2059
  return discountRV;
2034
2060
  }
@@ -2058,27 +2084,27 @@ export const fnTBILLEQ = args => {
2058
2084
  * price = (100 + DIM × rate × 100) / (1 + DSM × yld) - A × rate × 100
2059
2085
  */
2060
2086
  export const fnPRICEMAT = args => {
2061
- const settlementRV = toNumberRV(args[0]);
2087
+ const settlementRV = toNumberRV(topLeft(args[0]));
2062
2088
  if (isError(settlementRV)) {
2063
2089
  return settlementRV;
2064
2090
  }
2065
- const maturityRV = toNumberRV(args[1]);
2091
+ const maturityRV = toNumberRV(topLeft(args[1]));
2066
2092
  if (isError(maturityRV)) {
2067
2093
  return maturityRV;
2068
2094
  }
2069
- const issueRV = toNumberRV(args[2]);
2095
+ const issueRV = toNumberRV(topLeft(args[2]));
2070
2096
  if (isError(issueRV)) {
2071
2097
  return issueRV;
2072
2098
  }
2073
- const rateRV = toNumberRV(args[3]);
2099
+ const rateRV = toNumberRV(topLeft(args[3]));
2074
2100
  if (isError(rateRV)) {
2075
2101
  return rateRV;
2076
2102
  }
2077
- const yldRV = toNumberRV(args[4]);
2103
+ const yldRV = toNumberRV(topLeft(args[4]));
2078
2104
  if (isError(yldRV)) {
2079
2105
  return yldRV;
2080
2106
  }
2081
- const basisRV = args.length > 5 ? toNumberRV(args[5]) : rvNumber(0);
2107
+ const basisRV = args.length > 5 ? toNumberRV(topLeft(args[5])) : rvNumber(0);
2082
2108
  if (isError(basisRV)) {
2083
2109
  return basisRV;
2084
2110
  }
@@ -2114,27 +2140,27 @@ export const fnPRICEMAT = args => {
2114
2140
  * yield = ((1 + DIM × rate) / (pr/100 + A × rate) - 1) / DSM
2115
2141
  */
2116
2142
  export const fnYIELDMAT = args => {
2117
- const settlementRV = toNumberRV(args[0]);
2143
+ const settlementRV = toNumberRV(topLeft(args[0]));
2118
2144
  if (isError(settlementRV)) {
2119
2145
  return settlementRV;
2120
2146
  }
2121
- const maturityRV = toNumberRV(args[1]);
2147
+ const maturityRV = toNumberRV(topLeft(args[1]));
2122
2148
  if (isError(maturityRV)) {
2123
2149
  return maturityRV;
2124
2150
  }
2125
- const issueRV = toNumberRV(args[2]);
2151
+ const issueRV = toNumberRV(topLeft(args[2]));
2126
2152
  if (isError(issueRV)) {
2127
2153
  return issueRV;
2128
2154
  }
2129
- const rateRV = toNumberRV(args[3]);
2155
+ const rateRV = toNumberRV(topLeft(args[3]));
2130
2156
  if (isError(rateRV)) {
2131
2157
  return rateRV;
2132
2158
  }
2133
- const prRV = toNumberRV(args[4]);
2159
+ const prRV = toNumberRV(topLeft(args[4]));
2134
2160
  if (isError(prRV)) {
2135
2161
  return prRV;
2136
2162
  }
2137
- const basisRV = args.length > 5 ? toNumberRV(args[5]) : rvNumber(0);
2163
+ const basisRV = args.length > 5 ? toNumberRV(topLeft(args[5])) : rvNumber(0);
2138
2164
  if (isError(basisRV)) {
2139
2165
  return basisRV;
2140
2166
  }
@@ -2174,19 +2200,19 @@ export const fnYIELDMAT = args => {
2174
2200
  * settlement/maturity/frequency/basis values, or an error.
2175
2201
  */
2176
2202
  function parseCoupArgs(args) {
2177
- const settlementRV = toNumberRV(args[0]);
2203
+ const settlementRV = toNumberRV(topLeft(args[0]));
2178
2204
  if (isError(settlementRV)) {
2179
2205
  return settlementRV;
2180
2206
  }
2181
- const maturityRV = toNumberRV(args[1]);
2207
+ const maturityRV = toNumberRV(topLeft(args[1]));
2182
2208
  if (isError(maturityRV)) {
2183
2209
  return maturityRV;
2184
2210
  }
2185
- const frequencyRV = toNumberRV(args[2]);
2211
+ const frequencyRV = toNumberRV(topLeft(args[2]));
2186
2212
  if (isError(frequencyRV)) {
2187
2213
  return frequencyRV;
2188
2214
  }
2189
- const basisRV = args.length > 3 ? toNumberRV(args[3]) : rvNumber(0);
2215
+ const basisRV = args.length > 3 ? toNumberRV(topLeft(args[3])) : rvNumber(0);
2190
2216
  if (isError(basisRV)) {
2191
2217
  return basisRV;
2192
2218
  }