text: "use strict";
  
  function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
  
  require("core-js/modules/es.reflect.construct.js");
  
  require("core-js/modules/es.symbol.js");
  
  require("core-js/modules/es.symbol.description.js");
  
  require("core-js/modules/es.object.to-string.js");
  
  require("core-js/modules/es.symbol.iterator.js");
  
  require("core-js/modules/es.array.iterator.js");
  
  require("core-js/modules/es.string.iterator.js");
  
  require("core-js/modules/web.dom-collections.iterator.js");
  
  exports.__esModule = true;
  exports.MatrixPlugin = void 0;
  
  require("core-js/modules/es.object.get-prototype-of.js");
  
  var _Cell = require("../../Cell");
  
  var _errorMessage = require("../../error-message");
  
  var _Matrix = require("../../Matrix");
  
  var _SimpleRangeValue = require("../SimpleRangeValue");
  
  var _FunctionPlugin2 = require("./FunctionPlugin");
  
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  
  function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
  
  function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
  
  function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
  
  function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
  
  function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
  
  function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
  
  function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
  
  function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
  
  function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
  
  var MatrixPlugin = /*#__PURE__*/function (_FunctionPlugin) {
    _inherits(MatrixPlugin, _FunctionPlugin);
  
    var _super = _createSuper(MatrixPlugin);
  
    function MatrixPlugin(interpreter) {
      var _this;
  
      _classCallCheck(this, MatrixPlugin);
  
      _this = _super.call(this, interpreter);
  
      _this.createCpuKernel = function (kernel, outputSize) {
        return function () {
          var result = [];
  
          for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
            args[_key] = arguments[_key];
          }
  
          for (var y = 0; y < outputSize.height; ++y) {
            result.push([]);
  
            for (var x = 0; x < outputSize.width; ++x) {
              result[y][x] = kernel.apply({
                thread: {
                  x: x,
                  y: y
                }
              }, args);
            }
          }
  
          return result;
        };
      };
  
      _this.createGpuJsKernel = function (kernel, outputSize) {
        return _this.interpreter.getGpuInstance().createKernel(kernel).setPrecision('unsigned').setOutput([outputSize.width, outputSize.height]);
      };
  
      if (_this.config.gpujs === undefined) {
        _this.createKernel = _this.createCpuKernel;
      } else {
        _this.createKernel = _this.createGpuJsKernel;
      }
  
      return _this;
    }
  
    _createClass(MatrixPlugin, [{
      key: "mmult",
      value: function mmult(ast, formulaAddress) {
        var _this2 = this;
  
        return this.runMatrixFunction(ast.args, formulaAddress, this.metadata('MMULT'), function (leftMatrix, rightMatrix) {
          if (!leftMatrix.hasOnlyNumbers() || !rightMatrix.hasOnlyNumbers()) {
            return new _Cell.CellError(_Cell.ErrorType.VALUE, _errorMessage.ErrorMessage.NumberRange);
          }
  
          var outputSize = (0, _Matrix.matrixSizeForMultiplication)(leftMatrix.size, rightMatrix.size);
  
          var result = _this2.createKernel(function (a, b, width) {
            var sum = 0;
  
            for (var i = 0; i < width; ++i) {
              sum += a[this.thread.y][i] * b[i][this.thread.x];
            }
  
            return sum;
          }, outputSize)(leftMatrix.rawNumbers(), rightMatrix.rawNumbers(), leftMatrix.width());
  
          return _SimpleRangeValue.SimpleRangeValue.onlyNumbersDataWithoutRange(result, outputSize);
        });
      }
    }, {
      key: "maxpool",
      value: function maxpool(ast, formulaAddress) {
        var _this3 = this;
  
        return this.runMatrixFunction(ast.args, formulaAddress, this.metadata('MAXPOOL'), function (matrix, windowSize) {
          var stride = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : windowSize;
  
          if (!matrix.hasOnlyNumbers()) {
            return new _Cell.CellError(_Cell.ErrorType.VALUE, _errorMessage.ErrorMessage.NumberRange);
          }
  
          var outputSize = (0, _Matrix.matrixSizeForPoolFunction)(matrix.size, windowSize, stride);
  
          var result = _this3.createKernel(function (a, windowSize, stride) {
            var leftCornerX = this.thread.x * stride;
            var leftCornerY = this.thread.y * stride;
            var currentMax = a[leftCornerY][leftCornerX];
  
            for (var i = 0; i < windowSize; i++) {
              for (var j = 0; j < windowSize; j++) {
                currentMax = Math.max(currentMax, a[leftCornerY + i][leftCornerX + j]);
              }
            }
  
            return currentMax;
          }, outputSize)(matrix.rawNumbers(), windowSize, stride);
  
          return _SimpleRangeValue.SimpleRangeValue.onlyNumbersDataWithoutRange(result, outputSize);
        });
      }
    }, {
      key: "medianpool",
      value: function medianpool(ast, formulaAddress) {
        var _this4 = this;
  
        return this.runMatrixFunction(ast.args, formulaAddress, this.metadata('MEDIANPOOL'), function (matrix, windowSize) {
          var stride = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : windowSize;
  
          if (!matrix.hasOnlyNumbers()) {
            return new _Cell.CellError(_Cell.ErrorType.VALUE, _errorMessage.ErrorMessage.NumberRange);
          }
  
          var outputSize = (0, _Matrix.matrixSizeForPoolFunction)(matrix.size, windowSize, stride);
  
          var result = _this4.createKernel(function (a, windowSize, stride) {
            var leftCornerX = this.thread.x * stride;
            var leftCornerY = this.thread.y * stride;
            var currentMax = a[leftCornerY][leftCornerX];
  
            for (var i = 0; i < windowSize; i++) {
              for (var j = 0; j < windowSize; j++) {
                currentMax = Math.max(currentMax, a[leftCornerY + i][leftCornerX + j]);
              }
            }
  
            var currentMin = a[leftCornerY][leftCornerX];
  
            for (var i2 = 0; i2 < windowSize; i2++) {
              for (var j2 = 0; j2 < windowSize; j2++) {
                currentMin = Math.min(currentMin, a[leftCornerY + i2][leftCornerX + j2]);
              }
            }
  
            var numberOfElements = windowSize * windowSize;
            var leftEnd = currentMin;
            var rightEnd = currentMax;
            var result = 42;
  
            for (var iter = 0; iter < 32; iter++) {
              var medianGuess = (leftEnd + rightEnd) / 2;
              var medianGuessCount = 0;
  
              for (var i3 = 0; i3 < windowSize; i3++) {
                for (var j3 = 0; j3 < windowSize; j3++) {
                  if (a[leftCornerY + i3][leftCornerX + j3] > medianGuess) {
                    medianGuessCount++;
                  }
                }
              }
  
              if (windowSize % 2 === 0) {
                if (medianGuessCount === numberOfElements / 2) {
                  result = medianGuess;
                  break;
                } else if (medianGuessCount > numberOfElements / 2) {
                  leftEnd = medianGuess;
                } else {
                  rightEnd = medianGuess;
                }
              } else {
                if (medianGuessCount === (numberOfElements - 1) / 2) {
                  result = medianGuess;
                  break;
                } else if (medianGuessCount > (numberOfElements - 1) / 2) {
                  leftEnd = medianGuess;
                } else {
                  rightEnd = medianGuess;
                }
              }
            }
  
            return result;
          }, outputSize)(matrix.rawNumbers(), windowSize, stride);
  
          return _SimpleRangeValue.SimpleRangeValue.onlyNumbersDataWithoutRange(result, outputSize);
        });
      }
    }, {
      key: "transpose",
      value: function transpose(ast, formulaAddress) {
        return this.runMatrixFunction(ast.args, formulaAddress, this.metadata('TRANSPOSE'), function (matrix) {
          if (!matrix.hasOnlyNumbers()) {
            return new _Cell.CellError(_Cell.ErrorType.VALUE, _errorMessage.ErrorMessage.NumberRange);
          }
  
          var input = matrix.rawNumbers();
          var inputSize = matrix.size;
          var result = [];
  
          for (var i = 0; i < inputSize.width; ++i) {
            result[i] = [];
  
            for (var j = 0; j < inputSize.height; ++j) {
              result[i][j] = input[j][i];
            }
          }
  
          return _SimpleRangeValue.SimpleRangeValue.onlyNumbersDataWithoutRange(result, (0, _Matrix.matrixSizeForTranspose)(inputSize));
        });
      }
    }]);
  
    return MatrixPlugin;
  }(_FunctionPlugin2.FunctionPlugin);
  
  exports.MatrixPlugin = MatrixPlugin;
  MatrixPlugin.implementedFunctions = {
    'MMULT': {
      method: 'mmult',
      parameters: [{
        argumentType: _FunctionPlugin2.ArgumentTypes.RANGE
      }, {
        argumentType: _FunctionPlugin2.ArgumentTypes.RANGE
      }]
    },
    'TRANSPOSE': {
      method: 'transpose',
      parameters: [{
        argumentType: _FunctionPlugin2.ArgumentTypes.RANGE
      }]
    },
    'MAXPOOL': {
      method: 'maxpool',
      parameters: [{
        argumentType: _FunctionPlugin2.ArgumentTypes.RANGE
      }, {
        argumentType: _FunctionPlugin2.ArgumentTypes.NUMBER
      }, {
        argumentType: _FunctionPlugin2.ArgumentTypes.NUMBER,
        optionalArg: true
      }]
    },
    'MEDIANPOOL': {
      method: 'medianpool',
      parameters: [{
        argumentType: _FunctionPlugin2.ArgumentTypes.RANGE
      }, {
        argumentType: _FunctionPlugin2.ArgumentTypes.NUMBER
      }, {
        argumentType: _FunctionPlugin2.ArgumentTypes.NUMBER,
        optionalArg: true
      }]
    }
  };