Source: linearAlgebra.js

/**
* @method
* @file linearAlgebra.js
* @desc Provides an interface for linear algebra.
* @createDate 2018.8.11.
* @author yhzheng
*/
"use strict";

var outside = this;

/**
 * @class matrix
 * @classdesc This is the class of matrix.
 * @desc It's for create object and init object.
 */
class matrix
{
    constructor(width,height,value){
        this.type = "matrix";
        this.value = [];
        this.width = width;
        this.height = height;
        if (typeof value === "object"){
            for (var i = 0 ; i < height ; i++){
                this.value[i] = [];
                for (var j = 0 ; j < width ; j++){
                    this.value[i][j] = value[i][j];
                }
            }
        } else {
            for (var i = 0 ; i < height ; i++){
                this.value[i] = [];
                for (var j = 0 ; j < width ; j++){
                    this.value[i][j] = value;
                }
            }
        }
    }
    /**
     * @method
     * @function T
     * @desc For change this matrix to the value of matrix after T.
     */
    T(){
        this.value = outside.T(this).value;
    }
    /**
     * @method
     * @function each
     * @desc For each this matrix.
     */
    each(callback){
        for (var i = 0 ; i < this.width ; i++){
            for (var j = 0 ; j < this.height ; j++){
                callback(j,i,this.value[j][i]);
            }
        }
    }
    /**
     * @method
     * @function add
     * @param {matrix} matrix_ The matrix.
     * @desc For change this matrix to the value of matrix after added another matrix.
     */
    add(matrix_){
        var res = outside.add(this,matrix_);
        if (res)
            this.value = res.value;
    }
     /**
     * @method
     * @function product
     * @param {vector} matrix The matrix or vector
     * @desc For get the value of matrix or vector after product.
     */
    product(matrix) {
        var res = outside.product();
        if (res){
            if (typeof res === "object"){
                this.value = res.value;
                this.width = res.width;
                this.height = res.height;
            } else {
                this.value = res;
                this.width = null;
                this.height = null;
            }
        }
    }
    /**
     * @method
     * @function toString()
     * @desc For return the string of matrix.
     */
    toString(){
        return JSON.stringify(this);
    }
    /**
     * @method
     * @function print()
     * @desc For print the string of matrix.
     */
    print(){
        console.log(this.toString());
    }
    /**
     * @method
     * @function toArray()
     * @desc For return the value of matrix.
     */
    toArray(){
        return this.value;
    }
}

/**
 * @class vector
 * @classdesc This is the class of vector.
 * @desc It's for create object and init object.
 */
class vector extends matrix
{
    constructor(width,value){
        if (typeof value === "object"){
            value = [value];
        }
        super(width,1,value);
        this.type = "vector";
    }
    /**
     * @method
     * @function T
     * @desc For change this vector to the value of vector after T.
     */
    T(){
        var tmp = [];
        if (this.height == 1){
            for (var i = 0 ; i < this.width ; i++){
                tmp[i] = [];
                tmp[i][0] = this.value[0][i];
            }
        } else {
            tmp = [[]];
            for (var i = 0 ; i < this.height ; i++){
                tmp[0][i] = this.value[i][0];
            }
        }
        this.value = tmp;
        tmp = this.width;
        this.width = this.height;
        this.height = tmp;
    }
    /**
     * @method
     * @function each
     * @desc For each this vector.
     */
    each(callback){
        if (this.height == 1){
            for (var i = 0 ; i < this.width ; i++){
                callback(i,this.value[0][i]);
            }
        } else {
            for (var i = 0 ; i < this.height ; i++){
                callback(i,this.value[i][0]);
            }
        }
    }
}
/**
 * @method
 * @function T
 * @param {matrix} matrix_ The matrix.
 * @returns {matrix} The value of matrix after T.
 * @desc For get the value of matrix after T.
 */
function T(matrix_) {
    var tmpMatrix = new matrix(matrix_.height,matrix_.width,0);
    for (var i = 0 ; i < matrix_.width ; i++){
        for (var j = 0 ; j < matrix_.height ; j++){
            tmpMatrix.value[i][j] = matrix_.value[j][i];
        }
    }
    var tmp = matrix_.width;
    matrix_.width = matrix_.height;
    matrix_.height = tmp;
    return tmpMatrix;
}

/**
 * @method
 * @function add
 * @param {matrix} matrix1 The matrix or vector
 * @param {matrix} matrix2 The matrix or vector
 * @returns {matrix} The value of matrix after T.
 * @returns {boolean} If can't add,return this.
 * @desc For get the value of matrix after T.
 */
function add(matrix1,matrix2) {
    var res;
    res = add_matrix(matrix1,matrix2);
    if (res) return res;
    res = add_vector(matrix1,matrix2);
    if (res) return res;
    if (matrix1.height == 1 && matrix1.width == matrix2.width){
        for (var i = 0 ; i < matrix1.width ; i++){
            for (var j = 0 ; j < matrix2.height ; j++){
                matrix2.value[j][i] += matrix1.value[0][i];
            }
        }
        return matrix2;
    }
    if (matrix1.width == 1 && matrix1.height == matrix2.height){
        for (var i = 0 ; i < matrix1.height ; i++){
            for (var j = 0 ; j < matrix2.width ; j++){
                matrix2.value[i][j] += matrix1.value[i][0];
            }
        }
        return matrix2;
    }
    return false;
}

/**
 * @method
 * @function add_matrix
 * @param {matrix} matrix1 The matrix
 * @param {matrix} matrix2 The matrix
 * @returns {matrix} The value of matrix after added.
 * @returns {boolean} If can't add,return this.
 * @desc For get the value of matrix after added.
 */
function add_matrix(matrix1,matrix2) {
    if (matrix1.type != "matrix" || matrix2.type != "matrix"){
        return false;
    }
    if (matrix1.width == matrix2.width && matrix1.height == matrix2.height){
        for (var i = 0 ; i < matrix1.height ; i++){
            for (var j = 0 ; j < matrix1.width ; j++){
                matrix1.value[i][j] += matrix2.value[i][j];
            }
        }
    } else if (matrix1.width == matrix2.height && matrix1.height == matrix2.width){
        matrix1.T();
        return add_matrix(matrix1,matrix2);
    } else {
        return false;
    }
}

/**
 * @method
 * @function add_vector
 * @param {vector} vector1 The vector
 * @param {vector} vector2 The vector
 * @returns {vector} The value of vector after added.
 * @returns {boolean} If can't add,return this.
 * @desc For get the value of vector after added.
 */
function add_vector(vector1,vector2) {
    if (vector1.type != "vector" || vector2.type != "vector"){
        return false;
    }
    if (vector1.width == vector2.width){
        for (var i = 0 ; i < vector1.width ; i++){
            vector1.value[0][i] += vector2.value[0][i];
        }
    } else if (vector1.width == vector2.height){
        vector1.T();
        add_vector(vector1,vector2);
    } else {
        return false;
    }
}


/**
 * @method
 * @function product
 * @param {matrix} matrix1 The matrix or vector
 * @param {matrix} matrix2 The matrix or vector
 * @returns {matrix} The value of matrix after product.
 * @desc For get the value of matrix or vector after product.
 */
function product(matrix1,matrix2) {
    if (matrix1.type == "matrix" && matrix2.type == "matrix"){
        return matrix_product(matrix1,matrix2);
    }
    if (matrix1.type == "vector" && matrix2.type == "vector"){
        return vector_product(matrix1,matrix2);
    }
    if (matrix1.type == "matrix"){
        if (matrix2.width == 1){
            for (var i = 0 ; i < matrix1.height ; i++){
                for (var j = 0 ; j < matrix1.width ; j++){
                    matrix1.value[i][j] *= matrix2.value[i][0];
                }
            }
        } else {
            for (var i = 0 ; i < matrix1.height ; i++){
                for (var j = 0 ; j < matrix1.width ; j++){
                    matrix1.value[i][j] *= matrix2.value[0][i];
                }
            }
        }
    } else {
        if (matrix1.width == 1){
            for (var i = 0 ; i < matrix2.height ; i++){
                for (var j = 0 ; j < matrix2.width ; j++){
                    matrix2.value[i][j] *= matrix2.value[i][0];
                }
            }
        } else {
            for (var i = 0 ; i < matrix2.height ; i++){
                for (var j = 0 ; j < matrix1.width ; j++){
                    matrix2.value[i][j] *= matrix1.value[0][i];
                }
            }
        }
    }
}

/**
 * @method
 * @function matrix_product
 * @param {matrix} matrix1 The matrix
 * @param {matrix} matrix2 The matrix
 * @returns {matrix} The value of matrix after product.
 * @desc For get the value of matrix after product.
 */
function matrix_product(matrix1,matrix2) {
    if (matrix1.width != matrix2.height){
        return false;
    }
    var matrix3 = new matrix(matrix1.height,matrix2.width,0);
    matrix3.each(function (i,j) {
        for (var k = 0 ; k < matrix1.width/* or matrix2.width */ ; k++){
            matrix3.value[i][j] += matrix1.value[i][k] * matrix2.value[k][j];
        }
    });
    return matrix3;
}

/**
 * @method
 * @function vector_product
 * @param {vector} vector1 The vector
 * @param {vector} vector2 The vector
 * @returns {number} The value of vector after product.
 * @desc For get the value of vector after product.
 */
function vector_product(vector1,vector2) {
    var num = 0;
    if (vector1.width != 1){
        vector1.T();
    }
    if (vector2.width != 1){
        vector2.T();
    }
    if (vector1.height < vector2.height){
        vector1.each(function (i,value) {
            num += value * vector2.value[i][0];
        });
    } else {
        vector2.each(function (i,value) {
            num += value * vector1.value[i][0];
        });
    }
    return num;
}

module.exports.matrix = matrix;
module.exports.vector = vector;
module.exports.T = T;
module.exports.add = add;
module.exports.add_matrix = add_matrix;
module.exports.add_vector = add_vector;
module.exports.matrix_product = matrix_product;
module.exports.vector_product = vector_product;
module.exports.product = product;