'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.createAlgorithm07 = void 0;

var _factory = require("../../../utils/factory");

var _DimensionError = require("../../../error/DimensionError");

var name = 'algorithm07';
var dependencies = ['typed', 'DenseMatrix'];
var createAlgorithm07 =
/* #__PURE__ */
(0, _factory.factory)(name, dependencies, function (_ref) {
  var typed = _ref.typed,
      DenseMatrix = _ref.DenseMatrix;

  /**
   * Iterates over SparseMatrix A and SparseMatrix B items (zero and nonzero) and invokes the callback function f(Aij, Bij).
   * Callback function invoked MxN times.
   *
   * C(i,j) = f(Aij, Bij)
   *
   * @param {Matrix}   a                 The SparseMatrix instance (A)
   * @param {Matrix}   b                 The SparseMatrix instance (B)
   * @param {Function} callback          The f(Aij,Bij) operation to invoke
   *
   * @return {Matrix}                    DenseMatrix (C)
   *
   * see https://github.com/josdejong/mathjs/pull/346#issuecomment-97620294
   */
  return function algorithm07(a, b, callback) {
    // sparse matrix arrays
    var asize = a._size;
    var adt = a._datatype; // sparse matrix arrays

    var bsize = b._size;
    var bdt = b._datatype; // validate dimensions

    if (asize.length !== bsize.length) {
      throw new _DimensionError.DimensionError(asize.length, bsize.length);
    } // check rows & columns


    if (asize[0] !== bsize[0] || asize[1] !== bsize[1]) {
      throw new RangeError('Dimension mismatch. Matrix A (' + asize + ') must match Matrix B (' + bsize + ')');
    } // rows & columns


    var rows = asize[0];
    var columns = asize[1]; // datatype

    var dt; // zero value

    var zero = 0; // callback signature to use

    var cf = callback; // process data types

    if (typeof adt === 'string' && adt === bdt) {
      // datatype
      dt = adt; // convert 0 to the same datatype

      zero = typed.convert(0, dt); // callback

      cf = typed.find(callback, [dt, dt]);
    } // vars


    var i, j; // result arrays

    var cdata = []; // initialize c

    for (i = 0; i < rows; i++) {
      cdata[i] = [];
    } // matrix


    var c = new DenseMatrix({
      data: cdata,
      size: [rows, columns],
      datatype: dt
    }); // workspaces

    var xa = [];
    var xb = []; // marks indicating we have a value in x for a given column

    var wa = [];
    var wb = []; // loop columns

    for (j = 0; j < columns; j++) {
      // columns mark
      var mark = j + 1; // scatter the values of A(:,j) into workspace

      _scatter(a, j, wa, xa, mark); // scatter the values of B(:,j) into workspace


      _scatter(b, j, wb, xb, mark); // loop rows


      for (i = 0; i < rows; i++) {
        // matrix values @ i,j
        var va = wa[i] === mark ? xa[i] : zero;
        var vb = wb[i] === mark ? xb[i] : zero; // invoke callback

        cdata[i][j] = cf(va, vb);
      }
    } // return sparse matrix


    return c;
  };

  function _scatter(m, j, w, x, mark) {
    // a arrays
    var values = m._values;
    var index = m._index;
    var ptr = m._ptr; // loop values in column j

    for (var k = ptr[j], k1 = ptr[j + 1]; k < k1; k++) {
      // row
      var i = index[k]; // update workspace

      w[i] = mark;
      x[i] = values[k];
    }
  }
});
exports.createAlgorithm07 = createAlgorithm07;