Skip to content

Commit a8d5f86

Browse files
committed
feat: add new matrix addition method and improve performance of mmul and kroneckerProduct method
1 parent 28cc87c commit a8d5f86

File tree

2 files changed

+60
-14
lines changed

2 files changed

+60
-14
lines changed

src/__tests__/test.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,24 @@
1-
import { SparseMatrix } from '..';
1+
import { SparseMatrix } from '../index';
22

33
describe('Sparse Matrix', () => {
4+
it('add', () => {
5+
let m1 = new SparseMatrix([
6+
[2, 0, 1],
7+
[0, 0, 3],
8+
[2, 0, 1],
9+
]);
10+
let m2 = new SparseMatrix([
11+
[0, 1, 5],
12+
[2, 0, 0],
13+
[-2, 0, -1],
14+
]);
15+
let m3 = m1.add(m2).to2DArray();
16+
expect(m3).toStrictEqual([
17+
[2, 1, 6],
18+
[2, 0, 3],
19+
[0, 0, 0],
20+
]);
21+
});
422
it('mmul', () => {
523
let m1 = new SparseMatrix([
624
[2, 0, 1],

src/index.js

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,12 @@ export class SparseMatrix {
1717

1818
if (Array.isArray(rows)) {
1919
const matrix = rows;
20-
rows = matrix.length;
21-
options = columns || {};
20+
const nbRows = matrix.length;
21+
const nbColmuns = matrix[0].length;
22+
options = columns || { initialCapacity: nbRows * nbColmuns };
2223
columns = matrix[0].length;
23-
this._init(rows, columns, new HashTable(options), options.threshold);
24-
for (let i = 0; i < rows; i++) {
24+
this._init(nbRows, columns, new HashTable(options), options.threshold);
25+
for (let i = 0; i < nbRows; i++) {
2526
for (let j = 0; j < columns; j++) {
2627
let value = matrix[i][j];
2728
if (this.threshold && Math.abs(value) < this.threshold) value = 0;
@@ -30,6 +31,7 @@ export class SparseMatrix {
3031
}
3132
}
3233
}
34+
this.elements.maybeShrinkCapacity();
3335
} else {
3436
this._init(rows, columns, new HashTable(options), options.threshold);
3537
}
@@ -132,6 +134,19 @@ export class SparseMatrix {
132134
return this;
133135
}
134136

137+
addNew(other) {
138+
if (typeof other === 'number') return this.addS(other);
139+
if (this.rows !== other.rows || this.columns !== other.columns) {
140+
throw new RangeError('Matrices dimensions must be equal');
141+
}
142+
143+
other.withEachNonZero((i, j, v) => {
144+
this.set(i, j, v + this.get(i, j));
145+
});
146+
147+
return this;
148+
}
149+
135150
mmul(other) {
136151
if (this.columns !== other.rows) {
137152
// eslint-disable-next-line no-console
@@ -144,14 +159,12 @@ export class SparseMatrix {
144159
const p = other.columns;
145160

146161
const result = new SparseMatrix(m, p);
147-
this.forEachNonZero((i, j, v1) => {
148-
other.forEachNonZero((k, l, v2) => {
162+
this.withEachNonZero((i, j, v1) => {
163+
other.withEachNonZero((k, l, v2) => {
149164
if (j === k) {
150165
result.set(i, l, result.get(i, l) + v1 * v2);
151166
}
152-
return v2;
153167
});
154-
return v1;
155168
});
156169
return result;
157170
}
@@ -165,16 +178,31 @@ export class SparseMatrix {
165178
const result = new SparseMatrix(m * p, n * q, {
166179
initialCapacity: this.cardinality * other.cardinality,
167180
});
168-
this.forEachNonZero((i, j, v1) => {
169-
other.forEachNonZero((k, l, v2) => {
170-
result.set(p * i + k, q * j + l, v1 * v2);
171-
return v2;
181+
182+
this.withEachNonZero((i, j, v1) => {
183+
const pi = p * i;
184+
const qj = q * j;
185+
other.withEachNonZero((k, l, v2) => {
186+
result.set(pi + k, qj + l, v1 * v2);
172187
});
173-
return v1;
174188
});
175189
return result;
176190
}
177191

192+
withEachNonZero(callback) {
193+
const { state, table, values } = this.elements;
194+
const nbStates = state.length;
195+
const activeIndex = [];
196+
for (let i = 0; i < nbStates; i++) {
197+
if (state[i] === 1) activeIndex.push(i);
198+
}
199+
const columns = this.columns;
200+
for (const i of activeIndex) {
201+
const key = table[i];
202+
callback((key / columns) | 0, key % columns, values[i]);
203+
}
204+
}
205+
178206
forEachNonZero(callback) {
179207
this.elements.forEachPair((key, value) => {
180208
const i = (key / this.columns) | 0;

0 commit comments

Comments
 (0)