1 | 'use strict'
|
2 |
|
3 | const extend = require('../../utils/object').extend
|
4 | const array = require('../../utils/array')
|
5 |
|
6 | function factory (type, config, load, typed) {
|
7 | const latex = require('../../utils/latex')
|
8 |
|
9 | const matrix = load(require('../../type/matrix/function/matrix'))
|
10 | const addScalar = load(require('./addScalar'))
|
11 | const multiplyScalar = load(require('./multiplyScalar'))
|
12 | const equalScalar = load(require('../relational/equalScalar'))
|
13 |
|
14 | const algorithm11 = load(require('../../type/matrix/utils/algorithm11'))
|
15 | const algorithm14 = load(require('../../type/matrix/utils/algorithm14'))
|
16 |
|
17 | const DenseMatrix = type.DenseMatrix
|
18 | const SparseMatrix = type.SparseMatrix
|
19 |
|
20 | |
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 | const multiply = typed('multiply', extend({
|
54 |
|
55 |
|
56 | 'Array, Array': function (x, y) {
|
57 |
|
58 | _validateMatrixDimensions(array.size(x), array.size(y))
|
59 |
|
60 |
|
61 | const m = multiply(matrix(x), matrix(y))
|
62 |
|
63 | return type.isMatrix(m) ? m.valueOf() : m
|
64 | },
|
65 |
|
66 | 'Matrix, Matrix': function (x, y) {
|
67 |
|
68 | const xsize = x.size()
|
69 | const ysize = y.size()
|
70 |
|
71 |
|
72 | _validateMatrixDimensions(xsize, ysize)
|
73 |
|
74 |
|
75 | if (xsize.length === 1) {
|
76 |
|
77 | if (ysize.length === 1) {
|
78 |
|
79 | return _multiplyVectorVector(x, y, xsize[0])
|
80 | }
|
81 |
|
82 | return _multiplyVectorMatrix(x, y)
|
83 | }
|
84 |
|
85 | if (ysize.length === 1) {
|
86 |
|
87 | return _multiplyMatrixVector(x, y)
|
88 | }
|
89 |
|
90 | return _multiplyMatrixMatrix(x, y)
|
91 | },
|
92 |
|
93 | 'Matrix, Array': function (x, y) {
|
94 |
|
95 | return multiply(x, matrix(y))
|
96 | },
|
97 |
|
98 | 'Array, Matrix': function (x, y) {
|
99 |
|
100 | return multiply(matrix(x, y.storage()), y)
|
101 | },
|
102 |
|
103 | 'SparseMatrix, any': function (x, y) {
|
104 | return algorithm11(x, y, multiplyScalar, false)
|
105 | },
|
106 |
|
107 | 'DenseMatrix, any': function (x, y) {
|
108 | return algorithm14(x, y, multiplyScalar, false)
|
109 | },
|
110 |
|
111 | 'any, SparseMatrix': function (x, y) {
|
112 | return algorithm11(y, x, multiplyScalar, true)
|
113 | },
|
114 |
|
115 | 'any, DenseMatrix': function (x, y) {
|
116 | return algorithm14(y, x, multiplyScalar, true)
|
117 | },
|
118 |
|
119 | 'Array, any': function (x, y) {
|
120 |
|
121 | return algorithm14(matrix(x), y, multiplyScalar, false).valueOf()
|
122 | },
|
123 |
|
124 | 'any, Array': function (x, y) {
|
125 |
|
126 | return algorithm14(matrix(y), x, multiplyScalar, true).valueOf()
|
127 | },
|
128 |
|
129 | 'any, any': multiplyScalar,
|
130 |
|
131 | 'any, any, ...any': function (x, y, rest) {
|
132 | let result = multiply(x, y)
|
133 |
|
134 | for (let i = 0; i < rest.length; i++) {
|
135 | result = multiply(result, rest[i])
|
136 | }
|
137 |
|
138 | return result
|
139 | }
|
140 | }, multiplyScalar.signatures))
|
141 |
|
142 | function _validateMatrixDimensions (size1, size2) {
|
143 |
|
144 | switch (size1.length) {
|
145 | case 1:
|
146 |
|
147 | switch (size2.length) {
|
148 | case 1:
|
149 |
|
150 | if (size1[0] !== size2[0]) {
|
151 |
|
152 | throw new RangeError('Dimension mismatch in multiplication. Vectors must have the same length')
|
153 | }
|
154 | break
|
155 | case 2:
|
156 |
|
157 | if (size1[0] !== size2[0]) {
|
158 |
|
159 | throw new RangeError('Dimension mismatch in multiplication. Vector length (' + size1[0] + ') must match Matrix rows (' + size2[0] + ')')
|
160 | }
|
161 | break
|
162 | default:
|
163 | throw new Error('Can only multiply a 1 or 2 dimensional matrix (Matrix B has ' + size2.length + ' dimensions)')
|
164 | }
|
165 | break
|
166 | case 2:
|
167 |
|
168 | switch (size2.length) {
|
169 | case 1:
|
170 |
|
171 | if (size1[1] !== size2[0]) {
|
172 |
|
173 | throw new RangeError('Dimension mismatch in multiplication. Matrix columns (' + size1[1] + ') must match Vector length (' + size2[0] + ')')
|
174 | }
|
175 | break
|
176 | case 2:
|
177 |
|
178 | if (size1[1] !== size2[0]) {
|
179 |
|
180 | throw new RangeError('Dimension mismatch in multiplication. Matrix A columns (' + size1[1] + ') must match Matrix B rows (' + size2[0] + ')')
|
181 | }
|
182 | break
|
183 | default:
|
184 | throw new Error('Can only multiply a 1 or 2 dimensional matrix (Matrix B has ' + size2.length + ' dimensions)')
|
185 | }
|
186 | break
|
187 | default:
|
188 | throw new Error('Can only multiply a 1 or 2 dimensional matrix (Matrix A has ' + size1.length + ' dimensions)')
|
189 | }
|
190 | }
|
191 |
|
192 | |
193 |
|
194 |
|
195 |
|
196 |
|
197 |
|
198 |
|
199 |
|
200 | function _multiplyVectorVector (a, b, n) {
|
201 |
|
202 | if (n === 0) { throw new Error('Cannot multiply two empty vectors') }
|
203 |
|
204 |
|
205 | const adata = a._data
|
206 | const adt = a._datatype
|
207 |
|
208 | const bdata = b._data
|
209 | const bdt = b._datatype
|
210 |
|
211 |
|
212 | let dt
|
213 |
|
214 | let af = addScalar
|
215 |
|
216 | let mf = multiplyScalar
|
217 |
|
218 |
|
219 | if (adt && bdt && adt === bdt && typeof adt === 'string') {
|
220 |
|
221 | dt = adt
|
222 |
|
223 | af = typed.find(addScalar, [dt, dt])
|
224 | mf = typed.find(multiplyScalar, [dt, dt])
|
225 | }
|
226 |
|
227 |
|
228 | let c = mf(adata[0], bdata[0])
|
229 |
|
230 | for (let i = 1; i < n; i++) {
|
231 |
|
232 | c = af(c, mf(adata[i], bdata[i]))
|
233 | }
|
234 | return c
|
235 | }
|
236 |
|
237 | |
238 |
|
239 |
|
240 |
|
241 |
|
242 |
|
243 |
|
244 |
|
245 | function _multiplyVectorMatrix (a, b) {
|
246 |
|
247 | if (b.storage() !== 'dense') {
|
248 | throw new Error('Support for SparseMatrix not implemented')
|
249 | }
|
250 | return _multiplyVectorDenseMatrix(a, b)
|
251 | }
|
252 |
|
253 | |
254 |
|
255 |
|
256 |
|
257 |
|
258 |
|
259 |
|
260 |
|
261 | function _multiplyVectorDenseMatrix (a, b) {
|
262 |
|
263 | const adata = a._data
|
264 | const asize = a._size
|
265 | const adt = a._datatype
|
266 |
|
267 | const bdata = b._data
|
268 | const bsize = b._size
|
269 | const bdt = b._datatype
|
270 |
|
271 | const alength = asize[0]
|
272 | const bcolumns = bsize[1]
|
273 |
|
274 |
|
275 | let dt
|
276 |
|
277 | let af = addScalar
|
278 |
|
279 | let mf = multiplyScalar
|
280 |
|
281 |
|
282 | if (adt && bdt && adt === bdt && typeof adt === 'string') {
|
283 |
|
284 | dt = adt
|
285 |
|
286 | af = typed.find(addScalar, [dt, dt])
|
287 | mf = typed.find(multiplyScalar, [dt, dt])
|
288 | }
|
289 |
|
290 |
|
291 | const c = []
|
292 |
|
293 |
|
294 | for (let j = 0; j < bcolumns; j++) {
|
295 |
|
296 | let sum = mf(adata[0], bdata[0][j])
|
297 |
|
298 | for (let i = 1; i < alength; i++) {
|
299 |
|
300 | sum = af(sum, mf(adata[i], bdata[i][j]))
|
301 | }
|
302 | c[j] = sum
|
303 | }
|
304 |
|
305 |
|
306 | return new DenseMatrix({
|
307 | data: c,
|
308 | size: [bcolumns],
|
309 | datatype: dt
|
310 | })
|
311 | }
|
312 |
|
313 | |
314 |
|
315 |
|
316 |
|
317 |
|
318 |
|
319 |
|
320 |
|
321 | const _multiplyMatrixVector = typed('_multiplyMatrixVector', {
|
322 | 'DenseMatrix, any': _multiplyDenseMatrixVector,
|
323 | 'SparseMatrix, any': _multiplySparseMatrixVector
|
324 | })
|
325 |
|
326 | |
327 |
|
328 |
|
329 |
|
330 |
|
331 |
|
332 |
|
333 |
|
334 | const _multiplyMatrixMatrix = typed('_multiplyMatrixMatrix', {
|
335 | 'DenseMatrix, DenseMatrix': _multiplyDenseMatrixDenseMatrix,
|
336 | 'DenseMatrix, SparseMatrix': _multiplyDenseMatrixSparseMatrix,
|
337 | 'SparseMatrix, DenseMatrix': _multiplySparseMatrixDenseMatrix,
|
338 | 'SparseMatrix, SparseMatrix': _multiplySparseMatrixSparseMatrix
|
339 | })
|
340 |
|
341 | |
342 |
|
343 |
|
344 |
|
345 |
|
346 |
|
347 |
|
348 |
|
349 | function _multiplyDenseMatrixVector (a, b) {
|
350 |
|
351 | const adata = a._data
|
352 | const asize = a._size
|
353 | const adt = a._datatype
|
354 |
|
355 | const bdata = b._data
|
356 | const bdt = b._datatype
|
357 |
|
358 | const arows = asize[0]
|
359 | const acolumns = asize[1]
|
360 |
|
361 |
|
362 | let dt
|
363 |
|
364 | let af = addScalar
|
365 |
|
366 | let mf = multiplyScalar
|
367 |
|
368 |
|
369 | if (adt && bdt && adt === bdt && typeof adt === 'string') {
|
370 |
|
371 | dt = adt
|
372 |
|
373 | af = typed.find(addScalar, [dt, dt])
|
374 | mf = typed.find(multiplyScalar, [dt, dt])
|
375 | }
|
376 |
|
377 |
|
378 | const c = []
|
379 |
|
380 |
|
381 | for (let i = 0; i < arows; i++) {
|
382 |
|
383 | const row = adata[i]
|
384 |
|
385 | let sum = mf(row[0], bdata[0])
|
386 |
|
387 | for (let j = 1; j < acolumns; j++) {
|
388 |
|
389 | sum = af(sum, mf(row[j], bdata[j]))
|
390 | }
|
391 | c[i] = sum
|
392 | }
|
393 |
|
394 |
|
395 | return new DenseMatrix({
|
396 | data: c,
|
397 | size: [arows],
|
398 | datatype: dt
|
399 | })
|
400 | }
|
401 |
|
402 | |
403 |
|
404 |
|
405 |
|
406 |
|
407 |
|
408 |
|
409 |
|
410 | function _multiplyDenseMatrixDenseMatrix (a, b) {
|
411 |
|
412 | const adata = a._data
|
413 | const asize = a._size
|
414 | const adt = a._datatype
|
415 |
|
416 | const bdata = b._data
|
417 | const bsize = b._size
|
418 | const bdt = b._datatype
|
419 |
|
420 | const arows = asize[0]
|
421 | const acolumns = asize[1]
|
422 | const bcolumns = bsize[1]
|
423 |
|
424 |
|
425 | let dt
|
426 |
|
427 | let af = addScalar
|
428 |
|
429 | let mf = multiplyScalar
|
430 |
|
431 |
|
432 | if (adt && bdt && adt === bdt && typeof adt === 'string') {
|
433 |
|
434 | dt = adt
|
435 |
|
436 | af = typed.find(addScalar, [dt, dt])
|
437 | mf = typed.find(multiplyScalar, [dt, dt])
|
438 | }
|
439 |
|
440 |
|
441 | const c = []
|
442 |
|
443 |
|
444 | for (let i = 0; i < arows; i++) {
|
445 |
|
446 | const row = adata[i]
|
447 |
|
448 | c[i] = []
|
449 |
|
450 | for (let j = 0; j < bcolumns; j++) {
|
451 |
|
452 | let sum = mf(row[0], bdata[0][j])
|
453 |
|
454 | for (let x = 1; x < acolumns; x++) {
|
455 |
|
456 | sum = af(sum, mf(row[x], bdata[x][j]))
|
457 | }
|
458 | c[i][j] = sum
|
459 | }
|
460 | }
|
461 |
|
462 |
|
463 | return new DenseMatrix({
|
464 | data: c,
|
465 | size: [arows, bcolumns],
|
466 | datatype: dt
|
467 | })
|
468 | }
|
469 |
|
470 | |
471 |
|
472 |
|
473 |
|
474 |
|
475 |
|
476 |
|
477 |
|
478 | function _multiplyDenseMatrixSparseMatrix (a, b) {
|
479 |
|
480 | const adata = a._data
|
481 | const asize = a._size
|
482 | const adt = a._datatype
|
483 |
|
484 | const bvalues = b._values
|
485 | const bindex = b._index
|
486 | const bptr = b._ptr
|
487 | const bsize = b._size
|
488 | const bdt = b._datatype
|
489 |
|
490 | if (!bvalues) { throw new Error('Cannot multiply Dense Matrix times Pattern only Matrix') }
|
491 |
|
492 | const arows = asize[0]
|
493 | const bcolumns = bsize[1]
|
494 |
|
495 |
|
496 | let dt
|
497 |
|
498 | let af = addScalar
|
499 |
|
500 | let mf = multiplyScalar
|
501 |
|
502 | let eq = equalScalar
|
503 |
|
504 | let zero = 0
|
505 |
|
506 |
|
507 | if (adt && bdt && adt === bdt && typeof adt === 'string') {
|
508 |
|
509 | dt = adt
|
510 |
|
511 | af = typed.find(addScalar, [dt, dt])
|
512 | mf = typed.find(multiplyScalar, [dt, dt])
|
513 | eq = typed.find(equalScalar, [dt, dt])
|
514 |
|
515 | zero = typed.convert(0, dt)
|
516 | }
|
517 |
|
518 |
|
519 | const cvalues = []
|
520 | const cindex = []
|
521 | const cptr = []
|
522 |
|
523 | const c = new SparseMatrix({
|
524 | values: cvalues,
|
525 | index: cindex,
|
526 | ptr: cptr,
|
527 | size: [arows, bcolumns],
|
528 | datatype: dt
|
529 | })
|
530 |
|
531 |
|
532 | for (let jb = 0; jb < bcolumns; jb++) {
|
533 |
|
534 | cptr[jb] = cindex.length
|
535 |
|
536 | const kb0 = bptr[jb]
|
537 | const kb1 = bptr[jb + 1]
|
538 |
|
539 | if (kb1 > kb0) {
|
540 |
|
541 | let last = 0
|
542 |
|
543 | for (let i = 0; i < arows; i++) {
|
544 |
|
545 | const mark = i + 1
|
546 |
|
547 | let cij
|
548 |
|
549 | for (let kb = kb0; kb < kb1; kb++) {
|
550 |
|
551 | const ib = bindex[kb]
|
552 |
|
553 | if (last !== mark) {
|
554 |
|
555 | cij = mf(adata[i][ib], bvalues[kb])
|
556 |
|
557 | last = mark
|
558 | } else {
|
559 |
|
560 | cij = af(cij, mf(adata[i][ib], bvalues[kb]))
|
561 | }
|
562 | }
|
563 |
|
564 | if (last === mark && !eq(cij, zero)) {
|
565 |
|
566 | cindex.push(i)
|
567 | cvalues.push(cij)
|
568 | }
|
569 | }
|
570 | }
|
571 | }
|
572 |
|
573 | cptr[bcolumns] = cindex.length
|
574 |
|
575 |
|
576 | return c
|
577 | }
|
578 |
|
579 | |
580 |
|
581 |
|
582 |
|
583 |
|
584 |
|
585 |
|
586 |
|
587 | function _multiplySparseMatrixVector (a, b) {
|
588 |
|
589 | const avalues = a._values
|
590 | const aindex = a._index
|
591 | const aptr = a._ptr
|
592 | const adt = a._datatype
|
593 |
|
594 | if (!avalues) { throw new Error('Cannot multiply Pattern only Matrix times Dense Matrix') }
|
595 |
|
596 | const bdata = b._data
|
597 | const bdt = b._datatype
|
598 |
|
599 | const arows = a._size[0]
|
600 | const brows = b._size[0]
|
601 |
|
602 | const cvalues = []
|
603 | const cindex = []
|
604 | const cptr = []
|
605 |
|
606 |
|
607 | let dt
|
608 |
|
609 | let af = addScalar
|
610 |
|
611 | let mf = multiplyScalar
|
612 |
|
613 | let eq = equalScalar
|
614 |
|
615 | let zero = 0
|
616 |
|
617 |
|
618 | if (adt && bdt && adt === bdt && typeof adt === 'string') {
|
619 |
|
620 | dt = adt
|
621 |
|
622 | af = typed.find(addScalar, [dt, dt])
|
623 | mf = typed.find(multiplyScalar, [dt, dt])
|
624 | eq = typed.find(equalScalar, [dt, dt])
|
625 |
|
626 | zero = typed.convert(0, dt)
|
627 | }
|
628 |
|
629 |
|
630 | const x = []
|
631 |
|
632 | const w = []
|
633 |
|
634 |
|
635 | cptr[0] = 0
|
636 |
|
637 | for (let ib = 0; ib < brows; ib++) {
|
638 |
|
639 | const vbi = bdata[ib]
|
640 |
|
641 | if (!eq(vbi, zero)) {
|
642 |
|
643 | for (let ka0 = aptr[ib], ka1 = aptr[ib + 1], ka = ka0; ka < ka1; ka++) {
|
644 |
|
645 | const ia = aindex[ka]
|
646 |
|
647 | if (!w[ia]) {
|
648 |
|
649 | w[ia] = true
|
650 |
|
651 | cindex.push(ia)
|
652 |
|
653 | x[ia] = mf(vbi, avalues[ka])
|
654 | } else {
|
655 |
|
656 | x[ia] = af(x[ia], mf(vbi, avalues[ka]))
|
657 | }
|
658 | }
|
659 | }
|
660 | }
|
661 |
|
662 | for (let p1 = cindex.length, p = 0; p < p1; p++) {
|
663 |
|
664 | const ic = cindex[p]
|
665 |
|
666 | cvalues[p] = x[ic]
|
667 | }
|
668 |
|
669 | cptr[1] = cindex.length
|
670 |
|
671 |
|
672 | return new SparseMatrix({
|
673 | values: cvalues,
|
674 | index: cindex,
|
675 | ptr: cptr,
|
676 | size: [arows, 1],
|
677 | datatype: dt
|
678 | })
|
679 | }
|
680 |
|
681 | |
682 |
|
683 |
|
684 |
|
685 |
|
686 |
|
687 |
|
688 |
|
689 | function _multiplySparseMatrixDenseMatrix (a, b) {
|
690 |
|
691 | const avalues = a._values
|
692 | const aindex = a._index
|
693 | const aptr = a._ptr
|
694 | const adt = a._datatype
|
695 |
|
696 | if (!avalues) { throw new Error('Cannot multiply Pattern only Matrix times Dense Matrix') }
|
697 |
|
698 | const bdata = b._data
|
699 | const bdt = b._datatype
|
700 |
|
701 | const arows = a._size[0]
|
702 | const brows = b._size[0]
|
703 | const bcolumns = b._size[1]
|
704 |
|
705 |
|
706 | let dt
|
707 |
|
708 | let af = addScalar
|
709 |
|
710 | let mf = multiplyScalar
|
711 |
|
712 | let eq = equalScalar
|
713 |
|
714 | let zero = 0
|
715 |
|
716 |
|
717 | if (adt && bdt && adt === bdt && typeof adt === 'string') {
|
718 |
|
719 | dt = adt
|
720 |
|
721 | af = typed.find(addScalar, [dt, dt])
|
722 | mf = typed.find(multiplyScalar, [dt, dt])
|
723 | eq = typed.find(equalScalar, [dt, dt])
|
724 |
|
725 | zero = typed.convert(0, dt)
|
726 | }
|
727 |
|
728 |
|
729 | const cvalues = []
|
730 | const cindex = []
|
731 | const cptr = []
|
732 |
|
733 | const c = new SparseMatrix({
|
734 | values: cvalues,
|
735 | index: cindex,
|
736 | ptr: cptr,
|
737 | size: [arows, bcolumns],
|
738 | datatype: dt
|
739 | })
|
740 |
|
741 |
|
742 | const x = []
|
743 |
|
744 | const w = []
|
745 |
|
746 |
|
747 | for (let jb = 0; jb < bcolumns; jb++) {
|
748 |
|
749 | cptr[jb] = cindex.length
|
750 |
|
751 | const mark = jb + 1
|
752 |
|
753 | for (let ib = 0; ib < brows; ib++) {
|
754 |
|
755 | const vbij = bdata[ib][jb]
|
756 |
|
757 | if (!eq(vbij, zero)) {
|
758 |
|
759 | for (let ka0 = aptr[ib], ka1 = aptr[ib + 1], ka = ka0; ka < ka1; ka++) {
|
760 |
|
761 | const ia = aindex[ka]
|
762 |
|
763 | if (w[ia] !== mark) {
|
764 |
|
765 | w[ia] = mark
|
766 |
|
767 | cindex.push(ia)
|
768 |
|
769 | x[ia] = mf(vbij, avalues[ka])
|
770 | } else {
|
771 |
|
772 | x[ia] = af(x[ia], mf(vbij, avalues[ka]))
|
773 | }
|
774 | }
|
775 | }
|
776 | }
|
777 |
|
778 | for (let p0 = cptr[jb], p1 = cindex.length, p = p0; p < p1; p++) {
|
779 |
|
780 | const ic = cindex[p]
|
781 |
|
782 | cvalues[p] = x[ic]
|
783 | }
|
784 | }
|
785 |
|
786 | cptr[bcolumns] = cindex.length
|
787 |
|
788 |
|
789 | return c
|
790 | }
|
791 |
|
792 | |
793 |
|
794 |
|
795 |
|
796 |
|
797 |
|
798 |
|
799 |
|
800 | function _multiplySparseMatrixSparseMatrix (a, b) {
|
801 |
|
802 | const avalues = a._values
|
803 | const aindex = a._index
|
804 | const aptr = a._ptr
|
805 | const adt = a._datatype
|
806 |
|
807 | const bvalues = b._values
|
808 | const bindex = b._index
|
809 | const bptr = b._ptr
|
810 | const bdt = b._datatype
|
811 |
|
812 |
|
813 | const arows = a._size[0]
|
814 | const bcolumns = b._size[1]
|
815 |
|
816 | const values = avalues && bvalues
|
817 |
|
818 |
|
819 | let dt
|
820 |
|
821 | let af = addScalar
|
822 |
|
823 | let mf = multiplyScalar
|
824 |
|
825 |
|
826 | if (adt && bdt && adt === bdt && typeof adt === 'string') {
|
827 |
|
828 | dt = adt
|
829 |
|
830 | af = typed.find(addScalar, [dt, dt])
|
831 | mf = typed.find(multiplyScalar, [dt, dt])
|
832 | }
|
833 |
|
834 |
|
835 | const cvalues = values ? [] : undefined
|
836 | const cindex = []
|
837 | const cptr = []
|
838 |
|
839 | const c = new SparseMatrix({
|
840 | values: cvalues,
|
841 | index: cindex,
|
842 | ptr: cptr,
|
843 | size: [arows, bcolumns],
|
844 | datatype: dt
|
845 | })
|
846 |
|
847 |
|
848 | const x = values ? [] : undefined
|
849 |
|
850 | const w = []
|
851 |
|
852 | let ka, ka0, ka1, kb, kb0, kb1, ia, ib
|
853 |
|
854 | for (let jb = 0; jb < bcolumns; jb++) {
|
855 |
|
856 | cptr[jb] = cindex.length
|
857 |
|
858 | const mark = jb + 1
|
859 |
|
860 | for (kb0 = bptr[jb], kb1 = bptr[jb + 1], kb = kb0; kb < kb1; kb++) {
|
861 |
|
862 | ib = bindex[kb]
|
863 |
|
864 | if (values) {
|
865 |
|
866 | for (ka0 = aptr[ib], ka1 = aptr[ib + 1], ka = ka0; ka < ka1; ka++) {
|
867 |
|
868 | ia = aindex[ka]
|
869 |
|
870 | if (w[ia] !== mark) {
|
871 |
|
872 | w[ia] = mark
|
873 |
|
874 | cindex.push(ia)
|
875 |
|
876 | x[ia] = mf(bvalues[kb], avalues[ka])
|
877 | } else {
|
878 |
|
879 | x[ia] = af(x[ia], mf(bvalues[kb], avalues[ka]))
|
880 | }
|
881 | }
|
882 | } else {
|
883 |
|
884 | for (ka0 = aptr[ib], ka1 = aptr[ib + 1], ka = ka0; ka < ka1; ka++) {
|
885 |
|
886 | ia = aindex[ka]
|
887 |
|
888 | if (w[ia] !== mark) {
|
889 |
|
890 | w[ia] = mark
|
891 |
|
892 | cindex.push(ia)
|
893 | }
|
894 | }
|
895 | }
|
896 | }
|
897 |
|
898 | if (values) {
|
899 |
|
900 | for (let p0 = cptr[jb], p1 = cindex.length, p = p0; p < p1; p++) {
|
901 |
|
902 | const ic = cindex[p]
|
903 |
|
904 | cvalues[p] = x[ic]
|
905 | }
|
906 | }
|
907 | }
|
908 |
|
909 | cptr[bcolumns] = cindex.length
|
910 |
|
911 |
|
912 | return c
|
913 | }
|
914 |
|
915 | multiply.toTex = {
|
916 | 2: `\\left(\${args[0]}${latex.operators['multiply']}\${args[1]}\\right)`
|
917 | }
|
918 |
|
919 | return multiply
|
920 | }
|
921 |
|
922 | exports.name = 'multiply'
|
923 | exports.factory = factory
|