javascript/scripts/matrixUtils_js.js

/**
 * Utility functions for matrix operations.
 * @member matrixUtils_js
 * @memberof jsScripts
 */
export const matrixUtils = {
  /**
   * Performs matrix multiplication using the naive dot product.
   * @memberof matrixUtils_js
   * @param {number[]} d - The input matrices as a 2D array.
   * @param {number[]} sizes - The sizes of the matrices [m, n, p].
   * @returns {number[]} - The result of matrix multiplication.
   */
  matrixMultiply_js: (d, sizes) => {
    d = [d.slice(0, d.length / 2), d.slice(d.length / 2, d.length)];

    if (!sizes) {
      const n = Math.sqrt(d[0].length);
      if (d[0].length % n === 0 && d[1].length % n === 0) {
        sizes = [n, n, n];
      } else {
        console.error("Please input the sizes of your matrices.");
      }
    }
    const [m, n, p] = sizes;
    const a = d[0];
    const b = d[1];
    const c = new Array(m * p);

    for (let i = 0; i < m; i++) {
      for (let j = 0; j < p; j++) {
        let sum = 0;
        for (let k = 0; k < n; k++) {
          sum += a[i * n + k] * b[k * p + j];
        }
        c[i * p + j] = sum;
      }
    }
    return c;
  },

  /**
   * Performs matrix addition.
   * @memberof matrixUtils_js
   * @param {number[]} d - The input matrices as a 2D array.
   * @returns {number[]} - The result of matrix addition.
   */
  matrixAdd_js: (d) => {
    if (d.length === 1) {
      console.error("Please input array sizes nxm");
      return;
    } else {
      d = [d.slice(0, d.length / 2), d.slice(d.length / 2, d.length)];
      var res = new Array(d.length);
      for (var i = 0; i < d[0].length; i++) {
        res.push(d[0][i] + d[1][i]);
      }
      return res;
    }
  },

  /**
   * Creates a convolution of a 2D matrix.
   * @memberof matrixUtils_js
   * @param {object} data - The input data object.
   * @param {number[][]} data.input - The input matrix.
   * @param {number[][]} data.kernel - The kernel matrix.
   * @returns {number[][]} - The convolution result.
   */
  conv2d_js: (data) => {
    let { input, kernel } = data;
    let output = [];

    let inputRows = input.length;
    let inputCols = input[0].length;
    let kernelRows = kernel.length;
    let kernelCols = kernel[0].length;

    let padRows = Math.floor(kernelRows / 2);
    let padCols = Math.floor(kernelCols / 2);

    let paddedInput = [];
    for (let i = 0; i < inputRows + 2 * padRows; i++) {
      let row = [];
      for (let j = 0; j < inputCols + 2 * padCols; j++) {
        row.push(0);
      }
      paddedInput.push(row);
    }

    for (let i = 0; i < inputRows; i++) {
      for (let j = 0; j < inputCols; j++) {
        paddedInput[i + padRows][j + padCols] = input[i][j];
      }
    }

    for (let i = 0; i < inputRows; i++) {
      let row = [];
      for (let j = 0; j < inputCols; j++) {
        let sum = 0;
        for (let m = 0; m < kernelRows; m++) {
          for (let n = 0; n < kernelCols; n++) {
            let ii = i + m - padRows;
            let jj = j + n - padCols;
            sum += paddedInput[ii][jj] * kernel[m][n];
          }
        }
        row.push(sum);
      }
      output.push(row);
    }

    return output;
  },
  /**
   * Runs the specified function in the `matrixUtils` object with the given data.
   * @memberof matrixUtils_js
   * @param {string} name - The name of the function to run.
   * @param {*} data - The input data for the function.
   * @returns {*} - The result of the function, or `undefined` if the function is not found.
   */
  main: (name, data) => {
    if (typeof matrixUtils[name] === "undefined") {
      return console.error("Function is not found in the given script.");
    } else {
      return matrixUtils[name](data);
    }
  },
};