"use strict";
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
Object.defineProperty(exports, "__esModule", { value: true });
exports.glslTanh = exports.glslTan = exports.glslSqrt = exports.glslSigmoid = exports.glslRelu = exports.glslSin = exports.glslNot = exports.glslNeg = exports.glslLog = exports.glslIdentity = exports.glslFloor = exports.glslExp = exports.glslCos = exports.glslCeil = exports.glslAtan = exports.glslAsin = exports.glslAcos = exports.glslAbs = exports.WebGLUnaryOp = void 0;
const unary_op_1 = require("../../../ops/unary-op");
const glsl_definitions_1 = require("../glsl-definitions");
const glsl_source_1 = require("../glsl-source");
class WebGLUnaryOp extends unary_op_1.UnaryOp {
    constructor(typeConstraint, glslFunc) {
        super(typeConstraint);
        this.typeConstraint = typeConstraint;
        this.glslFunc = glslFunc;
    }
    run(inferenceHandler, inputs) {
        return inferenceHandler.run(this, inputs);
    }
    createProgramInfo(handler, inputs) {
        const outputShape = inputs[0].dims.slice();
        const inputLayout = handler.session.pack ?
            handler.getOrCreateTextureLayout(inputs[0], 4, true, inputs[0].dims, true) :
            handler.getOrCreateTextureLayout(inputs[0]);
        const outputLayout = handler.session.pack ?
            handler.createTextureLayoutFromShape(outputShape, 4, outputShape, { isPacked: true, reverseWH: true }) :
            handler.createTextureLayoutFromShape(outputShape);
        const glsl = glsl_source_1.getGlsl(handler.session.backend.glContext.version);
        const shaderSource = `
      ${this.glslFunc.body}
      void main() {
        vec4 v = ${glsl.texture2D}(A, TexCoords);
        v = ${this.glslFunc.name}(v);
        ${glsl.output} = v;
      }
      `;
        if (handler.session.pack) {
            return {
                inputLayouts: [inputLayout],
                outputLayout,
                samplers: ['A'],
                shaderSource,
                hasMain: true,
                expectPackedInputs: true,
                expectPackedOutputs: true
            };
        }
        else {
            return { inputLayouts: [inputLayout], outputLayout, samplers: ['A'], shaderSource, hasMain: true };
        }
    }
    createRunData(handler, programInfo, inputs) {
        const inputTD = handler.session.pack ?
            handler.getOrCreateTextureData(inputs[0], handler.getOrCreateTextureLayout(inputs[0], 1, false, [], true)) :
            handler.getOrCreateTextureData(inputs[0]);
        return {
            inputTextureDatas: [inputTD],
            outputTextureData: handler.createTextureDataFromLayout(programInfo.outputLayout, inputTD.tensor.type),
            uniformData: {}
        };
    }
}
exports.WebGLUnaryOp = WebGLUnaryOp;
function glslAbs() {
    return glslBuiltinUnary('abs');
}
exports.glslAbs = glslAbs;
function glslAcos() {
    return glslBuiltinUnary('acos');
}
exports.glslAcos = glslAcos;
function glslAsin() {
    return glslBuiltinUnary('asin');
}
exports.glslAsin = glslAsin;
function glslAtan() {
    return glslBuiltinUnary('atan');
}
exports.glslAtan = glslAtan;
function glslCeil() {
    return glslBuiltinUnary('ceil');
}
exports.glslCeil = glslCeil;
function glslCos() {
    return glslBuiltinUnary('cos');
}
exports.glslCos = glslCos;
function glslExp() {
    return glslBuiltinUnary('exp');
}
exports.glslExp = glslExp;
function glslFloor() {
    return glslBuiltinUnary('floor');
}
exports.glslFloor = glslFloor;
function glslIdentity() {
    const name = 'indentity_';
    const body = `
  float ${name}(float a) {
    return a;
  }
  vec4 ${name}(vec4 v) {
    return v;
  }
  `;
    return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
}
exports.glslIdentity = glslIdentity;
function glslLog() {
    return glslBuiltinUnary('log');
}
exports.glslLog = glslLog;
function glslNeg() {
    const name = 'neg_';
    const body = `
  float ${name}(float a) {
    return -a;
  }
  vec4 ${name}(vec4 v) {
    return -v;
  }
  `;
    return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
}
exports.glslNeg = glslNeg;
function glslNot() {
    const name = 'not_';
    const body = `
  float ${name}(float a) {
    return float( ! bool(a) );
  }
  bool ${name}(bool a) {
    return !a;
  }
  vec4 ${name}(vec4 v) {
    return vec4(!bool(v.x), !bool(v.y), !bool(v.z), !bool(v.w));
  }
  bvec4 ${name}(bvec4 v) {
    return bvec4(!v.x, !v.y, !v.z, !v.w);
  }
  `;
    return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
}
exports.glslNot = glslNot;
function glslSin() {
    return glslBuiltinUnary('sin');
}
exports.glslSin = glslSin;
function glslRelu() {
    const name = 'relu_';
    const body = `
  float ${name}(float a) {
    return max( a, 0.0 );
  }
  vec4 ${name}(vec4 v) {
    return max( v, 0.0 );
  }
  `;
    return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
}
exports.glslRelu = glslRelu;
function glslSigmoid() {
    const name = 'sigmoid_';
    const body = `
  float ${name}(float a) {
    return 1.0 / (1.0 + exp(-a));
  }
  vec4 ${name}(vec4 v) {
    return 1.0 / (1.0 + exp(-v));
  }
  `;
    return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
}
exports.glslSigmoid = glslSigmoid;
function glslSqrt() {
    return glslBuiltinUnary('sqrt');
}
exports.glslSqrt = glslSqrt;
function glslTan() {
    return glslBuiltinUnary('tan');
}
exports.glslTan = glslTan;
function glslTanh() {
    const name = 'tanh_';
    const body = `
  float ${name}(float a) {
    a = clamp(a, -10., 10.);
    a = exp(2.*a);
    return (a - 1.) / (a + 1.);
  }
  vec4 ${name}(vec4 v) {
    v = clamp(v, -10., 10.);
    v = exp(2.*v);
    return (v - 1.) / (v + 1.);
  }
  `;
    return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
}
exports.glslTanh = glslTanh;
function glslBuiltinUnary(fname) {
    const name = `${fname}_`;
    const body = `
  float ${name}(float a) {
    return ${fname}(a);
  }
  vec4 ${name}(vec4 v) {
    return ${fname}(v);
  }
  `;
    return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
}
//# sourceMappingURL=unary-op.js.map