@cj-tech-master/excelts 9.2.1 → 9.3.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 (383) hide show
  1. package/README.md +25 -2
  2. package/README_zh.md +29 -6
  3. package/dist/browser/index.browser.d.ts +1 -1
  4. package/dist/browser/index.browser.js +4 -0
  5. package/dist/browser/index.d.ts +1 -1
  6. package/dist/browser/index.js +4 -0
  7. package/dist/browser/modules/excel/cell.d.ts +17 -3
  8. package/dist/browser/modules/excel/cell.js +170 -22
  9. package/dist/browser/modules/excel/defined-names.d.ts +96 -1
  10. package/dist/browser/modules/excel/defined-names.js +411 -21
  11. package/dist/browser/modules/excel/image.d.ts +11 -0
  12. package/dist/browser/modules/excel/image.js +24 -1
  13. package/dist/browser/modules/excel/stream/workbook-reader.browser.d.ts +9 -3
  14. package/dist/browser/modules/excel/stream/workbook-reader.browser.js +14 -0
  15. package/dist/browser/modules/excel/stream/workbook-reader.d.ts +2 -1
  16. package/dist/browser/modules/excel/stream/workbook-writer.browser.d.ts +39 -5
  17. package/dist/browser/modules/excel/stream/workbook-writer.browser.js +48 -1
  18. package/dist/browser/modules/excel/stream/workbook-writer.d.ts +3 -2
  19. package/dist/browser/modules/excel/stream/worksheet-reader.js +17 -1
  20. package/dist/browser/modules/excel/stream/worksheet-writer.d.ts +39 -6
  21. package/dist/browser/modules/excel/stream/worksheet-writer.js +45 -5
  22. package/dist/browser/modules/excel/table.js +15 -2
  23. package/dist/browser/modules/excel/types.d.ts +133 -2
  24. package/dist/browser/modules/excel/utils/col-cache.d.ts +1 -0
  25. package/dist/browser/modules/excel/utils/col-cache.js +15 -0
  26. package/dist/browser/modules/excel/utils/drawing-utils.d.ts +3 -3
  27. package/dist/browser/modules/excel/utils/drawing-utils.js +4 -0
  28. package/dist/browser/modules/excel/utils/external-link-formula.d.ts +76 -0
  29. package/dist/browser/modules/excel/utils/external-link-formula.js +208 -0
  30. package/dist/browser/modules/excel/utils/iterate-stream.d.ts +9 -3
  31. package/dist/browser/modules/excel/utils/iterate-stream.js +3 -1
  32. package/dist/browser/modules/excel/utils/ooxml-paths.d.ts +19 -0
  33. package/dist/browser/modules/excel/utils/ooxml-paths.js +37 -2
  34. package/dist/browser/modules/excel/utils/shared-strings.d.ts +8 -3
  35. package/dist/browser/modules/excel/utils/shared-strings.js +21 -2
  36. package/dist/browser/modules/excel/utils/workbook-protection.d.ts +30 -0
  37. package/dist/browser/modules/excel/utils/workbook-protection.js +30 -0
  38. package/dist/browser/modules/excel/workbook.browser.d.ts +257 -6
  39. package/dist/browser/modules/excel/workbook.browser.js +318 -34
  40. package/dist/browser/modules/excel/workbook.d.ts +1 -1
  41. package/dist/browser/modules/excel/worksheet.d.ts +3 -1
  42. package/dist/browser/modules/excel/worksheet.js +21 -2
  43. package/dist/browser/modules/excel/xlsx/rel-type.d.ts +15 -0
  44. package/dist/browser/modules/excel/xlsx/rel-type.js +16 -1
  45. package/dist/browser/modules/excel/xlsx/xform/book/defined-name-xform.d.ts +6 -5
  46. package/dist/browser/modules/excel/xlsx/xform/book/defined-name-xform.js +21 -86
  47. package/dist/browser/modules/excel/xlsx/xform/book/external-link-xform.d.ts +84 -0
  48. package/dist/browser/modules/excel/xlsx/xform/book/external-link-xform.js +330 -0
  49. package/dist/browser/modules/excel/xlsx/xform/book/external-reference-xform.d.ts +17 -0
  50. package/dist/browser/modules/excel/xlsx/xform/book/external-reference-xform.js +24 -0
  51. package/dist/browser/modules/excel/xlsx/xform/book/workbook-calc-properties-xform.d.ts +3 -0
  52. package/dist/browser/modules/excel/xlsx/xform/book/workbook-calc-properties-xform.js +11 -2
  53. package/dist/browser/modules/excel/xlsx/xform/book/workbook-protection-xform.d.ts +20 -0
  54. package/dist/browser/modules/excel/xlsx/xform/book/workbook-protection-xform.js +66 -0
  55. package/dist/browser/modules/excel/xlsx/xform/book/workbook-xform.js +38 -5
  56. package/dist/browser/modules/excel/xlsx/xform/core/content-types-xform.js +19 -1
  57. package/dist/browser/modules/excel/xlsx/xform/core/metadata-xform.d.ts +56 -0
  58. package/dist/browser/modules/excel/xlsx/xform/core/metadata-xform.js +158 -0
  59. package/dist/browser/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.d.ts +26 -0
  60. package/dist/browser/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.js +105 -0
  61. package/dist/browser/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +3 -0
  62. package/dist/browser/modules/excel/xlsx/xform/drawing/drawing-xform.js +10 -2
  63. package/dist/browser/modules/excel/xlsx/xform/sheet/cell-xform.d.ts +1 -1
  64. package/dist/browser/modules/excel/xlsx/xform/sheet/cell-xform.js +166 -8
  65. package/dist/browser/modules/excel/xlsx/xform/sheet/data-validations-xform.js +1 -1
  66. package/dist/browser/modules/excel/xlsx/xform/sheet/ignored-errors-xform.d.ts +21 -0
  67. package/dist/browser/modules/excel/xlsx/xform/sheet/ignored-errors-xform.js +80 -0
  68. package/dist/browser/modules/excel/xlsx/xform/sheet/worksheet-xform.js +9 -4
  69. package/dist/browser/modules/excel/xlsx/xform/style/border-xform.js +4 -1
  70. package/dist/browser/modules/excel/xlsx/xlsx.browser.d.ts +172 -13
  71. package/dist/browser/modules/excel/xlsx/xlsx.browser.js +410 -20
  72. package/dist/browser/modules/excel/xlsx/xlsx.d.ts +7 -4
  73. package/dist/browser/modules/excel/xlsx/xlsx.js +4 -5
  74. package/dist/browser/modules/formula/compile/address-utils.d.ts +62 -0
  75. package/dist/browser/modules/formula/compile/address-utils.js +83 -0
  76. package/dist/browser/modules/formula/compile/binder.d.ts +42 -0
  77. package/dist/browser/modules/formula/compile/binder.js +487 -0
  78. package/dist/browser/modules/formula/compile/bound-ast.d.ts +230 -0
  79. package/dist/browser/modules/formula/compile/bound-ast.js +80 -0
  80. package/dist/browser/modules/formula/compile/compiled-formula.d.ts +137 -0
  81. package/dist/browser/modules/formula/compile/compiled-formula.js +383 -0
  82. package/dist/browser/modules/formula/compile/dependency-analysis.d.ts +93 -0
  83. package/dist/browser/modules/formula/compile/dependency-analysis.js +432 -0
  84. package/dist/browser/modules/formula/compile/structured-ref-utils.d.ts +93 -0
  85. package/dist/browser/modules/formula/compile/structured-ref-utils.js +136 -0
  86. package/dist/browser/modules/formula/default-syntax-probe.d.ts +79 -0
  87. package/dist/browser/modules/formula/default-syntax-probe.js +83 -0
  88. package/dist/browser/modules/formula/functions/_date-context.d.ts +4 -0
  89. package/dist/browser/modules/formula/functions/_date-context.js +29 -0
  90. package/dist/browser/modules/formula/functions/_shared.d.ts +121 -0
  91. package/dist/browser/modules/formula/functions/_shared.js +381 -0
  92. package/dist/browser/modules/formula/functions/conditional.d.ts +27 -0
  93. package/dist/browser/modules/formula/functions/conditional.js +343 -0
  94. package/dist/browser/modules/formula/functions/database.d.ts +37 -0
  95. package/dist/browser/modules/formula/functions/database.js +274 -0
  96. package/dist/browser/modules/formula/functions/date.d.ts +61 -0
  97. package/dist/browser/modules/formula/functions/date.js +855 -0
  98. package/dist/browser/modules/formula/functions/dynamic-array.d.ts +23 -0
  99. package/dist/browser/modules/formula/functions/dynamic-array.js +860 -0
  100. package/dist/browser/modules/formula/functions/engineering.d.ts +57 -0
  101. package/dist/browser/modules/formula/functions/engineering.js +1128 -0
  102. package/dist/browser/modules/formula/functions/financial.d.ts +202 -0
  103. package/dist/browser/modules/formula/functions/financial.js +2296 -0
  104. package/dist/browser/modules/formula/functions/lookup.d.ts +18 -0
  105. package/dist/browser/modules/formula/functions/lookup.js +886 -0
  106. package/dist/browser/modules/formula/functions/math.d.ts +114 -0
  107. package/dist/browser/modules/formula/functions/math.js +1406 -0
  108. package/dist/browser/modules/formula/functions/statistical.d.ts +193 -0
  109. package/dist/browser/modules/formula/functions/statistical.js +3390 -0
  110. package/dist/browser/modules/formula/functions/text.d.ts +86 -0
  111. package/dist/browser/modules/formula/functions/text.js +1845 -0
  112. package/dist/browser/modules/formula/host-registry.d.ts +53 -0
  113. package/dist/browser/modules/formula/host-registry.js +69 -0
  114. package/dist/browser/modules/formula/index.d.ts +39 -0
  115. package/dist/browser/modules/formula/index.js +49 -0
  116. package/dist/browser/modules/formula/install.d.ts +62 -0
  117. package/dist/browser/modules/formula/install.js +88 -0
  118. package/dist/browser/modules/formula/integration/apply-writeback-plan.d.ts +26 -0
  119. package/dist/browser/modules/formula/integration/apply-writeback-plan.js +210 -0
  120. package/dist/browser/modules/formula/integration/calculate-formulas-impl.d.ts +30 -0
  121. package/dist/browser/modules/formula/integration/calculate-formulas-impl.js +616 -0
  122. package/dist/browser/modules/formula/integration/calculate-formulas.d.ts +67 -0
  123. package/dist/browser/modules/formula/integration/calculate-formulas.js +68 -0
  124. package/dist/browser/modules/formula/integration/formula-instance.d.ts +64 -0
  125. package/dist/browser/modules/formula/integration/formula-instance.js +79 -0
  126. package/dist/browser/modules/formula/integration/workbook-adapter.d.ts +26 -0
  127. package/dist/browser/modules/formula/integration/workbook-adapter.js +324 -0
  128. package/dist/browser/modules/formula/integration/workbook-snapshot.d.ts +267 -0
  129. package/dist/browser/modules/formula/integration/workbook-snapshot.js +77 -0
  130. package/dist/browser/modules/formula/materialize/build-writeback-plan.d.ts +34 -0
  131. package/dist/browser/modules/formula/materialize/build-writeback-plan.js +473 -0
  132. package/dist/browser/modules/formula/materialize/spill-engine.d.ts +9 -0
  133. package/dist/browser/modules/formula/materialize/spill-engine.js +38 -0
  134. package/dist/browser/modules/formula/materialize/types.d.ts +179 -0
  135. package/dist/browser/modules/formula/materialize/types.js +29 -0
  136. package/dist/browser/modules/formula/materialize/writeback-plan.d.ts +167 -0
  137. package/dist/browser/modules/formula/materialize/writeback-plan.js +27 -0
  138. package/dist/browser/modules/formula/runtime/evaluator.d.ts +151 -0
  139. package/dist/browser/modules/formula/runtime/evaluator.js +2291 -0
  140. package/dist/browser/modules/formula/runtime/function-registry.d.ts +47 -0
  141. package/dist/browser/modules/formula/runtime/function-registry.js +840 -0
  142. package/dist/browser/modules/formula/runtime/values.d.ts +211 -0
  143. package/dist/browser/modules/formula/runtime/values.js +385 -0
  144. package/dist/browser/modules/formula/syntax/ast.d.ts +129 -0
  145. package/dist/browser/modules/formula/syntax/ast.js +28 -0
  146. package/dist/browser/modules/formula/syntax/parser.d.ts +18 -0
  147. package/dist/browser/modules/formula/syntax/parser.js +439 -0
  148. package/dist/browser/modules/formula/syntax/token-types.d.ts +153 -0
  149. package/dist/browser/modules/formula/syntax/token-types.js +59 -0
  150. package/dist/browser/modules/formula/syntax/tokenizer.d.ts +10 -0
  151. package/dist/browser/modules/formula/syntax/tokenizer.js +1074 -0
  152. package/dist/browser/modules/pdf/excel-bridge.js +9 -0
  153. package/dist/cjs/index.js +4 -0
  154. package/dist/cjs/modules/excel/cell.js +170 -22
  155. package/dist/cjs/modules/excel/defined-names.js +411 -21
  156. package/dist/cjs/modules/excel/image.js +24 -1
  157. package/dist/cjs/modules/excel/stream/workbook-reader.browser.js +14 -0
  158. package/dist/cjs/modules/excel/stream/workbook-writer.browser.js +48 -1
  159. package/dist/cjs/modules/excel/stream/worksheet-reader.js +17 -1
  160. package/dist/cjs/modules/excel/stream/worksheet-writer.js +45 -5
  161. package/dist/cjs/modules/excel/table.js +15 -2
  162. package/dist/cjs/modules/excel/utils/col-cache.js +15 -0
  163. package/dist/cjs/modules/excel/utils/drawing-utils.js +4 -0
  164. package/dist/cjs/modules/excel/utils/external-link-formula.js +212 -0
  165. package/dist/cjs/modules/excel/utils/iterate-stream.js +3 -1
  166. package/dist/cjs/modules/excel/utils/ooxml-paths.js +42 -2
  167. package/dist/cjs/modules/excel/utils/shared-strings.js +21 -2
  168. package/dist/cjs/modules/excel/utils/workbook-protection.js +33 -0
  169. package/dist/cjs/modules/excel/workbook.browser.js +318 -34
  170. package/dist/cjs/modules/excel/worksheet.js +20 -1
  171. package/dist/cjs/modules/excel/xlsx/rel-type.js +16 -1
  172. package/dist/cjs/modules/excel/xlsx/xform/book/defined-name-xform.js +21 -86
  173. package/dist/cjs/modules/excel/xlsx/xform/book/external-link-xform.js +333 -0
  174. package/dist/cjs/modules/excel/xlsx/xform/book/external-reference-xform.js +27 -0
  175. package/dist/cjs/modules/excel/xlsx/xform/book/workbook-calc-properties-xform.js +11 -2
  176. package/dist/cjs/modules/excel/xlsx/xform/book/workbook-protection-xform.js +69 -0
  177. package/dist/cjs/modules/excel/xlsx/xform/book/workbook-xform.js +38 -5
  178. package/dist/cjs/modules/excel/xlsx/xform/core/content-types-xform.js +18 -0
  179. package/dist/cjs/modules/excel/xlsx/xform/core/metadata-xform.js +161 -0
  180. package/dist/cjs/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.js +108 -0
  181. package/dist/cjs/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +3 -0
  182. package/dist/cjs/modules/excel/xlsx/xform/drawing/drawing-xform.js +10 -2
  183. package/dist/cjs/modules/excel/xlsx/xform/sheet/cell-xform.js +166 -8
  184. package/dist/cjs/modules/excel/xlsx/xform/sheet/data-validations-xform.js +1 -1
  185. package/dist/cjs/modules/excel/xlsx/xform/sheet/ignored-errors-xform.js +83 -0
  186. package/dist/cjs/modules/excel/xlsx/xform/sheet/worksheet-xform.js +9 -4
  187. package/dist/cjs/modules/excel/xlsx/xform/style/border-xform.js +4 -1
  188. package/dist/cjs/modules/excel/xlsx/xlsx.browser.js +408 -18
  189. package/dist/cjs/modules/excel/xlsx/xlsx.js +4 -5
  190. package/dist/cjs/modules/formula/compile/address-utils.js +89 -0
  191. package/dist/cjs/modules/formula/compile/binder.js +489 -0
  192. package/dist/cjs/modules/formula/compile/bound-ast.js +68 -0
  193. package/dist/cjs/modules/formula/compile/compiled-formula.js +387 -0
  194. package/dist/cjs/modules/formula/compile/dependency-analysis.js +437 -0
  195. package/dist/cjs/modules/formula/compile/structured-ref-utils.js +141 -0
  196. package/dist/cjs/modules/formula/default-syntax-probe.js +87 -0
  197. package/dist/cjs/modules/formula/functions/_date-context.js +33 -0
  198. package/dist/cjs/modules/formula/functions/_shared.js +396 -0
  199. package/dist/cjs/modules/formula/functions/conditional.js +354 -0
  200. package/dist/cjs/modules/formula/functions/database.js +288 -0
  201. package/dist/cjs/modules/formula/functions/date.js +883 -0
  202. package/dist/cjs/modules/formula/functions/dynamic-array.js +881 -0
  203. package/dist/cjs/modules/formula/functions/engineering.js +1183 -0
  204. package/dist/cjs/modules/formula/functions/financial.js +2348 -0
  205. package/dist/cjs/modules/formula/functions/lookup.js +902 -0
  206. package/dist/cjs/modules/formula/functions/math.js +1487 -0
  207. package/dist/cjs/modules/formula/functions/statistical.js +3488 -0
  208. package/dist/cjs/modules/formula/functions/text.js +1889 -0
  209. package/dist/cjs/modules/formula/host-registry.js +75 -0
  210. package/dist/cjs/modules/formula/index.js +58 -0
  211. package/dist/cjs/modules/formula/install.js +93 -0
  212. package/dist/cjs/modules/formula/integration/apply-writeback-plan.js +213 -0
  213. package/dist/cjs/modules/formula/integration/calculate-formulas-impl.js +619 -0
  214. package/dist/cjs/modules/formula/integration/calculate-formulas.js +71 -0
  215. package/dist/cjs/modules/formula/integration/formula-instance.js +82 -0
  216. package/dist/cjs/modules/formula/integration/workbook-adapter.js +327 -0
  217. package/dist/cjs/modules/formula/integration/workbook-snapshot.js +84 -0
  218. package/dist/cjs/modules/formula/materialize/build-writeback-plan.js +475 -0
  219. package/dist/cjs/modules/formula/materialize/spill-engine.js +42 -0
  220. package/dist/cjs/modules/formula/materialize/types.js +32 -0
  221. package/dist/cjs/modules/formula/materialize/writeback-plan.js +28 -0
  222. package/dist/cjs/modules/formula/runtime/evaluator.js +2298 -0
  223. package/dist/cjs/modules/formula/runtime/function-registry.js +846 -0
  224. package/dist/cjs/modules/formula/runtime/values.js +385 -0
  225. package/dist/cjs/modules/formula/syntax/ast.js +8 -0
  226. package/dist/cjs/modules/formula/syntax/parser.js +440 -0
  227. package/dist/cjs/modules/formula/syntax/token-types.js +32 -0
  228. package/dist/cjs/modules/formula/syntax/tokenizer.js +1076 -0
  229. package/dist/cjs/modules/pdf/excel-bridge.js +9 -0
  230. package/dist/esm/index.browser.js +4 -0
  231. package/dist/esm/index.js +4 -0
  232. package/dist/esm/modules/excel/cell.js +170 -22
  233. package/dist/esm/modules/excel/defined-names.js +411 -21
  234. package/dist/esm/modules/excel/image.js +24 -1
  235. package/dist/esm/modules/excel/stream/workbook-reader.browser.js +14 -0
  236. package/dist/esm/modules/excel/stream/workbook-writer.browser.js +48 -1
  237. package/dist/esm/modules/excel/stream/worksheet-reader.js +17 -1
  238. package/dist/esm/modules/excel/stream/worksheet-writer.js +45 -5
  239. package/dist/esm/modules/excel/table.js +15 -2
  240. package/dist/esm/modules/excel/utils/col-cache.js +15 -0
  241. package/dist/esm/modules/excel/utils/drawing-utils.js +4 -0
  242. package/dist/esm/modules/excel/utils/external-link-formula.js +208 -0
  243. package/dist/esm/modules/excel/utils/iterate-stream.js +3 -1
  244. package/dist/esm/modules/excel/utils/ooxml-paths.js +37 -2
  245. package/dist/esm/modules/excel/utils/shared-strings.js +21 -2
  246. package/dist/esm/modules/excel/utils/workbook-protection.js +30 -0
  247. package/dist/esm/modules/excel/workbook.browser.js +318 -34
  248. package/dist/esm/modules/excel/worksheet.js +21 -2
  249. package/dist/esm/modules/excel/xlsx/rel-type.js +16 -1
  250. package/dist/esm/modules/excel/xlsx/xform/book/defined-name-xform.js +21 -86
  251. package/dist/esm/modules/excel/xlsx/xform/book/external-link-xform.js +330 -0
  252. package/dist/esm/modules/excel/xlsx/xform/book/external-reference-xform.js +24 -0
  253. package/dist/esm/modules/excel/xlsx/xform/book/workbook-calc-properties-xform.js +11 -2
  254. package/dist/esm/modules/excel/xlsx/xform/book/workbook-protection-xform.js +66 -0
  255. package/dist/esm/modules/excel/xlsx/xform/book/workbook-xform.js +38 -5
  256. package/dist/esm/modules/excel/xlsx/xform/core/content-types-xform.js +19 -1
  257. package/dist/esm/modules/excel/xlsx/xform/core/metadata-xform.js +158 -0
  258. package/dist/esm/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.js +105 -0
  259. package/dist/esm/modules/excel/xlsx/xform/drawing/base-cell-anchor-xform.js +3 -0
  260. package/dist/esm/modules/excel/xlsx/xform/drawing/drawing-xform.js +10 -2
  261. package/dist/esm/modules/excel/xlsx/xform/sheet/cell-xform.js +166 -8
  262. package/dist/esm/modules/excel/xlsx/xform/sheet/data-validations-xform.js +1 -1
  263. package/dist/esm/modules/excel/xlsx/xform/sheet/ignored-errors-xform.js +80 -0
  264. package/dist/esm/modules/excel/xlsx/xform/sheet/worksheet-xform.js +9 -4
  265. package/dist/esm/modules/excel/xlsx/xform/style/border-xform.js +4 -1
  266. package/dist/esm/modules/excel/xlsx/xlsx.browser.js +410 -20
  267. package/dist/esm/modules/excel/xlsx/xlsx.js +4 -5
  268. package/dist/esm/modules/formula/compile/address-utils.js +83 -0
  269. package/dist/esm/modules/formula/compile/binder.js +487 -0
  270. package/dist/esm/modules/formula/compile/bound-ast.js +80 -0
  271. package/dist/esm/modules/formula/compile/compiled-formula.js +383 -0
  272. package/dist/esm/modules/formula/compile/dependency-analysis.js +432 -0
  273. package/dist/esm/modules/formula/compile/structured-ref-utils.js +136 -0
  274. package/dist/esm/modules/formula/default-syntax-probe.js +83 -0
  275. package/dist/esm/modules/formula/functions/_date-context.js +29 -0
  276. package/dist/esm/modules/formula/functions/_shared.js +381 -0
  277. package/dist/esm/modules/formula/functions/conditional.js +343 -0
  278. package/dist/esm/modules/formula/functions/database.js +274 -0
  279. package/dist/esm/modules/formula/functions/date.js +855 -0
  280. package/dist/esm/modules/formula/functions/dynamic-array.js +860 -0
  281. package/dist/esm/modules/formula/functions/engineering.js +1128 -0
  282. package/dist/esm/modules/formula/functions/financial.js +2296 -0
  283. package/dist/esm/modules/formula/functions/lookup.js +886 -0
  284. package/dist/esm/modules/formula/functions/math.js +1406 -0
  285. package/dist/esm/modules/formula/functions/statistical.js +3390 -0
  286. package/dist/esm/modules/formula/functions/text.js +1845 -0
  287. package/dist/esm/modules/formula/host-registry.js +69 -0
  288. package/dist/esm/modules/formula/index.js +49 -0
  289. package/dist/esm/modules/formula/install.js +88 -0
  290. package/dist/esm/modules/formula/integration/apply-writeback-plan.js +210 -0
  291. package/dist/esm/modules/formula/integration/calculate-formulas-impl.js +616 -0
  292. package/dist/esm/modules/formula/integration/calculate-formulas.js +68 -0
  293. package/dist/esm/modules/formula/integration/formula-instance.js +79 -0
  294. package/dist/esm/modules/formula/integration/workbook-adapter.js +324 -0
  295. package/dist/esm/modules/formula/integration/workbook-snapshot.js +77 -0
  296. package/dist/esm/modules/formula/materialize/build-writeback-plan.js +473 -0
  297. package/dist/esm/modules/formula/materialize/spill-engine.js +38 -0
  298. package/dist/esm/modules/formula/materialize/types.js +29 -0
  299. package/dist/esm/modules/formula/materialize/writeback-plan.js +27 -0
  300. package/dist/esm/modules/formula/runtime/evaluator.js +2291 -0
  301. package/dist/esm/modules/formula/runtime/function-registry.js +840 -0
  302. package/dist/esm/modules/formula/runtime/values.js +385 -0
  303. package/dist/esm/modules/formula/syntax/ast.js +28 -0
  304. package/dist/esm/modules/formula/syntax/parser.js +439 -0
  305. package/dist/esm/modules/formula/syntax/token-types.js +59 -0
  306. package/dist/esm/modules/formula/syntax/tokenizer.js +1074 -0
  307. package/dist/esm/modules/pdf/excel-bridge.js +9 -0
  308. package/dist/iife/excelts.iife.js +2302 -373
  309. package/dist/iife/excelts.iife.js.map +1 -1
  310. package/dist/iife/excelts.iife.min.js +34 -34
  311. package/dist/types/index.browser.d.ts +1 -1
  312. package/dist/types/index.d.ts +1 -1
  313. package/dist/types/modules/excel/cell.d.ts +17 -3
  314. package/dist/types/modules/excel/defined-names.d.ts +96 -1
  315. package/dist/types/modules/excel/image.d.ts +11 -0
  316. package/dist/types/modules/excel/stream/workbook-reader.browser.d.ts +9 -3
  317. package/dist/types/modules/excel/stream/workbook-reader.d.ts +2 -1
  318. package/dist/types/modules/excel/stream/workbook-writer.browser.d.ts +39 -5
  319. package/dist/types/modules/excel/stream/workbook-writer.d.ts +3 -2
  320. package/dist/types/modules/excel/stream/worksheet-writer.d.ts +39 -6
  321. package/dist/types/modules/excel/types.d.ts +133 -2
  322. package/dist/types/modules/excel/utils/col-cache.d.ts +1 -0
  323. package/dist/types/modules/excel/utils/drawing-utils.d.ts +3 -3
  324. package/dist/types/modules/excel/utils/external-link-formula.d.ts +76 -0
  325. package/dist/types/modules/excel/utils/iterate-stream.d.ts +9 -3
  326. package/dist/types/modules/excel/utils/ooxml-paths.d.ts +19 -0
  327. package/dist/types/modules/excel/utils/shared-strings.d.ts +8 -3
  328. package/dist/types/modules/excel/utils/workbook-protection.d.ts +30 -0
  329. package/dist/types/modules/excel/workbook.browser.d.ts +257 -6
  330. package/dist/types/modules/excel/workbook.d.ts +1 -1
  331. package/dist/types/modules/excel/worksheet.d.ts +3 -1
  332. package/dist/types/modules/excel/xlsx/rel-type.d.ts +15 -0
  333. package/dist/types/modules/excel/xlsx/xform/book/defined-name-xform.d.ts +6 -5
  334. package/dist/types/modules/excel/xlsx/xform/book/external-link-xform.d.ts +84 -0
  335. package/dist/types/modules/excel/xlsx/xform/book/external-reference-xform.d.ts +17 -0
  336. package/dist/types/modules/excel/xlsx/xform/book/workbook-calc-properties-xform.d.ts +3 -0
  337. package/dist/types/modules/excel/xlsx/xform/book/workbook-protection-xform.d.ts +20 -0
  338. package/dist/types/modules/excel/xlsx/xform/core/metadata-xform.d.ts +56 -0
  339. package/dist/types/modules/excel/xlsx/xform/drawing/absolute-anchor-xform.d.ts +26 -0
  340. package/dist/types/modules/excel/xlsx/xform/sheet/cell-xform.d.ts +1 -1
  341. package/dist/types/modules/excel/xlsx/xform/sheet/ignored-errors-xform.d.ts +21 -0
  342. package/dist/types/modules/excel/xlsx/xlsx.browser.d.ts +172 -13
  343. package/dist/types/modules/excel/xlsx/xlsx.d.ts +7 -4
  344. package/dist/types/modules/formula/compile/address-utils.d.ts +62 -0
  345. package/dist/types/modules/formula/compile/binder.d.ts +42 -0
  346. package/dist/types/modules/formula/compile/bound-ast.d.ts +230 -0
  347. package/dist/types/modules/formula/compile/compiled-formula.d.ts +137 -0
  348. package/dist/types/modules/formula/compile/dependency-analysis.d.ts +93 -0
  349. package/dist/types/modules/formula/compile/structured-ref-utils.d.ts +93 -0
  350. package/dist/types/modules/formula/default-syntax-probe.d.ts +79 -0
  351. package/dist/types/modules/formula/functions/_date-context.d.ts +4 -0
  352. package/dist/types/modules/formula/functions/_shared.d.ts +121 -0
  353. package/dist/types/modules/formula/functions/conditional.d.ts +27 -0
  354. package/dist/types/modules/formula/functions/database.d.ts +37 -0
  355. package/dist/types/modules/formula/functions/date.d.ts +61 -0
  356. package/dist/types/modules/formula/functions/dynamic-array.d.ts +23 -0
  357. package/dist/types/modules/formula/functions/engineering.d.ts +57 -0
  358. package/dist/types/modules/formula/functions/financial.d.ts +202 -0
  359. package/dist/types/modules/formula/functions/lookup.d.ts +18 -0
  360. package/dist/types/modules/formula/functions/math.d.ts +114 -0
  361. package/dist/types/modules/formula/functions/statistical.d.ts +193 -0
  362. package/dist/types/modules/formula/functions/text.d.ts +86 -0
  363. package/dist/types/modules/formula/host-registry.d.ts +53 -0
  364. package/dist/types/modules/formula/index.d.ts +39 -0
  365. package/dist/types/modules/formula/install.d.ts +62 -0
  366. package/dist/types/modules/formula/integration/apply-writeback-plan.d.ts +26 -0
  367. package/dist/types/modules/formula/integration/calculate-formulas-impl.d.ts +30 -0
  368. package/dist/types/modules/formula/integration/calculate-formulas.d.ts +67 -0
  369. package/dist/types/modules/formula/integration/formula-instance.d.ts +64 -0
  370. package/dist/types/modules/formula/integration/workbook-adapter.d.ts +26 -0
  371. package/dist/types/modules/formula/integration/workbook-snapshot.d.ts +267 -0
  372. package/dist/types/modules/formula/materialize/build-writeback-plan.d.ts +34 -0
  373. package/dist/types/modules/formula/materialize/spill-engine.d.ts +9 -0
  374. package/dist/types/modules/formula/materialize/types.d.ts +179 -0
  375. package/dist/types/modules/formula/materialize/writeback-plan.d.ts +167 -0
  376. package/dist/types/modules/formula/runtime/evaluator.d.ts +151 -0
  377. package/dist/types/modules/formula/runtime/function-registry.d.ts +47 -0
  378. package/dist/types/modules/formula/runtime/values.d.ts +211 -0
  379. package/dist/types/modules/formula/syntax/ast.d.ts +129 -0
  380. package/dist/types/modules/formula/syntax/parser.d.ts +18 -0
  381. package/dist/types/modules/formula/syntax/token-types.d.ts +153 -0
  382. package/dist/types/modules/formula/syntax/tokenizer.d.ts +10 -0
  383. package/package.json +28 -28
@@ -0,0 +1,1128 @@
1
+ /**
2
+ * Engineering Functions — Native RuntimeValue implementation.
3
+ */
4
+ import { RVKind, ERRORS, isError, toNumberRV, toStringRV, topLeft, rvNumber, rvString } from "../runtime/values.js";
5
+ import { checkError } from "./_shared.js";
6
+ // ============================================================================
7
+ // Base Conversion Functions
8
+ // ============================================================================
9
+ export const fnBIN2DEC = args => {
10
+ const err = checkError(args[0]);
11
+ if (err) {
12
+ return err;
13
+ }
14
+ const s = toStringRV(args[0]);
15
+ if (!/^[01]{1,10}$/.test(s)) {
16
+ return ERRORS.NUM;
17
+ }
18
+ // 10-bit two's complement
19
+ if (s.length === 10 && s[0] === "1") {
20
+ return rvNumber(parseInt(s.slice(1), 2) - 512);
21
+ }
22
+ return rvNumber(parseInt(s, 2));
23
+ };
24
+ export const fnDEC2BIN = args => {
25
+ const nRV = toNumberRV(args[0]);
26
+ if (isError(nRV)) {
27
+ return nRV;
28
+ }
29
+ // Excel's DEC→BASE family truncates toward zero, so negative fractions
30
+ // become `0`, not `-1` as `Math.floor` would produce.
31
+ const n = Math.trunc(nRV.value);
32
+ if (n < -512 || n > 511) {
33
+ return ERRORS.NUM;
34
+ }
35
+ // `places` is only meaningful when supplied and the input is non-negative.
36
+ // Excel restricts it to the [1, 10] range and returns #NUM! otherwise.
37
+ // For negative inputs Excel ignores `places` entirely, so we validate it
38
+ // only on the non-negative branch below.
39
+ const hasPlaces = args.length > 1 && args[1].kind !== RVKind.Blank;
40
+ const placesRV = hasPlaces ? toNumberRV(args[1]) : rvNumber(0);
41
+ if (isError(placesRV)) {
42
+ return placesRV;
43
+ }
44
+ const places = Math.trunc(placesRV.value);
45
+ if (n < 0) {
46
+ return rvString((n + 1024).toString(2));
47
+ }
48
+ if (hasPlaces && (places < 1 || places > 10)) {
49
+ return ERRORS.NUM;
50
+ }
51
+ const result = n.toString(2);
52
+ return rvString(places > 0 ? result.padStart(places, "0") : result);
53
+ };
54
+ export const fnHEX2DEC = args => {
55
+ const err = checkError(args[0]);
56
+ if (err) {
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) {
83
+ return ERRORS.NUM;
84
+ }
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
+ return rvString(places > 0 ? result.padStart(places, "0") : result);
102
+ };
103
+ export const fnOCT2DEC = args => {
104
+ const err = checkError(args[0]);
105
+ if (err) {
106
+ return err;
107
+ }
108
+ const s = toStringRV(args[0]);
109
+ if (!/^[0-7]{1,10}$/.test(s)) {
110
+ return ERRORS.NUM;
111
+ }
112
+ const num = parseInt(s, 8);
113
+ if (s.length === 10 && parseInt(s[0]) >= 4) {
114
+ return rvNumber(num - Math.pow(8, 10));
115
+ }
116
+ 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
+ };
150
+ /**
151
+ * Generic helper for the X2Y conversion family (BIN2HEX, HEX2BIN, …).
152
+ *
153
+ * `parseNInput` extracts the signed decimal value of the input string in
154
+ * its source base, enforcing the Excel length / digit-alphabet rules.
155
+ * `formatN` serialises the decimal back in the target base, honouring
156
+ * the optional `places` argument and the 10-digit two's-complement
157
+ * convention for negatives. Returning an `ErrorValue` from either stage
158
+ * aborts with that error — keeps each pairwise converter a three-liner.
159
+ */
160
+ function convertBase(args, parseNInput, format) {
161
+ const err = checkError(args[0]);
162
+ if (err) {
163
+ return err;
164
+ }
165
+ const s = toStringRV(args[0]);
166
+ const n = parseNInput(s);
167
+ if (typeof n !== "number") {
168
+ return n;
169
+ }
170
+ const hasPlaces = args.length > 1 && args[1].kind !== RVKind.Blank;
171
+ const placesRV = hasPlaces ? toNumberRV(args[1]) : rvNumber(0);
172
+ if (isError(placesRV)) {
173
+ return placesRV;
174
+ }
175
+ const places = Math.trunc(placesRV.value);
176
+ return format(n, places, hasPlaces);
177
+ }
178
+ /** Parse a binary input string as a signed decimal, or return #NUM!. */
179
+ function parseBinInput(s) {
180
+ if (!/^[01]{1,10}$/.test(s)) {
181
+ return ERRORS.NUM;
182
+ }
183
+ const num = parseInt(s, 2);
184
+ return s.length === 10 && s[0] === "1" ? num - Math.pow(2, 10) : num;
185
+ }
186
+ function parseOctInput(s) {
187
+ if (!/^[0-7]{1,10}$/.test(s)) {
188
+ return ERRORS.NUM;
189
+ }
190
+ const num = parseInt(s, 8);
191
+ return s.length === 10 && parseInt(s[0]) >= 4 ? num - Math.pow(8, 10) : num;
192
+ }
193
+ function parseHexInput(s) {
194
+ if (!/^[0-9A-Fa-f]{1,10}$/.test(s)) {
195
+ return ERRORS.NUM;
196
+ }
197
+ const num = parseInt(s, 16);
198
+ return s.length === 10 && parseInt(s[0], 16) >= 8 ? num - Math.pow(16, 10) : num;
199
+ }
200
+ /** Format a signed decimal to the target base; handles 10-digit negatives. */
201
+ function formatToBase(n, base, maxDigits, places, hasPlaces) {
202
+ if (n < 0) {
203
+ // Two's-complement style: Excel emits the full 10-digit width.
204
+ return rvString((n + Math.pow(base, 10)).toString(base).toUpperCase());
205
+ }
206
+ if (hasPlaces && (places < 1 || places > maxDigits)) {
207
+ return ERRORS.NUM;
208
+ }
209
+ const result = n.toString(base).toUpperCase();
210
+ return rvString(places > 0 ? result.padStart(places, "0") : result);
211
+ }
212
+ export const fnBIN2HEX = args => convertBase(args, parseBinInput, (n, places, hasPlaces) => formatToBase(n, 16, 10, places, hasPlaces));
213
+ export const fnBIN2OCT = args => convertBase(args, parseBinInput, (n, places, hasPlaces) => formatToBase(n, 8, 10, places, hasPlaces));
214
+ export const fnHEX2BIN = args => convertBase(args, parseHexInput, (n, places, hasPlaces) => {
215
+ // BIN can only hold values in [-512, 511]; Excel rejects anything wider.
216
+ if (n < -512 || n > 511) {
217
+ return ERRORS.NUM;
218
+ }
219
+ return formatToBase(n, 2, 10, places, hasPlaces);
220
+ });
221
+ export const fnHEX2OCT = args => convertBase(args, parseHexInput, (n, places, hasPlaces) => {
222
+ // OCT holds values in [-2^29, 2^29 − 1].
223
+ if (n < -536870912 || n > 536870911) {
224
+ return ERRORS.NUM;
225
+ }
226
+ return formatToBase(n, 8, 10, places, hasPlaces);
227
+ });
228
+ export const fnOCT2BIN = args => convertBase(args, parseOctInput, (n, places, hasPlaces) => {
229
+ if (n < -512 || n > 511) {
230
+ return ERRORS.NUM;
231
+ }
232
+ return formatToBase(n, 2, 10, places, hasPlaces);
233
+ });
234
+ export const fnOCT2HEX = args => convertBase(args, parseOctInput, (n, places, hasPlaces) => formatToBase(n, 16, 10, places, hasPlaces));
235
+ // ============================================================================
236
+ // Bessel functions
237
+ // ============================================================================
238
+ //
239
+ // The four Bessel variants (J, I, K, Y) satisfy recurrences that make a
240
+ // rolling evaluation both simple and numerically stable for modest
241
+ // arguments. Excel restricts these to integer order n >= 0 and real
242
+ // x >= 0; we enforce those bounds and otherwise match the standard
243
+ // power-series / backward-recurrence algorithms used across numerical
244
+ // libraries. Accuracy is better than ~1e-6 relative for |x| <= 30 and n
245
+ // <= 30 — the realistic domain where anyone actually uses BESSEL in a
246
+ // spreadsheet.
247
+ function besselJ(n, x) {
248
+ // Series expansion for moderate x, Miller's backward recurrence for
249
+ // larger x. Switch point chosen empirically where the direct series
250
+ // begins to lose precision.
251
+ if (x === 0) {
252
+ return n === 0 ? 1 : 0;
253
+ }
254
+ const ax = Math.abs(x);
255
+ if (ax < 15) {
256
+ // Direct power series: Jₙ(x) = Σ (-1)^k (x/2)^(n+2k) / (k! (n+k)!)
257
+ const half = x / 2;
258
+ let term = Math.pow(half, n);
259
+ for (let k = 1; k <= n; k++) {
260
+ term /= k;
261
+ }
262
+ let sum = term;
263
+ for (let k = 1; k < 100; k++) {
264
+ term = (-term * half * half) / (k * (n + k));
265
+ sum += term;
266
+ if (Math.abs(term) < 1e-15 * Math.abs(sum)) {
267
+ break;
268
+ }
269
+ }
270
+ return sum;
271
+ }
272
+ // Backward recurrence (Miller's algorithm). Start from a high order,
273
+ // iterate down, normalise using the known sum ∑(−1)ᵏJ₂ₖ = 1.
274
+ //
275
+ // The starting order needs to be (a) even, (b) higher than `n`, and
276
+ // (c) large enough that the recurrence has converged. The classic
277
+ // `2 * (n + ceil(sqrt(40 * n)))` formula collapses to 0 when `n = 0`,
278
+ // which makes the loop never execute and leaves `ans = 0` (wrong —
279
+ // J₀(20) ≈ 0.167, not 0). Floor the start at `2*ceil(x + 20)` so
280
+ // small-`n` large-`x` inputs still get a meaningful number of
281
+ // recurrence steps.
282
+ const startRaw = 2 * (n + Math.ceil(Math.sqrt(40 * Math.max(n, 1))));
283
+ const startMin = 2 * Math.ceil(x + 20);
284
+ let start = Math.max(startRaw, startMin);
285
+ // Make sure start is even so the Σ(-1)^k J_{2k} = 1 identity applies
286
+ // cleanly during the loop below.
287
+ if (start % 2 !== 0) {
288
+ start++;
289
+ }
290
+ let bjp = 0;
291
+ let bj = 1;
292
+ let ans = 0;
293
+ let sum = 0;
294
+ for (let j = start; j > 0; j--) {
295
+ const bjm = (2 * j * bj) / x - bjp;
296
+ bjp = bj;
297
+ bj = bjm;
298
+ if (Math.abs(bj) > 1e10) {
299
+ bj *= 1e-10;
300
+ bjp *= 1e-10;
301
+ ans *= 1e-10;
302
+ sum *= 1e-10;
303
+ }
304
+ if (j % 2 === 0) {
305
+ sum += bj;
306
+ }
307
+ if (j === n) {
308
+ ans = bjp;
309
+ }
310
+ }
311
+ sum = 2 * sum - bj;
312
+ return ans / sum;
313
+ }
314
+ function besselI(n, x) {
315
+ if (x === 0) {
316
+ return n === 0 ? 1 : 0;
317
+ }
318
+ // Iₙ(x) = Σ (x/2)^(n+2k) / (k! (n+k)!)
319
+ const half = x / 2;
320
+ let term = Math.pow(half, n);
321
+ for (let k = 1; k <= n; k++) {
322
+ term /= k;
323
+ }
324
+ let sum = term;
325
+ for (let k = 1; k < 200; k++) {
326
+ term = (term * half * half) / (k * (n + k));
327
+ sum += term;
328
+ if (Math.abs(term) < 1e-15 * Math.abs(sum)) {
329
+ break;
330
+ }
331
+ }
332
+ return sum;
333
+ }
334
+ function besselY(n, x) {
335
+ // Y₀ / Y₁ via standard small-argument expansions; higher orders via
336
+ // forward recurrence. Accuracy is modest (~1e-5) but matches Excel's
337
+ // own precision for BESSELY.
338
+ if (x === 0) {
339
+ return Number.NEGATIVE_INFINITY;
340
+ }
341
+ const y0 = (xv) => {
342
+ if (xv < 8) {
343
+ const y = xv * xv;
344
+ const ans1 = -2957821389 +
345
+ y *
346
+ (7062834065 +
347
+ y * (-512359803.6 + y * (10879881.29 + y * (-86327.92757 + y * 228.4622733))));
348
+ const ans2 = 40076544269 +
349
+ y * (745249964.8 + y * (7189466.438 + y * (47447.2647 + y * (226.1030244 + y))));
350
+ return ans1 / ans2 + 0.636619772 * besselJ(0, xv) * Math.log(xv);
351
+ }
352
+ const z = 8 / xv;
353
+ const y = z * z;
354
+ const ans1 = 1 +
355
+ y * (-0.1098628627e-2 + y * (0.2734510407e-4 + y * (-0.2073370639e-5 + y * 0.2093887211e-6)));
356
+ const ans2 = -0.1562499995e-1 +
357
+ y * (0.1430488765e-3 + y * (-0.6911147651e-5 + y * (0.7621095161e-6 + y * -0.934945152e-7)));
358
+ return (Math.sqrt(0.636619772 / xv) *
359
+ (Math.sin(xv - 0.785398164) * ans1 + z * Math.cos(xv - 0.785398164) * ans2));
360
+ };
361
+ const y1 = (xv) => {
362
+ if (xv < 8) {
363
+ const y = xv * xv;
364
+ const ans1 = xv *
365
+ (-0.4900604943e13 +
366
+ y *
367
+ (0.127527439e13 +
368
+ y *
369
+ (-0.5153438139e11 +
370
+ y * (0.7349264551e9 + y * (-0.4237922726e7 + y * 0.8511937935e4)))));
371
+ const ans2 = 0.249958057e14 +
372
+ y *
373
+ (0.4244419664e12 +
374
+ y *
375
+ (0.3733650367e10 +
376
+ y * (0.2245904002e8 + y * (0.102042605e6 + y * (0.3549632885e3 + y)))));
377
+ return ans1 / ans2 + 0.636619772 * (besselJ(1, xv) * Math.log(xv) - 1 / xv);
378
+ }
379
+ const z = 8 / xv;
380
+ const y = z * z;
381
+ const ans1 = 1 + y * (0.183105e-2 + y * (-0.3516396496e-4 + y * (0.2457520174e-5 + y * -0.240337019e-6)));
382
+ const ans2 = 0.04687499995 +
383
+ y * (-0.2002690873e-3 + y * (0.8449199096e-5 + y * (-0.88228987e-6 + y * 0.105787412e-6)));
384
+ return (Math.sqrt(0.636619772 / xv) *
385
+ (Math.sin(xv - 2.356194491) * ans1 + z * Math.cos(xv - 2.356194491) * ans2));
386
+ };
387
+ if (n === 0) {
388
+ return y0(x);
389
+ }
390
+ if (n === 1) {
391
+ return y1(x);
392
+ }
393
+ let bym = y0(x);
394
+ let by = y1(x);
395
+ for (let j = 1; j < n; j++) {
396
+ const byp = (2 * j * by) / x - bym;
397
+ bym = by;
398
+ by = byp;
399
+ }
400
+ return by;
401
+ }
402
+ function besselK(n, x) {
403
+ if (x === 0) {
404
+ return Number.POSITIVE_INFINITY;
405
+ }
406
+ const k0 = (xv) => {
407
+ if (xv <= 2) {
408
+ const y = (xv * xv) / 4;
409
+ return (-Math.log(xv / 2) * besselI(0, xv) +
410
+ (-0.57721566 +
411
+ y *
412
+ (0.4227842 +
413
+ y *
414
+ (0.23069756 +
415
+ y * (0.0348859 + y * (0.00262698 + y * (0.0001075 + y * 0.0000074)))))));
416
+ }
417
+ const y = 2 / xv;
418
+ return ((Math.exp(-xv) / Math.sqrt(xv)) *
419
+ (1.25331414 +
420
+ y *
421
+ (-0.07832358 +
422
+ y *
423
+ (0.02189568 +
424
+ y * (-0.01062446 + y * (0.00587872 + y * (-0.0025154 + y * 0.00053208)))))));
425
+ };
426
+ const k1 = (xv) => {
427
+ if (xv <= 2) {
428
+ const y = (xv * xv) / 4;
429
+ return (Math.log(xv / 2) * besselI(1, xv) +
430
+ (1 / xv) *
431
+ (1 +
432
+ y *
433
+ (0.15443144 +
434
+ y *
435
+ (-0.67278579 +
436
+ y * (-0.18156897 + y * (-0.01919402 + y * (-0.00110404 + y * -0.00004686)))))));
437
+ }
438
+ const y = 2 / xv;
439
+ return ((Math.exp(-xv) / Math.sqrt(xv)) *
440
+ (1.25331414 +
441
+ y *
442
+ (0.23498619 +
443
+ y *
444
+ (-0.0365562 +
445
+ y * (0.01504268 + y * (-0.00780353 + y * (0.00325614 + y * -0.00068245)))))));
446
+ };
447
+ if (n === 0) {
448
+ return k0(x);
449
+ }
450
+ if (n === 1) {
451
+ return k1(x);
452
+ }
453
+ // Kₙ₊₁(x) = (2n/x) Kₙ(x) + Kₙ₋₁(x)
454
+ let bkm = k0(x);
455
+ let bk = k1(x);
456
+ for (let j = 1; j < n; j++) {
457
+ const bkp = (2 * j * bk) / x + bkm;
458
+ bkm = bk;
459
+ bk = bkp;
460
+ }
461
+ return bk;
462
+ }
463
+ /** Common validation + dispatch for the four BESSEL* functions. */
464
+ function bessel(args, compute, allowZeroX) {
465
+ const xRV = toNumberRV(args[0]);
466
+ if (isError(xRV)) {
467
+ return xRV;
468
+ }
469
+ const nRV = toNumberRV(args[1]);
470
+ if (isError(nRV)) {
471
+ return nRV;
472
+ }
473
+ const n = Math.trunc(nRV.value);
474
+ // Excel accepts any real x for BESSELJ / BESSELI but requires x > 0
475
+ // for BESSELK / BESSELY (the log-term blows up at zero). For all four
476
+ // the order n must be a non-negative integer.
477
+ if (n < 0) {
478
+ return ERRORS.NUM;
479
+ }
480
+ if (!allowZeroX && xRV.value <= 0) {
481
+ return ERRORS.NUM;
482
+ }
483
+ if (allowZeroX && xRV.value < 0) {
484
+ return ERRORS.NUM;
485
+ }
486
+ const result = compute(n, xRV.value);
487
+ return Number.isFinite(result) ? rvNumber(result) : ERRORS.NUM;
488
+ }
489
+ export const fnBESSELJ = args => bessel(args, besselJ, true);
490
+ export const fnBESSELI = args => bessel(args, besselI, true);
491
+ export const fnBESSELK = args => bessel(args, besselK, false);
492
+ export const fnBESSELY = args => bessel(args, besselY, false);
493
+ export const fnDELTA = args => {
494
+ const n1 = toNumberRV(args[0]);
495
+ if (isError(n1)) {
496
+ return n1;
497
+ }
498
+ const n2 = args.length > 1 ? toNumberRV(args[1]) : rvNumber(0);
499
+ if (isError(n2)) {
500
+ return n2;
501
+ }
502
+ return rvNumber(n1.value === n2.value ? 1 : 0);
503
+ };
504
+ export const fnGESTEP = args => {
505
+ const n = toNumberRV(args[0]);
506
+ if (isError(n)) {
507
+ return n;
508
+ }
509
+ const step = args.length > 1 ? toNumberRV(args[1]) : rvNumber(0);
510
+ if (isError(step)) {
511
+ return step;
512
+ }
513
+ return rvNumber(n.value >= step.value ? 1 : 0);
514
+ };
515
+ // ============================================================================
516
+ // Complex Numbers, Bit Operations
517
+ // ============================================================================
518
+ function parseComplex(s) {
519
+ const text = s.trim();
520
+ if (text === "") {
521
+ return null;
522
+ }
523
+ // A valid numeric component (real or imaginary coefficient) must match
524
+ // this strict decimal grammar. Without it, the permissive fallback
525
+ // regex below lets garbage like "1.2.3+4i" or "ee+i" match and we
526
+ // then coerced NaN to 0, silently returning bogus complex numbers for
527
+ // 19 downstream IM* call sites. See R6-P0-2.
528
+ const NUM_RE = /^[+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?$/;
529
+ const toNumStrict = (x) => (NUM_RE.test(x) ? Number(x) : Number.NaN);
530
+ const pureReal = toNumStrict(text);
531
+ if (!Number.isNaN(pureReal) && !text.endsWith("i") && !text.endsWith("j")) {
532
+ return [pureReal, 0];
533
+ }
534
+ if (text === "i" || text === "j") {
535
+ return [0, 1];
536
+ }
537
+ if (text === "-i" || text === "-j") {
538
+ return [0, -1];
539
+ }
540
+ if (text === "+i" || text === "+j") {
541
+ return [0, 1];
542
+ }
543
+ // Pure imaginary "<num>i" or "<num>j"
544
+ if (text.endsWith("i") || text.endsWith("j")) {
545
+ const coef = text.slice(0, -1);
546
+ const coefNum = toNumStrict(coef);
547
+ if (!Number.isNaN(coefNum)) {
548
+ return [0, coefNum];
549
+ }
550
+ }
551
+ // Mixed real+imaginary form.
552
+ const re = /^([+-]?[\d.eE+-]*?)([+-][\d.eE]*)?[ij]$/;
553
+ const m = re.exec(text);
554
+ if (!m) {
555
+ return null;
556
+ }
557
+ const realRaw = m[1] ?? "";
558
+ const imagRaw = m[2] ?? "";
559
+ // Validate each component with the strict grammar (treating the bare
560
+ // sign tokens "+"/"-" as implicit coefficients of 1 / -1, matching
561
+ // Excel's "x+i" == "x+1i" shorthand).
562
+ const realPart = realRaw === "" || realRaw === "+" ? 0 : realRaw === "-" ? 0 : toNumStrict(realRaw);
563
+ const imagPart = imagRaw === "" ? 0 : imagRaw === "+" ? 1 : imagRaw === "-" ? -1 : toNumStrict(imagRaw);
564
+ if (Number.isNaN(realPart) || Number.isNaN(imagPart)) {
565
+ return null;
566
+ }
567
+ if (imagRaw === "" && realRaw !== "") {
568
+ // "5i" form already handled above; this branch would only fire
569
+ // for something like "+i" / "-i" which is caught earlier.
570
+ return null;
571
+ }
572
+ return [realPart, imagPart];
573
+ }
574
+ function formatComplex(re, im, suffix = "i") {
575
+ if (im === 0) {
576
+ return String(re);
577
+ }
578
+ if (re === 0) {
579
+ if (im === 1) {
580
+ return suffix;
581
+ }
582
+ if (im === -1) {
583
+ return "-" + suffix;
584
+ }
585
+ return im + suffix;
586
+ }
587
+ const imStr = im === 1 ? "+" + suffix : im === -1 ? "-" + suffix : (im > 0 ? "+" : "") + im + suffix;
588
+ return re + imStr;
589
+ }
590
+ export const fnCOMPLEX = args => {
591
+ const re = toNumberRV(args[0]);
592
+ if (isError(re)) {
593
+ return re;
594
+ }
595
+ const im = toNumberRV(args[1]);
596
+ if (isError(im)) {
597
+ return im;
598
+ }
599
+ let suffix = "i";
600
+ if (args.length > 2) {
601
+ const e2 = checkError(args[2]);
602
+ if (e2) {
603
+ return e2;
604
+ }
605
+ suffix = toStringRV(args[2]);
606
+ }
607
+ if (suffix !== "i" && suffix !== "j") {
608
+ return ERRORS.VALUE;
609
+ }
610
+ return rvString(formatComplex(re.value, im.value, suffix));
611
+ };
612
+ export const fnIMREAL = args => {
613
+ const err = checkError(args[0]);
614
+ if (err) {
615
+ return err;
616
+ }
617
+ const c = parseComplex(toStringRV(args[0]));
618
+ return c ? rvNumber(c[0]) : ERRORS.NUM;
619
+ };
620
+ export const fnIMAGINARY = args => {
621
+ const err = checkError(args[0]);
622
+ if (err) {
623
+ return err;
624
+ }
625
+ const c = parseComplex(toStringRV(args[0]));
626
+ return c ? rvNumber(c[1]) : ERRORS.NUM;
627
+ };
628
+ export const fnIMABS = args => {
629
+ const err = checkError(args[0]);
630
+ if (err) {
631
+ return err;
632
+ }
633
+ const c = parseComplex(toStringRV(args[0]));
634
+ if (!c) {
635
+ return ERRORS.NUM;
636
+ }
637
+ return rvNumber(Math.sqrt(c[0] * c[0] + c[1] * c[1]));
638
+ };
639
+ export const fnIMARGUMENT = args => {
640
+ const err = checkError(args[0]);
641
+ if (err) {
642
+ return err;
643
+ }
644
+ const c = parseComplex(toStringRV(args[0]));
645
+ if (!c) {
646
+ return ERRORS.NUM;
647
+ }
648
+ if (c[0] === 0 && c[1] === 0) {
649
+ return ERRORS.DIV0;
650
+ }
651
+ return rvNumber(Math.atan2(c[1], c[0]));
652
+ };
653
+ export const fnIMCONJUGATE = args => {
654
+ const err = checkError(args[0]);
655
+ if (err) {
656
+ return err;
657
+ }
658
+ const c = parseComplex(toStringRV(args[0]));
659
+ if (!c) {
660
+ return ERRORS.NUM;
661
+ }
662
+ return rvString(formatComplex(c[0], -c[1]));
663
+ };
664
+ /**
665
+ * Iterate every scalar cell in a complex-number argument, invoking `step`
666
+ * on the parsed `[re, im]` pair. Accepts arrays, ranges and single
667
+ * scalars; numbers are treated as real, errors propagate, blanks are
668
+ * skipped, non-parseable strings yield `#NUM!`.
669
+ */
670
+ function forEachComplexCell(arg, step) {
671
+ const visit = (cell) => {
672
+ if (cell.kind === RVKind.Error) {
673
+ return cell;
674
+ }
675
+ if (cell.kind === RVKind.Blank) {
676
+ return null;
677
+ }
678
+ if (cell.kind === RVKind.Number) {
679
+ step(cell.value, 0);
680
+ return null;
681
+ }
682
+ if (cell.kind === RVKind.Boolean) {
683
+ step(cell.value ? 1 : 0, 0);
684
+ return null;
685
+ }
686
+ if (cell.kind === RVKind.String) {
687
+ const c = parseComplex(cell.value);
688
+ if (!c) {
689
+ return ERRORS.NUM;
690
+ }
691
+ step(c[0], c[1]);
692
+ return null;
693
+ }
694
+ return null;
695
+ };
696
+ if (arg.kind === RVKind.Array) {
697
+ for (const row of arg.rows) {
698
+ for (const cell of row) {
699
+ const err = visit(cell);
700
+ if (err) {
701
+ return err;
702
+ }
703
+ }
704
+ }
705
+ return null;
706
+ }
707
+ // Non-array: visit the scalar directly (references have already been
708
+ // dereferenced to either an array or a scalar by the evaluator).
709
+ return visit(arg);
710
+ }
711
+ export const fnIMSUM = args => {
712
+ let re = 0;
713
+ let im = 0;
714
+ for (const a of args) {
715
+ const err = checkError(a);
716
+ if (err) {
717
+ return err;
718
+ }
719
+ const walkErr = forEachComplexCell(a, (r, i) => {
720
+ re += r;
721
+ im += i;
722
+ });
723
+ if (walkErr) {
724
+ return walkErr;
725
+ }
726
+ }
727
+ return rvString(formatComplex(re, im));
728
+ };
729
+ export const fnIMSUB = args => {
730
+ const e0 = checkError(args[0]);
731
+ if (e0) {
732
+ return e0;
733
+ }
734
+ const e1 = checkError(args[1]);
735
+ if (e1) {
736
+ return e1;
737
+ }
738
+ const c1 = parseComplex(toStringRV(args[0]));
739
+ const c2 = parseComplex(toStringRV(args[1]));
740
+ if (!c1 || !c2) {
741
+ return ERRORS.NUM;
742
+ }
743
+ return rvString(formatComplex(c1[0] - c2[0], c1[1] - c2[1]));
744
+ };
745
+ export const fnIMPRODUCT = args => {
746
+ let re = 1;
747
+ let im = 0;
748
+ for (const a of args) {
749
+ const err = checkError(a);
750
+ if (err) {
751
+ return err;
752
+ }
753
+ const walkErr = forEachComplexCell(a, (r, i) => {
754
+ const nRe = re * r - im * i;
755
+ const nIm = re * i + im * r;
756
+ re = nRe;
757
+ im = nIm;
758
+ });
759
+ if (walkErr) {
760
+ return walkErr;
761
+ }
762
+ }
763
+ return rvString(formatComplex(re, im));
764
+ };
765
+ export const fnIMDIV = args => {
766
+ const e0 = checkError(args[0]);
767
+ if (e0) {
768
+ return e0;
769
+ }
770
+ const e1 = checkError(args[1]);
771
+ if (e1) {
772
+ return e1;
773
+ }
774
+ const c1 = parseComplex(toStringRV(args[0]));
775
+ const c2 = parseComplex(toStringRV(args[1]));
776
+ if (!c1 || !c2) {
777
+ return ERRORS.NUM;
778
+ }
779
+ const d = c2[0] * c2[0] + c2[1] * c2[1];
780
+ if (d === 0) {
781
+ // Division by 0+0i. Excel's IMDIV returns `#NUM!` historically but
782
+ // our newer `cdiv` helper (used by IMTAN/IMCSC/etc.) returns
783
+ // `#DIV/0!`. Route to `#DIV/0!` here for engine-wide consistency
784
+ // with how the rest of the complex family handles the same
785
+ // singularity.
786
+ return ERRORS.DIV0;
787
+ }
788
+ return rvString(formatComplex((c1[0] * c2[0] + c1[1] * c2[1]) / d, (c1[1] * c2[0] - c1[0] * c2[1]) / d));
789
+ };
790
+ export const fnIMPOWER = args => {
791
+ const err = checkError(args[0]);
792
+ if (err) {
793
+ return err;
794
+ }
795
+ const c = parseComplex(toStringRV(args[0]));
796
+ if (!c) {
797
+ return ERRORS.NUM;
798
+ }
799
+ const n = toNumberRV(args[1]);
800
+ if (isError(n)) {
801
+ return n;
802
+ }
803
+ const r = Math.sqrt(c[0] * c[0] + c[1] * c[1]);
804
+ const theta = Math.atan2(c[1], c[0]);
805
+ const rn = Math.pow(r, n.value);
806
+ return rvString(formatComplex(rn * Math.cos(n.value * theta), rn * Math.sin(n.value * theta)));
807
+ };
808
+ export const fnIMSQRT = args => {
809
+ const err = checkError(args[0]);
810
+ if (err) {
811
+ return err;
812
+ }
813
+ const c = parseComplex(toStringRV(args[0]));
814
+ if (!c) {
815
+ return ERRORS.NUM;
816
+ }
817
+ const r = Math.sqrt(c[0] * c[0] + c[1] * c[1]);
818
+ const theta = Math.atan2(c[1], c[0]);
819
+ const sr = Math.sqrt(r);
820
+ return rvString(formatComplex(sr * Math.cos(theta / 2), sr * Math.sin(theta / 2)));
821
+ };
822
+ export const fnIMLN = args => {
823
+ const err = checkError(args[0]);
824
+ if (err) {
825
+ return err;
826
+ }
827
+ const c = parseComplex(toStringRV(args[0]));
828
+ if (!c) {
829
+ return ERRORS.NUM;
830
+ }
831
+ const r = Math.sqrt(c[0] * c[0] + c[1] * c[1]);
832
+ if (r === 0) {
833
+ return ERRORS.NUM;
834
+ }
835
+ return rvString(formatComplex(Math.log(r), Math.atan2(c[1], c[0])));
836
+ };
837
+ export const fnIMLOG2 = args => {
838
+ const err = checkError(args[0]);
839
+ if (err) {
840
+ return err;
841
+ }
842
+ const c = parseComplex(toStringRV(args[0]));
843
+ if (!c) {
844
+ return ERRORS.NUM;
845
+ }
846
+ const r = Math.sqrt(c[0] * c[0] + c[1] * c[1]);
847
+ if (r === 0) {
848
+ return ERRORS.NUM;
849
+ }
850
+ const ln2 = Math.log(2);
851
+ return rvString(formatComplex(Math.log(r) / ln2, Math.atan2(c[1], c[0]) / ln2));
852
+ };
853
+ export const fnIMLOG10 = args => {
854
+ const err = checkError(args[0]);
855
+ if (err) {
856
+ return err;
857
+ }
858
+ const c = parseComplex(toStringRV(args[0]));
859
+ if (!c) {
860
+ return ERRORS.NUM;
861
+ }
862
+ const r = Math.sqrt(c[0] * c[0] + c[1] * c[1]);
863
+ if (r === 0) {
864
+ return ERRORS.NUM;
865
+ }
866
+ const ln10 = Math.log(10);
867
+ return rvString(formatComplex(Math.log(r) / ln10, Math.atan2(c[1], c[0]) / ln10));
868
+ };
869
+ export const fnIMEXP = args => {
870
+ const err = checkError(args[0]);
871
+ if (err) {
872
+ return err;
873
+ }
874
+ const c = parseComplex(toStringRV(args[0]));
875
+ if (!c) {
876
+ return ERRORS.NUM;
877
+ }
878
+ const er = Math.exp(c[0]);
879
+ return rvString(formatComplex(er * Math.cos(c[1]), er * Math.sin(c[1])));
880
+ };
881
+ export const fnIMSIN = args => {
882
+ const err = checkError(args[0]);
883
+ if (err) {
884
+ return err;
885
+ }
886
+ const c = parseComplex(toStringRV(args[0]));
887
+ if (!c) {
888
+ return ERRORS.NUM;
889
+ }
890
+ return rvString(formatComplex(Math.sin(c[0]) * Math.cosh(c[1]), Math.cos(c[0]) * Math.sinh(c[1])));
891
+ };
892
+ export const fnIMCOS = args => {
893
+ const err = checkError(args[0]);
894
+ if (err) {
895
+ return err;
896
+ }
897
+ const c = parseComplex(toStringRV(args[0]));
898
+ if (!c) {
899
+ return ERRORS.NUM;
900
+ }
901
+ return rvString(formatComplex(Math.cos(c[0]) * Math.cosh(c[1]), -Math.sin(c[0]) * Math.sinh(c[1])));
902
+ };
903
+ /**
904
+ * Shared helper: parse a single complex argument and either hand it to
905
+ * `compute` (which returns `[re, im]` or an error) or short-circuit the
906
+ * error. All the IM* functions added in R7 share this shape.
907
+ */
908
+ function unaryComplex(args, compute) {
909
+ const err = checkError(args[0]);
910
+ if (err) {
911
+ return err;
912
+ }
913
+ // Allow number / boolean direct inputs: complex parser expects a
914
+ // string, but Excel's IM* family coerces booleans to 1/0 and numbers
915
+ // to pure-real complex. Falling through to `toStringRV` would render
916
+ // "TRUE" and then fail parsing.
917
+ const scalar = topLeft(args[0]);
918
+ let c;
919
+ if (scalar.kind === RVKind.Number) {
920
+ c = [scalar.value, 0];
921
+ }
922
+ else if (scalar.kind === RVKind.Boolean) {
923
+ c = [scalar.value ? 1 : 0, 0];
924
+ }
925
+ else if (scalar.kind === RVKind.Blank) {
926
+ c = [0, 0];
927
+ }
928
+ else {
929
+ c = parseComplex(toStringRV(scalar));
930
+ }
931
+ if (!c) {
932
+ return ERRORS.NUM;
933
+ }
934
+ const result = compute(c[0], c[1]);
935
+ if ("kind" in result && result.kind === RVKind.Error) {
936
+ return result;
937
+ }
938
+ const [re, im] = result;
939
+ if (!Number.isFinite(re) || !Number.isFinite(im)) {
940
+ return ERRORS.NUM;
941
+ }
942
+ return rvString(formatComplex(re, im));
943
+ }
944
+ /** Divide two complex numbers (a / b). */
945
+ function cdiv(a, b) {
946
+ const denom = b[0] * b[0] + b[1] * b[1];
947
+ if (denom === 0) {
948
+ return ERRORS.DIV0;
949
+ }
950
+ return [(a[0] * b[0] + a[1] * b[1]) / denom, (a[1] * b[0] - a[0] * b[1]) / denom];
951
+ }
952
+ export const fnIMTAN = args => unaryComplex(args, (re, im) => {
953
+ // tan(z) = sin(z) / cos(z)
954
+ const sinZ = [Math.sin(re) * Math.cosh(im), Math.cos(re) * Math.sinh(im)];
955
+ const cosZ = [Math.cos(re) * Math.cosh(im), -Math.sin(re) * Math.sinh(im)];
956
+ return cdiv(sinZ, cosZ);
957
+ });
958
+ export const fnIMCSC = args => unaryComplex(args, (re, im) => {
959
+ // csc(z) = 1 / sin(z)
960
+ const sinZ = [Math.sin(re) * Math.cosh(im), Math.cos(re) * Math.sinh(im)];
961
+ return cdiv([1, 0], sinZ);
962
+ });
963
+ export const fnIMSEC = args => unaryComplex(args, (re, im) => {
964
+ // sec(z) = 1 / cos(z)
965
+ const cosZ = [Math.cos(re) * Math.cosh(im), -Math.sin(re) * Math.sinh(im)];
966
+ return cdiv([1, 0], cosZ);
967
+ });
968
+ export const fnIMCOT = args => unaryComplex(args, (re, im) => {
969
+ // cot(z) = cos(z) / sin(z)
970
+ const sinZ = [Math.sin(re) * Math.cosh(im), Math.cos(re) * Math.sinh(im)];
971
+ const cosZ = [Math.cos(re) * Math.cosh(im), -Math.sin(re) * Math.sinh(im)];
972
+ return cdiv(cosZ, sinZ);
973
+ });
974
+ export const fnIMSINH = args => unaryComplex(args, (re, im) => [Math.sinh(re) * Math.cos(im), Math.cosh(re) * Math.sin(im)]);
975
+ export const fnIMCOSH = args => unaryComplex(args, (re, im) => [Math.cosh(re) * Math.cos(im), Math.sinh(re) * Math.sin(im)]);
976
+ export const fnIMTANH = args => unaryComplex(args, (re, im) => {
977
+ // tanh(z) = sinh(z) / cosh(z)
978
+ const sinhZ = [Math.sinh(re) * Math.cos(im), Math.cosh(re) * Math.sin(im)];
979
+ const coshZ = [Math.cosh(re) * Math.cos(im), Math.sinh(re) * Math.sin(im)];
980
+ return cdiv(sinhZ, coshZ);
981
+ });
982
+ export const fnIMCSCH = args => unaryComplex(args, (re, im) => {
983
+ const sinhZ = [Math.sinh(re) * Math.cos(im), Math.cosh(re) * Math.sin(im)];
984
+ return cdiv([1, 0], sinhZ);
985
+ });
986
+ export const fnIMSECH = args => unaryComplex(args, (re, im) => {
987
+ const coshZ = [Math.cosh(re) * Math.cos(im), Math.sinh(re) * Math.sin(im)];
988
+ return cdiv([1, 0], coshZ);
989
+ });
990
+ export const fnIMCOTH = args => unaryComplex(args, (re, im) => {
991
+ const sinhZ = [Math.sinh(re) * Math.cos(im), Math.cosh(re) * Math.sin(im)];
992
+ const coshZ = [Math.cosh(re) * Math.cos(im), Math.sinh(re) * Math.sin(im)];
993
+ return cdiv(coshZ, sinhZ);
994
+ });
995
+ // Excel's bitwise family (BITAND/BITOR/BITXOR/BITLSHIFT/BITRSHIFT) operates
996
+ // on integers in the range [0, 2^48 − 1]. JavaScript's `&`/`|`/`^` truncate
997
+ // to 32 bits, so we emulate 48-bit semantics by splitting each operand into
998
+ // a 24-bit low half and a 24-bit high half, combining those halves with
999
+ // native 32-bit bitwise ops, and recombining. The shift functions use the
1000
+ // same split so `BITLSHIFT(2^30, 10)` doesn't silently lose bits.
1001
+ const BIT_MAX = 2 ** 48 - 1;
1002
+ function bitOp(op) {
1003
+ return (a, b) => {
1004
+ const aHi = Math.floor(a / 0x1000000);
1005
+ const aLo = a - aHi * 0x1000000;
1006
+ const bHi = Math.floor(b / 0x1000000);
1007
+ const bLo = b - bHi * 0x1000000;
1008
+ return op(aHi, bHi) * 0x1000000 + (op(aLo, bLo) >>> 0);
1009
+ };
1010
+ }
1011
+ const bitAnd48 = bitOp((a, b) => (a & b) >>> 0);
1012
+ const bitOr48 = bitOp((a, b) => (a | b) >>> 0);
1013
+ const bitXor48 = bitOp((a, b) => (a ^ b) >>> 0);
1014
+ function validateBitOperand(v) {
1015
+ if (v < 0 || v > BIT_MAX) {
1016
+ return ERRORS.NUM;
1017
+ }
1018
+ // Excel rejects non-integer operands with #NUM!, rather than silently
1019
+ // truncating. Use the strict `v !== floor(v)` check so `5.9` does not
1020
+ // pass as `5`.
1021
+ if (v !== Math.floor(v)) {
1022
+ return ERRORS.NUM;
1023
+ }
1024
+ return v;
1025
+ }
1026
+ export const fnBITAND = args => {
1027
+ const a = toNumberRV(args[0]);
1028
+ if (isError(a)) {
1029
+ return a;
1030
+ }
1031
+ const b = toNumberRV(args[1]);
1032
+ if (isError(b)) {
1033
+ return b;
1034
+ }
1035
+ const av = validateBitOperand(a.value);
1036
+ if (typeof av !== "number") {
1037
+ return av;
1038
+ }
1039
+ const bv = validateBitOperand(b.value);
1040
+ if (typeof bv !== "number") {
1041
+ return bv;
1042
+ }
1043
+ return rvNumber(bitAnd48(av, bv));
1044
+ };
1045
+ export const fnBITOR = args => {
1046
+ const a = toNumberRV(args[0]);
1047
+ if (isError(a)) {
1048
+ return a;
1049
+ }
1050
+ const b = toNumberRV(args[1]);
1051
+ if (isError(b)) {
1052
+ return b;
1053
+ }
1054
+ const av = validateBitOperand(a.value);
1055
+ if (typeof av !== "number") {
1056
+ return av;
1057
+ }
1058
+ const bv = validateBitOperand(b.value);
1059
+ if (typeof bv !== "number") {
1060
+ return bv;
1061
+ }
1062
+ return rvNumber(bitOr48(av, bv));
1063
+ };
1064
+ export const fnBITXOR = args => {
1065
+ const a = toNumberRV(args[0]);
1066
+ if (isError(a)) {
1067
+ return a;
1068
+ }
1069
+ const b = toNumberRV(args[1]);
1070
+ if (isError(b)) {
1071
+ return b;
1072
+ }
1073
+ const av = validateBitOperand(a.value);
1074
+ if (typeof av !== "number") {
1075
+ return av;
1076
+ }
1077
+ const bv = validateBitOperand(b.value);
1078
+ if (typeof bv !== "number") {
1079
+ return bv;
1080
+ }
1081
+ return rvNumber(bitXor48(av, bv));
1082
+ };
1083
+ export const fnBITLSHIFT = args => {
1084
+ const num = toNumberRV(args[0]);
1085
+ if (isError(num)) {
1086
+ return num;
1087
+ }
1088
+ const shift = toNumberRV(args[1]);
1089
+ if (isError(shift)) {
1090
+ return shift;
1091
+ }
1092
+ const nv = validateBitOperand(num.value);
1093
+ if (typeof nv !== "number") {
1094
+ return nv;
1095
+ }
1096
+ const s = Math.trunc(shift.value);
1097
+ if (s < -53 || s > 53) {
1098
+ return ERRORS.NUM;
1099
+ }
1100
+ const result = s >= 0 ? nv * Math.pow(2, s) : Math.floor(nv / Math.pow(2, -s));
1101
+ if (result > BIT_MAX) {
1102
+ return ERRORS.NUM;
1103
+ }
1104
+ return rvNumber(result);
1105
+ };
1106
+ export const fnBITRSHIFT = args => {
1107
+ const num = toNumberRV(args[0]);
1108
+ if (isError(num)) {
1109
+ return num;
1110
+ }
1111
+ const shift = toNumberRV(args[1]);
1112
+ if (isError(shift)) {
1113
+ return shift;
1114
+ }
1115
+ const nv = validateBitOperand(num.value);
1116
+ if (typeof nv !== "number") {
1117
+ return nv;
1118
+ }
1119
+ const s = Math.trunc(shift.value);
1120
+ if (s < -53 || s > 53) {
1121
+ return ERRORS.NUM;
1122
+ }
1123
+ const result = s >= 0 ? Math.floor(nv / Math.pow(2, s)) : nv * Math.pow(2, -s);
1124
+ if (result > BIT_MAX) {
1125
+ return ERRORS.NUM;
1126
+ }
1127
+ return rvNumber(result);
1128
+ };