(function (global, factory) {
  if (typeof define === "function" && define.amd) {
    define(["exports", "../core/TempNode.js", "../core/ExpressionNode.js", "../utils/JoinNode.js", "../utils/SplitNode.js", "./OperatorNode.js"], factory);
  } else if (typeof exports !== "undefined") {
    factory(exports, require("../core/TempNode.js"), require("../core/ExpressionNode.js"), require("../utils/JoinNode.js"), require("../utils/SplitNode.js"), require("./OperatorNode.js"));
  } else {
    var mod = {
      exports: {}
    };
    factory(mod.exports, global.TempNode, global.ExpressionNode, global.JoinNode, global.SplitNode, global.OperatorNode);
    global.MathNode = mod.exports;
  }
})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports, _TempNode2, _ExpressionNode, _JoinNode, _SplitNode, _OperatorNode) {
  "use strict";

  Object.defineProperty(_exports, "__esModule", {
    value: true
  });
  _exports.default = void 0;
  _TempNode2 = _interopRequireDefault(_TempNode2);
  _ExpressionNode = _interopRequireDefault(_ExpressionNode);
  _JoinNode = _interopRequireDefault(_JoinNode);
  _SplitNode = _interopRequireDefault(_SplitNode);
  _OperatorNode = _interopRequireDefault(_OperatorNode);

  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

  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); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }

  function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } Object.defineProperty(subClass, "prototype", { value: Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }), writable: false }); 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; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } 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); }

  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

  var MathNode = /*#__PURE__*/function (_TempNode) {
    _inherits(MathNode, _TempNode);

    var _super = _createSuper(MathNode);

    // 1 input
    // 2 inputs
    // 3 inputs
    function MathNode(method, aNode) {
      var _this;

      var bNode = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
      var cNode = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;

      _classCallCheck(this, MathNode);

      _this = _super.call(this);
      _this.method = method;
      _this.aNode = aNode;
      _this.bNode = bNode;
      _this.cNode = cNode;
      return _this;
    }

    _createClass(MathNode, [{
      key: "getInputType",
      value: function getInputType(builder) {
        var aType = this.aNode.getNodeType(builder);
        var bType = this.bNode ? this.bNode.getNodeType(builder) : null;
        var cType = this.cNode ? this.cNode.getNodeType(builder) : null;
        var aLen = builder.getTypeLength(aType);
        var bLen = builder.getTypeLength(bType);
        var cLen = builder.getTypeLength(cType);

        if (aLen > bLen && aLen > cLen) {
          return aType;
        } else if (bLen > cLen) {
          return bType;
        } else if (cLen > aLen) {
          return cType;
        }

        return aType;
      }
    }, {
      key: "getNodeType",
      value: function getNodeType(builder) {
        var method = this.method;

        if (method === MathNode.LENGTH || method === MathNode.DISTANCE || method === MathNode.DOT) {
          return 'float';
        } else if (method === MathNode.CROSS) {
          return 'vec3';
        } else {
          return this.getInputType(builder);
        }
      }
    }, {
      key: "generate",
      value: function generate(builder, output) {
        var method = this.method;
        var type = this.getNodeType(builder);
        var inputType = this.getInputType(builder);
        var a = this.aNode;
        var b = this.bNode;
        var c = this.cNode;

        if (builder.renderer.isWebGLRenderer === true && (method === MathNode.DFDX || method === MathNode.DFDY) && output === 'vec3') {
          // Workaround for Adreno 3XX dFd*( vec3 ) bug. See #9988
          return new _JoinNode.default([new MathNode(method, new _SplitNode.default(a, 'x')), new MathNode(method, new _SplitNode.default(a, 'y')), new MathNode(method, new _SplitNode.default(a, 'z'))]).build(builder);
        } else if (method === MathNode.TRANSFORM_DIRECTION) {
          // dir can be either a direction vector or a normal vector
          // upper-left 3x3 of matrix is assumed to be orthogonal
          var tA = a;
          var tB = b;

          if (builder.isMatrix(tA.getNodeType(builder))) {
            tB = new _ExpressionNode.default("".concat(builder.getType('vec4'), "( ").concat(tB.build(builder, 'vec3'), ", 0.0 )"), 'vec4');
          } else {
            tA = new _ExpressionNode.default("".concat(builder.getType('vec4'), "( ").concat(tA.build(builder, 'vec3'), ", 0.0 )"), 'vec4');
          }

          var mulNode = new _SplitNode.default(new _OperatorNode.default('*', tA, tB), 'xyz');
          return new MathNode(MathNode.NORMALIZE, mulNode).build(builder);
        } else if (method === MathNode.SATURATE) {
          return "clamp( ".concat(a.build(builder, inputType), ", 0.0, 1.0 )");
        } else if (method === MathNode.NEGATE) {
          return '( -' + a.build(builder, inputType) + ' )';
        } else if (method === MathNode.INVERT) {
          return '( 1.0 - ' + a.build(builder, inputType) + ' )';
        } else {
          var params = [];

          if (method === MathNode.CROSS) {
            params.push(a.build(builder, type), b.build(builder, type));
          } else if (method === MathNode.STEP) {
            params.push(b.build(builder, builder.getTypeLength(a.getNodeType(builder)) === 1 ? 'float' : inputType), b.build(builder, inputType));
          } else if (method === MathNode.MIN || method === MathNode.MAX || method === MathNode.MOD) {
            params.push(a.build(builder, inputType), b.build(builder, builder.getTypeLength(b.getNodeType(builder)) === 1 ? 'float' : inputType));
          } else if (method === MathNode.REFRACT) {
            params.push(a.build(builder, inputType), b.build(builder, inputType), c.build(builder, 'float'));
          } else if (method === MathNode.MIX) {
            params.push(a.build(builder, inputType), b.build(builder, inputType), c.build(builder, builder.getTypeLength(c.getNodeType(builder)) === 1 ? 'float' : inputType));
          } else {
            params.push(a.build(builder, inputType));

            if (c !== null) {
              params.push(b.build(builder, inputType), c.build(builder, inputType));
            } else if (b !== null) {
              params.push(b.build(builder, inputType));
            }
          }

          return "".concat(builder.getMethod(method), "( ").concat(params.join(', '), " )");
        }
      }
    }]);

    return MathNode;
  }(_TempNode2.default);

  _defineProperty(MathNode, "RAD", 'radians');

  _defineProperty(MathNode, "DEG", 'degrees');

  _defineProperty(MathNode, "EXP", 'exp');

  _defineProperty(MathNode, "EXP2", 'exp2');

  _defineProperty(MathNode, "LOG", 'log');

  _defineProperty(MathNode, "LOG2", 'log2');

  _defineProperty(MathNode, "SQRT", 'sqrt');

  _defineProperty(MathNode, "INV_SQRT", 'inversesqrt');

  _defineProperty(MathNode, "FLOOR", 'floor');

  _defineProperty(MathNode, "CEIL", 'ceil');

  _defineProperty(MathNode, "NORMALIZE", 'normalize');

  _defineProperty(MathNode, "FRACT", 'fract');

  _defineProperty(MathNode, "SIN", 'sin');

  _defineProperty(MathNode, "COS", 'cos');

  _defineProperty(MathNode, "TAN", 'tan');

  _defineProperty(MathNode, "ASIN", 'asin');

  _defineProperty(MathNode, "ACOS", 'acos');

  _defineProperty(MathNode, "ATAN", 'atan');

  _defineProperty(MathNode, "ABS", 'abs');

  _defineProperty(MathNode, "SIGN", 'sign');

  _defineProperty(MathNode, "LENGTH", 'length');

  _defineProperty(MathNode, "NEGATE", 'negate');

  _defineProperty(MathNode, "INVERT", 'invert');

  _defineProperty(MathNode, "DFDX", 'dFdx');

  _defineProperty(MathNode, "DFDY", 'dFdy');

  _defineProperty(MathNode, "SATURATE", 'saturate');

  _defineProperty(MathNode, "MIN", 'min');

  _defineProperty(MathNode, "MAX", 'max');

  _defineProperty(MathNode, "MOD", 'mod');

  _defineProperty(MathNode, "STEP", 'step');

  _defineProperty(MathNode, "REFLECT", 'reflect');

  _defineProperty(MathNode, "DISTANCE", 'distance');

  _defineProperty(MathNode, "DOT", 'dot');

  _defineProperty(MathNode, "CROSS", 'cross');

  _defineProperty(MathNode, "POW", 'pow');

  _defineProperty(MathNode, "TRANSFORM_DIRECTION", 'transformDirection');

  _defineProperty(MathNode, "MIX", 'mix');

  _defineProperty(MathNode, "CLAMP", 'clamp');

  _defineProperty(MathNode, "REFRACT", 'refract');

  _defineProperty(MathNode, "SMOOTHSTEP", 'smoothstep');

  _defineProperty(MathNode, "FACEFORWARD", 'faceforward');

  var _default = MathNode;
  _exports.default = _default;
});