mathjs 13.1.0 → 13.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. package/HISTORY.md +30 -0
  2. package/bin/cli.js +24 -10
  3. package/lib/browser/math.js +1 -1
  4. package/lib/browser/math.js.LICENSE.txt +2 -2
  5. package/lib/browser/math.js.map +1 -1
  6. package/lib/cjs/core/function/typed.js +1 -0
  7. package/lib/cjs/expression/node/FunctionNode.js +9 -1
  8. package/lib/cjs/expression/parse.js +1 -1
  9. package/lib/cjs/expression/transform/filter.transform.js +28 -40
  10. package/lib/cjs/expression/transform/forEach.transform.js +29 -30
  11. package/lib/cjs/expression/transform/map.transform.js +8 -93
  12. package/lib/cjs/expression/transform/utils/transformCallback.js +101 -0
  13. package/lib/cjs/function/algebra/derivative.js +10 -11
  14. package/lib/cjs/function/matrix/filter.js +3 -2
  15. package/lib/cjs/function/matrix/forEach.js +3 -14
  16. package/lib/cjs/function/matrix/map.js +11 -33
  17. package/lib/cjs/header.js +2 -2
  18. package/lib/cjs/type/matrix/DenseMatrix.js +73 -29
  19. package/lib/cjs/type/matrix/SparseMatrix.js +7 -4
  20. package/lib/cjs/utils/array.js +22 -0
  21. package/lib/cjs/utils/customs.js +5 -12
  22. package/lib/cjs/utils/map.js +5 -3
  23. package/lib/cjs/utils/optimizeCallback.js +94 -0
  24. package/lib/cjs/version.js +1 -1
  25. package/lib/esm/core/function/typed.js +1 -0
  26. package/lib/esm/expression/node/FunctionNode.js +9 -1
  27. package/lib/esm/expression/parse.js +1 -1
  28. package/lib/esm/expression/transform/filter.transform.js +28 -40
  29. package/lib/esm/expression/transform/forEach.transform.js +29 -30
  30. package/lib/esm/expression/transform/map.transform.js +8 -93
  31. package/lib/esm/expression/transform/utils/transformCallback.js +95 -0
  32. package/lib/esm/function/algebra/derivative.js +10 -11
  33. package/lib/esm/function/matrix/filter.js +3 -2
  34. package/lib/esm/function/matrix/forEach.js +3 -14
  35. package/lib/esm/function/matrix/map.js +12 -34
  36. package/lib/esm/type/matrix/DenseMatrix.js +75 -32
  37. package/lib/esm/type/matrix/SparseMatrix.js +7 -4
  38. package/lib/esm/utils/array.js +21 -0
  39. package/lib/esm/utils/customs.js +5 -12
  40. package/lib/esm/utils/map.js +6 -4
  41. package/lib/esm/utils/optimizeCallback.js +88 -0
  42. package/lib/esm/version.js +1 -1
  43. package/package.json +7 -7
  44. package/types/index.d.ts +50 -12
  45. package/lib/cjs/utils/applyCallback.js +0 -73
  46. package/lib/esm/utils/applyCallback.js +0 -67
@@ -2,6 +2,7 @@ import { factory } from '../../utils/factory.js';
2
2
  import { isFunctionAssignmentNode, isSymbolNode } from '../../utils/is.js';
3
3
  import { createMap } from '../../function/matrix/map.js';
4
4
  import { compileInlineExpression } from './utils/compileInlineExpression.js';
5
+ import { createTransformCallback } from './utils/transformCallback.js';
5
6
  var name = 'map';
6
7
  var dependencies = ['typed'];
7
8
  export var createMapTransform = /* #__PURE__ */factory(name, dependencies, _ref => {
@@ -17,6 +18,9 @@ export var createMapTransform = /* #__PURE__ */factory(name, dependencies, _ref
17
18
  var map = createMap({
18
19
  typed
19
20
  });
21
+ var transformCallback = createTransformCallback({
22
+ typed
23
+ });
20
24
  function mapTransform(args, math, scope) {
21
25
  if (args.length === 0) {
22
26
  return map();
@@ -25,9 +29,8 @@ export var createMapTransform = /* #__PURE__ */factory(name, dependencies, _ref
25
29
  return map(args[0]);
26
30
  }
27
31
  var N = args.length - 1;
28
- var X, callback;
29
- callback = args[N];
30
- X = args.slice(0, N);
32
+ var X = args.slice(0, N);
33
+ var callback = args[N];
31
34
  X = X.map(arg => _compileAndEvaluate(arg, scope));
32
35
  if (callback) {
33
36
  if (isSymbolNode(callback) || isFunctionAssignmentNode(callback)) {
@@ -38,101 +41,13 @@ export var createMapTransform = /* #__PURE__ */factory(name, dependencies, _ref
38
41
  callback = compileInlineExpression(callback, math, scope);
39
42
  }
40
43
  }
41
- return map(...X, _transformCallback(callback, N));
44
+ return map(...X, transformCallback(callback, N));
42
45
  function _compileAndEvaluate(arg, scope) {
43
46
  return arg.compile().evaluate(scope);
44
47
  }
45
48
  }
46
49
  mapTransform.rawArgs = true;
47
50
  return mapTransform;
48
-
49
- /**
50
- * Transforms the given callback function based on its type and number of arrays.
51
- *
52
- * @param {Function} callback - The callback function to transform.
53
- * @param {number} numberOfArrays - The number of arrays to pass to the callback function.
54
- * @returns {*} - The transformed callback function.
55
- */
56
- function _transformCallback(callback, numberOfArrays) {
57
- if (typed.isTypedFunction(callback)) {
58
- return _transformTypedCallbackFunction(callback, numberOfArrays);
59
- } else {
60
- return _transformCallbackFunction(callback, callback.length, numberOfArrays);
61
- }
62
- }
63
-
64
- /**
65
- * Transforms the given typed callback function based on the number of arrays.
66
- *
67
- * @param {Function} typedFunction - The typed callback function to transform.
68
- * @param {number} numberOfArrays - The number of arrays to pass to the callback function.
69
- * @returns {*} - The transformed typed callback function.
70
- */
71
- function _transformTypedCallbackFunction(typedFunction, numberOfArrays) {
72
- var signatures = Object.fromEntries(Object.entries(typedFunction.signatures).map(_ref2 => {
73
- var [signature, callbackFunction] = _ref2;
74
- var numberOfCallbackInputs = signature.split(',').length;
75
- if (typed.isTypedFunction(callbackFunction)) {
76
- return [signature, _transformTypedCallbackFunction(callbackFunction, numberOfArrays)];
77
- } else {
78
- return [signature, _transformCallbackFunction(callbackFunction, numberOfCallbackInputs, numberOfArrays)];
79
- }
80
- }));
81
- if (typeof typedFunction.name === 'string') {
82
- return typed(typedFunction.name, signatures);
83
- } else {
84
- return typed(signatures);
85
- }
86
- }
87
51
  }, {
88
52
  isTransformFunction: true
89
- });
90
-
91
- /**
92
- * Transforms the callback function based on the number of callback inputs and arrays.
93
- * There are three cases:
94
- * 1. The callback function has N arguments.
95
- * 2. The callback function has N+1 arguments.
96
- * 3. The callback function has 2N+1 arguments.
97
- *
98
- * @param {Function} callbackFunction - The callback function to transform.
99
- * @param {number} numberOfCallbackInputs - The number of callback inputs.
100
- * @param {number} numberOfArrays - The number of arrays.
101
- * @returns {Function} The transformed callback function.
102
- */
103
- function _transformCallbackFunction(callbackFunction, numberOfCallbackInputs, numberOfArrays) {
104
- if (numberOfCallbackInputs === numberOfArrays) {
105
- return callbackFunction;
106
- } else if (numberOfCallbackInputs === numberOfArrays + 1) {
107
- return function () {
108
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
109
- args[_key] = arguments[_key];
110
- }
111
- var vals = args.slice(0, numberOfArrays);
112
- var idx = _transformDims(args[numberOfArrays]);
113
- return callbackFunction(...vals, idx);
114
- };
115
- } else if (numberOfCallbackInputs > numberOfArrays + 1) {
116
- return function () {
117
- for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
118
- args[_key2] = arguments[_key2];
119
- }
120
- var vals = args.slice(0, numberOfArrays);
121
- var idx = _transformDims(args[numberOfArrays]);
122
- var rest = args.slice(numberOfArrays + 1);
123
- return callbackFunction(...vals, idx, ...rest);
124
- };
125
- } else {
126
- return callbackFunction;
127
- }
128
- }
129
-
130
- /**
131
- * Transforms the dimensions by adding 1 to each dimension.
132
- *
133
- * @param {Array} dims - The dimensions to transform.
134
- * @returns {Array} The transformed dimensions.
135
- */
136
- function _transformDims(dims) {
137
- return dims.map(dim => dim.isBigNumber ? dim.plus(1) : dim + 1);
138
- }
53
+ });
@@ -0,0 +1,95 @@
1
+ import { factory } from '../../../utils/factory.js';
2
+ var name = 'transformCallback';
3
+ var dependencies = ['typed'];
4
+ export var createTransformCallback = /* #__PURE__ */factory(name, dependencies, _ref => {
5
+ var {
6
+ typed
7
+ } = _ref;
8
+ /**
9
+ * Transforms the given callback function based on its type and number of arrays.
10
+ *
11
+ * @param {Function} callback - The callback function to transform.
12
+ * @param {number} numberOfArrays - The number of arrays to pass to the callback function.
13
+ * @returns {*} - The transformed callback function.
14
+ */
15
+ return function (callback, numberOfArrays) {
16
+ if (typed.isTypedFunction(callback)) {
17
+ return _transformTypedCallbackFunction(callback, numberOfArrays);
18
+ } else {
19
+ return _transformCallbackFunction(callback, callback.length, numberOfArrays);
20
+ }
21
+ };
22
+
23
+ /**
24
+ * Transforms the given typed callback function based on the number of arrays.
25
+ *
26
+ * @param {Function} typedFunction - The typed callback function to transform.
27
+ * @param {number} numberOfArrays - The number of arrays to pass to the callback function.
28
+ * @returns {*} - The transformed callback function.
29
+ */
30
+ function _transformTypedCallbackFunction(typedFunction, numberOfArrays) {
31
+ var signatures = Object.fromEntries(Object.entries(typedFunction.signatures).map(_ref2 => {
32
+ var [signature, callbackFunction] = _ref2;
33
+ var numberOfCallbackInputs = signature.split(',').length;
34
+ if (typed.isTypedFunction(callbackFunction)) {
35
+ return [signature, _transformTypedCallbackFunction(callbackFunction, numberOfArrays)];
36
+ } else {
37
+ return [signature, _transformCallbackFunction(callbackFunction, numberOfCallbackInputs, numberOfArrays)];
38
+ }
39
+ }));
40
+ if (typeof typedFunction.name === 'string') {
41
+ return typed(typedFunction.name, signatures);
42
+ } else {
43
+ return typed(signatures);
44
+ }
45
+ }
46
+ });
47
+
48
+ /**
49
+ * Transforms the callback function based on the number of callback inputs and arrays.
50
+ * There are three cases:
51
+ * 1. The callback function has N arguments.
52
+ * 2. The callback function has N+1 arguments.
53
+ * 3. The callback function has 2N+1 arguments.
54
+ *
55
+ * @param {Function} callbackFunction - The callback function to transform.
56
+ * @param {number} numberOfCallbackInputs - The number of callback inputs.
57
+ * @param {number} numberOfArrays - The number of arrays.
58
+ * @returns {Function} The transformed callback function.
59
+ */
60
+ function _transformCallbackFunction(callbackFunction, numberOfCallbackInputs, numberOfArrays) {
61
+ if (numberOfCallbackInputs === numberOfArrays) {
62
+ return callbackFunction;
63
+ } else if (numberOfCallbackInputs === numberOfArrays + 1) {
64
+ return function () {
65
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
66
+ args[_key] = arguments[_key];
67
+ }
68
+ var vals = args.slice(0, numberOfArrays);
69
+ var idx = _transformDims(args[numberOfArrays]);
70
+ return callbackFunction(...vals, idx);
71
+ };
72
+ } else if (numberOfCallbackInputs > numberOfArrays + 1) {
73
+ return function () {
74
+ for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
75
+ args[_key2] = arguments[_key2];
76
+ }
77
+ var vals = args.slice(0, numberOfArrays);
78
+ var idx = _transformDims(args[numberOfArrays]);
79
+ var rest = args.slice(numberOfArrays + 1);
80
+ return callbackFunction(...vals, idx, ...rest);
81
+ };
82
+ } else {
83
+ return callbackFunction;
84
+ }
85
+ }
86
+
87
+ /**
88
+ * Transforms the dimensions by adding 1 to each dimension.
89
+ *
90
+ * @param {Array} dims - The dimensions to transform.
91
+ * @returns {Array} The transformed dimensions.
92
+ */
93
+ function _transformDims(dims) {
94
+ return dims.map(dim => dim + 1);
95
+ }
@@ -65,14 +65,18 @@ export var createDerivative = /* #__PURE__ */factory(name, dependencies, _ref =>
65
65
  var res = _derivative(expr, constNodes);
66
66
  return options.simplify ? simplify(res) : res;
67
67
  }
68
- typed.addConversion({
69
- from: 'identifier',
70
- to: 'SymbolNode',
71
- convert: parse
72
- });
68
+ function parseIdentifier(string) {
69
+ var symbol = parse(string);
70
+ if (!symbol.isSymbolNode) {
71
+ throw new TypeError('Invalid variable. ' + "Cannot parse ".concat(JSON.stringify(string), " into a variable in function derivative"));
72
+ }
73
+ return symbol;
74
+ }
73
75
  var derivative = typed(name, {
74
76
  'Node, SymbolNode': plainDerivative,
75
- 'Node, SymbolNode, Object': plainDerivative
77
+ 'Node, SymbolNode, Object': plainDerivative,
78
+ 'Node, string': (node, symbol) => plainDerivative(node, parseIdentifier(symbol)),
79
+ 'Node, string, Object': (node, symbol, options) => plainDerivative(node, parseIdentifier(symbol), options)
76
80
 
77
81
  /* TODO: implement and test syntax with order of derivatives -> implement as an option {order: number}
78
82
  'Node, SymbolNode, ConstantNode': function (expr, variable, {order}) {
@@ -86,11 +90,6 @@ export var createDerivative = /* #__PURE__ */factory(name, dependencies, _ref =>
86
90
  }
87
91
  */
88
92
  });
89
- typed.removeConversion({
90
- from: 'identifier',
91
- to: 'SymbolNode',
92
- convert: parse
93
- });
94
93
  derivative._simplify = true;
95
94
  derivative.toTex = function (deriv) {
96
95
  return _derivTex.apply(null, deriv.args);
@@ -1,4 +1,4 @@
1
- import { applyCallback } from '../../utils/applyCallback.js';
1
+ import { optimizeCallback } from '../../utils/optimizeCallback.js';
2
2
  import { filter, filterRegExp } from '../../utils/array.js';
3
3
  import { factory } from '../../utils/factory.js';
4
4
  var name = 'filter';
@@ -56,8 +56,9 @@ export var createFilter = /* #__PURE__ */factory(name, dependencies, _ref => {
56
56
  * @private
57
57
  */
58
58
  function _filterCallback(x, callback) {
59
+ var fastCallback = optimizeCallback(callback, x, 'filter');
59
60
  return filter(x, function (value, index, array) {
60
61
  // invoke the callback function with the right number of arguments
61
- return applyCallback(callback, value, [index], array, 'filter');
62
+ return fastCallback(value, [index], array);
62
63
  });
63
64
  }
@@ -1,6 +1,6 @@
1
- import { applyCallback } from '../../utils/applyCallback.js';
2
- import { forEach as forEachArray } from '../../utils/array.js';
1
+ import { optimizeCallback } from '../../utils/optimizeCallback.js';
3
2
  import { factory } from '../../utils/factory.js';
3
+ import { recurse } from '../../utils/array.js';
4
4
  var name = 'forEach';
5
5
  var dependencies = ['typed'];
6
6
  export var createForEach = /* #__PURE__ */factory(name, dependencies, _ref => {
@@ -45,16 +45,5 @@ export var createForEach = /* #__PURE__ */factory(name, dependencies, _ref => {
45
45
  * @private
46
46
  */
47
47
  function _forEach(array, callback) {
48
- var _recurse = function recurse(value, index) {
49
- if (Array.isArray(value)) {
50
- forEachArray(value, function (child, i) {
51
- // we create a copy of the index array and append the new index value
52
- _recurse(child, index.concat(i));
53
- });
54
- } else {
55
- // invoke the callback function with the right number of arguments
56
- return applyCallback(callback, value, index, array, 'forEach');
57
- }
58
- };
59
- _recurse(array, []);
48
+ recurse(array, [], array, optimizeCallback(callback, array, name));
60
49
  }
@@ -1,5 +1,5 @@
1
- import { applyCallback } from '../../utils/applyCallback.js';
2
- import { arraySize, broadcastSizes, broadcastTo, get } from '../../utils/array.js';
1
+ import { optimizeCallback } from '../../utils/optimizeCallback.js';
2
+ import { arraySize, broadcastSizes, broadcastTo, get, recurse } from '../../utils/array.js';
3
3
  import { factory } from '../../utils/factory.js';
4
4
  var name = 'map';
5
5
  var dependencies = ['typed'];
@@ -129,36 +129,14 @@ export var createMap = /* #__PURE__ */factory(name, dependencies, _ref => {
129
129
  return 0;
130
130
  }
131
131
  }
132
- });
133
-
134
- /**
135
- * Map for a multi dimensional array
136
- * @param {Array} array
137
- * @param {Function} callback
138
- * @return {Array}
139
- * @private
140
- */
141
- function _mapArray(array, callback) {
142
- return _recurse(array, [], array, callback);
143
- }
144
-
145
- /**
146
- * Recursive function to map a multi-dimensional array.
147
- *
148
- * @param {*} value - The current value being processed in the array.
149
- * @param {Array} index - The index of the current value being processed in the array.
150
- * @param {Array} array - The array being processed.
151
- * @param {Function} callback - Function that produces the element of the new Array, taking three arguments: the value of the element, the index of the element, and the Array being processed.
152
- * @returns {*} The new array with each element being the result of the callback function.
153
- */
154
- function _recurse(value, index, array, callback) {
155
- if (Array.isArray(value)) {
156
- return value.map(function (child, i) {
157
- // we create a copy of the index array and append the new index value
158
- return _recurse(child, index.concat(i), array, callback);
159
- });
160
- } else {
161
- // invoke the callback function with the right number of arguments
162
- return applyCallback(callback, value, index, array, 'map');
132
+ /**
133
+ * Map for a multi dimensional array
134
+ * @param {Array} array
135
+ * @param {Function} callback
136
+ * @return {Array}
137
+ * @private
138
+ */
139
+ function _mapArray(array, callback) {
140
+ return recurse(array, [], array, optimizeCallback(callback, array, name));
163
141
  }
164
- }
142
+ });
@@ -1,3 +1,4 @@
1
+ // deno-lint-ignore-file no-this-alias
1
2
  import { isArray, isBigNumber, isCollection, isIndex, isMatrix, isNumber, isString, typeOf } from '../../utils/is.js';
2
3
  import { arraySize, getArrayDataType, processSizesWildcard, reshape, resize, unsqueeze, validate, validateIndex, broadcastTo, get } from '../../utils/array.js';
3
4
  import { format } from '../../utils/string.js';
@@ -5,7 +6,7 @@ import { isInteger } from '../../utils/number.js';
5
6
  import { clone, deepStrictEqual } from '../../utils/object.js';
6
7
  import { DimensionError } from '../../error/DimensionError.js';
7
8
  import { factory } from '../../utils/factory.js';
8
- import { applyCallback } from '../../utils/applyCallback.js';
9
+ import { optimizeCallback } from '../../utils/optimizeCallback.js';
9
10
  var name = 'DenseMatrix';
10
11
  var dependencies = ['Matrix'];
11
12
  export var createDenseMatrixClass = /* #__PURE__ */factory(name, dependencies, _ref => {
@@ -516,6 +517,66 @@ export var createDenseMatrixClass = /* #__PURE__ */factory(name, dependencies, _
516
517
  return this._size.slice(0); // return a clone of _size
517
518
  };
518
519
 
520
+ /**
521
+ * Applies a callback function to a reference to each element of the matrix
522
+ * @memberof DenseMatrix
523
+ * @param {Function} callback The callback function is invoked with three
524
+ * parameters: an array, an integer index to that
525
+ * array, and the Matrix being traversed.
526
+ */
527
+ DenseMatrix.prototype._forEach = function (callback) {
528
+ // matrix instance
529
+ var me = this;
530
+ var s = me.size();
531
+
532
+ // if there is only one dimension, just loop through it
533
+ if (s.length === 1) {
534
+ for (var i = 0; i < s[0]; i++) {
535
+ callback(me._data, i, [i]);
536
+ }
537
+ return;
538
+ }
539
+
540
+ // keep track of the current index permutation
541
+ var index = Array(s.length).fill(0);
542
+
543
+ // store a reference of each dimension of the matrix for faster access
544
+ var data = Array(s.length - 1);
545
+ var last = data.length - 1;
546
+ data[0] = me._data[0];
547
+ for (var _i = 0; _i < last; _i++) {
548
+ data[_i + 1] = data[_i][0];
549
+ }
550
+ index[last] = -1;
551
+ while (true) {
552
+ var _i2 = void 0;
553
+ for (_i2 = last; _i2 >= 0; _i2--) {
554
+ // march index to the next permutation
555
+ index[_i2]++;
556
+ if (index[_i2] === s[_i2]) {
557
+ index[_i2] = 0;
558
+ continue;
559
+ }
560
+
561
+ // update references to matrix dimensions
562
+ data[_i2] = _i2 === 0 ? me._data[index[_i2]] : data[_i2 - 1][index[_i2]];
563
+ for (var j = _i2; j < last; j++) {
564
+ data[j + 1] = data[j][0];
565
+ }
566
+
567
+ // loop through the last dimension and map each value
568
+ for (var _j = 0; _j < s[data.length]; _j++) {
569
+ index[data.length] = _j;
570
+ callback(data[last], _j, index.slice(0));
571
+ }
572
+ break;
573
+ }
574
+ if (_i2 === -1) {
575
+ break;
576
+ }
577
+ }
578
+ };
579
+
519
580
  /**
520
581
  * Create a new matrix with the results of the callback function executed on
521
582
  * each entry of the matrix.
@@ -527,24 +588,13 @@ export var createDenseMatrixClass = /* #__PURE__ */factory(name, dependencies, _
527
588
  * @return {DenseMatrix} matrix
528
589
  */
529
590
  DenseMatrix.prototype.map = function (callback) {
530
- // matrix instance
531
591
  var me = this;
532
- var _recurse = function recurse(value, index) {
533
- if (isArray(value)) {
534
- return value.map(function (child, i) {
535
- return _recurse(child, index.concat(i));
536
- });
537
- } else {
538
- // invoke the callback function with the right number of arguments
539
- return applyCallback(callback, value, index, me, 'map');
540
- }
541
- };
542
-
543
- // determine the new datatype when the original matrix has datatype defined
544
- // TODO: should be done in matrix constructor instead
545
- var data = _recurse(this._data, []);
546
- var datatype = this._datatype !== undefined ? getArrayDataType(data, typeOf) : undefined;
547
- return new DenseMatrix(data, datatype);
592
+ var result = new DenseMatrix(me);
593
+ var fastCallback = optimizeCallback(callback, me._data, 'map');
594
+ result._forEach(function (arr, i, index) {
595
+ arr[i] = fastCallback(arr[i], index, me);
596
+ });
597
+ return result;
548
598
  };
549
599
 
550
600
  /**
@@ -555,18 +605,11 @@ export var createDenseMatrixClass = /* #__PURE__ */factory(name, dependencies, _
555
605
  * of the element, and the Matrix being traversed.
556
606
  */
557
607
  DenseMatrix.prototype.forEach = function (callback) {
558
- // matrix instance
559
608
  var me = this;
560
- var _recurse2 = function recurse(value, index) {
561
- if (isArray(value)) {
562
- value.forEach(function (child, i) {
563
- _recurse2(child, index.concat(i));
564
- });
565
- } else {
566
- callback(value, index, me);
567
- }
568
- };
569
- _recurse2(this._data, []);
609
+ var fastCallback = optimizeCallback(callback, me._data, 'map');
610
+ me._forEach(function (arr, i, index) {
611
+ fastCallback(arr[i], index, me);
612
+ });
570
613
  };
571
614
 
572
615
  /**
@@ -574,10 +617,10 @@ export var createDenseMatrixClass = /* #__PURE__ */factory(name, dependencies, _
574
617
  * @return {Iterable<{ value, index: number[] }>}
575
618
  */
576
619
  DenseMatrix.prototype[Symbol.iterator] = function* () {
577
- var _recurse3 = function* recurse(value, index) {
620
+ var _recurse = function* recurse(value, index) {
578
621
  if (isArray(value)) {
579
622
  for (var i = 0; i < value.length; i++) {
580
- yield* _recurse3(value[i], index.concat(i));
623
+ yield* _recurse(value[i], index.concat(i));
581
624
  }
582
625
  } else {
583
626
  yield {
@@ -586,7 +629,7 @@ export var createDenseMatrixClass = /* #__PURE__ */factory(name, dependencies, _
586
629
  };
587
630
  }
588
631
  };
589
- yield* _recurse3(this._data, []);
632
+ yield* _recurse(this._data, []);
590
633
  };
591
634
 
592
635
  /**
@@ -5,7 +5,7 @@ import { clone, deepStrictEqual } from '../../utils/object.js';
5
5
  import { arraySize, getArrayDataType, processSizesWildcard, unsqueeze, validateIndex } from '../../utils/array.js';
6
6
  import { factory } from '../../utils/factory.js';
7
7
  import { DimensionError } from '../../error/DimensionError.js';
8
- import { applyCallback } from '../../utils/applyCallback.js';
8
+ import { optimizeCallback } from '../../utils/optimizeCallback.js';
9
9
  var name = 'SparseMatrix';
10
10
  var dependencies = ['typed', 'equalScalar', 'Matrix'];
11
11
  export var createSparseMatrixClass = /* #__PURE__ */factory(name, dependencies, _ref => {
@@ -872,10 +872,11 @@ export var createSparseMatrixClass = /* #__PURE__ */factory(name, dependencies,
872
872
  // rows and columns
873
873
  var rows = this._size[0];
874
874
  var columns = this._size[1];
875
+ var fastCallback = optimizeCallback(callback, me, 'map');
875
876
  // invoke callback
876
877
  var invoke = function invoke(v, i, j) {
877
878
  // invoke callback
878
- return applyCallback(callback, v, [i, j], me, 'map');
879
+ return fastCallback(v, [i, j], me);
879
880
  };
880
881
  // invoke _map
881
882
  return _map(this, 0, rows - 1, 0, columns - 1, invoke, skipZeros);
@@ -980,6 +981,7 @@ export var createSparseMatrixClass = /* #__PURE__ */factory(name, dependencies,
980
981
  // rows and columns
981
982
  var rows = this._size[0];
982
983
  var columns = this._size[1];
984
+ var fastCallback = optimizeCallback(callback, me, 'forEach');
983
985
  // loop columns
984
986
  for (var j = 0; j < columns; j++) {
985
987
  // k0 <= k < k1 where k0 = _ptr[j] && k1 = _ptr[j+1]
@@ -992,7 +994,7 @@ export var createSparseMatrixClass = /* #__PURE__ */factory(name, dependencies,
992
994
  var i = this._index[k];
993
995
 
994
996
  // value @ k
995
- callback(this._values[k], [i, j], me);
997
+ fastCallback(this._values[k], [i, j], me);
996
998
  }
997
999
  } else {
998
1000
  // create a cache holding all defined values
@@ -1006,7 +1008,7 @@ export var createSparseMatrixClass = /* #__PURE__ */factory(name, dependencies,
1006
1008
  // and either read the value or zero
1007
1009
  for (var _i7 = 0; _i7 < rows; _i7++) {
1008
1010
  var value = _i7 in values ? values[_i7] : 0;
1009
- callback(value, [_i7, j], me);
1011
+ fastCallback(value, [_i7, j], me);
1010
1012
  }
1011
1013
  }
1012
1014
  }
@@ -1405,6 +1407,7 @@ export var createSparseMatrixClass = /* #__PURE__ */factory(name, dependencies,
1405
1407
  // indeces for column j
1406
1408
  var k0 = ptr[j];
1407
1409
  var k1 = ptr[j + 1];
1410
+
1408
1411
  // loop
1409
1412
  for (var k = k0; k < k1; k++) {
1410
1413
  // invoke callback
@@ -806,6 +806,27 @@ export function get(array, index) {
806
806
  return index.reduce((acc, curr) => acc[curr], array);
807
807
  }
808
808
 
809
+ /**
810
+ * Recursive function to map a multi-dimensional array.
811
+ *
812
+ * @param {*} value - The current value being processed in the array.
813
+ * @param {Array} index - The index of the current value being processed in the array.
814
+ * @param {Array} array - The array being processed.
815
+ * @param {Function} callback - Function that produces the element of the new Array, taking three arguments: the value of the element, the index of the element, and the Array being processed.
816
+ * @returns {*} The new array with each element being the result of the callback function.
817
+ */
818
+ export function recurse(value, index, array, callback) {
819
+ if (Array.isArray(value)) {
820
+ return value.map(function (child, i) {
821
+ // we create a copy of the index array and append the new index value
822
+ return recurse(child, index.concat(i), array, callback);
823
+ });
824
+ } else {
825
+ // invoke the callback function with the right number of arguments
826
+ return callback(value, index, array);
827
+ }
828
+ }
829
+
809
830
  /**
810
831
  * Deep clones a multidimensional array
811
832
  * @param {Array} array
@@ -10,7 +10,7 @@ import { hasOwnProperty } from './object.js';
10
10
  */
11
11
  function getSafeProperty(object, prop) {
12
12
  // only allow getting safe properties of a plain object
13
- if (isPlainObject(object) && isSafeProperty(object, prop)) {
13
+ if (isSafeProperty(object, prop)) {
14
14
  return object[prop];
15
15
  }
16
16
  if (typeof object[prop] === 'function' && isSafeMethod(object, prop)) {
@@ -31,27 +31,22 @@ function getSafeProperty(object, prop) {
31
31
  // TODO: merge this function into access.js?
32
32
  function setSafeProperty(object, prop, value) {
33
33
  // only allow setting safe properties of a plain object
34
- if (isPlainObject(object) && isSafeProperty(object, prop)) {
34
+ if (isSafeProperty(object, prop)) {
35
35
  object[prop] = value;
36
36
  return value;
37
37
  }
38
38
  throw new Error('No access to property "' + prop + '"');
39
39
  }
40
- function getSafeProperties(object) {
41
- return Object.keys(object).filter(prop => hasOwnProperty(object, prop));
42
- }
43
- function hasSafeProperty(object, prop) {
44
- return prop in object;
45
- }
46
40
 
47
41
  /**
48
- * Test whether a property is safe to use for an object.
42
+ * Test whether a property is safe to use on an object or Array.
49
43
  * For example .toString and .constructor are not safe
44
+ * @param {Object | Array} object
50
45
  * @param {string} prop
51
46
  * @return {boolean} Returns true when safe
52
47
  */
53
48
  function isSafeProperty(object, prop) {
54
- if (!object || typeof object !== 'object') {
49
+ if (!isPlainObject(object) && !Array.isArray(object)) {
55
50
  return false;
56
51
  }
57
52
  // SAFE: whitelisted
@@ -147,8 +142,6 @@ var safeNativeMethods = {
147
142
  export { getSafeProperty };
148
143
  export { setSafeProperty };
149
144
  export { isSafeProperty };
150
- export { hasSafeProperty };
151
- export { getSafeProperties };
152
145
  export { getSafeMethod };
153
146
  export { isSafeMethod };
154
147
  export { isPlainObject };