@@ -17,11 +17,12 @@ export class SparseMatrix {
17
17
18
18
if ( Array . isArray ( rows ) ) {
19
19
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 } ;
22
23
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 ++ ) {
25
26
for ( let j = 0 ; j < columns ; j ++ ) {
26
27
let value = matrix [ i ] [ j ] ;
27
28
if ( this . threshold && Math . abs ( value ) < this . threshold ) value = 0 ;
@@ -30,6 +31,7 @@ export class SparseMatrix {
30
31
}
31
32
}
32
33
}
34
+ this . elements . maybeShrinkCapacity ( ) ;
33
35
} else {
34
36
this . _init ( rows , columns , new HashTable ( options ) , options . threshold ) ;
35
37
}
@@ -132,6 +134,19 @@ export class SparseMatrix {
132
134
return this ;
133
135
}
134
136
137
+ add ( 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
+
135
150
mmul ( other ) {
136
151
if ( this . columns !== other . rows ) {
137
152
// eslint-disable-next-line no-console
@@ -144,14 +159,12 @@ export class SparseMatrix {
144
159
const p = other . columns ;
145
160
146
161
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 ) => {
149
164
if ( j === k ) {
150
165
result . set ( i , l , result . get ( i , l ) + v1 * v2 ) ;
151
166
}
152
- return v2 ;
153
167
} ) ;
154
- return v1 ;
155
168
} ) ;
156
169
return result ;
157
170
}
@@ -165,16 +178,31 @@ export class SparseMatrix {
165
178
const result = new SparseMatrix ( m * p , n * q , {
166
179
initialCapacity : this . cardinality * other . cardinality ,
167
180
} ) ;
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 ) ;
172
187
} ) ;
173
- return v1 ;
174
188
} ) ;
175
189
return result ;
176
190
}
177
191
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
+
178
206
forEachNonZero ( callback ) {
179
207
this . elements . forEachPair ( ( key , value ) => {
180
208
const i = ( key / this . columns ) | 0 ;
0 commit comments