UNPKG

3.41 kBJavaScriptView Raw
1import { factory } from '../../../utils/factory'
2import { DimensionError } from '../../../error/DimensionError'
3
4const name = 'algorithm01'
5const dependencies = ['typed']
6
7export const createAlgorithm01 = /* #__PURE__ */ factory(name, dependencies, ({ typed }) => {
8 /**
9 * Iterates over SparseMatrix nonzero items and invokes the callback function f(Dij, Sij).
10 * Callback function invoked NNZ times (number of nonzero items in SparseMatrix).
11 *
12 *
13 * ┌ f(Dij, Sij) ; S(i,j) !== 0
14 * C(i,j) = ┤
15 * └ Dij ; otherwise
16 *
17 *
18 * @param {Matrix} denseMatrix The DenseMatrix instance (D)
19 * @param {Matrix} sparseMatrix The SparseMatrix instance (S)
20 * @param {Function} callback The f(Dij,Sij) operation to invoke, where Dij = DenseMatrix(i,j) and Sij = SparseMatrix(i,j)
21 * @param {boolean} inverse A true value indicates callback should be invoked f(Sij,Dij)
22 *
23 * @return {Matrix} DenseMatrix (C)
24 *
25 * see https://github.com/josdejong/mathjs/pull/346#issuecomment-97477571
26 */
27 return function algorithm1 (denseMatrix, sparseMatrix, callback, inverse) {
28 // dense matrix arrays
29 const adata = denseMatrix._data
30 const asize = denseMatrix._size
31 const adt = denseMatrix._datatype
32 // sparse matrix arrays
33 const bvalues = sparseMatrix._values
34 const bindex = sparseMatrix._index
35 const bptr = sparseMatrix._ptr
36 const bsize = sparseMatrix._size
37 const bdt = sparseMatrix._datatype
38
39 // validate dimensions
40 if (asize.length !== bsize.length) { throw new DimensionError(asize.length, bsize.length) }
41
42 // check rows & columns
43 if (asize[0] !== bsize[0] || asize[1] !== bsize[1]) { throw new RangeError('Dimension mismatch. Matrix A (' + asize + ') must match Matrix B (' + bsize + ')') }
44
45 // sparse matrix cannot be a Pattern matrix
46 if (!bvalues) { throw new Error('Cannot perform operation on Dense Matrix and Pattern Sparse Matrix') }
47
48 // rows & columns
49 const rows = asize[0]
50 const columns = asize[1]
51
52 // process data types
53 const dt = typeof adt === 'string' && adt === bdt ? adt : undefined
54 // callback function
55 const cf = dt ? typed.find(callback, [dt, dt]) : callback
56
57 // vars
58 let i, j
59
60 // result (DenseMatrix)
61 const cdata = []
62 // initialize c
63 for (i = 0; i < rows; i++) { cdata[i] = [] }
64
65 // workspace
66 const x = []
67 // marks indicating we have a value in x for a given column
68 const w = []
69
70 // loop columns in b
71 for (j = 0; j < columns; j++) {
72 // column mark
73 const mark = j + 1
74 // values in column j
75 for (let k0 = bptr[j], k1 = bptr[j + 1], k = k0; k < k1; k++) {
76 // row
77 i = bindex[k]
78 // update workspace
79 x[i] = inverse ? cf(bvalues[k], adata[i][j]) : cf(adata[i][j], bvalues[k])
80 // mark i as updated
81 w[i] = mark
82 }
83 // loop rows
84 for (i = 0; i < rows; i++) {
85 // check row is in workspace
86 if (w[i] === mark) {
87 // c[i][j] was already calculated
88 cdata[i][j] = x[i]
89 } else {
90 // item does not exist in S
91 cdata[i][j] = adata[i][j]
92 }
93 }
94 }
95
96 // return dense matrix
97 return denseMatrix.createDenseMatrix({
98 data: cdata,
99 size: [rows, columns],
100 datatype: dt
101 })
102 }
103})