@cortex-js/compute-engine 0.19.1 → 0.20.1

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 (102) hide show
  1. package/dist/compute-engine.esm.js +1084 -377
  2. package/dist/compute-engine.js +1084 -377
  3. package/dist/compute-engine.min.esm.js +10 -9
  4. package/dist/compute-engine.min.js +10 -9
  5. package/dist/math-json.esm.js +2 -2
  6. package/dist/math-json.js +2 -2
  7. package/dist/math-json.min.esm.js +2 -2
  8. package/dist/math-json.min.js +2 -2
  9. package/dist/types/common/ansi-codes.d.ts +1 -1
  10. package/dist/types/common/grapheme-splitter.d.ts +1 -1
  11. package/dist/types/common/signals.d.ts +4 -4
  12. package/dist/types/common/utils.d.ts +1 -1
  13. package/dist/types/compute-engine/assume.d.ts +1 -1
  14. package/dist/types/compute-engine/boxed-expression/abstract-boxed-expression.d.ts +1 -1
  15. package/dist/types/compute-engine/boxed-expression/box.d.ts +1 -1
  16. package/dist/types/compute-engine/boxed-expression/boxed-dictionary.d.ts +1 -1
  17. package/dist/types/compute-engine/boxed-expression/boxed-domain.d.ts +1 -1
  18. package/dist/types/compute-engine/boxed-expression/boxed-function-definition.d.ts +1 -1
  19. package/dist/types/compute-engine/boxed-expression/boxed-function.d.ts +1 -1
  20. package/dist/types/compute-engine/boxed-expression/boxed-number.d.ts +1 -1
  21. package/dist/types/compute-engine/boxed-expression/boxed-patterns.d.ts +1 -1
  22. package/dist/types/compute-engine/boxed-expression/boxed-string.d.ts +1 -1
  23. package/dist/types/compute-engine/boxed-expression/boxed-symbol-definition.d.ts +1 -1
  24. package/dist/types/compute-engine/boxed-expression/boxed-symbol.d.ts +1 -1
  25. package/dist/types/compute-engine/boxed-expression/expression-map.d.ts +1 -1
  26. package/dist/types/compute-engine/boxed-expression/order.d.ts +1 -1
  27. package/dist/types/compute-engine/boxed-expression/serialize.d.ts +1 -1
  28. package/dist/types/compute-engine/boxed-expression/utils.d.ts +1 -3
  29. package/dist/types/compute-engine/boxed-expression/validate.d.ts +7 -3
  30. package/dist/types/compute-engine/collection-utils.d.ts +1 -1
  31. package/dist/types/compute-engine/compile.d.ts +1 -1
  32. package/dist/types/compute-engine/compute-engine.d.ts +1 -1
  33. package/dist/types/compute-engine/cost-function.d.ts +1 -1
  34. package/dist/types/compute-engine/domain-utils.d.ts +1 -1
  35. package/dist/types/compute-engine/function-utils.d.ts +1 -1
  36. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-algebra.d.ts +1 -1
  37. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-arithmetic.d.ts +1 -1
  38. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-calculus.d.ts +1 -1
  39. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-complex.d.ts +1 -1
  40. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-core.d.ts +25 -1
  41. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-inequalities.d.ts +1 -1
  42. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-linear-algebra.d.ts +2 -0
  43. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-logic.d.ts +1 -1
  44. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-other.d.ts +1 -1
  45. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-sets.d.ts +1 -1
  46. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-statistics.d.ts +1 -1
  47. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-symbols.d.ts +1 -1
  48. package/dist/types/compute-engine/latex-syntax/dictionary/definitions-trigonometry.d.ts +1 -1
  49. package/dist/types/compute-engine/latex-syntax/dictionary/definitions.d.ts +1 -1
  50. package/dist/types/compute-engine/latex-syntax/latex-syntax.d.ts +1 -1
  51. package/dist/types/compute-engine/latex-syntax/parse-identifier.d.ts +1 -1
  52. package/dist/types/compute-engine/latex-syntax/parse.d.ts +1 -23
  53. package/dist/types/compute-engine/latex-syntax/public.d.ts +11 -24
  54. package/dist/types/compute-engine/latex-syntax/serialize-number.d.ts +1 -1
  55. package/dist/types/compute-engine/latex-syntax/serializer-style.d.ts +1 -1
  56. package/dist/types/compute-engine/latex-syntax/serializer.d.ts +1 -1
  57. package/dist/types/compute-engine/latex-syntax/tokenizer.d.ts +1 -1
  58. package/dist/types/compute-engine/library/arithmetic-add.d.ts +1 -1
  59. package/dist/types/compute-engine/library/arithmetic-divide.d.ts +1 -1
  60. package/dist/types/compute-engine/library/arithmetic-multiply.d.ts +1 -1
  61. package/dist/types/compute-engine/library/arithmetic-power.d.ts +1 -1
  62. package/dist/types/compute-engine/library/arithmetic.d.ts +1 -1
  63. package/dist/types/compute-engine/library/calculus.d.ts +1 -1
  64. package/dist/types/compute-engine/library/collections.d.ts +1 -1
  65. package/dist/types/compute-engine/library/complex.d.ts +1 -1
  66. package/dist/types/compute-engine/library/control-structures.d.ts +1 -1
  67. package/dist/types/compute-engine/library/core.d.ts +1 -1
  68. package/dist/types/compute-engine/library/domains.d.ts +1 -1
  69. package/dist/types/compute-engine/library/library.d.ts +1 -1
  70. package/dist/types/compute-engine/library/linear-algebra.d.ts +1 -1
  71. package/dist/types/compute-engine/library/logic.d.ts +1 -1
  72. package/dist/types/compute-engine/library/polynomials.d.ts +1 -1
  73. package/dist/types/compute-engine/library/random-expression.d.ts +1 -1
  74. package/dist/types/compute-engine/library/relational-operator.d.ts +1 -1
  75. package/dist/types/compute-engine/library/sets.d.ts +1 -1
  76. package/dist/types/compute-engine/library/statistics.d.ts +1 -1
  77. package/dist/types/compute-engine/library/trigonometry.d.ts +1 -1
  78. package/dist/types/compute-engine/library/utils.d.ts +1 -1
  79. package/dist/types/compute-engine/numerics/numeric-bigint.d.ts +1 -1
  80. package/dist/types/compute-engine/numerics/numeric-bignum.d.ts +1 -1
  81. package/dist/types/compute-engine/numerics/numeric-complex.d.ts +1 -1
  82. package/dist/types/compute-engine/numerics/numeric.d.ts +1 -1
  83. package/dist/types/compute-engine/numerics/primes.d.ts +1 -1
  84. package/dist/types/compute-engine/numerics/rationals.d.ts +1 -1
  85. package/dist/types/compute-engine/numerics/richardson.d.ts +1 -1
  86. package/dist/types/compute-engine/public.d.ts +1 -1
  87. package/dist/types/compute-engine/rules.d.ts +1 -1
  88. package/dist/types/compute-engine/simplify-rules.d.ts +1 -1
  89. package/dist/types/compute-engine/solve.d.ts +1 -1
  90. package/dist/types/compute-engine/symbolic/derivative.d.ts +1 -1
  91. package/dist/types/compute-engine/symbolic/expand.d.ts +1 -1
  92. package/dist/types/compute-engine/symbolic/flatten.d.ts +1 -3
  93. package/dist/types/compute-engine/symbolic/negate.d.ts +1 -1
  94. package/dist/types/compute-engine/symbolic/polynomials.d.ts +1 -1
  95. package/dist/types/compute-engine/symbolic/product.d.ts +1 -1
  96. package/dist/types/compute-engine/symbolic/sum.d.ts +1 -1
  97. package/dist/types/compute-engine/symbolic/utils.d.ts +1 -1
  98. package/dist/types/compute-engine.d.ts +2 -2
  99. package/dist/types/math-json/math-json-format.d.ts +1 -1
  100. package/dist/types/math-json/utils.d.ts +2 -4
  101. package/dist/types/math-json.d.ts +2 -2
  102. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- /** CortexJS Compute Engine 0.19.1 */
1
+ /** CortexJS Compute Engine 0.20.1 */
2
2
  (function(global,factory){typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'],factory):(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ComputeEngine = {}));})(this, (function (exports) { 'use strict';
3
3
  var ComputeEngine = (() => {
4
4
  var __create = Object.create;
@@ -3980,6 +3980,13 @@ var ComputeEngine = (() => {
3980
3980
  return Math.max(0, expr.fn.length - 1);
3981
3981
  return 0;
3982
3982
  }
3983
+ function unhold(expr) {
3984
+ if (expr === null || expr === void 0)
3985
+ return null;
3986
+ if (head(expr) === "Hold")
3987
+ return op(expr, 1);
3988
+ return expr;
3989
+ }
3983
3990
  function symbol(expr) {
3984
3991
  if (expr === null || expr === void 0)
3985
3992
  return null;
@@ -3994,14 +4001,6 @@ var ComputeEngine = (() => {
3994
4001
  return null;
3995
4002
  return s;
3996
4003
  }
3997
- function isListLike(expr) {
3998
- if (expr === null)
3999
- return false;
4000
- const h = head(expr);
4001
- if (!h || typeof h !== "string")
4002
- return false;
4003
- return /^(List|Sequence|Tuple|Single|Pair|Triple)$/.test(h);
4004
- }
4005
4004
  function keyValuePair(expr) {
4006
4005
  const h = head(expr);
4007
4006
  if (h === "KeyValuePair" || h === "Tuple" || h === "Pair") {
@@ -4161,21 +4160,21 @@ var ComputeEngine = (() => {
4161
4160
  expr = op(expr, 1);
4162
4161
  if (expr === null)
4163
4162
  return [];
4164
- if (head(expr) !== "Sequence")
4163
+ h = head(expr);
4164
+ if (h !== "Sequence")
4165
4165
  return [expr];
4166
4166
  }
4167
- h = head(expr);
4168
4167
  if (h !== "Sequence")
4169
4168
  return null;
4170
4169
  return ops(expr) ?? [];
4171
4170
  }
4172
4171
  function isEmptySequence(expr) {
4173
- return expr !== null && head(expr) === "Sequence" && nops(expr) === 0;
4172
+ return head(expr) === "Sequence" && nops(expr) === 0;
4174
4173
  }
4175
4174
  function missingIfEmpty(expr) {
4176
- if (expr === null || isEmptySequence(expr))
4175
+ if (isEmptySequence(expr))
4177
4176
  return MISSING;
4178
- return expr;
4177
+ return expr ?? MISSING;
4179
4178
  }
4180
4179
  function countFunctionLeaves(xs) {
4181
4180
  if (xs[0] === "Square") {
@@ -4345,9 +4344,9 @@ var ComputeEngine = (() => {
4345
4344
  if (val < 0) {
4346
4345
  result += serializer.serialize(arg);
4347
4346
  } else if (head(arg) === "Negate") {
4348
- result += serializer.wrap(arg, 275);
4347
+ result += serializer.wrap(arg, ADDITION_PRECEDENCE);
4349
4348
  } else {
4350
- const term = serializer.wrap(arg, 275);
4349
+ const term = serializer.wrap(arg, ADDITION_PRECEDENCE);
4351
4350
  if (term[0] === "-" || term[0] === "+")
4352
4351
  result += term;
4353
4352
  else
@@ -4355,10 +4354,10 @@ var ComputeEngine = (() => {
4355
4354
  }
4356
4355
  }
4357
4356
  } else if (name === "Subtract") {
4358
- result = serializer.wrap(arg, 275);
4357
+ result = serializer.wrap(arg, ADDITION_PRECEDENCE);
4359
4358
  const arg2 = op(expr, 2);
4360
4359
  if (arg2 !== null) {
4361
- const term = serializer.wrap(arg2, 275);
4360
+ const term = serializer.wrap(arg2, ADDITION_PRECEDENCE);
4362
4361
  if (term[0] === "-")
4363
4362
  result += "+" + term.slice(1);
4364
4363
  else if (term[0] === "+")
@@ -4448,7 +4447,7 @@ var ComputeEngine = (() => {
4448
4447
  arg = op(arg, 1);
4449
4448
  isNegative = !isNegative;
4450
4449
  }
4451
- term = serializer.wrap(arg, 390);
4450
+ term = serializer.wrap(arg, MULTIPLICATION_PRECEDENCE);
4452
4451
  if (!result) {
4453
4452
  result = term;
4454
4453
  } else {
@@ -4697,11 +4696,14 @@ var ComputeEngine = (() => {
4697
4696
  latexTrigger: ["+"],
4698
4697
  kind: "infix",
4699
4698
  associativity: "both",
4700
- precedence: 275,
4699
+ precedence: ADDITION_PRECEDENCE,
4701
4700
  parse: (parser, lhs, until) => {
4702
- if (until && 275 < until.minPrec)
4701
+ if (until && ADDITION_PRECEDENCE < until.minPrec)
4703
4702
  return null;
4704
- const rhs = parser.parseExpression({ ...until, minPrec: 275 });
4703
+ const rhs = parser.parseExpression({
4704
+ ...until,
4705
+ minPrec: ADDITION_PRECEDENCE
4706
+ });
4705
4707
  if (rhs === null)
4706
4708
  return null;
4707
4709
  return applyAssociativeOperator("Add", lhs, rhs);
@@ -4711,9 +4713,9 @@ var ComputeEngine = (() => {
4711
4713
  {
4712
4714
  kind: "prefix",
4713
4715
  latexTrigger: ["+"],
4714
- precedence: 275,
4716
+ precedence: ADDITION_PRECEDENCE,
4715
4717
  parse: (parser, until) => {
4716
- if (until && 275 < until.minPrec)
4718
+ if (until && ADDITION_PRECEDENCE < until.minPrec)
4717
4719
  return null;
4718
4720
  return parser.parseExpression({ ...until, minPrec: 400 });
4719
4721
  }
@@ -4741,7 +4743,7 @@ var ComputeEngine = (() => {
4741
4743
  { name: "Chop", identifierTrigger: "chop", kind: "function", parse: "Chop" },
4742
4744
  {
4743
4745
  name: "Complex",
4744
- precedence: 274,
4746
+ precedence: ADDITION_PRECEDENCE - 1,
4745
4747
  // One less than precedence of `Add`: used for correct wrapping
4746
4748
  serialize: (serializer, expr) => {
4747
4749
  const re = machineValue(op(expr, 1));
@@ -4759,7 +4761,7 @@ var ComputeEngine = (() => {
4759
4761
  {
4760
4762
  name: "Divide",
4761
4763
  latexTrigger: "\\frac",
4762
- precedence: 660,
4764
+ precedence: DIVISION_PRECEDENCE,
4763
4765
  // For \frac specifically, not for \div, etc..
4764
4766
  // handles Leibnitz notation for partial derivatives
4765
4767
  parse: parseFraction,
@@ -4768,14 +4770,14 @@ var ComputeEngine = (() => {
4768
4770
  {
4769
4771
  kind: "infix",
4770
4772
  latexTrigger: "\\over",
4771
- precedence: 660,
4773
+ precedence: DIVISION_PRECEDENCE,
4772
4774
  parse: "Divide"
4773
4775
  },
4774
4776
  {
4775
4777
  latexTrigger: ["\\/"],
4776
4778
  kind: "infix",
4777
4779
  associativity: "non",
4778
- precedence: 660,
4780
+ precedence: DIVISION_PRECEDENCE,
4779
4781
  // ??? MathML has 265, but it's wrong.
4780
4782
  // It has to be at least higher than multiply
4781
4783
  // e.g. `1/2+3*x` -> `1/2 + 3*x` , not `1/(2+3*x)`
@@ -4785,14 +4787,14 @@ var ComputeEngine = (() => {
4785
4787
  latexTrigger: ["/"],
4786
4788
  kind: "infix",
4787
4789
  associativity: "non",
4788
- precedence: 660,
4790
+ precedence: DIVISION_PRECEDENCE,
4789
4791
  parse: "Divide"
4790
4792
  },
4791
4793
  {
4792
4794
  latexTrigger: ["\\div"],
4793
4795
  kind: "infix",
4794
4796
  associativity: "non",
4795
- precedence: 660,
4797
+ precedence: DIVISION_PRECEDENCE,
4796
4798
  // ??? according to MathML
4797
4799
  parse: "Divide"
4798
4800
  },
@@ -4809,13 +4811,13 @@ var ComputeEngine = (() => {
4809
4811
  name: "Factorial",
4810
4812
  latexTrigger: ["!"],
4811
4813
  kind: "postfix",
4812
- precedence: 810
4814
+ precedence: POSTFIX_PRECEDENCE
4813
4815
  },
4814
4816
  {
4815
4817
  name: "Factorial2",
4816
4818
  latexTrigger: ["!", "!"],
4817
4819
  kind: "postfix",
4818
- precedence: 810
4820
+ precedence: POSTFIX_PRECEDENCE
4819
4821
  },
4820
4822
  {
4821
4823
  name: "Floor",
@@ -4948,23 +4950,26 @@ var ComputeEngine = (() => {
4948
4950
  latexTrigger: ["\\mp"],
4949
4951
  kind: "infix",
4950
4952
  associativity: "both",
4951
- precedence: 270
4953
+ precedence: ARROW_PRECEDENCE
4952
4954
  },
4953
4955
  {
4954
4956
  name: "Multiply",
4955
4957
  latexTrigger: ["\\times"],
4956
4958
  kind: "infix",
4957
4959
  associativity: "both",
4958
- precedence: 390,
4960
+ precedence: MULTIPLICATION_PRECEDENCE,
4959
4961
  serialize: serializeMultiply
4960
4962
  },
4961
4963
  {
4962
4964
  latexTrigger: ["\\cdot"],
4963
4965
  kind: "infix",
4964
4966
  associativity: "both",
4965
- precedence: 390,
4967
+ precedence: MULTIPLICATION_PRECEDENCE,
4966
4968
  parse: (parser, lhs, terminator) => {
4967
- const rhs = parser.parseExpression({ ...terminator, minPrec: 392 });
4969
+ const rhs = parser.parseExpression({
4970
+ ...terminator,
4971
+ minPrec: MULTIPLICATION_PRECEDENCE + 2
4972
+ });
4968
4973
  if (rhs === null)
4969
4974
  return ["Multiply", lhs, MISSING];
4970
4975
  return applyAssociativeOperator("Multiply", lhs, rhs);
@@ -4974,23 +4979,77 @@ var ComputeEngine = (() => {
4974
4979
  latexTrigger: ["*"],
4975
4980
  kind: "infix",
4976
4981
  associativity: "both",
4977
- precedence: 390,
4982
+ precedence: MULTIPLICATION_PRECEDENCE,
4978
4983
  parse: (parser, lhs, terminator) => {
4979
- const rhs = parser.parseExpression({ ...terminator, minPrec: 392 });
4984
+ const rhs = parser.parseExpression({
4985
+ ...terminator,
4986
+ minPrec: MULTIPLICATION_PRECEDENCE + 2
4987
+ });
4980
4988
  if (rhs === null)
4981
4989
  return ["Multiply", lhs, MISSING];
4982
4990
  return applyAssociativeOperator("Multiply", lhs, rhs);
4983
4991
  }
4984
4992
  },
4993
+ // Infix modulo, as in `26 \bmod 5`
4994
+ {
4995
+ name: "Mod",
4996
+ latexTrigger: "\\bmod",
4997
+ kind: "infix",
4998
+ precedence: DIVISION_PRECEDENCE,
4999
+ serialize: (serializer, expr) => {
5000
+ if (nops(expr) !== 2)
5001
+ return "";
5002
+ const lhs = serializer.serialize(op(expr, 1));
5003
+ const rhs = serializer.serialize(op(expr, 2));
5004
+ return joinLatex([lhs, "\\bmod", rhs]);
5005
+ }
5006
+ },
5007
+ // Synonym to \\bmod
5008
+ {
5009
+ latexTrigger: "\\mod",
5010
+ kind: "infix",
5011
+ precedence: DIVISION_PRECEDENCE,
5012
+ parse: "Mod"
5013
+ },
5014
+ {
5015
+ latexTrigger: "\\pmod",
5016
+ kind: "prefix",
5017
+ precedence: COMPARISON_PRECEDENCE,
5018
+ parse: (parser) => {
5019
+ const rhs = parser.parseGroup() ?? parser.parseToken();
5020
+ return ["Mod", missingIfEmpty(rhs)];
5021
+ }
5022
+ },
5023
+ {
5024
+ name: "Congruent",
5025
+ serialize: (serializer, expr) => {
5026
+ const lhs = serializer.serialize(op(expr, 1));
5027
+ const rhs = serializer.serialize(op(expr, 2));
5028
+ if (op(expr, 3) === null)
5029
+ return joinLatex([lhs, "\\equiv", rhs]);
5030
+ const modulus = serializer.serialize(op(expr, 3));
5031
+ return joinLatex([lhs, "\\equiv", rhs, "\\pmod{", modulus, "}"]);
5032
+ }
5033
+ },
4985
5034
  {
4986
5035
  name: "Negate",
4987
5036
  latexTrigger: ["-"],
4988
5037
  kind: "prefix",
5038
+ precedence: ADDITION_PRECEDENCE,
4989
5039
  parse: (parser, terminator) => {
4990
- const rhs = parser.parseExpression({ ...terminator, minPrec: 400 });
5040
+ if (/\d/.test(parser.peek))
5041
+ return null;
5042
+ const index = parser.index;
5043
+ if (parser.parseNumber() !== null) {
5044
+ parser.index = index;
5045
+ return null;
5046
+ }
5047
+ const rhs = parser.parseExpression({
5048
+ ...terminator,
5049
+ minPrec: ADDITION_PRECEDENCE + 1
5050
+ });
4991
5051
  return ["Negate", missingIfEmpty(rhs)];
4992
- },
4993
- precedence: 275
5052
+ }
4994
5053
  },
4995
5054
  // {
4996
5055
  // /** If the argument is a vector */
@@ -5030,7 +5089,7 @@ var ComputeEngine = (() => {
5030
5089
  latexTrigger: ["\\pm"],
5031
5090
  kind: "infix",
5032
5091
  associativity: "both",
5033
- precedence: 270,
5092
+ precedence: ARROW_PRECEDENCE,
5034
5093
  serialize: (serializer, expr) => {
5035
5094
  const op12 = op(expr, 1);
5036
5095
  if (op12 === null)
@@ -5048,7 +5107,7 @@ var ComputeEngine = (() => {
5048
5107
  {
5049
5108
  latexTrigger: ["\\pm"],
5050
5109
  kind: "prefix",
5051
- precedence: 270,
5110
+ precedence: ARROW_PRECEDENCE,
5052
5111
  parse: (parser, terminator) => {
5053
5112
  const rhs = parser.parseExpression({ ...terminator, minPrec: 400 });
5054
5113
  return ["PlusMinus", missingIfEmpty(rhs)];
@@ -5058,7 +5117,7 @@ var ComputeEngine = (() => {
5058
5117
  latexTrigger: ["\\plusmn"],
5059
5118
  kind: "infix",
5060
5119
  associativity: "both",
5061
- precedence: 270,
5120
+ precedence: ARROW_PRECEDENCE,
5062
5121
  parse: (parser, lhs, terminator) => {
5063
5122
  const rhs = parser.parseExpression({ ...terminator, minPrec: 400 });
5064
5123
  return ["PlusMinus", lhs, missingIfEmpty(rhs)];
@@ -5067,7 +5126,7 @@ var ComputeEngine = (() => {
5067
5126
  {
5068
5127
  latexTrigger: ["\\plusmn"],
5069
5128
  kind: "prefix",
5070
- precedence: 270,
5129
+ precedence: ARROW_PRECEDENCE,
5071
5130
  parse: (parser, terminator) => {
5072
5131
  const rhs = parser.parseExpression({ ...terminator, minPrec: 400 });
5073
5132
  return ["PlusMinus", missingIfEmpty(rhs)];
@@ -5082,9 +5141,9 @@ var ComputeEngine = (() => {
5082
5141
  },
5083
5142
  {
5084
5143
  latexTrigger: "\\prod",
5085
- precedence: 390,
5144
+ precedence: MULTIPLICATION_PRECEDENCE,
5086
5145
  name: "Product",
5087
- parse: parseBigOp("Product", 390),
5146
+ parse: parseBigOp("Product", MULTIPLICATION_PRECEDENCE),
5088
5147
  serialize: serializeBigOp("\\prod")
5089
5148
  },
5090
5149
  // {
@@ -5095,7 +5154,7 @@ var ComputeEngine = (() => {
5095
5154
  // },
5096
5155
  {
5097
5156
  name: "Rational",
5098
- precedence: 660,
5157
+ precedence: DIVISION_PRECEDENCE,
5099
5158
  serialize: (serializer, expr) => {
5100
5159
  if (expr && nops(expr) === 1)
5101
5160
  return "\\operatorname{Rational}" + serializer.wrapArguments(expr);
@@ -5118,9 +5177,9 @@ var ComputeEngine = (() => {
5118
5177
  },
5119
5178
  {
5120
5179
  latexTrigger: ["\\sum"],
5121
- precedence: 275,
5180
+ precedence: ADDITION_PRECEDENCE,
5122
5181
  name: "Sum",
5123
- parse: parseBigOp("Sum", 275),
5182
+ parse: parseBigOp("Sum", ADDITION_PRECEDENCE),
5124
5183
  serialize: serializeBigOp("\\sum")
5125
5184
  },
5126
5185
  {
@@ -5140,9 +5199,12 @@ var ComputeEngine = (() => {
5140
5199
  latexTrigger: ["-"],
5141
5200
  kind: "infix",
5142
5201
  associativity: "both",
5143
- precedence: 275,
5202
+ precedence: ADDITION_PRECEDENCE,
5144
5203
  parse: (parser, lhs, terminator) => {
5145
- const rhs = parser.parseExpression({ ...terminator, minPrec: 277 });
5204
+ const rhs = parser.parseExpression({
5205
+ ...terminator,
5206
+ minPrec: ADDITION_PRECEDENCE + 2
5207
+ });
5146
5208
  return ["Subtract", lhs, missingIfEmpty(rhs)];
5147
5209
  }
5148
5210
  }
@@ -5243,10 +5305,9 @@ var ComputeEngine = (() => {
5243
5305
 
5244
5306
  // src/compute-engine/latex-syntax/dictionary/definitions-core.ts
5245
5307
  function parseSequence(parser, terminator, lhs, prec, sep) {
5246
- console.assert(lhs !== null);
5247
5308
  if (terminator.minPrec >= prec)
5248
5309
  return null;
5249
- const result = [lhs];
5310
+ const result = lhs ? [lhs] : ["Nothing"];
5250
5311
  let done = false;
5251
5312
  while (!done) {
5252
5313
  done = true;
@@ -5270,7 +5331,40 @@ var ComputeEngine = (() => {
5270
5331
  return result;
5271
5332
  }
5272
5333
  function serializeOps(sep = "") {
5273
- return (serializer, expr) => (ops(expr) ?? []).map((x) => serializer.serialize(x)).join(sep);
5334
+ return (serializer, expr) => {
5335
+ if (!expr)
5336
+ return "";
5337
+ const xs = ops(expr) ?? [];
5338
+ if (xs.length === 0)
5339
+ return "";
5340
+ if (xs.length === 1)
5341
+ return serializer.serialize(xs[0]);
5342
+ sep = {
5343
+ "&": "\\&",
5344
+ ":": "\\colon",
5345
+ "|": "\\mvert",
5346
+ "-": "-",
5347
+ "\xB7": "\\cdot",
5348
+ // U+00B7 MIDDLE DOT
5349
+ "\u2012": "-",
5350
+ // U+2012 FIGURE DASH
5351
+ "\u2013": "--",
5352
+ // U+2013 EN DASH
5353
+ "\u2014": "---",
5354
+ // U+2014 EM DASH
5355
+ "\u2015": "-",
5356
+ // U+2015 HORIZONTAL BAR
5357
+ "\u2022": "\\bullet",
5358
+ // U+2022 BULLET
5359
+ "\u2026": "\\ldots"
5360
+ }[sep] ?? sep;
5361
+ const ys = xs.reduce((acc, item) => {
5362
+ acc.push(serializer.serialize(item), sep);
5363
+ return acc;
5364
+ }, []);
5365
+ ys.pop();
5366
+ return joinLatex(ys);
5367
+ };
5274
5368
  }
5275
5369
  var DEFINITIONS_CORE = [
5276
5370
  //
@@ -5301,7 +5395,7 @@ var ComputeEngine = (() => {
5301
5395
  name: "Function",
5302
5396
  latexTrigger: ["\\mapsto"],
5303
5397
  kind: "infix",
5304
- precedence: 270,
5398
+ precedence: ARROW_PRECEDENCE,
5305
5399
  // MathML rightwards arrow
5306
5400
  parse: (parser, lhs) => {
5307
5401
  let params = [];
@@ -5309,18 +5403,16 @@ var ComputeEngine = (() => {
5309
5403
  lhs = op(lhs, 1) ?? "Nothing";
5310
5404
  if (head(lhs) === "Sequence") {
5311
5405
  for (const x of ops(lhs) ?? []) {
5312
- if (symbol(x))
5313
- params.push(symbol(x));
5314
- else
5406
+ if (!symbol(x))
5315
5407
  return null;
5408
+ params.push(symbol(x));
5316
5409
  }
5317
5410
  } else {
5318
- if (symbol(lhs))
5319
- params = [symbol(lhs)];
5320
- else
5411
+ if (!symbol(lhs))
5321
5412
  return null;
5413
+ params = [symbol(lhs)];
5322
5414
  }
5323
- let rhs = parser.parseExpression({ minPrec: 270 }) ?? "Nothing";
5415
+ let rhs = parser.parseExpression({ minPrec: ARROW_PRECEDENCE }) ?? "Nothing";
5324
5416
  if (head(rhs) === "Delimiter")
5325
5417
  rhs = op(rhs, 1) ?? "Nothing";
5326
5418
  if (head(rhs) === "Sequence")
@@ -5378,50 +5470,62 @@ var ComputeEngine = (() => {
5378
5470
  return ["Apply", rhs, lhs];
5379
5471
  }
5380
5472
  },
5473
+ // The mathtools package includes several synonmyms for \colonequals. The
5474
+ // current preferred one is `\coloneq`
5381
5475
  {
5382
5476
  name: "Assign",
5383
- latexTrigger: "\\coloneqq",
5477
+ latexTrigger: "\\coloneq",
5384
5478
  kind: "infix",
5385
5479
  associativity: "right",
5386
- precedence: 260,
5480
+ precedence: ASSIGNMENT_PRECEDENCE,
5387
5481
  // parse: (parser: Parser, lhs: Expression) => {
5388
5482
  // const rhs = parser.parseExpression({ minPrec: 260 }) ?? 'Nothing';
5389
5483
  // return ['Assign', lhs, rhs];
5390
5484
  // },
5391
5485
  serialize: (serializer, expr) => {
5486
+ const id = unhold(op(expr, 1));
5487
+ if (head(op(expr, 2)) === "Function") {
5488
+ const op_2 = op(expr, 2);
5489
+ const body = unhold(op(op_2, 1));
5490
+ const args = ops(op_2)?.slice(1) ?? [];
5491
+ return joinLatex([
5492
+ serializer.serialize(id),
5493
+ serializer.wrapString(
5494
+ args.map((x) => serializer.serialize(x)).join(", "),
5495
+ serializer.options.applyFunctionStyle(expr, serializer.level)
5496
+ ),
5497
+ "\\coloneq",
5498
+ serializer.serialize(body)
5499
+ ]);
5500
+ }
5392
5501
  return joinLatex([
5393
- serializer.serialize(op(expr, 1)),
5394
- "\\coloneqq",
5502
+ serializer.serialize(id),
5503
+ "\\coloneq",
5395
5504
  serializer.serialize(op(expr, 2))
5396
5505
  ]);
5397
- }
5506
+ },
5507
+ parse: parseAssign
5398
5508
  },
5399
5509
  {
5400
5510
  latexTrigger: [":", "="],
5401
5511
  kind: "infix",
5402
5512
  associativity: "right",
5403
- precedence: 260,
5404
- parse: "Assign"
5513
+ precedence: ASSIGNMENT_PRECEDENCE,
5514
+ parse: parseAssign
5405
5515
  },
5406
- // {
5407
- // kind: 'function',
5408
- // latexTrigger: ':=', // \coloneqq
5409
- // parse: (parser: Parser, lhs: Expression) => {
5410
- // const rhs = parser.parseExpression({ minPrec: 270 }) ?? 'Nothing';
5411
- // return ['Assign', lhs, rhs];
5412
- // },
5413
- // },
5414
5516
  {
5415
5517
  latexTrigger: "\\colonequals",
5416
- // \coloneqq
5417
5518
  kind: "infix",
5418
5519
  associativity: "right",
5419
- precedence: 260,
5420
- parse: "Assign"
5421
- // parse: (parser: Parser, lhs: Expression) => {
5422
- // const rhs = parser.parseExpression({ minPrec: 270 }) ?? 'Nothing';
5423
- // return ['Assign', lhs, rhs];
5424
- // },
5520
+ precedence: ASSIGNMENT_PRECEDENCE,
5521
+ parse: parseAssign
5522
+ },
5523
+ {
5524
+ latexTrigger: "\\coloneqq",
5525
+ kind: "infix",
5526
+ associativity: "right",
5527
+ precedence: ASSIGNMENT_PRECEDENCE,
5528
+ parse: parseAssign
5425
5529
  },
5426
5530
  {
5427
5531
  name: "BaseForm",
@@ -5457,25 +5561,47 @@ var ComputeEngine = (() => {
5457
5561
  }
5458
5562
  },
5459
5563
  {
5564
+ name: "Sequence",
5565
+ // Use a space as a separator, otherwise a sequence of numbers
5566
+ // could be interpreted as a single number.
5567
+ serialize: serializeOps(" ")
5568
+ },
5569
+ {
5570
+ name: "InvisibleOperator",
5571
+ serialize: serializeOps("")
5572
+ },
5573
+ {
5574
+ // The first argument is a function expression.
5575
+ // The second (optional) argument is a string specifying the
5576
+ // delimiters and separator.
5460
5577
  name: "Delimiter",
5461
5578
  serialize: (serializer, expr) => {
5462
- const argCount = nops(expr);
5463
- if (argCount === 0)
5464
- return "";
5465
- const style = serializer.options.groupStyle(expr, serializer.level + 1);
5466
5579
  const arg1 = op(expr, 1);
5580
+ const style = serializer.options.groupStyle(expr, serializer.level + 1);
5467
5581
  const h1 = head(arg1);
5468
- const defaultFence = { List: "[],", Sequence: "" }[typeof h1 === "string" ? h1 : ""] ?? "(),";
5469
- let open = defaultFence[0] ?? "";
5470
- let close = defaultFence[1] ?? "";
5471
- let sep = defaultFence[2] ?? "";
5472
- if (argCount > 1) {
5473
- const op22 = stringValue(op(expr, 2)) ?? "";
5474
- open = op22[0] ?? defaultFence[0];
5475
- close = op22[1] ?? defaultFence[1];
5476
- sep = op22[2] ?? defaultFence[2];
5477
- }
5478
- const body = isListLike(arg1) ? serializeOps(sep)(serializer, arg1) : serializer.serialize(arg1);
5582
+ let delims = {
5583
+ Set: "{,}",
5584
+ List: "[,]",
5585
+ Tuple: "(,)",
5586
+ Single: "(,)",
5587
+ Pair: "(,)",
5588
+ Triple: "(,)",
5589
+ Sequence: "(,)",
5590
+ String: '""'
5591
+ }[typeof h1 === "string" ? h1 : ""] ?? "(,)";
5592
+ if (nops(expr) > 1) {
5593
+ const op22 = stringValue(op(expr, 2));
5594
+ if (typeof op22 === "string" && op22.length <= 3)
5595
+ delims = op22;
5596
+ }
5597
+ let [open, sep, close] = ["", "", ""];
5598
+ if (delims.length === 3)
5599
+ [open, sep, close] = delims;
5600
+ else if (delims.length === 2)
5601
+ [open, close] = delims;
5602
+ else if (delims.length === 1)
5603
+ sep = delims;
5604
+ const body = arg1 ? ops(arg1) ? serializeOps(sep)(serializer, arg1) : serializer.serialize(arg1) : "";
5479
5605
  return serializer.wrapString(body, style, open + close);
5480
5606
  }
5481
5607
  },
@@ -5584,7 +5710,7 @@ var ComputeEngine = (() => {
5584
5710
  kind: "matchfix",
5585
5711
  openTrigger: "(",
5586
5712
  closeTrigger: ")",
5587
- parse: parseDelimiter
5713
+ parse: parseParenDelimiter
5588
5714
  },
5589
5715
  {
5590
5716
  latexTrigger: [","],
@@ -5599,7 +5725,20 @@ var ComputeEngine = (() => {
5599
5725
  const seq = parseSequence(parser, terminator, lhs, 20, ",");
5600
5726
  if (seq === null)
5601
5727
  return null;
5602
- return ["Sequence", ...seq];
5728
+ return ["Delimiter", ["Sequence", ...seq], { str: "," }];
5729
+ }
5730
+ },
5731
+ // Entry to handle the case of a single comma
5732
+ // with a missing lhs.
5733
+ {
5734
+ latexTrigger: [","],
5735
+ kind: "prefix",
5736
+ precedence: 20,
5737
+ parse: (parser, terminator) => {
5738
+ const seq = parseSequence(parser, terminator, null, 20, ",");
5739
+ if (seq === null)
5740
+ return null;
5741
+ return ["Delimiter", ["Sequence", ...seq], { str: "," }];
5603
5742
  }
5604
5743
  },
5605
5744
  {
@@ -5627,10 +5766,6 @@ var ComputeEngine = (() => {
5627
5766
  return "";
5628
5767
  }
5629
5768
  },
5630
- {
5631
- name: "Sequence",
5632
- serialize: serializeOps("")
5633
- },
5634
5769
  {
5635
5770
  latexTrigger: [";"],
5636
5771
  kind: "infix",
@@ -5639,12 +5774,7 @@ var ComputeEngine = (() => {
5639
5774
  const seq = parseSequence(parser, terminator, lhs, 19, ";");
5640
5775
  if (seq === null)
5641
5776
  return null;
5642
- return [
5643
- "Sequence",
5644
- ...seq.map(
5645
- (x) => head(x) === "Sequence" ? ["List", ...ops(x) ?? []] : x
5646
- )
5647
- ];
5777
+ return ["Delimiter", ["Sequence", ...seq], "';'"];
5648
5778
  }
5649
5779
  },
5650
5780
  {
@@ -5911,8 +6041,66 @@ var ComputeEngine = (() => {
5911
6041
  text += "$$";
5912
6042
  parser.index = index;
5913
6043
  }
5914
- } else
5915
- text += parser.matchChar() ?? parser.nextToken();
6044
+ } else {
6045
+ const c = parser.matchChar() ?? parser.nextToken();
6046
+ text += {
6047
+ "\\enskip": "\u2002",
6048
+ // en space
6049
+ "\\enspace": "\u2002",
6050
+ // en space
6051
+ "\\quad": "\u2003",
6052
+ // em space
6053
+ "\\qquad": "\u2003\u2003",
6054
+ // 2 em space
6055
+ "\\space": "\u2003",
6056
+ // em space
6057
+ "\\ ": "\u2003",
6058
+ // em space
6059
+ "\\;": "\u2004",
6060
+ // three per em space
6061
+ "\\,": "\u2009",
6062
+ // thin space
6063
+ "\\:": "\u205F",
6064
+ // medium mathematical space
6065
+ "\\!": "",
6066
+ // negative thin space
6067
+ "\\{": "{",
6068
+ "\\}": "}",
6069
+ "\\$": "$",
6070
+ "\\&": "&",
6071
+ "\\#": "#",
6072
+ "\\%": "%",
6073
+ "\\_": "_",
6074
+ "\\textbackslash": "\\",
6075
+ "\\textasciitilde": "~",
6076
+ "\\textasciicircum": "^",
6077
+ "\\textless": "<",
6078
+ "\\textgreater": ">",
6079
+ "\\textbar": "|",
6080
+ "\\textunderscore": "_",
6081
+ "\\textbraceleft": "{",
6082
+ "\\textbraceright": "}",
6083
+ "\\textasciigrave": "`",
6084
+ "\\textquotesingle": "'",
6085
+ "\\textquotedblleft": "\u201C",
6086
+ "\\textquotedblright": "\u201D",
6087
+ "\\textquotedbl": '"',
6088
+ "\\textquoteleft": "\u2018",
6089
+ "\\textquoteright": "\u2019",
6090
+ "\\textbullet": "\u2022",
6091
+ "\\textdagger": "\u2020",
6092
+ "\\textdaggerdbl": "\u2021",
6093
+ "\\textsection": "\xA7",
6094
+ "\\textparagraph": "\xB6",
6095
+ "\\textperiodcentered": "\xB7",
6096
+ "\\textellipsis": "\u2026",
6097
+ "\\textemdash": "\u2014",
6098
+ "\\textendash": "\u2013",
6099
+ "\\textregistered": "\xAE",
6100
+ "\\texttrademark": "\u2122",
6101
+ "\\textdegree": "\xB0"
6102
+ }[c] ?? c;
6103
+ }
5916
6104
  }
5917
6105
  if (runinStyle !== null && text) {
5918
6106
  runs.push(["Style", `'${text}'`, { dict: runinStyle }]);
@@ -5992,19 +6180,27 @@ var ComputeEngine = (() => {
5992
6180
  return ["Prime", missingIfEmpty(lhs)];
5993
6181
  return ["Prime", missingIfEmpty(lhs), order2];
5994
6182
  }
5995
- function parseDelimiter(_parser, body) {
6183
+ function parseParenDelimiter(_parser, body) {
5996
6184
  if (body === null || isEmptySequence(body))
5997
- return ["Sequence"];
6185
+ return ["Delimiter"];
6186
+ if (head(body) === "Delimiter" && op(body, 2)) {
6187
+ const delims = stringValue(op(body, 2));
6188
+ if (delims?.length === 1) {
6189
+ return ["Delimiter", op(body, 1) ?? ["Sequence"], { str: `(${delims})` }];
6190
+ }
6191
+ }
5998
6192
  if (head(body) === "Sequence") {
5999
6193
  if (nops(body) === 0)
6000
6194
  return ["Delimiter"];
6001
- return ["Delimiter", ["Sequence", ...ops(body) ?? []]];
6195
+ return ["Delimiter", body];
6002
6196
  }
6003
- return ["Delimiter", body];
6197
+ return ["Delimiter", ["Sequence", body]];
6004
6198
  }
6005
6199
  function parseList(_parser, body) {
6006
6200
  if (body === null || isEmptySequence(body))
6007
6201
  return ["List"];
6202
+ if (head(body) === "Delimiter")
6203
+ return parseList(_parser, op(body, 1));
6008
6204
  if (head(body) === "Range")
6009
6205
  return body;
6010
6206
  if (head(body) !== "Sequence" && head(body) !== "List")
@@ -6045,6 +6241,80 @@ var ComputeEngine = (() => {
6045
6241
  }
6046
6242
  return ["Range", start, end];
6047
6243
  }
6244
+ var DELIMITERS_SHORTHAND = {
6245
+ "(": "(",
6246
+ ")": ")",
6247
+ "[": "\\lbrack",
6248
+ "]": "\\rbrack",
6249
+ "\u27E6": "\\llbrack",
6250
+ // U+27E6 MATHEMATICAL LEFT WHITE SQUARE BRACKET
6251
+ "\u27E7": "\\rrbrack",
6252
+ // U+27E7 MATHEMATICAL RIGHT WHITE SQUARE BRACKET
6253
+ "{": "\\lbrace",
6254
+ "}": "\\rbrace",
6255
+ "<": "\\langle",
6256
+ ">": "\\rangle",
6257
+ // '|': '\\vert',
6258
+ "\u2016": "\\Vert",
6259
+ // U+2016 DOUBLE VERTICAL LINE
6260
+ "\\": "\\backslash",
6261
+ "\u2308": "\\lceil",
6262
+ // ⌈ U+2308 LEFT CEILING
6263
+ "\u2309": "\\rceil",
6264
+ // U+2309 RIGHT CEILING
6265
+ "\u230A": "\\lfloor",
6266
+ // ⌊ U+230A LEFT FLOOR
6267
+ "\u230B": "\\rfloor",
6268
+ // ⌋ U+230B RIGHT FLOOR
6269
+ "\u231C": "\\ulcorner",
6270
+ // ⌜ U+231C TOP LEFT CORNER
6271
+ "\u231D": "\\urcorner",
6272
+ // ⌝ U+231D TOP RIGHT CORNER
6273
+ "\u231E": "\\llcorner",
6274
+ // ⌞ U+231E BOTTOM LEFT CORNER
6275
+ "\u231F": "\\lrcorner",
6276
+ // ⌟ U+231F BOTTOM RIGHT CORNER
6277
+ "\u23B0": "\\lmoustache",
6278
+ // U+23B0 UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION
6279
+ "\u23B1": "\\rmoustache"
6280
+ // U+23B1 UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION
6281
+ // '⎹': '', // U+23B9 DIVIDES
6282
+ // '⎾': '', // U+23BE RIGHT PARENTHESIS UPPER HOOK
6283
+ // '⎿': '', // U+23BF RIGHT PARENTHESIS LOWER HOOK
6284
+ };
6285
+ function parseAssign(parser, lhs) {
6286
+ const index = parser.index;
6287
+ if (head(lhs) === "InvisibleOperator" && nops(lhs) === 2 && head(op(lhs, 2)) === "Delimiter" && head(op(op(lhs, 2), 1)) === "Sequence") {
6288
+ const fn = symbol(op(lhs, 1));
6289
+ if (!fn)
6290
+ return null;
6291
+ const args = ops(op(op(lhs, 2), 1));
6292
+ const rhs2 = parser.parseExpression({ minPrec: 0 });
6293
+ if (rhs2 === null) {
6294
+ parser.index = index;
6295
+ return null;
6296
+ }
6297
+ return ["Assign", fn, ["Function", rhs2, ...args ?? []]];
6298
+ }
6299
+ if (typeof head(lhs) === "string") {
6300
+ const fn = head(lhs);
6301
+ const args = ops(lhs) ?? [];
6302
+ const rhs2 = parser.parseExpression({ minPrec: 0 });
6303
+ if (rhs2 === null) {
6304
+ parser.index = index;
6305
+ return null;
6306
+ }
6307
+ return ["Assign", fn, ["Function", rhs2, ...args]];
6308
+ }
6309
+ if (!symbol(lhs))
6310
+ return null;
6311
+ const rhs = parser.parseExpression({ minPrec: 0 });
6312
+ if (rhs === null) {
6313
+ parser.index = index;
6314
+ return null;
6315
+ }
6316
+ return ["Assign", lhs, rhs];
6317
+ }
6048
6318
 
6049
6319
  // src/compute-engine/latex-syntax/dictionary/definitions-inequalities.ts
6050
6320
  var DEFINITIONS_INEQUALITIES = [
@@ -6101,7 +6371,7 @@ var ComputeEngine = (() => {
6101
6371
  latexTrigger: ["\\leqslant"],
6102
6372
  kind: "infix",
6103
6373
  associativity: "right",
6104
- precedence: 265,
6374
+ precedence: COMPARISON_PRECEDENCE + 5,
6105
6375
  // Note different precedence than `<=` as per MathML
6106
6376
  parse: "LessEqual"
6107
6377
  },
@@ -6110,28 +6380,28 @@ var ComputeEngine = (() => {
6110
6380
  latexTrigger: ["\\lneqq"],
6111
6381
  kind: "infix",
6112
6382
  associativity: "right",
6113
- precedence: 260
6383
+ precedence: COMPARISON_PRECEDENCE
6114
6384
  },
6115
6385
  {
6116
6386
  name: "NotLessNotEqual",
6117
6387
  latexTrigger: ["\\nleqq"],
6118
6388
  kind: "infix",
6119
6389
  associativity: "right",
6120
- precedence: 260
6390
+ precedence: COMPARISON_PRECEDENCE
6121
6391
  },
6122
6392
  {
6123
6393
  name: "LessOverEqual",
6124
6394
  latexTrigger: ["\\leqq"],
6125
6395
  kind: "infix",
6126
6396
  associativity: "right",
6127
- precedence: 265
6397
+ precedence: COMPARISON_PRECEDENCE + 5
6128
6398
  },
6129
6399
  {
6130
6400
  name: "GreaterOverEqual",
6131
6401
  latexTrigger: ["\\geqq"],
6132
6402
  kind: "infix",
6133
6403
  associativity: "right",
6134
- precedence: 265,
6404
+ precedence: COMPARISON_PRECEDENCE + 5,
6135
6405
  parse: "GreaterEqual"
6136
6406
  },
6137
6407
  {
@@ -6139,13 +6409,13 @@ var ComputeEngine = (() => {
6139
6409
  latexTrigger: ["="],
6140
6410
  kind: "infix",
6141
6411
  associativity: "right",
6142
- precedence: 260
6412
+ precedence: COMPARISON_PRECEDENCE
6143
6413
  },
6144
6414
  {
6145
6415
  latexTrigger: ["*", "="],
6146
6416
  kind: "infix",
6147
6417
  associativity: "right",
6148
- precedence: 260,
6418
+ precedence: COMPARISON_PRECEDENCE,
6149
6419
  parse: "StarEqual"
6150
6420
  },
6151
6421
  {
@@ -6153,42 +6423,42 @@ var ComputeEngine = (() => {
6153
6423
  latexTrigger: ["\\star", "="],
6154
6424
  kind: "infix",
6155
6425
  associativity: "right",
6156
- precedence: 260
6426
+ precedence: COMPARISON_PRECEDENCE
6157
6427
  },
6158
6428
  {
6159
6429
  name: "PlusEqual",
6160
6430
  latexTrigger: ["+", "="],
6161
6431
  kind: "infix",
6162
6432
  associativity: "right",
6163
- precedence: 260
6433
+ precedence: COMPARISON_PRECEDENCE
6164
6434
  },
6165
6435
  {
6166
6436
  name: "MinusEqual",
6167
6437
  latexTrigger: ["-", "="],
6168
6438
  kind: "infix",
6169
6439
  associativity: "right",
6170
- precedence: 260
6440
+ precedence: COMPARISON_PRECEDENCE
6171
6441
  },
6172
6442
  {
6173
6443
  name: "SlashEqual",
6174
6444
  latexTrigger: ["/", "="],
6175
6445
  kind: "infix",
6176
6446
  associativity: "right",
6177
- precedence: 260
6447
+ precedence: COMPARISON_PRECEDENCE
6178
6448
  },
6179
6449
  {
6180
6450
  name: "EqualEqual",
6181
6451
  latexTrigger: ["=", "="],
6182
6452
  kind: "infix",
6183
6453
  associativity: "right",
6184
- precedence: 260
6454
+ precedence: COMPARISON_PRECEDENCE
6185
6455
  },
6186
6456
  {
6187
6457
  name: "EqualEqualEqual",
6188
6458
  latexTrigger: ["=", "=", "="],
6189
6459
  kind: "infix",
6190
6460
  associativity: "right",
6191
- precedence: 265
6461
+ precedence: COMPARISON_PRECEDENCE + 5
6192
6462
  },
6193
6463
  {
6194
6464
  name: "TildeFullEqual",
@@ -6196,7 +6466,7 @@ var ComputeEngine = (() => {
6196
6466
  latexTrigger: ["\\cong"],
6197
6467
  kind: "infix",
6198
6468
  associativity: "right",
6199
- precedence: 260
6469
+ precedence: COMPARISON_PRECEDENCE
6200
6470
  },
6201
6471
  {
6202
6472
  name: "NotTildeFullEqual",
@@ -6204,7 +6474,7 @@ var ComputeEngine = (() => {
6204
6474
  latexTrigger: ["\\ncong"],
6205
6475
  kind: "infix",
6206
6476
  associativity: "right",
6207
- precedence: 260
6477
+ precedence: COMPARISON_PRECEDENCE
6208
6478
  },
6209
6479
  {
6210
6480
  name: "Approx",
@@ -6228,7 +6498,7 @@ var ComputeEngine = (() => {
6228
6498
  latexTrigger: ["\\approxeq"],
6229
6499
  kind: "infix",
6230
6500
  associativity: "right",
6231
- precedence: 260
6501
+ precedence: COMPARISON_PRECEDENCE
6232
6502
  },
6233
6503
  {
6234
6504
  name: "NotApproxEqual",
@@ -6251,7 +6521,7 @@ var ComputeEngine = (() => {
6251
6521
  latexTrigger: ["!", "="],
6252
6522
  kind: "infix",
6253
6523
  associativity: "right",
6254
- precedence: 260
6524
+ precedence: COMPARISON_PRECEDENCE
6255
6525
  // Note different precedence than \\ne per MathML
6256
6526
  },
6257
6527
  {
@@ -6281,7 +6551,7 @@ var ComputeEngine = (() => {
6281
6551
  latexTrigger: ["\\geqslant"],
6282
6552
  kind: "infix",
6283
6553
  associativity: "right",
6284
- precedence: 265,
6554
+ precedence: COMPARISON_PRECEDENCE + 5,
6285
6555
  // Note: different precedence than `>=` as per MathML
6286
6556
  parse: "GreaterEqual"
6287
6557
  },
@@ -6290,14 +6560,14 @@ var ComputeEngine = (() => {
6290
6560
  latexTrigger: ["\\gneqq"],
6291
6561
  kind: "infix",
6292
6562
  associativity: "right",
6293
- precedence: 260
6563
+ precedence: COMPARISON_PRECEDENCE
6294
6564
  },
6295
6565
  {
6296
6566
  name: "NotGreaterNotEqual",
6297
6567
  latexTrigger: ["\\ngeqq"],
6298
6568
  kind: "infix",
6299
6569
  associativity: "right",
6300
- precedence: 260
6570
+ precedence: COMPARISON_PRECEDENCE
6301
6571
  },
6302
6572
  {
6303
6573
  latexTrigger: [">"],
@@ -6332,7 +6602,7 @@ var ComputeEngine = (() => {
6332
6602
  latexTrigger: ["\\circeq"],
6333
6603
  kind: "infix",
6334
6604
  associativity: "right",
6335
- precedence: 260
6605
+ precedence: COMPARISON_PRECEDENCE
6336
6606
  },
6337
6607
  {
6338
6608
  name: "TriangleEqual",
@@ -6340,7 +6610,7 @@ var ComputeEngine = (() => {
6340
6610
  latexTrigger: ["\\triangleq"],
6341
6611
  kind: "infix",
6342
6612
  associativity: "right",
6343
- precedence: 260
6613
+ precedence: COMPARISON_PRECEDENCE
6344
6614
  },
6345
6615
  {
6346
6616
  name: "DotEqual",
@@ -6348,7 +6618,7 @@ var ComputeEngine = (() => {
6348
6618
  latexTrigger: ["\\doteq"],
6349
6619
  kind: "infix",
6350
6620
  associativity: "right",
6351
- precedence: 265
6621
+ precedence: COMPARISON_PRECEDENCE + 5
6352
6622
  },
6353
6623
  {
6354
6624
  name: "DotEqualDot",
@@ -6356,7 +6626,7 @@ var ComputeEngine = (() => {
6356
6626
  latexTrigger: ["\\doteqdot"],
6357
6627
  kind: "infix",
6358
6628
  associativity: "right",
6359
- precedence: 265
6629
+ precedence: COMPARISON_PRECEDENCE + 5
6360
6630
  },
6361
6631
  {
6362
6632
  name: "FallingDotEqual",
@@ -6364,7 +6634,7 @@ var ComputeEngine = (() => {
6364
6634
  latexTrigger: ["\\fallingdotseq"],
6365
6635
  kind: "infix",
6366
6636
  associativity: "right",
6367
- precedence: 265
6637
+ precedence: COMPARISON_PRECEDENCE + 5
6368
6638
  },
6369
6639
  {
6370
6640
  name: "RisingDotEqual",
@@ -6372,77 +6642,182 @@ var ComputeEngine = (() => {
6372
6642
  latexTrigger: ["\\fallingdotseq"],
6373
6643
  kind: "infix",
6374
6644
  associativity: "right",
6375
- precedence: 265
6645
+ precedence: COMPARISON_PRECEDENCE + 5
6376
6646
  },
6377
6647
  {
6378
6648
  name: "QuestionEqual",
6379
6649
  latexTrigger: ["\\questeq"],
6380
6650
  kind: "infix",
6381
6651
  associativity: "right",
6382
- precedence: 260
6652
+ precedence: COMPARISON_PRECEDENCE
6383
6653
  },
6384
6654
  {
6385
6655
  name: "MuchLess",
6386
6656
  latexTrigger: ["\\ll"],
6387
6657
  kind: "infix",
6388
6658
  associativity: "right",
6389
- precedence: 260
6659
+ precedence: COMPARISON_PRECEDENCE
6390
6660
  },
6391
6661
  {
6392
6662
  name: "MuchGreater",
6393
6663
  latexTrigger: ["\\gg"],
6394
6664
  kind: "infix",
6395
6665
  associativity: "right",
6396
- precedence: 260
6666
+ precedence: COMPARISON_PRECEDENCE
6397
6667
  },
6398
6668
  {
6399
6669
  name: "Precedes",
6400
6670
  latexTrigger: ["\\prec"],
6401
6671
  kind: "infix",
6402
6672
  associativity: "right",
6403
- precedence: 260
6673
+ precedence: COMPARISON_PRECEDENCE
6404
6674
  },
6405
6675
  {
6406
6676
  name: "Succeeds",
6407
6677
  latexTrigger: ["\\succ"],
6408
6678
  kind: "infix",
6409
6679
  associativity: "right",
6410
- precedence: 260
6680
+ precedence: COMPARISON_PRECEDENCE
6411
6681
  },
6412
6682
  {
6413
6683
  name: "PrecedesEqual",
6414
6684
  latexTrigger: ["\\preccurlyeq"],
6415
6685
  kind: "infix",
6416
6686
  associativity: "right",
6417
- precedence: 260
6687
+ precedence: COMPARISON_PRECEDENCE
6418
6688
  },
6419
6689
  {
6420
6690
  name: "SucceedsEqual",
6421
6691
  latexTrigger: ["\\curlyeqprec"],
6422
6692
  kind: "infix",
6423
6693
  associativity: "right",
6424
- precedence: 260
6694
+ precedence: COMPARISON_PRECEDENCE
6425
6695
  },
6426
6696
  {
6427
6697
  name: "NotPrecedes",
6428
6698
  latexTrigger: ["\\nprec"],
6429
6699
  kind: "infix",
6430
6700
  associativity: "right",
6431
- precedence: 260
6701
+ precedence: COMPARISON_PRECEDENCE
6432
6702
  },
6433
6703
  {
6434
6704
  name: "NotSucceeds",
6435
6705
  latexTrigger: ["\\nsucc"],
6436
6706
  kind: "infix",
6437
6707
  associativity: "right",
6438
- precedence: 260
6708
+ precedence: COMPARISON_PRECEDENCE
6439
6709
  },
6440
6710
  {
6441
6711
  name: "Between",
6442
6712
  latexTrigger: ["\\between"],
6443
6713
  kind: "infix",
6444
6714
  associativity: "right",
6445
- precedence: 265
6715
+ precedence: COMPARISON_PRECEDENCE + 5
6716
+ }
6717
+ ];
6718
+
6719
+ // src/compute-engine/latex-syntax/dictionary/definitions-linear-algebra.ts
6720
+ var DEFINITIONS_LINEAR_ALGEBRA = [
6721
+ // The first argument is the matrix data.
6722
+ // The second, optional, argument are the delimiters.
6723
+ // The third, optional, argument is the column specification.
6724
+ {
6725
+ name: "Matrix",
6726
+ // https://ctan.math.illinois.edu/macros/latex/required/tools/array.pdf
6727
+ serialize: (serializer, expr) => {
6728
+ const body = op(expr, 1);
6729
+ const delims = op(expr, 2) ?? "()";
6730
+ let columns = "";
6731
+ if (op(expr, 3) !== null) {
6732
+ const colsSpec = stringValue(op(expr, 3)) ?? "";
6733
+ for (const c of colsSpec) {
6734
+ if (c === "<")
6735
+ columns += "l";
6736
+ else if (c === ">")
6737
+ columns += "r";
6738
+ else if (c === "=")
6739
+ columns += "c";
6740
+ else if (c === "|")
6741
+ columns += "|";
6742
+ else if (c === ":")
6743
+ columns += ":";
6744
+ }
6745
+ }
6746
+ let [open, close] = ["", ""];
6747
+ if (typeof delims === "string" && delims.length === 2)
6748
+ [open, close] = delims;
6749
+ const rows = [];
6750
+ for (const row of ops(body) ?? []) {
6751
+ const cells = [];
6752
+ for (const cell of ops(row) ?? [])
6753
+ cells.push(serializer.serialize(cell));
6754
+ rows.push(cells.join(" & "));
6755
+ }
6756
+ const tabular = rows.join("\\\\\n");
6757
+ const optColumns = columns.length > 0 ? `[${columns}]` : "";
6758
+ if (open === "(" && close === ")")
6759
+ return joinLatex([
6760
+ "\\begin{pmatrix}",
6761
+ optColumns,
6762
+ tabular,
6763
+ "\\end{pmatrix}"
6764
+ ]);
6765
+ if (open === "[" && close === "]")
6766
+ return joinLatex([
6767
+ "\\begin{bmatrix}",
6768
+ optColumns,
6769
+ tabular,
6770
+ "\\end{bmatrix}"
6771
+ ]);
6772
+ if (open === "{" && close === "}")
6773
+ return joinLatex([
6774
+ "\\begin{Bmatrix}",
6775
+ optColumns,
6776
+ tabular,
6777
+ "\\end{Bmatrix}"
6778
+ ]);
6779
+ if (open === "|" && close === "|")
6780
+ return joinLatex([
6781
+ "\\begin{vmatrix}",
6782
+ optColumns,
6783
+ tabular,
6784
+ "\\end{vmatrix}"
6785
+ ]);
6786
+ if (open === "\u2016" && close === "\u2016")
6787
+ return joinLatex([
6788
+ "\\begin{Vmatrix}",
6789
+ optColumns,
6790
+ tabular,
6791
+ "\\end{Vmatrix}"
6792
+ ]);
6793
+ if (open === "{" && close === ".")
6794
+ return joinLatex([
6795
+ "\\begin{dcases}",
6796
+ optColumns,
6797
+ tabular,
6798
+ "\\end{dcases}"
6799
+ ]);
6800
+ if (open === "." && close === "}")
6801
+ return joinLatex([
6802
+ "\\begin{rcases}",
6803
+ optColumns,
6804
+ tabular,
6805
+ "\\end{rcases}"
6806
+ ]);
6807
+ if (columns || open !== "." || close !== ".") {
6808
+ return joinLatex([
6809
+ "\\left",
6810
+ DELIMITERS_SHORTHAND[open] ?? open,
6811
+ "\\begin{array}",
6812
+ `{${columns}}`,
6813
+ tabular,
6814
+ "\\end{array}",
6815
+ "\\right",
6816
+ DELIMITERS_SHORTHAND[close] ?? close
6817
+ ]);
6818
+ }
6819
+ return joinLatex(["\\begin{matrix}", tabular, "\\end{matrix}"]);
6820
+ }
6446
6821
  }
6447
6822
  ];
6448
6823
 
@@ -6596,7 +6971,15 @@ var ComputeEngine = (() => {
6596
6971
  kind: "infix",
6597
6972
  associativity: "right",
6598
6973
  precedence: 219,
6599
- parse: "Equivalent"
6974
+ parse: (parser, lhs, terminator) => {
6975
+ const rhs = parser.parseExpression({ ...terminator, minPrec: 219 });
6976
+ const index = parser.index;
6977
+ const modulus = parser.parseExpression({ ...terminator, minPrec: 219 });
6978
+ if (modulus && head(modulus) === "Mod")
6979
+ return ["Congruent", lhs, rhs, missingIfEmpty(op(modulus, 1))];
6980
+ parser.index = index;
6981
+ return ["Equivalent", lhs, missingIfEmpty(rhs)];
6982
+ }
6600
6983
  },
6601
6984
  {
6602
6985
  name: "Proves",
@@ -7349,6 +7732,9 @@ var ComputeEngine = (() => {
7349
7732
  parse: (_parser, body) => {
7350
7733
  if (body === null || isEmptySequence(body))
7351
7734
  return "EmptySet";
7735
+ if (head(body) == "Delimiter" && stringValue(op(body, 2)) === ",") {
7736
+ body = op(body, 1);
7737
+ }
7352
7738
  if (head(body) !== "Sequence")
7353
7739
  return ["Set", body];
7354
7740
  return ["Set", ...ops(body) ?? []];
@@ -7373,7 +7759,7 @@ var ComputeEngine = (() => {
7373
7759
  // or \\ominus
7374
7760
  kind: "infix",
7375
7761
  // @todo: parser could check that lhs and rhs are sets
7376
- precedence: 260
7762
+ precedence: COMPARISON_PRECEDENCE
7377
7763
  },
7378
7764
  // Predicates/Relations
7379
7765
  {
@@ -7707,7 +8093,10 @@ var ComputeEngine = (() => {
7707
8093
  const op12 = op(expr, 1);
7708
8094
  if (!op12)
7709
8095
  return [expr, null];
7710
- if (h === "Multiply") {
8096
+ if (h === "Sequence" && nops(expr) === 1) {
8097
+ return parseIntegralBodyExpression(op12);
8098
+ }
8099
+ if (h === "Multiply" || h === "InvisibleOperator") {
7711
8100
  const args = ops(expr);
7712
8101
  if (args && args.length > 1) {
7713
8102
  const sym = symbol(args[args.length - 2]);
@@ -7730,7 +8119,7 @@ var ComputeEngine = (() => {
7730
8119
  if (index) {
7731
8120
  if (!fn2)
7732
8121
  return [null, index];
7733
- return [["Delimiter", fn2, ...ops(expr).slice(1)], index];
8122
+ return [["Delimiter", ["Sequence", fn2], ...ops(expr).slice(1)], index];
7734
8123
  }
7735
8124
  } else if (h === "Add") {
7736
8125
  const args = ops(expr);
@@ -8473,25 +8862,26 @@ var ComputeEngine = (() => {
8473
8862
  return true;
8474
8863
  }
8475
8864
  var DEFAULT_LATEX_DICTIONARY = {
8476
- algebra: DEFINITIONS_ALGEBRA,
8477
- arithmetic: DEFINITIONS_ARITHMETIC,
8478
- calculus: DEFINITIONS_CALCULUS,
8479
- complex: DEFINITIONS_COMPLEX,
8480
- core: DEFINITIONS_CORE,
8481
- logic: DEFINITIONS_LOGIC,
8482
- relop: DEFINITIONS_INEQUALITIES,
8483
- other: DEFINITIONS_OTHERS,
8484
- physics: [
8865
+ "algebra": DEFINITIONS_ALGEBRA,
8866
+ "arithmetic": DEFINITIONS_ARITHMETIC,
8867
+ "calculus": DEFINITIONS_CALCULUS,
8868
+ "complex": DEFINITIONS_COMPLEX,
8869
+ "core": DEFINITIONS_CORE,
8870
+ "linear-algebra": DEFINITIONS_LINEAR_ALGEBRA,
8871
+ "logic": DEFINITIONS_LOGIC,
8872
+ "relop": DEFINITIONS_INEQUALITIES,
8873
+ "other": DEFINITIONS_OTHERS,
8874
+ "physics": [
8485
8875
  {
8486
8876
  name: "mu0",
8487
8877
  kind: "symbol",
8488
8878
  latexTrigger: "\\mu_0"
8489
8879
  }
8490
8880
  ],
8491
- sets: DEFINITIONS_SETS,
8492
- statistics: DEFINITIONS_STATISTICS,
8493
- symbols: DEFINITIONS_SYMBOLS,
8494
- trigonometry: DEFINITIONS_TRIGONOMETRY
8881
+ "sets": DEFINITIONS_SETS,
8882
+ "statistics": DEFINITIONS_STATISTICS,
8883
+ "symbols": DEFINITIONS_SYMBOLS,
8884
+ "trigonometry": DEFINITIONS_TRIGONOMETRY
8495
8885
  };
8496
8886
 
8497
8887
  // src/compute-engine/latex-syntax/parse-identifier.ts
@@ -8805,7 +9195,6 @@ var ComputeEngine = (() => {
8805
9195
  avoidExponentsInRange: [-7, 20]
8806
9196
  };
8807
9197
  var DEFAULT_PARSE_LATEX_OPTIONS = {
8808
- applyInvisibleOperator: "auto",
8809
9198
  skipSpace: true,
8810
9199
  parseArgumentsOfUnknownLatexCommands: true,
8811
9200
  parseNumbers: "auto",
@@ -9209,11 +9598,12 @@ var ComputeEngine = (() => {
9209
9598
  this.skipSpace();
9210
9599
  if (this.matchBoundary())
9211
9600
  return expr ?? ["Sequence"];
9212
- const from = this.index;
9213
9601
  while (!this.matchBoundary() && !this.atEnd)
9214
9602
  this.nextToken();
9215
- const err = this.error("syntax-error", from);
9216
- return expr ? ["Sequence", expr, err] : err;
9603
+ if (head(expr) === "Error")
9604
+ return expr;
9605
+ const err = this.error("expected-closing-delimiter", start);
9606
+ return expr ? ["InvisibleOperator", expr, err] : err;
9217
9607
  }
9218
9608
  this.index = start;
9219
9609
  return null;
@@ -9360,7 +9750,7 @@ var ComputeEngine = (() => {
9360
9750
  }
9361
9751
  parseDecimalDigits(options) {
9362
9752
  options ?? (options = {});
9363
- options.withGrouping ?? (options.withGrouping = false);
9753
+ options.withGrouping ?? (options.withGrouping = true);
9364
9754
  const result = [];
9365
9755
  let done = false;
9366
9756
  while (!done) {
@@ -9385,7 +9775,7 @@ var ComputeEngine = (() => {
9385
9775
  }
9386
9776
  parseSignedInteger(options) {
9387
9777
  options ?? (options = {});
9388
- options.withGrouping ?? (options.withGrouping = false);
9778
+ options.withGrouping ?? (options.withGrouping = true);
9389
9779
  const start = this.index;
9390
9780
  const sign2 = this.parseOptionalSign();
9391
9781
  const result = this.parseDecimalDigits(options);
@@ -9425,7 +9815,7 @@ var ComputeEngine = (() => {
9425
9815
  this.skipSpaceTokens();
9426
9816
  if (this.matchAll(this._beginExponentMarkerTokens)) {
9427
9817
  this.skipSpaceTokens();
9428
- const exponent = this.parseSignedInteger();
9818
+ const exponent = this.parseSignedInteger({ withGrouping: false });
9429
9819
  this.skipSpaceTokens();
9430
9820
  if (this.matchAll(this._endExponentMarkerTokens) && exponent)
9431
9821
  return exponent;
@@ -9480,7 +9870,14 @@ var ComputeEngine = (() => {
9480
9870
  return null;
9481
9871
  const start = this.index;
9482
9872
  this.skipVisualSpace();
9483
- this.match("+");
9873
+ let sign2 = 1;
9874
+ while (this.peek === "-" || this.peek === "+") {
9875
+ if (this.match("-"))
9876
+ sign2 *= -1;
9877
+ else
9878
+ this.match("+");
9879
+ this.skipVisualSpace();
9880
+ }
9484
9881
  let wholePart = "";
9485
9882
  let fractionalPart = "";
9486
9883
  let startsWithDecimalMarker = false;
@@ -9491,21 +9888,17 @@ var ComputeEngine = (() => {
9491
9888
  wholePart = "0";
9492
9889
  }
9493
9890
  } else
9494
- wholePart = this.parseDecimalDigits({ withGrouping: true });
9891
+ wholePart = this.parseDecimalDigits();
9495
9892
  if (!wholePart) {
9496
9893
  this.index = start;
9497
9894
  return null;
9498
9895
  }
9499
9896
  const fractionalIndex = this.index;
9500
- let hasFractionalPart = true;
9897
+ let hasFractionalPart = false;
9501
9898
  if (startsWithDecimalMarker || this.match(".") || this.matchAll(this._decimalMarkerTokens)) {
9502
- fractionalPart = this.parseDecimalDigits({ withGrouping: true });
9503
- if (!fractionalPart) {
9504
- this.index = fractionalIndex;
9505
- return { num: wholePart };
9506
- }
9507
- } else
9508
- hasFractionalPart = false;
9899
+ fractionalPart = this.parseDecimalDigits();
9900
+ hasFractionalPart = true;
9901
+ }
9509
9902
  let hasRepeatingPart = false;
9510
9903
  if (hasFractionalPart) {
9511
9904
  const repeat = this.parseRepeatingDecimal();
@@ -9515,14 +9908,18 @@ var ComputeEngine = (() => {
9515
9908
  } else if (this.match("\\ldots") || this.matchAll(this._truncationMarkerTokens)) {
9516
9909
  }
9517
9910
  }
9911
+ if (hasFractionalPart && !fractionalPart) {
9912
+ this.index = fractionalIndex;
9913
+ return { num: sign2 < 0 ? "-" + wholePart : wholePart };
9914
+ }
9518
9915
  this.skipVisualSpace();
9519
9916
  const exponent = this.parseExponent();
9520
9917
  if (!hasRepeatingPart && this.options.parseNumbers === "rational") {
9521
9918
  const whole = parseInt(wholePart, 10);
9522
9919
  if (!fractionalPart) {
9523
9920
  if (exponent)
9524
- return ["Multiply", whole, ["Power", 10, exponent]];
9525
- return whole;
9921
+ return ["Multiply", sign2 * whole, ["Power", 10, exponent]];
9922
+ return sign2 * whole;
9526
9923
  }
9527
9924
  const fraction = parseInt(fractionalPart, 10);
9528
9925
  const n = fractionalPart.length;
@@ -9531,14 +9928,14 @@ var ComputeEngine = (() => {
9531
9928
  if (exponent) {
9532
9929
  return [
9533
9930
  "Multiply",
9534
- ["Rational", numerator, denominator],
9931
+ ["Rational", sign2 * numerator, denominator],
9535
9932
  ["Power", 10, exponent]
9536
9933
  ];
9537
9934
  }
9538
- return ["Rational", numerator, denominator];
9935
+ return ["Rational", sign2 * numerator, denominator];
9539
9936
  }
9540
9937
  return {
9541
- num: wholePart + (hasFractionalPart ? "." + fractionalPart : "") + (exponent ? "e" + exponent : "")
9938
+ num: (sign2 < 0 ? "-" : "") + wholePart + (hasFractionalPart ? "." + fractionalPart : "") + (exponent ? "e" + exponent : "")
9542
9939
  };
9543
9940
  }
9544
9941
  /**
@@ -9666,8 +10063,13 @@ var ComputeEngine = (() => {
9666
10063
  return getSequence(group) ?? [];
9667
10064
  }
9668
10065
  if (kind === "implicit") {
9669
- if (head(group) === "Delimiter")
9670
- return getSequence(group) ?? [];
10066
+ if (head(group) === "Delimiter") {
10067
+ if (head(op1(group)) === "Sequence") {
10068
+ const seq = op1(op1(group));
10069
+ return seq ? [seq] : [];
10070
+ }
10071
+ return op1(group) ? [op1(group)] : [];
10072
+ }
9671
10073
  if (group !== null)
9672
10074
  return [group];
9673
10075
  const primary = this.parseExpression({ ...until, minPrec: 390 });
@@ -9926,7 +10328,7 @@ var ComputeEngine = (() => {
9926
10328
  );
9927
10329
  if (defs) {
9928
10330
  const nonEmptySuperscripts = superscripts.filter(
9929
- (x) => head(x) !== "Sequence"
10331
+ (x) => !(head(x) === "Sequence" && nops(x) === 0)
9930
10332
  );
9931
10333
  if (nonEmptySuperscripts.length !== 0) {
9932
10334
  const superscriptExpression = nonEmptySuperscripts.length === 1 ? nonEmptySuperscripts[0] : ["List", ...nonEmptySuperscripts];
@@ -9995,75 +10397,6 @@ var ComputeEngine = (() => {
9995
10397
  }
9996
10398
  return result;
9997
10399
  }
9998
- /**
9999
- * Apply an invisible operator between two expressions.
10000
- *
10001
- * If the `lhs` is an literal integer and the `rhs` is a literal rational
10002
- * -> 'invisible plus'
10003
- *
10004
- * That is '2 3/4' -> ['Add', 2, ['Rational', 3, 4]]
10005
- *
10006
- * If `lhs` is a number and `rhs` is a number but not a literal -> 'invisible multiply'.
10007
- * - 2x
10008
- * - 2(x+1)
10009
- * - x(x+1)
10010
- * - f(x)g(y)
10011
- * - 2 sin(x)
10012
- * - 2 f(x)
10013
- * - x f(x)
10014
- * - (x-1)(x+1)
10015
- * - (x+1)2 -> no
10016
- * - x2 -> no
10017
- * => lhs is a number, rhs is a number, but not a literal
10018
- */
10019
- applyInvisibleOperator(until, lhs) {
10020
- if (lhs === null || this.options.applyInvisibleOperator === null || head(lhs) === "Error" || symbol(lhs) === "Nothing" || isEmptySequence(lhs) || this.atTerminator(until))
10021
- return null;
10022
- if (this.peekDefinitions("operator").length > 0)
10023
- return null;
10024
- if (this.isFunctionHead(lhs)) {
10025
- const args = this.parseArguments("enclosure", { ...until, minPrec: 0 });
10026
- if (args === null)
10027
- return null;
10028
- return [lhs, ...args];
10029
- }
10030
- const start = this.index;
10031
- const rhs = this.parseExpression({ ...until, minPrec: 390 });
10032
- if (rhs === null || symbol(rhs) === "Nothing" || isEmptySequence(rhs)) {
10033
- this.index = start;
10034
- return null;
10035
- }
10036
- if (head(rhs) === "Error")
10037
- return applyAssociativeOperator("Sequence", lhs, rhs);
10038
- if (typeof this.options.applyInvisibleOperator === "function")
10039
- return this.options.applyInvisibleOperator(this, lhs, rhs);
10040
- if (this.isFunctionHead(lhs)) {
10041
- const seq = getSequence(rhs);
10042
- return seq ? [lhs, ...seq] : lhs;
10043
- }
10044
- const lhsNumber = machineValue(lhs);
10045
- if (lhsNumber !== null && Number.isInteger(lhsNumber)) {
10046
- const rhsHead = head(rhs);
10047
- if (rhsHead === "Divide" || rhsHead === "Rational") {
10048
- const [n, d] = [machineValue(op(rhs, 1)), machineValue(op(rhs, 2))];
10049
- if (n !== null && d !== null && n > 0 && n <= 1e3 && d > 1 && d <= 1e3 && Number.isInteger(n) && Number.isInteger(d))
10050
- return ["Add", lhs, rhs];
10051
- }
10052
- }
10053
- if (head(rhs) === "Delimiter") {
10054
- if (head(op(rhs, 1)) === "Sequence")
10055
- return [lhs, ...ops(op(rhs, 1)) ?? []];
10056
- if (!op(rhs, 1) || symbol(op(rhs, 1)) === "Nothing")
10057
- return applyAssociativeOperator(
10058
- "Sequence",
10059
- lhs,
10060
- this.error("expected-expression", start)
10061
- );
10062
- }
10063
- if (head(rhs) === "Sequence" || head(lhs) === "Sequence" || stringValue(lhs) !== null || stringValue(rhs) !== null || dictionary(lhs) !== null || dictionary(rhs) !== null)
10064
- return applyAssociativeOperator("Sequence", lhs, rhs);
10065
- return applyAssociativeOperator("Multiply", lhs, rhs);
10066
- }
10067
10400
  /**
10068
10401
  * This method can be invoked when we know we're in an error situation.
10069
10402
  *
@@ -10269,7 +10602,23 @@ var ComputeEngine = (() => {
10269
10602
  this.skipSpace();
10270
10603
  let result = this.parseInfixOperator(lhs, until);
10271
10604
  if (result === null) {
10272
- result = this.applyInvisibleOperator(until, lhs);
10605
+ if (this.peekDefinitions("operator").length === 0) {
10606
+ const rhs = this.parseExpression({
10607
+ ...until,
10608
+ minPrec: MULTIPLICATION_PRECEDENCE
10609
+ });
10610
+ if (rhs !== null) {
10611
+ if (head(lhs) === "InvisibleOperator") {
10612
+ if (head(rhs) === "InvisibleOperator")
10613
+ result = ["InvisibleOperator", ...ops(lhs), ...ops(rhs)];
10614
+ else
10615
+ result = ["InvisibleOperator", ...ops(lhs), rhs];
10616
+ } else if (head(rhs) === "InvisibleOperator") {
10617
+ result = ["InvisibleOperator", lhs, ...ops(rhs)];
10618
+ } else
10619
+ result = ["InvisibleOperator", lhs, rhs];
10620
+ }
10621
+ }
10273
10622
  }
10274
10623
  if (result !== null) {
10275
10624
  lhs = result;
@@ -10278,11 +10627,6 @@ var ComputeEngine = (() => {
10278
10627
  }
10279
10628
  }
10280
10629
  }
10281
- if (!lhs) {
10282
- lhs = this.parseSyntaxError();
10283
- while (!this.atTerminator(until))
10284
- this.nextToken();
10285
- }
10286
10630
  return this.decorate(lhs, start);
10287
10631
  }
10288
10632
  /**
@@ -10608,7 +10952,7 @@ var ComputeEngine = (() => {
10608
10952
  sansserif: (s) => `\\mathsf{${s}}`,
10609
10953
  monospace: (s) => `\\mathtt{${s}}`
10610
10954
  };
10611
- var Serializer2 = class {
10955
+ var Serializer4 = class {
10612
10956
  constructor(options, dictionary2, onError) {
10613
10957
  this.level = -1;
10614
10958
  this.options = options;
@@ -10690,10 +11034,24 @@ var ComputeEngine = (() => {
10690
11034
  return s;
10691
11035
  if (fence === void 0)
10692
11036
  fence = "()";
10693
- const openFence = fence?.[0] ?? ".";
10694
- const closeFence = fence?.[1] ?? ".";
11037
+ let openFence = fence?.[0] ?? ".";
11038
+ let closeFence = fence?.[1] ?? ".";
10695
11039
  if ((openFence === "." || closeFence === ".") && style === "paren")
10696
11040
  style = "leftright";
11041
+ if (openFence === '"')
11042
+ openFence = "``";
11043
+ else if (openFence === "|")
11044
+ openFence = "\\lvert";
11045
+ else
11046
+ openFence = DELIMITERS_SHORTHAND[openFence] ?? openFence;
11047
+ if (closeFence === '"')
11048
+ closeFence = "''";
11049
+ else if (closeFence === "|")
11050
+ closeFence = "\\rvert";
11051
+ else
11052
+ closeFence = DELIMITERS_SHORTHAND[closeFence] ?? closeFence;
11053
+ if (openFence === "." && closeFence === ".")
11054
+ return s;
10697
11055
  if (style === "leftright")
10698
11056
  return `\\left${openFence}${s}\\right${closeFence}}`;
10699
11057
  if (style === "big")
@@ -11086,7 +11444,7 @@ var ComputeEngine = (() => {
11086
11444
  get serializer() {
11087
11445
  if (this._serializer)
11088
11446
  return this._serializer;
11089
- this._serializer = new Serializer2(
11447
+ this._serializer = new Serializer4(
11090
11448
  this.options,
11091
11449
  this._dictionary,
11092
11450
  this.onError
@@ -13550,11 +13908,19 @@ var ComputeEngine = (() => {
13550
13908
  return result;
13551
13909
  }
13552
13910
  function flattenSequence(xs) {
13553
- if (xs.every((x) => x.head !== "Sequence"))
13911
+ if (xs.every((x) => x.head !== "Sequence" && x.head !== "Delimiter"))
13554
13912
  return xs;
13555
13913
  const ys = [];
13556
13914
  for (const x of xs) {
13557
- if (x.isValid && x.head === "Sequence") {
13915
+ if (!x.isValid)
13916
+ ys.push(x);
13917
+ else if (x.head === "Delimiter") {
13918
+ const seq = x.op1.ops ?? [];
13919
+ if (seq.length === 0)
13920
+ ys.push(x.engine.box(["Tupple"]));
13921
+ else
13922
+ ys.push(...flattenSequence(seq));
13923
+ } else if (x.head === "Sequence") {
13558
13924
  if (x.ops)
13559
13925
  ys.push(...x.ops);
13560
13926
  } else
@@ -13900,7 +14266,7 @@ var ComputeEngine = (() => {
13900
14266
  LogicOperators: [
13901
14267
  "FunctionOf",
13902
14268
  "Booleans",
13903
- ["OptArg", "Booleans"],
14269
+ ["VarArg", "Booleans"],
13904
14270
  "Booleans"
13905
14271
  ],
13906
14272
  Predicates: ["FunctionOf", "Anything", ["VarArg", "Anything"], "Booleans"],
@@ -14220,7 +14586,7 @@ var ComputeEngine = (() => {
14220
14586
  }
14221
14587
  function checkNumericArgs(ce, ops2, options) {
14222
14588
  let count = typeof options === "number" ? options : options?.count;
14223
- const flatten = typeof options === "number" ? true : options?.flatten ?? true;
14589
+ const flatten = typeof options === "number" || (options?.flatten ?? true);
14224
14590
  ops2 = canonical(ops2);
14225
14591
  if (flatten)
14226
14592
  ops2 = flattenSequence(ops2);
@@ -14281,7 +14647,7 @@ var ComputeEngine = (() => {
14281
14647
  x.infer(ce.Numbers);
14282
14648
  return xs;
14283
14649
  }
14284
- function checkArg(ce, arg, dom) {
14650
+ function checkDomain(ce, arg, dom) {
14285
14651
  if (arg === void 0 || arg === null)
14286
14652
  return ce.error("missing");
14287
14653
  if (dom === void 0)
@@ -14295,12 +14661,22 @@ var ComputeEngine = (() => {
14295
14661
  return arg;
14296
14662
  return ce.domainError(dom, arg.domain, arg);
14297
14663
  }
14298
- function checkArgs(ce, args, doms) {
14664
+ function checkPure(ce, arg) {
14665
+ if (arg === void 0 || arg === null)
14666
+ return ce.error("missing");
14667
+ arg = arg.canonical;
14668
+ if (!arg.isValid)
14669
+ return arg;
14670
+ if (arg.isPure)
14671
+ return arg;
14672
+ return ce.error("expected-pure-expression", arg);
14673
+ }
14674
+ function checkDomains(ce, args, doms) {
14299
14675
  if (args.length === doms.length && args.every((x, i) => !x.domain || x.domain.isCompatible(doms[i])))
14300
14676
  return args;
14301
14677
  const xs = [];
14302
14678
  for (let i = 0; i <= doms.length - 1; i++)
14303
- xs.push(checkArg(ce, args[i], doms[i]));
14679
+ xs.push(checkDomain(ce, args[i], doms[i]));
14304
14680
  for (let i = doms.length; i <= args.length - 1; i++)
14305
14681
  xs.push(ce.error("unexpected-argument", args[i]));
14306
14682
  return xs;
@@ -14476,9 +14852,9 @@ var ComputeEngine = (() => {
14476
14852
  } else
14477
14853
  index = ce.domainError("Symbols", index.domain, index);
14478
14854
  if (lower && lower.isFinite)
14479
- lower = checkArg(ce, lower, "Integers");
14855
+ lower = checkDomain(ce, lower, "Integers");
14480
14856
  if (upper && upper.isFinite)
14481
- upper = checkArg(ce, upper, "Integers");
14857
+ upper = checkDomain(ce, upper, "Integers");
14482
14858
  if (lower && upper)
14483
14859
  return ce.tuple([index, lower, upper]);
14484
14860
  if (upper)
@@ -14567,7 +14943,11 @@ var ComputeEngine = (() => {
14567
14943
  Limit: (args, compile2) => `_SYS.limit(${compile2(args[0])}, ${compile2(args[1])})`,
14568
14944
  Ln: "Math.log",
14569
14945
  List: (args, compile2) => `[${args.map((x) => compile2(x)).join(", ")}]`,
14570
- Log: "Math.log10",
14946
+ Log: (args, compile2) => {
14947
+ if (args.length === 1)
14948
+ return `Math.log(${compile2(args[0])})`;
14949
+ return `(Math.log(${compile2(args[0])}) / Math.log(${compile2(args[1])}))`;
14950
+ },
14571
14951
  LogGamma: "_SYS.lngamma",
14572
14952
  Lb: "Math.log2",
14573
14953
  Max: "Math.max",
@@ -14803,6 +15183,12 @@ var ComputeEngine = (() => {
14803
15183
  return compileLoop(h, args, target);
14804
15184
  if (args.every((x) => !isCollection(x))) {
14805
15185
  const op3 = target.operators?.(h);
15186
+ if ((h === "NotEqual" || h === "Equal" || h === "Less" || h === "Greater" || h === "LessEqual" || h === "GreaterEqual") && args.length > 2 && op3) {
15187
+ const result = [];
15188
+ for (let i = 0; i < args.length - 1; i++)
15189
+ result.push(compileExpr(h, [args[i], args[i + 1]], op3[1], target));
15190
+ return `(${result.join(") && (")})`;
15191
+ }
14806
15192
  if (op3 !== void 0) {
14807
15193
  if (args === null)
14808
15194
  return "";
@@ -14817,7 +15203,7 @@ var ComputeEngine = (() => {
14817
15203
  }
14818
15204
  if (h === "Function") {
14819
15205
  const params = args.slice(1).map((x) => x.symbol);
14820
- return `((${params.join(", ")}) => ${compile(args[0], {
15206
+ return `((${params.join(", ")}) => ${compile(args[0].canonical, {
14821
15207
  ...target,
14822
15208
  var: (id) => params.includes(id) ? id : target.var(id)
14823
15209
  })})`;
@@ -19896,6 +20282,12 @@ var ComputeEngine = (() => {
19896
20282
  complexity: 9e3,
19897
20283
  signature: {
19898
20284
  domain: ["FunctionOf", "Numbers", "Numbers"],
20285
+ canonical: (ce, args) => {
20286
+ const base = args[0];
20287
+ if (base instanceof BoxedNumber && base.isNegative)
20288
+ return ce.neg(ce._fn("Factorial", [ce.neg(base)]));
20289
+ return ce._fn("Factorial", [base]);
20290
+ },
19899
20291
  evaluate: (ce, ops2) => {
19900
20292
  const n = asSmallInteger(ops2[0]);
19901
20293
  if (n !== null && n >= 0) {
@@ -19994,7 +20386,7 @@ var ComputeEngine = (() => {
19994
20386
  domain: ["FunctionOf", "Numbers", ["OptArg", "Numbers"], "Numbers"],
19995
20387
  canonical: (ce, ops2) => {
19996
20388
  if (ops2.length === 1)
19997
- return ce._fn("Log", [checkArg(ce, ops2[0], "Numbers")]);
20389
+ return ce._fn("Log", [checkDomain(ce, ops2[0], "Numbers")]);
19998
20390
  ops2 = checkNumericArgs(ce, ops2, 2);
19999
20391
  if (ops2.length !== 2)
20000
20392
  return ce._fn("Log", ops2);
@@ -20051,6 +20443,27 @@ var ComputeEngine = (() => {
20051
20443
  )
20052
20444
  }
20053
20445
  },
20446
+ Mod: {
20447
+ description: "Modulo",
20448
+ wikidata: "Q1799665",
20449
+ complexity: 2500,
20450
+ threadable: true,
20451
+ signature: {
20452
+ domain: ["FunctionOf", "Numbers", "Numbers", "Numbers"],
20453
+ evaluate: (ce, ops2) => {
20454
+ if (ops2.length !== 2)
20455
+ return void 0;
20456
+ const [lhs, rhs] = ops2;
20457
+ const nLhs = lhs.value;
20458
+ const nRhs = rhs.value;
20459
+ if (typeof nLhs !== "number")
20460
+ return void 0;
20461
+ if (typeof nRhs !== "number")
20462
+ return void 0;
20463
+ return ce.number((nLhs % nRhs + nRhs) % nRhs);
20464
+ }
20465
+ }
20466
+ },
20054
20467
  Multiply: {
20055
20468
  wikidata: "Q40276",
20056
20469
  associative: true,
@@ -20128,7 +20541,10 @@ var ComputeEngine = (() => {
20128
20541
  args = checkNumericArgs(ce, args, 2);
20129
20542
  if (args.length !== 2)
20130
20543
  return ce._fn("Power", args);
20131
- return ce.pow(args[0], args[1]);
20544
+ const [base, exp2] = args;
20545
+ if (base instanceof BoxedNumber && base.isNegative)
20546
+ return ce.neg(ce.pow(base, exp2));
20547
+ return ce.pow(base, exp2);
20132
20548
  },
20133
20549
  simplify: (ce, ops2) => processPower(ce, ops2[0], ops2[1], "simplify"),
20134
20550
  evaluate: (ce, ops2) => processPower(ce, ops2[0], ops2[1], "evaluate"),
@@ -20162,9 +20578,9 @@ var ComputeEngine = (() => {
20162
20578
  return ce._fn("Rational", [ce.error("missing")]);
20163
20579
  if (args.length === 1)
20164
20580
  return ce._fn("Rational", [
20165
- checkArg(ce, args[0], "ExtendedRealNumbers")
20581
+ checkDomain(ce, args[0], "ExtendedRealNumbers")
20166
20582
  ]);
20167
- args = checkArgs(ce, args, ["Integers", "Integers"]);
20583
+ args = checkDomains(ce, args, ["Integers", "Integers"]);
20168
20584
  if (args.length !== 2 || !args[0].isValid || !args[1].isValid)
20169
20585
  return ce._fn("Rational", args);
20170
20586
  return ce.div(args[0], args[1]);
@@ -20325,7 +20741,7 @@ var ComputeEngine = (() => {
20325
20741
  domain: ["FunctionOf", "Numbers", ["OptArg", "Numbers"], "Numbers"],
20326
20742
  canonical: (ce, args) => {
20327
20743
  if (args.length === 1) {
20328
- const x = checkArg(ce, args[0], "Numbers");
20744
+ const x = checkDomain(ce, args[0], "Numbers");
20329
20745
  if (x.isValid)
20330
20746
  return ce.neg(x);
20331
20747
  }
@@ -21376,7 +21792,6 @@ var ComputeEngine = (() => {
21376
21792
  "Numbers"
21377
21793
  ],
21378
21794
  canonical: (ce, ops2) => {
21379
- const body = ops2[0] ?? ce.error("missing");
21380
21795
  let range = ops2[1];
21381
21796
  let index = null;
21382
21797
  let lower = null;
@@ -21396,9 +21811,9 @@ var ComputeEngine = (() => {
21396
21811
  if (!index.symbol)
21397
21812
  index = ce.domainError("Symbols", index.domain, index);
21398
21813
  if (lower)
21399
- lower = checkArg(ce, lower, ce.Numbers);
21814
+ lower = checkDomain(ce, lower, ce.Numbers);
21400
21815
  if (upper)
21401
- upper = checkArg(ce, upper, ce.Numbers);
21816
+ upper = checkDomain(ce, upper, ce.Numbers);
21402
21817
  if (lower && upper)
21403
21818
  range = ce.tuple([index, lower, upper]);
21404
21819
  else if (upper)
@@ -21407,7 +21822,11 @@ var ComputeEngine = (() => {
21407
21822
  range = ce.tuple([index, lower]);
21408
21823
  else
21409
21824
  range = index;
21410
- return ce._fn("Integrate", [body.canonical, range]);
21825
+ let body = ops2[0] ?? ce.error("missing");
21826
+ body = body.canonical;
21827
+ if (body.head === "Delimiter" && body.op1.head === "Sequence")
21828
+ body = body.op1.op1;
21829
+ return ce._fn("Integrate", [body, range]);
21411
21830
  }
21412
21831
  }
21413
21832
  },
@@ -21440,15 +21859,12 @@ var ComputeEngine = (() => {
21440
21859
  //
21441
21860
  // Data Structures
21442
21861
  //
21443
- Sequence: {
21444
- signature: {
21445
- domain: "Functions"
21446
- }
21447
- },
21448
21862
  List: {
21449
21863
  complexity: 8200,
21864
+ hold: "all",
21450
21865
  signature: {
21451
- domain: ["FunctionOf", ["VarArg", "Anything"], "Lists"]
21866
+ domain: ["FunctionOf", ["VarArg", "Anything"], "Lists"],
21867
+ canonical: canonicalList
21452
21868
  },
21453
21869
  size: (expr) => expr.nops,
21454
21870
  iterator: (expr, start, count) => {
@@ -21603,7 +22019,7 @@ var ComputeEngine = (() => {
21603
22019
  signature: {
21604
22020
  domain: ["FunctionOf", "Strings", "Anything", "Tuples"],
21605
22021
  canonical: (ce, args) => {
21606
- const [key, value] = checkArgs(ce, args, [ce.Strings, "Values"]);
22022
+ const [key, value] = checkDomains(ce, args, [ce.Strings, "Values"]);
21607
22023
  if (!key.isValid || !value.isValid)
21608
22024
  return ce._fn("KeyValuePair", [key, value]);
21609
22025
  return ce.tuple([key, value]);
@@ -22189,6 +22605,17 @@ var ComputeEngine = (() => {
22189
22605
  }
22190
22606
  return result;
22191
22607
  }
22608
+ function canonicalList(ce, ops2) {
22609
+ ops2 = ops2.map((op3) => {
22610
+ if (op3.head === "Delimiter") {
22611
+ if (op3.op1.head === "Sequence")
22612
+ return ce._fn("List", canonical(op3.op1.ops));
22613
+ return ce._fn("List", [op3.op1?.canonical ?? ce.Nothing]);
22614
+ }
22615
+ return op3.canonical;
22616
+ });
22617
+ return ce._fn("List", ops2);
22618
+ }
22192
22619
 
22193
22620
  // src/compute-engine/library/control-structures.ts
22194
22621
  var CONTROL_STRUCTURES_LIBRARY = [
@@ -22624,19 +23051,160 @@ var ComputeEngine = (() => {
22624
23051
  // Inert functions
22625
23052
  //
22626
23053
  {
23054
+ /**
23055
+ * ## THEORY OF OPERATIONS: SEQUENCES
23056
+ *
23057
+ * There are two similar functions used to represent sequences of
23058
+ * expressions:
23059
+ *
23060
+ * - `InvisibleOperator` represent a sequence of expressions
23061
+ * that are syntactically juxtaposed without any separator or
23062
+ * operators combining them. For example, `2x` is represented as
23063
+ * `["InvisibleOperator", 2, "x"]`. `InvisibleOperator` gets
23064
+ * transformed into `Multiply` (or some other semantic operation)
23065
+ * during canonicalization.
23066
+ *
23067
+ * - `Sequence` is used to represent a sequence of expressions
23068
+ * at a semantic level. It is a collection, but it is handled
23069
+ * specially when canonicalizing expressions, for example it
23070
+ * is automatically flattened and hoisted to the top level of the
23071
+ * argument list.
23072
+ * For example:
23073
+ * `["Add", "a", ["Sequence", "b", "c"]]` is canonicalized
23074
+ * to `["Add", "a", "b", "c"]`.
23075
+ *
23076
+ * The empty `Sequence` expression (i.e. `["Sequence"]`) is ignored
23077
+ * but it can be used to represent an "empty" expression.
23078
+ *
23079
+ * - `Delimiter` is used to represent a group of expressions
23080
+ * with an open and close delimiter and separator. They capture the
23081
+ * input syntax, and can get transformed into other expressions
23082
+ * during boxing and canonicalization.
23083
+ * The first argument is a function expression, such as `List`
23084
+ * or `Sequence`. The arguments of that expression are represented
23085
+ * with a separator between them and delimiters around the whole
23086
+ * group.
23087
+ * The second argument specify the separator and delimiters. If not
23088
+ * specified, the default is the string `"(,)"`
23089
+ *
23090
+ * Examples:
23091
+ * - `f(x)` ->
23092
+ * `["InvisibleOperator",
23093
+ * "f",
23094
+ * ["Delimiter", ["Sequence", "x"], "'(,)'"]
23095
+ * ]`
23096
+ *
23097
+ * - `1, 2; 3, 4` ->
23098
+ * `["Delimiter",
23099
+ * ["Sequence",
23100
+ * ["Delimiter", ["Sequence", 1, 2], "','"],
23101
+ * ["Delimiter", ["Sequence", 3, 4], "','"],
23102
+ * ],
23103
+ * "';'"
23104
+ * ]`
23105
+ *
23106
+ * - `2x` -> `["InvisibleOperator", 2, "x"]`
23107
+ *
23108
+ * - `2+` -> `["InvisibleOperator", 2, ["Error", "'unexpected-operator'", "+"]]`
23109
+ *
23110
+ *
23111
+ *
23112
+ *
23113
+ */
23114
+ InvisibleOperator: {
23115
+ complexity: 9e3,
23116
+ hold: "all",
23117
+ signature: {
23118
+ restParam: "Anything",
23119
+ result: (ce, args) => {
23120
+ if (args.length === 0)
23121
+ return ce.domain("NothingDomain");
23122
+ if (args.length === 1)
23123
+ return args[0].domain;
23124
+ return ce.Anything;
23125
+ },
23126
+ canonical: canonicalInvisibleOperator
23127
+ }
23128
+ },
23129
+ /** See above for a theory of operations */
23130
+ Sequence: {
23131
+ hold: "all",
23132
+ signature: {
23133
+ restParam: "Anything",
23134
+ result: (ce, args) => {
23135
+ if (args.length === 0)
23136
+ return ce.domain("NothingDomain");
23137
+ if (args.length === 1)
23138
+ return args[0].domain;
23139
+ return ce.Anything;
23140
+ },
23141
+ canonical: (ce, args) => {
23142
+ const xs = canonical(flattenSequence(args));
23143
+ if (xs.length === 0)
23144
+ return ce._fn("Sequence", []);
23145
+ if (xs.length === 1)
23146
+ return xs[0];
23147
+ return ce._fn("Sequence", xs);
23148
+ }
23149
+ }
23150
+ },
23151
+ /** See above for a theory of operations */
22627
23152
  Delimiter: {
22628
- // Use to represent groups of expressions. Named after https://en.wikipedia.org/wiki/Delimiter
23153
+ // Use to represent groups of expressions.
23154
+ // Named after https://en.wikipedia.org/wiki/Delimiter
22629
23155
  complexity: 9e3,
22630
- hold: "first",
23156
+ hold: "all",
22631
23157
  signature: {
22632
- domain: [
22633
- "FunctionOf",
22634
- "Anything",
22635
- ["OptArg", "Strings", "Strings"],
22636
- "Anything"
22637
- ],
23158
+ params: ["Anything"],
23159
+ optParams: ["Strings"],
22638
23160
  result: (_ce, args) => args[0].domain,
22639
- canonical: (ce, args) => args[0]?.canonical ?? ce.box(["Sequence"])
23161
+ // During canonicalization, Delimiters get replaced by their first
23162
+ // argument, which is a function expression (e.g. `List` or `Sequence`)
23163
+ canonical: (ce, args) => {
23164
+ if (args.length === 0)
23165
+ return ce._fn("Tuple", []);
23166
+ let body = args[0];
23167
+ console.assert(body.ops !== null);
23168
+ if (body.head === "Sequence")
23169
+ body = ce._fn("Sequence", ce.canonical(body.ops));
23170
+ args = [body, ...args.slice(1)];
23171
+ if (args.length === 1)
23172
+ return ce._fn("Delimiter", args);
23173
+ if (args.length > 2)
23174
+ return ce._fn("Delimiter", checkArity(ce, args, 2));
23175
+ if ((args[1].string?.length ?? 0) > 3) {
23176
+ return ce._fn("Delimiter", [
23177
+ args[0],
23178
+ ce.error("invalid-delimiter", args[1])
23179
+ ]);
23180
+ }
23181
+ return ce._fn("Delimiter", [
23182
+ args[0],
23183
+ checkDomain(ce, args[1], "Strings")
23184
+ ]);
23185
+ },
23186
+ evaluate: (ce, ops2) => {
23187
+ if (ops2.length === 0)
23188
+ return ce.Nothing;
23189
+ const op12 = ops2[0];
23190
+ if (op12.head === "Sequence" || op12.head === "Delimiter")
23191
+ ops2 = flattenSequence(ops2[0].ops);
23192
+ return ce._fn(
23193
+ "Tuple",
23194
+ ops2.map((x) => x.evaluate())
23195
+ );
23196
+ },
23197
+ N: (ce, ops2) => {
23198
+ if (ops2.length === 0)
23199
+ return ce.Nothing;
23200
+ const op12 = ops2[0];
23201
+ if (op12.head === "Sequence" || op12.head === "Delimiter")
23202
+ ops2 = flattenSequence(ops2[0].ops);
23203
+ return ce._fn(
23204
+ "Tuple",
23205
+ ops2.map((x) => x.N())
23206
+ );
23207
+ }
22640
23208
  }
22641
23209
  },
22642
23210
  Error: {
@@ -22661,7 +23229,7 @@ var ComputeEngine = (() => {
22661
23229
  signature: {
22662
23230
  domain: ["FunctionOf", "Strings", ["VarArg", "Anything"], "Anything"],
22663
23231
  canonical: (ce, args) => {
22664
- const code = checkArg(ce, args[0], ce.Strings).string;
23232
+ const code = checkDomain(ce, args[0], ce.Strings).string;
22665
23233
  if (code === "incompatible-domain") {
22666
23234
  return ce._fn("ErrorCode", [ce.string(code), args[1], args[2]]);
22667
23235
  }
@@ -22681,11 +23249,11 @@ var ComputeEngine = (() => {
22681
23249
  return ce.domain("Strings");
22682
23250
  if (op12.head === "Numbers")
22683
23251
  return ce.domain("Numbers");
22684
- return void 0;
23252
+ return op12.domain;
22685
23253
  },
22686
23254
  // By definition, for arguments of the canonical expression of
22687
23255
  // `Hold` are not canonicalized.
22688
- canonical: (ce, args) => args.length !== 1 ? null : ce._fn("Hold", args),
23256
+ canonical: (ce, args) => args.length !== 1 ? null : ce.hold(args[0]),
22689
23257
  evaluate: (ce, ops2) => ops2[0]
22690
23258
  }
22691
23259
  },
@@ -22780,18 +23348,17 @@ var ComputeEngine = (() => {
22780
23348
  },
22781
23349
  Assign: {
22782
23350
  hold: "all",
23351
+ pure: false,
22783
23352
  signature: {
22784
- domain: ["FunctionOf", "Symbols", "Anything", "Anything"],
23353
+ domain: ["FunctionOf", "Anything", "Anything", "Anything"],
22785
23354
  canonical: (ce, args) => {
22786
23355
  if (args.length !== 2)
22787
23356
  return null;
22788
23357
  const op12 = args[0];
22789
- const op22 = args[1];
22790
23358
  if (!op12.symbol)
22791
23359
  return null;
22792
- if (op22.symbol)
22793
- return ce._fn("Assign", args);
22794
- return ce._fn("Assign", [op12, ce._fn("Hold", [op22])]);
23360
+ const op22 = args[1];
23361
+ return ce._fn("Assign", [op12, op22]);
22795
23362
  },
22796
23363
  evaluate: (ce, ops2) => {
22797
23364
  const op12 = ops2[0];
@@ -22806,6 +23373,7 @@ var ComputeEngine = (() => {
22806
23373
  },
22807
23374
  Assume: {
22808
23375
  hold: "all",
23376
+ pure: false,
22809
23377
  signature: {
22810
23378
  domain: ["FunctionOf", "Anything", "Anything"],
22811
23379
  evaluate: (ce, ops2) => ce.string(ce.assume(ops2[0]))
@@ -22813,6 +23381,7 @@ var ComputeEngine = (() => {
22813
23381
  },
22814
23382
  Declare: {
22815
23383
  hold: "all",
23384
+ pure: false,
22816
23385
  signature: {
22817
23386
  domain: ["FunctionOf", "Symbols", "Anything"],
22818
23387
  canonical: (ce, args) => {
@@ -22966,17 +23535,15 @@ var ComputeEngine = (() => {
22966
23535
  const op22 = args[1];
22967
23536
  if (op12.string) {
22968
23537
  const base = asSmallInteger(op22);
22969
- if (base !== null) {
22970
- if (base > 1 && base <= 36) {
22971
- const [value, rest] = fromDigits(op12.string, base);
22972
- if (rest) {
22973
- return ce.error(
22974
- ["unexpected-digit", { str: rest[0] }],
22975
- ["LatexString", ce.string(op12.string)]
22976
- );
22977
- }
22978
- return ce.number(value);
23538
+ if (base !== null && base > 1 && base <= 36) {
23539
+ const [value, rest] = fromDigits(op12.string, base);
23540
+ if (rest) {
23541
+ return ce.error(
23542
+ ["unexpected-digit", { str: rest[0] }],
23543
+ ["LatexString", ce.string(op12.string)]
23544
+ );
22979
23545
  }
23546
+ return ce.number(value);
22980
23547
  }
22981
23548
  }
22982
23549
  if (op12.symbol) {
@@ -23094,9 +23661,74 @@ var ComputeEngine = (() => {
23094
23661
  }
23095
23662
  }
23096
23663
  ];
23664
+ function canonicalInvisibleOperator(ce, ops2) {
23665
+ if (ops2.length === 0)
23666
+ return null;
23667
+ const lhs = ops2[0];
23668
+ if (ops2.length === 1)
23669
+ return canonicalInvisibleOperator(ce, [lhs.canonical]);
23670
+ if (ops2.length === 2) {
23671
+ const lhsNumber = asFloat(lhs);
23672
+ if (lhsNumber !== null && Number.isInteger(lhsNumber)) {
23673
+ const rhs2 = ops2[1];
23674
+ if (rhs2.head === "Divide" || rhs2.head === "Rational") {
23675
+ const [n, d] = [asFloat(rhs2.op1), asFloat(rhs2.op2)];
23676
+ if (n !== null && d !== null && n > 0 && n <= 1e3 && d > 1 && d <= 1e3 && Number.isInteger(n) && Number.isInteger(d))
23677
+ return ce.add([lhs.canonical, rhs2.canonical]);
23678
+ }
23679
+ }
23680
+ let rhs = ops2[1];
23681
+ if (lhs.symbol && rhs.head === "Delimiter" && !ce.lookupSymbol(lhs.symbol)) {
23682
+ if (!ce.lookupFunction(lhs.symbol)) {
23683
+ ce.declare(lhs.symbol, "Functions");
23684
+ }
23685
+ if (rhs.nops === 0)
23686
+ return ce.box([lhs.symbol]);
23687
+ rhs = rhs.op1;
23688
+ if (rhs.head === "Sequence")
23689
+ return ce.box([lhs.symbol, ...ce.canonical(rhs.ops)]);
23690
+ return ce.box([lhs.symbol, rhs.canonical]);
23691
+ }
23692
+ }
23693
+ ops2 = canonical(flattenSequence(ops2));
23694
+ if (ops2.every(
23695
+ (x) => x.isValid && (!x.domain || x.domain.isNumeric || isIndexableCollection(x) && !x.string)
23696
+ ))
23697
+ return ce._fn("Multiply", flattenOps(ops2, "Multiply"));
23698
+ return ce._fn("Tuple", ops2);
23699
+ }
23097
23700
 
23098
23701
  // src/compute-engine/library/linear-algebra.ts
23099
- var LINEAR_ALGEBRA_LIBRARY = [];
23702
+ var LINEAR_ALGEBRA_LIBRARY = [
23703
+ {
23704
+ Matrix: {
23705
+ complexity: 9e3,
23706
+ hold: "all",
23707
+ signature: {
23708
+ params: ["Lists"],
23709
+ optParams: ["Strings", "Strings"],
23710
+ result: "Lists",
23711
+ canonical: canonicalMatrix,
23712
+ evaluate: (_ce, ops2) => ops2[0].evaluate(),
23713
+ N: (_ce, ops2) => ops2[0].N()
23714
+ }
23715
+ }
23716
+ }
23717
+ ];
23718
+ function canonicalMatrix(ce, ops2) {
23719
+ if (ops2.length === 0)
23720
+ return ce._fn("Matrix", []);
23721
+ const body = ops2[0].canonical;
23722
+ const delims = ops2[1]?.canonical;
23723
+ const columns = ops2[2]?.canonical;
23724
+ if (ops2.length > 3)
23725
+ return ce._fn("Matrix", checkArity(ce, ops2, 3));
23726
+ if (columns)
23727
+ return ce._fn("Matrix", [body, delims, columns]);
23728
+ if (delims)
23729
+ return ce._fn("Matrix", [body, delims]);
23730
+ return ce._fn("Matrix", [body]);
23731
+ }
23100
23732
 
23101
23733
  // src/compute-engine/library/logic.ts
23102
23734
  var LOGIC_LIBRARY = {
@@ -23161,6 +23793,15 @@ var ComputeEngine = (() => {
23161
23793
  complexity: 10200,
23162
23794
  signature: {
23163
23795
  domain: "LogicOperators",
23796
+ canonical: (ce, args) => {
23797
+ const lhs = args[0].symbol;
23798
+ const rhs = args[1].symbol;
23799
+ if (lhs === "True" && rhs === "True" || lhs === "False" && rhs === "False")
23800
+ return ce.True;
23801
+ if (lhs === "True" && rhs === "False" || lhs === "False" && rhs === "True")
23802
+ return ce.False;
23803
+ return ce._fn("Equivalent", args);
23804
+ },
23164
23805
  simplify: processEquivalent,
23165
23806
  evaluate: processEquivalent
23166
23807
  }
@@ -23230,7 +23871,7 @@ var ComputeEngine = (() => {
23230
23871
  return ce._fn("Or", ops2);
23231
23872
  }
23232
23873
  function processNot(ce, args) {
23233
- const op12 = args[0].symbol;
23874
+ const op12 = args[0]?.symbol;
23234
23875
  if (op12 === "True")
23235
23876
  return ce.False;
23236
23877
  if (op12 === "False")
@@ -23294,17 +23935,42 @@ var ComputeEngine = (() => {
23294
23935
 
23295
23936
  // src/compute-engine/library/relational-operator.ts
23296
23937
  var RELOP_LIBRARY = {
23938
+ Congruent: {
23939
+ commutative: false,
23940
+ complexity: 11e3,
23941
+ numeric: true,
23942
+ signature: {
23943
+ simplify: (ce, ops2) => {
23944
+ if (ops2.length < 3)
23945
+ return void 0;
23946
+ return ce._fn("Equal", [
23947
+ ce.box(["Mod", ops2[0], ops2[2]]).simplify(),
23948
+ ce.box(["Mod", ops2[1], ops2[2]]).simplify()
23949
+ ]).simplify();
23950
+ },
23951
+ evaluate: (ce, ops2) => {
23952
+ if (ops2.length < 3)
23953
+ return void 0;
23954
+ const [lhs, rhs, modulo] = ops2;
23955
+ const nLhs = lhs.value;
23956
+ const nRhs = rhs.value;
23957
+ const nModulo = modulo.value;
23958
+ if (typeof nLhs !== "number")
23959
+ return void 0;
23960
+ if (typeof nRhs !== "number")
23961
+ return void 0;
23962
+ if (typeof nModulo !== "number")
23963
+ return void 0;
23964
+ return nLhs % nModulo === nRhs % nModulo ? ce.True : ce.False;
23965
+ }
23966
+ }
23967
+ },
23297
23968
  Equal: {
23298
23969
  commutative: true,
23299
23970
  complexity: 11e3,
23300
23971
  signature: {
23301
23972
  domain: "RelationalOperators",
23302
- canonical: (ce, ops2) => {
23303
- return ce._fn(
23304
- "Equal",
23305
- flattenOps(flattenSequence(canonical(ops2)), "Equal")
23306
- );
23307
- },
23973
+ canonical: (ce, args) => canonicalRelational(ce, "Equal", args),
23308
23974
  evaluate: (ce, ops2) => {
23309
23975
  if (ops2.length < 2)
23310
23976
  return ce.True;
@@ -23328,6 +23994,7 @@ var ComputeEngine = (() => {
23328
23994
  complexity: 11e3,
23329
23995
  signature: {
23330
23996
  domain: "RelationalOperators",
23997
+ canonical: (ce, args) => canonicalRelational(ce, "NotEqual", args),
23331
23998
  evaluate: (ce, ops2) => {
23332
23999
  if (ops2.length < 2)
23333
24000
  return ce.False;
@@ -23349,7 +24016,7 @@ var ComputeEngine = (() => {
23349
24016
  complexity: 11e3,
23350
24017
  signature: {
23351
24018
  domain: "RelationalOperators",
23352
- canonical: (ce, ops2) => ce._fn("Less", flattenOps(flattenSequence(canonical(ops2)), "Less")),
24019
+ canonical: (ce, ops2) => canonicalRelational(ce, "Less", ops2),
23353
24020
  evaluate: (ce, ops2) => {
23354
24021
  if (ops2.length < 2)
23355
24022
  return ce.True;
@@ -23376,14 +24043,14 @@ var ComputeEngine = (() => {
23376
24043
  complexity: 11e3,
23377
24044
  signature: {
23378
24045
  domain: "RelationalOperators",
23379
- canonical: (ce, args) => ce._fn("Not", [ce._fn("Less", args)])
24046
+ canonical: (ce, ops2) => ce._fn("Not", [canonicalRelational(ce, "Less", ops2)])
23380
24047
  }
23381
24048
  },
23382
24049
  Greater: {
23383
24050
  complexity: 11e3,
23384
24051
  signature: {
23385
24052
  domain: "RelationalOperators",
23386
- canonical: (ce, args) => ce._fn("Less", args.reverse()),
24053
+ canonical: (ce, ops2) => canonicalRelational(ce, "Less", ops2.reverse()),
23387
24054
  evaluate: (ce, ops2) => {
23388
24055
  if (ops2.length < 2)
23389
24056
  return ce.True;
@@ -23417,6 +24084,7 @@ var ComputeEngine = (() => {
23417
24084
  complexity: 11e3,
23418
24085
  signature: {
23419
24086
  domain: "RelationalOperators",
24087
+ canonical: (ce, ops2) => canonicalRelational(ce, "LessEqual", ops2),
23420
24088
  evaluate: (ce, ops2) => {
23421
24089
  if (ops2.length < 2)
23422
24090
  return ce.True;
@@ -23443,14 +24111,14 @@ var ComputeEngine = (() => {
23443
24111
  complexity: 11e3,
23444
24112
  signature: {
23445
24113
  domain: "RelationalOperators",
23446
- canonical: (ce, args) => ce._fn("Not", [ce._fn("LessEqual", args)])
24114
+ canonical: (ce, ops2) => ce._fn("Not", [canonicalRelational(ce, "LessEqual", ops2)])
23447
24115
  }
23448
24116
  },
23449
24117
  GreaterEqual: {
23450
24118
  complexity: 11e3,
23451
24119
  signature: {
23452
24120
  domain: "RelationalOperators",
23453
- canonical: (ce, args) => ce._fn("LessEqual", args.reverse()),
24121
+ canonical: (ce, args) => canonicalRelational(ce, "LessEqual", args.reverse()),
23454
24122
  evaluate: (ce, ops2) => {
23455
24123
  if (ops2.length < 2)
23456
24124
  return ce.True;
@@ -23477,94 +24145,136 @@ var ComputeEngine = (() => {
23477
24145
  complexity: 11e3,
23478
24146
  signature: {
23479
24147
  domain: "RelationalOperators",
23480
- canonical: (ce, args) => ce._fn("Not", [ce._fn("GreaterEqual", args)])
24148
+ canonical: (ce, args) => ce._fn("Not", [canonicalRelational(ce, "GreaterEqual", args)])
23481
24149
  }
23482
24150
  },
23483
24151
  TildeFullEqual: {
23484
24152
  description: "Indicate isomorphism, congruence and homotopic equivalence",
23485
- signature: { domain: "RelationalOperators" }
24153
+ signature: {
24154
+ domain: "RelationalOperators",
24155
+ canonical: (ce, args) => canonicalRelational(ce, "TildeFullEqual", args)
24156
+ }
23486
24157
  // @todo evaluate: (ce, ...args: BoxedExpression[]) => SemiBoxedExpression {}
23487
24158
  },
23488
24159
  NotTildeFullEqual: {
23489
24160
  complexity: 11100,
23490
24161
  signature: {
23491
24162
  domain: "RelationalOperators",
23492
- canonical: (ce, args) => ce._fn("Not", [ce._fn("TildeFullEqual", args)])
24163
+ canonical: (ce, args) => ce._fn("Not", [canonicalRelational(ce, "TildeFullEqual", args)])
23493
24164
  }
23494
24165
  },
23495
24166
  TildeEqual: {
23496
24167
  description: "Approximately or asymptotically equal",
23497
24168
  complexity: 11e3,
23498
- signature: { domain: "RelationalOperators" }
24169
+ signature: {
24170
+ domain: "RelationalOperators",
24171
+ canonical: (ce, args) => canonicalRelational(ce, "TildeEqual", args)
24172
+ }
23499
24173
  // @todo evaluate: (ce, ...args: BoxedExpression[]) => SemiBoxedExpression {}
23500
24174
  },
23501
24175
  NotTildeEqual: {
23502
24176
  complexity: 11100,
23503
24177
  signature: {
23504
24178
  domain: "RelationalOperators",
23505
- canonical: (ce, args) => ce._fn("Not", [ce._fn("TildeEqual", args)])
24179
+ canonical: (ce, args) => ce._fn("Not", [canonicalRelational(ce, "TildeEqual", args)])
23506
24180
  }
23507
24181
  },
23508
24182
  Approx: {
23509
24183
  complexity: 11100,
23510
- signature: { domain: "RelationalOperators" }
24184
+ signature: {
24185
+ domain: "RelationalOperators",
24186
+ canonical: (ce, args) => canonicalRelational(ce, "Approx", args)
24187
+ }
23511
24188
  // @todo evaluate: (ce, ...args: BoxedExpression[]) => SemiBoxedExpression {}
23512
24189
  },
23513
24190
  NotApprox: {
23514
24191
  complexity: 11100,
23515
24192
  signature: {
23516
24193
  domain: "RelationalOperators",
23517
- canonical: (ce, args) => ce._fn("Not", [ce._fn("Approx", args)])
24194
+ canonical: (ce, args) => ce._fn("Not", [canonicalRelational(ce, "Approx", args)])
23518
24195
  }
23519
24196
  },
23520
24197
  ApproxEqual: {
23521
24198
  complexity: 11100,
23522
- signature: { domain: "RelationalOperators" }
24199
+ signature: {
24200
+ domain: "RelationalOperators",
24201
+ canonical: (ce, args) => canonicalRelational(ce, "ApproxEqual", args)
24202
+ }
23523
24203
  // @todo evaluate: (ce, ...args: BoxedExpression[]) => SemiBoxedExpression {}
23524
24204
  },
23525
24205
  NotApproxEqual: {
23526
24206
  complexity: 11100,
23527
24207
  signature: {
23528
24208
  domain: "RelationalOperators",
23529
- canonical: (ce, args) => ce._fn("Not", [ce._fn("ApproxEqual", args)])
24209
+ canonical: (ce, args) => ce._fn("Not", [canonicalRelational(ce, "ApproxEqual", args)])
23530
24210
  }
23531
24211
  },
23532
24212
  ApproxNotEqual: {
23533
24213
  complexity: 11100,
23534
- signature: { domain: "RelationalOperators" }
24214
+ signature: {
24215
+ domain: "RelationalOperators",
24216
+ canonical: (ce, args) => canonicalRelational(ce, "ApproxNotEqual", args)
24217
+ }
23535
24218
  // @todo evaluate: (ce, ...args: BoxedExpression[]) => SemiBoxedExpression {}
23536
24219
  },
23537
24220
  NotApproxNotEqual: {
23538
24221
  complexity: 11100,
23539
24222
  signature: {
23540
24223
  domain: "RelationalOperators",
23541
- canonical: (ce, args) => ce._fn("Not", [ce._fn("ApproxNotEqual", args)])
24224
+ canonical: (ce, args) => ce._fn("Not", [canonicalRelational(ce, "ApproxNotEqual", args)])
23542
24225
  }
23543
24226
  },
23544
24227
  Precedes: {
23545
24228
  complexity: 11100,
23546
- signature: { domain: "RelationalOperators" }
24229
+ signature: {
24230
+ domain: "RelationalOperators",
24231
+ canonical: (ce, args) => canonicalRelational(ce, "Precedes", args)
24232
+ }
23547
24233
  // @todo evaluate: (ce, ...args: BoxedExpression[]) => SemiBoxedExpression {}
23548
24234
  },
23549
24235
  NotPrecedes: {
23550
24236
  complexity: 11100,
23551
24237
  signature: {
23552
24238
  domain: "RelationalOperators",
23553
- canonical: (ce, args) => ce._fn("Not", [ce._fn("Precedes", args)])
24239
+ canonical: (ce, args) => ce._fn("Not", [canonicalRelational(ce, "Precedes", args)])
23554
24240
  }
23555
24241
  },
23556
24242
  Succeeds: {
23557
- signature: { domain: "RelationalOperators" }
24243
+ signature: {
24244
+ domain: "RelationalOperators",
24245
+ canonical: (ce, args) => canonicalRelational(ce, "Succeeds", args)
24246
+ }
23558
24247
  // @todo evaluate: (ce, ...args: BoxedExpression[]) => SemiBoxedExpression {}
23559
24248
  },
23560
24249
  NotSucceeds: {
23561
24250
  complexity: 11100,
23562
24251
  signature: {
23563
24252
  domain: "RelationalOperators",
23564
- canonical: (ce, args) => ce._fn("Not", [ce._fn("Succeeds", args)])
24253
+ canonical: (ce, args) => ce._fn("Not", [canonicalRelational(ce, "Succeeds", args)])
23565
24254
  }
23566
24255
  }
23567
24256
  };
24257
+ function canonicalRelational(ce, head2, ops2) {
24258
+ ops2 = flattenOps(flattenSequence(canonical(ops2)), head2);
24259
+ const nestedRelational = [];
24260
+ let newOps = [];
24261
+ for (const op3 of ops2) {
24262
+ if (isRelationalOperator(op3)) {
24263
+ nestedRelational.push(op3);
24264
+ newOps.push(op3.ops[op3.ops.length - 1]);
24265
+ } else
24266
+ newOps.push(op3);
24267
+ }
24268
+ newOps = newOps.map((op3) => checkPure(ce, op3));
24269
+ if (nestedRelational.length === 0)
24270
+ return ce._fn(head2, newOps);
24271
+ return ce._fn("And", [ce._fn(head2, newOps), ...nestedRelational]);
24272
+ }
24273
+ function isRelationalOperator(op3) {
24274
+ return typeof op3.head === "string" && /Equal|NotEqual|Less|NotLess|Greater|NotGreater|LessEqual|NotLessNotEqual|GreaterEqual|NotGreater|NotEqual|TildeFullEqual|NotTildeFullEqual|TildeEqual|NotTildeEqual|Approx|NotApprox|ApproxEqual|NotApproxEqual|ApproxNotEqual|NotApproxNotEqual|Precedes|NotPrecedes|Succeeds|NotSucceeds/.test(
24275
+ op3.head
24276
+ );
24277
+ }
23568
24278
 
23569
24279
  // src/compute-engine/library/sets.ts
23570
24280
  var SETS_LIBRARY = {
@@ -26362,14 +27072,7 @@ ${JSON.stringify(entry)}`
26362
27072
  return this._hash;
26363
27073
  }
26364
27074
  get isPure() {
26365
- const def = this._def ?? this.engine.lookupSymbol(this._id, this.wikidata);
26366
- if (!def)
26367
- return false;
26368
- if (def instanceof _BoxedSymbolDefinition)
26369
- return (def?.constant && def.value?.isPure) ?? false;
26370
- if (def instanceof _BoxedFunctionDefinition)
26371
- return def?.pure ?? false;
26372
- return false;
27075
+ return true;
26373
27076
  }
26374
27077
  get json() {
26375
27078
  const wikidata = this._scope ? this.wikidata : void 0;
@@ -26878,15 +27581,15 @@ ${JSON.stringify(entry)}`
26878
27581
  TranscendentalNumbers: null,
26879
27582
  PositiveNumbers: null,
26880
27583
  Functions: null,
26881
- // (Anything^n) -> Anything
27584
+ // (Anything*) -> Anything
26882
27585
  NumericFunctions: null,
26883
- // (Numbers^n) -> Numbers
27586
+ // (Numbers+) -> Numbers
26884
27587
  RealFunctions: null,
26885
- // (ExtendedRealNumbers^n) -> ExtendRealNumbers
27588
+ // (ExtendedRealNumbers+) -> ExtendRealNumbers
26886
27589
  LogicOperators: null,
26887
- // (Booleans, Booleans) -> Boolean
27590
+ // (Booleans+) -> Boolean
26888
27591
  Predicates: null
26889
- // (Anything^n) -> Booleans
27592
+ // (Anything+) -> Booleans
26890
27593
  };
26891
27594
  if (options !== void 0 && typeof options !== "object")
26892
27595
  throw Error("Unexpected argument");
@@ -27158,7 +27861,12 @@ ${JSON.stringify(entry)}`
27158
27861
  bignum(a) {
27159
27862
  if (typeof a === "bigint")
27160
27863
  return new this._bignum(a.toString());
27161
- return new this._bignum(a);
27864
+ try {
27865
+ return new this._bignum(a);
27866
+ } catch (e) {
27867
+ console.error(e);
27868
+ }
27869
+ return this._BIGNUM_NAN;
27162
27870
  }
27163
27871
  complex(a, b) {
27164
27872
  if (a instanceof Decimal)
@@ -27507,11 +28215,10 @@ ${JSON.stringify(entry)}`
27507
28215
  const scope = symDef.scope;
27508
28216
  scope?.ids?.delete(symDef.name);
27509
28217
  if (!args && !isFunctionValue(value)) {
27510
- if (value === void 0 || value === null) {
28218
+ if (value === void 0 || value === null)
27511
28219
  symDef.value = void 0;
27512
- return this;
27513
- }
27514
- symDef.value = this.box(value);
28220
+ else
28221
+ symDef.value = this.box(value);
27515
28222
  scope?.ids?.set(symDef.name, symDef);
27516
28223
  return this;
27517
28224
  }
@@ -28144,10 +28851,10 @@ ${JSON.stringify(entry)}`
28144
28851
  }
28145
28852
 
28146
28853
  // src/compute-engine.ts
28147
- var version = "0.19.1";
28854
+ var version = "0.20.1";
28148
28855
  globalThis[Symbol.for("io.cortexjs.compute-engine")] = {
28149
28856
  ComputeEngine: ComputeEngine.prototype.constructor,
28150
- version: "0.19.1"
28857
+ version: "0.20.1"
28151
28858
  };
28152
28859
  return __toCommonJS(compute_engine_exports);
28153
28860
  })();