UNPKG

4.57 kBJavaScriptView Raw
1import { factory } from '../../../utils/factory'
2import { DimensionError } from '../../../error/DimensionError'
3import { scatter } from '../../../utils/collection'
4
5const name = 'algorithm06'
6const dependencies = ['typed', 'equalScalar']
7
8export const createAlgorithm06 = /* #__PURE__ */ factory(name, dependencies, ({ typed, equalScalar }) => {
9 /**
10 * Iterates over SparseMatrix A and SparseMatrix B nonzero items and invokes the callback function f(Aij, Bij).
11 * Callback function invoked (Anz U Bnz) times, where Anz and Bnz are the nonzero elements in both matrices.
12 *
13 *
14 * ┌ f(Aij, Bij) ; A(i,j) !== 0 && B(i,j) !== 0
15 * C(i,j) = ┤
16 * └ 0 ; otherwise
17 *
18 *
19 * @param {Matrix} a The SparseMatrix instance (A)
20 * @param {Matrix} b The SparseMatrix instance (B)
21 * @param {Function} callback The f(Aij,Bij) operation to invoke
22 *
23 * @return {Matrix} SparseMatrix (C)
24 *
25 * see https://github.com/josdejong/mathjs/pull/346#issuecomment-97620294
26 */
27 return function algorithm06 (a, b, callback) {
28 // sparse matrix arrays
29 const avalues = a._values
30 const asize = a._size
31 const adt = a._datatype
32 // sparse matrix arrays
33 const bvalues = b._values
34 const bsize = b._size
35 const bdt = b._datatype
36
37 // validate dimensions
38 if (asize.length !== bsize.length) { throw new DimensionError(asize.length, bsize.length) }
39
40 // check rows & columns
41 if (asize[0] !== bsize[0] || asize[1] !== bsize[1]) { throw new RangeError('Dimension mismatch. Matrix A (' + asize + ') must match Matrix B (' + bsize + ')') }
42
43 // rows & columns
44 const rows = asize[0]
45 const columns = asize[1]
46
47 // datatype
48 let dt
49 // equal signature to use
50 let eq = equalScalar
51 // zero value
52 let zero = 0
53 // callback signature to use
54 let cf = callback
55
56 // process data types
57 if (typeof adt === 'string' && adt === bdt) {
58 // datatype
59 dt = adt
60 // find signature that matches (dt, dt)
61 eq = typed.find(equalScalar, [dt, dt])
62 // convert 0 to the same datatype
63 zero = typed.convert(0, dt)
64 // callback
65 cf = typed.find(callback, [dt, dt])
66 }
67
68 // result arrays
69 const cvalues = avalues && bvalues ? [] : undefined
70 const cindex = []
71 const cptr = []
72 // matrix
73 const c = a.createSparseMatrix({
74 values: cvalues,
75 index: cindex,
76 ptr: cptr,
77 size: [rows, columns],
78 datatype: dt
79 })
80
81 // workspaces
82 const x = cvalues ? [] : undefined
83 // marks indicating we have a value in x for a given column
84 const w = []
85 // marks indicating value in a given row has been updated
86 const u = []
87
88 // loop columns
89 for (let j = 0; j < columns; j++) {
90 // update cptr
91 cptr[j] = cindex.length
92 // columns mark
93 const mark = j + 1
94 // scatter the values of A(:,j) into workspace
95 scatter(a, j, w, x, u, mark, c, cf)
96 // scatter the values of B(:,j) into workspace
97 scatter(b, j, w, x, u, mark, c, cf)
98 // check we need to process values (non pattern matrix)
99 if (x) {
100 // initialize first index in j
101 let k = cptr[j]
102 // loop index in j
103 while (k < cindex.length) {
104 // row
105 const i = cindex[k]
106 // check function was invoked on current row (Aij !=0 && Bij != 0)
107 if (u[i] === mark) {
108 // value @ i
109 const v = x[i]
110 // check for zero value
111 if (!eq(v, zero)) {
112 // push value
113 cvalues.push(v)
114 // increment pointer
115 k++
116 } else {
117 // remove value @ i, do not increment pointer
118 cindex.splice(k, 1)
119 }
120 } else {
121 // remove value @ i, do not increment pointer
122 cindex.splice(k, 1)
123 }
124 }
125 } else {
126 // initialize first index in j
127 let p = cptr[j]
128 // loop index in j
129 while (p < cindex.length) {
130 // row
131 const r = cindex[p]
132 // check function was invoked on current row (Aij !=0 && Bij != 0)
133 if (u[r] !== mark) {
134 // remove value @ i, do not increment pointer
135 cindex.splice(p, 1)
136 } else {
137 // increment pointer
138 p++
139 }
140 }
141 }
142 }
143 // update cptr
144 cptr[columns] = cindex.length
145
146 // return sparse matrix
147 return c
148 }
149})