mathjs 10.2.0 → 10.4.1
Sign up to get free protection for your applications and to get access to all the features.
- package/HISTORY.md +43 -0
- package/docs/expressions/syntax.md +31 -2
- package/docs/reference/functions/cumsum.md +57 -0
- package/docs/reference/functions/format.md +1 -1
- package/docs/reference/functions/map.md +22 -5
- package/docs/reference/functions/subset.md +10 -2
- package/docs/reference/functions/sum.md +2 -1
- package/docs/reference/functions/symbolicEqual.md +62 -0
- package/docs/reference/functions.md +3 -1
- package/lib/browser/math.js +6 -6
- package/lib/browser/math.js.map +1 -1
- package/lib/cjs/entry/dependenciesAny/dependenciesCumSum.generated.js +26 -0
- package/lib/cjs/entry/dependenciesAny/dependenciesCumSumTransform.generated.js +26 -0
- package/lib/cjs/entry/dependenciesAny/dependenciesSymbolicEqual.generated.js +29 -0
- package/lib/cjs/entry/dependenciesAny.generated.js +24 -0
- package/lib/cjs/entry/dependenciesNumber/dependenciesCumSum.generated.js +26 -0
- package/lib/cjs/entry/dependenciesNumber/dependenciesCumSumTransform.generated.js +26 -0
- package/lib/cjs/entry/dependenciesNumber.generated.js +16 -0
- package/lib/cjs/entry/impureFunctionsAny.generated.js +22 -8
- package/lib/cjs/entry/impureFunctionsNumber.generated.js +6 -0
- package/lib/cjs/entry/pureFunctionsAny.generated.js +18 -12
- package/lib/cjs/entry/pureFunctionsNumber.generated.js +8 -2
- package/lib/cjs/expression/embeddedDocs/construction/fraction.js +3 -3
- package/lib/cjs/expression/embeddedDocs/embeddedDocs.js +240 -234
- package/lib/cjs/expression/embeddedDocs/function/algebra/symbolicEqual.js +15 -0
- package/lib/cjs/expression/embeddedDocs/function/matrix/subset.js +2 -2
- package/lib/cjs/expression/embeddedDocs/function/statistics/cumsum.js +15 -0
- package/lib/cjs/expression/node/FunctionNode.js +74 -55
- package/lib/cjs/expression/parse.js +12 -8
- package/lib/cjs/expression/transform/cumsum.transform.js +57 -0
- package/lib/cjs/expression/transform/sum.transform.js +1 -1
- package/lib/cjs/factoriesAny.js +24 -0
- package/lib/cjs/factoriesNumber.js +18 -2
- package/lib/cjs/function/algebra/simplify.js +8 -0
- package/lib/cjs/function/algebra/simplifyCore.js +2 -2
- package/lib/cjs/function/algebra/symbolicEqual.js +88 -0
- package/lib/cjs/function/matrix/eigs/complexEigs.js +39 -28
- package/lib/cjs/function/matrix/map.js +53 -15
- package/lib/cjs/function/matrix/subset.js +15 -5
- package/lib/cjs/function/statistics/cumsum.js +151 -0
- package/lib/cjs/function/statistics/sum.js +1 -1
- package/lib/cjs/function/string/format.js +1 -1
- package/lib/cjs/header.js +2 -2
- package/lib/cjs/type/fraction/function/fraction.js +20 -8
- package/lib/cjs/utils/collection.js +3 -27
- package/lib/cjs/utils/switch.js +31 -0
- package/lib/cjs/version.js +1 -1
- package/lib/esm/entry/dependenciesAny/dependenciesCumSum.generated.js +14 -0
- package/lib/esm/entry/dependenciesAny/dependenciesCumSumTransform.generated.js +14 -0
- package/lib/esm/entry/dependenciesAny/dependenciesSymbolicEqual.generated.js +16 -0
- package/lib/esm/entry/dependenciesAny.generated.js +3 -0
- package/lib/esm/entry/dependenciesNumber/dependenciesCumSum.generated.js +14 -0
- package/lib/esm/entry/dependenciesNumber/dependenciesCumSumTransform.generated.js +14 -0
- package/lib/esm/entry/dependenciesNumber.generated.js +2 -0
- package/lib/esm/entry/impureFunctionsAny.generated.js +22 -9
- package/lib/esm/entry/impureFunctionsNumber.generated.js +8 -2
- package/lib/esm/entry/pureFunctionsAny.generated.js +13 -8
- package/lib/esm/entry/pureFunctionsNumber.generated.js +6 -1
- package/lib/esm/expression/embeddedDocs/construction/fraction.js +3 -3
- package/lib/esm/expression/embeddedDocs/embeddedDocs.js +220 -216
- package/lib/esm/expression/embeddedDocs/function/algebra/symbolicEqual.js +8 -0
- package/lib/esm/expression/embeddedDocs/function/matrix/subset.js +2 -2
- package/lib/esm/expression/embeddedDocs/function/statistics/cumsum.js +8 -0
- package/lib/esm/expression/node/FunctionNode.js +70 -53
- package/lib/esm/expression/parse.js +12 -8
- package/lib/esm/expression/transform/cumsum.transform.js +48 -0
- package/lib/esm/expression/transform/sum.transform.js +1 -1
- package/lib/esm/factoriesAny.js +3 -0
- package/lib/esm/factoriesNumber.js +2 -0
- package/lib/esm/function/algebra/simplify.js +8 -0
- package/lib/esm/function/algebra/simplifyCore.js +2 -2
- package/lib/esm/function/algebra/symbolicEqual.js +80 -0
- package/lib/esm/function/matrix/eigs/complexEigs.js +36 -25
- package/lib/esm/function/matrix/map.js +53 -15
- package/lib/esm/function/matrix/subset.js +15 -5
- package/lib/esm/function/statistics/cumsum.js +139 -0
- package/lib/esm/function/statistics/sum.js +1 -1
- package/lib/esm/function/string/format.js +1 -1
- package/lib/esm/type/fraction/function/fraction.js +20 -8
- package/lib/esm/utils/collection.js +1 -26
- package/lib/esm/utils/switch.js +24 -0
- package/lib/esm/version.js +1 -1
- package/package.json +15 -11
- package/types/index.d.ts +209 -23
- package/types/index.ts +274 -57
- 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
|
-
|
86
|
-
|
87
|
-
|
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
|
-
|
91
|
-
|
92
|
-
|
87
|
+
var resolveFn = scope => {
|
88
|
+
if (scope.has(_name)) {
|
89
|
+
return scope.get(_name);
|
90
|
+
}
|
93
91
|
|
94
|
-
|
95
|
-
|
92
|
+
if (_name in math) {
|
93
|
+
return getSafeProperty(math, _name);
|
94
|
+
}
|
96
95
|
|
97
|
-
|
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
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
return
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
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
|
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](
|
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
|
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(
|
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
|
245
|
-
// space, tab, and newline when inside parameters
|
244
|
+
state.comment = ''; // skip over ignored characters:
|
246
245
|
|
247
|
-
while (
|
248
|
-
|
249
|
-
|
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
|
-
|
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
|
9
|
+
* This transform changed the last `dim` parameter of function sum
|
10
10
|
* from one-based to zero based
|
11
11
|
*/
|
12
12
|
|
package/lib/esm/factoriesAny.js
CHANGED
@@ -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); //
|
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
|
-
//
|
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
|
88
|
-
var one = big ? bignumber(1) : cplx ? complex(1) : 1;
|
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 =
|
110
|
-
var rowNorm =
|
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 =
|
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
|
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
|
-
|
438
|
-
var
|
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(
|
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(
|
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
|
12
|
-
* each entry of
|
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
|
29
|
-
* @param {Function} callback
|
30
|
-
*
|
31
|
-
*
|
32
|
-
*
|
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
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
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
|
};
|