multiply.js 25 KB

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