From 78d5254b2efec6b1433438ec6e013516a5214967 Mon Sep 17 00:00:00 2001 From: David Contreras Date: Wed, 12 Feb 2025 23:50:14 -0600 Subject: [PATCH] Initial commit --- src/type/matrix/DenseMatrix.js | 4 +-- src/utils/collection.js | 31 ++++++++++++------- test/benchmark/forEach.js | 26 ++++++++++++++++ test/benchmark/map.js | 24 ++++++++++++++ .../type/matrix/DenseMatrix.test.js | 8 ++--- 5 files changed, 75 insertions(+), 18 deletions(-) diff --git a/src/type/matrix/DenseMatrix.js b/src/type/matrix/DenseMatrix.js index b78fc9acba..089562da16 100644 --- a/src/type/matrix/DenseMatrix.js +++ b/src/type/matrix/DenseMatrix.js @@ -606,7 +606,7 @@ export const createDenseMatrixClass = /* #__PURE__ */ factory(name, dependencies if (maxDepth === 0) return me.clone() const result = new DenseMatrix(me) - const fastCallback = optimizeCallback(callback, me._data, 'map') + const fastCallback = optimizeCallback(callback, me, 'map') if (maxDepth === 1) { return new DenseMatrix( me._data.map((value, index) => fastCallback(value, [index], me)) @@ -629,7 +629,7 @@ export const createDenseMatrixClass = /* #__PURE__ */ factory(name, dependencies */ DenseMatrix.prototype.forEach = function (callback) { const me = this - const fastCallback = optimizeCallback(callback, me._data, 'map') + const fastCallback = optimizeCallback(callback, me, 'map') me._forEach(function (arr, i, index) { fastCallback(arr[i], index, me) }) diff --git a/src/utils/collection.js b/src/utils/collection.js index 021d980cba..d22d2061a0 100644 --- a/src/utils/collection.js +++ b/src/utils/collection.js @@ -27,14 +27,13 @@ export function containsCollections (array) { */ export function deepForEach (array, callback) { if (isMatrix(array)) { - array = array.valueOf() + array.forEach(callback) + } else { + recurseForEach(array, callback) } - - for (let i = 0, ii = array.length; i < ii; i++) { - const value = array[i] - + function recurseForEach (value) { if (Array.isArray(value)) { - deepForEach(value, callback) + value.forEach(recurseForEach) } else { callback(value) } @@ -54,13 +53,21 @@ export function deepForEach (array, callback) { * @return {Array | Matrix} res */ export function deepMap (array, callback, skipZeros) { - if (array && (typeof array.map === 'function')) { - // TODO: replace array.map with a for loop to improve performance - return array.map(function (x) { - return deepMap(x, callback, skipZeros) - }) + const skipZerosCallback = skipZeros + ? value => value === 0 ? 0 : callback(value) + : callback + if (isMatrix(array)) { + // TODO: use a callback that uses only one arguemnt + return array.map(v => skipZerosCallback(v)) } else { - return callback(array) + return recurseMap(array) + } + function recurseMap (value) { + if (Array.isArray(value)) { + return value.map(recurseMap) + } else { + return skipZerosCallback(value) + } } } diff --git a/test/benchmark/forEach.js b/test/benchmark/forEach.js index 555f4b12ae..2da2dac438 100644 --- a/test/benchmark/forEach.js +++ b/test/benchmark/forEach.js @@ -43,6 +43,32 @@ const bench = new Bench({ time: 100, iterations: 100 }) .add('numberMatrix.forEach(abs.signatures.number)', () => { numberMatrix.forEach(abs.signatures.number) }) + .add('genericMatrix.forEach(abs+idx)', () => { + genericMatrix.forEach((x, idx) => abs(x) + idx[0] - idx[1]) + }) + .add('numberMatrix.forEach(abs+idx)', () => { + numberMatrix.forEach((x, idx) => abs(x) + idx[0] - idx[1]) + }) + .add('forEach(genericMatrix, abs+idx)', () => { + forEach(genericMatrix, (x, idx) => abs(x) + idx[0] - idx[1]) + }) + .add('genericMatrix.forEach(abs+idx+arr)', () => { + genericMatrix.forEach((x, idx, X) => abs(x) + idx[0] - idx[1] + X.get([0, 0])) + }) + .add('numberMatrix.forEach(abs+idx+arr)', () => { + numberMatrix.forEach((x, idx, X) => abs(x) + idx[0] - idx[1] + X.get([0, 0])) + }) + .add('forEach(genericMatrix, abs+idx+arr)', () => { + forEach(genericMatrix, (x, idx, X) => abs(x) + idx[0] - idx[1] + X.get([0, 0])) + }) + .add('forEach(array, abs+idx+arr)', () => { + forEach(array, (x, idx, X) => abs(x) + idx[0] - idx[1] + X[0][0]) + }) + .add('genericMatrix iterate', () => { + for (const v of genericMatrix) { + abs(v.value) + } + }) bench.addEventListener('cycle', (event) => console.log(formatTaskResult(bench, event.task))) await bench.run() diff --git a/test/benchmark/map.js b/test/benchmark/map.js index 974265af84..4d2430caf2 100644 --- a/test/benchmark/map.js +++ b/test/benchmark/map.js @@ -43,6 +43,30 @@ const bench = new Bench({ time: 100, iterations: 100 }) .add('numberMatrix.map(abs.signatures.number)', () => { numberMatrix.map(abs.signatures.number) }) + .add('map(array, abs + idx)', () => { + map(array, (x, idx) => abs(x) + idx[0] - idx[1]) + }) + .add('genericMatrix.map(abs + idx)', () => { + genericMatrix.map((x, idx) => abs(x) + idx[0] - idx[1]) + }) + .add('numberMatrix.map(abs + idx)', () => { + numberMatrix.map((x, idx) => abs(x) + idx[0] - idx[1]) + }) + .add('map(array, abs + idx + arr)', () => { + map(array, (x, idx, X) => abs(x) + idx[0] - idx[1] + X[0][0]) + }) + .add('genericMatrix.map(abs + idx + matrix)', () => { + genericMatrix.map((x, idx, X) => abs(x) + idx[0] - idx[1] + X.get([0, 0])) + }) + .add('numberMatrix.map(abs + idx + matrix)', () => { + numberMatrix.map((x, idx, X) => abs(x) + idx[0] - idx[1] + X.get([0, 0])) + }) + .add('genericMatrix iterate', () => { + const result = genericMatrix.clone() + for (const v of genericMatrix) { + result.set(v.index, abs(v.value)) + } + }) bench.addEventListener('cycle', (event) => console.log(formatTaskResult(bench, event.task))) await bench.run() diff --git a/test/unit-tests/type/matrix/DenseMatrix.test.js b/test/unit-tests/type/matrix/DenseMatrix.test.js index 10bdca50ab..8ec8893051 100644 --- a/test/unit-tests/type/matrix/DenseMatrix.test.js +++ b/test/unit-tests/type/matrix/DenseMatrix.test.js @@ -818,22 +818,22 @@ describe('DenseMatrix', function () { ]) expected = [] m.forEach((value, index) => { expected.push({ value, index }) }) - assert.deepStrictEqual(expected, [...m]) + assert.deepStrictEqual([...m], expected) m = new DenseMatrix([1]) expected = [] m.forEach((value, index) => { expected.push({ value, index }) }) - assert.deepStrictEqual(expected, [...m]) + assert.deepStrictEqual([...m], expected) m = new DenseMatrix([1, 2, 3]) expected = [] m.forEach((value, index) => { expected.push({ value, index }) }) - assert.deepStrictEqual(expected, [...m]) + assert.deepStrictEqual([...m], expected) m = new DenseMatrix([]) expected = [] m.forEach((value, index) => { expected.push({ value, index }) }) - assert.deepStrictEqual(expected, [...m]) + assert.deepStrictEqual([...m], expected) }) })