UNPKG

3.19 kBJavaScriptView Raw
1import { factory } from '../../../utils/factory'
2import { DimensionError } from '../../../error/DimensionError'
3
4const name = 'algorithm07'
5const dependencies = ['typed', 'DenseMatrix']
6
7export const createAlgorithm07 = /* #__PURE__ */ factory(name, dependencies, ({ typed, DenseMatrix }) => {
8 /**
9 * Iterates over SparseMatrix A and SparseMatrix B items (zero and nonzero) and invokes the callback function f(Aij, Bij).
10 * Callback function invoked MxN times.
11 *
12 * C(i,j) = f(Aij, Bij)
13 *
14 * @param {Matrix} a The SparseMatrix instance (A)
15 * @param {Matrix} b The SparseMatrix instance (B)
16 * @param {Function} callback The f(Aij,Bij) operation to invoke
17 *
18 * @return {Matrix} DenseMatrix (C)
19 *
20 * see https://github.com/josdejong/mathjs/pull/346#issuecomment-97620294
21 */
22 return function algorithm07 (a, b, callback) {
23 // sparse matrix arrays
24 const asize = a._size
25 const adt = a._datatype
26 // sparse matrix arrays
27 const bsize = b._size
28 const bdt = b._datatype
29
30 // validate dimensions
31 if (asize.length !== bsize.length) { throw new DimensionError(asize.length, bsize.length) }
32
33 // check rows & columns
34 if (asize[0] !== bsize[0] || asize[1] !== bsize[1]) { throw new RangeError('Dimension mismatch. Matrix A (' + asize + ') must match Matrix B (' + bsize + ')') }
35
36 // rows & columns
37 const rows = asize[0]
38 const columns = asize[1]
39
40 // datatype
41 let dt
42 // zero value
43 let zero = 0
44 // callback signature to use
45 let cf = callback
46
47 // process data types
48 if (typeof adt === 'string' && adt === bdt) {
49 // datatype
50 dt = adt
51 // convert 0 to the same datatype
52 zero = typed.convert(0, dt)
53 // callback
54 cf = typed.find(callback, [dt, dt])
55 }
56
57 // vars
58 let i, j
59
60 // result arrays
61 const cdata = []
62 // initialize c
63 for (i = 0; i < rows; i++) { cdata[i] = [] }
64
65 // matrix
66 const c = new DenseMatrix({
67 data: cdata,
68 size: [rows, columns],
69 datatype: dt
70 })
71
72 // workspaces
73 const xa = []
74 const xb = []
75 // marks indicating we have a value in x for a given column
76 const wa = []
77 const wb = []
78
79 // loop columns
80 for (j = 0; j < columns; j++) {
81 // columns mark
82 const mark = j + 1
83 // scatter the values of A(:,j) into workspace
84 _scatter(a, j, wa, xa, mark)
85 // scatter the values of B(:,j) into workspace
86 _scatter(b, j, wb, xb, mark)
87 // loop rows
88 for (i = 0; i < rows; i++) {
89 // matrix values @ i,j
90 const va = wa[i] === mark ? xa[i] : zero
91 const vb = wb[i] === mark ? xb[i] : zero
92 // invoke callback
93 cdata[i][j] = cf(va, vb)
94 }
95 }
96
97 // return sparse matrix
98 return c
99 }
100
101 function _scatter (m, j, w, x, mark) {
102 // a arrays
103 const values = m._values
104 const index = m._index
105 const ptr = m._ptr
106 // loop values in column j
107 for (let k = ptr[j], k1 = ptr[j + 1]; k < k1; k++) {
108 // row
109 const i = index[k]
110 // update workspace
111 w[i] = mark
112 x[i] = values[k]
113 }
114 }
115})