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