mathjs 11.3.3 → 11.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/HISTORY.md +25 -0
  2. package/lib/browser/math.js +1 -1
  3. package/lib/browser/math.js.LICENSE.txt +2 -2
  4. package/lib/browser/math.js.map +1 -1
  5. package/lib/cjs/entry/dependenciesAny/dependenciesLyap.generated.js +26 -0
  6. package/lib/cjs/entry/dependenciesAny/dependenciesPolynomialRoot.generated.js +42 -0
  7. package/lib/cjs/entry/dependenciesAny/dependenciesSchur.generated.js +30 -0
  8. package/lib/cjs/entry/dependenciesAny/dependenciesSylvester.generated.js +46 -0
  9. package/lib/cjs/entry/dependenciesAny.generated.js +28 -0
  10. package/lib/cjs/entry/impureFunctionsAny.generated.js +21 -17
  11. package/lib/cjs/entry/pureFunctionsAny.generated.js +100 -48
  12. package/lib/cjs/expression/embeddedDocs/embeddedDocs.js +8 -0
  13. package/lib/cjs/expression/embeddedDocs/function/algebra/polynomialRoot.js +15 -0
  14. package/lib/cjs/expression/embeddedDocs/function/matrix/lyap.js +15 -0
  15. package/lib/cjs/expression/embeddedDocs/function/matrix/reshape.js +1 -1
  16. package/lib/cjs/expression/embeddedDocs/function/matrix/schur.js +15 -0
  17. package/lib/cjs/expression/embeddedDocs/function/matrix/sylvester.js +15 -0
  18. package/lib/cjs/factoriesAny.js +28 -0
  19. package/lib/cjs/function/algebra/decomposition/schur.js +75 -0
  20. package/lib/cjs/function/algebra/lyap.js +57 -0
  21. package/lib/cjs/function/algebra/polynomialRoot.js +139 -0
  22. package/lib/cjs/function/algebra/simplify/wildcards.js +38 -0
  23. package/lib/cjs/function/algebra/simplify.js +161 -48
  24. package/lib/cjs/function/algebra/simplifyConstant.js +29 -12
  25. package/lib/cjs/function/algebra/sylvester.js +127 -0
  26. package/lib/cjs/function/matrix/forEach.js +1 -1
  27. package/lib/cjs/function/matrix/reshape.js +1 -1
  28. package/lib/cjs/function/string/format.js +24 -24
  29. package/lib/cjs/header.js +2 -2
  30. package/lib/cjs/version.js +1 -1
  31. package/lib/esm/entry/dependenciesAny/dependenciesLyap.generated.js +18 -0
  32. package/lib/esm/entry/dependenciesAny/dependenciesPolynomialRoot.generated.js +34 -0
  33. package/lib/esm/entry/dependenciesAny/dependenciesSchur.generated.js +22 -0
  34. package/lib/esm/entry/dependenciesAny/dependenciesSylvester.generated.js +38 -0
  35. package/lib/esm/entry/dependenciesAny.generated.js +4 -0
  36. package/lib/esm/entry/impureFunctionsAny.generated.js +22 -18
  37. package/lib/esm/entry/pureFunctionsAny.generated.js +87 -39
  38. package/lib/esm/expression/embeddedDocs/embeddedDocs.js +8 -0
  39. package/lib/esm/expression/embeddedDocs/function/algebra/polynomialRoot.js +8 -0
  40. package/lib/esm/expression/embeddedDocs/function/matrix/lyap.js +8 -0
  41. package/lib/esm/expression/embeddedDocs/function/matrix/reshape.js +1 -1
  42. package/lib/esm/expression/embeddedDocs/function/matrix/schur.js +8 -0
  43. package/lib/esm/expression/embeddedDocs/function/matrix/sylvester.js +8 -0
  44. package/lib/esm/factoriesAny.js +4 -0
  45. package/lib/esm/function/algebra/decomposition/schur.js +70 -0
  46. package/lib/esm/function/algebra/lyap.js +52 -0
  47. package/lib/esm/function/algebra/polynomialRoot.js +122 -0
  48. package/lib/esm/function/algebra/simplify/wildcards.js +20 -0
  49. package/lib/esm/function/algebra/simplify.js +162 -49
  50. package/lib/esm/function/algebra/simplifyConstant.js +29 -12
  51. package/lib/esm/function/algebra/sylvester.js +118 -0
  52. package/lib/esm/function/matrix/forEach.js +1 -1
  53. package/lib/esm/function/matrix/reshape.js +1 -1
  54. package/lib/esm/function/string/format.js +24 -24
  55. package/lib/esm/version.js +1 -1
  56. package/package.json +14 -14
  57. package/types/index.d.ts +88 -6
@@ -0,0 +1,122 @@
1
+ import { factory } from '../../utils/factory.js';
2
+ var name = 'polynomialRoot';
3
+ var dependencies = ['typed', 'isZero', 'equalScalar', 'add', 'subtract', 'multiply', 'divide', 'sqrt', 'unaryMinus', 'cbrt', 'typeOf', 'im', 're'];
4
+ export var createPolynomialRoot = /* #__PURE__ */factory(name, dependencies, _ref => {
5
+ var {
6
+ typed,
7
+ isZero,
8
+ equalScalar,
9
+ add,
10
+ subtract,
11
+ multiply,
12
+ divide,
13
+ sqrt,
14
+ unaryMinus,
15
+ cbrt,
16
+ typeOf,
17
+ im,
18
+ re
19
+ } = _ref;
20
+ /**
21
+ * Finds the numerical values of the distinct roots of a polynomial with real or complex coefficients.
22
+ * Currently operates only on linear, quadratic, and cubic polynomials using the standard
23
+ * formulas for the roots.
24
+ *
25
+ * Syntax:
26
+ *
27
+ * polynomialRoot(constant, linearCoeff, quadraticCoeff, cubicCoeff)
28
+ *
29
+ * Examples:
30
+ * // linear
31
+ * math.polynomialRoot(6, 3) // [-2]
32
+ * math.polynomialRoot(math.complex(6,3), 3) // [-2 - i]
33
+ * math.polynomialRoot(math.complex(6,3), math.complex(2,1)) // [-3 + 0i]
34
+ * // quadratic
35
+ * math.polynomialRoot(2, -3, 1) // [2, 1]
36
+ * math.polynomialRoot(8, 8, 2) // [-2]
37
+ * math.polynomialRoot(-2, 0, 1) // [1.4142135623730951, -1.4142135623730951]
38
+ * math.polynomialRoot(2, -2, 1) // [1 + i, 1 - i]
39
+ * math.polynomialRoot(math.complex(1,3), math.complex(-3, -2), 1) // [2 + i, 1 + i]
40
+ * // cubic
41
+ * math.polynomialRoot(-6, 11, -6, 1) // [1, 3, 2]
42
+ * math.polynomialRoot(-8, 0, 0, 1) // [-1 - 1.7320508075688774i, 2, -1 + 1.7320508075688774i]
43
+ * math.polynomialRoot(0, 8, 8, 2) // [0, -2]
44
+ * math.polynomialRoot(1, 1, 1, 1) // [-1 + 0i, 0 - i, 0 + i]
45
+ *
46
+ * See also:
47
+ * cbrt, sqrt
48
+ *
49
+ * @param {... number | Complex} coeffs
50
+ * The coefficients of the polynomial, starting with with the constant coefficent, followed
51
+ * by the linear coefficient and subsequent coefficients of increasing powers.
52
+ * @return {Array} The distinct roots of the polynomial
53
+ */
54
+
55
+ return typed(name, {
56
+ 'number|Complex, ...number|Complex': (constant, restCoeffs) => {
57
+ var coeffs = [constant, ...restCoeffs];
58
+ while (coeffs.length > 0 && isZero(coeffs[coeffs.length - 1])) {
59
+ coeffs.pop();
60
+ }
61
+ if (coeffs.length < 2) {
62
+ throw new RangeError("Polynomial [".concat(constant, ", ").concat(restCoeffs, "] must have a non-zero non-constant coefficient"));
63
+ }
64
+ switch (coeffs.length) {
65
+ case 2:
66
+ // linear
67
+ return [unaryMinus(divide(coeffs[0], coeffs[1]))];
68
+ case 3:
69
+ {
70
+ // quadratic
71
+ var [c, b, a] = coeffs;
72
+ var denom = multiply(2, a);
73
+ var d1 = multiply(b, b);
74
+ var d2 = multiply(4, a, c);
75
+ if (equalScalar(d1, d2)) return [divide(unaryMinus(b), denom)];
76
+ var discriminant = sqrt(subtract(d1, d2));
77
+ return [divide(subtract(discriminant, b), denom), divide(subtract(unaryMinus(discriminant), b), denom)];
78
+ }
79
+ case 4:
80
+ {
81
+ // cubic, cf. https://en.wikipedia.org/wiki/Cubic_equation
82
+ var [d, _c, _b, _a] = coeffs;
83
+ var _denom = unaryMinus(multiply(3, _a));
84
+ var D0_1 = multiply(_b, _b);
85
+ var D0_2 = multiply(3, _a, _c);
86
+ var D1_1 = add(multiply(2, _b, _b, _b), multiply(27, _a, _a, d));
87
+ var D1_2 = multiply(9, _a, _b, _c);
88
+ if (equalScalar(D0_1, D0_2) && equalScalar(D1_1, D1_2)) {
89
+ return [divide(_b, _denom)];
90
+ }
91
+ var Delta0 = subtract(D0_1, D0_2);
92
+ var Delta1 = subtract(D1_1, D1_2);
93
+ var discriminant1 = add(multiply(18, _a, _b, _c, d), multiply(_b, _b, _c, _c));
94
+ var discriminant2 = add(multiply(4, _b, _b, _b, d), multiply(4, _a, _c, _c, _c), multiply(27, _a, _a, d, d));
95
+ if (equalScalar(discriminant1, discriminant2)) {
96
+ return [divide(subtract(multiply(4, _a, _b, _c), add(multiply(9, _a, _a, d), multiply(_b, _b, _b))), multiply(_a, Delta0)),
97
+ // simple root
98
+ divide(subtract(multiply(9, _a, d), multiply(_b, _c)), multiply(2, Delta0)) // double root
99
+ ];
100
+ }
101
+ // OK, we have three distinct roots
102
+ var Ccubed;
103
+ if (equalScalar(D0_1, D0_2)) {
104
+ Ccubed = Delta1;
105
+ } else {
106
+ Ccubed = divide(add(Delta1, sqrt(subtract(multiply(Delta1, Delta1), multiply(4, Delta0, Delta0, Delta0)))), 2);
107
+ }
108
+ var allRoots = true;
109
+ var rawRoots = cbrt(Ccubed, allRoots).toArray().map(C => divide(add(_b, C, divide(Delta0, C)), _denom));
110
+ return rawRoots.map(r => {
111
+ if (typeOf(r) === 'Complex' && equalScalar(re(r), re(r) + im(r))) {
112
+ return re(r);
113
+ }
114
+ return r;
115
+ });
116
+ }
117
+ default:
118
+ throw new RangeError("only implemented for cubic or lower-order polynomials, not ".concat(coeffs));
119
+ }
120
+ }
121
+ });
122
+ });
@@ -0,0 +1,20 @@
1
+ import { isConstantNode, isFunctionNode, isOperatorNode, isParenthesisNode } from '../../../utils/is.js';
2
+ export { isConstantNode, isSymbolNode as isVariableNode } from '../../../utils/is.js';
3
+ export function isNumericNode(x) {
4
+ return isConstantNode(x) || isOperatorNode(x) && x.isUnary() && isConstantNode(x.args[0]);
5
+ }
6
+ export function isConstantExpression(x) {
7
+ if (isConstantNode(x)) {
8
+ // Basic Constant types
9
+ return true;
10
+ }
11
+ if ((isFunctionNode(x) || isOperatorNode(x)) && x.args.every(isConstantExpression)) {
12
+ // Can be constant depending on arguments
13
+ return true;
14
+ }
15
+ if (isParenthesisNode(x) && isConstantExpression(x.content)) {
16
+ // Parenthesis are transparent
17
+ return true;
18
+ }
19
+ return false; // Probably missing some edge cases
20
+ }
@@ -1,4 +1,5 @@
1
- import { isConstantNode, isParenthesisNode } from '../../utils/is.js';
1
+ import { isParenthesisNode } from '../../utils/is.js';
2
+ import { isConstantNode, isVariableNode, isNumericNode, isConstantExpression } from './simplify/wildcards.js';
2
3
  import { factory } from '../../utils/factory.js';
3
4
  import { createUtil } from './simplify/util.js';
4
5
  import { hasOwnProperty } from '../../utils/object.js';
@@ -75,9 +76,15 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
75
76
  * expression is that variables starting with the following characters are
76
77
  * interpreted as wildcards:
77
78
  *
78
- * - 'n' - matches any Node
79
- * - 'c' - matches any ConstantNode
80
- * - 'v' - matches any Node that is not a ConstantNode
79
+ * - 'n' - Matches any node [Node]
80
+ * - 'c' - Matches a constant literal (5 or 3.2) [ConstantNode]
81
+ * - 'cl' - Matches a constant literal; same as c [ConstantNode]
82
+ * - 'cd' - Matches a decimal literal (5 or -3.2) [ConstantNode or unaryMinus wrapping a ConstantNode]
83
+ * - 'ce' - Matches a constant expression (-5 or √3) [Expressions consisting of only ConstantNodes, functions, and operators]
84
+ * - 'v' - Matches a variable; anything not matched by c (-5 or x) [Node that is not a ConstantNode]
85
+ * - 'vl' - Matches a variable literal (x or y) [SymbolNode]
86
+ * - 'vd' - Matches a non-decimal expression; anything not matched by cd (x or √3) [Node that is not a ConstantNode or unaryMinus that is wrapping a ConstantNode]
87
+ * - 've' - Matches a variable expression; anything not matched by ce (x or 2x) [Expressions that contain a SymbolNode or other non-constant term]
81
88
  *
82
89
  * The default list of rules is exposed on the function as `simplify.rules`
83
90
  * and can be used as a basis to built a set of custom rules. Note that since
@@ -250,7 +257,7 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
250
257
  }
251
258
  }
252
259
  }, {
253
- s: '-(c*v) -> v * (-c)',
260
+ s: '-(cl*v) -> v * (-cl)',
254
261
  // make non-constant terms positive
255
262
  assuming: {
256
263
  multiply: {
@@ -261,7 +268,7 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
261
268
  }
262
269
  }
263
270
  }, {
264
- s: '-(c*v) -> (-c) * v',
271
+ s: '-(cl*v) -> (-cl) * v',
265
272
  // non-commutative version, part 1
266
273
  assuming: {
267
274
  multiply: {
@@ -272,7 +279,7 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
272
279
  }
273
280
  }
274
281
  }, {
275
- s: '-(v*c) -> v * (-c)',
282
+ s: '-(v*cl) -> v * (-cl)',
276
283
  // non-commutative version, part 2
277
284
  assuming: {
278
285
  multiply: {
@@ -330,24 +337,24 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
330
337
  },
331
338
  // collect like factors; into a sum, only do this for nonconstants
332
339
  {
333
- l: ' v * ( v * n1 + n2)',
334
- r: 'v^2 * n1 + v * n2'
340
+ l: ' vd * ( vd * n1 + n2)',
341
+ r: 'vd^2 * n1 + vd * n2'
335
342
  }, {
336
- s: ' v * (v^n4 * n1 + n2) -> v^(1+n4) * n1 + v * n2',
343
+ s: ' vd * (vd^n4 * n1 + n2) -> vd^(1+n4) * n1 + vd * n2',
337
344
  assuming: {
338
345
  divide: {
339
346
  total: true
340
347
  }
341
348
  } // v*1/v = v^(1+-1) needs 1/v
342
349
  }, {
343
- s: 'v^n3 * ( v * n1 + n2) -> v^(n3+1) * n1 + v^n3 * n2',
350
+ s: 'vd^n3 * ( vd * n1 + n2) -> vd^(n3+1) * n1 + vd^n3 * n2',
344
351
  assuming: {
345
352
  divide: {
346
353
  total: true
347
354
  }
348
355
  }
349
356
  }, {
350
- s: 'v^n3 * (v^n4 * n1 + n2) -> v^(n3+n4) * n1 + v^n3 * n2',
357
+ s: 'vd^n3 * (vd^n4 * n1 + n2) -> vd^(n3+n4) * n1 + vd^n3 * n2',
351
358
  assuming: {
352
359
  divide: {
353
360
  total: true
@@ -390,8 +397,8 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
390
397
  l: 'n+-n',
391
398
  r: '0'
392
399
  }, {
393
- l: 'v*n + v',
394
- r: 'v*(n+1)'
400
+ l: 'vd*n + vd',
401
+ r: 'vd*(n+1)'
395
402
  },
396
403
  // NOTE: leftmost position is special:
397
404
  {
@@ -405,9 +412,17 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
405
412
  }, {
406
413
  l: 'n3^(-n4)*n1 + n3^n5 * n2',
407
414
  r: 'n3^(-n4)*(n1 + n3^(n4+n5)*n2)'
415
+ },
416
+ // noncommutative additional cases (term collection & factoring)
417
+ {
418
+ s: 'n*vd + vd -> (n+1)*vd',
419
+ assuming: {
420
+ multiply: {
421
+ commutative: false
422
+ }
423
+ }
408
424
  }, {
409
- s: 'n*v + v -> (n+1)*v',
410
- // noncommutative additional cases
425
+ s: 'vd + n*vd -> (1+n)*vd',
411
426
  assuming: {
412
427
  multiply: {
413
428
  commutative: false
@@ -420,6 +435,16 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
420
435
  commutative: false
421
436
  }
422
437
  }
438
+ }, {
439
+ s: 'n^n1 * n -> n^(n1+1)',
440
+ assuming: {
441
+ divide: {
442
+ total: true
443
+ },
444
+ multiply: {
445
+ commutative: false
446
+ }
447
+ }
423
448
  }, {
424
449
  s: 'n1*n3^(-n4) + n2 * n3 -> (n1 + n2*n3^(n4 + 1))*n3^(-n4)',
425
450
  assuming: {
@@ -435,10 +460,17 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
435
460
  }
436
461
  }
437
462
  }, {
438
- l: 'n*c + c',
439
- r: '(n+1)*c'
463
+ l: 'n*cd + cd',
464
+ r: '(n+1)*cd'
440
465
  }, {
441
- s: 'c*n + c -> c*(n+1)',
466
+ s: 'cd*n + cd -> cd*(n+1)',
467
+ assuming: {
468
+ multiply: {
469
+ commutative: false
470
+ }
471
+ }
472
+ }, {
473
+ s: 'cd + cd*n -> cd*(1+n)',
442
474
  assuming: {
443
475
  multiply: {
444
476
  commutative: false
@@ -469,7 +501,7 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
469
501
  },
470
502
  // final ordering of constants
471
503
  {
472
- s: 'c+v -> v+c',
504
+ s: 'ce+ve -> ve+ce',
473
505
  assuming: {
474
506
  add: {
475
507
  commutative: true
@@ -481,7 +513,7 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
481
513
  }
482
514
  }
483
515
  }, {
484
- s: 'v*c -> c*v',
516
+ s: 'vd*cd -> cd*vd',
485
517
  assuming: {
486
518
  multiply: {
487
519
  commutative: true
@@ -599,15 +631,33 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
599
631
  newRule.evaluate = parse(ruleObject.evaluate);
600
632
  }
601
633
  if (isAssociative(newRule.l, context)) {
634
+ var nonCommutative = !isCommutative(newRule.l, context);
635
+ var leftExpandsym;
636
+ // Gen. the LHS placeholder used in this NC-context specific expansion rules
637
+ if (nonCommutative) leftExpandsym = _getExpandPlaceholderSymbol();
602
638
  var makeNode = createMakeNodeFunction(newRule.l);
603
639
  var expandsym = _getExpandPlaceholderSymbol();
604
640
  newRule.expanded = {};
605
- newRule.expanded.l = makeNode([newRule.l.clone(), expandsym]);
641
+ newRule.expanded.l = makeNode([newRule.l, expandsym]);
606
642
  // Push the expandsym into the deepest possible branch.
607
643
  // This helps to match the newRule against nodes returned from getSplits() later on.
608
644
  flatten(newRule.expanded.l, context);
609
645
  unflattenr(newRule.expanded.l, context);
610
646
  newRule.expanded.r = makeNode([newRule.r, expandsym]);
647
+
648
+ // In and for a non-commutative context, attempting with yet additional expansion rules makes
649
+ // way for more matches cases of multi-arg expressions; such that associative rules (such as
650
+ // 'n*n -> n^2') can be applied to exprs. such as 'a * b * b' and 'a * b * b * a'.
651
+ if (nonCommutative) {
652
+ // 'Non-commutative' 1: LHS (placeholder) only
653
+ newRule.expandedNC1 = {};
654
+ newRule.expandedNC1.l = makeNode([leftExpandsym, newRule.l]);
655
+ newRule.expandedNC1.r = makeNode([leftExpandsym, newRule.r]);
656
+ // 'Non-commutative' 2: farmost LHS and RHS placeholders
657
+ newRule.expandedNC2 = {};
658
+ newRule.expandedNC2.l = makeNode([leftExpandsym, newRule.expanded.l]);
659
+ newRule.expandedNC2.r = makeNode([leftExpandsym, newRule.expanded.r]);
660
+ }
611
661
  }
612
662
  return newRule;
613
663
  }
@@ -813,6 +863,16 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
813
863
  repl = rule.expanded.r;
814
864
  matches = _ruleMatch(rule.expanded.l, res, mergedContext)[0];
815
865
  }
866
+ // Additional, non-commutative context expansion-rules
867
+ if (!matches && rule.expandedNC1) {
868
+ repl = rule.expandedNC1.r;
869
+ matches = _ruleMatch(rule.expandedNC1.l, res, mergedContext)[0];
870
+ if (!matches) {
871
+ // Existence of NC1 implies NC2
872
+ repl = rule.expandedNC2.r;
873
+ matches = _ruleMatch(rule.expandedNC2.l, res, mergedContext)[0];
874
+ }
875
+ }
816
876
  if (matches) {
817
877
  // const before = res.toString({parenthesis: 'all'})
818
878
 
@@ -1030,8 +1090,8 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
1030
1090
  res = mergeChildMatches(childMatches);
1031
1091
  } else if (node.args.length >= 2 && rule.args.length === 2) {
1032
1092
  // node is flattened, rule is not
1033
- // Associative operators/functions can be split in different ways so we check if the rule matches each
1034
- // them and return their union.
1093
+ // Associative operators/functions can be split in different ways so we check if the rule
1094
+ // matches for each of them and return their union.
1035
1095
  var splits = getSplits(node, context);
1036
1096
  var splitMatches = [];
1037
1097
  for (var _i2 = 0; _i2 < splits.length; _i2++) {
@@ -1047,9 +1107,8 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
1047
1107
  }
1048
1108
  } else if (rule instanceof SymbolNode) {
1049
1109
  // If the rule is a SymbolNode, then it carries a special meaning
1050
- // according to the first character of the symbol node name.
1051
- // c.* matches a ConstantNode
1052
- // n.* matches any node
1110
+ // according to the first one or two characters of the symbol node name.
1111
+ // These meanings are expalined in the documentation for simplify()
1053
1112
  if (rule.name.length === 0) {
1054
1113
  throw new Error('Symbol in rule has 0 length...!?');
1055
1114
  }
@@ -1058,29 +1117,83 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
1058
1117
  if (rule.name !== node.name) {
1059
1118
  return [];
1060
1119
  }
1061
- } else if (rule.name[0] === 'n' || rule.name.substring(0, 2) === '_p') {
1062
- // rule matches _anything_, so assign this node to the rule.name placeholder
1063
- // Assign node to the rule.name placeholder.
1064
- // Our parent will check for matches among placeholders.
1065
- res[0].placeholders[rule.name] = node;
1066
- } else if (rule.name[0] === 'v') {
1067
- // rule matches any variable thing (not a ConstantNode)
1068
- if (!isConstantNode(node)) {
1069
- res[0].placeholders[rule.name] = node;
1070
- } else {
1071
- // Mis-match: rule was expecting something other than a ConstantNode
1072
- return [];
1073
- }
1074
- } else if (rule.name[0] === 'c') {
1075
- // rule matches any ConstantNode
1076
- if (node instanceof ConstantNode) {
1077
- res[0].placeholders[rule.name] = node;
1078
- } else {
1079
- // Mis-match: rule was expecting a ConstantNode
1080
- return [];
1081
- }
1082
1120
  } else {
1083
- throw new Error('Invalid symbol in rule: ' + rule.name);
1121
+ // wildcards are composed of up to two alphabetic or underscore characters
1122
+ switch (rule.name[1] >= 'a' && rule.name[1] <= 'z' ? rule.name.substring(0, 2) : rule.name[0]) {
1123
+ case 'n':
1124
+ case '_p':
1125
+ // rule matches _anything_, so assign this node to the rule.name placeholder
1126
+ // Assign node to the rule.name placeholder.
1127
+ // Our parent will check for matches among placeholders.
1128
+ res[0].placeholders[rule.name] = node;
1129
+ break;
1130
+ case 'c':
1131
+ case 'cl':
1132
+ // rule matches a ConstantNode
1133
+ if (isConstantNode(node)) {
1134
+ res[0].placeholders[rule.name] = node;
1135
+ } else {
1136
+ // mis-match: rule does not encompass current node
1137
+ return [];
1138
+ }
1139
+ break;
1140
+ case 'v':
1141
+ // rule matches anything other than a ConstantNode
1142
+ if (!isConstantNode(node)) {
1143
+ res[0].placeholders[rule.name] = node;
1144
+ } else {
1145
+ // mis-match: rule does not encompass current node
1146
+ return [];
1147
+ }
1148
+ break;
1149
+ case 'vl':
1150
+ // rule matches VariableNode
1151
+ if (isVariableNode(node)) {
1152
+ res[0].placeholders[rule.name] = node;
1153
+ } else {
1154
+ // mis-match: rule does not encompass current node
1155
+ return [];
1156
+ }
1157
+ break;
1158
+ case 'cd':
1159
+ // rule matches a ConstantNode or unaryMinus-wrapped ConstantNode
1160
+ if (isNumericNode(node)) {
1161
+ res[0].placeholders[rule.name] = node;
1162
+ } else {
1163
+ // mis-match: rule does not encompass current node
1164
+ return [];
1165
+ }
1166
+ break;
1167
+ case 'vd':
1168
+ // rule matches anything other than a ConstantNode or unaryMinus-wrapped ConstantNode
1169
+ if (!isNumericNode(node)) {
1170
+ res[0].placeholders[rule.name] = node;
1171
+ } else {
1172
+ // mis-match: rule does not encompass current node
1173
+ return [];
1174
+ }
1175
+ break;
1176
+ case 'ce':
1177
+ // rule matches expressions that have a constant value
1178
+ if (isConstantExpression(node)) {
1179
+ res[0].placeholders[rule.name] = node;
1180
+ } else {
1181
+ // mis-match: rule does not encompass current node
1182
+ return [];
1183
+ }
1184
+ break;
1185
+ case 've':
1186
+ // rule matches expressions that do not have a constant value
1187
+ if (!isConstantExpression(node)) {
1188
+ res[0].placeholders[rule.name] = node;
1189
+ } else {
1190
+ // mis-match: rule does not encompass current node
1191
+ return [];
1192
+ }
1193
+ break;
1194
+ default:
1195
+ throw new Error('Invalid symbol in rule: ' + rule.name);
1196
+ }
1084
1197
  }
1085
1198
  } else if (rule instanceof ConstantNode) {
1086
1199
  // Literal constant must match exactly
@@ -286,20 +286,37 @@ export var createSimplifyConstant = /* #__PURE__ */factory(name, dependencies, _
286
286
  * @return - Either a Node representing a binary expression or Fraction
287
287
  */
288
288
  function foldOp(fn, args, makeNode, options) {
289
- return args.reduce(function (a, b) {
290
- if (!isNode(a) && !isNode(b)) {
289
+ var first = args.shift();
290
+
291
+ // In the following reduction, sofar always has one of the three following
292
+ // forms: [NODE], [CONSTANT], or [NODE, CONSTANT]
293
+ var reduction = args.reduce((sofar, next) => {
294
+ if (!isNode(next)) {
295
+ var last = sofar.pop();
296
+ if (isNode(last)) {
297
+ return [last, next];
298
+ }
299
+ // Two constants in a row, try to fold them into one
291
300
  try {
292
- return _eval(fn, [a, b], options);
293
- } catch (ignoreandcontinue) {}
294
- a = _toNode(a);
295
- b = _toNode(b);
296
- } else if (!isNode(a)) {
297
- a = _toNode(a);
298
- } else if (!isNode(b)) {
299
- b = _toNode(b);
301
+ sofar.push(_eval(fn, [last, next], options));
302
+ return sofar;
303
+ } catch (ignoreandcontinue) {
304
+ sofar.push(last);
305
+ // fall through to Node case
306
+ }
300
307
  }
301
- return makeNode([a, b]);
302
- });
308
+
309
+ // Encountered a Node, or failed folding --
310
+ // collapse everything so far into a single tree:
311
+ sofar.push(_ensureNode(sofar.pop()));
312
+ var newtree = sofar.length === 1 ? sofar[0] : makeNode(sofar);
313
+ return [makeNode([newtree, _ensureNode(next)])];
314
+ }, [first]);
315
+ if (reduction.length === 1) {
316
+ return reduction[0];
317
+ }
318
+ // Might end up with a tree and a constant at the end:
319
+ return makeNode([reduction[0], _toNode(reduction[1])]);
303
320
  }
304
321
 
305
322
  // destroys the original node and returns a folded one
@@ -0,0 +1,118 @@
1
+ import { factory } from '../../utils/factory.js';
2
+ var name = 'sylvester';
3
+ var dependencies = ['typed', 'schur', 'matrixFromColumns', 'matrix', 'multiply', 'range', 'concat', 'transpose', 'index', 'subset', 'add', 'subtract', 'identity', 'lusolve', 'abs'];
4
+ export var createSylvester = /* #__PURE__ */factory(name, dependencies, _ref => {
5
+ var {
6
+ typed,
7
+ schur,
8
+ matrixFromColumns,
9
+ matrix,
10
+ multiply,
11
+ range,
12
+ concat,
13
+ transpose,
14
+ index,
15
+ subset,
16
+ add,
17
+ subtract,
18
+ identity,
19
+ lusolve,
20
+ abs
21
+ } = _ref;
22
+ /**
23
+ *
24
+ * Solves the real-valued Sylvester equation AX+XB=C for X, where A, B and C are
25
+ * matrices of appropriate dimensions, being A and B squared. Notice that other
26
+ * equivalent definitions for the Sylvester equation exist and this function
27
+ * assumes the one presented in the original publication of the the Bartels-
28
+ * Stewart algorithm, which is implemented by this function.
29
+ * https://en.wikipedia.org/wiki/Sylvester_equation
30
+ *
31
+ * Syntax:
32
+ *
33
+ * math.sylvester(A, B, C)
34
+ *
35
+ * Examples:
36
+ *
37
+ * const A = [[-1, -2], [1, 1]]
38
+ * const B = [[2, -1], [1, -2]]
39
+ * const C = [[-3, 2], [3, 0]]
40
+ * math.sylvester(A, B, C) // returns DenseMatrix [[-0.25, 0.25], [1.5, -1.25]]
41
+ *
42
+ * See also:
43
+ *
44
+ * schur, lyap
45
+ *
46
+ * @param {Matrix | Array} A Matrix A
47
+ * @param {Matrix | Array} B Matrix B
48
+ * @param {Matrix | Array} C Matrix C
49
+ * @return {Matrix | Array} Matrix X, solving the Sylvester equation
50
+ */
51
+ return typed(name, {
52
+ 'Matrix, Matrix, Matrix': _sylvester,
53
+ 'Array, Matrix, Matrix': function ArrayMatrixMatrix(A, B, C) {
54
+ return _sylvester(matrix(A), B, C);
55
+ },
56
+ 'Array, Array, Matrix': function ArrayArrayMatrix(A, B, C) {
57
+ return _sylvester(matrix(A), matrix(B), C);
58
+ },
59
+ 'Array, Matrix, Array': function ArrayMatrixArray(A, B, C) {
60
+ return _sylvester(matrix(A), B, matrix(C));
61
+ },
62
+ 'Matrix, Array, Matrix': function MatrixArrayMatrix(A, B, C) {
63
+ return _sylvester(A, matrix(B), C);
64
+ },
65
+ 'Matrix, Array, Array': function MatrixArrayArray(A, B, C) {
66
+ return _sylvester(A, matrix(B), matrix(C));
67
+ },
68
+ 'Matrix, Matrix, Array': function MatrixMatrixArray(A, B, C) {
69
+ return _sylvester(A, B, matrix(C));
70
+ },
71
+ 'Array, Array, Array': function ArrayArrayArray(A, B, C) {
72
+ return _sylvester(matrix(A), matrix(B), matrix(C)).toArray();
73
+ }
74
+ });
75
+ function _sylvester(A, B, C) {
76
+ var n = B.size()[0];
77
+ var m = A.size()[0];
78
+ var sA = schur(A);
79
+ var F = sA.T;
80
+ var U = sA.U;
81
+ var sB = schur(multiply(-1, B));
82
+ var G = sB.T;
83
+ var V = sB.U;
84
+ var D = multiply(multiply(transpose(U), C), V);
85
+ var all = range(0, m);
86
+ var y = [];
87
+ var hc = (a, b) => concat(a, b, 1);
88
+ var vc = (a, b) => concat(a, b, 0);
89
+ for (var k = 0; k < n; k++) {
90
+ if (k < n - 1 && abs(subset(G, index(k + 1, k))) > 1e-5) {
91
+ var RHS = vc(subset(D, index(all, k)), subset(D, index(all, k + 1)));
92
+ for (var j = 0; j < k; j++) {
93
+ RHS = add(RHS, vc(multiply(y[j], subset(G, index(j, k))), multiply(y[j], subset(G, index(j, k + 1)))));
94
+ }
95
+ var gkk = multiply(identity(m), multiply(-1, subset(G, index(k, k))));
96
+ var gmk = multiply(identity(m), multiply(-1, subset(G, index(k + 1, k))));
97
+ var gkm = multiply(identity(m), multiply(-1, subset(G, index(k, k + 1))));
98
+ var gmm = multiply(identity(m), multiply(-1, subset(G, index(k + 1, k + 1))));
99
+ var LHS = vc(hc(add(F, gkk), gmk), hc(gkm, add(F, gmm)));
100
+ var yAux = lusolve(LHS, RHS);
101
+ y[k] = yAux.subset(index(range(0, m), 0));
102
+ y[k + 1] = yAux.subset(index(range(m, 2 * m), 0));
103
+ k++;
104
+ } else {
105
+ var _RHS = subset(D, index(all, k));
106
+ for (var _j = 0; _j < k; _j++) {
107
+ _RHS = add(_RHS, multiply(y[_j], subset(G, index(_j, k))));
108
+ }
109
+ var _gkk = subset(G, index(k, k));
110
+ var _LHS = subtract(F, multiply(_gkk, identity(m)));
111
+ y[k] = lusolve(_LHS, _RHS);
112
+ }
113
+ }
114
+ var Y = matrix(matrixFromColumns(...y));
115
+ var X = multiply(U, multiply(Y, transpose(V)));
116
+ return X;
117
+ }
118
+ });
@@ -33,7 +33,7 @@ export var createForEach = /* #__PURE__ */factory(name, dependencies, _ref => {
33
33
  return typed(name, {
34
34
  'Array, function': _forEach,
35
35
  'Matrix, function': function MatrixFunction(x, callback) {
36
- return x.forEach(callback);
36
+ x.forEach(callback);
37
37
  }
38
38
  });
39
39
  });
@@ -49,7 +49,7 @@ export var createReshape = /* #__PURE__ */factory(name, dependencies, _ref => {
49
49
  */
50
50
  return typed(name, {
51
51
  'Matrix, Array': function MatrixArray(x, sizes) {
52
- return x.reshape(sizes);
52
+ return x.reshape(sizes, true);
53
53
  },
54
54
  'Array, Array': function ArrayArray(x, sizes) {
55
55
  sizes.forEach(function (size) {