mathjs 10.2.0 → 10.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. package/HISTORY.md +43 -0
  2. package/docs/expressions/syntax.md +31 -2
  3. package/docs/reference/functions/cumsum.md +57 -0
  4. package/docs/reference/functions/format.md +1 -1
  5. package/docs/reference/functions/map.md +22 -5
  6. package/docs/reference/functions/subset.md +10 -2
  7. package/docs/reference/functions/sum.md +2 -1
  8. package/docs/reference/functions/symbolicEqual.md +62 -0
  9. package/docs/reference/functions.md +3 -1
  10. package/lib/browser/math.js +6 -6
  11. package/lib/browser/math.js.map +1 -1
  12. package/lib/cjs/entry/dependenciesAny/dependenciesCumSum.generated.js +26 -0
  13. package/lib/cjs/entry/dependenciesAny/dependenciesCumSumTransform.generated.js +26 -0
  14. package/lib/cjs/entry/dependenciesAny/dependenciesSymbolicEqual.generated.js +29 -0
  15. package/lib/cjs/entry/dependenciesAny.generated.js +24 -0
  16. package/lib/cjs/entry/dependenciesNumber/dependenciesCumSum.generated.js +26 -0
  17. package/lib/cjs/entry/dependenciesNumber/dependenciesCumSumTransform.generated.js +26 -0
  18. package/lib/cjs/entry/dependenciesNumber.generated.js +16 -0
  19. package/lib/cjs/entry/impureFunctionsAny.generated.js +22 -8
  20. package/lib/cjs/entry/impureFunctionsNumber.generated.js +6 -0
  21. package/lib/cjs/entry/pureFunctionsAny.generated.js +18 -12
  22. package/lib/cjs/entry/pureFunctionsNumber.generated.js +8 -2
  23. package/lib/cjs/expression/embeddedDocs/construction/fraction.js +3 -3
  24. package/lib/cjs/expression/embeddedDocs/embeddedDocs.js +240 -234
  25. package/lib/cjs/expression/embeddedDocs/function/algebra/symbolicEqual.js +15 -0
  26. package/lib/cjs/expression/embeddedDocs/function/matrix/subset.js +2 -2
  27. package/lib/cjs/expression/embeddedDocs/function/statistics/cumsum.js +15 -0
  28. package/lib/cjs/expression/node/FunctionNode.js +74 -55
  29. package/lib/cjs/expression/parse.js +12 -8
  30. package/lib/cjs/expression/transform/cumsum.transform.js +57 -0
  31. package/lib/cjs/expression/transform/sum.transform.js +1 -1
  32. package/lib/cjs/factoriesAny.js +24 -0
  33. package/lib/cjs/factoriesNumber.js +18 -2
  34. package/lib/cjs/function/algebra/simplify.js +8 -0
  35. package/lib/cjs/function/algebra/simplifyCore.js +2 -2
  36. package/lib/cjs/function/algebra/symbolicEqual.js +88 -0
  37. package/lib/cjs/function/matrix/eigs/complexEigs.js +39 -28
  38. package/lib/cjs/function/matrix/map.js +53 -15
  39. package/lib/cjs/function/matrix/subset.js +15 -5
  40. package/lib/cjs/function/statistics/cumsum.js +151 -0
  41. package/lib/cjs/function/statistics/sum.js +1 -1
  42. package/lib/cjs/function/string/format.js +1 -1
  43. package/lib/cjs/header.js +2 -2
  44. package/lib/cjs/type/fraction/function/fraction.js +20 -8
  45. package/lib/cjs/utils/collection.js +3 -27
  46. package/lib/cjs/utils/switch.js +31 -0
  47. package/lib/cjs/version.js +1 -1
  48. package/lib/esm/entry/dependenciesAny/dependenciesCumSum.generated.js +14 -0
  49. package/lib/esm/entry/dependenciesAny/dependenciesCumSumTransform.generated.js +14 -0
  50. package/lib/esm/entry/dependenciesAny/dependenciesSymbolicEqual.generated.js +16 -0
  51. package/lib/esm/entry/dependenciesAny.generated.js +3 -0
  52. package/lib/esm/entry/dependenciesNumber/dependenciesCumSum.generated.js +14 -0
  53. package/lib/esm/entry/dependenciesNumber/dependenciesCumSumTransform.generated.js +14 -0
  54. package/lib/esm/entry/dependenciesNumber.generated.js +2 -0
  55. package/lib/esm/entry/impureFunctionsAny.generated.js +22 -9
  56. package/lib/esm/entry/impureFunctionsNumber.generated.js +8 -2
  57. package/lib/esm/entry/pureFunctionsAny.generated.js +13 -8
  58. package/lib/esm/entry/pureFunctionsNumber.generated.js +6 -1
  59. package/lib/esm/expression/embeddedDocs/construction/fraction.js +3 -3
  60. package/lib/esm/expression/embeddedDocs/embeddedDocs.js +220 -216
  61. package/lib/esm/expression/embeddedDocs/function/algebra/symbolicEqual.js +8 -0
  62. package/lib/esm/expression/embeddedDocs/function/matrix/subset.js +2 -2
  63. package/lib/esm/expression/embeddedDocs/function/statistics/cumsum.js +8 -0
  64. package/lib/esm/expression/node/FunctionNode.js +70 -53
  65. package/lib/esm/expression/parse.js +12 -8
  66. package/lib/esm/expression/transform/cumsum.transform.js +48 -0
  67. package/lib/esm/expression/transform/sum.transform.js +1 -1
  68. package/lib/esm/factoriesAny.js +3 -0
  69. package/lib/esm/factoriesNumber.js +2 -0
  70. package/lib/esm/function/algebra/simplify.js +8 -0
  71. package/lib/esm/function/algebra/simplifyCore.js +2 -2
  72. package/lib/esm/function/algebra/symbolicEqual.js +80 -0
  73. package/lib/esm/function/matrix/eigs/complexEigs.js +36 -25
  74. package/lib/esm/function/matrix/map.js +53 -15
  75. package/lib/esm/function/matrix/subset.js +15 -5
  76. package/lib/esm/function/statistics/cumsum.js +139 -0
  77. package/lib/esm/function/statistics/sum.js +1 -1
  78. package/lib/esm/function/string/format.js +1 -1
  79. package/lib/esm/type/fraction/function/fraction.js +20 -8
  80. package/lib/esm/utils/collection.js +1 -26
  81. package/lib/esm/utils/switch.js +24 -0
  82. package/lib/esm/version.js +1 -1
  83. package/package.json +15 -11
  84. package/types/index.d.ts +209 -23
  85. package/types/index.ts +274 -57
  86. package/types/tsconfig.json +2 -1
@@ -77,76 +77,93 @@ export var createFunctionNode = /* #__PURE__ */factory(name, dependencies, _ref
77
77
  var evalArgs = this.args.map(arg => arg._compile(math, argNames));
78
78
 
79
79
  if (isSymbolNode(this.fn)) {
80
- // we can statically determine whether the function has an rawArgs property
81
80
  var _name = this.fn.name;
82
- var fn = _name in math ? getSafeProperty(math, _name) : undefined;
83
- var isRaw = typeof fn === 'function' && fn.rawArgs === true;
84
81
 
85
- var resolveFn = scope => {
86
- if (scope.has(_name)) {
87
- return scope.get(_name);
88
- }
82
+ if (!argNames[_name]) {
83
+ // we can statically determine whether the function has an rawArgs property
84
+ var fn = _name in math ? getSafeProperty(math, _name) : undefined;
85
+ var isRaw = typeof fn === 'function' && fn.rawArgs === true;
89
86
 
90
- if (_name in math) {
91
- return getSafeProperty(math, _name);
92
- }
87
+ var resolveFn = scope => {
88
+ if (scope.has(_name)) {
89
+ return scope.get(_name);
90
+ }
93
91
 
94
- return FunctionNode.onUndefinedFunction(_name);
95
- };
92
+ if (_name in math) {
93
+ return getSafeProperty(math, _name);
94
+ }
96
95
 
97
- if (isRaw) {
98
- // pass unevaluated parameters (nodes) to the function
99
- // "raw" evaluation
100
- var rawArgs = this.args;
101
- return function evalFunctionNode(scope, args, context) {
102
- var fn = resolveFn(scope);
103
- return fn(rawArgs, math, createSubScope(scope, args), scope);
96
+ return FunctionNode.onUndefinedFunction(_name);
104
97
  };
105
- } else {
106
- // "regular" evaluation
107
- switch (evalArgs.length) {
108
- case 0:
109
- return function evalFunctionNode(scope, args, context) {
110
- var fn = resolveFn(scope);
111
- return fn();
112
- };
113
-
114
- case 1:
115
- return function evalFunctionNode(scope, args, context) {
116
- var fn = resolveFn(scope);
117
- var evalArg0 = evalArgs[0];
118
- return fn(evalArg0(scope, args, context));
119
- };
120
-
121
- case 2:
122
- return function evalFunctionNode(scope, args, context) {
123
- var fn = resolveFn(scope);
124
- var evalArg0 = evalArgs[0];
125
- var evalArg1 = evalArgs[1];
126
- return fn(evalArg0(scope, args, context), evalArg1(scope, args, context));
127
- };
128
-
129
- default:
130
- return function evalFunctionNode(scope, args, context) {
131
- var fn = resolveFn(scope);
132
- var values = evalArgs.map(evalArg => evalArg(scope, args, context));
133
- return fn(...values);
134
- };
98
+
99
+ if (isRaw) {
100
+ // pass unevaluated parameters (nodes) to the function
101
+ // "raw" evaluation
102
+ var rawArgs = this.args;
103
+ return function evalFunctionNode(scope, args, context) {
104
+ var fn = resolveFn(scope);
105
+ return fn(rawArgs, math, createSubScope(scope, args), scope);
106
+ };
107
+ } else {
108
+ // "regular" evaluation
109
+ switch (evalArgs.length) {
110
+ case 0:
111
+ return function evalFunctionNode(scope, args, context) {
112
+ var fn = resolveFn(scope);
113
+ return fn();
114
+ };
115
+
116
+ case 1:
117
+ return function evalFunctionNode(scope, args, context) {
118
+ var fn = resolveFn(scope);
119
+ var evalArg0 = evalArgs[0];
120
+ return fn(evalArg0(scope, args, context));
121
+ };
122
+
123
+ case 2:
124
+ return function evalFunctionNode(scope, args, context) {
125
+ var fn = resolveFn(scope);
126
+ var evalArg0 = evalArgs[0];
127
+ var evalArg1 = evalArgs[1];
128
+ return fn(evalArg0(scope, args, context), evalArg1(scope, args, context));
129
+ };
130
+
131
+ default:
132
+ return function evalFunctionNode(scope, args, context) {
133
+ var fn = resolveFn(scope);
134
+ var values = evalArgs.map(evalArg => evalArg(scope, args, context));
135
+ return fn(...values);
136
+ };
137
+ }
135
138
  }
139
+ } else {
140
+ // the function symbol is an argName
141
+ var _rawArgs = this.args;
142
+ return function evalFunctionNode(scope, args, context) {
143
+ var fn = args[_name];
144
+ var isRaw = fn && fn.rawArgs;
145
+
146
+ if (isRaw) {
147
+ return fn(_rawArgs, math, createSubScope(scope, args), scope); // "raw" evaluation
148
+ } else {
149
+ var values = evalArgs.map(evalArg => evalArg(scope, args, context));
150
+ return fn.apply(fn, values);
151
+ }
152
+ };
136
153
  }
137
154
  } else if (isAccessorNode(this.fn) && isIndexNode(this.fn.index) && this.fn.index.isObjectProperty()) {
138
155
  // execute the function with the right context: the object of the AccessorNode
139
156
  var evalObject = this.fn.object._compile(math, argNames);
140
157
 
141
158
  var prop = this.fn.index.getObjectProperty();
142
- var _rawArgs = this.args;
159
+ var _rawArgs2 = this.args;
143
160
  return function evalFunctionNode(scope, args, context) {
144
161
  var object = evalObject(scope, args, context);
145
162
  validateSafeMethod(object, prop);
146
163
  var isRaw = object[prop] && object[prop].rawArgs;
147
164
 
148
165
  if (isRaw) {
149
- return object[prop](_rawArgs, math, createSubScope(scope, args), scope); // "raw" evaluation
166
+ return object[prop](_rawArgs2, math, createSubScope(scope, args), scope); // "raw" evaluation
150
167
  } else {
151
168
  // "regular" evaluation
152
169
  var values = evalArgs.map(evalArg => evalArg(scope, args, context));
@@ -158,13 +175,13 @@ export var createFunctionNode = /* #__PURE__ */factory(name, dependencies, _ref
158
175
  // we have to dynamically determine whether the function has a rawArgs property
159
176
  var evalFn = this.fn._compile(math, argNames);
160
177
 
161
- var _rawArgs2 = this.args;
178
+ var _rawArgs3 = this.args;
162
179
  return function evalFunctionNode(scope, args, context) {
163
180
  var fn = evalFn(scope, args, context);
164
181
  var isRaw = fn && fn.rawArgs;
165
182
 
166
183
  if (isRaw) {
167
- return fn(_rawArgs2, math, createSubScope(scope, args), scope); // "raw" evaluation
184
+ return fn(_rawArgs3, math, createSubScope(scope, args), scope); // "raw" evaluation
168
185
  } else {
169
186
  // "regular" evaluation
170
187
  var values = evalArgs.map(evalArg => evalArg(scope, args, context));
@@ -241,18 +241,22 @@ export var createParse = /* #__PURE__ */factory(name, dependencies, _ref => {
241
241
  function getToken(state) {
242
242
  state.tokenType = TOKENTYPE.NULL;
243
243
  state.token = '';
244
- state.comment = ''; // skip over whitespaces
245
- // space, tab, and newline when inside parameters
244
+ state.comment = ''; // skip over ignored characters:
246
245
 
247
- while (parse.isWhitespace(currentCharacter(state), state.nestingLevel)) {
248
- next(state);
249
- } // skip comment
246
+ while (true) {
247
+ // comments:
248
+ if (currentCharacter(state) === '#') {
249
+ while (currentCharacter(state) !== '\n' && currentCharacter(state) !== '') {
250
+ state.comment += currentCharacter(state);
251
+ next(state);
252
+ }
253
+ } // whitespace: space, tab, and newline when inside parameters
250
254
 
251
255
 
252
- if (currentCharacter(state) === '#') {
253
- while (currentCharacter(state) !== '\n' && currentCharacter(state) !== '') {
254
- state.comment += currentCharacter(state);
256
+ if (parse.isWhitespace(currentCharacter(state), state.nestingLevel)) {
255
257
  next(state);
258
+ } else {
259
+ break;
256
260
  }
257
261
  } // check for end of expression
258
262
 
@@ -0,0 +1,48 @@
1
+ import { isBigNumber, isCollection, isNumber } from '../../utils/is.js';
2
+ import { factory } from '../../utils/factory.js';
3
+ import { errorTransform } from './utils/errorTransform.js';
4
+ import { createCumSum } from '../../function/statistics/cumsum.js';
5
+ /**
6
+ * Attach a transform function to math.sum
7
+ * Adds a property transform containing the transform function.
8
+ *
9
+ * This transform changed the last `dim` parameter of function sum
10
+ * from one-based to zero based
11
+ */
12
+
13
+ var name = 'cumsum';
14
+ var dependencies = ['typed', 'add', 'unaryPlus'];
15
+ export var createCumSumTransform = /* #__PURE__ */factory(name, dependencies, _ref => {
16
+ var {
17
+ typed,
18
+ add,
19
+ unaryPlus
20
+ } = _ref;
21
+ var cumsum = createCumSum({
22
+ typed,
23
+ add,
24
+ unaryPlus
25
+ });
26
+ return typed(name, {
27
+ '...any': function any(args) {
28
+ // change last argument dim from one-based to zero-based
29
+ if (args.length === 2 && isCollection(args[0])) {
30
+ var dim = args[1];
31
+
32
+ if (isNumber(dim)) {
33
+ args[1] = dim - 1;
34
+ } else if (isBigNumber(dim)) {
35
+ args[1] = dim.minus(1);
36
+ }
37
+ }
38
+
39
+ try {
40
+ return cumsum.apply(null, args);
41
+ } catch (err) {
42
+ throw errorTransform(err);
43
+ }
44
+ }
45
+ });
46
+ }, {
47
+ isTransformFunction: true
48
+ });
@@ -6,7 +6,7 @@ import { lastDimToZeroBase } from './utils/lastDimToZeroBase.js';
6
6
  * Attach a transform function to math.sum
7
7
  * Adds a property transform containing the transform function.
8
8
  *
9
- * This transform changed the last `dim` parameter of function mean
9
+ * This transform changed the last `dim` parameter of function sum
10
10
  * from one-based to zero based
11
11
  */
12
12
 
@@ -221,6 +221,7 @@ export { createDivide } from './function/arithmetic/divide.js';
221
221
  export { createDistance } from './function/geometry/distance.js';
222
222
  export { createIntersect } from './function/geometry/intersect.js';
223
223
  export { createSum } from './function/statistics/sum.js';
224
+ export { createCumSum } from './function/statistics/cumsum.js';
224
225
  export { createMean } from './function/statistics/mean.js';
225
226
  export { createMedian } from './function/statistics/median.js';
226
227
  export { createMad } from './function/statistics/mad.js';
@@ -245,6 +246,7 @@ export { createLeafCount } from './function/algebra/leafCount.js';
245
246
  export { createSimplify } from './function/algebra/simplify.js';
246
247
  export { createSimplifyCore } from './function/algebra/simplifyCore.js';
247
248
  export { createResolve } from './function/algebra/resolve.js';
249
+ export { createSymbolicEqual } from './function/algebra/symbolicEqual.js';
248
250
  export { createDerivative } from './function/algebra/derivative.js';
249
251
  export { createRationalize } from './function/algebra/rationalize.js';
250
252
  export { createReviver } from './json/reviver.js';
@@ -268,4 +270,5 @@ export { createConcatTransform } from './expression/transform/concat.transform.j
268
270
  export { createDiffTransform } from './expression/transform/diff.transform.js';
269
271
  export { createStdTransform } from './expression/transform/std.transform.js';
270
272
  export { createSumTransform } from './expression/transform/sum.transform.js';
273
+ export { createCumSumTransform } from './expression/transform/cumsum.transform.js';
271
274
  export { createVarianceTransform } from './expression/transform/variance.transform.js';
@@ -146,6 +146,7 @@ export { createProd } from './function/statistics/prod.js';
146
146
  export { createMax } from './function/statistics/max.js';
147
147
  export { createMin } from './function/statistics/min.js';
148
148
  export { createSum } from './function/statistics/sum.js';
149
+ export { createCumSum } from './function/statistics/cumsum.js';
149
150
  export { createMean } from './function/statistics/mean.js';
150
151
  export { createMedian } from './function/statistics/median.js';
151
152
  export { createMad } from './function/statistics/mad.js';
@@ -195,6 +196,7 @@ export var createSubsetTransform = /* #__PURE__ */factory('subset', [], () => no
195
196
  });
196
197
  export { createStdTransform } from './expression/transform/std.transform.js';
197
198
  export { createSumTransform } from './expression/transform/sum.transform.js';
199
+ export { createCumSumTransform } from './expression/transform/cumsum.transform.js';
198
200
  export { createVarianceTransform } from './expression/transform/variance.transform.js'; // utils
199
201
 
200
202
  export { createClone } from './function/utils/clone.js';
@@ -327,6 +327,14 @@ export var createSimplify = /* #__PURE__ */factory(name, dependencies, _ref => {
327
327
  total: true
328
328
  }
329
329
  }
330
+ }, {
331
+ s: 'n-n -> 0',
332
+ // partial alternative when we can't always subtract
333
+ assuming: {
334
+ subtract: {
335
+ total: false
336
+ }
337
+ }
330
338
  }, {
331
339
  s: '-(c*v) -> v * (-c)',
332
340
  // make non-constant terms positive
@@ -206,9 +206,9 @@ export var createSimplifyCore = /* #__PURE__ */factory(name, dependencies, _ref
206
206
  }
207
207
  }
208
208
  }
209
-
210
- return new OperatorNode(node.op, node.fn, [_a, a1]);
211
209
  }
210
+
211
+ return new OperatorNode(node.op, node.fn, [_a, a1]);
212
212
  } else if (isFunctionNode(node)) {
213
213
  return new FunctionNode(simplifyCore(node.fn), node.args.map(n => simplifyCore(n, options)));
214
214
  } else if (isArrayNode(node)) {
@@ -0,0 +1,80 @@
1
+ import { isConstantNode } from '../../utils/is.js';
2
+ import { factory } from '../../utils/factory.js';
3
+ var name = 'symbolicEqual';
4
+ var dependencies = ['parse', 'simplify', 'typed', 'OperatorNode'];
5
+ export var createSymbolicEqual = /* #__PURE__ */factory(name, dependencies, _ref => {
6
+ var {
7
+ parse,
8
+ simplify,
9
+ typed,
10
+ OperatorNode
11
+ } = _ref;
12
+
13
+ /**
14
+ * Attempts to determine if two expressions are symbolically equal, i.e.
15
+ * one is the result of valid algebraic manipulations on the other.
16
+ * Currently, this simply checks if the difference of the two expressions
17
+ * simplifies down to 0. So there are two important caveats:
18
+ * 1. whether two expressions are symbolically equal depends on the
19
+ * manipulations allowed. Therefore, this function takes an optional
20
+ * third argument, which are the options that control the behavior
21
+ * as documented for the `simplify()` function.
22
+ * 2. it is in general intractable to find the minimal simplification of
23
+ * an arbitrarily complicated expression. So while a `true` value
24
+ * of `symbolicEqual` ensures that the two expressions can be manipulated
25
+ * to match each other, a `false` value does not absolutely rule this out.
26
+ *
27
+ * Syntax:
28
+ *
29
+ * symbolicEqual(expr1, expr2)
30
+ * symbolicEqual(expr1, expr2, options)
31
+ *
32
+ * Examples:
33
+ *
34
+ * symbolicEqual('x*y', 'y*x') // true
35
+ * symbolicEqual('x*y', 'y*x', {context: {multiply: {commutative: false}}})
36
+ * //false
37
+ * symbolicEqual('x/y', '(y*x^(-1))^(-1)') // true
38
+ * symbolicEqual('abs(x)','x') // false
39
+ * symbolicEqual('abs(x)','x', simplify.positiveContext) // true
40
+ *
41
+ * See also:
42
+ *
43
+ * simplify, evaluate
44
+ *
45
+ * @param {Node|string} expr1 The first expression to compare
46
+ * @param {Node|string} expr2 The second expression to compare
47
+ * @param {Object} [options] Optional option object, passed to simplify
48
+ * @returns {boolean}
49
+ * Returns true if a valid manipulation making the expressions equal
50
+ * is found.
51
+ */
52
+ return typed(name, {
53
+ 'string, string': function stringString(s1, s2) {
54
+ return this(parse(s1), parse(s2), {});
55
+ },
56
+ 'string, string, Object': function stringStringObject(s1, s2, options) {
57
+ return this(parse(s1), parse(s2), options);
58
+ },
59
+ 'Node, string': function NodeString(e1, s2) {
60
+ return this(e1, parse(s2), {});
61
+ },
62
+ 'Node, string, Object': function NodeStringObject(e1, s2, options) {
63
+ return this(e1, parse(s2), options);
64
+ },
65
+ 'string, Node': function stringNode(s1, e2) {
66
+ return this(parse(s1), e2, {});
67
+ },
68
+ 'string, Node, Object': function stringNodeObject(s1, e2, options) {
69
+ return this(parse(s1), e2, options);
70
+ },
71
+ 'Node, Node': function NodeNode(e1, e2) {
72
+ return this(e1, e2, {});
73
+ },
74
+ 'Node, Node, Object': function NodeNodeObject(e1, e2, options) {
75
+ var diff = new OperatorNode('-', 'subtract', [e1, e2]);
76
+ var simplified = simplify(diff, {}, options);
77
+ return isConstantNode(simplified) && !simplified.value;
78
+ }
79
+ });
80
+ });
@@ -38,32 +38,36 @@ export function createComplexEigs(_ref) {
38
38
  } // TODO check if any row/col are zero except the diagonal
39
39
  // make sure corresponding rows and columns have similar magnitude
40
40
  // important because of numerical stability
41
+ // MODIFIES arr by side effect!
41
42
 
42
43
 
43
44
  var R = balance(arr, N, prec, type, findVectors); // R is the row transformation matrix
44
- // A' = R A R⁻¹, A is the original matrix
45
+ // arr = A' = R A R⁻¹, A is the original matrix
45
46
  // (if findVectors is false, R is undefined)
47
+ // (And so to return to original matrix: A = R⁻¹ arr R)
46
48
  // TODO if magnitudes of elements vary over many orders,
47
49
  // move greatest elements to the top left corner
48
50
  // using similarity transformations, reduce the matrix
49
51
  // to Hessenberg form (upper triangular plus one subdiagonal row)
50
52
  // updates the transformation matrix R with new row operationsq
53
+ // MODIFIES arr by side effect!
51
54
 
52
- reduceToHessenberg(arr, N, prec, type, findVectors, R); // find eigenvalues
55
+ reduceToHessenberg(arr, N, prec, type, findVectors, R); // still true that original A = R⁻¹ arr R)
56
+ // find eigenvalues
53
57
 
54
58
  var {
55
59
  values,
56
60
  C
57
61
  } = iterateUntilTriangular(arr, N, prec, type, findVectors); // values is the list of eigenvalues, C is the column
58
- // transformation matrix that transforms the hessenberg
59
- // matrix to upper triangular
60
- // compose transformations A hess. and hess. triang.
62
+ // transformation matrix that transforms arr, the hessenberg
63
+ // matrix, to upper triangular
64
+ // (So U = C⁻¹ arr C and the relationship between current arr
65
+ // and original A is unchanged.)
61
66
 
62
- C = multiply(inv(R), C);
63
67
  var vectors;
64
68
 
65
69
  if (findVectors) {
66
- vectors = findEigenvectors(arr, N, C, values, prec, type);
70
+ vectors = findEigenvectors(arr, N, C, R, values, prec, type);
67
71
  vectors = matrixFromColumns(...vectors);
68
72
  }
69
73
 
@@ -84,8 +88,9 @@ export function createComplexEigs(_ref) {
84
88
  function balance(arr, N, prec, type, findVectors) {
85
89
  var big = type === 'BigNumber';
86
90
  var cplx = type === 'Complex';
87
- var zero = big ? bignumber(0) : cplx ? complex(0) : 0;
88
- var one = big ? bignumber(1) : cplx ? complex(1) : 1; // base of the floating-point arithmetic
91
+ var realzero = big ? bignumber(0) : 0;
92
+ var one = big ? bignumber(1) : cplx ? complex(1) : 1;
93
+ var realone = big ? bignumber(1) : 1; // base of the floating-point arithmetic
89
94
 
90
95
  var radix = big ? bignumber(10) : 2;
91
96
  var radixSq = multiplyScalar(radix, radix); // the diagonal transformation matrix R
@@ -106,12 +111,13 @@ export function createComplexEigs(_ref) {
106
111
  for (var i = 0; i < N; i++) {
107
112
  // compute the taxicab norm of i-th column and row
108
113
  // TODO optimize for complex numbers
109
- var colNorm = zero;
110
- var rowNorm = zero;
114
+ var colNorm = realzero;
115
+ var rowNorm = realzero;
111
116
 
112
117
  for (var j = 0; j < N; j++) {
113
118
  if (i === j) continue;
114
- var c = abs(arr[i][j]);
119
+ var c = abs(arr[i][j]); // should be real
120
+
115
121
  colNorm = addScalar(colNorm, c);
116
122
  rowNorm = addScalar(rowNorm, c);
117
123
  }
@@ -120,7 +126,7 @@ export function createComplexEigs(_ref) {
120
126
  // find integer power closest to balancing the matrix
121
127
  // (we want to scale only by integer powers of radix,
122
128
  // so that we don't lose any precision due to round-off)
123
- var f = one;
129
+ var f = realone;
124
130
  var _c = colNorm;
125
131
  var rowDivRadix = divideScalar(rowNorm, radix);
126
132
  var rowMulRadix = multiplyScalar(rowNorm, radix);
@@ -392,16 +398,17 @@ export function createComplexEigs(_ref) {
392
398
  };
393
399
  }
394
400
  /**
395
- * @param {Matrix} A original matrix
401
+ * @param {Matrix} A hessenberg-form matrix
396
402
  * @param {number} N size of A
397
403
  * @param {Matrix} C column transformation matrix that turns A into upper triangular
404
+ * @param {Matrix} R similarity that turns original matrix into A
398
405
  * @param {number[]} values array of eigenvalues of A
399
406
  * @param {'number'|'BigNumber'|'Complex'} type
400
407
  * @returns {number[][]} eigenvalues
401
408
  */
402
409
 
403
410
 
404
- function findEigenvectors(A, N, C, values, prec, type) {
411
+ function findEigenvectors(A, N, C, R, values, prec, type) {
405
412
  var Cinv = inv(C);
406
413
  var U = multiply(Cinv, A, C);
407
414
  var big = type === 'BigNumber';
@@ -434,30 +441,34 @@ export function createComplexEigs(_ref) {
434
441
 
435
442
  var failedLambdas = [];
436
443
 
437
- for (var _i4 = 0; _i4 < len; _i4++) {
438
- var _λ = uniqueValues[_i4];
439
-
440
- var _A = subtract(U, multiply(_λ, E)); // the characteristic matrix
441
-
444
+ var _loop = function _loop(_i4) {
445
+ var λ = uniqueValues[_i4];
446
+ var S = subtract(U, multiply(λ, E)); // the characteristic matrix
442
447
 
443
- var solutions = usolveAll(_A, b);
444
- solutions = solutions.map(v => multiply(C, v));
448
+ var solutions = usolveAll(S, b);
445
449
  solutions.shift(); // ignore the null vector
446
450
  // looks like we missed something, try inverse iteration
447
451
 
448
452
  while (solutions.length < multiplicities[_i4]) {
449
- var approxVec = inverseIterate(_A, N, solutions, prec, type);
453
+ var approxVec = inverseIterate(S, N, solutions, prec, type);
450
454
 
451
455
  if (approxVec == null) {
452
456
  // no more vectors were found
453
- failedLambdas.push(_λ);
457
+ failedLambdas.push(λ);
454
458
  break;
455
459
  }
456
460
 
457
461
  solutions.push(approxVec);
458
- }
462
+ } // Transform back into original array coordinates
463
+
459
464
 
465
+ var correction = multiply(inv(R), C);
466
+ solutions = solutions.map(v => multiply(correction, v));
460
467
  vectors.push(...solutions.map(v => flatten(v)));
468
+ };
469
+
470
+ for (var _i4 = 0; _i4 < len; _i4++) {
471
+ _loop(_i4);
461
472
  }
462
473
 
463
474
  if (failedLambdas.length !== 0) {
@@ -8,8 +8,15 @@ export var createMap = /* #__PURE__ */factory(name, dependencies, _ref => {
8
8
  } = _ref;
9
9
 
10
10
  /**
11
- * Create a new matrix or array with the results of the callback function executed on
12
- * each entry of the matrix/array.
11
+ * Create a new matrix or array with the results of a callback function executed on
12
+ * each entry of a given matrix/array.
13
+ *
14
+ * For each entry of the input, the callback is invoked with three arguments:
15
+ * the value of the entry, the index at which that entry occurs, and the full
16
+ * matrix/array being traversed. Note that because the matrix/array might be
17
+ * multidimensional, the "index" argument is always an array of numbers giving
18
+ * the index in each dimension. This is true even for vectors: the "index"
19
+ * argument is an array of length 1, rather than simply a number.
13
20
  *
14
21
  * Syntax:
15
22
  *
@@ -21,15 +28,25 @@ export var createMap = /* #__PURE__ */factory(name, dependencies, _ref => {
21
28
  * return value * value
22
29
  * }) // returns [1, 4, 9]
23
30
  *
31
+ * // The calling convention for the callback can cause subtleties:
32
+ * math.map([1, 2, 3], math.format)
33
+ * // throws TypeError: map attempted to call 'format(1,[0])' but argument 2 of type Array does not match expected type number or function or Object or string or boolean
34
+ * // [This happens because `format` _can_ take a second argument,
35
+ * // but its semantics don't match that of the 2nd argument `map` provides]
36
+ *
37
+ * // To avoid this error, use a function that takes exactly the
38
+ * // desired arguments:
39
+ * math.map([1, 2, 3], x => math.format(x)) // returns ['1', '2', '3']
40
+ *
24
41
  * See also:
25
42
  *
26
43
  * filter, forEach, sort
27
44
  *
28
- * @param {Matrix | Array} x The matrix to iterate on.
29
- * @param {Function} callback The callback method is invoked with three
30
- * parameters: the value of the element, the index
31
- * of the element, and the matrix being traversed.
32
- * @return {Matrix | array} Transformed map of x
45
+ * @param {Matrix | Array} x The input to iterate on.
46
+ * @param {Function} callback
47
+ * The function to call (as described above) on each entry of the input
48
+ * @return {Matrix | array}
49
+ * Transformed map of x; always has the same type and shape as x
33
50
  */
34
51
  return typed(name, {
35
52
  'Array, function': _map,
@@ -57,14 +74,35 @@ function _map(array, callback) {
57
74
  return recurse(child, index.concat(i));
58
75
  });
59
76
  } else {
60
- // invoke the callback function with the right number of arguments
61
- if (args === 1) {
62
- return callback(value);
63
- } else if (args === 2) {
64
- return callback(value, index);
65
- } else {
66
- // 3 or -1
67
- return callback(value, index, array);
77
+ try {
78
+ // invoke the callback function with the right number of arguments
79
+ if (args === 1) {
80
+ return callback(value);
81
+ } else if (args === 2) {
82
+ return callback(value, index);
83
+ } else {
84
+ // 3 or -1
85
+ return callback(value, index, array);
86
+ }
87
+ } catch (err) {
88
+ // But maybe the arguments still weren't right
89
+ if (err instanceof TypeError && 'data' in err && err.data.category === 'wrongType') {
90
+ var newmsg = "map attempted to call '".concat(err.data.fn, "(").concat(value);
91
+ var indexString = JSON.stringify(index);
92
+
93
+ if (args === 2) {
94
+ newmsg += ',' + indexString;
95
+ } else if (args !== 1) {
96
+ newmsg += ",".concat(indexString, ",").concat(array);
97
+ }
98
+
99
+ newmsg += ")' but argument ".concat(err.data.index + 1, " of type ");
100
+ newmsg += "".concat(err.data.actual, " does not match expected type ");
101
+ newmsg += err.data.expected.join(' or ');
102
+ throw new TypeError(newmsg);
103
+ }
104
+
105
+ throw err;
68
106
  }
69
107
  }
70
108
  };