@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
  var __create = Object.create;
3
3
  var __defProp = Object.defineProperty;
4
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -3950,6 +3950,13 @@ function nops(expr) {
3950
3950
  return Math.max(0, expr.fn.length - 1);
3951
3951
  return 0;
3952
3952
  }
3953
+ function unhold(expr) {
3954
+ if (expr === null || expr === void 0)
3955
+ return null;
3956
+ if (head(expr) === "Hold")
3957
+ return op(expr, 1);
3958
+ return expr;
3959
+ }
3953
3960
  function symbol(expr) {
3954
3961
  if (expr === null || expr === void 0)
3955
3962
  return null;
@@ -3964,14 +3971,6 @@ function symbol(expr) {
3964
3971
  return null;
3965
3972
  return s;
3966
3973
  }
3967
- function isListLike(expr) {
3968
- if (expr === null)
3969
- return false;
3970
- const h = head(expr);
3971
- if (!h || typeof h !== "string")
3972
- return false;
3973
- return /^(List|Sequence|Tuple|Single|Pair|Triple)$/.test(h);
3974
- }
3975
3974
  function keyValuePair(expr) {
3976
3975
  const h = head(expr);
3977
3976
  if (h === "KeyValuePair" || h === "Tuple" || h === "Pair") {
@@ -4131,21 +4130,21 @@ function getSequence(expr) {
4131
4130
  expr = op(expr, 1);
4132
4131
  if (expr === null)
4133
4132
  return [];
4134
- if (head(expr) !== "Sequence")
4133
+ h = head(expr);
4134
+ if (h !== "Sequence")
4135
4135
  return [expr];
4136
4136
  }
4137
- h = head(expr);
4138
4137
  if (h !== "Sequence")
4139
4138
  return null;
4140
4139
  return ops(expr) ?? [];
4141
4140
  }
4142
4141
  function isEmptySequence(expr) {
4143
- return expr !== null && head(expr) === "Sequence" && nops(expr) === 0;
4142
+ return head(expr) === "Sequence" && nops(expr) === 0;
4144
4143
  }
4145
4144
  function missingIfEmpty(expr) {
4146
- if (expr === null || isEmptySequence(expr))
4145
+ if (isEmptySequence(expr))
4147
4146
  return MISSING;
4148
- return expr;
4147
+ return expr ?? MISSING;
4149
4148
  }
4150
4149
  function countFunctionLeaves(xs) {
4151
4150
  if (xs[0] === "Square") {
@@ -4315,9 +4314,9 @@ function serializeAdd(serializer, expr) {
4315
4314
  if (val < 0) {
4316
4315
  result += serializer.serialize(arg);
4317
4316
  } else if (head(arg) === "Negate") {
4318
- result += serializer.wrap(arg, 275);
4317
+ result += serializer.wrap(arg, ADDITION_PRECEDENCE);
4319
4318
  } else {
4320
- const term = serializer.wrap(arg, 275);
4319
+ const term = serializer.wrap(arg, ADDITION_PRECEDENCE);
4321
4320
  if (term[0] === "-" || term[0] === "+")
4322
4321
  result += term;
4323
4322
  else
@@ -4325,10 +4324,10 @@ function serializeAdd(serializer, expr) {
4325
4324
  }
4326
4325
  }
4327
4326
  } else if (name === "Subtract") {
4328
- result = serializer.wrap(arg, 275);
4327
+ result = serializer.wrap(arg, ADDITION_PRECEDENCE);
4329
4328
  const arg2 = op(expr, 2);
4330
4329
  if (arg2 !== null) {
4331
- const term = serializer.wrap(arg2, 275);
4330
+ const term = serializer.wrap(arg2, ADDITION_PRECEDENCE);
4332
4331
  if (term[0] === "-")
4333
4332
  result += "+" + term.slice(1);
4334
4333
  else if (term[0] === "+")
@@ -4418,7 +4417,7 @@ function serializeMultiply(serializer, expr) {
4418
4417
  arg = op(arg, 1);
4419
4418
  isNegative = !isNegative;
4420
4419
  }
4421
- term = serializer.wrap(arg, 390);
4420
+ term = serializer.wrap(arg, MULTIPLICATION_PRECEDENCE);
4422
4421
  if (!result) {
4423
4422
  result = term;
4424
4423
  } else {
@@ -4667,11 +4666,14 @@ var DEFINITIONS_ARITHMETIC = [
4667
4666
  latexTrigger: ["+"],
4668
4667
  kind: "infix",
4669
4668
  associativity: "both",
4670
- precedence: 275,
4669
+ precedence: ADDITION_PRECEDENCE,
4671
4670
  parse: (parser, lhs, until) => {
4672
- if (until && 275 < until.minPrec)
4671
+ if (until && ADDITION_PRECEDENCE < until.minPrec)
4673
4672
  return null;
4674
- const rhs = parser.parseExpression({ ...until, minPrec: 275 });
4673
+ const rhs = parser.parseExpression({
4674
+ ...until,
4675
+ minPrec: ADDITION_PRECEDENCE
4676
+ });
4675
4677
  if (rhs === null)
4676
4678
  return null;
4677
4679
  return applyAssociativeOperator("Add", lhs, rhs);
@@ -4681,9 +4683,9 @@ var DEFINITIONS_ARITHMETIC = [
4681
4683
  {
4682
4684
  kind: "prefix",
4683
4685
  latexTrigger: ["+"],
4684
- precedence: 275,
4686
+ precedence: ADDITION_PRECEDENCE,
4685
4687
  parse: (parser, until) => {
4686
- if (until && 275 < until.minPrec)
4688
+ if (until && ADDITION_PRECEDENCE < until.minPrec)
4687
4689
  return null;
4688
4690
  return parser.parseExpression({ ...until, minPrec: 400 });
4689
4691
  }
@@ -4711,7 +4713,7 @@ var DEFINITIONS_ARITHMETIC = [
4711
4713
  { name: "Chop", identifierTrigger: "chop", kind: "function", parse: "Chop" },
4712
4714
  {
4713
4715
  name: "Complex",
4714
- precedence: 274,
4716
+ precedence: ADDITION_PRECEDENCE - 1,
4715
4717
  // One less than precedence of `Add`: used for correct wrapping
4716
4718
  serialize: (serializer, expr) => {
4717
4719
  const re = machineValue(op(expr, 1));
@@ -4729,7 +4731,7 @@ var DEFINITIONS_ARITHMETIC = [
4729
4731
  {
4730
4732
  name: "Divide",
4731
4733
  latexTrigger: "\\frac",
4732
- precedence: 660,
4734
+ precedence: DIVISION_PRECEDENCE,
4733
4735
  // For \frac specifically, not for \div, etc..
4734
4736
  // handles Leibnitz notation for partial derivatives
4735
4737
  parse: parseFraction,
@@ -4738,14 +4740,14 @@ var DEFINITIONS_ARITHMETIC = [
4738
4740
  {
4739
4741
  kind: "infix",
4740
4742
  latexTrigger: "\\over",
4741
- precedence: 660,
4743
+ precedence: DIVISION_PRECEDENCE,
4742
4744
  parse: "Divide"
4743
4745
  },
4744
4746
  {
4745
4747
  latexTrigger: ["\\/"],
4746
4748
  kind: "infix",
4747
4749
  associativity: "non",
4748
- precedence: 660,
4750
+ precedence: DIVISION_PRECEDENCE,
4749
4751
  // ??? MathML has 265, but it's wrong.
4750
4752
  // It has to be at least higher than multiply
4751
4753
  // e.g. `1/2+3*x` -> `1/2 + 3*x` , not `1/(2+3*x)`
@@ -4755,14 +4757,14 @@ var DEFINITIONS_ARITHMETIC = [
4755
4757
  latexTrigger: ["/"],
4756
4758
  kind: "infix",
4757
4759
  associativity: "non",
4758
- precedence: 660,
4760
+ precedence: DIVISION_PRECEDENCE,
4759
4761
  parse: "Divide"
4760
4762
  },
4761
4763
  {
4762
4764
  latexTrigger: ["\\div"],
4763
4765
  kind: "infix",
4764
4766
  associativity: "non",
4765
- precedence: 660,
4767
+ precedence: DIVISION_PRECEDENCE,
4766
4768
  // ??? according to MathML
4767
4769
  parse: "Divide"
4768
4770
  },
@@ -4779,13 +4781,13 @@ var DEFINITIONS_ARITHMETIC = [
4779
4781
  name: "Factorial",
4780
4782
  latexTrigger: ["!"],
4781
4783
  kind: "postfix",
4782
- precedence: 810
4784
+ precedence: POSTFIX_PRECEDENCE
4783
4785
  },
4784
4786
  {
4785
4787
  name: "Factorial2",
4786
4788
  latexTrigger: ["!", "!"],
4787
4789
  kind: "postfix",
4788
- precedence: 810
4790
+ precedence: POSTFIX_PRECEDENCE
4789
4791
  },
4790
4792
  {
4791
4793
  name: "Floor",
@@ -4918,23 +4920,26 @@ var DEFINITIONS_ARITHMETIC = [
4918
4920
  latexTrigger: ["\\mp"],
4919
4921
  kind: "infix",
4920
4922
  associativity: "both",
4921
- precedence: 270
4923
+ precedence: ARROW_PRECEDENCE
4922
4924
  },
4923
4925
  {
4924
4926
  name: "Multiply",
4925
4927
  latexTrigger: ["\\times"],
4926
4928
  kind: "infix",
4927
4929
  associativity: "both",
4928
- precedence: 390,
4930
+ precedence: MULTIPLICATION_PRECEDENCE,
4929
4931
  serialize: serializeMultiply
4930
4932
  },
4931
4933
  {
4932
4934
  latexTrigger: ["\\cdot"],
4933
4935
  kind: "infix",
4934
4936
  associativity: "both",
4935
- precedence: 390,
4937
+ precedence: MULTIPLICATION_PRECEDENCE,
4936
4938
  parse: (parser, lhs, terminator) => {
4937
- const rhs = parser.parseExpression({ ...terminator, minPrec: 392 });
4939
+ const rhs = parser.parseExpression({
4940
+ ...terminator,
4941
+ minPrec: MULTIPLICATION_PRECEDENCE + 2
4942
+ });
4938
4943
  if (rhs === null)
4939
4944
  return ["Multiply", lhs, MISSING];
4940
4945
  return applyAssociativeOperator("Multiply", lhs, rhs);
@@ -4944,23 +4949,77 @@ var DEFINITIONS_ARITHMETIC = [
4944
4949
  latexTrigger: ["*"],
4945
4950
  kind: "infix",
4946
4951
  associativity: "both",
4947
- precedence: 390,
4952
+ precedence: MULTIPLICATION_PRECEDENCE,
4948
4953
  parse: (parser, lhs, terminator) => {
4949
- const rhs = parser.parseExpression({ ...terminator, minPrec: 392 });
4954
+ const rhs = parser.parseExpression({
4955
+ ...terminator,
4956
+ minPrec: MULTIPLICATION_PRECEDENCE + 2
4957
+ });
4950
4958
  if (rhs === null)
4951
4959
  return ["Multiply", lhs, MISSING];
4952
4960
  return applyAssociativeOperator("Multiply", lhs, rhs);
4953
4961
  }
4954
4962
  },
4963
+ // Infix modulo, as in `26 \bmod 5`
4964
+ {
4965
+ name: "Mod",
4966
+ latexTrigger: "\\bmod",
4967
+ kind: "infix",
4968
+ precedence: DIVISION_PRECEDENCE,
4969
+ serialize: (serializer, expr) => {
4970
+ if (nops(expr) !== 2)
4971
+ return "";
4972
+ const lhs = serializer.serialize(op(expr, 1));
4973
+ const rhs = serializer.serialize(op(expr, 2));
4974
+ return joinLatex([lhs, "\\bmod", rhs]);
4975
+ }
4976
+ },
4977
+ // Synonym to \\bmod
4978
+ {
4979
+ latexTrigger: "\\mod",
4980
+ kind: "infix",
4981
+ precedence: DIVISION_PRECEDENCE,
4982
+ parse: "Mod"
4983
+ },
4984
+ {
4985
+ latexTrigger: "\\pmod",
4986
+ kind: "prefix",
4987
+ precedence: COMPARISON_PRECEDENCE,
4988
+ parse: (parser) => {
4989
+ const rhs = parser.parseGroup() ?? parser.parseToken();
4990
+ return ["Mod", missingIfEmpty(rhs)];
4991
+ }
4992
+ },
4993
+ {
4994
+ name: "Congruent",
4995
+ serialize: (serializer, expr) => {
4996
+ const lhs = serializer.serialize(op(expr, 1));
4997
+ const rhs = serializer.serialize(op(expr, 2));
4998
+ if (op(expr, 3) === null)
4999
+ return joinLatex([lhs, "\\equiv", rhs]);
5000
+ const modulus = serializer.serialize(op(expr, 3));
5001
+ return joinLatex([lhs, "\\equiv", rhs, "\\pmod{", modulus, "}"]);
5002
+ }
5003
+ },
4955
5004
  {
4956
5005
  name: "Negate",
4957
5006
  latexTrigger: ["-"],
4958
5007
  kind: "prefix",
5008
+ precedence: ADDITION_PRECEDENCE,
4959
5009
  parse: (parser, terminator) => {
4960
- const rhs = parser.parseExpression({ ...terminator, minPrec: 400 });
5010
+ if (/\d/.test(parser.peek))
5011
+ return null;
5012
+ const index = parser.index;
5013
+ if (parser.parseNumber() !== null) {
5014
+ parser.index = index;
5015
+ return null;
5016
+ }
5017
+ const rhs = parser.parseExpression({
5018
+ ...terminator,
5019
+ minPrec: ADDITION_PRECEDENCE + 1
5020
+ });
4961
5021
  return ["Negate", missingIfEmpty(rhs)];
4962
- },
4963
- precedence: 275
5022
+ }
4964
5023
  },
4965
5024
  // {
4966
5025
  // /** If the argument is a vector */
@@ -5000,7 +5059,7 @@ var DEFINITIONS_ARITHMETIC = [
5000
5059
  latexTrigger: ["\\pm"],
5001
5060
  kind: "infix",
5002
5061
  associativity: "both",
5003
- precedence: 270,
5062
+ precedence: ARROW_PRECEDENCE,
5004
5063
  serialize: (serializer, expr) => {
5005
5064
  const op12 = op(expr, 1);
5006
5065
  if (op12 === null)
@@ -5018,7 +5077,7 @@ var DEFINITIONS_ARITHMETIC = [
5018
5077
  {
5019
5078
  latexTrigger: ["\\pm"],
5020
5079
  kind: "prefix",
5021
- precedence: 270,
5080
+ precedence: ARROW_PRECEDENCE,
5022
5081
  parse: (parser, terminator) => {
5023
5082
  const rhs = parser.parseExpression({ ...terminator, minPrec: 400 });
5024
5083
  return ["PlusMinus", missingIfEmpty(rhs)];
@@ -5028,7 +5087,7 @@ var DEFINITIONS_ARITHMETIC = [
5028
5087
  latexTrigger: ["\\plusmn"],
5029
5088
  kind: "infix",
5030
5089
  associativity: "both",
5031
- precedence: 270,
5090
+ precedence: ARROW_PRECEDENCE,
5032
5091
  parse: (parser, lhs, terminator) => {
5033
5092
  const rhs = parser.parseExpression({ ...terminator, minPrec: 400 });
5034
5093
  return ["PlusMinus", lhs, missingIfEmpty(rhs)];
@@ -5037,7 +5096,7 @@ var DEFINITIONS_ARITHMETIC = [
5037
5096
  {
5038
5097
  latexTrigger: ["\\plusmn"],
5039
5098
  kind: "prefix",
5040
- precedence: 270,
5099
+ precedence: ARROW_PRECEDENCE,
5041
5100
  parse: (parser, terminator) => {
5042
5101
  const rhs = parser.parseExpression({ ...terminator, minPrec: 400 });
5043
5102
  return ["PlusMinus", missingIfEmpty(rhs)];
@@ -5052,9 +5111,9 @@ var DEFINITIONS_ARITHMETIC = [
5052
5111
  },
5053
5112
  {
5054
5113
  latexTrigger: "\\prod",
5055
- precedence: 390,
5114
+ precedence: MULTIPLICATION_PRECEDENCE,
5056
5115
  name: "Product",
5057
- parse: parseBigOp("Product", 390),
5116
+ parse: parseBigOp("Product", MULTIPLICATION_PRECEDENCE),
5058
5117
  serialize: serializeBigOp("\\prod")
5059
5118
  },
5060
5119
  // {
@@ -5065,7 +5124,7 @@ var DEFINITIONS_ARITHMETIC = [
5065
5124
  // },
5066
5125
  {
5067
5126
  name: "Rational",
5068
- precedence: 660,
5127
+ precedence: DIVISION_PRECEDENCE,
5069
5128
  serialize: (serializer, expr) => {
5070
5129
  if (expr && nops(expr) === 1)
5071
5130
  return "\\operatorname{Rational}" + serializer.wrapArguments(expr);
@@ -5088,9 +5147,9 @@ var DEFINITIONS_ARITHMETIC = [
5088
5147
  },
5089
5148
  {
5090
5149
  latexTrigger: ["\\sum"],
5091
- precedence: 275,
5150
+ precedence: ADDITION_PRECEDENCE,
5092
5151
  name: "Sum",
5093
- parse: parseBigOp("Sum", 275),
5152
+ parse: parseBigOp("Sum", ADDITION_PRECEDENCE),
5094
5153
  serialize: serializeBigOp("\\sum")
5095
5154
  },
5096
5155
  {
@@ -5110,9 +5169,12 @@ var DEFINITIONS_ARITHMETIC = [
5110
5169
  latexTrigger: ["-"],
5111
5170
  kind: "infix",
5112
5171
  associativity: "both",
5113
- precedence: 275,
5172
+ precedence: ADDITION_PRECEDENCE,
5114
5173
  parse: (parser, lhs, terminator) => {
5115
- const rhs = parser.parseExpression({ ...terminator, minPrec: 277 });
5174
+ const rhs = parser.parseExpression({
5175
+ ...terminator,
5176
+ minPrec: ADDITION_PRECEDENCE + 2
5177
+ });
5116
5178
  return ["Subtract", lhs, missingIfEmpty(rhs)];
5117
5179
  }
5118
5180
  }
@@ -5213,10 +5275,9 @@ function parseLog(command, parser) {
5213
5275
 
5214
5276
  // src/compute-engine/latex-syntax/dictionary/definitions-core.ts
5215
5277
  function parseSequence(parser, terminator, lhs, prec, sep) {
5216
- console.assert(lhs !== null);
5217
5278
  if (terminator.minPrec >= prec)
5218
5279
  return null;
5219
- const result = [lhs];
5280
+ const result = lhs ? [lhs] : ["Nothing"];
5220
5281
  let done = false;
5221
5282
  while (!done) {
5222
5283
  done = true;
@@ -5240,7 +5301,40 @@ function parseSequence(parser, terminator, lhs, prec, sep) {
5240
5301
  return result;
5241
5302
  }
5242
5303
  function serializeOps(sep = "") {
5243
- return (serializer, expr) => (ops(expr) ?? []).map((x) => serializer.serialize(x)).join(sep);
5304
+ return (serializer, expr) => {
5305
+ if (!expr)
5306
+ return "";
5307
+ const xs = ops(expr) ?? [];
5308
+ if (xs.length === 0)
5309
+ return "";
5310
+ if (xs.length === 1)
5311
+ return serializer.serialize(xs[0]);
5312
+ sep = {
5313
+ "&": "\\&",
5314
+ ":": "\\colon",
5315
+ "|": "\\mvert",
5316
+ "-": "-",
5317
+ "\xB7": "\\cdot",
5318
+ // U+00B7 MIDDLE DOT
5319
+ "\u2012": "-",
5320
+ // U+2012 FIGURE DASH
5321
+ "\u2013": "--",
5322
+ // U+2013 EN DASH
5323
+ "\u2014": "---",
5324
+ // U+2014 EM DASH
5325
+ "\u2015": "-",
5326
+ // U+2015 HORIZONTAL BAR
5327
+ "\u2022": "\\bullet",
5328
+ // U+2022 BULLET
5329
+ "\u2026": "\\ldots"
5330
+ }[sep] ?? sep;
5331
+ const ys = xs.reduce((acc, item) => {
5332
+ acc.push(serializer.serialize(item), sep);
5333
+ return acc;
5334
+ }, []);
5335
+ ys.pop();
5336
+ return joinLatex(ys);
5337
+ };
5244
5338
  }
5245
5339
  var DEFINITIONS_CORE = [
5246
5340
  //
@@ -5271,7 +5365,7 @@ var DEFINITIONS_CORE = [
5271
5365
  name: "Function",
5272
5366
  latexTrigger: ["\\mapsto"],
5273
5367
  kind: "infix",
5274
- precedence: 270,
5368
+ precedence: ARROW_PRECEDENCE,
5275
5369
  // MathML rightwards arrow
5276
5370
  parse: (parser, lhs) => {
5277
5371
  let params = [];
@@ -5279,18 +5373,16 @@ var DEFINITIONS_CORE = [
5279
5373
  lhs = op(lhs, 1) ?? "Nothing";
5280
5374
  if (head(lhs) === "Sequence") {
5281
5375
  for (const x of ops(lhs) ?? []) {
5282
- if (symbol(x))
5283
- params.push(symbol(x));
5284
- else
5376
+ if (!symbol(x))
5285
5377
  return null;
5378
+ params.push(symbol(x));
5286
5379
  }
5287
5380
  } else {
5288
- if (symbol(lhs))
5289
- params = [symbol(lhs)];
5290
- else
5381
+ if (!symbol(lhs))
5291
5382
  return null;
5383
+ params = [symbol(lhs)];
5292
5384
  }
5293
- let rhs = parser.parseExpression({ minPrec: 270 }) ?? "Nothing";
5385
+ let rhs = parser.parseExpression({ minPrec: ARROW_PRECEDENCE }) ?? "Nothing";
5294
5386
  if (head(rhs) === "Delimiter")
5295
5387
  rhs = op(rhs, 1) ?? "Nothing";
5296
5388
  if (head(rhs) === "Sequence")
@@ -5348,50 +5440,62 @@ var DEFINITIONS_CORE = [
5348
5440
  return ["Apply", rhs, lhs];
5349
5441
  }
5350
5442
  },
5443
+ // The mathtools package includes several synonmyms for \colonequals. The
5444
+ // current preferred one is `\coloneq`
5351
5445
  {
5352
5446
  name: "Assign",
5353
- latexTrigger: "\\coloneqq",
5447
+ latexTrigger: "\\coloneq",
5354
5448
  kind: "infix",
5355
5449
  associativity: "right",
5356
- precedence: 260,
5450
+ precedence: ASSIGNMENT_PRECEDENCE,
5357
5451
  // parse: (parser: Parser, lhs: Expression) => {
5358
5452
  // const rhs = parser.parseExpression({ minPrec: 260 }) ?? 'Nothing';
5359
5453
  // return ['Assign', lhs, rhs];
5360
5454
  // },
5361
5455
  serialize: (serializer, expr) => {
5456
+ const id = unhold(op(expr, 1));
5457
+ if (head(op(expr, 2)) === "Function") {
5458
+ const op_2 = op(expr, 2);
5459
+ const body = unhold(op(op_2, 1));
5460
+ const args = ops(op_2)?.slice(1) ?? [];
5461
+ return joinLatex([
5462
+ serializer.serialize(id),
5463
+ serializer.wrapString(
5464
+ args.map((x) => serializer.serialize(x)).join(", "),
5465
+ serializer.options.applyFunctionStyle(expr, serializer.level)
5466
+ ),
5467
+ "\\coloneq",
5468
+ serializer.serialize(body)
5469
+ ]);
5470
+ }
5362
5471
  return joinLatex([
5363
- serializer.serialize(op(expr, 1)),
5364
- "\\coloneqq",
5472
+ serializer.serialize(id),
5473
+ "\\coloneq",
5365
5474
  serializer.serialize(op(expr, 2))
5366
5475
  ]);
5367
- }
5476
+ },
5477
+ parse: parseAssign
5368
5478
  },
5369
5479
  {
5370
5480
  latexTrigger: [":", "="],
5371
5481
  kind: "infix",
5372
5482
  associativity: "right",
5373
- precedence: 260,
5374
- parse: "Assign"
5483
+ precedence: ASSIGNMENT_PRECEDENCE,
5484
+ parse: parseAssign
5375
5485
  },
5376
- // {
5377
- // kind: 'function',
5378
- // latexTrigger: ':=', // \coloneqq
5379
- // parse: (parser: Parser, lhs: Expression) => {
5380
- // const rhs = parser.parseExpression({ minPrec: 270 }) ?? 'Nothing';
5381
- // return ['Assign', lhs, rhs];
5382
- // },
5383
- // },
5384
5486
  {
5385
5487
  latexTrigger: "\\colonequals",
5386
- // \coloneqq
5387
5488
  kind: "infix",
5388
5489
  associativity: "right",
5389
- precedence: 260,
5390
- parse: "Assign"
5391
- // parse: (parser: Parser, lhs: Expression) => {
5392
- // const rhs = parser.parseExpression({ minPrec: 270 }) ?? 'Nothing';
5393
- // return ['Assign', lhs, rhs];
5394
- // },
5490
+ precedence: ASSIGNMENT_PRECEDENCE,
5491
+ parse: parseAssign
5492
+ },
5493
+ {
5494
+ latexTrigger: "\\coloneqq",
5495
+ kind: "infix",
5496
+ associativity: "right",
5497
+ precedence: ASSIGNMENT_PRECEDENCE,
5498
+ parse: parseAssign
5395
5499
  },
5396
5500
  {
5397
5501
  name: "BaseForm",
@@ -5427,25 +5531,47 @@ var DEFINITIONS_CORE = [
5427
5531
  }
5428
5532
  },
5429
5533
  {
5534
+ name: "Sequence",
5535
+ // Use a space as a separator, otherwise a sequence of numbers
5536
+ // could be interpreted as a single number.
5537
+ serialize: serializeOps(" ")
5538
+ },
5539
+ {
5540
+ name: "InvisibleOperator",
5541
+ serialize: serializeOps("")
5542
+ },
5543
+ {
5544
+ // The first argument is a function expression.
5545
+ // The second (optional) argument is a string specifying the
5546
+ // delimiters and separator.
5430
5547
  name: "Delimiter",
5431
5548
  serialize: (serializer, expr) => {
5432
- const argCount = nops(expr);
5433
- if (argCount === 0)
5434
- return "";
5435
- const style = serializer.options.groupStyle(expr, serializer.level + 1);
5436
5549
  const arg1 = op(expr, 1);
5550
+ const style = serializer.options.groupStyle(expr, serializer.level + 1);
5437
5551
  const h1 = head(arg1);
5438
- const defaultFence = { List: "[],", Sequence: "" }[typeof h1 === "string" ? h1 : ""] ?? "(),";
5439
- let open = defaultFence[0] ?? "";
5440
- let close = defaultFence[1] ?? "";
5441
- let sep = defaultFence[2] ?? "";
5442
- if (argCount > 1) {
5443
- const op22 = stringValue(op(expr, 2)) ?? "";
5444
- open = op22[0] ?? defaultFence[0];
5445
- close = op22[1] ?? defaultFence[1];
5446
- sep = op22[2] ?? defaultFence[2];
5447
- }
5448
- const body = isListLike(arg1) ? serializeOps(sep)(serializer, arg1) : serializer.serialize(arg1);
5552
+ let delims = {
5553
+ Set: "{,}",
5554
+ List: "[,]",
5555
+ Tuple: "(,)",
5556
+ Single: "(,)",
5557
+ Pair: "(,)",
5558
+ Triple: "(,)",
5559
+ Sequence: "(,)",
5560
+ String: '""'
5561
+ }[typeof h1 === "string" ? h1 : ""] ?? "(,)";
5562
+ if (nops(expr) > 1) {
5563
+ const op22 = stringValue(op(expr, 2));
5564
+ if (typeof op22 === "string" && op22.length <= 3)
5565
+ delims = op22;
5566
+ }
5567
+ let [open, sep, close] = ["", "", ""];
5568
+ if (delims.length === 3)
5569
+ [open, sep, close] = delims;
5570
+ else if (delims.length === 2)
5571
+ [open, close] = delims;
5572
+ else if (delims.length === 1)
5573
+ sep = delims;
5574
+ const body = arg1 ? ops(arg1) ? serializeOps(sep)(serializer, arg1) : serializer.serialize(arg1) : "";
5449
5575
  return serializer.wrapString(body, style, open + close);
5450
5576
  }
5451
5577
  },
@@ -5554,7 +5680,7 @@ var DEFINITIONS_CORE = [
5554
5680
  kind: "matchfix",
5555
5681
  openTrigger: "(",
5556
5682
  closeTrigger: ")",
5557
- parse: parseDelimiter
5683
+ parse: parseParenDelimiter
5558
5684
  },
5559
5685
  {
5560
5686
  latexTrigger: [","],
@@ -5569,7 +5695,20 @@ var DEFINITIONS_CORE = [
5569
5695
  const seq = parseSequence(parser, terminator, lhs, 20, ",");
5570
5696
  if (seq === null)
5571
5697
  return null;
5572
- return ["Sequence", ...seq];
5698
+ return ["Delimiter", ["Sequence", ...seq], { str: "," }];
5699
+ }
5700
+ },
5701
+ // Entry to handle the case of a single comma
5702
+ // with a missing lhs.
5703
+ {
5704
+ latexTrigger: [","],
5705
+ kind: "prefix",
5706
+ precedence: 20,
5707
+ parse: (parser, terminator) => {
5708
+ const seq = parseSequence(parser, terminator, null, 20, ",");
5709
+ if (seq === null)
5710
+ return null;
5711
+ return ["Delimiter", ["Sequence", ...seq], { str: "," }];
5573
5712
  }
5574
5713
  },
5575
5714
  {
@@ -5597,10 +5736,6 @@ var DEFINITIONS_CORE = [
5597
5736
  return "";
5598
5737
  }
5599
5738
  },
5600
- {
5601
- name: "Sequence",
5602
- serialize: serializeOps("")
5603
- },
5604
5739
  {
5605
5740
  latexTrigger: [";"],
5606
5741
  kind: "infix",
@@ -5609,12 +5744,7 @@ var DEFINITIONS_CORE = [
5609
5744
  const seq = parseSequence(parser, terminator, lhs, 19, ";");
5610
5745
  if (seq === null)
5611
5746
  return null;
5612
- return [
5613
- "Sequence",
5614
- ...seq.map(
5615
- (x) => head(x) === "Sequence" ? ["List", ...ops(x) ?? []] : x
5616
- )
5617
- ];
5747
+ return ["Delimiter", ["Sequence", ...seq], "';'"];
5618
5748
  }
5619
5749
  },
5620
5750
  {
@@ -5881,8 +6011,66 @@ function parseTextRun(parser, style) {
5881
6011
  text += "$$";
5882
6012
  parser.index = index;
5883
6013
  }
5884
- } else
5885
- text += parser.matchChar() ?? parser.nextToken();
6014
+ } else {
6015
+ const c = parser.matchChar() ?? parser.nextToken();
6016
+ text += {
6017
+ "\\enskip": "\u2002",
6018
+ // en space
6019
+ "\\enspace": "\u2002",
6020
+ // en space
6021
+ "\\quad": "\u2003",
6022
+ // em space
6023
+ "\\qquad": "\u2003\u2003",
6024
+ // 2 em space
6025
+ "\\space": "\u2003",
6026
+ // em space
6027
+ "\\ ": "\u2003",
6028
+ // em space
6029
+ "\\;": "\u2004",
6030
+ // three per em space
6031
+ "\\,": "\u2009",
6032
+ // thin space
6033
+ "\\:": "\u205F",
6034
+ // medium mathematical space
6035
+ "\\!": "",
6036
+ // negative thin space
6037
+ "\\{": "{",
6038
+ "\\}": "}",
6039
+ "\\$": "$",
6040
+ "\\&": "&",
6041
+ "\\#": "#",
6042
+ "\\%": "%",
6043
+ "\\_": "_",
6044
+ "\\textbackslash": "\\",
6045
+ "\\textasciitilde": "~",
6046
+ "\\textasciicircum": "^",
6047
+ "\\textless": "<",
6048
+ "\\textgreater": ">",
6049
+ "\\textbar": "|",
6050
+ "\\textunderscore": "_",
6051
+ "\\textbraceleft": "{",
6052
+ "\\textbraceright": "}",
6053
+ "\\textasciigrave": "`",
6054
+ "\\textquotesingle": "'",
6055
+ "\\textquotedblleft": "\u201C",
6056
+ "\\textquotedblright": "\u201D",
6057
+ "\\textquotedbl": '"',
6058
+ "\\textquoteleft": "\u2018",
6059
+ "\\textquoteright": "\u2019",
6060
+ "\\textbullet": "\u2022",
6061
+ "\\textdagger": "\u2020",
6062
+ "\\textdaggerdbl": "\u2021",
6063
+ "\\textsection": "\xA7",
6064
+ "\\textparagraph": "\xB6",
6065
+ "\\textperiodcentered": "\xB7",
6066
+ "\\textellipsis": "\u2026",
6067
+ "\\textemdash": "\u2014",
6068
+ "\\textendash": "\u2013",
6069
+ "\\textregistered": "\xAE",
6070
+ "\\texttrademark": "\u2122",
6071
+ "\\textdegree": "\xB0"
6072
+ }[c] ?? c;
6073
+ }
5886
6074
  }
5887
6075
  if (runinStyle !== null && text) {
5888
6076
  runs.push(["Style", `'${text}'`, { dict: runinStyle }]);
@@ -5962,19 +6150,27 @@ function parsePrime(parser, lhs, order2) {
5962
6150
  return ["Prime", missingIfEmpty(lhs)];
5963
6151
  return ["Prime", missingIfEmpty(lhs), order2];
5964
6152
  }
5965
- function parseDelimiter(_parser, body) {
6153
+ function parseParenDelimiter(_parser, body) {
5966
6154
  if (body === null || isEmptySequence(body))
5967
- return ["Sequence"];
6155
+ return ["Delimiter"];
6156
+ if (head(body) === "Delimiter" && op(body, 2)) {
6157
+ const delims = stringValue(op(body, 2));
6158
+ if (delims?.length === 1) {
6159
+ return ["Delimiter", op(body, 1) ?? ["Sequence"], { str: `(${delims})` }];
6160
+ }
6161
+ }
5968
6162
  if (head(body) === "Sequence") {
5969
6163
  if (nops(body) === 0)
5970
6164
  return ["Delimiter"];
5971
- return ["Delimiter", ["Sequence", ...ops(body) ?? []]];
6165
+ return ["Delimiter", body];
5972
6166
  }
5973
- return ["Delimiter", body];
6167
+ return ["Delimiter", ["Sequence", body]];
5974
6168
  }
5975
6169
  function parseList(_parser, body) {
5976
6170
  if (body === null || isEmptySequence(body))
5977
6171
  return ["List"];
6172
+ if (head(body) === "Delimiter")
6173
+ return parseList(_parser, op(body, 1));
5978
6174
  if (head(body) === "Range")
5979
6175
  return body;
5980
6176
  if (head(body) !== "Sequence" && head(body) !== "List")
@@ -6015,6 +6211,80 @@ function parseRange(parser, lhs) {
6015
6211
  }
6016
6212
  return ["Range", start, end];
6017
6213
  }
6214
+ var DELIMITERS_SHORTHAND = {
6215
+ "(": "(",
6216
+ ")": ")",
6217
+ "[": "\\lbrack",
6218
+ "]": "\\rbrack",
6219
+ "\u27E6": "\\llbrack",
6220
+ // U+27E6 MATHEMATICAL LEFT WHITE SQUARE BRACKET
6221
+ "\u27E7": "\\rrbrack",
6222
+ // U+27E7 MATHEMATICAL RIGHT WHITE SQUARE BRACKET
6223
+ "{": "\\lbrace",
6224
+ "}": "\\rbrace",
6225
+ "<": "\\langle",
6226
+ ">": "\\rangle",
6227
+ // '|': '\\vert',
6228
+ "\u2016": "\\Vert",
6229
+ // U+2016 DOUBLE VERTICAL LINE
6230
+ "\\": "\\backslash",
6231
+ "\u2308": "\\lceil",
6232
+ // ⌈ U+2308 LEFT CEILING
6233
+ "\u2309": "\\rceil",
6234
+ // U+2309 RIGHT CEILING
6235
+ "\u230A": "\\lfloor",
6236
+ // ⌊ U+230A LEFT FLOOR
6237
+ "\u230B": "\\rfloor",
6238
+ // ⌋ U+230B RIGHT FLOOR
6239
+ "\u231C": "\\ulcorner",
6240
+ // ⌜ U+231C TOP LEFT CORNER
6241
+ "\u231D": "\\urcorner",
6242
+ // ⌝ U+231D TOP RIGHT CORNER
6243
+ "\u231E": "\\llcorner",
6244
+ // ⌞ U+231E BOTTOM LEFT CORNER
6245
+ "\u231F": "\\lrcorner",
6246
+ // ⌟ U+231F BOTTOM RIGHT CORNER
6247
+ "\u23B0": "\\lmoustache",
6248
+ // U+23B0 UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION
6249
+ "\u23B1": "\\rmoustache"
6250
+ // U+23B1 UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION
6251
+ // '⎹': '', // U+23B9 DIVIDES
6252
+ // '⎾': '', // U+23BE RIGHT PARENTHESIS UPPER HOOK
6253
+ // '⎿': '', // U+23BF RIGHT PARENTHESIS LOWER HOOK
6254
+ };
6255
+ function parseAssign(parser, lhs) {
6256
+ const index = parser.index;
6257
+ if (head(lhs) === "InvisibleOperator" && nops(lhs) === 2 && head(op(lhs, 2)) === "Delimiter" && head(op(op(lhs, 2), 1)) === "Sequence") {
6258
+ const fn = symbol(op(lhs, 1));
6259
+ if (!fn)
6260
+ return null;
6261
+ const args = ops(op(op(lhs, 2), 1));
6262
+ const rhs2 = parser.parseExpression({ minPrec: 0 });
6263
+ if (rhs2 === null) {
6264
+ parser.index = index;
6265
+ return null;
6266
+ }
6267
+ return ["Assign", fn, ["Function", rhs2, ...args ?? []]];
6268
+ }
6269
+ if (typeof head(lhs) === "string") {
6270
+ const fn = head(lhs);
6271
+ const args = ops(lhs) ?? [];
6272
+ const rhs2 = parser.parseExpression({ minPrec: 0 });
6273
+ if (rhs2 === null) {
6274
+ parser.index = index;
6275
+ return null;
6276
+ }
6277
+ return ["Assign", fn, ["Function", rhs2, ...args]];
6278
+ }
6279
+ if (!symbol(lhs))
6280
+ return null;
6281
+ const rhs = parser.parseExpression({ minPrec: 0 });
6282
+ if (rhs === null) {
6283
+ parser.index = index;
6284
+ return null;
6285
+ }
6286
+ return ["Assign", lhs, rhs];
6287
+ }
6018
6288
 
6019
6289
  // src/compute-engine/latex-syntax/dictionary/definitions-inequalities.ts
6020
6290
  var DEFINITIONS_INEQUALITIES = [
@@ -6071,7 +6341,7 @@ var DEFINITIONS_INEQUALITIES = [
6071
6341
  latexTrigger: ["\\leqslant"],
6072
6342
  kind: "infix",
6073
6343
  associativity: "right",
6074
- precedence: 265,
6344
+ precedence: COMPARISON_PRECEDENCE + 5,
6075
6345
  // Note different precedence than `<=` as per MathML
6076
6346
  parse: "LessEqual"
6077
6347
  },
@@ -6080,28 +6350,28 @@ var DEFINITIONS_INEQUALITIES = [
6080
6350
  latexTrigger: ["\\lneqq"],
6081
6351
  kind: "infix",
6082
6352
  associativity: "right",
6083
- precedence: 260
6353
+ precedence: COMPARISON_PRECEDENCE
6084
6354
  },
6085
6355
  {
6086
6356
  name: "NotLessNotEqual",
6087
6357
  latexTrigger: ["\\nleqq"],
6088
6358
  kind: "infix",
6089
6359
  associativity: "right",
6090
- precedence: 260
6360
+ precedence: COMPARISON_PRECEDENCE
6091
6361
  },
6092
6362
  {
6093
6363
  name: "LessOverEqual",
6094
6364
  latexTrigger: ["\\leqq"],
6095
6365
  kind: "infix",
6096
6366
  associativity: "right",
6097
- precedence: 265
6367
+ precedence: COMPARISON_PRECEDENCE + 5
6098
6368
  },
6099
6369
  {
6100
6370
  name: "GreaterOverEqual",
6101
6371
  latexTrigger: ["\\geqq"],
6102
6372
  kind: "infix",
6103
6373
  associativity: "right",
6104
- precedence: 265,
6374
+ precedence: COMPARISON_PRECEDENCE + 5,
6105
6375
  parse: "GreaterEqual"
6106
6376
  },
6107
6377
  {
@@ -6109,13 +6379,13 @@ var DEFINITIONS_INEQUALITIES = [
6109
6379
  latexTrigger: ["="],
6110
6380
  kind: "infix",
6111
6381
  associativity: "right",
6112
- precedence: 260
6382
+ precedence: COMPARISON_PRECEDENCE
6113
6383
  },
6114
6384
  {
6115
6385
  latexTrigger: ["*", "="],
6116
6386
  kind: "infix",
6117
6387
  associativity: "right",
6118
- precedence: 260,
6388
+ precedence: COMPARISON_PRECEDENCE,
6119
6389
  parse: "StarEqual"
6120
6390
  },
6121
6391
  {
@@ -6123,42 +6393,42 @@ var DEFINITIONS_INEQUALITIES = [
6123
6393
  latexTrigger: ["\\star", "="],
6124
6394
  kind: "infix",
6125
6395
  associativity: "right",
6126
- precedence: 260
6396
+ precedence: COMPARISON_PRECEDENCE
6127
6397
  },
6128
6398
  {
6129
6399
  name: "PlusEqual",
6130
6400
  latexTrigger: ["+", "="],
6131
6401
  kind: "infix",
6132
6402
  associativity: "right",
6133
- precedence: 260
6403
+ precedence: COMPARISON_PRECEDENCE
6134
6404
  },
6135
6405
  {
6136
6406
  name: "MinusEqual",
6137
6407
  latexTrigger: ["-", "="],
6138
6408
  kind: "infix",
6139
6409
  associativity: "right",
6140
- precedence: 260
6410
+ precedence: COMPARISON_PRECEDENCE
6141
6411
  },
6142
6412
  {
6143
6413
  name: "SlashEqual",
6144
6414
  latexTrigger: ["/", "="],
6145
6415
  kind: "infix",
6146
6416
  associativity: "right",
6147
- precedence: 260
6417
+ precedence: COMPARISON_PRECEDENCE
6148
6418
  },
6149
6419
  {
6150
6420
  name: "EqualEqual",
6151
6421
  latexTrigger: ["=", "="],
6152
6422
  kind: "infix",
6153
6423
  associativity: "right",
6154
- precedence: 260
6424
+ precedence: COMPARISON_PRECEDENCE
6155
6425
  },
6156
6426
  {
6157
6427
  name: "EqualEqualEqual",
6158
6428
  latexTrigger: ["=", "=", "="],
6159
6429
  kind: "infix",
6160
6430
  associativity: "right",
6161
- precedence: 265
6431
+ precedence: COMPARISON_PRECEDENCE + 5
6162
6432
  },
6163
6433
  {
6164
6434
  name: "TildeFullEqual",
@@ -6166,7 +6436,7 @@ var DEFINITIONS_INEQUALITIES = [
6166
6436
  latexTrigger: ["\\cong"],
6167
6437
  kind: "infix",
6168
6438
  associativity: "right",
6169
- precedence: 260
6439
+ precedence: COMPARISON_PRECEDENCE
6170
6440
  },
6171
6441
  {
6172
6442
  name: "NotTildeFullEqual",
@@ -6174,7 +6444,7 @@ var DEFINITIONS_INEQUALITIES = [
6174
6444
  latexTrigger: ["\\ncong"],
6175
6445
  kind: "infix",
6176
6446
  associativity: "right",
6177
- precedence: 260
6447
+ precedence: COMPARISON_PRECEDENCE
6178
6448
  },
6179
6449
  {
6180
6450
  name: "Approx",
@@ -6198,7 +6468,7 @@ var DEFINITIONS_INEQUALITIES = [
6198
6468
  latexTrigger: ["\\approxeq"],
6199
6469
  kind: "infix",
6200
6470
  associativity: "right",
6201
- precedence: 260
6471
+ precedence: COMPARISON_PRECEDENCE
6202
6472
  },
6203
6473
  {
6204
6474
  name: "NotApproxEqual",
@@ -6221,7 +6491,7 @@ var DEFINITIONS_INEQUALITIES = [
6221
6491
  latexTrigger: ["!", "="],
6222
6492
  kind: "infix",
6223
6493
  associativity: "right",
6224
- precedence: 260
6494
+ precedence: COMPARISON_PRECEDENCE
6225
6495
  // Note different precedence than \\ne per MathML
6226
6496
  },
6227
6497
  {
@@ -6251,7 +6521,7 @@ var DEFINITIONS_INEQUALITIES = [
6251
6521
  latexTrigger: ["\\geqslant"],
6252
6522
  kind: "infix",
6253
6523
  associativity: "right",
6254
- precedence: 265,
6524
+ precedence: COMPARISON_PRECEDENCE + 5,
6255
6525
  // Note: different precedence than `>=` as per MathML
6256
6526
  parse: "GreaterEqual"
6257
6527
  },
@@ -6260,14 +6530,14 @@ var DEFINITIONS_INEQUALITIES = [
6260
6530
  latexTrigger: ["\\gneqq"],
6261
6531
  kind: "infix",
6262
6532
  associativity: "right",
6263
- precedence: 260
6533
+ precedence: COMPARISON_PRECEDENCE
6264
6534
  },
6265
6535
  {
6266
6536
  name: "NotGreaterNotEqual",
6267
6537
  latexTrigger: ["\\ngeqq"],
6268
6538
  kind: "infix",
6269
6539
  associativity: "right",
6270
- precedence: 260
6540
+ precedence: COMPARISON_PRECEDENCE
6271
6541
  },
6272
6542
  {
6273
6543
  latexTrigger: [">"],
@@ -6302,7 +6572,7 @@ var DEFINITIONS_INEQUALITIES = [
6302
6572
  latexTrigger: ["\\circeq"],
6303
6573
  kind: "infix",
6304
6574
  associativity: "right",
6305
- precedence: 260
6575
+ precedence: COMPARISON_PRECEDENCE
6306
6576
  },
6307
6577
  {
6308
6578
  name: "TriangleEqual",
@@ -6310,7 +6580,7 @@ var DEFINITIONS_INEQUALITIES = [
6310
6580
  latexTrigger: ["\\triangleq"],
6311
6581
  kind: "infix",
6312
6582
  associativity: "right",
6313
- precedence: 260
6583
+ precedence: COMPARISON_PRECEDENCE
6314
6584
  },
6315
6585
  {
6316
6586
  name: "DotEqual",
@@ -6318,7 +6588,7 @@ var DEFINITIONS_INEQUALITIES = [
6318
6588
  latexTrigger: ["\\doteq"],
6319
6589
  kind: "infix",
6320
6590
  associativity: "right",
6321
- precedence: 265
6591
+ precedence: COMPARISON_PRECEDENCE + 5
6322
6592
  },
6323
6593
  {
6324
6594
  name: "DotEqualDot",
@@ -6326,7 +6596,7 @@ var DEFINITIONS_INEQUALITIES = [
6326
6596
  latexTrigger: ["\\doteqdot"],
6327
6597
  kind: "infix",
6328
6598
  associativity: "right",
6329
- precedence: 265
6599
+ precedence: COMPARISON_PRECEDENCE + 5
6330
6600
  },
6331
6601
  {
6332
6602
  name: "FallingDotEqual",
@@ -6334,7 +6604,7 @@ var DEFINITIONS_INEQUALITIES = [
6334
6604
  latexTrigger: ["\\fallingdotseq"],
6335
6605
  kind: "infix",
6336
6606
  associativity: "right",
6337
- precedence: 265
6607
+ precedence: COMPARISON_PRECEDENCE + 5
6338
6608
  },
6339
6609
  {
6340
6610
  name: "RisingDotEqual",
@@ -6342,77 +6612,182 @@ var DEFINITIONS_INEQUALITIES = [
6342
6612
  latexTrigger: ["\\fallingdotseq"],
6343
6613
  kind: "infix",
6344
6614
  associativity: "right",
6345
- precedence: 265
6615
+ precedence: COMPARISON_PRECEDENCE + 5
6346
6616
  },
6347
6617
  {
6348
6618
  name: "QuestionEqual",
6349
6619
  latexTrigger: ["\\questeq"],
6350
6620
  kind: "infix",
6351
6621
  associativity: "right",
6352
- precedence: 260
6622
+ precedence: COMPARISON_PRECEDENCE
6353
6623
  },
6354
6624
  {
6355
6625
  name: "MuchLess",
6356
6626
  latexTrigger: ["\\ll"],
6357
6627
  kind: "infix",
6358
6628
  associativity: "right",
6359
- precedence: 260
6629
+ precedence: COMPARISON_PRECEDENCE
6360
6630
  },
6361
6631
  {
6362
6632
  name: "MuchGreater",
6363
6633
  latexTrigger: ["\\gg"],
6364
6634
  kind: "infix",
6365
6635
  associativity: "right",
6366
- precedence: 260
6636
+ precedence: COMPARISON_PRECEDENCE
6367
6637
  },
6368
6638
  {
6369
6639
  name: "Precedes",
6370
6640
  latexTrigger: ["\\prec"],
6371
6641
  kind: "infix",
6372
6642
  associativity: "right",
6373
- precedence: 260
6643
+ precedence: COMPARISON_PRECEDENCE
6374
6644
  },
6375
6645
  {
6376
6646
  name: "Succeeds",
6377
6647
  latexTrigger: ["\\succ"],
6378
6648
  kind: "infix",
6379
6649
  associativity: "right",
6380
- precedence: 260
6650
+ precedence: COMPARISON_PRECEDENCE
6381
6651
  },
6382
6652
  {
6383
6653
  name: "PrecedesEqual",
6384
6654
  latexTrigger: ["\\preccurlyeq"],
6385
6655
  kind: "infix",
6386
6656
  associativity: "right",
6387
- precedence: 260
6657
+ precedence: COMPARISON_PRECEDENCE
6388
6658
  },
6389
6659
  {
6390
6660
  name: "SucceedsEqual",
6391
6661
  latexTrigger: ["\\curlyeqprec"],
6392
6662
  kind: "infix",
6393
6663
  associativity: "right",
6394
- precedence: 260
6664
+ precedence: COMPARISON_PRECEDENCE
6395
6665
  },
6396
6666
  {
6397
6667
  name: "NotPrecedes",
6398
6668
  latexTrigger: ["\\nprec"],
6399
6669
  kind: "infix",
6400
6670
  associativity: "right",
6401
- precedence: 260
6671
+ precedence: COMPARISON_PRECEDENCE
6402
6672
  },
6403
6673
  {
6404
6674
  name: "NotSucceeds",
6405
6675
  latexTrigger: ["\\nsucc"],
6406
6676
  kind: "infix",
6407
6677
  associativity: "right",
6408
- precedence: 260
6678
+ precedence: COMPARISON_PRECEDENCE
6409
6679
  },
6410
6680
  {
6411
6681
  name: "Between",
6412
6682
  latexTrigger: ["\\between"],
6413
6683
  kind: "infix",
6414
6684
  associativity: "right",
6415
- precedence: 265
6685
+ precedence: COMPARISON_PRECEDENCE + 5
6686
+ }
6687
+ ];
6688
+
6689
+ // src/compute-engine/latex-syntax/dictionary/definitions-linear-algebra.ts
6690
+ var DEFINITIONS_LINEAR_ALGEBRA = [
6691
+ // The first argument is the matrix data.
6692
+ // The second, optional, argument are the delimiters.
6693
+ // The third, optional, argument is the column specification.
6694
+ {
6695
+ name: "Matrix",
6696
+ // https://ctan.math.illinois.edu/macros/latex/required/tools/array.pdf
6697
+ serialize: (serializer, expr) => {
6698
+ const body = op(expr, 1);
6699
+ const delims = op(expr, 2) ?? "()";
6700
+ let columns = "";
6701
+ if (op(expr, 3) !== null) {
6702
+ const colsSpec = stringValue(op(expr, 3)) ?? "";
6703
+ for (const c of colsSpec) {
6704
+ if (c === "<")
6705
+ columns += "l";
6706
+ else if (c === ">")
6707
+ columns += "r";
6708
+ else if (c === "=")
6709
+ columns += "c";
6710
+ else if (c === "|")
6711
+ columns += "|";
6712
+ else if (c === ":")
6713
+ columns += ":";
6714
+ }
6715
+ }
6716
+ let [open, close] = ["", ""];
6717
+ if (typeof delims === "string" && delims.length === 2)
6718
+ [open, close] = delims;
6719
+ const rows = [];
6720
+ for (const row of ops(body) ?? []) {
6721
+ const cells = [];
6722
+ for (const cell of ops(row) ?? [])
6723
+ cells.push(serializer.serialize(cell));
6724
+ rows.push(cells.join(" & "));
6725
+ }
6726
+ const tabular = rows.join("\\\\\n");
6727
+ const optColumns = columns.length > 0 ? `[${columns}]` : "";
6728
+ if (open === "(" && close === ")")
6729
+ return joinLatex([
6730
+ "\\begin{pmatrix}",
6731
+ optColumns,
6732
+ tabular,
6733
+ "\\end{pmatrix}"
6734
+ ]);
6735
+ if (open === "[" && close === "]")
6736
+ return joinLatex([
6737
+ "\\begin{bmatrix}",
6738
+ optColumns,
6739
+ tabular,
6740
+ "\\end{bmatrix}"
6741
+ ]);
6742
+ if (open === "{" && close === "}")
6743
+ return joinLatex([
6744
+ "\\begin{Bmatrix}",
6745
+ optColumns,
6746
+ tabular,
6747
+ "\\end{Bmatrix}"
6748
+ ]);
6749
+ if (open === "|" && close === "|")
6750
+ return joinLatex([
6751
+ "\\begin{vmatrix}",
6752
+ optColumns,
6753
+ tabular,
6754
+ "\\end{vmatrix}"
6755
+ ]);
6756
+ if (open === "\u2016" && close === "\u2016")
6757
+ return joinLatex([
6758
+ "\\begin{Vmatrix}",
6759
+ optColumns,
6760
+ tabular,
6761
+ "\\end{Vmatrix}"
6762
+ ]);
6763
+ if (open === "{" && close === ".")
6764
+ return joinLatex([
6765
+ "\\begin{dcases}",
6766
+ optColumns,
6767
+ tabular,
6768
+ "\\end{dcases}"
6769
+ ]);
6770
+ if (open === "." && close === "}")
6771
+ return joinLatex([
6772
+ "\\begin{rcases}",
6773
+ optColumns,
6774
+ tabular,
6775
+ "\\end{rcases}"
6776
+ ]);
6777
+ if (columns || open !== "." || close !== ".") {
6778
+ return joinLatex([
6779
+ "\\left",
6780
+ DELIMITERS_SHORTHAND[open] ?? open,
6781
+ "\\begin{array}",
6782
+ `{${columns}}`,
6783
+ tabular,
6784
+ "\\end{array}",
6785
+ "\\right",
6786
+ DELIMITERS_SHORTHAND[close] ?? close
6787
+ ]);
6788
+ }
6789
+ return joinLatex(["\\begin{matrix}", tabular, "\\end{matrix}"]);
6790
+ }
6416
6791
  }
6417
6792
  ];
6418
6793
 
@@ -6566,7 +6941,15 @@ var DEFINITIONS_LOGIC = [
6566
6941
  kind: "infix",
6567
6942
  associativity: "right",
6568
6943
  precedence: 219,
6569
- parse: "Equivalent"
6944
+ parse: (parser, lhs, terminator) => {
6945
+ const rhs = parser.parseExpression({ ...terminator, minPrec: 219 });
6946
+ const index = parser.index;
6947
+ const modulus = parser.parseExpression({ ...terminator, minPrec: 219 });
6948
+ if (modulus && head(modulus) === "Mod")
6949
+ return ["Congruent", lhs, rhs, missingIfEmpty(op(modulus, 1))];
6950
+ parser.index = index;
6951
+ return ["Equivalent", lhs, missingIfEmpty(rhs)];
6952
+ }
6570
6953
  },
6571
6954
  {
6572
6955
  name: "Proves",
@@ -7319,6 +7702,9 @@ var DEFINITIONS_SETS = [
7319
7702
  parse: (_parser, body) => {
7320
7703
  if (body === null || isEmptySequence(body))
7321
7704
  return "EmptySet";
7705
+ if (head(body) == "Delimiter" && stringValue(op(body, 2)) === ",") {
7706
+ body = op(body, 1);
7707
+ }
7322
7708
  if (head(body) !== "Sequence")
7323
7709
  return ["Set", body];
7324
7710
  return ["Set", ...ops(body) ?? []];
@@ -7343,7 +7729,7 @@ var DEFINITIONS_SETS = [
7343
7729
  // or \\ominus
7344
7730
  kind: "infix",
7345
7731
  // @todo: parser could check that lhs and rhs are sets
7346
- precedence: 260
7732
+ precedence: COMPARISON_PRECEDENCE
7347
7733
  },
7348
7734
  // Predicates/Relations
7349
7735
  {
@@ -7677,7 +8063,10 @@ function parseIntegralBodyExpression(expr) {
7677
8063
  const op12 = op(expr, 1);
7678
8064
  if (!op12)
7679
8065
  return [expr, null];
7680
- if (h === "Multiply") {
8066
+ if (h === "Sequence" && nops(expr) === 1) {
8067
+ return parseIntegralBodyExpression(op12);
8068
+ }
8069
+ if (h === "Multiply" || h === "InvisibleOperator") {
7681
8070
  const args = ops(expr);
7682
8071
  if (args && args.length > 1) {
7683
8072
  const sym = symbol(args[args.length - 2]);
@@ -7700,7 +8089,7 @@ function parseIntegralBodyExpression(expr) {
7700
8089
  if (index) {
7701
8090
  if (!fn2)
7702
8091
  return [null, index];
7703
- return [["Delimiter", fn2, ...ops(expr).slice(1)], index];
8092
+ return [["Delimiter", ["Sequence", fn2], ...ops(expr).slice(1)], index];
7704
8093
  }
7705
8094
  } else if (h === "Add") {
7706
8095
  const args = ops(expr);
@@ -8443,25 +8832,26 @@ function isValidEntry(entry, onError) {
8443
8832
  return true;
8444
8833
  }
8445
8834
  var DEFAULT_LATEX_DICTIONARY = {
8446
- algebra: DEFINITIONS_ALGEBRA,
8447
- arithmetic: DEFINITIONS_ARITHMETIC,
8448
- calculus: DEFINITIONS_CALCULUS,
8449
- complex: DEFINITIONS_COMPLEX,
8450
- core: DEFINITIONS_CORE,
8451
- logic: DEFINITIONS_LOGIC,
8452
- relop: DEFINITIONS_INEQUALITIES,
8453
- other: DEFINITIONS_OTHERS,
8454
- physics: [
8835
+ "algebra": DEFINITIONS_ALGEBRA,
8836
+ "arithmetic": DEFINITIONS_ARITHMETIC,
8837
+ "calculus": DEFINITIONS_CALCULUS,
8838
+ "complex": DEFINITIONS_COMPLEX,
8839
+ "core": DEFINITIONS_CORE,
8840
+ "linear-algebra": DEFINITIONS_LINEAR_ALGEBRA,
8841
+ "logic": DEFINITIONS_LOGIC,
8842
+ "relop": DEFINITIONS_INEQUALITIES,
8843
+ "other": DEFINITIONS_OTHERS,
8844
+ "physics": [
8455
8845
  {
8456
8846
  name: "mu0",
8457
8847
  kind: "symbol",
8458
8848
  latexTrigger: "\\mu_0"
8459
8849
  }
8460
8850
  ],
8461
- sets: DEFINITIONS_SETS,
8462
- statistics: DEFINITIONS_STATISTICS,
8463
- symbols: DEFINITIONS_SYMBOLS,
8464
- trigonometry: DEFINITIONS_TRIGONOMETRY
8851
+ "sets": DEFINITIONS_SETS,
8852
+ "statistics": DEFINITIONS_STATISTICS,
8853
+ "symbols": DEFINITIONS_SYMBOLS,
8854
+ "trigonometry": DEFINITIONS_TRIGONOMETRY
8465
8855
  };
8466
8856
 
8467
8857
  // src/compute-engine/latex-syntax/parse-identifier.ts
@@ -8775,7 +9165,6 @@ var DEFAULT_LATEX_NUMBER_OPTIONS = {
8775
9165
  avoidExponentsInRange: [-7, 20]
8776
9166
  };
8777
9167
  var DEFAULT_PARSE_LATEX_OPTIONS = {
8778
- applyInvisibleOperator: "auto",
8779
9168
  skipSpace: true,
8780
9169
  parseArgumentsOfUnknownLatexCommands: true,
8781
9170
  parseNumbers: "auto",
@@ -9179,11 +9568,12 @@ var _Parser = class {
9179
9568
  this.skipSpace();
9180
9569
  if (this.matchBoundary())
9181
9570
  return expr ?? ["Sequence"];
9182
- const from = this.index;
9183
9571
  while (!this.matchBoundary() && !this.atEnd)
9184
9572
  this.nextToken();
9185
- const err = this.error("syntax-error", from);
9186
- return expr ? ["Sequence", expr, err] : err;
9573
+ if (head(expr) === "Error")
9574
+ return expr;
9575
+ const err = this.error("expected-closing-delimiter", start);
9576
+ return expr ? ["InvisibleOperator", expr, err] : err;
9187
9577
  }
9188
9578
  this.index = start;
9189
9579
  return null;
@@ -9330,7 +9720,7 @@ var _Parser = class {
9330
9720
  }
9331
9721
  parseDecimalDigits(options) {
9332
9722
  options ?? (options = {});
9333
- options.withGrouping ?? (options.withGrouping = false);
9723
+ options.withGrouping ?? (options.withGrouping = true);
9334
9724
  const result = [];
9335
9725
  let done = false;
9336
9726
  while (!done) {
@@ -9355,7 +9745,7 @@ var _Parser = class {
9355
9745
  }
9356
9746
  parseSignedInteger(options) {
9357
9747
  options ?? (options = {});
9358
- options.withGrouping ?? (options.withGrouping = false);
9748
+ options.withGrouping ?? (options.withGrouping = true);
9359
9749
  const start = this.index;
9360
9750
  const sign2 = this.parseOptionalSign();
9361
9751
  const result = this.parseDecimalDigits(options);
@@ -9395,7 +9785,7 @@ var _Parser = class {
9395
9785
  this.skipSpaceTokens();
9396
9786
  if (this.matchAll(this._beginExponentMarkerTokens)) {
9397
9787
  this.skipSpaceTokens();
9398
- const exponent = this.parseSignedInteger();
9788
+ const exponent = this.parseSignedInteger({ withGrouping: false });
9399
9789
  this.skipSpaceTokens();
9400
9790
  if (this.matchAll(this._endExponentMarkerTokens) && exponent)
9401
9791
  return exponent;
@@ -9450,7 +9840,14 @@ var _Parser = class {
9450
9840
  return null;
9451
9841
  const start = this.index;
9452
9842
  this.skipVisualSpace();
9453
- this.match("+");
9843
+ let sign2 = 1;
9844
+ while (this.peek === "-" || this.peek === "+") {
9845
+ if (this.match("-"))
9846
+ sign2 *= -1;
9847
+ else
9848
+ this.match("+");
9849
+ this.skipVisualSpace();
9850
+ }
9454
9851
  let wholePart = "";
9455
9852
  let fractionalPart = "";
9456
9853
  let startsWithDecimalMarker = false;
@@ -9461,21 +9858,17 @@ var _Parser = class {
9461
9858
  wholePart = "0";
9462
9859
  }
9463
9860
  } else
9464
- wholePart = this.parseDecimalDigits({ withGrouping: true });
9861
+ wholePart = this.parseDecimalDigits();
9465
9862
  if (!wholePart) {
9466
9863
  this.index = start;
9467
9864
  return null;
9468
9865
  }
9469
9866
  const fractionalIndex = this.index;
9470
- let hasFractionalPart = true;
9867
+ let hasFractionalPart = false;
9471
9868
  if (startsWithDecimalMarker || this.match(".") || this.matchAll(this._decimalMarkerTokens)) {
9472
- fractionalPart = this.parseDecimalDigits({ withGrouping: true });
9473
- if (!fractionalPart) {
9474
- this.index = fractionalIndex;
9475
- return { num: wholePart };
9476
- }
9477
- } else
9478
- hasFractionalPart = false;
9869
+ fractionalPart = this.parseDecimalDigits();
9870
+ hasFractionalPart = true;
9871
+ }
9479
9872
  let hasRepeatingPart = false;
9480
9873
  if (hasFractionalPart) {
9481
9874
  const repeat = this.parseRepeatingDecimal();
@@ -9485,14 +9878,18 @@ var _Parser = class {
9485
9878
  } else if (this.match("\\ldots") || this.matchAll(this._truncationMarkerTokens)) {
9486
9879
  }
9487
9880
  }
9881
+ if (hasFractionalPart && !fractionalPart) {
9882
+ this.index = fractionalIndex;
9883
+ return { num: sign2 < 0 ? "-" + wholePart : wholePart };
9884
+ }
9488
9885
  this.skipVisualSpace();
9489
9886
  const exponent = this.parseExponent();
9490
9887
  if (!hasRepeatingPart && this.options.parseNumbers === "rational") {
9491
9888
  const whole = parseInt(wholePart, 10);
9492
9889
  if (!fractionalPart) {
9493
9890
  if (exponent)
9494
- return ["Multiply", whole, ["Power", 10, exponent]];
9495
- return whole;
9891
+ return ["Multiply", sign2 * whole, ["Power", 10, exponent]];
9892
+ return sign2 * whole;
9496
9893
  }
9497
9894
  const fraction = parseInt(fractionalPart, 10);
9498
9895
  const n = fractionalPart.length;
@@ -9501,14 +9898,14 @@ var _Parser = class {
9501
9898
  if (exponent) {
9502
9899
  return [
9503
9900
  "Multiply",
9504
- ["Rational", numerator, denominator],
9901
+ ["Rational", sign2 * numerator, denominator],
9505
9902
  ["Power", 10, exponent]
9506
9903
  ];
9507
9904
  }
9508
- return ["Rational", numerator, denominator];
9905
+ return ["Rational", sign2 * numerator, denominator];
9509
9906
  }
9510
9907
  return {
9511
- num: wholePart + (hasFractionalPart ? "." + fractionalPart : "") + (exponent ? "e" + exponent : "")
9908
+ num: (sign2 < 0 ? "-" : "") + wholePart + (hasFractionalPart ? "." + fractionalPart : "") + (exponent ? "e" + exponent : "")
9512
9909
  };
9513
9910
  }
9514
9911
  /**
@@ -9636,8 +10033,13 @@ var _Parser = class {
9636
10033
  return getSequence(group) ?? [];
9637
10034
  }
9638
10035
  if (kind === "implicit") {
9639
- if (head(group) === "Delimiter")
9640
- return getSequence(group) ?? [];
10036
+ if (head(group) === "Delimiter") {
10037
+ if (head(op1(group)) === "Sequence") {
10038
+ const seq = op1(op1(group));
10039
+ return seq ? [seq] : [];
10040
+ }
10041
+ return op1(group) ? [op1(group)] : [];
10042
+ }
9641
10043
  if (group !== null)
9642
10044
  return [group];
9643
10045
  const primary = this.parseExpression({ ...until, minPrec: 390 });
@@ -9896,7 +10298,7 @@ var _Parser = class {
9896
10298
  );
9897
10299
  if (defs) {
9898
10300
  const nonEmptySuperscripts = superscripts.filter(
9899
- (x) => head(x) !== "Sequence"
10301
+ (x) => !(head(x) === "Sequence" && nops(x) === 0)
9900
10302
  );
9901
10303
  if (nonEmptySuperscripts.length !== 0) {
9902
10304
  const superscriptExpression = nonEmptySuperscripts.length === 1 ? nonEmptySuperscripts[0] : ["List", ...nonEmptySuperscripts];
@@ -9965,75 +10367,6 @@ var _Parser = class {
9965
10367
  }
9966
10368
  return result;
9967
10369
  }
9968
- /**
9969
- * Apply an invisible operator between two expressions.
9970
- *
9971
- * If the `lhs` is an literal integer and the `rhs` is a literal rational
9972
- * -> 'invisible plus'
9973
- *
9974
- * That is '2 3/4' -> ['Add', 2, ['Rational', 3, 4]]
9975
- *
9976
- * If `lhs` is a number and `rhs` is a number but not a literal -> 'invisible multiply'.
9977
- * - 2x
9978
- * - 2(x+1)
9979
- * - x(x+1)
9980
- * - f(x)g(y)
9981
- * - 2 sin(x)
9982
- * - 2 f(x)
9983
- * - x f(x)
9984
- * - (x-1)(x+1)
9985
- * - (x+1)2 -> no
9986
- * - x2 -> no
9987
- * => lhs is a number, rhs is a number, but not a literal
9988
- */
9989
- applyInvisibleOperator(until, lhs) {
9990
- if (lhs === null || this.options.applyInvisibleOperator === null || head(lhs) === "Error" || symbol(lhs) === "Nothing" || isEmptySequence(lhs) || this.atTerminator(until))
9991
- return null;
9992
- if (this.peekDefinitions("operator").length > 0)
9993
- return null;
9994
- if (this.isFunctionHead(lhs)) {
9995
- const args = this.parseArguments("enclosure", { ...until, minPrec: 0 });
9996
- if (args === null)
9997
- return null;
9998
- return [lhs, ...args];
9999
- }
10000
- const start = this.index;
10001
- const rhs = this.parseExpression({ ...until, minPrec: 390 });
10002
- if (rhs === null || symbol(rhs) === "Nothing" || isEmptySequence(rhs)) {
10003
- this.index = start;
10004
- return null;
10005
- }
10006
- if (head(rhs) === "Error")
10007
- return applyAssociativeOperator("Sequence", lhs, rhs);
10008
- if (typeof this.options.applyInvisibleOperator === "function")
10009
- return this.options.applyInvisibleOperator(this, lhs, rhs);
10010
- if (this.isFunctionHead(lhs)) {
10011
- const seq = getSequence(rhs);
10012
- return seq ? [lhs, ...seq] : lhs;
10013
- }
10014
- const lhsNumber = machineValue(lhs);
10015
- if (lhsNumber !== null && Number.isInteger(lhsNumber)) {
10016
- const rhsHead = head(rhs);
10017
- if (rhsHead === "Divide" || rhsHead === "Rational") {
10018
- const [n, d] = [machineValue(op(rhs, 1)), machineValue(op(rhs, 2))];
10019
- if (n !== null && d !== null && n > 0 && n <= 1e3 && d > 1 && d <= 1e3 && Number.isInteger(n) && Number.isInteger(d))
10020
- return ["Add", lhs, rhs];
10021
- }
10022
- }
10023
- if (head(rhs) === "Delimiter") {
10024
- if (head(op(rhs, 1)) === "Sequence")
10025
- return [lhs, ...ops(op(rhs, 1)) ?? []];
10026
- if (!op(rhs, 1) || symbol(op(rhs, 1)) === "Nothing")
10027
- return applyAssociativeOperator(
10028
- "Sequence",
10029
- lhs,
10030
- this.error("expected-expression", start)
10031
- );
10032
- }
10033
- if (head(rhs) === "Sequence" || head(lhs) === "Sequence" || stringValue(lhs) !== null || stringValue(rhs) !== null || dictionary(lhs) !== null || dictionary(rhs) !== null)
10034
- return applyAssociativeOperator("Sequence", lhs, rhs);
10035
- return applyAssociativeOperator("Multiply", lhs, rhs);
10036
- }
10037
10370
  /**
10038
10371
  * This method can be invoked when we know we're in an error situation.
10039
10372
  *
@@ -10239,7 +10572,23 @@ var _Parser = class {
10239
10572
  this.skipSpace();
10240
10573
  let result = this.parseInfixOperator(lhs, until);
10241
10574
  if (result === null) {
10242
- result = this.applyInvisibleOperator(until, lhs);
10575
+ if (this.peekDefinitions("operator").length === 0) {
10576
+ const rhs = this.parseExpression({
10577
+ ...until,
10578
+ minPrec: MULTIPLICATION_PRECEDENCE
10579
+ });
10580
+ if (rhs !== null) {
10581
+ if (head(lhs) === "InvisibleOperator") {
10582
+ if (head(rhs) === "InvisibleOperator")
10583
+ result = ["InvisibleOperator", ...ops(lhs), ...ops(rhs)];
10584
+ else
10585
+ result = ["InvisibleOperator", ...ops(lhs), rhs];
10586
+ } else if (head(rhs) === "InvisibleOperator") {
10587
+ result = ["InvisibleOperator", lhs, ...ops(rhs)];
10588
+ } else
10589
+ result = ["InvisibleOperator", lhs, rhs];
10590
+ }
10591
+ }
10243
10592
  }
10244
10593
  if (result !== null) {
10245
10594
  lhs = result;
@@ -10248,11 +10597,6 @@ var _Parser = class {
10248
10597
  }
10249
10598
  }
10250
10599
  }
10251
- if (!lhs) {
10252
- lhs = this.parseSyntaxError();
10253
- while (!this.atTerminator(until))
10254
- this.nextToken();
10255
- }
10256
10600
  return this.decorate(lhs, start);
10257
10601
  }
10258
10602
  /**
@@ -10578,7 +10922,7 @@ var STYLE_MODIFIERS = {
10578
10922
  sansserif: (s) => `\\mathsf{${s}}`,
10579
10923
  monospace: (s) => `\\mathtt{${s}}`
10580
10924
  };
10581
- var Serializer2 = class {
10925
+ var Serializer4 = class {
10582
10926
  constructor(options, dictionary2, onError) {
10583
10927
  this.level = -1;
10584
10928
  this.options = options;
@@ -10660,10 +11004,24 @@ var Serializer2 = class {
10660
11004
  return s;
10661
11005
  if (fence === void 0)
10662
11006
  fence = "()";
10663
- const openFence = fence?.[0] ?? ".";
10664
- const closeFence = fence?.[1] ?? ".";
11007
+ let openFence = fence?.[0] ?? ".";
11008
+ let closeFence = fence?.[1] ?? ".";
10665
11009
  if ((openFence === "." || closeFence === ".") && style === "paren")
10666
11010
  style = "leftright";
11011
+ if (openFence === '"')
11012
+ openFence = "``";
11013
+ else if (openFence === "|")
11014
+ openFence = "\\lvert";
11015
+ else
11016
+ openFence = DELIMITERS_SHORTHAND[openFence] ?? openFence;
11017
+ if (closeFence === '"')
11018
+ closeFence = "''";
11019
+ else if (closeFence === "|")
11020
+ closeFence = "\\rvert";
11021
+ else
11022
+ closeFence = DELIMITERS_SHORTHAND[closeFence] ?? closeFence;
11023
+ if (openFence === "." && closeFence === ".")
11024
+ return s;
10667
11025
  if (style === "leftright")
10668
11026
  return `\\left${openFence}${s}\\right${closeFence}}`;
10669
11027
  if (style === "big")
@@ -11056,7 +11414,7 @@ var LatexSyntax = class _LatexSyntax {
11056
11414
  get serializer() {
11057
11415
  if (this._serializer)
11058
11416
  return this._serializer;
11059
- this._serializer = new Serializer2(
11417
+ this._serializer = new Serializer4(
11060
11418
  this.options,
11061
11419
  this._dictionary,
11062
11420
  this.onError
@@ -13520,11 +13878,19 @@ function flattenOps(ops2, head2) {
13520
13878
  return result;
13521
13879
  }
13522
13880
  function flattenSequence(xs) {
13523
- if (xs.every((x) => x.head !== "Sequence"))
13881
+ if (xs.every((x) => x.head !== "Sequence" && x.head !== "Delimiter"))
13524
13882
  return xs;
13525
13883
  const ys = [];
13526
13884
  for (const x of xs) {
13527
- if (x.isValid && x.head === "Sequence") {
13885
+ if (!x.isValid)
13886
+ ys.push(x);
13887
+ else if (x.head === "Delimiter") {
13888
+ const seq = x.op1.ops ?? [];
13889
+ if (seq.length === 0)
13890
+ ys.push(x.engine.box(["Tupple"]));
13891
+ else
13892
+ ys.push(...flattenSequence(seq));
13893
+ } else if (x.head === "Sequence") {
13528
13894
  if (x.ops)
13529
13895
  ys.push(...x.ops);
13530
13896
  } else
@@ -13870,7 +14236,7 @@ var DOMAIN_ALIAS = {
13870
14236
  LogicOperators: [
13871
14237
  "FunctionOf",
13872
14238
  "Booleans",
13873
- ["OptArg", "Booleans"],
14239
+ ["VarArg", "Booleans"],
13874
14240
  "Booleans"
13875
14241
  ],
13876
14242
  Predicates: ["FunctionOf", "Anything", ["VarArg", "Anything"], "Booleans"],
@@ -14190,7 +14556,7 @@ function checkArity(ce, ops2, count) {
14190
14556
  }
14191
14557
  function checkNumericArgs(ce, ops2, options) {
14192
14558
  let count = typeof options === "number" ? options : options?.count;
14193
- const flatten = typeof options === "number" ? true : options?.flatten ?? true;
14559
+ const flatten = typeof options === "number" || (options?.flatten ?? true);
14194
14560
  ops2 = canonical(ops2);
14195
14561
  if (flatten)
14196
14562
  ops2 = flattenSequence(ops2);
@@ -14251,7 +14617,7 @@ function checkNumericArgs(ce, ops2, options) {
14251
14617
  x.infer(ce.Numbers);
14252
14618
  return xs;
14253
14619
  }
14254
- function checkArg(ce, arg, dom) {
14620
+ function checkDomain(ce, arg, dom) {
14255
14621
  if (arg === void 0 || arg === null)
14256
14622
  return ce.error("missing");
14257
14623
  if (dom === void 0)
@@ -14265,12 +14631,22 @@ function checkArg(ce, arg, dom) {
14265
14631
  return arg;
14266
14632
  return ce.domainError(dom, arg.domain, arg);
14267
14633
  }
14268
- function checkArgs(ce, args, doms) {
14634
+ function checkPure(ce, arg) {
14635
+ if (arg === void 0 || arg === null)
14636
+ return ce.error("missing");
14637
+ arg = arg.canonical;
14638
+ if (!arg.isValid)
14639
+ return arg;
14640
+ if (arg.isPure)
14641
+ return arg;
14642
+ return ce.error("expected-pure-expression", arg);
14643
+ }
14644
+ function checkDomains(ce, args, doms) {
14269
14645
  if (args.length === doms.length && args.every((x, i) => !x.domain || x.domain.isCompatible(doms[i])))
14270
14646
  return args;
14271
14647
  const xs = [];
14272
14648
  for (let i = 0; i <= doms.length - 1; i++)
14273
- xs.push(checkArg(ce, args[i], doms[i]));
14649
+ xs.push(checkDomain(ce, args[i], doms[i]));
14274
14650
  for (let i = doms.length; i <= args.length - 1; i++)
14275
14651
  xs.push(ce.error("unexpected-argument", args[i]));
14276
14652
  return xs;
@@ -14446,9 +14822,9 @@ function canonicalLimits(limits) {
14446
14822
  } else
14447
14823
  index = ce.domainError("Symbols", index.domain, index);
14448
14824
  if (lower && lower.isFinite)
14449
- lower = checkArg(ce, lower, "Integers");
14825
+ lower = checkDomain(ce, lower, "Integers");
14450
14826
  if (upper && upper.isFinite)
14451
- upper = checkArg(ce, upper, "Integers");
14827
+ upper = checkDomain(ce, upper, "Integers");
14452
14828
  if (lower && upper)
14453
14829
  return ce.tuple([index, lower, upper]);
14454
14830
  if (upper)
@@ -14537,7 +14913,11 @@ var NATIVE_JS_FUNCTIONS = {
14537
14913
  Limit: (args, compile2) => `_SYS.limit(${compile2(args[0])}, ${compile2(args[1])})`,
14538
14914
  Ln: "Math.log",
14539
14915
  List: (args, compile2) => `[${args.map((x) => compile2(x)).join(", ")}]`,
14540
- Log: "Math.log10",
14916
+ Log: (args, compile2) => {
14917
+ if (args.length === 1)
14918
+ return `Math.log(${compile2(args[0])})`;
14919
+ return `(Math.log(${compile2(args[0])}) / Math.log(${compile2(args[1])}))`;
14920
+ },
14541
14921
  LogGamma: "_SYS.lngamma",
14542
14922
  Lb: "Math.log2",
14543
14923
  Max: "Math.max",
@@ -14773,6 +15153,12 @@ function compileExpr(h, args, prec, target) {
14773
15153
  return compileLoop(h, args, target);
14774
15154
  if (args.every((x) => !isCollection(x))) {
14775
15155
  const op3 = target.operators?.(h);
15156
+ if ((h === "NotEqual" || h === "Equal" || h === "Less" || h === "Greater" || h === "LessEqual" || h === "GreaterEqual") && args.length > 2 && op3) {
15157
+ const result = [];
15158
+ for (let i = 0; i < args.length - 1; i++)
15159
+ result.push(compileExpr(h, [args[i], args[i + 1]], op3[1], target));
15160
+ return `(${result.join(") && (")})`;
15161
+ }
14776
15162
  if (op3 !== void 0) {
14777
15163
  if (args === null)
14778
15164
  return "";
@@ -14787,7 +15173,7 @@ function compileExpr(h, args, prec, target) {
14787
15173
  }
14788
15174
  if (h === "Function") {
14789
15175
  const params = args.slice(1).map((x) => x.symbol);
14790
- return `((${params.join(", ")}) => ${compile(args[0], {
15176
+ return `((${params.join(", ")}) => ${compile(args[0].canonical, {
14791
15177
  ...target,
14792
15178
  var: (id) => params.includes(id) ? id : target.var(id)
14793
15179
  })})`;
@@ -19866,6 +20252,12 @@ var ARITHMETIC_LIBRARY = [
19866
20252
  complexity: 9e3,
19867
20253
  signature: {
19868
20254
  domain: ["FunctionOf", "Numbers", "Numbers"],
20255
+ canonical: (ce, args) => {
20256
+ const base = args[0];
20257
+ if (base instanceof BoxedNumber && base.isNegative)
20258
+ return ce.neg(ce._fn("Factorial", [ce.neg(base)]));
20259
+ return ce._fn("Factorial", [base]);
20260
+ },
19869
20261
  evaluate: (ce, ops2) => {
19870
20262
  const n = asSmallInteger(ops2[0]);
19871
20263
  if (n !== null && n >= 0) {
@@ -19964,7 +20356,7 @@ var ARITHMETIC_LIBRARY = [
19964
20356
  domain: ["FunctionOf", "Numbers", ["OptArg", "Numbers"], "Numbers"],
19965
20357
  canonical: (ce, ops2) => {
19966
20358
  if (ops2.length === 1)
19967
- return ce._fn("Log", [checkArg(ce, ops2[0], "Numbers")]);
20359
+ return ce._fn("Log", [checkDomain(ce, ops2[0], "Numbers")]);
19968
20360
  ops2 = checkNumericArgs(ce, ops2, 2);
19969
20361
  if (ops2.length !== 2)
19970
20362
  return ce._fn("Log", ops2);
@@ -20021,6 +20413,27 @@ var ARITHMETIC_LIBRARY = [
20021
20413
  )
20022
20414
  }
20023
20415
  },
20416
+ Mod: {
20417
+ description: "Modulo",
20418
+ wikidata: "Q1799665",
20419
+ complexity: 2500,
20420
+ threadable: true,
20421
+ signature: {
20422
+ domain: ["FunctionOf", "Numbers", "Numbers", "Numbers"],
20423
+ evaluate: (ce, ops2) => {
20424
+ if (ops2.length !== 2)
20425
+ return void 0;
20426
+ const [lhs, rhs] = ops2;
20427
+ const nLhs = lhs.value;
20428
+ const nRhs = rhs.value;
20429
+ if (typeof nLhs !== "number")
20430
+ return void 0;
20431
+ if (typeof nRhs !== "number")
20432
+ return void 0;
20433
+ return ce.number((nLhs % nRhs + nRhs) % nRhs);
20434
+ }
20435
+ }
20436
+ },
20024
20437
  Multiply: {
20025
20438
  wikidata: "Q40276",
20026
20439
  associative: true,
@@ -20098,7 +20511,10 @@ var ARITHMETIC_LIBRARY = [
20098
20511
  args = checkNumericArgs(ce, args, 2);
20099
20512
  if (args.length !== 2)
20100
20513
  return ce._fn("Power", args);
20101
- return ce.pow(args[0], args[1]);
20514
+ const [base, exp2] = args;
20515
+ if (base instanceof BoxedNumber && base.isNegative)
20516
+ return ce.neg(ce.pow(base, exp2));
20517
+ return ce.pow(base, exp2);
20102
20518
  },
20103
20519
  simplify: (ce, ops2) => processPower(ce, ops2[0], ops2[1], "simplify"),
20104
20520
  evaluate: (ce, ops2) => processPower(ce, ops2[0], ops2[1], "evaluate"),
@@ -20132,9 +20548,9 @@ var ARITHMETIC_LIBRARY = [
20132
20548
  return ce._fn("Rational", [ce.error("missing")]);
20133
20549
  if (args.length === 1)
20134
20550
  return ce._fn("Rational", [
20135
- checkArg(ce, args[0], "ExtendedRealNumbers")
20551
+ checkDomain(ce, args[0], "ExtendedRealNumbers")
20136
20552
  ]);
20137
- args = checkArgs(ce, args, ["Integers", "Integers"]);
20553
+ args = checkDomains(ce, args, ["Integers", "Integers"]);
20138
20554
  if (args.length !== 2 || !args[0].isValid || !args[1].isValid)
20139
20555
  return ce._fn("Rational", args);
20140
20556
  return ce.div(args[0], args[1]);
@@ -20295,7 +20711,7 @@ var ARITHMETIC_LIBRARY = [
20295
20711
  domain: ["FunctionOf", "Numbers", ["OptArg", "Numbers"], "Numbers"],
20296
20712
  canonical: (ce, args) => {
20297
20713
  if (args.length === 1) {
20298
- const x = checkArg(ce, args[0], "Numbers");
20714
+ const x = checkDomain(ce, args[0], "Numbers");
20299
20715
  if (x.isValid)
20300
20716
  return ce.neg(x);
20301
20717
  }
@@ -21346,7 +21762,6 @@ var CALCULUS_LIBRARY = [
21346
21762
  "Numbers"
21347
21763
  ],
21348
21764
  canonical: (ce, ops2) => {
21349
- const body = ops2[0] ?? ce.error("missing");
21350
21765
  let range = ops2[1];
21351
21766
  let index = null;
21352
21767
  let lower = null;
@@ -21366,9 +21781,9 @@ var CALCULUS_LIBRARY = [
21366
21781
  if (!index.symbol)
21367
21782
  index = ce.domainError("Symbols", index.domain, index);
21368
21783
  if (lower)
21369
- lower = checkArg(ce, lower, ce.Numbers);
21784
+ lower = checkDomain(ce, lower, ce.Numbers);
21370
21785
  if (upper)
21371
- upper = checkArg(ce, upper, ce.Numbers);
21786
+ upper = checkDomain(ce, upper, ce.Numbers);
21372
21787
  if (lower && upper)
21373
21788
  range = ce.tuple([index, lower, upper]);
21374
21789
  else if (upper)
@@ -21377,7 +21792,11 @@ var CALCULUS_LIBRARY = [
21377
21792
  range = ce.tuple([index, lower]);
21378
21793
  else
21379
21794
  range = index;
21380
- return ce._fn("Integrate", [body.canonical, range]);
21795
+ let body = ops2[0] ?? ce.error("missing");
21796
+ body = body.canonical;
21797
+ if (body.head === "Delimiter" && body.op1.head === "Sequence")
21798
+ body = body.op1.op1;
21799
+ return ce._fn("Integrate", [body, range]);
21381
21800
  }
21382
21801
  }
21383
21802
  },
@@ -21410,15 +21829,12 @@ var COLLECTIONS_LIBRARY = {
21410
21829
  //
21411
21830
  // Data Structures
21412
21831
  //
21413
- Sequence: {
21414
- signature: {
21415
- domain: "Functions"
21416
- }
21417
- },
21418
21832
  List: {
21419
21833
  complexity: 8200,
21834
+ hold: "all",
21420
21835
  signature: {
21421
- domain: ["FunctionOf", ["VarArg", "Anything"], "Lists"]
21836
+ domain: ["FunctionOf", ["VarArg", "Anything"], "Lists"],
21837
+ canonical: canonicalList
21422
21838
  },
21423
21839
  size: (expr) => expr.nops,
21424
21840
  iterator: (expr, start, count) => {
@@ -21573,7 +21989,7 @@ var COLLECTIONS_LIBRARY = {
21573
21989
  signature: {
21574
21990
  domain: ["FunctionOf", "Strings", "Anything", "Tuples"],
21575
21991
  canonical: (ce, args) => {
21576
- const [key, value] = checkArgs(ce, args, [ce.Strings, "Values"]);
21992
+ const [key, value] = checkDomains(ce, args, [ce.Strings, "Values"]);
21577
21993
  if (!key.isValid || !value.isValid)
21578
21994
  return ce._fn("KeyValuePair", [key, value]);
21579
21995
  return ce.tuple([key, value]);
@@ -22159,6 +22575,17 @@ function indexes(ranges) {
22159
22575
  }
22160
22576
  return result;
22161
22577
  }
22578
+ function canonicalList(ce, ops2) {
22579
+ ops2 = ops2.map((op3) => {
22580
+ if (op3.head === "Delimiter") {
22581
+ if (op3.op1.head === "Sequence")
22582
+ return ce._fn("List", canonical(op3.op1.ops));
22583
+ return ce._fn("List", [op3.op1?.canonical ?? ce.Nothing]);
22584
+ }
22585
+ return op3.canonical;
22586
+ });
22587
+ return ce._fn("List", ops2);
22588
+ }
22162
22589
 
22163
22590
  // src/compute-engine/library/control-structures.ts
22164
22591
  var CONTROL_STRUCTURES_LIBRARY = [
@@ -22594,19 +23021,160 @@ var CORE_LIBRARY = [
22594
23021
  // Inert functions
22595
23022
  //
22596
23023
  {
23024
+ /**
23025
+ * ## THEORY OF OPERATIONS: SEQUENCES
23026
+ *
23027
+ * There are two similar functions used to represent sequences of
23028
+ * expressions:
23029
+ *
23030
+ * - `InvisibleOperator` represent a sequence of expressions
23031
+ * that are syntactically juxtaposed without any separator or
23032
+ * operators combining them. For example, `2x` is represented as
23033
+ * `["InvisibleOperator", 2, "x"]`. `InvisibleOperator` gets
23034
+ * transformed into `Multiply` (or some other semantic operation)
23035
+ * during canonicalization.
23036
+ *
23037
+ * - `Sequence` is used to represent a sequence of expressions
23038
+ * at a semantic level. It is a collection, but it is handled
23039
+ * specially when canonicalizing expressions, for example it
23040
+ * is automatically flattened and hoisted to the top level of the
23041
+ * argument list.
23042
+ * For example:
23043
+ * `["Add", "a", ["Sequence", "b", "c"]]` is canonicalized
23044
+ * to `["Add", "a", "b", "c"]`.
23045
+ *
23046
+ * The empty `Sequence` expression (i.e. `["Sequence"]`) is ignored
23047
+ * but it can be used to represent an "empty" expression.
23048
+ *
23049
+ * - `Delimiter` is used to represent a group of expressions
23050
+ * with an open and close delimiter and separator. They capture the
23051
+ * input syntax, and can get transformed into other expressions
23052
+ * during boxing and canonicalization.
23053
+ * The first argument is a function expression, such as `List`
23054
+ * or `Sequence`. The arguments of that expression are represented
23055
+ * with a separator between them and delimiters around the whole
23056
+ * group.
23057
+ * The second argument specify the separator and delimiters. If not
23058
+ * specified, the default is the string `"(,)"`
23059
+ *
23060
+ * Examples:
23061
+ * - `f(x)` ->
23062
+ * `["InvisibleOperator",
23063
+ * "f",
23064
+ * ["Delimiter", ["Sequence", "x"], "'(,)'"]
23065
+ * ]`
23066
+ *
23067
+ * - `1, 2; 3, 4` ->
23068
+ * `["Delimiter",
23069
+ * ["Sequence",
23070
+ * ["Delimiter", ["Sequence", 1, 2], "','"],
23071
+ * ["Delimiter", ["Sequence", 3, 4], "','"],
23072
+ * ],
23073
+ * "';'"
23074
+ * ]`
23075
+ *
23076
+ * - `2x` -> `["InvisibleOperator", 2, "x"]`
23077
+ *
23078
+ * - `2+` -> `["InvisibleOperator", 2, ["Error", "'unexpected-operator'", "+"]]`
23079
+ *
23080
+ *
23081
+ *
23082
+ *
23083
+ */
23084
+ InvisibleOperator: {
23085
+ complexity: 9e3,
23086
+ hold: "all",
23087
+ signature: {
23088
+ restParam: "Anything",
23089
+ result: (ce, args) => {
23090
+ if (args.length === 0)
23091
+ return ce.domain("NothingDomain");
23092
+ if (args.length === 1)
23093
+ return args[0].domain;
23094
+ return ce.Anything;
23095
+ },
23096
+ canonical: canonicalInvisibleOperator
23097
+ }
23098
+ },
23099
+ /** See above for a theory of operations */
23100
+ Sequence: {
23101
+ hold: "all",
23102
+ signature: {
23103
+ restParam: "Anything",
23104
+ result: (ce, args) => {
23105
+ if (args.length === 0)
23106
+ return ce.domain("NothingDomain");
23107
+ if (args.length === 1)
23108
+ return args[0].domain;
23109
+ return ce.Anything;
23110
+ },
23111
+ canonical: (ce, args) => {
23112
+ const xs = canonical(flattenSequence(args));
23113
+ if (xs.length === 0)
23114
+ return ce._fn("Sequence", []);
23115
+ if (xs.length === 1)
23116
+ return xs[0];
23117
+ return ce._fn("Sequence", xs);
23118
+ }
23119
+ }
23120
+ },
23121
+ /** See above for a theory of operations */
22597
23122
  Delimiter: {
22598
- // Use to represent groups of expressions. Named after https://en.wikipedia.org/wiki/Delimiter
23123
+ // Use to represent groups of expressions.
23124
+ // Named after https://en.wikipedia.org/wiki/Delimiter
22599
23125
  complexity: 9e3,
22600
- hold: "first",
23126
+ hold: "all",
22601
23127
  signature: {
22602
- domain: [
22603
- "FunctionOf",
22604
- "Anything",
22605
- ["OptArg", "Strings", "Strings"],
22606
- "Anything"
22607
- ],
23128
+ params: ["Anything"],
23129
+ optParams: ["Strings"],
22608
23130
  result: (_ce, args) => args[0].domain,
22609
- canonical: (ce, args) => args[0]?.canonical ?? ce.box(["Sequence"])
23131
+ // During canonicalization, Delimiters get replaced by their first
23132
+ // argument, which is a function expression (e.g. `List` or `Sequence`)
23133
+ canonical: (ce, args) => {
23134
+ if (args.length === 0)
23135
+ return ce._fn("Tuple", []);
23136
+ let body = args[0];
23137
+ console.assert(body.ops !== null);
23138
+ if (body.head === "Sequence")
23139
+ body = ce._fn("Sequence", ce.canonical(body.ops));
23140
+ args = [body, ...args.slice(1)];
23141
+ if (args.length === 1)
23142
+ return ce._fn("Delimiter", args);
23143
+ if (args.length > 2)
23144
+ return ce._fn("Delimiter", checkArity(ce, args, 2));
23145
+ if ((args[1].string?.length ?? 0) > 3) {
23146
+ return ce._fn("Delimiter", [
23147
+ args[0],
23148
+ ce.error("invalid-delimiter", args[1])
23149
+ ]);
23150
+ }
23151
+ return ce._fn("Delimiter", [
23152
+ args[0],
23153
+ checkDomain(ce, args[1], "Strings")
23154
+ ]);
23155
+ },
23156
+ evaluate: (ce, ops2) => {
23157
+ if (ops2.length === 0)
23158
+ return ce.Nothing;
23159
+ const op12 = ops2[0];
23160
+ if (op12.head === "Sequence" || op12.head === "Delimiter")
23161
+ ops2 = flattenSequence(ops2[0].ops);
23162
+ return ce._fn(
23163
+ "Tuple",
23164
+ ops2.map((x) => x.evaluate())
23165
+ );
23166
+ },
23167
+ N: (ce, ops2) => {
23168
+ if (ops2.length === 0)
23169
+ return ce.Nothing;
23170
+ const op12 = ops2[0];
23171
+ if (op12.head === "Sequence" || op12.head === "Delimiter")
23172
+ ops2 = flattenSequence(ops2[0].ops);
23173
+ return ce._fn(
23174
+ "Tuple",
23175
+ ops2.map((x) => x.N())
23176
+ );
23177
+ }
22610
23178
  }
22611
23179
  },
22612
23180
  Error: {
@@ -22631,7 +23199,7 @@ var CORE_LIBRARY = [
22631
23199
  signature: {
22632
23200
  domain: ["FunctionOf", "Strings", ["VarArg", "Anything"], "Anything"],
22633
23201
  canonical: (ce, args) => {
22634
- const code = checkArg(ce, args[0], ce.Strings).string;
23202
+ const code = checkDomain(ce, args[0], ce.Strings).string;
22635
23203
  if (code === "incompatible-domain") {
22636
23204
  return ce._fn("ErrorCode", [ce.string(code), args[1], args[2]]);
22637
23205
  }
@@ -22651,11 +23219,11 @@ var CORE_LIBRARY = [
22651
23219
  return ce.domain("Strings");
22652
23220
  if (op12.head === "Numbers")
22653
23221
  return ce.domain("Numbers");
22654
- return void 0;
23222
+ return op12.domain;
22655
23223
  },
22656
23224
  // By definition, for arguments of the canonical expression of
22657
23225
  // `Hold` are not canonicalized.
22658
- canonical: (ce, args) => args.length !== 1 ? null : ce._fn("Hold", args),
23226
+ canonical: (ce, args) => args.length !== 1 ? null : ce.hold(args[0]),
22659
23227
  evaluate: (ce, ops2) => ops2[0]
22660
23228
  }
22661
23229
  },
@@ -22750,18 +23318,17 @@ var CORE_LIBRARY = [
22750
23318
  },
22751
23319
  Assign: {
22752
23320
  hold: "all",
23321
+ pure: false,
22753
23322
  signature: {
22754
- domain: ["FunctionOf", "Symbols", "Anything", "Anything"],
23323
+ domain: ["FunctionOf", "Anything", "Anything", "Anything"],
22755
23324
  canonical: (ce, args) => {
22756
23325
  if (args.length !== 2)
22757
23326
  return null;
22758
23327
  const op12 = args[0];
22759
- const op22 = args[1];
22760
23328
  if (!op12.symbol)
22761
23329
  return null;
22762
- if (op22.symbol)
22763
- return ce._fn("Assign", args);
22764
- return ce._fn("Assign", [op12, ce._fn("Hold", [op22])]);
23330
+ const op22 = args[1];
23331
+ return ce._fn("Assign", [op12, op22]);
22765
23332
  },
22766
23333
  evaluate: (ce, ops2) => {
22767
23334
  const op12 = ops2[0];
@@ -22776,6 +23343,7 @@ var CORE_LIBRARY = [
22776
23343
  },
22777
23344
  Assume: {
22778
23345
  hold: "all",
23346
+ pure: false,
22779
23347
  signature: {
22780
23348
  domain: ["FunctionOf", "Anything", "Anything"],
22781
23349
  evaluate: (ce, ops2) => ce.string(ce.assume(ops2[0]))
@@ -22783,6 +23351,7 @@ var CORE_LIBRARY = [
22783
23351
  },
22784
23352
  Declare: {
22785
23353
  hold: "all",
23354
+ pure: false,
22786
23355
  signature: {
22787
23356
  domain: ["FunctionOf", "Symbols", "Anything"],
22788
23357
  canonical: (ce, args) => {
@@ -22936,17 +23505,15 @@ var CORE_LIBRARY = [
22936
23505
  const op22 = args[1];
22937
23506
  if (op12.string) {
22938
23507
  const base = asSmallInteger(op22);
22939
- if (base !== null) {
22940
- if (base > 1 && base <= 36) {
22941
- const [value, rest] = fromDigits(op12.string, base);
22942
- if (rest) {
22943
- return ce.error(
22944
- ["unexpected-digit", { str: rest[0] }],
22945
- ["LatexString", ce.string(op12.string)]
22946
- );
22947
- }
22948
- return ce.number(value);
23508
+ if (base !== null && base > 1 && base <= 36) {
23509
+ const [value, rest] = fromDigits(op12.string, base);
23510
+ if (rest) {
23511
+ return ce.error(
23512
+ ["unexpected-digit", { str: rest[0] }],
23513
+ ["LatexString", ce.string(op12.string)]
23514
+ );
22949
23515
  }
23516
+ return ce.number(value);
22950
23517
  }
22951
23518
  }
22952
23519
  if (op12.symbol) {
@@ -23064,9 +23631,74 @@ var CORE_LIBRARY = [
23064
23631
  }
23065
23632
  }
23066
23633
  ];
23634
+ function canonicalInvisibleOperator(ce, ops2) {
23635
+ if (ops2.length === 0)
23636
+ return null;
23637
+ const lhs = ops2[0];
23638
+ if (ops2.length === 1)
23639
+ return canonicalInvisibleOperator(ce, [lhs.canonical]);
23640
+ if (ops2.length === 2) {
23641
+ const lhsNumber = asFloat(lhs);
23642
+ if (lhsNumber !== null && Number.isInteger(lhsNumber)) {
23643
+ const rhs2 = ops2[1];
23644
+ if (rhs2.head === "Divide" || rhs2.head === "Rational") {
23645
+ const [n, d] = [asFloat(rhs2.op1), asFloat(rhs2.op2)];
23646
+ if (n !== null && d !== null && n > 0 && n <= 1e3 && d > 1 && d <= 1e3 && Number.isInteger(n) && Number.isInteger(d))
23647
+ return ce.add([lhs.canonical, rhs2.canonical]);
23648
+ }
23649
+ }
23650
+ let rhs = ops2[1];
23651
+ if (lhs.symbol && rhs.head === "Delimiter" && !ce.lookupSymbol(lhs.symbol)) {
23652
+ if (!ce.lookupFunction(lhs.symbol)) {
23653
+ ce.declare(lhs.symbol, "Functions");
23654
+ }
23655
+ if (rhs.nops === 0)
23656
+ return ce.box([lhs.symbol]);
23657
+ rhs = rhs.op1;
23658
+ if (rhs.head === "Sequence")
23659
+ return ce.box([lhs.symbol, ...ce.canonical(rhs.ops)]);
23660
+ return ce.box([lhs.symbol, rhs.canonical]);
23661
+ }
23662
+ }
23663
+ ops2 = canonical(flattenSequence(ops2));
23664
+ if (ops2.every(
23665
+ (x) => x.isValid && (!x.domain || x.domain.isNumeric || isIndexableCollection(x) && !x.string)
23666
+ ))
23667
+ return ce._fn("Multiply", flattenOps(ops2, "Multiply"));
23668
+ return ce._fn("Tuple", ops2);
23669
+ }
23067
23670
 
23068
23671
  // src/compute-engine/library/linear-algebra.ts
23069
- var LINEAR_ALGEBRA_LIBRARY = [];
23672
+ var LINEAR_ALGEBRA_LIBRARY = [
23673
+ {
23674
+ Matrix: {
23675
+ complexity: 9e3,
23676
+ hold: "all",
23677
+ signature: {
23678
+ params: ["Lists"],
23679
+ optParams: ["Strings", "Strings"],
23680
+ result: "Lists",
23681
+ canonical: canonicalMatrix,
23682
+ evaluate: (_ce, ops2) => ops2[0].evaluate(),
23683
+ N: (_ce, ops2) => ops2[0].N()
23684
+ }
23685
+ }
23686
+ }
23687
+ ];
23688
+ function canonicalMatrix(ce, ops2) {
23689
+ if (ops2.length === 0)
23690
+ return ce._fn("Matrix", []);
23691
+ const body = ops2[0].canonical;
23692
+ const delims = ops2[1]?.canonical;
23693
+ const columns = ops2[2]?.canonical;
23694
+ if (ops2.length > 3)
23695
+ return ce._fn("Matrix", checkArity(ce, ops2, 3));
23696
+ if (columns)
23697
+ return ce._fn("Matrix", [body, delims, columns]);
23698
+ if (delims)
23699
+ return ce._fn("Matrix", [body, delims]);
23700
+ return ce._fn("Matrix", [body]);
23701
+ }
23070
23702
 
23071
23703
  // src/compute-engine/library/logic.ts
23072
23704
  var LOGIC_LIBRARY = {
@@ -23131,6 +23763,15 @@ var LOGIC_LIBRARY = {
23131
23763
  complexity: 10200,
23132
23764
  signature: {
23133
23765
  domain: "LogicOperators",
23766
+ canonical: (ce, args) => {
23767
+ const lhs = args[0].symbol;
23768
+ const rhs = args[1].symbol;
23769
+ if (lhs === "True" && rhs === "True" || lhs === "False" && rhs === "False")
23770
+ return ce.True;
23771
+ if (lhs === "True" && rhs === "False" || lhs === "False" && rhs === "True")
23772
+ return ce.False;
23773
+ return ce._fn("Equivalent", args);
23774
+ },
23134
23775
  simplify: processEquivalent,
23135
23776
  evaluate: processEquivalent
23136
23777
  }
@@ -23200,7 +23841,7 @@ function processOr(ce, args) {
23200
23841
  return ce._fn("Or", ops2);
23201
23842
  }
23202
23843
  function processNot(ce, args) {
23203
- const op12 = args[0].symbol;
23844
+ const op12 = args[0]?.symbol;
23204
23845
  if (op12 === "True")
23205
23846
  return ce.False;
23206
23847
  if (op12 === "False")
@@ -23264,17 +23905,42 @@ var POLYNOMIALS_LIBRARY = [
23264
23905
 
23265
23906
  // src/compute-engine/library/relational-operator.ts
23266
23907
  var RELOP_LIBRARY = {
23908
+ Congruent: {
23909
+ commutative: false,
23910
+ complexity: 11e3,
23911
+ numeric: true,
23912
+ signature: {
23913
+ simplify: (ce, ops2) => {
23914
+ if (ops2.length < 3)
23915
+ return void 0;
23916
+ return ce._fn("Equal", [
23917
+ ce.box(["Mod", ops2[0], ops2[2]]).simplify(),
23918
+ ce.box(["Mod", ops2[1], ops2[2]]).simplify()
23919
+ ]).simplify();
23920
+ },
23921
+ evaluate: (ce, ops2) => {
23922
+ if (ops2.length < 3)
23923
+ return void 0;
23924
+ const [lhs, rhs, modulo] = ops2;
23925
+ const nLhs = lhs.value;
23926
+ const nRhs = rhs.value;
23927
+ const nModulo = modulo.value;
23928
+ if (typeof nLhs !== "number")
23929
+ return void 0;
23930
+ if (typeof nRhs !== "number")
23931
+ return void 0;
23932
+ if (typeof nModulo !== "number")
23933
+ return void 0;
23934
+ return nLhs % nModulo === nRhs % nModulo ? ce.True : ce.False;
23935
+ }
23936
+ }
23937
+ },
23267
23938
  Equal: {
23268
23939
  commutative: true,
23269
23940
  complexity: 11e3,
23270
23941
  signature: {
23271
23942
  domain: "RelationalOperators",
23272
- canonical: (ce, ops2) => {
23273
- return ce._fn(
23274
- "Equal",
23275
- flattenOps(flattenSequence(canonical(ops2)), "Equal")
23276
- );
23277
- },
23943
+ canonical: (ce, args) => canonicalRelational(ce, "Equal", args),
23278
23944
  evaluate: (ce, ops2) => {
23279
23945
  if (ops2.length < 2)
23280
23946
  return ce.True;
@@ -23298,6 +23964,7 @@ var RELOP_LIBRARY = {
23298
23964
  complexity: 11e3,
23299
23965
  signature: {
23300
23966
  domain: "RelationalOperators",
23967
+ canonical: (ce, args) => canonicalRelational(ce, "NotEqual", args),
23301
23968
  evaluate: (ce, ops2) => {
23302
23969
  if (ops2.length < 2)
23303
23970
  return ce.False;
@@ -23319,7 +23986,7 @@ var RELOP_LIBRARY = {
23319
23986
  complexity: 11e3,
23320
23987
  signature: {
23321
23988
  domain: "RelationalOperators",
23322
- canonical: (ce, ops2) => ce._fn("Less", flattenOps(flattenSequence(canonical(ops2)), "Less")),
23989
+ canonical: (ce, ops2) => canonicalRelational(ce, "Less", ops2),
23323
23990
  evaluate: (ce, ops2) => {
23324
23991
  if (ops2.length < 2)
23325
23992
  return ce.True;
@@ -23346,14 +24013,14 @@ var RELOP_LIBRARY = {
23346
24013
  complexity: 11e3,
23347
24014
  signature: {
23348
24015
  domain: "RelationalOperators",
23349
- canonical: (ce, args) => ce._fn("Not", [ce._fn("Less", args)])
24016
+ canonical: (ce, ops2) => ce._fn("Not", [canonicalRelational(ce, "Less", ops2)])
23350
24017
  }
23351
24018
  },
23352
24019
  Greater: {
23353
24020
  complexity: 11e3,
23354
24021
  signature: {
23355
24022
  domain: "RelationalOperators",
23356
- canonical: (ce, args) => ce._fn("Less", args.reverse()),
24023
+ canonical: (ce, ops2) => canonicalRelational(ce, "Less", ops2.reverse()),
23357
24024
  evaluate: (ce, ops2) => {
23358
24025
  if (ops2.length < 2)
23359
24026
  return ce.True;
@@ -23387,6 +24054,7 @@ var RELOP_LIBRARY = {
23387
24054
  complexity: 11e3,
23388
24055
  signature: {
23389
24056
  domain: "RelationalOperators",
24057
+ canonical: (ce, ops2) => canonicalRelational(ce, "LessEqual", ops2),
23390
24058
  evaluate: (ce, ops2) => {
23391
24059
  if (ops2.length < 2)
23392
24060
  return ce.True;
@@ -23413,14 +24081,14 @@ var RELOP_LIBRARY = {
23413
24081
  complexity: 11e3,
23414
24082
  signature: {
23415
24083
  domain: "RelationalOperators",
23416
- canonical: (ce, args) => ce._fn("Not", [ce._fn("LessEqual", args)])
24084
+ canonical: (ce, ops2) => ce._fn("Not", [canonicalRelational(ce, "LessEqual", ops2)])
23417
24085
  }
23418
24086
  },
23419
24087
  GreaterEqual: {
23420
24088
  complexity: 11e3,
23421
24089
  signature: {
23422
24090
  domain: "RelationalOperators",
23423
- canonical: (ce, args) => ce._fn("LessEqual", args.reverse()),
24091
+ canonical: (ce, args) => canonicalRelational(ce, "LessEqual", args.reverse()),
23424
24092
  evaluate: (ce, ops2) => {
23425
24093
  if (ops2.length < 2)
23426
24094
  return ce.True;
@@ -23447,94 +24115,136 @@ var RELOP_LIBRARY = {
23447
24115
  complexity: 11e3,
23448
24116
  signature: {
23449
24117
  domain: "RelationalOperators",
23450
- canonical: (ce, args) => ce._fn("Not", [ce._fn("GreaterEqual", args)])
24118
+ canonical: (ce, args) => ce._fn("Not", [canonicalRelational(ce, "GreaterEqual", args)])
23451
24119
  }
23452
24120
  },
23453
24121
  TildeFullEqual: {
23454
24122
  description: "Indicate isomorphism, congruence and homotopic equivalence",
23455
- signature: { domain: "RelationalOperators" }
24123
+ signature: {
24124
+ domain: "RelationalOperators",
24125
+ canonical: (ce, args) => canonicalRelational(ce, "TildeFullEqual", args)
24126
+ }
23456
24127
  // @todo evaluate: (ce, ...args: BoxedExpression[]) => SemiBoxedExpression {}
23457
24128
  },
23458
24129
  NotTildeFullEqual: {
23459
24130
  complexity: 11100,
23460
24131
  signature: {
23461
24132
  domain: "RelationalOperators",
23462
- canonical: (ce, args) => ce._fn("Not", [ce._fn("TildeFullEqual", args)])
24133
+ canonical: (ce, args) => ce._fn("Not", [canonicalRelational(ce, "TildeFullEqual", args)])
23463
24134
  }
23464
24135
  },
23465
24136
  TildeEqual: {
23466
24137
  description: "Approximately or asymptotically equal",
23467
24138
  complexity: 11e3,
23468
- signature: { domain: "RelationalOperators" }
24139
+ signature: {
24140
+ domain: "RelationalOperators",
24141
+ canonical: (ce, args) => canonicalRelational(ce, "TildeEqual", args)
24142
+ }
23469
24143
  // @todo evaluate: (ce, ...args: BoxedExpression[]) => SemiBoxedExpression {}
23470
24144
  },
23471
24145
  NotTildeEqual: {
23472
24146
  complexity: 11100,
23473
24147
  signature: {
23474
24148
  domain: "RelationalOperators",
23475
- canonical: (ce, args) => ce._fn("Not", [ce._fn("TildeEqual", args)])
24149
+ canonical: (ce, args) => ce._fn("Not", [canonicalRelational(ce, "TildeEqual", args)])
23476
24150
  }
23477
24151
  },
23478
24152
  Approx: {
23479
24153
  complexity: 11100,
23480
- signature: { domain: "RelationalOperators" }
24154
+ signature: {
24155
+ domain: "RelationalOperators",
24156
+ canonical: (ce, args) => canonicalRelational(ce, "Approx", args)
24157
+ }
23481
24158
  // @todo evaluate: (ce, ...args: BoxedExpression[]) => SemiBoxedExpression {}
23482
24159
  },
23483
24160
  NotApprox: {
23484
24161
  complexity: 11100,
23485
24162
  signature: {
23486
24163
  domain: "RelationalOperators",
23487
- canonical: (ce, args) => ce._fn("Not", [ce._fn("Approx", args)])
24164
+ canonical: (ce, args) => ce._fn("Not", [canonicalRelational(ce, "Approx", args)])
23488
24165
  }
23489
24166
  },
23490
24167
  ApproxEqual: {
23491
24168
  complexity: 11100,
23492
- signature: { domain: "RelationalOperators" }
24169
+ signature: {
24170
+ domain: "RelationalOperators",
24171
+ canonical: (ce, args) => canonicalRelational(ce, "ApproxEqual", args)
24172
+ }
23493
24173
  // @todo evaluate: (ce, ...args: BoxedExpression[]) => SemiBoxedExpression {}
23494
24174
  },
23495
24175
  NotApproxEqual: {
23496
24176
  complexity: 11100,
23497
24177
  signature: {
23498
24178
  domain: "RelationalOperators",
23499
- canonical: (ce, args) => ce._fn("Not", [ce._fn("ApproxEqual", args)])
24179
+ canonical: (ce, args) => ce._fn("Not", [canonicalRelational(ce, "ApproxEqual", args)])
23500
24180
  }
23501
24181
  },
23502
24182
  ApproxNotEqual: {
23503
24183
  complexity: 11100,
23504
- signature: { domain: "RelationalOperators" }
24184
+ signature: {
24185
+ domain: "RelationalOperators",
24186
+ canonical: (ce, args) => canonicalRelational(ce, "ApproxNotEqual", args)
24187
+ }
23505
24188
  // @todo evaluate: (ce, ...args: BoxedExpression[]) => SemiBoxedExpression {}
23506
24189
  },
23507
24190
  NotApproxNotEqual: {
23508
24191
  complexity: 11100,
23509
24192
  signature: {
23510
24193
  domain: "RelationalOperators",
23511
- canonical: (ce, args) => ce._fn("Not", [ce._fn("ApproxNotEqual", args)])
24194
+ canonical: (ce, args) => ce._fn("Not", [canonicalRelational(ce, "ApproxNotEqual", args)])
23512
24195
  }
23513
24196
  },
23514
24197
  Precedes: {
23515
24198
  complexity: 11100,
23516
- signature: { domain: "RelationalOperators" }
24199
+ signature: {
24200
+ domain: "RelationalOperators",
24201
+ canonical: (ce, args) => canonicalRelational(ce, "Precedes", args)
24202
+ }
23517
24203
  // @todo evaluate: (ce, ...args: BoxedExpression[]) => SemiBoxedExpression {}
23518
24204
  },
23519
24205
  NotPrecedes: {
23520
24206
  complexity: 11100,
23521
24207
  signature: {
23522
24208
  domain: "RelationalOperators",
23523
- canonical: (ce, args) => ce._fn("Not", [ce._fn("Precedes", args)])
24209
+ canonical: (ce, args) => ce._fn("Not", [canonicalRelational(ce, "Precedes", args)])
23524
24210
  }
23525
24211
  },
23526
24212
  Succeeds: {
23527
- signature: { domain: "RelationalOperators" }
24213
+ signature: {
24214
+ domain: "RelationalOperators",
24215
+ canonical: (ce, args) => canonicalRelational(ce, "Succeeds", args)
24216
+ }
23528
24217
  // @todo evaluate: (ce, ...args: BoxedExpression[]) => SemiBoxedExpression {}
23529
24218
  },
23530
24219
  NotSucceeds: {
23531
24220
  complexity: 11100,
23532
24221
  signature: {
23533
24222
  domain: "RelationalOperators",
23534
- canonical: (ce, args) => ce._fn("Not", [ce._fn("Succeeds", args)])
24223
+ canonical: (ce, args) => ce._fn("Not", [canonicalRelational(ce, "Succeeds", args)])
23535
24224
  }
23536
24225
  }
23537
24226
  };
24227
+ function canonicalRelational(ce, head2, ops2) {
24228
+ ops2 = flattenOps(flattenSequence(canonical(ops2)), head2);
24229
+ const nestedRelational = [];
24230
+ let newOps = [];
24231
+ for (const op3 of ops2) {
24232
+ if (isRelationalOperator(op3)) {
24233
+ nestedRelational.push(op3);
24234
+ newOps.push(op3.ops[op3.ops.length - 1]);
24235
+ } else
24236
+ newOps.push(op3);
24237
+ }
24238
+ newOps = newOps.map((op3) => checkPure(ce, op3));
24239
+ if (nestedRelational.length === 0)
24240
+ return ce._fn(head2, newOps);
24241
+ return ce._fn("And", [ce._fn(head2, newOps), ...nestedRelational]);
24242
+ }
24243
+ function isRelationalOperator(op3) {
24244
+ 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(
24245
+ op3.head
24246
+ );
24247
+ }
23538
24248
 
23539
24249
  // src/compute-engine/library/sets.ts
23540
24250
  var SETS_LIBRARY = {
@@ -26332,14 +27042,7 @@ var BoxedSymbol = class _BoxedSymbol extends _BoxedExpression {
26332
27042
  return this._hash;
26333
27043
  }
26334
27044
  get isPure() {
26335
- const def = this._def ?? this.engine.lookupSymbol(this._id, this.wikidata);
26336
- if (!def)
26337
- return false;
26338
- if (def instanceof _BoxedSymbolDefinition)
26339
- return (def?.constant && def.value?.isPure) ?? false;
26340
- if (def instanceof _BoxedFunctionDefinition)
26341
- return def?.pure ?? false;
26342
- return false;
27045
+ return true;
26343
27046
  }
26344
27047
  get json() {
26345
27048
  const wikidata = this._scope ? this.wikidata : void 0;
@@ -26848,15 +27551,15 @@ var ComputeEngine = class _ComputeEngine {
26848
27551
  TranscendentalNumbers: null,
26849
27552
  PositiveNumbers: null,
26850
27553
  Functions: null,
26851
- // (Anything^n) -> Anything
27554
+ // (Anything*) -> Anything
26852
27555
  NumericFunctions: null,
26853
- // (Numbers^n) -> Numbers
27556
+ // (Numbers+) -> Numbers
26854
27557
  RealFunctions: null,
26855
- // (ExtendedRealNumbers^n) -> ExtendRealNumbers
27558
+ // (ExtendedRealNumbers+) -> ExtendRealNumbers
26856
27559
  LogicOperators: null,
26857
- // (Booleans, Booleans) -> Boolean
27560
+ // (Booleans+) -> Boolean
26858
27561
  Predicates: null
26859
- // (Anything^n) -> Booleans
27562
+ // (Anything+) -> Booleans
26860
27563
  };
26861
27564
  if (options !== void 0 && typeof options !== "object")
26862
27565
  throw Error("Unexpected argument");
@@ -27128,7 +27831,12 @@ var ComputeEngine = class _ComputeEngine {
27128
27831
  bignum(a) {
27129
27832
  if (typeof a === "bigint")
27130
27833
  return new this._bignum(a.toString());
27131
- return new this._bignum(a);
27834
+ try {
27835
+ return new this._bignum(a);
27836
+ } catch (e) {
27837
+ console.error(e);
27838
+ }
27839
+ return this._BIGNUM_NAN;
27132
27840
  }
27133
27841
  complex(a, b) {
27134
27842
  if (a instanceof Decimal)
@@ -27477,11 +28185,10 @@ var ComputeEngine = class _ComputeEngine {
27477
28185
  const scope = symDef.scope;
27478
28186
  scope?.ids?.delete(symDef.name);
27479
28187
  if (!args && !isFunctionValue(value)) {
27480
- if (value === void 0 || value === null) {
28188
+ if (value === void 0 || value === null)
27481
28189
  symDef.value = void 0;
27482
- return this;
27483
- }
27484
- symDef.value = this.box(value);
28190
+ else
28191
+ symDef.value = this.box(value);
27485
28192
  scope?.ids?.set(symDef.name, symDef);
27486
28193
  return this;
27487
28194
  }
@@ -28114,10 +28821,10 @@ function isFunctionValue(value) {
28114
28821
  }
28115
28822
 
28116
28823
  // src/compute-engine.ts
28117
- var version = "0.19.1";
28824
+ var version = "0.20.1";
28118
28825
  globalThis[Symbol.for("io.cortexjs.compute-engine")] = {
28119
28826
  ComputeEngine: ComputeEngine.prototype.constructor,
28120
- version: "0.19.1"
28827
+ version: "0.20.1"
28121
28828
  };
28122
28829
  export {
28123
28830
  ADDITION_PRECEDENCE,