mathjs 13.1.1 → 13.2.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 (39) hide show
  1. package/HISTORY.md +17 -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/core/function/typed.js +1 -0
  6. package/lib/cjs/expression/parse.js +1 -1
  7. package/lib/cjs/expression/transform/filter.transform.js +28 -40
  8. package/lib/cjs/expression/transform/forEach.transform.js +29 -30
  9. package/lib/cjs/expression/transform/map.transform.js +8 -93
  10. package/lib/cjs/expression/transform/utils/transformCallback.js +101 -0
  11. package/lib/cjs/function/algebra/derivative.js +10 -11
  12. package/lib/cjs/function/matrix/filter.js +3 -2
  13. package/lib/cjs/function/matrix/forEach.js +3 -14
  14. package/lib/cjs/function/matrix/map.js +11 -33
  15. package/lib/cjs/header.js +2 -2
  16. package/lib/cjs/type/matrix/DenseMatrix.js +73 -29
  17. package/lib/cjs/type/matrix/SparseMatrix.js +7 -4
  18. package/lib/cjs/utils/array.js +22 -0
  19. package/lib/cjs/utils/optimizeCallback.js +94 -0
  20. package/lib/cjs/version.js +1 -1
  21. package/lib/esm/core/function/typed.js +1 -0
  22. package/lib/esm/expression/parse.js +1 -1
  23. package/lib/esm/expression/transform/filter.transform.js +28 -40
  24. package/lib/esm/expression/transform/forEach.transform.js +29 -30
  25. package/lib/esm/expression/transform/map.transform.js +8 -93
  26. package/lib/esm/expression/transform/utils/transformCallback.js +95 -0
  27. package/lib/esm/function/algebra/derivative.js +10 -11
  28. package/lib/esm/function/matrix/filter.js +3 -2
  29. package/lib/esm/function/matrix/forEach.js +3 -14
  30. package/lib/esm/function/matrix/map.js +12 -34
  31. package/lib/esm/type/matrix/DenseMatrix.js +75 -32
  32. package/lib/esm/type/matrix/SparseMatrix.js +7 -4
  33. package/lib/esm/utils/array.js +21 -0
  34. package/lib/esm/utils/optimizeCallback.js +88 -0
  35. package/lib/esm/version.js +1 -1
  36. package/package.json +7 -7
  37. package/types/index.d.ts +50 -12
  38. package/lib/cjs/utils/applyCallback.js +0 -73
  39. package/lib/esm/utils/applyCallback.js +0 -67
@@ -0,0 +1,88 @@
1
+ import typed from 'typed-function';
2
+ import { get, arraySize } from './array.js';
3
+ import { typeOf as _typeOf } from './is.js';
4
+
5
+ /**
6
+ * Simplifies a callback function by reducing its complexity and potentially improving its performance.
7
+ *
8
+ * @param {Function} callback The original callback function to simplify.
9
+ * @param {Array|Matrix} array The array that will be used with the callback function.
10
+ * @param {string} name The name of the function that is using the callback.
11
+ * @returns {Function} Returns a simplified version of the callback function.
12
+ */
13
+ export function optimizeCallback(callback, array, name) {
14
+ if (typed.isTypedFunction(callback)) {
15
+ var firstIndex = (array.isMatrix ? array.size() : arraySize(array)).map(() => 0);
16
+ var firstValue = array.isMatrix ? array.get(firstIndex) : get(array, firstIndex);
17
+ var hasSingleSignature = Object.keys(callback.signatures).length === 1;
18
+ var numberOfArguments = _findNumberOfArguments(callback, firstValue, firstIndex, array);
19
+ var fastCallback = hasSingleSignature ? Object.values(callback.signatures)[0] : callback;
20
+ if (numberOfArguments >= 1 && numberOfArguments <= 3) {
21
+ return function () {
22
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
23
+ args[_key] = arguments[_key];
24
+ }
25
+ return _tryFunctionWithArgs(fastCallback, args.slice(0, numberOfArguments), name, callback.name);
26
+ };
27
+ }
28
+ return function () {
29
+ for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
30
+ args[_key2] = arguments[_key2];
31
+ }
32
+ return _tryFunctionWithArgs(fastCallback, args, name, callback.name);
33
+ };
34
+ }
35
+ return callback;
36
+ }
37
+ function _findNumberOfArguments(callback, value, index, array) {
38
+ var testArgs = [value, index, array];
39
+ for (var i = 3; i > 0; i--) {
40
+ var args = testArgs.slice(0, i);
41
+ if (typed.resolve(callback, args) !== null) {
42
+ return i;
43
+ }
44
+ }
45
+ }
46
+
47
+ /**
48
+ * @param {function} func The selected function taken from one of the signatures of the callback function
49
+ * @param {Array} args List with arguments to apply to the selected signature
50
+ * @param {string} mappingFnName the name of the function that is using the callback
51
+ * @param {string} callbackName the name of the callback function
52
+ * @returns {*} Returns the return value of the invoked signature
53
+ * @throws {TypeError} Throws an error when no matching signature was found
54
+ */
55
+ function _tryFunctionWithArgs(func, args, mappingFnName, callbackName) {
56
+ try {
57
+ return func(...args);
58
+ } catch (err) {
59
+ _createCallbackError(err, args, mappingFnName, callbackName);
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Creates and throws a detailed TypeError when a callback function fails.
65
+ *
66
+ * @param {Error} err The original error thrown by the callback function.
67
+ * @param {Array} args The arguments that were passed to the callback function.
68
+ * @param {string} mappingFnName The name of the function that is using the callback.
69
+ * @param {string} callbackName The name of the callback function.
70
+ * @throws {TypeError} Throws a detailed TypeError with enriched error message.
71
+ */
72
+ function _createCallbackError(err, args, mappingFnName, callbackName) {
73
+ var _err$data;
74
+ // Enrich the error message so the user understands that it took place inside the callback function
75
+ if (err instanceof TypeError && ((_err$data = err.data) === null || _err$data === void 0 ? void 0 : _err$data.category) === 'wrongType') {
76
+ var argsDesc = [];
77
+ argsDesc.push("value: ".concat(_typeOf(args[0])));
78
+ if (args.length >= 2) {
79
+ argsDesc.push("index: ".concat(_typeOf(args[1])));
80
+ }
81
+ if (args.length >= 3) {
82
+ argsDesc.push("array: ".concat(_typeOf(args[2])));
83
+ }
84
+ throw new TypeError("Function ".concat(mappingFnName, " cannot apply callback arguments ") + "".concat(callbackName, "(").concat(argsDesc.join(', '), ") at index ").concat(JSON.stringify(args[1])));
85
+ } else {
86
+ throw new TypeError("Function ".concat(mappingFnName, " cannot apply callback arguments ") + "to function ".concat(callbackName, ": ").concat(err.message));
87
+ }
88
+ }
@@ -1,3 +1,3 @@
1
- export var version = '13.1.1';
1
+ export var version = '13.2.0';
2
2
  // Note: This file is automatically generated when building math.js.
3
3
  // Changes made in this file will be overwritten.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mathjs",
3
- "version": "13.1.1",
3
+ "version": "13.2.0",
4
4
  "description": "Math.js is an extensive math library for JavaScript and Node.js. It features a flexible expression parser with support for symbolic computation, comes with a large set of built-in functions and constants, and offers an integrated solution to work with different data types like numbers, big numbers, complex numbers, fractions, units, and matrices.",
5
5
  "author": "Jos de Jong <wjosdejong@gmail.com> (https://github.com/josdejong)",
6
6
  "homepage": "https://mathjs.org",
@@ -25,7 +25,7 @@
25
25
  "unit"
26
26
  ],
27
27
  "dependencies": {
28
- "@babel/runtime": "^7.25.4",
28
+ "@babel/runtime": "^7.25.6",
29
29
  "complex.js": "^2.1.1",
30
30
  "decimal.js": "^10.4.3",
31
31
  "escape-latex": "^1.2.0",
@@ -43,11 +43,11 @@
43
43
  "@babel/preset-env": "7.25.4",
44
44
  "@babel/register": "7.24.6",
45
45
  "@types/assert": "1.5.10",
46
- "@types/mocha": "10.0.7",
46
+ "@types/mocha": "10.0.8",
47
47
  "@typescript-eslint/eslint-plugin": "7.16.1",
48
48
  "@typescript-eslint/parser": "7.16.1",
49
49
  "assert": "2.1.0",
50
- "babel-loader": "9.1.3",
50
+ "babel-loader": "9.2.1",
51
51
  "benchmark": "2.1.4",
52
52
  "c8": "10.1.2",
53
53
  "codecov": "3.8.3",
@@ -57,7 +57,7 @@
57
57
  "eslint": "8.57.0",
58
58
  "eslint-config-prettier": "9.1.0",
59
59
  "eslint-config-standard": "17.1.0",
60
- "eslint-plugin-import": "2.29.1",
60
+ "eslint-plugin-import": "2.30.0",
61
61
  "eslint-plugin-mocha": "10.5.0",
62
62
  "eslint-plugin-n": "16.6.2",
63
63
  "eslint-plugin-prettier": "5.2.1",
@@ -88,11 +88,11 @@
88
88
  "pad-right": "0.2.2",
89
89
  "prettier": "3.3.3",
90
90
  "process": "0.11.10",
91
- "sinon": "18.0.0",
91
+ "sinon": "19.0.2",
92
92
  "sylvester": "0.0.21",
93
93
  "ts-node": "10.9.2",
94
94
  "typescript": "5.5.4",
95
- "webpack": "5.94.0",
95
+ "webpack": "5.95.0",
96
96
  "zeros": "1.0.0"
97
97
  },
98
98
  "type": "module",
package/types/index.d.ts CHANGED
@@ -246,8 +246,17 @@ export interface ConditionalNodeCtor {
246
246
  ): ConditionalNode
247
247
  }
248
248
 
249
- export interface ConstantNode<TValue extends string | number = number>
250
- extends MathNode {
249
+ export interface ConstantNode<
250
+ TValue extends
251
+ | string
252
+ | number
253
+ | boolean
254
+ | null
255
+ | undefined
256
+ | bigint
257
+ | BigNumber
258
+ | Fraction = number
259
+ > extends MathNode {
251
260
  type: 'ConstantNode'
252
261
  isConstantNode: true
253
262
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -255,7 +264,17 @@ export interface ConstantNode<TValue extends string | number = number>
255
264
  }
256
265
 
257
266
  export interface ConstantNodeCtor {
258
- new <TValue extends string | number = string>(
267
+ new <
268
+ TValue extends
269
+ | string
270
+ | number
271
+ | boolean
272
+ | null
273
+ | undefined
274
+ | bigint
275
+ | BigNumber
276
+ | Fraction = string
277
+ >(
259
278
  value: TValue
260
279
  ): ConstantNode<TValue>
261
280
  }
@@ -1022,6 +1041,15 @@ export interface MathJsInstance extends MathJsFactory {
1022
1041
  simplifyConstant(expr: MathNode | string, options?: SimplifyOptions): MathNode
1023
1042
  simplifyCore(expr: MathNode | string, options?: SimplifyOptions): MathNode
1024
1043
 
1044
+ /**
1045
+ * Gives the number of “leaf nodes” in the parse tree of the given
1046
+ * expression. A leaf node is one that has no subexpressions, essentially
1047
+ * either a symbol or a constant. Note that `5!` has just one leaf, the `5`;
1048
+ * the unary factorial operator does not add a leaf. On the other hand,
1049
+ * function symbols do add leaves, so `sin(x)/cos(x)` has four leaves.
1050
+ */
1051
+ leafCount(expr: MathNode): number
1052
+
1025
1053
  /**
1026
1054
  * Replaces variable nodes with their scoped values
1027
1055
  * @param node Tree to replace variable nodes in
@@ -2531,15 +2559,15 @@ export interface MathJsInstance extends MathJsFactory {
2531
2559
  /**
2532
2560
  * Determines if two expressions are symbolically equal, i.e. one is the
2533
2561
  * result of valid algebraic manipulations on the other.
2534
- * @param {Node|string} expr1 The first expression to compare
2535
- * @param {Node|string} expr2 The second expression to compare
2562
+ * @param {Node} expr1 The first expression to compare
2563
+ * @param {Node} expr2 The second expression to compare
2536
2564
  * @param {Object} [options] Optional option object, passed to simplify
2537
2565
  * @returns {boolean} Returns true if a valid manipulation making the
2538
2566
  * expressions equal is found.
2539
2567
  */
2540
2568
  symbolicEqual(
2541
- expr1: MathNode | string,
2542
- expr2: MathNode | string,
2569
+ expr1: MathNode,
2570
+ expr2: MathNode,
2543
2571
  options?: SimplifyOptions
2544
2572
  ): boolean
2545
2573
 
@@ -4869,6 +4897,15 @@ export interface MathJsChain<TValue> {
4869
4897
  options?: SimplifyOptions
4870
4898
  ): MathJsChain<MathNode>
4871
4899
 
4900
+ /**
4901
+ * Gives the number of “leaf nodes” in the parse tree of the given
4902
+ * expression. A leaf node is one that has no subexpressions, essentially
4903
+ * either a symbol or a constant. Note that `5!` has just one leaf, the `5`;
4904
+ * the unary factorial operator does not add a leaf. On the other hand,
4905
+ * function symbols do add leaves, so `sin(x)/cos(x)` has four leaves.
4906
+ */
4907
+ leafCount(this: MathJsChain<MathNode>): MathJsChain<number>
4908
+
4872
4909
  /**
4873
4910
  * Calculate the Sparse Matrix LU decomposition with full pivoting.
4874
4911
  * Sparse Matrix A is decomposed in two matrices (L, U) and two
@@ -6123,17 +6160,16 @@ export interface MathJsChain<TValue> {
6123
6160
  /**
6124
6161
  * Determines if two expressions are symbolically equal, i.e. one is the
6125
6162
  * result of valid algebraic manipulations on the other.
6126
- * @param {Node|string} expr1 The first expression to compare
6127
- * @param {Node|string} expr2 The second expression to compare
6163
+ * @param {Node} expr2 The second expression to compare
6128
6164
  * @param {Object} [options] Optional option object, passed to simplify
6129
6165
  * @returns {boolean} Returns true if a valid manipulation making the
6130
6166
  * expressions equal is found.
6131
6167
  */
6132
6168
  symbolicEqual(
6133
- this: MathJsChain<MathNode | string>,
6134
- expr2: MathNode | string,
6169
+ this: MathJsChain<MathNode>,
6170
+ expr2: MathNode,
6135
6171
  options?: SimplifyOptions
6136
- ): boolean
6172
+ ): MathJsChain<boolean>
6137
6173
 
6138
6174
  /**
6139
6175
  * Test whether two values are unequal. The function tests whether the
@@ -6966,6 +7002,8 @@ export const {
6966
7002
  simplify,
6967
7003
  simplifyConstant,
6968
7004
  simplifyCore,
7005
+ symbolicEqual,
7006
+ leafCount,
6969
7007
  resolve,
6970
7008
  slu,
6971
7009
  usolve,
@@ -1,73 +0,0 @@
1
- "use strict";
2
-
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
- Object.defineProperty(exports, "__esModule", {
5
- value: true
6
- });
7
- exports.applyCallback = applyCallback;
8
- var _typedFunction = _interopRequireDefault(require("typed-function"));
9
- var _is = require("./is.js");
10
- /**
11
- * Invoke a callback for functions like map and filter with a matching number of arguments
12
- * @param {function} callback
13
- * @param {any} value
14
- * @param {number | number[]} index
15
- * @param {Array} array
16
- * @param {string} mappingFnName The name of the function that is invoking these callbacks, for example "map" or "filter"
17
- * @returns {*}
18
- */
19
- function applyCallback(callback, value, index, array, mappingFnName) {
20
- if (_typedFunction.default.isTypedFunction(callback)) {
21
- // invoke the typed callback function with the matching number of arguments only
22
-
23
- const args3 = [value, index, array];
24
- const signature3 = _typedFunction.default.resolve(callback, args3);
25
- if (signature3) {
26
- return tryWithArgs(signature3.implementation, args3);
27
- }
28
- const args2 = [value, index];
29
- const signature2 = _typedFunction.default.resolve(callback, args2);
30
- if (signature2) {
31
- return tryWithArgs(signature2.implementation, args2);
32
- }
33
- const args1 = [value];
34
- const signature1 = _typedFunction.default.resolve(callback, args1);
35
- if (signature1) {
36
- return tryWithArgs(signature1.implementation, args1);
37
- }
38
-
39
- // fallback (will throw an exception)
40
- return tryWithArgs(callback, args3);
41
- } else {
42
- // A regular JavaScript function
43
- return callback(value, index, array);
44
- }
45
-
46
- /**
47
- * @param {function} signature The selected signature of the typed-function
48
- * @param {Array} args List with arguments to apply to the selected signature
49
- * @returns {*} Returns the return value of the invoked signature
50
- * @throws {TypeError} Throws an error when no matching signature was found
51
- */
52
- function tryWithArgs(signature, args) {
53
- try {
54
- return signature.apply(signature, args);
55
- } catch (err) {
56
- var _err$data;
57
- // Enrich the error message so the user understands that it took place inside the callback function
58
- if (err instanceof TypeError && ((_err$data = err.data) === null || _err$data === void 0 ? void 0 : _err$data.category) === 'wrongType') {
59
- const argsDesc = [];
60
- argsDesc.push(`value: ${(0, _is.typeOf)(value)}`);
61
- if (args.length >= 2) {
62
- argsDesc.push(`index: ${(0, _is.typeOf)(index)}`);
63
- }
64
- if (args.length >= 3) {
65
- argsDesc.push(`array: ${(0, _is.typeOf)(array)}`);
66
- }
67
- throw new TypeError(`Function ${mappingFnName} cannot apply callback arguments ` + `${callback.name}(${argsDesc.join(', ')}) at index ${JSON.stringify(index)}`);
68
- } else {
69
- throw new TypeError(`Function ${mappingFnName} cannot apply callback arguments ` + `to function ${callback.name}: ${err.message}`);
70
- }
71
- }
72
- }
73
- }
@@ -1,67 +0,0 @@
1
- import typed from 'typed-function';
2
- import { typeOf as _typeOf } from './is.js';
3
-
4
- /**
5
- * Invoke a callback for functions like map and filter with a matching number of arguments
6
- * @param {function} callback
7
- * @param {any} value
8
- * @param {number | number[]} index
9
- * @param {Array} array
10
- * @param {string} mappingFnName The name of the function that is invoking these callbacks, for example "map" or "filter"
11
- * @returns {*}
12
- */
13
- export function applyCallback(callback, value, index, array, mappingFnName) {
14
- if (typed.isTypedFunction(callback)) {
15
- // invoke the typed callback function with the matching number of arguments only
16
-
17
- var args3 = [value, index, array];
18
- var signature3 = typed.resolve(callback, args3);
19
- if (signature3) {
20
- return tryWithArgs(signature3.implementation, args3);
21
- }
22
- var args2 = [value, index];
23
- var signature2 = typed.resolve(callback, args2);
24
- if (signature2) {
25
- return tryWithArgs(signature2.implementation, args2);
26
- }
27
- var args1 = [value];
28
- var signature1 = typed.resolve(callback, args1);
29
- if (signature1) {
30
- return tryWithArgs(signature1.implementation, args1);
31
- }
32
-
33
- // fallback (will throw an exception)
34
- return tryWithArgs(callback, args3);
35
- } else {
36
- // A regular JavaScript function
37
- return callback(value, index, array);
38
- }
39
-
40
- /**
41
- * @param {function} signature The selected signature of the typed-function
42
- * @param {Array} args List with arguments to apply to the selected signature
43
- * @returns {*} Returns the return value of the invoked signature
44
- * @throws {TypeError} Throws an error when no matching signature was found
45
- */
46
- function tryWithArgs(signature, args) {
47
- try {
48
- return signature.apply(signature, args);
49
- } catch (err) {
50
- var _err$data;
51
- // Enrich the error message so the user understands that it took place inside the callback function
52
- if (err instanceof TypeError && ((_err$data = err.data) === null || _err$data === void 0 ? void 0 : _err$data.category) === 'wrongType') {
53
- var argsDesc = [];
54
- argsDesc.push("value: ".concat(_typeOf(value)));
55
- if (args.length >= 2) {
56
- argsDesc.push("index: ".concat(_typeOf(index)));
57
- }
58
- if (args.length >= 3) {
59
- argsDesc.push("array: ".concat(_typeOf(array)));
60
- }
61
- throw new TypeError("Function ".concat(mappingFnName, " cannot apply callback arguments ") + "".concat(callback.name, "(").concat(argsDesc.join(', '), ") at index ").concat(JSON.stringify(index)));
62
- } else {
63
- throw new TypeError("Function ".concat(mappingFnName, " cannot apply callback arguments ") + "to function ".concat(callback.name, ": ").concat(err.message));
64
- }
65
- }
66
- }
67
- }