multiply.js

/**
 * @classdesc A library for multiplying a scalar/array/matrix to a scalar/array/matrix. This library will always return matrix type.   
 * @class matrix/multiply
 * @hideconstructor
 */
var u = require('./mUtils');
var matrix = require('../matrix');


// Is multiply valid? e.g. is A.n == B.m 
function isMatrixMultiplyValid(A,B)
{
    var returnVal = false;
    var demA = u.matrix_demension(A);
    var demB = u.matrix_demension(B);

    if(demA[1] == demB[0])
    {
        returnVal = true;
    }
    return returnVal;
}


//Matrix multiply constant 
function matrix_multiplyc(A,c)
{
    var M = [];

    if((typeof A[0][0]) != 'undefined')
    {
        for(var i =0; i<A.length; i++)
        {
            M[i] = [];
            for(var j = 0; j<A[0].length;j++)
            {
                M[i][j] = A[i][j]*c;
            }
        }
    }
    else
    {
        for(var i =0; i<A.length; i++)
        {
            M[i] = A[i]*c;
        }
    }
    return M;
}


//Matrix dot product 
function matrix_dot(m1, m2) {
    var result = [];
    for (var i = 0; i < m1.length; i++) {
        result[i] = [];
        for (var j = 0; j < m2[0].length; j++) {
            var sum = 0;
            for (var k = 0; k < m1[0].length; k++) {
                sum += m1[i][k] * m2[k][j];
            }
            result[i][j] = sum;
        }
    }
    return result;
}


//Matrix element wise multiplication 
function matrix_multiply_same(A,B)
{
    var M = []; 

    for(var i = 0; i < A.length; i++)
    {
        M[i] = [];
        for(var j = 0; j< A[0].length; j++)
        {
            M[i][j] = A[i][j] * B[i][j];
        }
    }

    return M;
}


//Higher level multiply function 
function matrix_multiply(A,B)
{
    var returnVal = 0;
    var bIsScalar = u.isScalar(B);
    var aIsScalar = u.isScalar(A);
    var matrixSameSize = u.matrix_compare_size(A,B);

    if(bIsScalar)
    {
        B = u.getScalar(B);
        returnVal = matrix_multiplyc(A,B);	
    }else if(aIsScalar){
        A = u.getScalar(A);
        returnVal = matrix_multiplyc(B,A);	
    }
    else if(isMatrixMultiplyValid(A,B))
    {
        returnVal = matrix_dot(A,B);
    }
    else if(matrixSameSize)
    {
        returnVal = matrix_multiply_same(A,B);
    }
    else
    {
        returnVal = 'Invalid';
    }

    return returnVal;
}

/**
 * Add a scalar/array/matrix to self
 * @method multiply
 * @param {scalar/array/matrix} x - Multiplies a scalar/array/matrix to self
 * @returns {matrix}
 * @memberof matrix/multiply
 * @example // Add a scalar to a matrix
 * var M = require('./src/matrix_lib'); // or require('math-script')
 * var A = M.ident(2,2); // Create a matrix 
 * A = A.multiply(3); // multiply scalar
 * console.log(A.print())
 * //Result 
 * //3.000           0.000
 * //0.000           3.000
 * 
 * // Perform a matrix dot product
 * var B = M.make([[1,2],[3,4]);
 * B = B.multiply(B)  
 * console.log(B.print())
 * //Result
 * //7.000           10.000
 * //15.000          22.000
 * @example
 * // Use in execute environment  
 * var M = require('./src/matrix_lib'); // or require('math-script')
 * M.execute(function(M){
 * 
 * var A = M.make([[1,2],[3,4]]); // Create a 2x2 matrix
 * var B = (A*A)*3 + 1; // Perform op on matrices and scalars
 * console.log(B.print())
 * 
 * });
 * //Result
 * //22.000          31.000
 * //46.000          67.000
 * 
 */
matrix.multiply = function(A,B)
{
    return new matrix(matrix_multiply(matrix.make(A).value,matrix.make(B).value));
}

//Add prototype to parent class 
matrix.prototype.multiply = function(x){
    var M = matrix_multiply(this.value,matrix.make(x).value);
    return matrix.make(M);
}

// Overload support
matrix.prototype.__multiply = function(x)
{
    var M = matrix_multiply(matrix.make(x).value,this.value,);
    return matrix.make(M);
};

// Scalar overload support  
matrix.numberOverrides.__multiply = function (x) {
    return matrix.make(x).multiply(this);
};