diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsBuiltinPrecisionTests.js | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsBuiltinPrecisionTests.js')
-rw-r--r-- | dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsBuiltinPrecisionTests.js | 5415 |
1 files changed, 5415 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsBuiltinPrecisionTests.js b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsBuiltinPrecisionTests.js new file mode 100644 index 0000000000..4dc3be70f3 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/deqp/modules/shared/glsBuiltinPrecisionTests.js @@ -0,0 +1,5415 @@ +/*------------------------------------------------------------------------- + * drawElements Quality Program OpenGL ES Utilities + * ------------------------------------------------ + * + * Copyright 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +'use strict'; +goog.provide('modules.shared.glsBuiltinPrecisionTests'); +goog.require('framework.common.tcuFloatFormat'); +goog.require('framework.common.tcuInterval'); +goog.require('framework.common.tcuMatrix'); +goog.require('framework.common.tcuMatrixUtil'); +goog.require('framework.common.tcuTestCase'); +goog.require('framework.delibs.debase.deMath'); +goog.require('framework.delibs.debase.deRandom'); +goog.require('framework.delibs.debase.deUtil'); +goog.require('framework.opengl.gluShaderProgram'); +goog.require('framework.opengl.gluShaderUtil'); +goog.require('framework.opengl.gluVarType'); +goog.require('framework.opengl.simplereference.sglrGLContext'); +goog.require('modules.shared.glsBuiltinPrecisionTestsUnitTests'); +goog.require('modules.shared.glsShaderExecUtil'); + +goog.scope(function() { + + var glsBuiltinPrecisionTests = modules.shared.glsBuiltinPrecisionTests; + var tcuTestCase = framework.common.tcuTestCase; + var gluShaderProgram = framework.opengl.gluShaderProgram; + var gluShaderUtil = framework.opengl.gluShaderUtil; + var tcuInterval = framework.common.tcuInterval; + var tcuFloatFormat = framework.common.tcuFloatFormat; + var deRandom = framework.delibs.debase.deRandom; + var glsShaderExecUtil = modules.shared.glsShaderExecUtil; + var sglrGLContext = framework.opengl.simplereference.sglrGLContext; + var deMath = framework.delibs.debase.deMath; + var deUtil = framework.delibs.debase.deUtil; + var gluVarType = framework.opengl.gluVarType; + var tcuMatrix = framework.common.tcuMatrix; + var tcuMatrixUtil = framework.common.tcuMatrixUtil; + var ref = modules.shared.glsBuiltinPrecisionTestsUnitTests.cppreference; + var referenceComparison = modules.shared.glsBuiltinPrecisionTestsUnitTests.referenceComparison; + + var DE_ASSERT = function(x) { + if (!x) + throw new Error('Assert failed'); + }; + +var setParentClass = function(child, parent) { + child.prototype = Object.create(parent.prototype); + child.prototype.constructor = child; +}; + + /** @typedef {(tcuInterval.Interval|Array<tcuInterval.Interval>|tcuMatrix.Matrix)} */ + glsBuiltinPrecisionTests.Intervals; + + /** @typedef {(number|Array<number>|tcuMatrix.Matrix)} */ + glsBuiltinPrecisionTests.Value; + + /** @typedef {(string)} */ + glsBuiltinPrecisionTests.Typename; + + //Change to true for WebGL unit testing + var enableUnittests = false; + + /** + * @param {number} value + * @return {boolean} + */ + glsBuiltinPrecisionTests.isFloat = function(value) { + return value % 1 !== 0; + }; + + /** + * @constructor + * @param {string} R + * @param {string=} P0 + * @param {string=} P1 + * @param {string=} P2 + * @param {string=} P3 + */ + glsBuiltinPrecisionTests.Signature = function(R, P0, P1, P2, P3) { + this.Ret = R; + this.Arg0 = P0 === undefined ? 'void' : P0; + this.Arg1 = P1 === undefined ? 'void' : P1; + this.Arg2 = P2 === undefined ? 'void' : P2; + this.Arg3 = P3 === undefined ? 'void' : P3; + }; + + /** @typedef {Array<glsBuiltinPrecisionTests.FuncBase>} */ + glsBuiltinPrecisionTests.FuncSet; + + /** + * @constructor + * @template T + * @param {T} A0 + * @param {T} A1 + * @param {T} A2 + * @param {T} A3 + */ + glsBuiltinPrecisionTests.Tuple4 = function(A0, A1, A2, A3) { + this.a = A0; + this.b = A1; + this.c = A2; + this.d = A3; + }; + + /** + * @typedef {!glsBuiltinPrecisionTests.Tuple4<string>} + */ + glsBuiltinPrecisionTests.ParamNames; + + /** + * Returns true for all other types except Void + * @param {string} typename + */ + glsBuiltinPrecisionTests.isTypeValid = function(typename) { + if (typename === 'void') + return false; + return true; + }; + + /** + * Returns true for all other types except Void + * @param {*} In + * @return {number} + */ + glsBuiltinPrecisionTests.numInputs = function(In) { + return (!glsBuiltinPrecisionTests.isTypeValid(In.In0) ? 0 : + !glsBuiltinPrecisionTests.isTypeValid(In.In1) ? 1 : + !glsBuiltinPrecisionTests.isTypeValid(In.In2) ? 2 : + !glsBuiltinPrecisionTests.isTypeValid(In.In3) ? 3 : + 4); + }; + + /** + * Returns true for all other types except Void + * @param {*} Out + * @return {number} + */ + glsBuiltinPrecisionTests.numOutputs = function(Out) { + return (!glsBuiltinPrecisionTests.isTypeValid(Out.Out0) ? 0 : + !glsBuiltinPrecisionTests.isTypeValid(Out.Out1) ? 1 : + 2); + }; + + /** + * @constructor + * @param {glsBuiltinPrecisionTests.Typename=} In0_ + * @param {glsBuiltinPrecisionTests.Typename=} In1_ + * @param {glsBuiltinPrecisionTests.Typename=} In2_ + * @param {glsBuiltinPrecisionTests.Typename=} In3_ + */ + glsBuiltinPrecisionTests.InTypes = function(In0_, In1_, In2_, In3_) { + this.In0 = In0_ === undefined ? 'void' : In0_; + this.In1 = In1_ === undefined ? 'void' : In1_; + this.In2 = In2_ === undefined ? 'void' : In2_; + this.In3 = In3_ === undefined ? 'void' : In3_; + }; + + /** + * @constructor + * @param {glsBuiltinPrecisionTests.Typename=} Out0_ + * @param {glsBuiltinPrecisionTests.Typename=} Out1_ + */ + glsBuiltinPrecisionTests.OutTypes = function(Out0_, Out1_) { + this.Out0 = Out0_ === undefined ? 'void' : Out0_; + this.Out1 = Out1_ === undefined ? 'void' : Out1_; + }; + + /** + * @constructor + */ + glsBuiltinPrecisionTests.Environment = function() { + /** @type {Object} */ this.m_map = {}; + }; + + /** + * @param {glsBuiltinPrecisionTests.Variable} variable + * @param {*} value + */ + glsBuiltinPrecisionTests.Environment.prototype.bind = function(variable, value) { + this.m_map[variable.getName()] = value; + }; + + /** + * @param {*} variable + * @return {glsBuiltinPrecisionTests.Intervals} + */ + glsBuiltinPrecisionTests.Environment.prototype.lookup = function(variable) { + if (variable instanceof glsBuiltinPrecisionTests.Variable) + return this.m_map[variable.getName()]; + + throw new Error('Invalid lookup input: ' + variable); + }; + + /** + * @constructor + * @param {tcuFloatFormat.FloatFormat} format_ + * @param {gluShaderUtil.precision} floatPrecision_ + * @param {glsBuiltinPrecisionTests.Environment} env_ + * @param {number=} callDepth_ + */ + glsBuiltinPrecisionTests.EvalContext = function(format_, floatPrecision_, env_, callDepth_) { + this.format = format_; + this.floatPrecision = floatPrecision_; + this.env = env_; + this.callDepth = callDepth_ === undefined ? 0 : callDepth_; + }; + + /** + * @param {string} typename typename + * @param {tcuFloatFormat.FloatFormat} fmt + * @param {glsBuiltinPrecisionTests.Intervals} value + * @return {glsBuiltinPrecisionTests.Intervals} + */ + glsBuiltinPrecisionTests.convert = function(typename, fmt, value) { + var traits = glsBuiltinPrecisionTests.Traits.traitsFactory(typename); + + if (value instanceof Array) { + var ret = []; + for (var i = 0; i < value.length; i++) + ret.push(traits.doConvert(fmt, value[i])); + return ret; + } + + if (value instanceof tcuMatrix.Matrix) { + var ret = new tcuMatrix.Matrix(value.rows, value.cols); + for (var i = 0; i < value.rows; i++) + for (var j = 0; j < value.cols; j++) + ret.set(i, j, traits.doConvert(fmt, value.get(i, j))); + return ret; + } + + return traits.doConvert(fmt, value); + }; + + /** + * Returns true if every element of `ival` contains the corresponding element of `value`. + * @param {string} typename typename + * @param {glsBuiltinPrecisionTests.Intervals} ival + * @param {*} value + * @return {boolean} + */ + glsBuiltinPrecisionTests.contains = function(typename, ival, value) { + var traits = glsBuiltinPrecisionTests.Traits.traitsFactory(typename); + var contains = true; + + if (value instanceof Array) { + for (var i = 0; i < value.length; i++) + contains &= traits.doContains(ival[i], value[i]); + return contains; + } + + if (value instanceof tcuMatrix.Matrix) { + for (var i = 0; i < value.rows; i++) + for (var j = 0; j < value.cols; j++) + contains &= traits.doContains(ival.get(i, j), value.get(i, j)); + return contains; + } + + return traits.doContains(ival, value); + }; + + /** + * @param {string} typename typename + * @param {glsBuiltinPrecisionTests.Intervals} ival0 + * @param {glsBuiltinPrecisionTests.Intervals} ival1 + * @return {glsBuiltinPrecisionTests.Intervals} + */ + glsBuiltinPrecisionTests.union = function(typename, ival0, ival1) { + var traits = glsBuiltinPrecisionTests.Traits.traitsFactory(typename); + + if (ival0 instanceof Array) { + var ret = []; + for (var i = 0; i < ival0.length; i++) + ret.push(traits.doUnion(ival0[i], ival1[i])); + return ret; + } + + if (ival0 instanceof tcuMatrix.Matrix) { + var ret = new tcuMatrix.Matrix(ival0.rows, ival0.cols); + for (var i = 0; i < ival0.rows; i++) + for (var j = 0; j < ival0.cols; j++) + ret.set(i, j, traits.doUnion(ival0.get(i, j), ival1.get(i, j))); + return ret; + } + + return traits.doUnion(ival0, ival1); + }; + + /** + * @param {string} typename + * @constructor + */ + glsBuiltinPrecisionTests.Traits = function(typename) { + this.typename = typename; + this.rows = 1; + this.cols = 1; + }; + + glsBuiltinPrecisionTests.Traits.prototype.isScalar = function() { + return this.rows == 1 && this.cols == 1; + }; + + glsBuiltinPrecisionTests.Traits.prototype.isVector = function() { + return this.rows > 0 && this.cols == 1; + }; + + glsBuiltinPrecisionTests.Traits.prototype.isMatrix = function() { + return this.rows > 0 && this.cols > 1; + }; + + /** + * @param {string=} typename + */ + glsBuiltinPrecisionTests.Traits.traitsFactory = function(typename) { + switch (typename) { + case 'boolean' : return new glsBuiltinPrecisionTests.TraitsBool(); + case 'float' : case 'vec2' : case 'vec3' : case 'vec4' : + case 'mat2' : case 'mat2x3' : case 'mat2x4' : + case 'mat3x2' : case 'mat3' : case 'mat3x4' : + case 'mat4x2' : case 'mat4x3' : case 'mat4' : + return new glsBuiltinPrecisionTests.TraitsFloat(typename); + case 'int' : return new glsBuiltinPrecisionTests.TraitsInt(); + case 'void' : return new glsBuiltinPrecisionTests.TraitsVoid(); + default: + throw new Error('Invalid typename:' + typename); + } + }; + + glsBuiltinPrecisionTests.round = function(typename, fmt, value) { + var traits = glsBuiltinPrecisionTests.Traits.traitsFactory(typename); + + if (value instanceof Array) { + var ret = []; + for (var i = 0; i < value.length; i++) + ret.push(traits.doRound(fmt, value[i])); + return ret; + } + + if (value instanceof tcuMatrix.Matrix) { + var ret = new tcuMatrix.Matrix(value.rows, value.cols); + for (var i = 0; i < value.rows; i++) + for (var j = 0; j < value.cols; j++) + ret.set(i, j, traits.doRound(fmt, value.get(i, j))); + return ret; + } + + return traits.doRound(fmt, value); + }; + + /** + * cast the input typed array to correct type + * @param {string} typename + * @param {goog.TypedArray} input + * @return {goog.TypedArray} + */ + glsBuiltinPrecisionTests.cast = function(typename, input) { + var traits = glsBuiltinPrecisionTests.Traits.traitsFactory(typename); + return traits.doCast(input); + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.Traits} + */ + glsBuiltinPrecisionTests.TraitsVoid = function() { + glsBuiltinPrecisionTests.Traits.call(this, 'void'); + }; + + setParentClass(glsBuiltinPrecisionTests.TraitsVoid, glsBuiltinPrecisionTests.Traits); + + /** + * @param {*} value + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.TraitsVoid.prototype.doMakeIVal = function(value) { + return new tcuInterval.Interval(); + }; + + /** + * @param {*} value1 + * @param {*} value2 + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.TraitsVoid.prototype.doUnion = function(value1, value2) { + return new tcuInterval.Interval(); + }; + + /** + * @param {*} value + * @return {boolean} + */ + glsBuiltinPrecisionTests.TraitsVoid.prototype.doContains = function(value) { + return true; + }; + + /** + * @param {tcuFloatFormat.FloatFormat} fmt + * @param {tcuInterval.Interval} ival + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.TraitsVoid.prototype.doConvert = function(fmt, ival) { + return new tcuInterval.Interval(); + }; + + /** + * @param {tcuFloatFormat.FloatFormat} fmt + * @param {*} ival + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.TraitsVoid.prototype.doRound = function(fmt, ival) { + return new tcuInterval.Interval(); + }; + + /** + * @param {tcuFloatFormat.FloatFormat} fmt + * @param {*} ival + */ + glsBuiltinPrecisionTests.TraitsVoid.prototype.doPrintIVal = function(fmt, ival) { + return '()'; + }; + + /** + * @param {tcuFloatFormat.FloatFormat} fmt + * @param {*} value + */ + glsBuiltinPrecisionTests.TraitsVoid.prototype.doPrintValue = function(fmt, value) { + return '()'; + }; + + glsBuiltinPrecisionTests.dataTypeSize = function(detailedType) { + var size = [1, 1]; + switch (detailedType) { + case 'vec2' : size[0] = 2; break; + case 'vec3' : size[0] = 3; break; + case 'vec4' : size[0] = 4; break; + case 'mat2' : size = [2 , 2]; break; + case 'mat2x3' : size = [3 , 2]; break; + case 'mat2x4' : size = [4 , 2]; break; + + case 'mat3x2' : size = [2 , 3]; break; + case 'mat3' : size = [3 , 3]; break; + case 'mat3x4' : size = [4 , 3]; break; + + case 'mat4x2' : size = [2 , 4]; break; + case 'mat4x3' : size = [3 , 4]; break; + case 'mat4' : size = [4 , 4]; break; + } + return size; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.Traits} + * @param {string} typename + * @param {string=} detailedType + */ + glsBuiltinPrecisionTests.ScalarTraits = function(typename, detailedType) { + glsBuiltinPrecisionTests.Traits.call(this, typename); + var size = glsBuiltinPrecisionTests.dataTypeSize(detailedType); + this.rows = size[0]; + this.cols = size[1]; + + /** type{tcuInterval.Interval} */ this.iVal; + }; + + setParentClass(glsBuiltinPrecisionTests.ScalarTraits, glsBuiltinPrecisionTests.Traits); + + glsBuiltinPrecisionTests.ScalarTraits.prototype = Object.create(glsBuiltinPrecisionTests.Traits.prototype); + glsBuiltinPrecisionTests.ScalarTraits.prototype.constructor = glsBuiltinPrecisionTests.ScalarTraits; + + /** + * @param {*} value + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.ScalarTraits.prototype.doMakeIVal = function(value) { + // Thankfully all scalar types have a well-defined conversion to `double`, + // hence Interval can represent their ranges without problems. + return new tcuInterval.Interval(/** @type {number} */ (value)); + }; + + /** + * @param {tcuInterval.Interval} a + * @param {tcuInterval.Interval} b + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.ScalarTraits.prototype.doUnion = function(a, b) { + return a.operatorOrBinary(b); + }; + + /** + * @param {tcuInterval.Interval} a + * @param {number} value + * @return {boolean} + */ + glsBuiltinPrecisionTests.ScalarTraits.prototype.doContains = function(a, value) { + return a.contains(new tcuInterval.Interval(value)); + }; + + /** + * @param {tcuFloatFormat.FloatFormat} fmt + * @param {tcuInterval.Interval} ival + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.ScalarTraits.prototype.doConvert = function(fmt, ival) { + return fmt.convert(ival); + }; + + /** + * @param {tcuFloatFormat.FloatFormat} fmt + * @param {number} value + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.ScalarTraits.prototype.doRound = function(fmt, value) { + return fmt.roundOut(new tcuInterval.Interval(value), false);//TODO cast to double + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.ScalarTraits} + * @param {string} detailedType + */ + glsBuiltinPrecisionTests.TraitsFloat = function(detailedType) { + glsBuiltinPrecisionTests.ScalarTraits.call(this, 'float', detailedType); + }; + + glsBuiltinPrecisionTests.TraitsFloat.prototype = Object.create(glsBuiltinPrecisionTests.ScalarTraits.prototype); + glsBuiltinPrecisionTests.TraitsFloat.prototype.constructor = glsBuiltinPrecisionTests.TraitsFloat; + + /** + * @param {tcuFloatFormat.FloatFormat} fmt + * @param {tcuInterval.Interval} ival + */ + glsBuiltinPrecisionTests.TraitsFloat.prototype.doPrintIVal = function(fmt, ival) { + return fmt.intervalToHex(ival); + }; + + /** + * @param {goog.TypedArray} input + * @return {goog.TypedArray} + */ + glsBuiltinPrecisionTests.TraitsFloat.prototype.doCast = function(input) { + return new Float32Array(input.buffer); + }; + + /** + * @param {tcuFloatFormat.FloatFormat} fmt + * @param {number} value + */ + glsBuiltinPrecisionTests.TraitsFloat.prototype.doPrintValue = function(fmt, value) { + return fmt.floatToHex(value); + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.ScalarTraits} + */ + glsBuiltinPrecisionTests.TraitsBool = function() { + glsBuiltinPrecisionTests.ScalarTraits.call(this, 'boolean'); + }; + + glsBuiltinPrecisionTests.TraitsBool.prototype = Object.create(glsBuiltinPrecisionTests.ScalarTraits.prototype); + glsBuiltinPrecisionTests.TraitsBool.prototype.constructor = glsBuiltinPrecisionTests.TraitsBool; + + /** + * @param {tcuFloatFormat.FloatFormat} fmt + * @param {tcuInterval.Interval} ival + */ + glsBuiltinPrecisionTests.TraitsBool.prototype.doPrintIVal = function(fmt, ival) { + /** type{string} */ var os = '{'; + var ifalse = new tcuInterval.Interval(0); + var itrue = new tcuInterval.Interval(1); + if (ival.contains(ifalse)) + os += 'false'; + if (ival.contains(ifalse) && ival.contains(itrue)) + os += ', '; + if (ival.contains(itrue)) + os += 'true'; + os += '}'; + return os; + }; + + /** + * @param {tcuFloatFormat.FloatFormat} fmt + * @param {boolean} value + */ + glsBuiltinPrecisionTests.TraitsBool.prototype.doPrintValue = function(fmt, value) { + return value ? 'true' : 'false'; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.ScalarTraits} + */ + glsBuiltinPrecisionTests.TraitsInt = function() { + glsBuiltinPrecisionTests.ScalarTraits.call(this, 'int'); + }; + + glsBuiltinPrecisionTests.TraitsInt.prototype = Object.create(glsBuiltinPrecisionTests.ScalarTraits.prototype); + glsBuiltinPrecisionTests.TraitsInt.prototype.constructor = glsBuiltinPrecisionTests.TraitsInt; + + /** + * @param {tcuFloatFormat.FloatFormat} fmt + * @param {tcuInterval.Interval} ival + */ + glsBuiltinPrecisionTests.TraitsInt.prototype.doPrintIVal = function(fmt, ival) { + return '[' + (ival.lo()) + ', ' + (ival.hi()) + ']'; + }; + + /** + * @param {tcuFloatFormat.FloatFormat} fmt + * @param {number} value + */ + glsBuiltinPrecisionTests.TraitsInt.prototype.doPrintValue = function(fmt, value) { + return value.toString(10); + }; + + /** + * @constructor + */ + glsBuiltinPrecisionTests.Statement = function() { + + }; + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + */ + glsBuiltinPrecisionTests.Statement.prototype.execute = function(ctx) { + this.doExecute(ctx); + }; + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.Statement.prototype.print = function() { + return this.doPrint(); + }; + + glsBuiltinPrecisionTests.Statement.prototype.toString = function() { + return this.print(); + }; + + /** + * Output the functions that this expression refers to + * @param {glsBuiltinPrecisionTests.FuncSet} dst + * + */ + glsBuiltinPrecisionTests.Statement.prototype.getUsedFuncs = function(dst) { + this.doGetUsedFuncs(dst); + }; + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + */ + glsBuiltinPrecisionTests.Statement.prototype.doExecute = function(ctx) { + throw new Error('Virtual function. Please override.'); + }; + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.Statement.prototype.doPrint = function() { + throw new Error('Virtual function. Please override.'); + }; + + /** + * Output the functions that this expression refers to + * @param {glsBuiltinPrecisionTests.FuncSet} dst + * + */ + glsBuiltinPrecisionTests.Statement.prototype.doGetUsedFuncs = function(dst) { + throw new Error('Virtual function. Please override.'); + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.Statement} + * @param {glsBuiltinPrecisionTests.Variable} variable + * @param {glsBuiltinPrecisionTests.Expr} value + * @param {boolean} isDeclaration + */ + glsBuiltinPrecisionTests.VariableStatement = function(variable, value, isDeclaration) { + this.m_variable = variable; + this.m_value = value; + this.m_isDeclaration = isDeclaration; + + }; + + setParentClass(glsBuiltinPrecisionTests.VariableStatement, glsBuiltinPrecisionTests.Statement); + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + */ + glsBuiltinPrecisionTests.VariableStatement.prototype.doExecute = function(ctx) { + ctx.env.bind(this.m_variable, this.m_value.evaluate(ctx)); + }; + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.VariableStatement.prototype.doPrint = function() { + var v = this.m_variable; + var os = ''; + if (this.m_isDeclaration) + os += gluVarType.declareVariable(gluVarType.getVarTypeOf(v.typename), + v.getName()); + else + os += v.getName(); + + os += ' = ' + this.m_value.printExpr() + ';\n'; + + return os; + }; + + /** + * Output the functions that this expression refers to + * @param {glsBuiltinPrecisionTests.FuncSet} dst + * + */ + glsBuiltinPrecisionTests.VariableStatement.prototype.doGetUsedFuncs = function(dst) { + this.m_value.getUsedFuncs(dst); + }; + + /** + * @param {glsBuiltinPrecisionTests.Variable} variable + * @param {glsBuiltinPrecisionTests.Expr} definiens + * @return {glsBuiltinPrecisionTests.VariableStatement} + */ + glsBuiltinPrecisionTests.variableDeclaration = function(variable, definiens) { + return new glsBuiltinPrecisionTests.VariableStatement(variable, definiens, true); + }; + + /** + * @param {string} typename + * @param {string} name + * @param {glsBuiltinPrecisionTests.ExpandContext} ctx + * @param {glsBuiltinPrecisionTests.Expr} expr + * @return {glsBuiltinPrecisionTests.Variable} + */ + glsBuiltinPrecisionTests.bindExpression = function(typename, name, ctx, expr) { + var variable = ctx.genSym(typename, name); + ctx.addStatement(glsBuiltinPrecisionTests.variableDeclaration(variable, expr)); + return variable; + }; + + /** + * Common base class for all expressions regardless of their type. + * @constructor + */ + glsBuiltinPrecisionTests.ExprBase = function() {}; + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.ExprBase.prototype.printExpr = function() { + return this.doPrintExpr(); + }; + + glsBuiltinPrecisionTests.ExprBase.prototype.toString = function() { + return this.printExpr(); + }; + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.ExprBase.prototype.doPrintExpr = function() { + throw new Error('Virtual function. Please override.'); + }; + + /** + * Output the functions that this expression refers to + * @param {glsBuiltinPrecisionTests.FuncSet} dst + * + */ + glsBuiltinPrecisionTests.ExprBase.prototype.getUsedFuncs = function(/*FuncSet&*/ dst) { + this.doGetUsedFuncs(dst); + }; + + /** + * Output the functions that this expression refers to + * @param {glsBuiltinPrecisionTests.FuncSet} dst + * + */ + glsBuiltinPrecisionTests.ExprBase.prototype.doGetUsedFuncs = function(/*FuncSet&*/ dst) { + throw new Error('Virtual function. Please override.'); + }; + + /** + * Type-specific operations for an expression representing type typename. + * @constructor + * @extends {glsBuiltinPrecisionTests.ExprBase} + * @param {glsBuiltinPrecisionTests.Typename} typename + */ + glsBuiltinPrecisionTests.Expr = function(typename) { + glsBuiltinPrecisionTests.ExprBase.call(this); + this.typename = typename; + }; + + setParentClass(glsBuiltinPrecisionTests.Expr, glsBuiltinPrecisionTests.ExprBase); + + /** + * Type-specific operations for an expression representing type typename. + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + */ + glsBuiltinPrecisionTests.Expr.prototype.evaluate = function(ctx) { + return this.doEvaluate(ctx); + }; + + /** + * Type-specific operations for an expression representing type typename. + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + */ + glsBuiltinPrecisionTests.Expr.prototype.doEvaluate = function(ctx) { + throw new Error('Virtual function. Please override.'); + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.Expr} + * @param {glsBuiltinPrecisionTests.Typename} typename + * @param {string=} name + */ + glsBuiltinPrecisionTests.Variable = function(typename, name) { + glsBuiltinPrecisionTests.Expr.call(this, typename); + /** @type {string} */ this.m_name = name || '<undefined>'; + }; + + setParentClass(glsBuiltinPrecisionTests.Variable, glsBuiltinPrecisionTests.Expr); + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.Variable.prototype.getName = function() { + return this.m_name; + }; + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.Variable.prototype.doPrintExpr = function() { + return this.m_name; + }; + + glsBuiltinPrecisionTests.Variable.prototype.toString = function() { + return this.doPrintExpr(); + }; + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + * @return {*} + */ + glsBuiltinPrecisionTests.Variable.prototype.doEvaluate = function(ctx) { + return ctx.env.lookup(this); + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.Variable} + * @param {*=} t + */ + glsBuiltinPrecisionTests.Void = function(t) { + glsBuiltinPrecisionTests.Variable.call(this, 'void'); + }; + + setParentClass(glsBuiltinPrecisionTests.Void, glsBuiltinPrecisionTests.Variable); + + glsBuiltinPrecisionTests.Void.prototype.doEvaluate = function(ctx) { + return undefined; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.Variable} + * @param {number} value + */ + glsBuiltinPrecisionTests.Constant = function(value) { + glsBuiltinPrecisionTests.Variable.call(this, 'float'); + this.m_value = value; + }; + + setParentClass(glsBuiltinPrecisionTests.Constant, glsBuiltinPrecisionTests.Variable); + + glsBuiltinPrecisionTests.Constant.prototype.doEvaluate = function(ctx) { + return new tcuInterval.Interval(this.m_value); + }; + + /** + * @constructor + * @param {*} typename + */ + glsBuiltinPrecisionTests.DefaultSampling = function(typename) { + this.typename = typename; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.Expr} + * @param {glsBuiltinPrecisionTests.Variable} vector + * @param {number} index + */ + glsBuiltinPrecisionTests.VectorVariable = function(vector, index) { + glsBuiltinPrecisionTests.Expr.call(this, vector.typename); + this.m_vector = vector; + this.m_index = index; + }; + + setParentClass(glsBuiltinPrecisionTests.VectorVariable, glsBuiltinPrecisionTests.Expr); + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.VectorVariable.prototype.doEvaluate = function(ctx) { + var tmp = this.m_vector.doEvaluate(ctx); + return tmp[this.m_index]; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.Expr} + * @param {glsBuiltinPrecisionTests.Variable} matrix + * @param {number} row + * @param {number} col + */ + glsBuiltinPrecisionTests.MatrixVariable = function(matrix, row, col) { + glsBuiltinPrecisionTests.Expr.call(this, matrix.typename); + this.m_matrix = matrix; + this.m_row = row; + this.m_col = col; + }; + + setParentClass(glsBuiltinPrecisionTests.MatrixVariable, glsBuiltinPrecisionTests.Expr); + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.MatrixVariable.prototype.doEvaluate = function(ctx) { + var tmp = this.m_matrix.doEvaluate(ctx); + return tmp.get(this.m_row, this.m_col); + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.Expr} + * @param {glsBuiltinPrecisionTests.Typename} typename + * @param {glsBuiltinPrecisionTests.Func} func + * @param {glsBuiltinPrecisionTests.Expr=} arg0 + * @param {glsBuiltinPrecisionTests.Expr=} arg1 + * @param {glsBuiltinPrecisionTests.Expr=} arg2 + * @param {glsBuiltinPrecisionTests.Expr=} arg3 + */ + glsBuiltinPrecisionTests.Apply = function(typename, func, arg0, arg1, arg2, arg3) { + glsBuiltinPrecisionTests.Expr.call(this, typename); + this.m_func = func; + /** @type {glsBuiltinPrecisionTests.Tuple4} */ this.m_args; + if (arg0 instanceof glsBuiltinPrecisionTests.Tuple4) + this.m_args = /** @type {glsBuiltinPrecisionTests.Tuple4} */ (arg0); + else { + this.m_args = new glsBuiltinPrecisionTests.Tuple4(arg0 || new glsBuiltinPrecisionTests.Void(), + arg1 || new glsBuiltinPrecisionTests.Void(), + arg2 || new glsBuiltinPrecisionTests.Void(), + arg3 || new glsBuiltinPrecisionTests.Void()); + } + }; + + setParentClass(glsBuiltinPrecisionTests.Apply, glsBuiltinPrecisionTests.Expr); + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.Apply.prototype.doPrintExpr = function() { + var args = [this.m_args.a, this.m_args.b, this.m_args.c, this.m_args.d]; + return this.m_func.print(args); + }; + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + * @return {glsBuiltinPrecisionTests.Intervals} + */ + glsBuiltinPrecisionTests.Apply.prototype.doEvaluate = function(ctx) { + var debug = false; + + if (debug) { + glsBuiltinPrecisionTests.Apply.prototype.doEvaluate.level = glsBuiltinPrecisionTests.Apply.prototype.doEvaluate.level || 0; + var level = glsBuiltinPrecisionTests.Apply.prototype.doEvaluate.level; + glsBuiltinPrecisionTests.Apply.prototype.doEvaluate.level++; + var name = this.m_func.constructor.toString(); + name = name.replace(/[\s\S]*glsBuiltinPrecisionTests\./m, '').replace(/\.call[\s\S]*/m, ''); + if (this.m_func.getName) + name += ' ' + this.m_func.getName(); + console.log('<' + level + '> Function ' + name); + } + + var a = this.m_args.a.evaluate(ctx); + var b = this.m_args.b.evaluate(ctx); + var c = this.m_args.c.evaluate(ctx); + var d = this.m_args.d.evaluate(ctx); + var retVal = this.m_func.applyFunction(ctx, a, b, c, d); + + if (debug) { + console.log('<' + level + '> a: ' + a); + console.log('<' + level + '> b: ' + b); + console.log('<' + level + '> returning: ' + retVal); + glsBuiltinPrecisionTests.Apply.prototype.doEvaluate.level--; + } + return retVal; + }; + + /** + * @param {glsBuiltinPrecisionTests.Func} func + * @param {glsBuiltinPrecisionTests.Expr=} arg0 + * @param {glsBuiltinPrecisionTests.Expr=} arg1 + * @param {glsBuiltinPrecisionTests.Expr=} arg2 + * @param {glsBuiltinPrecisionTests.Expr=} arg3 + */ + var app = function(func, arg0, arg1, arg2, arg3) { + return new glsBuiltinPrecisionTests.Apply('float', func, arg0, arg1, arg2, arg3); + }; + + /** + * @param {glsBuiltinPrecisionTests.FuncSet} dst + */ + glsBuiltinPrecisionTests.Apply.prototype.doGetUsedFuncs = function(dst) { + this.m_func.getUsedFuncs(dst); + this.m_args.a.getUsedFuncs(dst); + this.m_args.b.getUsedFuncs(dst); + this.m_args.c.getUsedFuncs(dst); + this.m_args.d.getUsedFuncs(dst); + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.Apply} + * @param {glsBuiltinPrecisionTests.Func} func + * @param {glsBuiltinPrecisionTests.Expr=} arg0 + * @param {glsBuiltinPrecisionTests.Expr=} arg1 + * @param {glsBuiltinPrecisionTests.Expr=} arg2 + * @param {glsBuiltinPrecisionTests.Expr=} arg3 + */ + glsBuiltinPrecisionTests.ApplyScalar = function(func, arg0, arg1, arg2, arg3) { + glsBuiltinPrecisionTests.Apply.call(this, 'float', func, arg0, arg1, arg2, arg3); + }; + + setParentClass(glsBuiltinPrecisionTests.ApplyScalar, glsBuiltinPrecisionTests.Apply); + + glsBuiltinPrecisionTests.ApplyScalar.prototype.doEvaluate = function(ctx) { + var debug = false; + + if (debug) { + glsBuiltinPrecisionTests.ApplyScalar.prototype.doEvaluate.level = glsBuiltinPrecisionTests.ApplyScalar.prototype.doEvaluate.level || 0; + var level = glsBuiltinPrecisionTests.ApplyScalar.prototype.doEvaluate.level; + glsBuiltinPrecisionTests.ApplyScalar.prototype.doEvaluate.level++; + var name = this.m_func.constructor.toString(); + name = name.replace(/[\s\S]*glsBuiltinPrecisionTests\./m, '').replace(/\.call[\s\S]*/m, ''); + if (this.m_func.getName) + name += ' ' + this.m_func.getName(); + console.log('scalar<' + level + '> Function ' + name); + } + + var a = this.m_args.a.evaluate(ctx); + var b = this.m_args.b.evaluate(ctx); + var c = this.m_args.c.evaluate(ctx); + var d = this.m_args.d.evaluate(ctx); + if (a instanceof Array) { + var ret = []; + for (var i = 0; i < a.length; i++) { + var p0 = a instanceof Array ? a[i] : a; + var p1 = b instanceof Array ? b[i] : b; + var p2 = c instanceof Array ? c[i] : c; + var p3 = d instanceof Array ? d[i] : d; + ret.push(this.m_func.applyFunction(ctx, p0, p1, p2, p3)); + } + return ret; + } + + var retVal = this.m_func.applyFunction(ctx, a, b, c, d); + + if (debug) { + console.log('scalar<' + level + '> a: ' + a); + console.log('scalar<' + level + '> b: ' + b); + console.log('scalar<' + level + '> return1: ' + ret); + console.log('scalar<' + level + '> return2: ' + retVal); + glsBuiltinPrecisionTests.Apply.prototype.doEvaluate.level--; + } + + return retVal; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.Apply} + */ + glsBuiltinPrecisionTests.ApplyVar = function(typename, func, arg0, arg1, arg2, arg3) { + glsBuiltinPrecisionTests.Apply.call(this, typename, func, arg0, arg1, arg2, arg3); + }; + + setParentClass(glsBuiltinPrecisionTests.ApplyVar, glsBuiltinPrecisionTests.Apply); + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + * @return {glsBuiltinPrecisionTests.Intervals} + */ + glsBuiltinPrecisionTests.ApplyVar.prototype.doEvaluate = function(ctx) { + return this.m_func.applyFunction(ctx, + ctx.env.lookup(this.m_args.a), ctx.env.lookup(this.m_args.b), + ctx.env.lookup(this.m_args.c), ctx.env.lookup(this.m_args.d), + [this.m_args.a.getName(), this.m_args.b.getName(), + this.m_args.c.getName(), this.m_args.d.getName()]); + }; + + /** + * @constructor + */ + glsBuiltinPrecisionTests.FuncBase = function() {}; + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.FuncBase.prototype.getName = function() { + return ''; + }; + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.FuncBase.prototype.getRequiredExtension = function() { + return ''; + }; + + /** + * @param {Array<glsBuiltinPrecisionTests.ExprBase>} args + * @return {string} + */ + glsBuiltinPrecisionTests.FuncBase.prototype.print = function(args) { + return ''; + }; + + /** + * Index of output parameter, or -1 if none of the parameters is output. + * @return {number} + */ + glsBuiltinPrecisionTests.FuncBase.prototype.getOutParamIndex = function() { + return -1; + }; + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.FuncBase.prototype.printDefinition = function() { + return this.doPrintDefinition(); + }; + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.FuncBase.prototype.doPrintDefinition = function() { + throw new Error('Virtual function. Please override.'); + }; + + /** + * typedef set<const FuncBase*> FuncSet; + * @param {glsBuiltinPrecisionTests.FuncSet} dst + */ + glsBuiltinPrecisionTests.FuncBase.prototype.getUsedFuncs = function(dst) { + this.doGetUsedFuncs(dst); + }; + + /** + * @param {glsBuiltinPrecisionTests.FuncSet} dst + */ + glsBuiltinPrecisionTests.FuncBase.prototype.doGetUsedFuncs = function(dst) {}; + + /*************************************/ + /** + * \brief Function objects. + * + * Each Func object represents a GLSL function. It can be applied to interval + * arguments, and it returns the an interval that is a conservative + * approximation of the image of the GLSL function over the argument + * intervals. That is, it is given a set of possible arguments and it returns + * the set of possible values. + * + * @constructor + * @extends {glsBuiltinPrecisionTests.FuncBase} + * @param {glsBuiltinPrecisionTests.Signature} Sig_ template <typename Sig_> + */ + glsBuiltinPrecisionTests.Func = function(Sig_) { + glsBuiltinPrecisionTests.FuncBase.call(this); + this.Sig = Sig_; + this.Ret = this.Sig.Ret; + this.Arg0 = this.Sig.Arg0; + this.Arg1 = this.Sig.Arg1; + this.Arg2 = this.Sig.Arg2; + this.Arg3 = this.Sig.Arg3; + }; + + glsBuiltinPrecisionTests.Func.prototype = Object.create(glsBuiltinPrecisionTests.FuncBase.prototype); + glsBuiltinPrecisionTests.Func.prototype.constructor = glsBuiltinPrecisionTests.Func; + + /** + * @param {Array<glsBuiltinPrecisionTests.ExprBase>} args + * @return {string} + */ + glsBuiltinPrecisionTests.Func.prototype.print = function(args) { + return this.doPrint(args); + }; + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + * @param {glsBuiltinPrecisionTests.Intervals=} Iarg0 + * @param {glsBuiltinPrecisionTests.Intervals=} Iarg1 + * @param {glsBuiltinPrecisionTests.Intervals=} Iarg2 + * @param {glsBuiltinPrecisionTests.Intervals=} Iarg3 + * @return {glsBuiltinPrecisionTests.Intervals} + */ + glsBuiltinPrecisionTests.Func.prototype.applyFunction = function(ctx, Iarg0, Iarg1, Iarg2, Iarg3, variablenames) { + return this.applyArgs(ctx, new glsBuiltinPrecisionTests.Tuple4(Iarg0, Iarg1, Iarg2, Iarg3), variablenames); + }; + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + * @param {glsBuiltinPrecisionTests.Tuple4} args + * @return {glsBuiltinPrecisionTests.Intervals} + */ + glsBuiltinPrecisionTests.Func.prototype.applyArgs = function(ctx, args, variablenames) { + return this.doApply(ctx, args, variablenames); + }; + + /** + * @return {glsBuiltinPrecisionTests.ParamNames} + */ + glsBuiltinPrecisionTests.Func.prototype.getParamNames = function() { + return this.doGetParamNames(); + }; + + /** + * @param {Array<glsBuiltinPrecisionTests.ExprBase>} args + * @return {string} + */ + glsBuiltinPrecisionTests.Func.prototype.doPrint = function(args) { + /** type{string} */ var os = this.getName() + '('; + + // TODO: fix the generics + for (var i = 0; i < args.length; i++) + if (glsBuiltinPrecisionTests.isTypeValid(args[i].typename)) { + if (i != 0) + os += ', '; + os += args[i]; + } + + os += ')'; + + return os; + }; + + /** + * @return {glsBuiltinPrecisionTests.ParamNames} args + */ + glsBuiltinPrecisionTests.Func.prototype.doGetParamNames = function() { + /** @type {glsBuiltinPrecisionTests.ParamNames} */ var names = new glsBuiltinPrecisionTests.Tuple4('a', 'b', 'c', 'd'); + return names; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.Func} + * @param {glsBuiltinPrecisionTests.Signature} Sig template <typename Sig> + * + */ + glsBuiltinPrecisionTests.PrimitiveFunc = function(Sig) { + glsBuiltinPrecisionTests.Func.call(this, Sig); + this.Ret = Sig.Ret; + }; + + glsBuiltinPrecisionTests.PrimitiveFunc.prototype = Object.create(glsBuiltinPrecisionTests.Func.prototype); + glsBuiltinPrecisionTests.PrimitiveFunc.prototype.constructor = glsBuiltinPrecisionTests.PrimitiveFunc; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.PrimitiveFunc} + * @param {string} typename + * + */ + glsBuiltinPrecisionTests.Cond = function(typename) { + var sig = new glsBuiltinPrecisionTests.Signature(typename, 'boolean', typename, typename); + glsBuiltinPrecisionTests.PrimitiveFunc.call(this, sig); + }; + + setParentClass(glsBuiltinPrecisionTests.Cond, glsBuiltinPrecisionTests.PrimitiveFunc); + + glsBuiltinPrecisionTests.Cond.prototype.getName = function() { + return '_cond'; + }; + + glsBuiltinPrecisionTests.Cond.prototype.doPrint = function(args) { + var str = '(' + args[0] + ' ? ' + args[1] + ' : ' + args[2] + ')'; + return str; + }; + + glsBuiltinPrecisionTests.Cond.prototype.doApply = function(ctx, iargs) { + var ret; + if (glsBuiltinPrecisionTests.contains(this.Sig.Arg0, iargs.a, 1)) + ret = iargs.b; + if (glsBuiltinPrecisionTests.contains(this.Sig.Arg0, iargs.a, 0)) { + if (ret) + ret = glsBuiltinPrecisionTests.union(this.Sig.Ret, ret, iargs.c); + else + ret = iargs.c; + } + if (ret) + return ret; + return new tcuInterval.Interval(); + }; + + /** + * If multipleInputs is false, GenVec duplicates first input to proper size + * @constructor + * @extends {glsBuiltinPrecisionTests.PrimitiveFunc} + * @param {number} size + * @param {boolean=} multipleInputs + */ + glsBuiltinPrecisionTests.GenVec = function(size, multipleInputs) { + var vecName = glsBuiltinPrecisionTests.sizeToName(size); + var p = [ + size >= 1 ? 'float' : undefined, + size >= 2 ? 'float' : undefined, + size >= 3 ? 'float' : undefined, + size >= 4 ? 'float' : undefined + ]; + var sig = new glsBuiltinPrecisionTests.Signature(vecName, p[0], p[1], p[2], p[3]); + glsBuiltinPrecisionTests.PrimitiveFunc.call(this, sig); + this.size = size; + this.vecName = vecName; + this.multipleInputs = multipleInputs || false; + }; + + setParentClass(glsBuiltinPrecisionTests.GenVec, glsBuiltinPrecisionTests.PrimitiveFunc); + + glsBuiltinPrecisionTests.GenVec.prototype.getName = function() { + return this.vecName; + }; + + glsBuiltinPrecisionTests.GenVec.prototype.doApply = function(ctx, iargs) { + if (this.size == 1) + return iargs.a; + + var ret = this.multipleInputs ? + [iargs.a, iargs.b, iargs.c, iargs.d] : + [iargs.a, iargs.a, iargs.a, iargs.a]; + + return ret.slice(0, this.size); + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.PrimitiveFunc} + * @param {number} rows + * @param {number} cols + */ + glsBuiltinPrecisionTests.GenMat = function(rows, cols) { + var name = glsBuiltinPrecisionTests.dataTypeNameOfMatrix('float', rows, cols); + var vecName = glsBuiltinPrecisionTests.sizeToName(rows); + var p = [ + cols >= 1 ? vecName : undefined, + cols >= 2 ? vecName : undefined, + cols >= 3 ? vecName : undefined, + cols >= 4 ? vecName : undefined + ]; + var sig = new glsBuiltinPrecisionTests.Signature(name, p[0], p[1], p[2], p[3]); + glsBuiltinPrecisionTests.PrimitiveFunc.call(this, sig); + this.rows = rows; + this.cols = cols; + this.name = name; + this.vecName = vecName; + }; + + setParentClass(glsBuiltinPrecisionTests.GenMat, glsBuiltinPrecisionTests.PrimitiveFunc); + + glsBuiltinPrecisionTests.GenMat.prototype.getName = function() { + return this.name; + }; + + glsBuiltinPrecisionTests.GenMat.prototype.doApply = function(ctx, iargs) { + var ret = new tcuMatrix.Matrix(this.rows, this.cols); + var inputs = [iargs.a, iargs.b, iargs.c, iargs.d]; + + for (var i = 0; i < this.rows; i++) + for (var j = 0; j < this.cols; j++) + ret.set(i, j, inputs[j][i]); + return ret; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.PrimitiveFunc} + * @param {string} typename + * + */ + glsBuiltinPrecisionTests.CompareOperator = function(typename) { + var sig = new glsBuiltinPrecisionTests.Signature('boolean', typename, typename); + glsBuiltinPrecisionTests.PrimitiveFunc.call(this, sig); + }; + + setParentClass(glsBuiltinPrecisionTests.CompareOperator, glsBuiltinPrecisionTests.PrimitiveFunc); + + glsBuiltinPrecisionTests.CompareOperator.prototype.doPrint = function(args) { + var str = '(' + args[0] + this.getSymbol() + args[1] + ')'; + return str; + }; + + glsBuiltinPrecisionTests.CompareOperator.prototype.doApply = function(ctx, iargs) { + var arg0 = iargs.a; + var arg1 = iargs.b; + + var ret = new tcuInterval.Interval(); + + if (this.canSucceed(arg0, arg1)) + ret = new tcuInterval.Interval(1); + if (this.canFail(arg0, arg1)) + ret.operatorOrAssignBinary(new tcuInterval.Interval(0)); + + return ret; + }; + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.CompareOperator.prototype.getSymbol = function() { + throw new Error('Virtual function. Please override.'); + }; + + /** + * @param {tcuInterval.Interval} arg0 + * @param {tcuInterval.Interval} arg1 + * @return {boolean} + */ + glsBuiltinPrecisionTests.CompareOperator.prototype.canSucceed = function(arg0, arg1) { + throw new Error('Virtual function. Please override.'); + }; + /** + * @param {tcuInterval.Interval} arg0 + * @param {tcuInterval.Interval} arg1 + * @return {boolean} + */ + glsBuiltinPrecisionTests.CompareOperator.prototype.canFail = function(arg0, arg1) { + throw new Error('Virtual function. Please override.'); + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.CompareOperator} + * @param {string} typename + * + */ + glsBuiltinPrecisionTests.LessThan = function(typename) { + glsBuiltinPrecisionTests.CompareOperator.call(this, typename); + }; + + setParentClass(glsBuiltinPrecisionTests.LessThan, glsBuiltinPrecisionTests.CompareOperator); + + glsBuiltinPrecisionTests.LessThan.prototype.getSymbol = function() { + return '<'; + }; + + glsBuiltinPrecisionTests.LessThan.prototype.canSucceed = function(a, b) { + return (a.lo() < b.hi()); + }; + + glsBuiltinPrecisionTests.LessThan.prototype.canFail = function(a, b) { + return !(a.hi() < b.lo()); + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.PrimitiveFunc} + * + */ + glsBuiltinPrecisionTests.FloatFunc1 = function() { + var sig = new glsBuiltinPrecisionTests.Signature('float', 'float'); + glsBuiltinPrecisionTests.PrimitiveFunc.call(this, sig); + }; + + glsBuiltinPrecisionTests.FloatFunc1.prototype = Object.create(glsBuiltinPrecisionTests.PrimitiveFunc.prototype); + glsBuiltinPrecisionTests.FloatFunc1.prototype.constructor = glsBuiltinPrecisionTests.FloatFunc1; + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + * @param {glsBuiltinPrecisionTests.Tuple4} iargs + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.FloatFunc1.prototype.doApply = function(ctx, iargs) { + var a = /** @type {tcuInterval.Interval} */ (iargs.a); + return this.applyMonotone(ctx, a); + }; + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + * @param {tcuInterval.Interval} iarg0 + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.FloatFunc1.prototype.applyMonotone = function(ctx, iarg0) { + /** @type {tcuInterval.Interval} */ var ret = new tcuInterval.Interval(); + + /** + * @param {number=} x + * @param {number=} y + * @return {tcuInterval.Interval} + */ + var body = function(x, y) { + x = x || 0; + return this.applyPoint(ctx, x); + }; + ret = tcuInterval.applyMonotone1(iarg0, body.bind(this)); + + ret.operatorOrAssignBinary(this.innerExtrema(ctx, iarg0)); + + ret.operatorAndAssignBinary(this.getCodomain().operatorOrBinary(new tcuInterval.Interval(NaN))); + + return ctx.format.convert(ret); + }; + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + * @param {tcuInterval.Interval} iargs + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.FloatFunc1.prototype.innerExtrema = function(ctx, iargs) { + return new tcuInterval.Interval(); // empty interval, i.e. no extrema + }; + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + * @param {number} arg0 + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.FloatFunc1.prototype.applyPoint = function(ctx, arg0) { + var exact = this.applyExact(arg0); + var prec = this.precision(ctx, exact, arg0); + + var a = new tcuInterval.Interval(exact); + var b = tcuInterval.withNumbers(-prec, prec); + return tcuInterval.Interval.operatorSum(a, b); + }; + + /** + * @param {number} x + * @return {number} + */ + glsBuiltinPrecisionTests.FloatFunc1.prototype.applyExact = function(x) { + throw new Error('Internal error. Cannot apply'); + }; + + /** + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.FloatFunc1.prototype.getCodomain = function() { + return tcuInterval.unbounded(true); + }; + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + * @param {number} x + * @param {number} y + * @return {number} + */ + glsBuiltinPrecisionTests.FloatFunc1.prototype.precision = function(ctx, x, y) { + return 0; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.FloatFunc1} + */ + glsBuiltinPrecisionTests.Negate = function() { + glsBuiltinPrecisionTests.FloatFunc1.call(this); + }; + + setParentClass(glsBuiltinPrecisionTests.Negate, glsBuiltinPrecisionTests.FloatFunc1); + + glsBuiltinPrecisionTests.Negate.prototype.getName = function() { + return '_negate'; + }; + + glsBuiltinPrecisionTests.Negate.prototype.doPrint = function(args) { + return '-' + args[0]; + }; + + glsBuiltinPrecisionTests.Negate.prototype.precision = function(ctx, ret, x) { + return 0; + }; + glsBuiltinPrecisionTests.Negate.prototype.applyExact = function(x) { + return -x; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.FloatFunc1} + */ + glsBuiltinPrecisionTests.InverseSqrt = function() { + glsBuiltinPrecisionTests.FloatFunc1.call(this); + }; + + setParentClass(glsBuiltinPrecisionTests.InverseSqrt, glsBuiltinPrecisionTests.FloatFunc1); + + glsBuiltinPrecisionTests.InverseSqrt.prototype.getName = function() { + return 'inversesqrt'; + }; + + glsBuiltinPrecisionTests.InverseSqrt.prototype.precision = function(ctx, ret, x) { + if (x <= 0) + return NaN; + return ctx.format.ulp(ret, 2.0); + }; + + glsBuiltinPrecisionTests.InverseSqrt.prototype.applyExact = function(x) { + return 1 / Math.sqrt(x); + }; + + glsBuiltinPrecisionTests.InverseSqrt.prototype.getCodomain = function() { + return tcuInterval.withNumbers(0, Infinity); + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.FloatFunc1} + */ + glsBuiltinPrecisionTests.Round = function() { + glsBuiltinPrecisionTests.FloatFunc1.call(this); + }; + + setParentClass(glsBuiltinPrecisionTests.Round, glsBuiltinPrecisionTests.FloatFunc1); + + glsBuiltinPrecisionTests.Round.prototype.getName = function() { + return 'round'; + }; + + glsBuiltinPrecisionTests.Round.prototype.precision = function(ctx, ret, x) { + return 0; + }; + + glsBuiltinPrecisionTests.Round.prototype.applyPoint = function(ctx, x) { + var truncated = Math.trunc(x); + var fract = x - truncated; + var ret = new tcuInterval.Interval(); + + // When x is inf or -inf, truncated would be inf or -inf too. Then fract + // would be NaN (inf - inf). While in native c code, it would be 0 (inf) or -0 (-inf). + // This behavior in JS differs from that in native c code. + if (Math.abs(fract) <= 0.5 || isNaN(fract)) + ret.operatorOrAssignBinary(new tcuInterval.Interval(truncated)); + if (Math.abs(fract) >= 0.5) + ret.operatorOrAssignBinary(new tcuInterval.Interval(truncated + deMath.deSign(fract))); + + return ret; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.FloatFunc1} + * @param {string} name + * @param {tcuInterval.DoubleFunc1} func + */ + glsBuiltinPrecisionTests.CFloatFunc1 = function(name, func) { + glsBuiltinPrecisionTests.FloatFunc1.call(this); + /** @type {string} */ this.m_name = name; + /** @type {tcuInterval.DoubleFunc1} */this.m_func = func; + }; + + glsBuiltinPrecisionTests.CFloatFunc1.prototype = Object.create(glsBuiltinPrecisionTests.FloatFunc1.prototype); + glsBuiltinPrecisionTests.CFloatFunc1.prototype.constructor = glsBuiltinPrecisionTests.CFloatFunc1; + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.CFloatFunc1.prototype.getName = function() { + return this.m_name; + }; + + /** + * @param {number} x + * @return {number} + */ + glsBuiltinPrecisionTests.CFloatFunc1.prototype.applyExact = function(x) { + return this.m_func(x); + }; + + /** + * PrimitiveFunc<Signature<float, float, float> > + * @constructor + * @extends {glsBuiltinPrecisionTests.PrimitiveFunc} + */ + glsBuiltinPrecisionTests.FloatFunc2 = function() { + /** @type {glsBuiltinPrecisionTests.Signature} */ var Sig = new glsBuiltinPrecisionTests.Signature('float', 'float', 'float'); + glsBuiltinPrecisionTests.PrimitiveFunc.call(this, Sig); + }; + + glsBuiltinPrecisionTests.FloatFunc2.prototype = Object.create(glsBuiltinPrecisionTests.PrimitiveFunc.prototype); + glsBuiltinPrecisionTests.FloatFunc2.prototype.constructor = glsBuiltinPrecisionTests.FloatFunc2; + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + * @param {glsBuiltinPrecisionTests.Tuple4} iargs + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.FloatFunc2.prototype.doApply = function(ctx, iargs) { + var a = /** @type {tcuInterval.Interval} */ (iargs.a); + var b = /** @type {tcuInterval.Interval} */ (iargs.b); + return this.applyMonotone(ctx, a, b); + }; + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + * @param {tcuInterval.Interval} xi + * @param {tcuInterval.Interval} yi + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.FloatFunc2.prototype.applyMonotone = function(ctx, xi, yi) { + /** @type {tcuInterval.Interval} */ var ret = new tcuInterval.Interval(); + + /** + * @param {number=} x + * @param {number=} y + * @return {tcuInterval.Interval} + */ + var body = function(x, y) { + x = x || 0; + y = y || 0; + return this.applyPoint(ctx, x, y); + }; + ret = tcuInterval.applyMonotone2(xi, yi, body.bind(this)); + + ret.operatorOrAssignBinary(this.innerExtrema(ctx, xi, yi)); + + ret.operatorAndAssignBinary(this.getCodomain().operatorOrBinary(new tcuInterval.Interval(NaN))); + + return ctx.format.convert(ret); + }; + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + * @param {tcuInterval.Interval} xi + * @param {tcuInterval.Interval} yi + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.FloatFunc2.prototype.innerExtrema = function(ctx, xi, yi) { + return new tcuInterval.Interval(); // empty interval, i.e. no extrema + }; + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + * @param {number} x + * @param {number} y + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.FloatFunc2.prototype.applyPoint = function(ctx, x, y) { + /** @type {number} */ var exact = this.applyExact(x, y); + var prec = this.precision(ctx, exact, x, y); + + var a = new tcuInterval.Interval(exact); + var b = tcuInterval.withNumbers(-prec, prec); + return tcuInterval.Interval.operatorSum(a, b); + }; + + /** + * @param {number} x + * @param {number} y + * @return {number} + */ + glsBuiltinPrecisionTests.FloatFunc2.prototype.applyExact = function(x, y) { + throw new Error('Virtual function. Please override'); + }; + + /** + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.FloatFunc2.prototype.getCodomain = function() { + return tcuInterval.unbounded(true); + }; + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + * @param {number} ret + * @param {number} x + * @param {number} y + * @return {number} + */ + glsBuiltinPrecisionTests.FloatFunc2.prototype.precision = function(ctx, ret, x, y) { + throw new Error('Virtual function. Please override'); + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.FloatFunc2} + * @param {string} name + * @param {tcuInterval.DoubleFunc2} func + */ + glsBuiltinPrecisionTests.CFloatFunc2 = function(name, func) { + glsBuiltinPrecisionTests.FloatFunc2.call(this); + /** @type {string} */ this.m_name = name; + /** @type {tcuInterval.DoubleFunc2} */ this.m_func = func; + }; + + glsBuiltinPrecisionTests.CFloatFunc2.prototype = Object.create(glsBuiltinPrecisionTests.FloatFunc2.prototype); + glsBuiltinPrecisionTests.CFloatFunc2.prototype.constructor = glsBuiltinPrecisionTests.CFloatFunc2; + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.CFloatFunc2.prototype.getName = function() { + return this.m_name; + }; + + /** + * @param {number} x + * @param {number} y + * @return {number} + */ + glsBuiltinPrecisionTests.CFloatFunc2.prototype.applyExact = function(x, y) { + return this.m_func(x, y); + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.FloatFunc2} + */ + glsBuiltinPrecisionTests.InfixOperator = function() { + glsBuiltinPrecisionTests.FloatFunc2.call(this); + }; + + glsBuiltinPrecisionTests.InfixOperator.prototype = Object.create(glsBuiltinPrecisionTests.FloatFunc2.prototype); + glsBuiltinPrecisionTests.InfixOperator.prototype.constructor = glsBuiltinPrecisionTests.InfixOperator; + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.InfixOperator.prototype.getSymbol = function() { + glsBuiltinPrecisionTests.FloatFunc2.call(this); + return ''; + }; + + /** + * @param {Array<glsBuiltinPrecisionTests.ExprBase>} args + * @return {string} + */ + glsBuiltinPrecisionTests.InfixOperator.prototype.doPrint = function(args) { + return '(' + args[0] + ' ' + this.getSymbol() + ' ' + args[1] + ')'; + }; + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + * @param {number} x + * @param {number} y + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.InfixOperator.prototype.applyPoint = function(ctx, x, y) { + /** @type {number} */ var exact = this.applyExact(x, y); + + // Allow either representable number on both sides of the exact value, + // but require exactly representable values to be preserved. + return ctx.format.roundOut(new tcuInterval.Interval(exact), isFinite(x) && isFinite(y)); + }; + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + * @param {number} x + * @param {number} y + * @param {number} z + * @return {number} + */ + glsBuiltinPrecisionTests.InfixOperator.prototype.precision = function(ctx, x, y, z) { + return 0; + }; + + /** + * Signature<float, float, float, float> + * @constructor + * @extends {glsBuiltinPrecisionTests.PrimitiveFunc} + */ + glsBuiltinPrecisionTests.FloatFunc3 = function() { + /** @type {glsBuiltinPrecisionTests.Signature} */ var sig = new glsBuiltinPrecisionTests.Signature('float', 'float', 'float', 'float'); + glsBuiltinPrecisionTests.PrimitiveFunc.call(this, sig); + }; + + glsBuiltinPrecisionTests.FloatFunc3.prototype = Object.create(glsBuiltinPrecisionTests.PrimitiveFunc.prototype); + glsBuiltinPrecisionTests.FloatFunc3.prototype.constructor = glsBuiltinPrecisionTests.FloatFunc3; + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + * @param {glsBuiltinPrecisionTests.Tuple4} iargs + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.FloatFunc3.prototype.doApply = function(ctx, iargs) { + var a = /** @type {tcuInterval.Interval} */ (iargs.a); + var b = /** @type {tcuInterval.Interval} */ (iargs.b); + var c = /** @type {tcuInterval.Interval} */ (iargs.c); + var retVal = this.applyMonotone(ctx, a, b, c); + return retVal; + }; + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + * @param {tcuInterval.Interval} xi + * @param {tcuInterval.Interval} yi + * @param {tcuInterval.Interval} zi + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.FloatFunc3.prototype.applyMonotone = function(ctx, xi, yi, zi) { + /** + * @param {number=} x + * @param {number=} y + * @param {number=} z + * @return {tcuInterval.Interval} + */ + var body = function(x, y, z) { + x = x || 0; + y = y || 0; + z = z || 0; + return this.applyPoint(ctx, x, y, z); + }; + var ret = tcuInterval.applyMonotone3(xi, yi, zi, body.bind(this)); + var retVal; + + ret.operatorOrAssignBinary(this.innerExtrema(ctx, xi, yi, zi)); + + ret.operatorAndAssignBinary(this.getCodomain().operatorOrBinary(new tcuInterval.Interval(NaN))); + + retVal = ctx.format.convert(ret); + return retVal; + }; + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + * @param {tcuInterval.Interval} xi + * @param {tcuInterval.Interval} yi + * @param {tcuInterval.Interval} zi + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.FloatFunc3.prototype.innerExtrema = function(ctx, xi, yi, zi) { + return new tcuInterval.Interval(); // empty interval, i.e. no extrema + }; + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + * @param {number} x + * @param {number} y + * @param {number} z + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.FloatFunc3.prototype.applyPoint = function(ctx, x, y, z) { + /** @type {number} */ var exact = this.applyExact(x, y, z); + /** @type {number} */ var prec = this.precision(ctx, exact, x, y, z); + + var a = new tcuInterval.Interval(exact); + var b = tcuInterval.withNumbers(-prec, prec); + return tcuInterval.Interval.operatorSum(a, b); + }; + + /** + * @param {number} x + * @param {number} y + * @param {number} z + * @return {number} + */ + glsBuiltinPrecisionTests.FloatFunc3.prototype.applyExact = function(x, y, z) { + throw new Error('Virtual function. Please override'); + }; + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + * @param {number} result + * @param {number} x + * @param {number} y + * @param {number} z + * @return {number} + */ + glsBuiltinPrecisionTests.FloatFunc3.prototype.precision = function(ctx, result, x, y, z) { + throw new Error('Virtual function. Please override'); + }; + + /** + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.FloatFunc3.prototype.getCodomain = function() { + return tcuInterval.unbounded(true); + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.FloatFunc3} + */ + glsBuiltinPrecisionTests.Clamp = function() { + glsBuiltinPrecisionTests.FloatFunc3.call(this); + }; + + setParentClass(glsBuiltinPrecisionTests.Clamp, glsBuiltinPrecisionTests.FloatFunc3); + + glsBuiltinPrecisionTests.Clamp.prototype.getName = function() { + return 'clamp'; + }; + + glsBuiltinPrecisionTests.Clamp.prototype.applyExact = function(x, minVal, maxVal) { + var debug = false; + var retVal; + + retVal = deMath.clamp(x, minVal, maxVal); + if (debug) { + console.log('> minVal: ' + minVal); + console.log('> maxVal: ' + maxVal); + console.log('> x: ' + x); + console.log('> ret: ' + retVal); + } + return retVal; + + }; + + glsBuiltinPrecisionTests.Clamp.prototype.precision = function(ctx, result, x, minVal, maxVal) { + var debug = false; + var retVal; + + retVal = minVal > maxVal ? NaN : 0; + + if (debug) { + console.log('precision> minVal: ' + minVal); + console.log('precision> maxVal: ' + maxVal); + console.log('precision> x: ' + x); + console.log('precision> ret: ' + retVal); + } + + return retVal; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.InfixOperator} + */ + glsBuiltinPrecisionTests.Add = function() { + glsBuiltinPrecisionTests.InfixOperator.call(this); + }; + + glsBuiltinPrecisionTests.Add.prototype = Object.create(glsBuiltinPrecisionTests.InfixOperator.prototype); + glsBuiltinPrecisionTests.Add.prototype.constructor = glsBuiltinPrecisionTests.Add; + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.Add.prototype.getName = function() { + return 'add'; + }; + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.Add.prototype.getSymbol = function() { + return '+'; + }; + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + * @param {glsBuiltinPrecisionTests.Tuple4} iargs + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.Add.prototype.doApply = function(ctx, iargs) { + var a = /** @type {tcuInterval.Interval} */ (iargs.a); + var b = /** @type {tcuInterval.Interval} */ (iargs.b); + // Fast-path for common case + if (iargs.a.isOrdinary() && iargs.b.isOrdinary()) { + /** type{tcuInterval.Interval} */ var ret; + ret = tcuInterval.setIntervalBounds( + function(dummy) { + return iargs.a.lo() + iargs.b.lo(); + }, + function(dummy) { + return iargs.a.hi() + iargs.b.hi(); + }); + return ctx.format.convert(ctx.format.roundOut(ret, true)); + } + return this.applyMonotone(ctx, a, b); + }; + + /** + * @param {number} x + * @param {number} y + * @return {number} + */ + glsBuiltinPrecisionTests.Add.prototype.applyExact = function(x, y) { + return x + y; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.InfixOperator} + */ + glsBuiltinPrecisionTests.Sub = function() { + glsBuiltinPrecisionTests.InfixOperator.call(this); + }; + + glsBuiltinPrecisionTests.Sub.prototype = Object.create(glsBuiltinPrecisionTests.InfixOperator.prototype); + glsBuiltinPrecisionTests.Sub.prototype.constructor = glsBuiltinPrecisionTests.Sub; + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.Sub.prototype.getName = function() { + return 'sub'; + }; + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.Sub.prototype.getSymbol = function() { + return '-'; + }; + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + * @param {glsBuiltinPrecisionTests.Tuple4} iargs + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.Sub.prototype.doApply = function(ctx, iargs) { + var a = /** @type {tcuInterval.Interval} */ (iargs.a); + var b = /** @type {tcuInterval.Interval} */ (iargs.b); + var retVal; + + // Fast-path for common case + if (iargs.a.isOrdinary() && iargs.b.isOrdinary()) { + /** type{tcuInterval.Interval} */ var ret; + ret = tcuInterval.setIntervalBounds( + function(dummy) { + return iargs.a.lo() - iargs.b.hi(); + }, + function(dummy) { + return iargs.a.hi() - iargs.b.lo(); + }); + return ctx.format.convert(ctx.format.roundOut(ret, true)); + } + retVal = this.applyMonotone(ctx, a, b); + return retVal; + }; + + /** + * @param {number} x + * @param {number} y + * @return {number} + */ + glsBuiltinPrecisionTests.Sub.prototype.applyExact = function(x, y) { + return x - y; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.InfixOperator} + */ + glsBuiltinPrecisionTests.Mul = function() { + glsBuiltinPrecisionTests.InfixOperator.call(this); + }; + + glsBuiltinPrecisionTests.Mul.prototype = Object.create(glsBuiltinPrecisionTests.InfixOperator.prototype); + glsBuiltinPrecisionTests.Mul.prototype.constructor = glsBuiltinPrecisionTests.Mul; + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.Mul.prototype.getName = function() { + return 'mul'; + }; + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.Mul.prototype.getSymbol = function() { + return '*'; + }; + + glsBuiltinPrecisionTests.isNegative = function(n) { + return ((n = +n) || 1 / n) < 0; + }; + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + * @param {glsBuiltinPrecisionTests.Tuple4} iargs + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.Mul.prototype.doApply = function(ctx, iargs) { + var a = /** @type {tcuInterval.Interval} */ (iargs.a); + var b = /** @type {tcuInterval.Interval} */ (iargs.b); + // Fast-path for common case + if (iargs.a.isOrdinary() && iargs.b.isOrdinary()) { + /** type{tcuInterval.Interval} */ var ret = new tcuInterval.Interval(); + if (glsBuiltinPrecisionTests.isNegative(a.hi())) { + a = a.operatorNegative(); + b = b.operatorNegative(); + } + if (a.lo() >= 0 && b.lo() >= 0) { + ret = tcuInterval.setIntervalBounds( + function(dummy) { + return iargs.a.lo() * iargs.b.lo(); + }, + function(dummy) { + return iargs.a.hi() * iargs.b.hi(); + }); + return ctx.format.convert(ctx.format.roundOut(ret, true)); + } + if (a.lo() >= 0 && b.hi() <= 0) { + ret = tcuInterval.setIntervalBounds( + function(dummy) { + return iargs.a.hi() * iargs.b.lo(); + }, + function(dummy) { + return iargs.a.lo() * iargs.b.hi(); + }); + return ctx.format.convert(ctx.format.roundOut(ret, true)); + } + } + + return this.applyMonotone(ctx, a, b); + }; + + /** + * @param {number} x + * @param {number} y + * @return {number} + */ + glsBuiltinPrecisionTests.Mul.prototype.applyExact = function(x, y) { + return x * y; + }; + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + * @param {tcuInterval.Interval} xi + * @param {tcuInterval.Interval} yi + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.Mul.prototype.innerExtrema = function(ctx, xi, yi) { + if (((xi.contains(tcuInterval.NEGATIVE_INFINITY) || xi.contains(tcuInterval.POSITIVE_INFINITY)) && yi.contains(tcuInterval.ZERO)) || + ((yi.contains(tcuInterval.NEGATIVE_INFINITY) || yi.contains(tcuInterval.POSITIVE_INFINITY)) && xi.contains(tcuInterval.ZERO))) + return new tcuInterval.Interval(NaN); + + return new tcuInterval.Interval(); // empty interval, i.e. no extrema + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.InfixOperator} + */ + glsBuiltinPrecisionTests.Div = function() { + glsBuiltinPrecisionTests.InfixOperator.call(this); + }; + + glsBuiltinPrecisionTests.Div.prototype = Object.create(glsBuiltinPrecisionTests.InfixOperator.prototype); + glsBuiltinPrecisionTests.Div.prototype.constructor = glsBuiltinPrecisionTests.Div; + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.Div.prototype.getName = function() { + return 'div'; + }; + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.Div.prototype.getSymbol = function() { + return '/'; + }; + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + * @param {tcuInterval.Interval} nom + * @param {tcuInterval.Interval} den + * @return {tcuInterval.Interval} + */ + glsBuiltinPrecisionTests.Div.prototype.innerExtrema = function(ctx, nom, den) { + var ret = new tcuInterval.Interval(); + if (den.contains(tcuInterval.ZERO)) { + if (nom.contains(tcuInterval.ZERO)) + ret.operatorOrAssignBinary(tcuInterval.NAN); + if (nom.lo() < 0 || nom.hi() > 0.0) + ret.operatorOrAssignBinary(tcuInterval.unbounded()); + } + + return ret; + }; + + glsBuiltinPrecisionTests.Div.prototype.precision = function(ctx, ret, nom, den) { + var fmt = ctx.format; + + // \todo [2014-03-05 lauri] Check that the limits in GLSL 3.10 are actually correct. + // For now, we assume that division's precision is 2.5 ULP when the value is within + // [2^MINEXP, 2^MAXEXP-1] + + if (den === 0) + return 0; // Result must be exactly inf + else if (deMath.deInBounds32(Math.abs(den), + deMath.deLdExp(1, fmt.getMinExp()), + deMath.deLdExp(1, fmt.getMaxExp() - 1))) + return fmt.ulp(ret, 2.5); + else + return Infinity; // Can be any number, but must be a number. + }; + + /** + * @param {number} x + * @param {number} y + * @return {number} + */ + glsBuiltinPrecisionTests.Div.prototype.applyExact = function(x, y) { + return x / y; + }; + + glsBuiltinPrecisionTests.Div.prototype.applyPoint = function(ctx, x, y) { + var ret = glsBuiltinPrecisionTests.FloatFunc2.prototype.applyPoint.call(this, ctx, x, y); + if (isFinite(x) && isFinite(y) && y != 0) { + var dst = ctx.format.convert(ret); + if (dst.contains(tcuInterval.NEGATIVE_INFINITY)) { + ret.operatorOrAssignBinary(-ctx.format.getMaxValue()); + } + if (dst.contains(tcuInterval.POSITIVE_INFINITY)) { + ret.operatorOrAssignBinary(+ctx.format.getMaxValue()); + } + } + return ret; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.PrimitiveFunc} + */ + glsBuiltinPrecisionTests.CompWiseFunc = function(typename, Sig) { + glsBuiltinPrecisionTests.PrimitiveFunc.call(this, Sig); + this.typename = typename; + }; + + setParentClass(glsBuiltinPrecisionTests.CompWiseFunc, glsBuiltinPrecisionTests.PrimitiveFunc); + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.CompWiseFunc.prototype.getName = function() { + return this.doGetScalarFunc().getName(); + }; + + /** + * @param {Array<glsBuiltinPrecisionTests.ExprBase>} args + * @return {string} + */ + glsBuiltinPrecisionTests.CompWiseFunc.prototype.doPrint = function(args) { + return this.doGetScalarFunc().print(args); + }; + + /** + * @return {glsBuiltinPrecisionTests.Func} + */ + glsBuiltinPrecisionTests.CompWiseFunc.prototype.doGetScalarFunc = function() { + throw new Error('Virtual function. Please override.'); + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.CompWiseFunc} + * @param {number} rows + * @param {number} cols + */ + glsBuiltinPrecisionTests.CompMatFuncBase = function(rows, cols) { + var name = glsBuiltinPrecisionTests.dataTypeNameOfMatrix('float', rows, cols); + glsBuiltinPrecisionTests.CompWiseFunc.call(this, 'float', new glsBuiltinPrecisionTests.Signature(name, name, name)); + this.rows = rows; + this.cols = cols; + }; + + setParentClass(glsBuiltinPrecisionTests.CompMatFuncBase, glsBuiltinPrecisionTests.CompWiseFunc); + + glsBuiltinPrecisionTests.CompMatFuncBase.prototype.doApply = function(ctx, iargs) { + var ret = new tcuMatrix.Matrix(this.rows, this.cols); + var fun = this.doGetScalarFunc(); + + for (var row = 0; row < this.rows; ++row) + for (var col = 0; col < this.cols; ++col) + ret.set(row, col, fun.applyFunction(ctx, + iargs.a.get(row, col), + iargs.b.get(row, col))); + + return ret; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.CompMatFuncBase} + * @param {function(new:glsBuiltinPrecisionTests.Func)} F + * @param {number} rows + * @param {number} cols + */ + glsBuiltinPrecisionTests.CompMatFunc = function(F, rows, cols) { + glsBuiltinPrecisionTests.CompMatFuncBase.call(this, rows, cols); + this.m_function = F; + }; + + setParentClass(glsBuiltinPrecisionTests.CompMatFunc, glsBuiltinPrecisionTests.CompMatFuncBase); + + /** + * @return {glsBuiltinPrecisionTests.Func} + */ + glsBuiltinPrecisionTests.CompMatFunc.prototype.doGetScalarFunc = function() { + return new this.m_function(); + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.Mul} + */ + glsBuiltinPrecisionTests.ScalarMatrixCompMult = function() { + glsBuiltinPrecisionTests.Mul.call(this); + }; + + setParentClass(glsBuiltinPrecisionTests.ScalarMatrixCompMult, glsBuiltinPrecisionTests.Mul); + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.ScalarMatrixCompMult.prototype.getName = function() { + return 'matrixCompMult'; + }; + + /** + * @param {Array<glsBuiltinPrecisionTests.ExprBase>} args + * @return {string} + */ + glsBuiltinPrecisionTests.ScalarMatrixCompMult.prototype.doPrint = function(args) { + return glsBuiltinPrecisionTests.Func.prototype.doPrint.call(this, args); + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.CompMatFunc} + * @param {number} rows + * @param {number} cols + */ + glsBuiltinPrecisionTests.MatrixCompMult = function(rows, cols) { + glsBuiltinPrecisionTests.CompMatFunc.call(this, glsBuiltinPrecisionTests.ScalarMatrixCompMult, rows, cols); + }; + + setParentClass(glsBuiltinPrecisionTests.MatrixCompMult, glsBuiltinPrecisionTests.CompMatFunc); + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.PrimitiveFunc} + * @param {number} rows + * @param {number} cols + */ + glsBuiltinPrecisionTests.OuterProduct = function(rows, cols) { + var name = glsBuiltinPrecisionTests.dataTypeNameOfMatrix('float', rows, cols); + var sig = new glsBuiltinPrecisionTests.Signature(name, 'vec' + rows, 'vec' + cols); + glsBuiltinPrecisionTests.PrimitiveFunc.call(this, sig); + this.rows = rows; + this.cols = cols; + }; + + setParentClass(glsBuiltinPrecisionTests.OuterProduct, glsBuiltinPrecisionTests.PrimitiveFunc); + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.OuterProduct.prototype.getName = function() { + return 'outerProduct'; + }; + + glsBuiltinPrecisionTests.OuterProduct.prototype.doApply = function(ctx, iargs) { + var ret = new tcuMatrix.Matrix(this.rows, this.cols); + var mul = new glsBuiltinPrecisionTests.Mul(); + + for (var row = 0; row < this.rows; ++row) { + for (var col = 0; col < this.cols; ++col) + ret.set(row, col, mul.applyFunction(ctx, iargs.a[row], iargs.b[col])); + } + + return ret; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.PrimitiveFunc} + * @param {number} rows + * @param {number} cols + */ + glsBuiltinPrecisionTests.Transpose = function(rows, cols) { + var nameRet = glsBuiltinPrecisionTests.dataTypeNameOfMatrix('float', rows, cols); + var nameParam = glsBuiltinPrecisionTests.dataTypeNameOfMatrix('float', cols, rows); + var sig = new glsBuiltinPrecisionTests.Signature(nameRet, nameParam); + glsBuiltinPrecisionTests.PrimitiveFunc.call(this, sig); + this.rows = rows; + this.cols = cols; + }; + + setParentClass(glsBuiltinPrecisionTests.Transpose, glsBuiltinPrecisionTests.PrimitiveFunc); + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.Transpose.prototype.getName = function() { + return 'transpose'; + }; + + glsBuiltinPrecisionTests.Transpose.prototype.doApply = function(ctx, iargs) { + var ret = new tcuMatrix.Matrix(this.rows, this.cols); + + for (var row = 0; row < this.rows; ++row) + for (var col = 0; col < this.cols; ++col) + ret.set(row, col, iargs.a.get(col, row)); + + return ret; + }; + + /** + * @constructor + * @param {*} In + */ + glsBuiltinPrecisionTests.Inputs = function(In) { + // vector<typename In::In0> in0; + // vector<typename In::In1> in1; + // vector<typename In::In2> in2; + // vector<typename In::In3> in3; + this.in0 = []; + this.in1 = []; + this.in2 = []; + this.in3 = []; + }; + + /** + * @constructor + * @param {number} size + * @param {*} Out + */ + glsBuiltinPrecisionTests.Outputs = function(size, Out) { + // Outputs (size_t size) : out0(size), out1(size) {} + this.out0 = []; + this.out1 = []; + }; + + /** + * @constructor + * @param {*} In + * @param {*} Out + */ + glsBuiltinPrecisionTests.Variables = function(In, Out) { + this.in0 = new glsBuiltinPrecisionTests.Variable(In.In0); + this.in1 = new glsBuiltinPrecisionTests.Variable(In.In1); + this.in2 = new glsBuiltinPrecisionTests.Variable(In.In2); + this.in3 = new glsBuiltinPrecisionTests.Variable(In.In3); + this.out0 = new glsBuiltinPrecisionTests.Variable(Out.Out0); + this.out1 = new glsBuiltinPrecisionTests.Variable(Out.Out1); + }; + + /** + * @constructor + * @param {function(new:glsBuiltinPrecisionTests.Func)} F + * @return {glsBuiltinPrecisionTests.GenFuncs} + */ + glsBuiltinPrecisionTests.makeVectorizedFuncs = function(F) { + return new glsBuiltinPrecisionTests.GenFuncs( + new F(), + new glsBuiltinPrecisionTests.VectorizedFunc(new F(), 2), + new glsBuiltinPrecisionTests.VectorizedFunc(new F(), 3), + new glsBuiltinPrecisionTests.VectorizedFunc(new F(), 4)); + }; + + /** + * @constructor + * @param {glsBuiltinPrecisionTests.Typename} typename + */ + glsBuiltinPrecisionTests.Sampling = function(typename) { + this.typename = typename; + }; + + /** + * @param {glsBuiltinPrecisionTests.Typename} typename + * @param {number=} size + * @return {glsBuiltinPrecisionTests.Sampling} + */ + glsBuiltinPrecisionTests.SamplingFactory = function(typename, size) { + if (size > 1) + return new glsBuiltinPrecisionTests.DefaultSamplingVector(typename, size); + switch (typename) { + case 'vec4' : return new glsBuiltinPrecisionTests.DefaultSamplingVector('float', 4); + case 'vec3' : return new glsBuiltinPrecisionTests.DefaultSamplingVector('float', 3); + case 'vec2' : return new glsBuiltinPrecisionTests.DefaultSamplingVector('float', 2); + case 'boolean' : return new glsBuiltinPrecisionTests.DefaultSamplingBool(typename); + case 'float' : return new glsBuiltinPrecisionTests.DefaultSamplingFloat(typename); + case 'mat2': return new glsBuiltinPrecisionTests.DefaultSamplingMatrix('float', 2, 2); + case 'mat2x3': return new glsBuiltinPrecisionTests.DefaultSamplingMatrix('float', 3, 2); + case 'mat2x4': return new glsBuiltinPrecisionTests.DefaultSamplingMatrix('float', 4, 2); + case 'mat3x2': return new glsBuiltinPrecisionTests.DefaultSamplingMatrix('float', 2, 3); + case 'mat3': return new glsBuiltinPrecisionTests.DefaultSamplingMatrix('float', 3, 3); + case 'mat3x4': return new glsBuiltinPrecisionTests.DefaultSamplingMatrix('float', 4, 3); + case 'mat4x2': return new glsBuiltinPrecisionTests.DefaultSamplingMatrix('float', 2, 4); + case 'mat4x3': return new glsBuiltinPrecisionTests.DefaultSamplingMatrix('float', 3, 4); + case 'mat4': return new glsBuiltinPrecisionTests.DefaultSamplingMatrix('float', 4, 4); + case 'int' : return new glsBuiltinPrecisionTests.DefaultSamplingInt(typename); + } + return new glsBuiltinPrecisionTests.DefaultSamplingVoid(typename); + }; + + /** + * @param {tcuFloatFormat.FloatFormat} fmt + * @param {Array<*>} arr + */ + glsBuiltinPrecisionTests.Sampling.prototype.genFixeds = function(fmt, arr) { + throw new Error('Virtual function. Please override.'); + }; + + /** + * @param {tcuFloatFormat.FloatFormat} fmt + * @param {gluShaderUtil.precision} precision + * @param {deRandom.Random} random + * @return {*} + */ + glsBuiltinPrecisionTests.Sampling.prototype.genRandom = function(fmt, precision, random) { + return 0; + }; + + /** + * @return {number} + */ + glsBuiltinPrecisionTests.Sampling.prototype.getWeight = function() { + return 0; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.Sampling} + * @param {glsBuiltinPrecisionTests.Typename} typename + */ + glsBuiltinPrecisionTests.DefaultSamplingVoid = function(typename) { + glsBuiltinPrecisionTests.Sampling.call(this, typename); + }; + + glsBuiltinPrecisionTests.DefaultSamplingVoid.prototype = Object.create(glsBuiltinPrecisionTests.Sampling.prototype); + glsBuiltinPrecisionTests.DefaultSamplingVoid.prototype.constructor = glsBuiltinPrecisionTests.DefaultSamplingVoid; + + /** + * @param {tcuFloatFormat.FloatFormat} fmt + * @param {Array<number>} dst + */ + glsBuiltinPrecisionTests.DefaultSamplingVoid.prototype.genFixeds = function(fmt, dst) { + dst.push(NaN); + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.Sampling} + * @param {glsBuiltinPrecisionTests.Typename} typename + */ + glsBuiltinPrecisionTests.DefaultSamplingBool = function(typename) { + glsBuiltinPrecisionTests.Sampling.call(this, typename); + }; + + glsBuiltinPrecisionTests.DefaultSamplingBool.prototype = Object.create(glsBuiltinPrecisionTests.Sampling.prototype); + glsBuiltinPrecisionTests.DefaultSamplingBool.prototype.constructor = glsBuiltinPrecisionTests.DefaultSamplingBool; + + /** + * @param {tcuFloatFormat.FloatFormat} fmt + * @param {Array<Boolean>} dst + */ + glsBuiltinPrecisionTests.DefaultSamplingBool.prototype.genFixeds = function(fmt, dst) { + dst.push(true); + dst.push(false); + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.Sampling} + * @param {glsBuiltinPrecisionTests.Typename} typename + */ + glsBuiltinPrecisionTests.DefaultSamplingInt = function(typename) { + glsBuiltinPrecisionTests.Sampling.call(this, typename); + }; + + glsBuiltinPrecisionTests.DefaultSamplingInt.prototype = Object.create(glsBuiltinPrecisionTests.Sampling.prototype); + glsBuiltinPrecisionTests.DefaultSamplingInt.prototype.constructor = glsBuiltinPrecisionTests.DefaultSamplingInt; + + glsBuiltinPrecisionTests.DefaultSamplingInt.prototype.genRandom = function(fmt, prec, rnd) { + /** @type {number} */ var exp = rnd.getInt(0, this.getNumBits(prec) - 2); + /** @type {number} */ var sign = rnd.getBool() ? -1 : 1; + + return sign * rnd.getInt(0, 1 << exp); + }; + + glsBuiltinPrecisionTests.DefaultSamplingInt.prototype.genFixeds = function(fmt, dst) { + dst.push(0); + dst.push(-1); + dst.push(1); + }; + + glsBuiltinPrecisionTests.DefaultSamplingInt.prototype.getWeight = function() { + return 1.0; + }; + + /** + * @param {gluShaderUtil.precision} prec + * @return {number} + */ + glsBuiltinPrecisionTests.DefaultSamplingInt.prototype.getNumBits = function(prec) { + switch (prec) { + case gluShaderUtil.precision.PRECISION_LOWP: return 8; + case gluShaderUtil.precision.PRECISION_MEDIUMP: return 16; + case gluShaderUtil.precision.PRECISION_HIGHP: return 32; + default: + throw new Error('Invalid precision: ' + prec); + } + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.Sampling} + * @param {glsBuiltinPrecisionTests.Typename} typename + */ + glsBuiltinPrecisionTests.DefaultSamplingFloat = function(typename) { + glsBuiltinPrecisionTests.Sampling.call(this, typename); + }; + + glsBuiltinPrecisionTests.DefaultSamplingFloat.prototype = Object.create(glsBuiltinPrecisionTests.Sampling.prototype); + glsBuiltinPrecisionTests.DefaultSamplingFloat.prototype.constructor = glsBuiltinPrecisionTests.DefaultSamplingFloat; + + glsBuiltinPrecisionTests.DefaultSamplingFloat.prototype.genRandom = function(format, prec, rnd) { + /** type{number} */ var minExp = format.getMinExp(); + /** type{number} */ var maxExp = format.getMaxExp(); + /** type{boolean} */ var haveSubnormal = format.hasSubnormal() != tcuFloatFormat.YesNoMaybe.NO; + + // Choose exponent so that the cumulative distribution is cubic. + // This makes the probability distribution quadratic, with the peak centered on zero. + /** type{number} */ var minRoot = deMath.deCbrt(minExp - 0.5 - (haveSubnormal ? 1.0 : 0.0)); + /** type{number} */ var maxRoot = deMath.deCbrt(maxExp + 0.5); + /** type{number} */ var fractionBits = format.getFractionBits(); + /** type{number} */ var exp = deMath.rint(Math.pow(rnd.getFloat(minRoot, maxRoot), + 3.0)); + /** type{number} */ var base = 0.0; // integral power of two + /** type{number} */ var quantum = 0.0; // smallest representable difference in the binade + /** type{number} */ var significand = 0.0; // Significand. + + // DE_ASSERT(fractionBits < std::numeric_limits<float>::digits); + + // Generate some occasional special numbers + switch (rnd.getInt(0, 64)) { + case 0: return 0; + case 1: return Number.POSITIVE_INFINITY; + case 2: return Number.NEGATIVE_INFINITY; + case 3: return NaN; + default: break; + } + + if (exp >= minExp) { + // Normal number + base = deMath.deFloatLdExp(1.0, exp); + quantum = deMath.deFloatLdExp(1.0, exp - fractionBits); + } else { + // Subnormal + base = 0.0; + quantum = deMath.deFloatLdExp(1.0, minExp - fractionBits); + } + + switch (rnd.getInt(0, 16)) { + // The highest number in this binade, significand is all bits one. + case 0: + significand = base - quantum; + break; + // Significand is one. + case 1: + significand = quantum; + break; + // Significand is zero. + case 2: + significand = 0.0; + break; + // Random (evenly distributed) significand. + default: { + /** type{number} */ var intFraction = rnd.getInt() & ((1 << fractionBits) - 1); + significand = intFraction * quantum; + } + } + + // Produce positive numbers more often than negative. + return (rnd.getInt(0, 3) == 0 ? -1.0 : 1.0) * (base + significand); + }; + + glsBuiltinPrecisionTests.DefaultSamplingFloat.prototype.genFixeds = function(format, dst) { + /** @type {number} */ var minExp = format.getMinExp(); + /** @type {number} */ var maxExp = format.getMaxExp(); + /** @type {number} */ var fractionBits = format.getFractionBits(); + /** @type {number} */ var minQuantum = deMath.deFloatLdExp(1.0, minExp - fractionBits); + /** @type {number} */ var minNormalized = deMath.deFloatLdExp(1.0, minExp); + /** @type {number} */ var maxQuantum = deMath.deFloatLdExp(1.0, maxExp - fractionBits); + + // If unit testing is enabled, include exact numbers + if (enableUnittests) { + dst.push(0.2); + dst.push(0.5); + } + + // NaN + dst.push(NaN); + // Zero + dst.push(0.0); + + for (var sign = -1; sign <= 1; sign += 2) { + // Smallest subnormal + dst.push(sign * minQuantum); + + // Largest subnormal + dst.push(sign * (minNormalized - minQuantum)); + + // Smallest normalized + dst.push(sign * minNormalized); + + // Next smallest normalized + dst.push(sign * (minNormalized + minQuantum)); + + dst.push(sign * 0.5); + dst.push(sign * 1.0); + dst.push(sign * 2.0); + + // Largest number + dst.push(sign * (deMath.deFloatLdExp(1.0, maxExp) + + (deMath.deFloatLdExp(1.0, maxExp) - maxQuantum))); + + dst.push(sign * Number.POSITIVE_INFINITY); + } + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.Sampling} + * @param {glsBuiltinPrecisionTests.Typename} typename + * @param {number} size + */ + glsBuiltinPrecisionTests.DefaultSamplingVector = function(typename, size) { + glsBuiltinPrecisionTests.Sampling.call(this, typename); + this.size = size; + }; + + glsBuiltinPrecisionTests.DefaultSamplingVector.prototype = Object.create(glsBuiltinPrecisionTests.Sampling.prototype); + glsBuiltinPrecisionTests.DefaultSamplingVector.prototype.constructor = glsBuiltinPrecisionTests.DefaultSamplingVector; + + glsBuiltinPrecisionTests.DefaultSamplingVector.prototype.genRandom = function(fmt, prec, rnd) { + /** @type {Array<*>} */ var ret = []; + + for (var ndx = 0; ndx < this.size; ++ndx) + ret[ndx] = glsBuiltinPrecisionTests.SamplingFactory(this.typename).genRandom(fmt, prec, rnd); + + return ret; + }; + + glsBuiltinPrecisionTests.DefaultSamplingVector.prototype.genFixeds = function(fmt, dst) { + /** @type {Array<*>} */ var scalars = []; + + glsBuiltinPrecisionTests.SamplingFactory(this.typename).genFixeds(fmt, scalars); + + for (var scalarNdx = 0; scalarNdx < scalars.length; ++scalarNdx) { + var value = []; + for (var i = 0; i < this.size; i++) + value[i] = scalars[scalarNdx]; + dst.push(value); + } + }; + + glsBuiltinPrecisionTests.DefaultSamplingVector.prototype.getWeight = function() { + return Math.pow(glsBuiltinPrecisionTests.SamplingFactory(this.typename).getWeight(), this.size); + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.Sampling} + * @param {glsBuiltinPrecisionTests.Typename} typename + * @param {number} rows + * @param {number} cols + */ + glsBuiltinPrecisionTests.DefaultSamplingMatrix = function(typename, rows, cols) { + glsBuiltinPrecisionTests.Sampling.call(this, typename); + this.rows = rows; + this.cols = cols; + }; + + glsBuiltinPrecisionTests.DefaultSamplingMatrix.prototype = Object.create(glsBuiltinPrecisionTests.Sampling.prototype); + glsBuiltinPrecisionTests.DefaultSamplingMatrix.prototype.constructor = glsBuiltinPrecisionTests.DefaultSamplingMatrix; + + glsBuiltinPrecisionTests.DefaultSamplingMatrix.prototype.genRandom = function(fmt, prec, rnd) { + /** @type {tcuMatrix.Matrix} */ var ret = new tcuMatrix.Matrix(this.rows, this.cols); + var sampler = glsBuiltinPrecisionTests.SamplingFactory(this.typename); + + for (var rowNdx = 0; rowNdx < this.rows; ++rowNdx) + for (var colNdx = 0; colNdx < this.cols; ++colNdx) + ret.set(rowNdx, colNdx, sampler.genRandom(fmt, prec, rnd)); + + return ret; + }; + + glsBuiltinPrecisionTests.DefaultSamplingMatrix.prototype.genFixeds = function(fmt, dst) { + /** @type {Array<number>} */ var scalars = []; + + glsBuiltinPrecisionTests.SamplingFactory(this.typename).genFixeds(fmt, scalars); + + for (var scalarNdx = 0; scalarNdx < scalars.length; ++scalarNdx) + dst.push(new tcuMatrix.Matrix(this.rows, this.cols, scalars[scalarNdx])); + + if (this.cols == this.rows) { + var mat = new tcuMatrix.Matrix(this.rows, this.cols, 0); + var x = 1; + mat.set(0, 0, x); + for (var ndx = 0; ndx < this.cols; ++ndx) { + mat.set(this.cols - 1 - ndx, ndx, x); + x *= 2; + } + dst.push(mat); + } + }; + + glsBuiltinPrecisionTests.DefaultSamplingMatrix.prototype.getWeight = function() { + return Math.pow(glsBuiltinPrecisionTests.SamplingFactory(this.typename).getWeight(), this.rows * this.cols); + }; + + /** + * @constructor + * @param {number=} size + * @param {glsBuiltinPrecisionTests.InTypes} In + */ + glsBuiltinPrecisionTests.Samplings = function(In, size) { + this.in0 = glsBuiltinPrecisionTests.SamplingFactory(In.In0, size); + this.in1 = glsBuiltinPrecisionTests.SamplingFactory(In.In1, size); + this.in2 = glsBuiltinPrecisionTests.SamplingFactory(In.In2, size); + this.in3 = glsBuiltinPrecisionTests.SamplingFactory(In.In3, size); + }; + + /** + * @param {glsBuiltinPrecisionTests.InTypes} In + * @param {number=} size + * @constructor + * @extends {glsBuiltinPrecisionTests.Samplings} + */ + glsBuiltinPrecisionTests.DefaultSamplings = function(In, size) { + glsBuiltinPrecisionTests.Samplings.call(this, In, size); + }; + + /** + * @constructor + * @extends {tcuTestCase.DeqpTest} + * @param {glsBuiltinPrecisionTests.Context} context + * @param {string} name + * @param {string} extension + */ + glsBuiltinPrecisionTests.PrecisionCase = function(context, name, extension) { + /** @type {string} */ this.m_extension = extension === undefined ? '' : extension; + /** @type {glsBuiltinPrecisionTests.Context} */ this.m_ctx = context; + /** @type {*} */ this.m_status; + /** @type {deRandom.Random} */ this.m_rnd = new deRandom.Random(1234); // (0xdeadbeefu + context.testContext.getCommandLine().getBaseSeed()) + tcuTestCase.DeqpTest.call(this, name, extension); + }; + + glsBuiltinPrecisionTests.PrecisionCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype); + glsBuiltinPrecisionTests.PrecisionCase.prototype.constructor = glsBuiltinPrecisionTests.PrecisionCase; + + /** + * @return {tcuFloatFormat.FloatFormat} + */ + glsBuiltinPrecisionTests.PrecisionCase.prototype.getFormat = function() { + return this.m_ctx.floatFormat; + }; + + /** + * Return an output value extracted from flat array + * @param {goog.NumberArray} output + * @param {number} index Index of the element to extract + * @param {*} reference Reference for type informaion + * @return {glsBuiltinPrecisionTests.Value} + */ + glsBuiltinPrecisionTests.getOutput = function(output, index, reference) { + if (reference instanceof Array) { + var ret = []; + var size = reference.length; + for (var i = 0; i < size; i++) + ret[i] = output[size * index + i]; + return ret; + } + if (reference instanceof tcuMatrix.Matrix) { + var ret = new tcuMatrix.Matrix(reference.rows, reference.cols); + var size = reference.rows * reference.cols; + for (var i = 0; i < reference.rows; i++) + for (var j = 0; j < reference.cols; j++) + ret.set(i, j, output[size * index + j * reference.rows + i]); + return ret; + } + + return output[index]; + }; + /** + * @param {glsBuiltinPrecisionTests.Variables} variables Variables<In, Out> + * @param {glsBuiltinPrecisionTests.Inputs} inputs Inputs<In> + * @param {glsBuiltinPrecisionTests.Statement} stmt + */ + glsBuiltinPrecisionTests.PrecisionCase.prototype.testStatement = function(variables, inputs, stmt) { + /** @type {tcuFloatFormat.FloatFormat} */ var fmt = this.getFormat(); + /** @type {number} */ var inCount = glsBuiltinPrecisionTests.numInputs(this.In); + /** @type {number} */ var outCount = glsBuiltinPrecisionTests.numOutputs(this.Out); + /** @type {number} */ var numValues = (inCount > 0) ? inputs.in0.length : 1; + /** @type {tcuFloatFormat.FloatFormat} */ var highpFmt = this.m_ctx.highpFormat; + var outputs = []; + /** @type {number} */ var maxMsgs = 100; + /** @type {number} */ var numErrors = 0; + /** @type {glsShaderExecUtil.ShaderSpec} */ var spec = new glsShaderExecUtil.ShaderSpec(); + /** @type {glsBuiltinPrecisionTests.Environment} */ var env = new glsBuiltinPrecisionTests.Environment(); // Hoisted out of the inner loop for optimization. + + switch (inCount) { + case 4: DE_ASSERT(inputs.in3.length == numValues); + case 3: DE_ASSERT(inputs.in2.length == numValues); + case 2: DE_ASSERT(inputs.in1.length == numValues); + case 1: DE_ASSERT(inputs.in0.length == numValues); + default: break; + } + if (enableUnittests) + numValues = 2; + + // TODO: Fix logging + //Print out the statement and its definitions + // bufferedLogToConsole("Statement: " + stmt); + // var funcInfo = '' + // var funcs = {}; + // stmt.getUsedFuncs(funcs); + // for (var key in funcs) { + // var func = funcs[key]; + // funcInfo += func.printDefinition(); + // }; + // if (funcInfo.length > 0) + // bufferedLogToConsole('Reference definitions:' + funcInfo); + + // Initialize ShaderSpec from precision, variables and statement. + + spec.globalDeclarations = 'precision ' + gluShaderUtil.getPrecisionName(this.m_ctx.precision) + ' float;\n'; + + if (this.m_extension.length > 0) + spec.globalDeclarations += '#extension ' + this.m_extension + ' : require\n'; + + spec.inputs = []; + + switch (inCount) { + case 4: spec.inputs[3] = this.makeSymbol(variables.in3); + case 3: spec.inputs[2] = this.makeSymbol(variables.in2); + case 2: spec.inputs[1] = this.makeSymbol(variables.in1); + case 1: spec.inputs[0] = this.makeSymbol(variables.in0); + default: break; + } + + spec.outputs = []; + + switch (outCount) { + case 2: spec.outputs[1] = this.makeSymbol(variables.out1); + case 1: spec.outputs[0] = this.makeSymbol(variables.out0); + default: break; + } + + spec.source = stmt; + + if (enableUnittests == false) { + // Run the shader with inputs. + /** @type {glsShaderExecUtil.ShaderExecutor} */ + var executor = glsShaderExecUtil.createExecutor(this.m_ctx.shaderType, spec); + /** @type {Array<*>} */ var inputArr = + [ + tcuMatrixUtil.flatten(inputs.in0), tcuMatrixUtil.flatten(inputs.in1), tcuMatrixUtil.flatten(inputs.in2), tcuMatrixUtil.flatten(inputs.in3) + ]; + + // executor.log(log()); + if (!executor.isOk()) + testFailed('Shader compilation failed'); + + executor.useProgram(); + var outputArray = executor.execute(numValues, inputArr); + + switch (outCount) { + case 2: + outputs[1] = glsBuiltinPrecisionTests.cast(this.Out.Out1, outputArray[1]); + case 1: + outputs[0] = glsBuiltinPrecisionTests.cast(this.Out.Out0, outputArray[0]); + default: break; + } + } + + // Initialize environment with dummy values so we don't need to bind in inner loop. + + var in0 = new tcuInterval.Interval(); + var in1 = new tcuInterval.Interval(); + var in2 = new tcuInterval.Interval(); + var in3 = new tcuInterval.Interval(); + var reference0 = new tcuInterval.Interval(); + var reference1 = new tcuInterval.Interval(); + + env.bind(variables.in0, in0); + env.bind(variables.in1, in1); + env.bind(variables.in2, in2); + env.bind(variables.in3, in3); + env.bind(variables.out0, reference0); + env.bind(variables.out1, reference1); + + // For each input tuple, compute output reference interval and compare + // shader output to the reference. + for (var valueNdx = 0; valueNdx < numValues; valueNdx++) { + /** @type {boolean} */ var result = true; + var value0, value1; + var msg = ''; + + var in0_ = glsBuiltinPrecisionTests.convert(this.Arg0, fmt, glsBuiltinPrecisionTests.round(this.Arg0, fmt, inputs.in0[valueNdx])); + var in1_ = glsBuiltinPrecisionTests.convert(this.Arg1, fmt, glsBuiltinPrecisionTests.round(this.Arg1, fmt, inputs.in1[valueNdx])); + var in2_ = glsBuiltinPrecisionTests.convert(this.Arg2, fmt, glsBuiltinPrecisionTests.round(this.Arg2, fmt, inputs.in2[valueNdx])); + var in3_ = glsBuiltinPrecisionTests.convert(this.Arg3, fmt, glsBuiltinPrecisionTests.round(this.Arg3, fmt, inputs.in3[valueNdx])); + + env.bind(variables.in0, in0_); + env.bind(variables.in1, in1_); + env.bind(variables.in2, in2_); + env.bind(variables.in3, in3_); + + stmt.execute(new glsBuiltinPrecisionTests.EvalContext(fmt, this.m_ctx.precision, env)); + + switch (outCount) { + case 2: + reference1 = glsBuiltinPrecisionTests.convert(this.Out.Out1, highpFmt, env.lookup(variables.out1)); + if (enableUnittests) + result = referenceComparison(reference1, valueNdx + outCount - 1, this.m_ctx.floatFormat); + else { + value1 = glsBuiltinPrecisionTests.getOutput(outputs[1], valueNdx, reference1); + if (!glsBuiltinPrecisionTests.contains(this.Out.Out1, reference1, value1)) { + msg = 'Shader output 1 (' + value1 + ') is outside acceptable range: ' + reference1; + result = false; + } + } + case 1: + reference0 = glsBuiltinPrecisionTests.convert(this.Out.Out0, highpFmt, env.lookup(variables.out0)); + if (enableUnittests) + result = referenceComparison(reference0, valueNdx + outCount - 1, this.m_ctx.floatFormat); + else { + value0 = glsBuiltinPrecisionTests.getOutput(outputs[0], valueNdx, reference0); + if (!glsBuiltinPrecisionTests.contains(this.Out.Out0, reference0, value0)) { + msg = 'Shader output 0 (' + value0 + ') is outside acceptable range: ' + reference0; + result = false; + } + } + default: break; + } + + if (!result) + ++numErrors; + + if (!result && numErrors <= maxMsgs) { + /** @type {string} */ var builder = ''; + + builder += (result ? 'Passed' : 'Failed') + '\n' + msg + '\n sample:\n' + valueNdx; + + if (inCount > 0) { + builder += '\t' + variables.in0.getName() + ' = ' + + inputs.in0[valueNdx] + '\n'; + } + + if (inCount > 1) { + builder += '\t' + variables.in1.getName() + ' = ' + + inputs.in1[valueNdx] + '\n'; + } + + if (inCount > 2) { + builder += '\t' + variables.in2.getName() + ' = ' + + inputs.in2[valueNdx] + '\n'; + } + + if (inCount > 3) { + builder += '\t' + variables.in3.getName() + ' = ' + + inputs.in3[valueNdx] + '\n'; + } + + if (enableUnittests == false) { + if (outCount > 0) { + builder += '\t' + variables.out0.getName() + ' = ' + + value0 + '\n' + + '\tExpected range: ' + + reference0 + '\n'; + } + + if (outCount > 1) { + builder += '\t' + variables.out1.getName() + ' = ' + + value1 + '\n' + + '\tExpected range: ' + + reference1 + '\n'; + } + } + bufferedLogToConsole(builder); + } + } + + if (numErrors > maxMsgs) { + bufferedLogToConsole('(Skipped ' + (numErrors - maxMsgs) + ' messages.)'); + } + + if (numErrors == 0) { + testPassed('All ' + numValues + ' inputs passed.'); + } else { + testFailed('' + numErrors + '/' + numValues + ' inputs failed.'); + } + }; + + /** + * @param {glsBuiltinPrecisionTests.Variable} variable Variable<typename> + * @return {glsShaderExecUtil.Symbol} + */ + glsBuiltinPrecisionTests.PrecisionCase.prototype.makeSymbol = function(variable) { + var v = variable; + return new glsShaderExecUtil.Symbol(v.getName(), gluVarType.getVarTypeOf(v.typename, this.m_size, this.m_ctx.precision)); + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.Tuple4} + * @param {*} in0 + * @param {*} in1 + * @param {*} in2 + * @param {*} in3 + */ + glsBuiltinPrecisionTests.InTuple = function(in0, in1, in2, in3) { + glsBuiltinPrecisionTests.Tuple4.call(this, in0, in1, in2, in3); + }; + + glsBuiltinPrecisionTests.InTuple.prototype = Object.create(glsBuiltinPrecisionTests.Tuple4.prototype); + glsBuiltinPrecisionTests.InTuple.prototype.constructor = glsBuiltinPrecisionTests.InTuple; + + /** + * @param {*} In + * @param {glsBuiltinPrecisionTests.Samplings} samplings Samplings<In> + * @param {tcuFloatFormat.FloatFormat} floatFormat + * @param {gluShaderUtil.precision} intPrecision + * @param {number} numSamples + * @param {deRandom.Random} rnd + * @return {glsBuiltinPrecisionTests.Inputs} + */ + glsBuiltinPrecisionTests.generateInputs = function(In, samplings, floatFormat, intPrecision, numSamples, rnd) { + /*Inputs<In>*/ var ret = new glsBuiltinPrecisionTests.Inputs(In); + /*Inputs<In>*/ var fixedInputs = new glsBuiltinPrecisionTests.Inputs(In); + // set<InTuple<In>, InputLess<InTuple<In> > > seenInputs; + /** @type {Array<glsBuiltinPrecisionTests.InTuple,glsBuiltinPrecisionTests.InputLess>} */ + var seenInputs = []; + + samplings.in0.genFixeds(floatFormat, fixedInputs.in0); + samplings.in1.genFixeds(floatFormat, fixedInputs.in1); + samplings.in2.genFixeds(floatFormat, fixedInputs.in2); + samplings.in3.genFixeds(floatFormat, fixedInputs.in3); + + for (var ndx0 = 0; ndx0 < fixedInputs.in0.length; ++ndx0) { + for (var ndx1 = 0; ndx1 < fixedInputs.in1.length; ++ndx1) { + for (var ndx2 = 0; ndx2 < fixedInputs.in2.length; ++ndx2) { + for (var ndx3 = 0; ndx3 < fixedInputs.in3.length; ++ndx3) { + var tuple = new glsBuiltinPrecisionTests.InTuple(fixedInputs.in0[ndx0], + fixedInputs.in1[ndx1], + fixedInputs.in2[ndx2], + fixedInputs.in3[ndx3]); + + seenInputs.push(tuple); + ret.in0.push(tuple.a); + ret.in1.push(tuple.b); + ret.in2.push(tuple.c); + ret.in3.push(tuple.d); + } + } + } + } + + for (var ndx = 0; ndx < numSamples; ++ndx) { + var in0 = samplings.in0.genRandom(floatFormat, intPrecision, rnd); + var in1 = samplings.in1.genRandom(floatFormat, intPrecision, rnd); + var in2 = samplings.in2.genRandom(floatFormat, intPrecision, rnd); + var in3 = samplings.in3.genRandom(floatFormat, intPrecision, rnd); + var tuple = new glsBuiltinPrecisionTests.InTuple(in0, in1, in2, in3); + + // if (de::contains(seenInputs, tuple)) + // continue; + + seenInputs.push(tuple); + ret.in0.push(in0); + ret.in1.push(in1); + ret.in2.push(in2); + ret.in3.push(in3); + } + + return ret; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.PrecisionCase} + * @param {string} name + * @param {glsBuiltinPrecisionTests.FuncBase} func + */ + glsBuiltinPrecisionTests.FuncCaseBase = function(context, name, func) { + glsBuiltinPrecisionTests.PrecisionCase.call(this, context, name, func.getRequiredExtension()); + }; + + glsBuiltinPrecisionTests.FuncCaseBase.prototype = Object.create(glsBuiltinPrecisionTests.PrecisionCase.prototype); + glsBuiltinPrecisionTests.FuncCaseBase.prototype.constructor = glsBuiltinPrecisionTests.FuncCaseBase; + + glsBuiltinPrecisionTests.FuncCaseBase.prototype.iterate = function() { + + assertMsgOptions(!(this.m_extension !== undefined && this.m_extension.trim() !== '') && + !sglrGLContext.isExtensionSupported(gl, this.m_extension), + 'Unsupported extension: ' + this.m_extension, false, true); + + this.runTest(); + + // m_status.setTestContextResult(m_testCtx); + return tcuTestCase.IterateResult.STOP; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.FuncCaseBase} + * @param {glsBuiltinPrecisionTests.Context} context + * @param {string} name + * @param {glsBuiltinPrecisionTests.Func} func + */ + glsBuiltinPrecisionTests.InOutFuncCase = function(context, name, func) { + glsBuiltinPrecisionTests.FuncCaseBase.call(this, context, name, func); + this.Sig = func.Sig; + this.m_func = func; + this.Ret = func.Sig.Ret; + this.Arg0 = func.Sig.Arg0; + this.Arg1 = func.Sig.Arg1; + this.Arg2 = func.Sig.Arg2; + this.Arg3 = func.Sig.Arg3; + this.In = new glsBuiltinPrecisionTests.InTypes(this.Arg0, this.Arg2, this.Arg3); + this.Out = new glsBuiltinPrecisionTests.OutTypes(this.Ret, this.Arg1); + this.m_size = this.m_func.m_size; + }; + + glsBuiltinPrecisionTests.InOutFuncCase.prototype = Object.create(glsBuiltinPrecisionTests.FuncCaseBase.prototype); + glsBuiltinPrecisionTests.InOutFuncCase.prototype.constructor = glsBuiltinPrecisionTests.InOutFuncCase; + + /** + * Samplings<In> + * @return {glsBuiltinPrecisionTests.Samplings} + */ + glsBuiltinPrecisionTests.InOutFuncCase.prototype.getSamplings = function() { + return new glsBuiltinPrecisionTests.DefaultSamplings(this.In, this.m_size); + }; + + /** + * @param {glsBuiltinPrecisionTests.Signature} Sig_ + */ + glsBuiltinPrecisionTests.InOutFuncCase.prototype.runTest = function(Sig_) { + /** @type {glsBuiltinPrecisionTests.Inputs} */ var inputs = (glsBuiltinPrecisionTests.generateInputs( + this.In, + this.getSamplings(), + this.m_ctx.floatFormat, + this.m_ctx.precision, + this.m_ctx.numRandoms, + this.m_rnd)); + + var variables = new glsBuiltinPrecisionTests.Variables(this.In, this.Out); + // Variables<In, Out> variables; + // + variables.out0 = new glsBuiltinPrecisionTests.Variable(this.Out.Out0, 'out0'); + variables.out1 = new glsBuiltinPrecisionTests.Variable(this.Arg1, 'out1'); + variables.in0 = new glsBuiltinPrecisionTests.Variable(this.Arg0, 'in0'); + variables.in1 = new glsBuiltinPrecisionTests.Variable(this.Arg2, 'in1'); + variables.in2 = new glsBuiltinPrecisionTests.Variable(this.Arg3, 'in2'); + variables.in3 = new glsBuiltinPrecisionTests.Variable('void', 'in3'); + + var expr = glsBuiltinPrecisionTests.applyVar(this.m_func, + variables.in0, variables.out1, + variables.in1, variables.in2); + var stmt = glsBuiltinPrecisionTests.variableAssignment(variables.out0, expr); + + this.testStatement(variables, inputs, stmt); + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.FuncCaseBase} + * @param {glsBuiltinPrecisionTests.Context} context + * @param {string} name + * @param {glsBuiltinPrecisionTests.Func} func + */ + glsBuiltinPrecisionTests.FuncCase = function(context, name, func) { + glsBuiltinPrecisionTests.FuncCaseBase.call(this, context, name, func); + this.Sig = func.Sig; + this.m_func = func; + this.Ret = func.Sig.Ret; + this.Arg0 = func.Sig.Arg0; + this.Arg1 = func.Sig.Arg1; + this.Arg2 = func.Sig.Arg2; + this.Arg3 = func.Sig.Arg3; + this.In = new glsBuiltinPrecisionTests.InTypes(this.Arg0, this.Arg1, this.Arg2, this.Arg3); + this.Out = new glsBuiltinPrecisionTests.OutTypes(this.Ret); + this.m_size = this.m_func.m_size; + }; + + glsBuiltinPrecisionTests.FuncCase.prototype = Object.create(glsBuiltinPrecisionTests.FuncCaseBase.prototype); + glsBuiltinPrecisionTests.FuncCase.prototype.constructor = glsBuiltinPrecisionTests.FuncCase; + + /** + * Samplings<In> + * @return {glsBuiltinPrecisionTests.Samplings} + */ + glsBuiltinPrecisionTests.FuncCase.prototype.getSamplings = function() { + return new glsBuiltinPrecisionTests.DefaultSamplings(this.In, this.m_size); + }; + + /** + * @param {glsBuiltinPrecisionTests.Signature} Sig_ + */ + glsBuiltinPrecisionTests.FuncCase.prototype.runTest = function(Sig_) { + /** @type {glsBuiltinPrecisionTests.Inputs} */ var inputs = (glsBuiltinPrecisionTests.generateInputs( + this.In, + this.getSamplings(), + this.m_ctx.floatFormat, + this.m_ctx.precision, + this.m_ctx.numRandoms, + this.m_rnd)); + + var variables = new glsBuiltinPrecisionTests.Variables(this.In, this.Out); + // Variables<In, Out> variables; + // + variables.out0 = new glsBuiltinPrecisionTests.Variable(this.Ret, 'out0'); + variables.out1 = new glsBuiltinPrecisionTests.Variable('void', 'out1'); + variables.in0 = new glsBuiltinPrecisionTests.Variable(this.Arg0, 'in0'); + variables.in1 = new glsBuiltinPrecisionTests.Variable(this.Arg1, 'in1'); + variables.in2 = new glsBuiltinPrecisionTests.Variable(this.Arg2, 'in2'); + variables.in3 = new glsBuiltinPrecisionTests.Variable(this.Arg3, 'in3'); + + var expr = glsBuiltinPrecisionTests.applyVar(this.m_func, + variables.in0, variables.in1, + variables.in2, variables.in3); + var stmt = glsBuiltinPrecisionTests.variableAssignment(variables.out0, expr); + + this.testStatement(variables, inputs, stmt); + }; + + /** + * @param {glsBuiltinPrecisionTests.Func} func + * @param {glsBuiltinPrecisionTests.Variable} arg0 + * @param {glsBuiltinPrecisionTests.Variable} arg1 + * @param {glsBuiltinPrecisionTests.Variable} arg2 + * @param {glsBuiltinPrecisionTests.Variable} arg3 + * @return {glsBuiltinPrecisionTests.ApplyVar} + */ + glsBuiltinPrecisionTests.applyVar = function(func, arg0, arg1, arg2, arg3) { + return new glsBuiltinPrecisionTests.ApplyVar(func.Sig, func, arg0, arg1, arg2, arg3); + }; + + /** + * @param {glsBuiltinPrecisionTests.Variable} variable + * @param {glsBuiltinPrecisionTests.ApplyVar} value + * @param {boolean} isDeclaration + */ + glsBuiltinPrecisionTests.variableStatement = function(variable, value, isDeclaration) { + return new glsBuiltinPrecisionTests.VariableStatement(variable, value, isDeclaration); + }; + + /** + * @param {glsBuiltinPrecisionTests.Variable} variable + * @param {glsBuiltinPrecisionTests.ApplyVar} value + */ + glsBuiltinPrecisionTests.variableAssignment = function(variable, value) { + return glsBuiltinPrecisionTests.variableStatement(variable, value, false); + }; + + /** + * @constructor + */ + glsBuiltinPrecisionTests.CaseFactories = function() {}; + + /** + * @return {Array<glsBuiltinPrecisionTests.CaseFactory>} + */ + glsBuiltinPrecisionTests.CaseFactories.prototype.getFactories = function() {}; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.CaseFactories} + */ + glsBuiltinPrecisionTests.BuiltinFuncs = function() { + /** @type {Array<glsBuiltinPrecisionTests.CaseFactory>} */ this.m_factories = []; + }; + + glsBuiltinPrecisionTests.BuiltinFuncs.prototype = Object.create(glsBuiltinPrecisionTests.CaseFactories.prototype); + glsBuiltinPrecisionTests.BuiltinFuncs.prototype.constructor = glsBuiltinPrecisionTests.BuiltinFuncs; + + /** + * @return {Array<glsBuiltinPrecisionTests.CaseFactory>} + */ + glsBuiltinPrecisionTests.BuiltinFuncs.prototype.getFactories = function() { + return this.m_factories.slice(); + }; + + /** + * @param {glsBuiltinPrecisionTests.CaseFactory} fact + */ + glsBuiltinPrecisionTests.BuiltinFuncs.prototype.addFactory = function(fact) { + this.m_factories.push(fact); + }; + + /** + * @param {glsBuiltinPrecisionTests.Context} context + * @param {string} name + * @param {glsBuiltinPrecisionTests.Func} func + * @return {glsBuiltinPrecisionTests.PrecisionCase} + */ + glsBuiltinPrecisionTests.createFuncCase = function(context, name, func) { + switch (func.getOutParamIndex()) { + case -1: + return new glsBuiltinPrecisionTests.FuncCase(context, name, func); + case 1: + return new glsBuiltinPrecisionTests.InOutFuncCase(context, name, func); + default: + throw new Error(!'Impossible'); + } + }; + + /** + * @constructor + */ + glsBuiltinPrecisionTests.CaseFactory = function() {}; + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.CaseFactory.prototype.getName = function() { + return ''; + }; + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.CaseFactory.prototype.getDesc = function() { + return ''; + }; + + /** + * @param {glsBuiltinPrecisionTests.Context} ctx + */ + glsBuiltinPrecisionTests.CaseFactory.prototype.createCase = function(ctx) { + throw new Error('Virtual function. Please override.'); + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.CaseFactory} + * @param {glsBuiltinPrecisionTests.Func} func + */ + glsBuiltinPrecisionTests.SimpleFuncCaseFactory = function(func) { + glsBuiltinPrecisionTests.CaseFactory.call(this); + this.m_func = func; + }; + + setParentClass(glsBuiltinPrecisionTests.SimpleFuncCaseFactory, glsBuiltinPrecisionTests.CaseFactory); + + glsBuiltinPrecisionTests.SimpleFuncCaseFactory.prototype.getName = function() { + return this.m_func.getName().toLowerCase(); + }; + + glsBuiltinPrecisionTests.SimpleFuncCaseFactory.prototype.getDesc = function() { + return "Function '" + this.getName() + "'"; + }; + + glsBuiltinPrecisionTests.SimpleFuncCaseFactory.prototype.createCase = function(ctx) { + return glsBuiltinPrecisionTests.createFuncCase(ctx, ctx.name, this.m_func); + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.CaseFactory} + */ + glsBuiltinPrecisionTests.FuncCaseFactory = function() { + glsBuiltinPrecisionTests.CaseFactory.call(this); + }; + + setParentClass(glsBuiltinPrecisionTests.FuncCaseFactory, glsBuiltinPrecisionTests.CaseFactory); + + glsBuiltinPrecisionTests.FuncCaseFactory.prototype.getFunc = function() { + throw new Error('Virtual function. Please override.'); + }; + + glsBuiltinPrecisionTests.FuncCaseFactory.prototype.getName = function() { + return this.getFunc().getName().toLowerCase(); + }; + + glsBuiltinPrecisionTests.FuncCaseFactory.prototype.getDesc = function() { + return "Function '" + this.getFunc().getName() + "'"; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.FuncCaseFactory} + */ + glsBuiltinPrecisionTests.TemplateFuncCaseFactory = function(genF) { + glsBuiltinPrecisionTests.FuncCaseFactory.call(this); + this.m_genF = genF; + }; + + setParentClass(glsBuiltinPrecisionTests.TemplateFuncCaseFactory, glsBuiltinPrecisionTests.FuncCaseFactory); + + glsBuiltinPrecisionTests.TemplateFuncCaseFactory.prototype.getFunc = function() { + return new this.m_genF(1); + }; + + /** + * @param {glsBuiltinPrecisionTests.Context} ctx + */ + glsBuiltinPrecisionTests.TemplateFuncCaseFactory.prototype.createCase = function(ctx) { + var group = tcuTestCase.newTest(ctx.name, ctx.name); + group.addChild(glsBuiltinPrecisionTests.createFuncCase(ctx, 'scalar', new this.m_genF(1))); + group.addChild(glsBuiltinPrecisionTests.createFuncCase(ctx, 'vec2', new this.m_genF(2))); + group.addChild(glsBuiltinPrecisionTests.createFuncCase(ctx, 'vec3', new this.m_genF(3))); + group.addChild(glsBuiltinPrecisionTests.createFuncCase(ctx, 'vec4', new this.m_genF(4))); + + return group; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.FuncCaseFactory} + */ + glsBuiltinPrecisionTests.MatrixFuncCaseFactory = function(genF) { + glsBuiltinPrecisionTests.FuncCaseFactory.call(this); + this.m_genF = genF; + }; + + setParentClass(glsBuiltinPrecisionTests.MatrixFuncCaseFactory, glsBuiltinPrecisionTests.FuncCaseFactory); + + glsBuiltinPrecisionTests.MatrixFuncCaseFactory.prototype.getFunc = function() { + return new this.m_genF(2, 2); + }; + + /** + * @param {glsBuiltinPrecisionTests.Context} ctx + */ + glsBuiltinPrecisionTests.MatrixFuncCaseFactory.prototype.createCase = function(ctx) { + var group = tcuTestCase.newTest(ctx.name, ctx.name); + this.addCase(ctx, group, 2, 2); + this.addCase(ctx, group, 3, 2); + this.addCase(ctx, group, 4, 2); + this.addCase(ctx, group, 2, 3); + this.addCase(ctx, group, 3, 3); + this.addCase(ctx, group, 4, 3); + this.addCase(ctx, group, 2, 4); + this.addCase(ctx, group, 3, 4); + this.addCase(ctx, group, 4, 4); + + return group; + }; + + /** + * @param {glsBuiltinPrecisionTests.Context} ctx + * @param {tcuTestCase.DeqpTest} group + * @param {number} rows + * @param {number} cols + */ + glsBuiltinPrecisionTests.MatrixFuncCaseFactory.prototype.addCase = function(ctx, group, rows, cols) { + var name = glsBuiltinPrecisionTests.dataTypeNameOfMatrix('float', rows, cols); + group.addChild(glsBuiltinPrecisionTests.createFuncCase(ctx, name, new this.m_genF(rows, cols))); + }; + + glsBuiltinPrecisionTests.dataTypeNameOfMatrix = function(typename, rows, cols) { + switch (typename) { + case 'float': + if (rows === cols) + return 'mat' + rows; + else + return 'mat' + cols + 'x' + rows; + } + throw new Error('Invalid arguments (' + typename + ', ' + rows + ', ' + cols + ')'); + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.FuncCaseFactory} + */ + glsBuiltinPrecisionTests.SquareMatrixFuncCaseFactory = function(genF) { + glsBuiltinPrecisionTests.FuncCaseFactory.call(this); + this.m_genF = genF; + }; + + setParentClass(glsBuiltinPrecisionTests.SquareMatrixFuncCaseFactory, glsBuiltinPrecisionTests.FuncCaseFactory); + + glsBuiltinPrecisionTests.SquareMatrixFuncCaseFactory.prototype.getFunc = function() { + return new this.m_genF(2); + }; + + /** + * @param {glsBuiltinPrecisionTests.Context} ctx + */ + glsBuiltinPrecisionTests.SquareMatrixFuncCaseFactory.prototype.createCase = function(ctx) { + var group = tcuTestCase.newTest(ctx.name, ctx.name); + + group.addChild(glsBuiltinPrecisionTests.createFuncCase(ctx, 'mat2', new this.m_genF(2))); + return group; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.PrimitiveFunc} + * @param {glsBuiltinPrecisionTests.Func} scalarFunc + * @param {number=} size + */ + glsBuiltinPrecisionTests.GenFunc = function(scalarFunc, size) { + glsBuiltinPrecisionTests.PrimitiveFunc.call(this, scalarFunc.Sig); + this.m_func = scalarFunc; + this.m_size = size; + }; + + glsBuiltinPrecisionTests.GenFunc.prototype = Object.create(glsBuiltinPrecisionTests.PrimitiveFunc.prototype); + glsBuiltinPrecisionTests.GenFunc.prototype.constructor = glsBuiltinPrecisionTests.GenFunc; + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.GenFunc.prototype.getName = function() { + return this.m_func.getName(); + }; + + /** + * @return {number} + */ + glsBuiltinPrecisionTests.GenFunc.prototype.getOutParamIndex = function() { + return this.m_func.getOutParamIndex(); + }; + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.GenFunc.prototype.getRequiredExtension = function() { + return this.m_func.getRequiredExtension(); + }; + + /** + * @param {Array<glsBuiltinPrecisionTests.ExprBase>} args + */ + glsBuiltinPrecisionTests.GenFunc.prototype.doPrint = function(args) { + return this.m_func.print(args); + }; + + /** + * @param {glsBuiltinPrecisionTests.EvalContext} ctx + * @param {glsBuiltinPrecisionTests.Tuple4} iargs + * @return {*} + */ + glsBuiltinPrecisionTests.GenFunc.prototype.doApply = function(ctx, iargs) { + /** @type {Array<*>} */ var ret = []; + + if (this.m_size > 1) { + for (var ndx = 0; ndx < this.m_size; ++ndx) { + var a = iargs.a === undefined ? undefined : iargs.a[ndx]; + var b = iargs.b === undefined ? undefined : iargs.b[ndx]; + var c = iargs.c === undefined ? undefined : iargs.c[ndx]; + var d = iargs.d === undefined ? undefined : iargs.d[ndx]; + ret[ndx] = this.m_func.applyFunction(ctx, a, b, c, d); + } + } else + ret[0] = this.m_func.applyFunction(ctx, iargs.a, iargs.b, iargs.c, iargs.d); + + return ret; + }; + + /** + * @param {glsBuiltinPrecisionTests.FuncSet} dst + */ + glsBuiltinPrecisionTests.GenFunc.prototype.doGetUsedFuncs = function(dst) { + this.m_func.getUsedFuncs(dst); + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.GenFunc} + * @param {glsBuiltinPrecisionTests.Func} func + * @param {number} size + */ + glsBuiltinPrecisionTests.VectorizedFunc = function(func, size) { + glsBuiltinPrecisionTests.GenFunc.call(this, func, size); + }; + + glsBuiltinPrecisionTests.VectorizedFunc.prototype = Object.create(glsBuiltinPrecisionTests.GenFunc.prototype); + glsBuiltinPrecisionTests.VectorizedFunc.prototype.constructor = glsBuiltinPrecisionTests.VectorizedFunc; + + /** + * @constructor + * @param {glsBuiltinPrecisionTests.Func} func_ + * @param {glsBuiltinPrecisionTests.GenFunc} func2_ + * @param {glsBuiltinPrecisionTests.GenFunc} func3_ + * @param {glsBuiltinPrecisionTests.GenFunc} func4_ + */ + glsBuiltinPrecisionTests.GenFuncs = function(func_, func2_, func3_, func4_) { + this.func = func_; + this.func2 = func2_; + this.func3 = func3_; + this.func4 = func4_; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.CaseFactory} + * @param {glsBuiltinPrecisionTests.GenFuncs} funcs + * @param {string} name + */ + glsBuiltinPrecisionTests.GenFuncCaseFactory = function(funcs, name) { + glsBuiltinPrecisionTests.CaseFactory.call(this); + this.m_funcs = funcs; + this.m_name = name; + }; + + glsBuiltinPrecisionTests.GenFuncCaseFactory.prototype = Object.create(glsBuiltinPrecisionTests.CaseFactory.prototype); + glsBuiltinPrecisionTests.GenFuncCaseFactory.prototype.constructor = glsBuiltinPrecisionTests.GenFuncCaseFactory; + + /** + * @param {glsBuiltinPrecisionTests.Context} ctx + * @return {tcuTestCase.DeqpTest} + */ + glsBuiltinPrecisionTests.GenFuncCaseFactory.prototype.createCase = function(ctx) { + /** @type {tcuTestCase.DeqpTest} */ + var group = tcuTestCase.newTest(ctx.name, ctx.name); + group.addChild(glsBuiltinPrecisionTests.createFuncCase(ctx, 'scalar', this.m_funcs.func)); + group.addChild(glsBuiltinPrecisionTests.createFuncCase(ctx, 'vec2', this.m_funcs.func2)); + group.addChild(glsBuiltinPrecisionTests.createFuncCase(ctx, 'vec3', this.m_funcs.func3)); + group.addChild(glsBuiltinPrecisionTests.createFuncCase(ctx, 'vec4', this.m_funcs.func4)); + + return group; + }; + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.GenFuncCaseFactory.prototype.getName = function() { + return this.m_name; + }; + + /** + * @return {string} + */ + glsBuiltinPrecisionTests.GenFuncCaseFactory.prototype.getDesc = function() { + return "Function '" + this.m_funcs.func.getName() + "'"; + }; + + /** + * @constructor + * @param {string} name_ + * @param {tcuFloatFormat.FloatFormat} floatFormat_ + * @param {tcuFloatFormat.FloatFormat} highpFormat_ + * @param {gluShaderUtil.precision} precision_ + * @param {gluShaderProgram.shaderType} shaderType_ + * @param {number} numRandoms_ + */ + glsBuiltinPrecisionTests.Context = function(name_, floatFormat_, highpFormat_, precision_, shaderType_, numRandoms_) { + /** @type {string} */ this.name = name_; + /** @type {tcuFloatFormat.FloatFormat} */ this.floatFormat = floatFormat_; + /** @type {tcuFloatFormat.FloatFormat} */ this.highpFormat = highpFormat_; + /** @type {gluShaderUtil.precision} */ this.precision = precision_; + /** @type {gluShaderProgram.shaderType} */ this.shaderType = shaderType_; + /** @type {number} */ this.numRandoms = numRandoms_; + }; + + /** + * @constructor + * @param {tcuFloatFormat.FloatFormat} highp_ + * @param {tcuFloatFormat.FloatFormat} mediump_ + * @param {tcuFloatFormat.FloatFormat} lowp_ + * @param {Array<gluShaderProgram.shaderType>} shaderTypes_ + * @param {number} numRandoms_ + */ + glsBuiltinPrecisionTests.PrecisionTestContext = function(highp_, mediump_, lowp_, shaderTypes_, numRandoms_) { + /** @type {Array<gluShaderProgram.shaderType>} */ this.shaderTypes = shaderTypes_; + /** @type {Array<tcuFloatFormat.FloatFormat>} */ this.formats = []; + this.formats[gluShaderUtil.precision.PRECISION_HIGHP] = highp_; + this.formats[gluShaderUtil.precision.PRECISION_MEDIUMP] = mediump_; + this.formats[gluShaderUtil.precision.PRECISION_LOWP] = lowp_; + /** @type {number} */ this.numRandoms = numRandoms_; + }; + + /** + * \brief Simple incremental counter. + * + * This is used to make sure that different ExpandContexts will not produce + * overlapping temporary names. + * @constructor + * + */ + glsBuiltinPrecisionTests.Counter = function() { + this.m_count = 0; + }; + + glsBuiltinPrecisionTests.Counter.prototype.get = function() { + return this.m_count++; + }; + + /** + * @constructor + */ + glsBuiltinPrecisionTests.ExpandContext = function(counter) { + this.m_counter = counter; + this.m_statements = []; + }; + + /** + * @param {string} typename + * @param {string} baseName + * @return {glsBuiltinPrecisionTests.Variable} + */ + glsBuiltinPrecisionTests.ExpandContext.prototype.genSym = function(typename, baseName) { + return new glsBuiltinPrecisionTests.Variable(typename, baseName + this.m_counter.get()); + }; + + glsBuiltinPrecisionTests.ExpandContext.prototype.addStatement = function(/*const StatementP&*/ stmt) { + this.m_statements.push(stmt); + }; + + glsBuiltinPrecisionTests.ExpandContext.prototype.getStatements = function() { + return this.m_statements; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.Func} + * @param {glsBuiltinPrecisionTests.Signature} Sig_ template <typename Sig_> + */ + glsBuiltinPrecisionTests.DerivedFunc = function(Sig_) { + glsBuiltinPrecisionTests.Func.call(this, Sig_); + }; + + setParentClass(glsBuiltinPrecisionTests.DerivedFunc, glsBuiltinPrecisionTests.Func); + + glsBuiltinPrecisionTests.DerivedFunc.prototype.doPrintDefinition = function() { + var os = ''; + var paramNames = this.getParamNames(); + + this.initialize(); + + os += this.Ret + ' ' + this.getName() + + '('; + if (glsBuiltinPrecisionTests.isTypeValid(this.Arg0)) + os += this.Arg0 + ' ' + paramNames.a; + if (glsBuiltinPrecisionTests.isTypeValid(this.Arg1)) + os += ', ' + this.Arg1 + ' ' + paramNames.b; + if (glsBuiltinPrecisionTests.isTypeValid(this.Arg2)) + os += ', ' + this.Arg2 + ' ' + paramNames.c; + if (glsBuiltinPrecisionTests.isTypeValid(this.Arg3)) + os += ', ' + this.Arg3 + ' ' + paramNames.d; + os += ')\n{\n'; + + for (var ndx = 0; ndx < this.m_body.length; ++ndx) + os += this.m_body[ndx]; + os += 'return ' + this.m_ret + ';\n'; + os += '}\n'; + + return os; + }; + + glsBuiltinPrecisionTests.DerivedFunc.prototype.doApply = function(ctx, args) { + var funEnv = new glsBuiltinPrecisionTests.Environment(); + this.initialize(); + + funEnv.bind(this.m_var0, args.a); + funEnv.bind(this.m_var1, args.b); + funEnv.bind(this.m_var2, args.c); + funEnv.bind(this.m_var3, args.d); + + var funCtx = new glsBuiltinPrecisionTests.EvalContext(ctx.format, ctx.floatPrecision, funEnv, ctx.callDepth); + + for (var ndx = 0; ndx < this.m_body.length; ++ndx) + this.m_body[ndx].execute(funCtx); + + var ret = this.m_ret.evaluate(funCtx); + + // \todo [lauri] Store references instead of values in environment + args.a = funEnv.lookup(this.m_var0); + args.b = funEnv.lookup(this.m_var1); + args.c = funEnv.lookup(this.m_var2); + args.d = funEnv.lookup(this.m_var3); + + return ret; + }; + + glsBuiltinPrecisionTests.DerivedFunc.prototype.initialize = function() { + if (!this.m_ret) { + var paramNames = this.getParamNames(); + var symCounter = new glsBuiltinPrecisionTests.Counter(); + var ctx = new glsBuiltinPrecisionTests.ExpandContext(symCounter); + + this.m_var0 = new glsBuiltinPrecisionTests.Variable(this.Arg0, paramNames.a); + this.m_var1 = new glsBuiltinPrecisionTests.Variable(this.Arg1, paramNames.b); + this.m_var2 = new glsBuiltinPrecisionTests.Variable(this.Arg2, paramNames.c); + this.m_var3 = new glsBuiltinPrecisionTests.Variable(this.Arg3, paramNames.d); + var args = new glsBuiltinPrecisionTests.Tuple4(this.m_var0, + this.m_var1, this.m_var2, this.m_var3); + + this.m_ret = this.doExpand(ctx, args); + this.m_body = ctx.getStatements(); + } + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.Func} + * @param {glsBuiltinPrecisionTests.Signature} Sig_ template <typename Sig_> + */ + glsBuiltinPrecisionTests.Alternatives = function(Sig_) { + glsBuiltinPrecisionTests.Func.call(this, Sig_); + }; + + setParentClass(glsBuiltinPrecisionTests.Alternatives,glsBuiltinPrecisionTests.Func); + + glsBuiltinPrecisionTests.Alternatives.prototype.getName = function() { + return 'alternatives'; + }; + + glsBuiltinPrecisionTests.Alternatives.prototype.doPrintDefinition = function() {}; + + glsBuiltinPrecisionTests.Alternatives.prototype.doGetUsedFuncs = function(dst) {}; + + glsBuiltinPrecisionTests.Alternatives.prototype.doApply = function(ctx,args) { + return glsBuiltinPrecisionTests.union(this.Sig.Ret,args.a,args.b); + }; + + glsBuiltinPrecisionTests.Alternatives.prototype.doPrint = function(args) { + return '{' + args[0] + '|' + args[1] + '}'; + }; + + glsBuiltinPrecisionTests.sizeToName = function(size) { + switch (size) { + case 4: return 'vec4'; + case 3: return 'vec3'; + case 2: return 'vec2'; + } + return 'float'; + }; + + /** + * @constructor + * @param {number} size + * @extends {glsBuiltinPrecisionTests.DerivedFunc} + */ + glsBuiltinPrecisionTests.Dot = function(size) { + var name = glsBuiltinPrecisionTests.sizeToName(size); + var sig = new glsBuiltinPrecisionTests.Signature('float', name, name); + glsBuiltinPrecisionTests.DerivedFunc.call(this, sig); + this.m_inputSize = size; + }; + + setParentClass(glsBuiltinPrecisionTests.Dot, glsBuiltinPrecisionTests.DerivedFunc); + + glsBuiltinPrecisionTests.Dot.prototype.getName = function() { + return 'dot'; + }; + + glsBuiltinPrecisionTests.Dot.prototype.doExpand = function(ctx, args) { + if (this.m_inputSize > 1) { + var val = app(new glsBuiltinPrecisionTests.Mul(), + new glsBuiltinPrecisionTests.VectorVariable(args.a, 0), new glsBuiltinPrecisionTests.VectorVariable(args.b, 0)); + for (var i = 1; i < this.m_inputSize; i++) { + var tmp = new glsBuiltinPrecisionTests.Apply('float', new glsBuiltinPrecisionTests.Mul(), + new glsBuiltinPrecisionTests.VectorVariable(args.a, i), new glsBuiltinPrecisionTests.VectorVariable(args.b, i)); + val = app(new glsBuiltinPrecisionTests.Add(), val, tmp); + } + return val; + } else { + // args.a * args.b + var ret = app(new glsBuiltinPrecisionTests.Mul(), args.a, args.b); + return ret; + } + }; + + /** + * @constructor + * @param {number} size + * @extends {glsBuiltinPrecisionTests.DerivedFunc} + */ + glsBuiltinPrecisionTests.Length = function(size) { + var name = glsBuiltinPrecisionTests.sizeToName(size); + var sig = new glsBuiltinPrecisionTests.Signature('float', name); + glsBuiltinPrecisionTests.DerivedFunc.call(this, sig); + this.m_inputSize = size; + }; + + setParentClass(glsBuiltinPrecisionTests.Length, glsBuiltinPrecisionTests.DerivedFunc); + + glsBuiltinPrecisionTests.Length.prototype.getName = function() { + return 'length'; + }; + + glsBuiltinPrecisionTests.Length.prototype.doExpand = function(ctx, args) { + //sqrt(dot(args.a, args.a)); + var v0 = app(new glsBuiltinPrecisionTests.Dot(this.m_inputSize), args.a, args.a); + var v1 = app(new glsBuiltinPrecisionTests.Sqrt(), v0); + return v1; + }; + + /** + * @constructor + * @param {number} size + * @extends {glsBuiltinPrecisionTests.DerivedFunc} + */ + glsBuiltinPrecisionTests.Distance = function(size) { + var name = glsBuiltinPrecisionTests.sizeToName(size); + var sig = new glsBuiltinPrecisionTests.Signature('float', name, name); + glsBuiltinPrecisionTests.DerivedFunc.call(this, sig); + this.m_inputSize = size; + }; + + setParentClass(glsBuiltinPrecisionTests.Distance, glsBuiltinPrecisionTests.DerivedFunc); + + glsBuiltinPrecisionTests.Distance.prototype.getName = function() { + return 'distance'; + }; + + glsBuiltinPrecisionTests.Distance.prototype.doExpand = function(ctx, args) { + //length(args.a - args.b); + var v0 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Sub(), args.a, args.b); + var v1 = app(new glsBuiltinPrecisionTests.Length(this.m_inputSize), v0); + return v1; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.DerivedFunc} + */ + glsBuiltinPrecisionTests.Cross = function() { + var sig = new glsBuiltinPrecisionTests.Signature('vec3', 'vec3', 'vec3'); + glsBuiltinPrecisionTests.DerivedFunc.call(this, sig); + this.m_inputSize = 3; + }; + + setParentClass(glsBuiltinPrecisionTests.Cross, glsBuiltinPrecisionTests.DerivedFunc); + + glsBuiltinPrecisionTests.Cross.prototype.getName = function() { + return 'cross'; + }; + + glsBuiltinPrecisionTests.Cross.prototype.doExpand = function(ctx, args) { + // vec3(x.a[1] * x.b[2] - x.b[1] * x.a[2], + // x.a[2] * x.b[0] - x.b[2] * x.a[0], + // x.a[0] * x.b[1] - x.b[0] * x.a[1]); + var a = [], b = []; + for (var i = 0; i < this.m_inputSize; i++) { + a[i] = new glsBuiltinPrecisionTests.VectorVariable(args.a, i); + b[i] = new glsBuiltinPrecisionTests.VectorVariable(args.b, i); + } + var v0 = app(new glsBuiltinPrecisionTests.Mul(), a[1], b[2]); + var v1 = app(new glsBuiltinPrecisionTests.Mul(), b[1], a[2]); + var v2 = app(new glsBuiltinPrecisionTests.Sub(), v0, v1); + + var v3 = app(new glsBuiltinPrecisionTests.Mul(), a[2], b[0]); + var v4 = app(new glsBuiltinPrecisionTests.Mul(), b[2], a[0]); + var v5 = app(new glsBuiltinPrecisionTests.Sub(), v3, v4); + + var v6 = app(new glsBuiltinPrecisionTests.Mul(), a[0], b[1]); + var v7 = app(new glsBuiltinPrecisionTests.Mul(), b[0], a[1]); + var v8 = app(new glsBuiltinPrecisionTests.Sub(), v6, v7); + + var v9 = app(new glsBuiltinPrecisionTests.GenVec(this.m_inputSize, true), v2, v5, v8); + return v9; + }; + + /** + * @constructor + * @param {number} size + * @extends {glsBuiltinPrecisionTests.DerivedFunc} + */ + glsBuiltinPrecisionTests.Normalize = function(size) { + var name = glsBuiltinPrecisionTests.sizeToName(size); + var sig = new glsBuiltinPrecisionTests.Signature(name, name); + glsBuiltinPrecisionTests.DerivedFunc.call(this, sig); + this.m_inputSize = size; + }; + + setParentClass(glsBuiltinPrecisionTests.Normalize, glsBuiltinPrecisionTests.DerivedFunc); + + glsBuiltinPrecisionTests.Normalize.prototype.getName = function() { + return 'normalize'; + }; + + glsBuiltinPrecisionTests.Normalize.prototype.doExpand = function(ctx, args) { + //args.a / length<Size>(args.a); + var v0 = app(new glsBuiltinPrecisionTests.Length(this.m_inputSize), args.a); + var v1 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Div(), args.a, v0); + return v1; + }; + + /** + * @constructor + * @param {number} size + * @extends {glsBuiltinPrecisionTests.DerivedFunc} + */ + glsBuiltinPrecisionTests.FaceForward = function(size) { + var name = glsBuiltinPrecisionTests.sizeToName(size); + var sig = new glsBuiltinPrecisionTests.Signature(name, name, name, name); + glsBuiltinPrecisionTests.DerivedFunc.call(this, sig); + this.m_inputSize = size; + this.typename = name; + }; + + setParentClass(glsBuiltinPrecisionTests.FaceForward, glsBuiltinPrecisionTests.DerivedFunc); + + glsBuiltinPrecisionTests.FaceForward.prototype.getName = function() { + return 'faceforward'; + }; + + glsBuiltinPrecisionTests.FaceForward.prototype.doExpand = function(ctx, args) { + //cond(dot(args.c, args.b) < constant(0.0f), args.a, -args.a); + var zero = new glsBuiltinPrecisionTests.Constant(0); + var v0 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Negate(), args.a); + var v1 = app(new glsBuiltinPrecisionTests.Dot(this.m_inputSize), args.c, args.b); + var v2 = app(new glsBuiltinPrecisionTests.LessThan('float'), v1, zero); + var v3 = app(new glsBuiltinPrecisionTests.Cond(this.typename), v2, args.a, v0); + return v3; + }; + + /** + * @constructor + * @param {number} size + * @extends {glsBuiltinPrecisionTests.DerivedFunc} + */ + glsBuiltinPrecisionTests.Reflect = function(size) { + var name = glsBuiltinPrecisionTests.sizeToName(size); + var sig = new glsBuiltinPrecisionTests.Signature(name, name, name); + glsBuiltinPrecisionTests.DerivedFunc.call(this, sig); + this.m_inputSize = size; + }; + + setParentClass(glsBuiltinPrecisionTests.Reflect, glsBuiltinPrecisionTests.DerivedFunc); + + glsBuiltinPrecisionTests.Reflect.prototype.getName = function() { + return 'reflect'; + }; + + glsBuiltinPrecisionTests.Reflect.prototype.doExpand = function(ctx, args) { + //args.a - (args.b * dot(args.b, args.a) * constant(2.0f)); + var two = new glsBuiltinPrecisionTests.Constant(2); + var v0 = app(new glsBuiltinPrecisionTests.Dot(this.m_inputSize), args.b, args.a); + var v1 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Mul(), args.b, v0); + var v2 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Mul(), v1, two); + var v3 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Sub(), args.a, v2); + return v3; + }; + + /** + * @constructor + * @param {number} size + * @extends {glsBuiltinPrecisionTests.DerivedFunc} + */ + glsBuiltinPrecisionTests.Refract = function(size) { + var name = glsBuiltinPrecisionTests.sizeToName(size); + var sig = new glsBuiltinPrecisionTests.Signature(name, name, name, 'float'); + glsBuiltinPrecisionTests.DerivedFunc.call(this, sig); + this.m_inputSize = size; + this.typename = name; + }; + + setParentClass(glsBuiltinPrecisionTests.Refract, glsBuiltinPrecisionTests.DerivedFunc); + + glsBuiltinPrecisionTests.Refract.prototype.getName = function() { + return 'refract'; + }; + + glsBuiltinPrecisionTests.Refract.prototype.doExpand = function(ctx, args) { + var i = args.a; + var n = args.b; + var eta = args.c; + var zero = new glsBuiltinPrecisionTests.Constant(0); + var one = new glsBuiltinPrecisionTests.Constant(1); + // dotNI = dot(n, i) + var v0 = app(new glsBuiltinPrecisionTests.Dot(this.m_inputSize), n, i); + var dotNI = glsBuiltinPrecisionTests.bindExpression('float', 'dotNI', ctx, v0); + // k = 1 - eta * eta * (1 - dotNI * dotNI) + var v1 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Mul(), dotNI, dotNI); + var v2 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Sub(), one, v1); + var v3 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Mul(), eta, eta); + var v4 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Mul(), v3, v2); + var v5 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Sub(), one, v4); + var k = glsBuiltinPrecisionTests.bindExpression('float', 'k', ctx, v5); + + // i * eta - n * (eta * dotNI + sqrt(k)) + var v6 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Mul(), eta, dotNI); + var v7 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Sqrt(), k); + var v8 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Add(), v6, v7); + var v9 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Mul(), n, v8); + var v10 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Mul(), i, eta); + var v11 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Sub(), v10, v9); + + var v12 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.LessThan('float'), k, zero); + + var zeroVector = app(new glsBuiltinPrecisionTests.GenVec(this.m_inputSize), zero); + var v13 = app(new glsBuiltinPrecisionTests.Cond(this.typename), v12, zeroVector, v11); + return v13; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.DerivedFunc} + */ + glsBuiltinPrecisionTests.Radians = function() { + var sig = new glsBuiltinPrecisionTests.Signature('float', 'float'); + glsBuiltinPrecisionTests.DerivedFunc.call(this, sig); + }; + + setParentClass(glsBuiltinPrecisionTests.Radians, glsBuiltinPrecisionTests.DerivedFunc); + + glsBuiltinPrecisionTests.Radians.prototype.getName = function() { + return 'radians'; + }; + + glsBuiltinPrecisionTests.Radians.prototype.doExpand = function(ctx, args) { + var val = app(new glsBuiltinPrecisionTests.Div(), + new glsBuiltinPrecisionTests.Constant(Math.PI), + new glsBuiltinPrecisionTests.Constant(180)); + return new glsBuiltinPrecisionTests.Apply('float', + new glsBuiltinPrecisionTests.Mul(), + val, + args.a); + + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.DerivedFunc} + */ + glsBuiltinPrecisionTests.Degrees = function() { + var sig = new glsBuiltinPrecisionTests.Signature('float', 'float'); + glsBuiltinPrecisionTests.DerivedFunc.call(this, sig); + }; + + setParentClass(glsBuiltinPrecisionTests.Degrees, glsBuiltinPrecisionTests.DerivedFunc); + + glsBuiltinPrecisionTests.Degrees.prototype.getName = function() { + return 'degrees'; + }; + + glsBuiltinPrecisionTests.Degrees.prototype.doExpand = function(ctx, args) { + var val = app(new glsBuiltinPrecisionTests.Div(), + new glsBuiltinPrecisionTests.Constant(180), + new glsBuiltinPrecisionTests.Constant(Math.PI)); + return new glsBuiltinPrecisionTests.Apply('float', + new glsBuiltinPrecisionTests.Mul(), + val, + args.a); + + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.DerivedFunc} + */ + glsBuiltinPrecisionTests.Sinh = function() { + var sig = new glsBuiltinPrecisionTests.Signature('float', 'float'); + glsBuiltinPrecisionTests.DerivedFunc.call(this, sig); + }; + + setParentClass(glsBuiltinPrecisionTests.Sinh, glsBuiltinPrecisionTests.DerivedFunc); + + glsBuiltinPrecisionTests.Sinh.prototype.getName = function() { + return 'sinh'; + }; + + glsBuiltinPrecisionTests.Sinh.prototype.doExpand = function(ctx, args) { + // (exp(x) - exp(-x)) / constant(2.0f) + var x = args.a; + var v0 = app(new glsBuiltinPrecisionTests.Exp(), x); + var v1 = app(new glsBuiltinPrecisionTests.Negate(), x); + var v2 = app(new glsBuiltinPrecisionTests.Exp(), v1); + var v3 = app(new glsBuiltinPrecisionTests.Sub(), v0, v2); + var v4 = new glsBuiltinPrecisionTests.Constant(2); + var v5 = new glsBuiltinPrecisionTests.Apply('float', new glsBuiltinPrecisionTests.Div, v3, v4); + return v5; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.DerivedFunc} + */ + glsBuiltinPrecisionTests.Cosh = function() { + var sig = new glsBuiltinPrecisionTests.Signature('float', 'float'); + glsBuiltinPrecisionTests.DerivedFunc.call(this, sig); + }; + + setParentClass(glsBuiltinPrecisionTests.Cosh, glsBuiltinPrecisionTests.DerivedFunc); + + glsBuiltinPrecisionTests.Cosh.prototype.getName = function() { + return 'cosh'; + }; + + glsBuiltinPrecisionTests.Cosh.prototype.doExpand = function(ctx, args) { + // (exp(x) + exp(-x)) / constant(2.0f) + var x = args.a; + var v0 = app(new glsBuiltinPrecisionTests.Exp(), x); + var v1 = app(new glsBuiltinPrecisionTests.Negate(), x); + var v2 = app(new glsBuiltinPrecisionTests.Exp(), v1); + var v3 = app(new glsBuiltinPrecisionTests.Add(), v0, v2); + var v4 = new glsBuiltinPrecisionTests.Constant(2); + var v5 = new glsBuiltinPrecisionTests.Apply('float', new glsBuiltinPrecisionTests.Div, v3, v4); + return v5; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.DerivedFunc} + */ + glsBuiltinPrecisionTests.Tanh = function() { + var sig = new glsBuiltinPrecisionTests.Signature('float', 'float'); + glsBuiltinPrecisionTests.DerivedFunc.call(this, sig); + }; + + setParentClass(glsBuiltinPrecisionTests.Tanh, glsBuiltinPrecisionTests.DerivedFunc); + + glsBuiltinPrecisionTests.Tanh.prototype.getName = function() { + return 'tanh'; + }; + + glsBuiltinPrecisionTests.Tanh.prototype.doExpand = function(ctx, args) { + // sinh(x) / cosh(x) + var x = args.a; + var v0 = app(new glsBuiltinPrecisionTests.Sinh(), x); + var v1 = app(new glsBuiltinPrecisionTests.Cosh(), x); + var v2 = new glsBuiltinPrecisionTests.Apply('float', new glsBuiltinPrecisionTests.Div, v0, v1); + return v2; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.DerivedFunc} + */ + glsBuiltinPrecisionTests.ASinh = function() { + var sig = new glsBuiltinPrecisionTests.Signature('float', 'float'); + glsBuiltinPrecisionTests.DerivedFunc.call(this, sig); + }; + + setParentClass(glsBuiltinPrecisionTests.ASinh, glsBuiltinPrecisionTests.DerivedFunc); + + glsBuiltinPrecisionTests.ASinh.prototype.getName = function() { + return 'asinh'; + }; + + glsBuiltinPrecisionTests.ASinh.prototype.doExpand = function(ctx, args) { + // log(x + sqrt(x * x + constant(1.0f))) + var x = args.a; + var v0 = app(new glsBuiltinPrecisionTests.Mul(), x, x); + var v1 = new glsBuiltinPrecisionTests.Constant(1); + var v2 = app(new glsBuiltinPrecisionTests.Add(), v0, v1); + var v3 = app(new glsBuiltinPrecisionTests.Sqrt(), v2); + var v4 = app(new glsBuiltinPrecisionTests.Add(), x, v3); + var v5 = app(new glsBuiltinPrecisionTests.Log(), v4); + return v5; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.DerivedFunc} + */ + glsBuiltinPrecisionTests.ACosh = function() { + var sig = new glsBuiltinPrecisionTests.Signature('float', 'float'); + glsBuiltinPrecisionTests.DerivedFunc.call(this, sig); + }; + + setParentClass(glsBuiltinPrecisionTests.ACosh, glsBuiltinPrecisionTests.DerivedFunc); + + glsBuiltinPrecisionTests.ACosh.prototype.getName = function() { + return 'acosh'; + }; + + glsBuiltinPrecisionTests.ACosh.prototype.doExpand = function(ctx, args) { + // log(x + sqrt((x + constant(1.0f)) * (x - constant(1.0f)))) + var x = args.a; + var one = new glsBuiltinPrecisionTests.Constant(1); + var v0 = app(new glsBuiltinPrecisionTests.Add(), x, one); + var v1 = app(new glsBuiltinPrecisionTests.Sub(), x, one); + var v2 = app(new glsBuiltinPrecisionTests.Mul(), v0, v1); + var v3 = app(new glsBuiltinPrecisionTests.Sqrt(), v2); + var v4 = app(new glsBuiltinPrecisionTests.Add(), x, v3); + var v5 = app(new glsBuiltinPrecisionTests.Log(), v4); + return v5; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.DerivedFunc} + */ + glsBuiltinPrecisionTests.ATanh = function() { + var sig = new glsBuiltinPrecisionTests.Signature('float', 'float'); + glsBuiltinPrecisionTests.DerivedFunc.call(this, sig); + }; + + setParentClass(glsBuiltinPrecisionTests.ATanh, glsBuiltinPrecisionTests.DerivedFunc); + + glsBuiltinPrecisionTests.ATanh.prototype.getName = function() { + return 'atanh'; + }; + + glsBuiltinPrecisionTests.ATanh.prototype.doExpand = function(ctx, args) { + // constant(0.5f) * log((constant(1.0f) + x) / (constant(1.0f) - x)) + var x = args.a; + var one = new glsBuiltinPrecisionTests.Constant(1); + var half = new glsBuiltinPrecisionTests.Constant(0.5); + var v0 = app(new glsBuiltinPrecisionTests.Add(), one, x); + var v1 = app(new glsBuiltinPrecisionTests.Sub(), one, x); + var v2 = app(new glsBuiltinPrecisionTests.Div(), v0, v1); + var v3 = app(new glsBuiltinPrecisionTests.Log(), v2); + var v4 = app(new glsBuiltinPrecisionTests.Mul(), half, v3); + return v4; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.DerivedFunc} + */ + glsBuiltinPrecisionTests.Sqrt = function() { + var sig = new glsBuiltinPrecisionTests.Signature('float', 'float'); + glsBuiltinPrecisionTests.DerivedFunc.call(this, sig); + }; + + setParentClass(glsBuiltinPrecisionTests.Sqrt, glsBuiltinPrecisionTests.DerivedFunc); + + glsBuiltinPrecisionTests.Sqrt.prototype.getName = function() { + return 'sqrt'; + }; + + glsBuiltinPrecisionTests.Sqrt.prototype.doExpand = function(ctx, args) { + // constant(1.0f) / app<InverseSqrt>(x) + var x = args.a; + var one = new glsBuiltinPrecisionTests.Constant(1); + var v0 = app(new glsBuiltinPrecisionTests.InverseSqrt(), x); + var v1 = app(new glsBuiltinPrecisionTests.Div(), one, v0); + return v1; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.DerivedFunc} + */ + glsBuiltinPrecisionTests.Fract = function() { + var sig = new glsBuiltinPrecisionTests.Signature('float', 'float'); + glsBuiltinPrecisionTests.DerivedFunc.call(this, sig); + }; + + setParentClass(glsBuiltinPrecisionTests.Fract, glsBuiltinPrecisionTests.DerivedFunc); + + glsBuiltinPrecisionTests.Fract.prototype.getName = function() { + return 'fract'; + }; + + glsBuiltinPrecisionTests.Fract.prototype.doExpand = function(ctx, args) { + // x - floor(x) + var x = args.a; + var v0 = app(new glsBuiltinPrecisionTests.Floor(), x); + var v1 = app(new glsBuiltinPrecisionTests.Sub(), x, v0); + return v1; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.DerivedFunc} + */ + glsBuiltinPrecisionTests.Mod = function() { + var sig = new glsBuiltinPrecisionTests.Signature('float', 'float', 'float'); + glsBuiltinPrecisionTests.DerivedFunc.call(this, sig); + }; + + setParentClass(glsBuiltinPrecisionTests.Mod, glsBuiltinPrecisionTests.DerivedFunc); + + glsBuiltinPrecisionTests.Mod.prototype.getName = function() { + return 'mod'; + }; + + glsBuiltinPrecisionTests.Mod.prototype.doExpand = function(ctx, args) { + // x - y * floor(x/y) + var x = args.a; + var y = args.b; + var v0 = app(new glsBuiltinPrecisionTests.Div(), x, y); + var v1 = app(new glsBuiltinPrecisionTests.Floor(), v0); + var v2 = app(new glsBuiltinPrecisionTests.Mul(), y, v1); + var v3 = app(new glsBuiltinPrecisionTests.Sub(), x, v2); + return v3; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.PrimitiveFunc} + */ + glsBuiltinPrecisionTests.Modf = function() { + var sig = new glsBuiltinPrecisionTests.Signature('float', 'float', 'float'); + glsBuiltinPrecisionTests.PrimitiveFunc.call(this, sig); + }; + setParentClass(glsBuiltinPrecisionTests.Modf, glsBuiltinPrecisionTests.PrimitiveFunc); + + glsBuiltinPrecisionTests.Modf.prototype.getName = function() { + return 'modf'; + }; + + glsBuiltinPrecisionTests.Modf.prototype.doApply = function(ctx, iargs, variablenames) { + var intPart; + var func1 = function(x) { + intPart = Math.trunc(x); + return x - intPart; + }; + var func2 = function(x) { + return Math.trunc(x); + }; + + var fracIV = tcuInterval.applyMonotone1p(func1, iargs.a); + var wholeIV = tcuInterval.applyMonotone1p(func2, iargs.a); + + if (!iargs.a.isFinite()) { + // Behavior on modf(Inf) not well-defined, allow anything as a fractional part + // See Khronos bug 13907 + fracIV.operatorOrAssignBinary(tcuInterval.NAN); + } + + ctx.env.m_map[variablenames[1]] = wholeIV; + return fracIV; + }; + + glsBuiltinPrecisionTests.Modf.prototype.getOutParamIndex = function() { + return 1; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.DerivedFunc} + */ + glsBuiltinPrecisionTests.Mix = function() { + var sig = new glsBuiltinPrecisionTests.Signature('float', 'float', 'float', 'float'); + glsBuiltinPrecisionTests.DerivedFunc.call(this, sig); + }; + + setParentClass(glsBuiltinPrecisionTests.Mix, glsBuiltinPrecisionTests.DerivedFunc); + + glsBuiltinPrecisionTests.Mix.prototype.getName = function() { + return 'mix'; + }; + + glsBuiltinPrecisionTests.Mix.prototype.operation1 = function(ctx, args) { + // (x * (constant(1.0f) - a)) + y * a + var x = args.a; + var y = args.b; + var a = args.c; + var one = new glsBuiltinPrecisionTests.Constant(1); + var v0 = app(new glsBuiltinPrecisionTests.Sub(), one, a); + var v1 = app(new glsBuiltinPrecisionTests.Mul(), x, v0); + var v2 = app(new glsBuiltinPrecisionTests.Mul(), y, a); + var v3 = app(new glsBuiltinPrecisionTests.Add(), v1, v2); + return v3; + }; + + glsBuiltinPrecisionTests.Mix.prototype.operation2 = function(ctx, args) { + // x + (y - x) * a + var x = args.a; + var y = args.b; + var a = args.c; + var v0 = app(new glsBuiltinPrecisionTests.Sub(), y, x); + var v1 = app(new glsBuiltinPrecisionTests.Mul(), a, v0); + var v2 = app(new glsBuiltinPrecisionTests.Add(), x, v1); + return v2; + }; + + glsBuiltinPrecisionTests.Mix.prototype.doExpand = function(ctx, args){ + return app(new glsBuiltinPrecisionTests.Alternatives(this.Sig), this.operation1(ctx, args), this.operation2(ctx, args), new glsBuiltinPrecisionTests.Void(), new glsBuiltinPrecisionTests.Void()); + } + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.DerivedFunc} + */ + glsBuiltinPrecisionTests.SmoothStep = function() { + var sig = new glsBuiltinPrecisionTests.Signature('float', 'float', 'float', 'float'); + glsBuiltinPrecisionTests.DerivedFunc.call(this, sig); + }; + + setParentClass(glsBuiltinPrecisionTests.SmoothStep, glsBuiltinPrecisionTests.DerivedFunc); + + glsBuiltinPrecisionTests.SmoothStep.prototype.getName = function() { + return 'smoothstep'; + }; + + glsBuiltinPrecisionTests.SmoothStep.prototype.doExpand = function(ctx, args) { + var edge0 = args.a; + var edge1 = args.b; + var x = args.c; + var zero = new glsBuiltinPrecisionTests.Constant(0); + var one = new glsBuiltinPrecisionTests.Constant(1); + //clamp((x - edge0) / (edge1 - edge0), constant(0.0f), constant(1.0f)); + var v0 = app(new glsBuiltinPrecisionTests.Sub(), x, edge0); + var v1 = app(new glsBuiltinPrecisionTests.Sub(), edge1, edge0); + var v2 = app(new glsBuiltinPrecisionTests.Div(), v0, v1); + var v3 = app(new glsBuiltinPrecisionTests.Clamp(), v2, zero, one); + var t = glsBuiltinPrecisionTests.bindExpression('float', 't', ctx, v3); + //(t * t * (constant(3.0f) - constant(2.0f) * t)) + var two = new glsBuiltinPrecisionTests.Constant(2); + var three = new glsBuiltinPrecisionTests.Constant(3); + var v4 = app(new glsBuiltinPrecisionTests.Mul(), v3, v3); + var v5 = app(new glsBuiltinPrecisionTests.Mul(), two, v3); + var v6 = app(new glsBuiltinPrecisionTests.Sub(), three, v5); + var v7 = app(new glsBuiltinPrecisionTests.Mul(), v4, v6); + return v7; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.DerivedFunc} + */ + glsBuiltinPrecisionTests.Pow = function() { + var sig = new glsBuiltinPrecisionTests.Signature('float', 'float', 'float'); + glsBuiltinPrecisionTests.DerivedFunc.call(this, sig); + }; + + setParentClass(glsBuiltinPrecisionTests.Pow, glsBuiltinPrecisionTests.DerivedFunc); + + glsBuiltinPrecisionTests.Pow.prototype.getName = function() { + return 'pow'; + }; + + glsBuiltinPrecisionTests.Pow.prototype.doExpand = function(ctx, args) { + // exp2(y * log2(x)) + var x = args.a; + var y = args.b; + var v0 = app(new glsBuiltinPrecisionTests.Log2(), x); + var v1 = app(new glsBuiltinPrecisionTests.Mul(), y, v0); + var v2 = app(new glsBuiltinPrecisionTests.Exp2(), v1); + return v2; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.CFloatFunc1} + */ + glsBuiltinPrecisionTests.ExpFunc = function(name, func) { + glsBuiltinPrecisionTests.CFloatFunc1.call(this, name, func); + }; + + setParentClass(glsBuiltinPrecisionTests.ExpFunc, glsBuiltinPrecisionTests.CFloatFunc1); + + glsBuiltinPrecisionTests.ExpFunc.prototype.getCodomain = function() { + return tcuInterval.withNumbers(0, Infinity); + }; + + glsBuiltinPrecisionTests.ExpFunc.prototype.precision = function(ctx, ret, x) { + switch (ctx.floatPrecision) { + case gluShaderUtil.precision.PRECISION_HIGHP: + return ctx.format.ulp(ret, 3.0 + 2.0 * Math.abs(x)); + case gluShaderUtil.precision.PRECISION_MEDIUMP: + return ctx.format.ulp(ret, 2.0 + 2.0 * Math.abs(x)); + case gluShaderUtil.precision.PRECISION_LOWP: + return ctx.format.ulp(ret, 2.0); + default: + throw new Error(!'Impossible'); + } + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.ExpFunc} + */ + glsBuiltinPrecisionTests.Exp = function() { + glsBuiltinPrecisionTests.ExpFunc.call(this, 'exp', Math.exp); + }; + + setParentClass(glsBuiltinPrecisionTests.Exp, glsBuiltinPrecisionTests.ExpFunc); + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.ExpFunc} + */ + glsBuiltinPrecisionTests.Exp2 = function() { + /** + * @param {number} x + * @return {number} + */ + var exp2 = function(x) { + return Math.exp(x * Math.LN2); + }; + glsBuiltinPrecisionTests.ExpFunc.call(this, 'exp2', exp2); + }; + + setParentClass(glsBuiltinPrecisionTests.Exp2, glsBuiltinPrecisionTests.ExpFunc); + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.CFloatFunc1} + */ + glsBuiltinPrecisionTests.LogFunc = function(name, func) { + glsBuiltinPrecisionTests.CFloatFunc1.call(this, name, func); + }; + + setParentClass(glsBuiltinPrecisionTests.LogFunc, glsBuiltinPrecisionTests.CFloatFunc1); + + glsBuiltinPrecisionTests.LogFunc.prototype.precision = function(ctx, ret, x) { + if (x <= 0) + return NaN; + switch (ctx.floatPrecision) { + case gluShaderUtil.precision.PRECISION_HIGHP: + return (0.5 <= x && x <= 2.0) ? deMath.deLdExp(1.0, -21) : ctx.format.ulp(ret, 3.0); + case gluShaderUtil.precision.PRECISION_MEDIUMP: + return (0.5 <= x && x <= 2.0) ? deMath.deLdExp(1.0, -7) : ctx.format.ulp(ret, 2.0); + case gluShaderUtil.precision.PRECISION_LOWP: + return ctx.format.ulp(ret, 2.0); + default: + throw new Error(!'Impossible'); + } + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.LogFunc} + */ + glsBuiltinPrecisionTests.Log = function() { + glsBuiltinPrecisionTests.LogFunc.call(this, 'log', Math.log); + }; + + setParentClass(glsBuiltinPrecisionTests.Log, glsBuiltinPrecisionTests.LogFunc); + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.LogFunc} + */ + glsBuiltinPrecisionTests.Log2 = function() { + glsBuiltinPrecisionTests.LogFunc.call(this, 'log2', Math.log2); + }; + + setParentClass(glsBuiltinPrecisionTests.Log2, glsBuiltinPrecisionTests.LogFunc); + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.CFloatFunc1} + */ + glsBuiltinPrecisionTests.PreciseFunc1 = function(name, func) { + glsBuiltinPrecisionTests.CFloatFunc1.call(this, name, func); + }; + + setParentClass(glsBuiltinPrecisionTests.PreciseFunc1, glsBuiltinPrecisionTests.CFloatFunc1); + + glsBuiltinPrecisionTests.PreciseFunc1.prototype.precision = function(ctx, ret, x) { + return 0; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.PreciseFunc1} + */ + glsBuiltinPrecisionTests.Abs = function() { + glsBuiltinPrecisionTests.PreciseFunc1.call(this, 'abs', Math.abs); + }; + setParentClass(glsBuiltinPrecisionTests.Abs, glsBuiltinPrecisionTests.PreciseFunc1); + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.PreciseFunc1} + */ + glsBuiltinPrecisionTests.Sign = function() { + glsBuiltinPrecisionTests.PreciseFunc1.call(this, 'sign', Math.sign); + }; + setParentClass(glsBuiltinPrecisionTests.Sign, glsBuiltinPrecisionTests.PreciseFunc1); + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.PreciseFunc1} + */ + glsBuiltinPrecisionTests.Floor = function() { + glsBuiltinPrecisionTests.PreciseFunc1.call(this, 'floor', Math.floor); + }; + setParentClass(glsBuiltinPrecisionTests.Floor, glsBuiltinPrecisionTests.PreciseFunc1); + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.PreciseFunc1} + */ + glsBuiltinPrecisionTests.RoundEven = function() { + glsBuiltinPrecisionTests.PreciseFunc1.call(this, 'roundEven', deMath.rint); + }; + setParentClass(glsBuiltinPrecisionTests.RoundEven, glsBuiltinPrecisionTests.PreciseFunc1); + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.PreciseFunc1} + */ + glsBuiltinPrecisionTests.Ceil = function() { + glsBuiltinPrecisionTests.PreciseFunc1.call(this, 'ceil', Math.ceil); + }; + setParentClass(glsBuiltinPrecisionTests.Ceil, glsBuiltinPrecisionTests.PreciseFunc1); + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.PreciseFunc1} + */ + glsBuiltinPrecisionTests.Trunc = function() { + glsBuiltinPrecisionTests.PreciseFunc1.call(this, 'trunc', Math.trunc); + }; + setParentClass(glsBuiltinPrecisionTests.Trunc, glsBuiltinPrecisionTests.PreciseFunc1); + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.CFloatFunc2} + */ + glsBuiltinPrecisionTests.PreciseFunc2 = function(name, func) { + glsBuiltinPrecisionTests.CFloatFunc2.call(this, name, func); + }; + + setParentClass(glsBuiltinPrecisionTests.PreciseFunc2, glsBuiltinPrecisionTests.CFloatFunc2); + + glsBuiltinPrecisionTests.PreciseFunc2.prototype.precision = function(ctx, ret, x, y) { + return 0; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.PreciseFunc2} + */ + glsBuiltinPrecisionTests.Min = function() { + glsBuiltinPrecisionTests.PreciseFunc2.call(this, 'min', Math.min); + }; + setParentClass(glsBuiltinPrecisionTests.Min, glsBuiltinPrecisionTests.PreciseFunc2); + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.PreciseFunc2} + */ + glsBuiltinPrecisionTests.Max = function() { + glsBuiltinPrecisionTests.PreciseFunc2.call(this, 'max', Math.max); + }; + setParentClass(glsBuiltinPrecisionTests.Max, glsBuiltinPrecisionTests.PreciseFunc2); + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.PreciseFunc2} + */ + glsBuiltinPrecisionTests.Step = function() { + /** + * @param {number} edge + * @param {number} x + * return number + */ + var step = function(edge, x) { + return x < edge ? 0.0 : 1.0; + }; + glsBuiltinPrecisionTests.PreciseFunc2.call(this, 'step', step); + }; + setParentClass(glsBuiltinPrecisionTests.Step, glsBuiltinPrecisionTests.PreciseFunc2); + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.CFloatFunc1} + */ + glsBuiltinPrecisionTests.TrigFunc = function(name, func, loEx, hiEx) { + glsBuiltinPrecisionTests.CFloatFunc1.call(this, name, func); + this.m_loExtremum = loEx; + this.m_hiExtremum = hiEx; + }; + + setParentClass(glsBuiltinPrecisionTests.TrigFunc, glsBuiltinPrecisionTests.CFloatFunc1); + + glsBuiltinPrecisionTests.TrigFunc.prototype.innerExtrema = function(ctx, angle) { + var lo = angle.lo(); + var hi = angle.hi(); + var loSlope = this.doGetSlope(lo); + var hiSlope = this.doGetSlope(hi); + + // Detect the high and low values the function can take between the + // interval endpoints. + if (angle.length() >= 2.0 * Math.PI) { + // The interval is longer than a full cycle, so it must get all possible values. + return this.m_hiExtremum.operatorOrBinary(this.m_loExtremum); + } else if (loSlope == 1 && hiSlope == -1) { + // The slope can change from positive to negative only at the maximum value. + return this.m_hiExtremum; + } else if (loSlope == -1 && hiSlope == 1) { + // The slope can change from negative to positive only at the maximum value. + return this.m_loExtremum; + } else if (loSlope == hiSlope && + deMath.deSign(this.applyExact(hi) - this.applyExact(lo)) * loSlope == -1) { + // The slope has changed twice between the endpoints, so both extrema are included. + return this.m_hiExtremum.operatorOrBinary(this.m_loExtremum); + } + + return new tcuInterval.Interval(); + }; + + glsBuiltinPrecisionTests.TrigFunc.prototype.getCodomain = function() { + // Ensure that result is always within [-1, 1], or NaN (for +-inf) + var v = tcuInterval.withIntervals(new tcuInterval.Interval(-1), new tcuInterval.Interval(1)); + return v.operatorOrBinary(tcuInterval.NAN); + }; + + glsBuiltinPrecisionTests.TrigFunc.prototype.precision = function(ctx, ret, arg) { + if (ctx.floatPrecision == gluShaderUtil.precision.PRECISION_HIGHP) { + // Use precision from OpenCL fast relaxed math + if (-Math.PI <= arg && arg <= Math.PI) { + return deMath.deLdExp(1.0, -11); + } else { + // "larger otherwise", let's pick |x| * 2^-12 , which is slightly over + // 2^-11 at x == pi. + return deMath.deLdExp(Math.abs(arg), -12); + } + } else if (ctx.floatPrecision == gluShaderUtil.precision.PRECISION_MEDIUMP) { + if (-Math.PI <= arg && arg <= Math.PI) { + // from OpenCL half-float extension specification + return ctx.format.ulp(ret, 2.0); + } else { + // |x| * 2^-10 , slightly larger than 2 ULP at x == pi + return deMath.deLdExp(Math.abs(arg), -10); + } + } else { + // from OpenCL half-float extension specification + return ctx.format.ulp(ret, 2.0); + } + }; + + /** + * @param {number} angle + * @return number + */ + glsBuiltinPrecisionTests.TrigFunc.prototype.doGetSlope = function(angle) { + throw new Error('Virtual function. Please override.'); + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.TrigFunc} + */ + glsBuiltinPrecisionTests.Sin = function() { + glsBuiltinPrecisionTests.TrigFunc.call(this, 'sin', Math.sin, new tcuInterval.Interval(-1), new tcuInterval.Interval(1)); + }; + + setParentClass(glsBuiltinPrecisionTests.Sin, glsBuiltinPrecisionTests.TrigFunc); + + glsBuiltinPrecisionTests.Sin.prototype.doGetSlope = function(angle) { + return deMath.deSign(Math.cos(angle)); + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.TrigFunc} + */ + glsBuiltinPrecisionTests.Cos = function() { + glsBuiltinPrecisionTests.TrigFunc.call(this, 'cos', Math.cos, new tcuInterval.Interval(-1), new tcuInterval.Interval(1)); + }; + + setParentClass(glsBuiltinPrecisionTests.Cos, glsBuiltinPrecisionTests.TrigFunc); + + glsBuiltinPrecisionTests.Cos.prototype.doGetSlope = function(angle) { + return -deMath.deSign(Math.sin(angle)); + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.DerivedFunc} + */ + glsBuiltinPrecisionTests.Tan = function() { + var sig = new glsBuiltinPrecisionTests.Signature('float', 'float'); + glsBuiltinPrecisionTests.DerivedFunc.call(this, sig); + }; + + setParentClass(glsBuiltinPrecisionTests.Tan, glsBuiltinPrecisionTests.DerivedFunc); + + glsBuiltinPrecisionTests.Tan.prototype.getName = function() { + return 'tan'; + }; + + glsBuiltinPrecisionTests.Tan.prototype.doExpand = function(ctx, args) { + // sin(x) * (constant(1.0f) / cos(x) + var x = args.a; + var sin = app(new glsBuiltinPrecisionTests.Sin(), x); + var cos = app(new glsBuiltinPrecisionTests.Cos(), x); + var expr = app(new glsBuiltinPrecisionTests.Div(), + new glsBuiltinPrecisionTests.Constant(1), + cos); + + expr = new glsBuiltinPrecisionTests.Apply('float', new glsBuiltinPrecisionTests.Mul(), + sin, + expr); + return expr; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.CFloatFunc1} + */ + glsBuiltinPrecisionTests.ASin = function() { + glsBuiltinPrecisionTests.CFloatFunc1.call(this, 'asin', Math.asin); + }; + + setParentClass(glsBuiltinPrecisionTests.ASin, glsBuiltinPrecisionTests.CFloatFunc1); + + glsBuiltinPrecisionTests.ASin.prototype.precision = function(ctx, ret, x) { + if (!deMath.deInBounds32(x, -1.0, 1.0)) + return NaN; + + if (ctx.floatPrecision == gluShaderUtil.precision.PRECISION_HIGHP) { + // Absolute error of 2^-11 + return deMath.deLdExp(1.0, -11); + } else { + // Absolute error of 2^-8 + return deMath.deLdExp(1.0, -8); + } + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.CFloatFunc1} + */ + glsBuiltinPrecisionTests.ArcTrigFunc = function(name, func, precisionULPs, domain, coddomain) { + glsBuiltinPrecisionTests.CFloatFunc1.call(this, name, func); + this.m_precision = precisionULPs; + this.m_domain = domain; + this.m_codomain = coddomain; + }; + + setParentClass(glsBuiltinPrecisionTests.ArcTrigFunc, glsBuiltinPrecisionTests.CFloatFunc1); + + glsBuiltinPrecisionTests.ArcTrigFunc.prototype.precision = function(ctx, ret, x) { + if (!this.m_domain.contains(new tcuInterval.Interval(x))) + return NaN; + + if (ctx.floatPrecision == gluShaderUtil.precision.PRECISION_HIGHP) { + // Use OpenCL's precision + return ctx.format.ulp(ret, this.m_precision); + } else { + // Use OpenCL half-float spec + return ctx.format.ulp(ret, 2.0); + } + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.ArcTrigFunc} + */ + glsBuiltinPrecisionTests.ACos = function() { + glsBuiltinPrecisionTests.ArcTrigFunc.call(this, 'acos', Math.acos, 4096.0, + tcuInterval.withNumbers(-1, 1), + tcuInterval.withNumbers(0, Math.PI)); + }; + + setParentClass(glsBuiltinPrecisionTests.ACos, glsBuiltinPrecisionTests.ArcTrigFunc); + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.ArcTrigFunc} + */ + glsBuiltinPrecisionTests.ATan = function() { + glsBuiltinPrecisionTests.ArcTrigFunc.call(this, 'atan', Math.atan, 4096.0, + tcuInterval.unbounded(), + tcuInterval.withNumbers(-Math.PI * 0.5, Math.PI * 0.5)); + }; + + setParentClass(glsBuiltinPrecisionTests.ATan, glsBuiltinPrecisionTests.ArcTrigFunc); + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.CFloatFunc2} + */ + glsBuiltinPrecisionTests.ATan2 = function() { + glsBuiltinPrecisionTests.CFloatFunc2.call(this, 'atan', Math.atan2); + }; + + setParentClass(glsBuiltinPrecisionTests.ATan2, glsBuiltinPrecisionTests.CFloatFunc2); + + glsBuiltinPrecisionTests.ATan2.prototype.innerExtrema = function(ctx, xi, yi) { + var ret = new tcuInterval.Interval(); + + if (yi.contains(tcuInterval.ZERO)) { + if (xi.contains(tcuInterval.ZERO)) + ret.operatorOrAssignBinary(tcuInterval.NAN); + if (xi.intersects(tcuInterval.withNumbers(-Infinity, 0))) + ret.operatorOrAssignBinary(tcuInterval.withNumbers(-Math.PI, Math.PI)); + } + + if (ctx.format.hasInf() != tcuFloatFormat.YesNoMaybe.YES && (!yi.isFinite() || !xi.isFinite())) { + // Infinities may not be supported, allow anything, including NaN + ret.operatorOrAssignBinary(tcuInterval.NAN); + } + + return ret; + }; + + glsBuiltinPrecisionTests.ATan2.prototype.precision = function(ctx, ret, x, y) { + if (ctx.floatPrecision == gluShaderUtil.precision.PRECISION_HIGHP) + return ctx.format.ulp(ret, 4096.0); + else + return ctx.format.ulp(ret, 2.0); + }; + + /** + * @constructor + * @param {number} size + * @extends {glsBuiltinPrecisionTests.DerivedFunc} + */ + glsBuiltinPrecisionTests.DeterminantBase = function(size) { + var sig = new glsBuiltinPrecisionTests.Signature('float', 'mat' + size); + glsBuiltinPrecisionTests.DerivedFunc.call(this, sig); + }; + + setParentClass(glsBuiltinPrecisionTests.DeterminantBase, glsBuiltinPrecisionTests.DerivedFunc); + + glsBuiltinPrecisionTests.DeterminantBase.prototype.getName = function() { + return 'determinant'; + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.DeterminantBase} + */ + glsBuiltinPrecisionTests.Determinant = function() { + // TODO: Support sizes 3 and 4 + this.size = 2; + glsBuiltinPrecisionTests.DeterminantBase.call(this, this.size); + }; + + setParentClass(glsBuiltinPrecisionTests.Determinant, glsBuiltinPrecisionTests.DeterminantBase); + + glsBuiltinPrecisionTests.Determinant.prototype.doExpand = function(ctx, args) { + // mat[0][0] * mat[1][1] - mat[1][0] * mat[0][1] + var elem0_0 = new glsBuiltinPrecisionTests.MatrixVariable(args.a, 0, 0); + var elem0_1 = new glsBuiltinPrecisionTests.MatrixVariable(args.a, 0, 1); + var elem1_0 = new glsBuiltinPrecisionTests.MatrixVariable(args.a, 1, 0); + var elem1_1 = new glsBuiltinPrecisionTests.MatrixVariable(args.a, 1, 1); + + var val0 = app(new glsBuiltinPrecisionTests.Mul(), elem0_0, elem1_1); + var val1 = app(new glsBuiltinPrecisionTests.Mul(), elem0_1, elem1_0); + return new glsBuiltinPrecisionTests.Apply('float', new glsBuiltinPrecisionTests.Sub(), val0, val1); + }; + + /** + * @constructor + * @extends {glsBuiltinPrecisionTests.DerivedFunc} + */ + glsBuiltinPrecisionTests.Inverse = function() { + this.size = 2; + var name = 'mat' + this.size; + var sig = new glsBuiltinPrecisionTests.Signature(name, name); + glsBuiltinPrecisionTests.DerivedFunc.call(this, sig); + }; + + setParentClass(glsBuiltinPrecisionTests.Inverse, glsBuiltinPrecisionTests.DerivedFunc); + + glsBuiltinPrecisionTests.Inverse.prototype.getName = function() { + return 'inverse'; + }; + + glsBuiltinPrecisionTests.Inverse.prototype.doExpand = function(ctx, args) { + var mat = args.a; + var v0 = app(new glsBuiltinPrecisionTests.Determinant(), mat); + var det = glsBuiltinPrecisionTests.bindExpression('float', 'det', ctx, v0); + + var elem0_0 = new glsBuiltinPrecisionTests.MatrixVariable(args.a, 0, 0); + var elem0_1 = new glsBuiltinPrecisionTests.MatrixVariable(args.a, 0, 1); + var elem1_0 = new glsBuiltinPrecisionTests.MatrixVariable(args.a, 1, 0); + var elem1_1 = new glsBuiltinPrecisionTests.MatrixVariable(args.a, 1, 1); + + var result0_0 = app(new glsBuiltinPrecisionTests.Div(), elem1_1, det); + var result0_1 = app(new glsBuiltinPrecisionTests.Div(), elem0_1, det); + result0_1 = app(new glsBuiltinPrecisionTests.Negate(), result0_1); + var result1_0 = app(new glsBuiltinPrecisionTests.Div(), elem1_0, det); + result1_0 = app(new glsBuiltinPrecisionTests.Negate(), result1_0); + var result1_1 = app(new glsBuiltinPrecisionTests.Div(), elem0_0, det); + + var col0 = app(new glsBuiltinPrecisionTests.GenVec(this.size, true), result0_0, result1_0); + var col1 = app(new glsBuiltinPrecisionTests.GenVec(this.size, true), result0_1, result1_1); + var ret = app(new glsBuiltinPrecisionTests.GenMat(this.size, this.size), col0, col1); + + return ret; + }; + + /** + * @param {glsBuiltinPrecisionTests.PrecisionTestContext} ctx + * @param {glsBuiltinPrecisionTests.CaseFactory} factory + * @return {tcuTestCase.DeqpTest} + */ + glsBuiltinPrecisionTests.createFuncGroup = function(ctx, factory) { + /** @type {tcuTestCase.DeqpTest} */ var group = tcuTestCase.newTest(factory.getName(), factory.getDesc()); + + for (var precNdx in gluShaderUtil.precision) { + /** @type {gluShaderUtil.precision} */ var precision = gluShaderUtil.precision[precNdx]; + /** @type {string} */ var precName = gluShaderUtil.getPrecisionName(precision); + /** @type {tcuFloatFormat.FloatFormat} */ var fmt = ctx.formats[precision]; + /** @type {tcuFloatFormat.FloatFormat} */ var highpFmt = ctx.formats[gluShaderUtil.precision.PRECISION_HIGHP]; + + for (var shaderNdx in ctx.shaderTypes) { + /** @type {gluShaderProgram.shaderType} */ var shaderType = ctx.shaderTypes[shaderNdx]; + /** @type {string} */ var shaderName = gluShaderProgram.getShaderTypeName(shaderType); + /** @type {string} */ var name = precName + '_' + shaderName; + /** @type {glsBuiltinPrecisionTests.Context} */ var caseCtx = new glsBuiltinPrecisionTests.Context(name, fmt, highpFmt, + precision, shaderType, ctx.numRandoms); + + group.addChild(factory.createCase(caseCtx)); + } + } + + return group; + }; + + /** + * @param {glsBuiltinPrecisionTests.CaseFactories} cases + * @param {Array<gluShaderProgram.shaderType>} shaderTypes + * @param {tcuTestCase.DeqpTest} dstGroup + */ + glsBuiltinPrecisionTests.addBuiltinPrecisionTests = function(cases, shaderTypes, dstGroup) { + /** @type {tcuFloatFormat.FloatFormat} */ var highp = new tcuFloatFormat.FloatFormat(-126, 127, 23, true, + tcuFloatFormat.YesNoMaybe.MAYBE, // subnormals + tcuFloatFormat.YesNoMaybe.YES, // infinities + tcuFloatFormat.YesNoMaybe.MAYBE); // NaN + // \todo [2014-04-01 lauri] Check these once Khronos bug 11840 is resolved. + /** @type {tcuFloatFormat.FloatFormat} */ var mediump = new tcuFloatFormat.FloatFormat(-13, 13, 9, false); + // A fixed-point format is just a floating point format with a fixed + // exponent and support for subnormals. + /** @type {tcuFloatFormat.FloatFormat} */ var lowp = new tcuFloatFormat.FloatFormat(0, 0, 7, false, tcuFloatFormat.YesNoMaybe.YES); + /** @type {glsBuiltinPrecisionTests.PrecisionTestContext} */ var ctx = new glsBuiltinPrecisionTests.PrecisionTestContext(highp, mediump, lowp, + shaderTypes, 16384); + + for (var ndx = 0; ndx < cases.getFactories().length; ++ndx) + dstGroup.addChild(glsBuiltinPrecisionTests.createFuncGroup(ctx, cases.getFactories()[ndx])); + }; + + /** + * @param {function(new:glsBuiltinPrecisionTests.Func)} F + * @param {glsBuiltinPrecisionTests.CaseFactories} funcs + * @param {string=} name + */ + glsBuiltinPrecisionTests.addScalarFactory = function(F, funcs, name) { + if (name === undefined) + name = (new F()).getName(); + + funcs.addFactory(new glsBuiltinPrecisionTests.GenFuncCaseFactory(glsBuiltinPrecisionTests.makeVectorizedFuncs(F), name)); + }; + + /** + * @param {function(new:glsBuiltinPrecisionTests.Func)} F + */ + glsBuiltinPrecisionTests.createSimpleFuncCaseFactory = function(F) { + return new glsBuiltinPrecisionTests.SimpleFuncCaseFactory(new F()); + }; + + /** + * @param {number} caseId test case Id + * @return {glsBuiltinPrecisionTests.CaseFactories} + */ + glsBuiltinPrecisionTests.createES3BuiltinCases = function(caseId) { + /** @type {glsBuiltinPrecisionTests.CaseFactories} */ var funcs = new glsBuiltinPrecisionTests.BuiltinFuncs(); + + switch (caseId) { + case 0: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Add, funcs); break; + case 1: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Sub, funcs); break; + case 2: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Mul, funcs); break; + case 3: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Div, funcs); break; + case 4: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Radians, funcs); break; + case 5: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Degrees, funcs); break; + case 6: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Sin, funcs); break; + case 7: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Cos, funcs); break; + case 8: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Tan, funcs); break; + case 9: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.ASin, funcs); break; + case 10: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.ACos, funcs); break; + case 11: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.ATan, funcs); break; + case 12: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.ATan2, funcs, 'atan2'); break; + case 13: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Sinh, funcs); break; + case 14: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Cosh, funcs); break; + case 15: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Tanh, funcs); break; + case 16: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.ASinh, funcs); break; + case 17: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.ACosh, funcs); break; + case 18: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.ATanh, funcs); break; + case 19: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Pow, funcs); break; + case 20: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Exp, funcs); break; + case 21: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Exp2, funcs); break; + case 22: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Log, funcs); break; + case 23: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Log2, funcs); break; + case 24: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Sqrt, funcs); break; + case 25: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.InverseSqrt, funcs); break; + case 26: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Abs, funcs); break; + case 27: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Sign, funcs); break; + case 28: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Floor, funcs); break; + case 29: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Trunc, funcs); break; + case 30: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Round, funcs); break; + case 31: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.RoundEven, funcs); break; + case 32: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Ceil, funcs); break; + case 33: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Fract, funcs); break; + case 34: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Mod, funcs); break; + case 35: funcs.addFactory(glsBuiltinPrecisionTests.createSimpleFuncCaseFactory(glsBuiltinPrecisionTests.Modf)); break; + case 36: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Min, funcs); break; + case 37: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Max, funcs); break; + case 38: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Mix, funcs); break; + case 39: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Step, funcs); break; + case 40: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.SmoothStep, funcs); break; + case 41: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Clamp, funcs); break; + case 42: funcs.addFactory(new glsBuiltinPrecisionTests.TemplateFuncCaseFactory(glsBuiltinPrecisionTests.Length)); break; + case 43: funcs.addFactory(new glsBuiltinPrecisionTests.TemplateFuncCaseFactory(glsBuiltinPrecisionTests.Distance)); break; + case 44: funcs.addFactory(new glsBuiltinPrecisionTests.TemplateFuncCaseFactory(glsBuiltinPrecisionTests.Dot)); break; + case 45: funcs.addFactory(glsBuiltinPrecisionTests.createSimpleFuncCaseFactory(glsBuiltinPrecisionTests.Cross)); break; + case 46: funcs.addFactory(new glsBuiltinPrecisionTests.TemplateFuncCaseFactory(glsBuiltinPrecisionTests.Normalize)); break; + case 47: funcs.addFactory(new glsBuiltinPrecisionTests.TemplateFuncCaseFactory(glsBuiltinPrecisionTests.FaceForward)); break; + case 48: funcs.addFactory(new glsBuiltinPrecisionTests.TemplateFuncCaseFactory(glsBuiltinPrecisionTests.Reflect)); break; + case 49: funcs.addFactory(new glsBuiltinPrecisionTests.TemplateFuncCaseFactory(glsBuiltinPrecisionTests.Refract)); break; + case 50: funcs.addFactory(new glsBuiltinPrecisionTests.MatrixFuncCaseFactory(glsBuiltinPrecisionTests.MatrixCompMult)); break; + case 51: funcs.addFactory(new glsBuiltinPrecisionTests.MatrixFuncCaseFactory(glsBuiltinPrecisionTests.OuterProduct)); break; + case 52: funcs.addFactory(new glsBuiltinPrecisionTests.MatrixFuncCaseFactory(glsBuiltinPrecisionTests.Transpose)); break; + case 53: funcs.addFactory(new glsBuiltinPrecisionTests.SquareMatrixFuncCaseFactory(glsBuiltinPrecisionTests.Determinant)); break; + case 54: funcs.addFactory(new glsBuiltinPrecisionTests.SquareMatrixFuncCaseFactory(glsBuiltinPrecisionTests.Inverse)); break; + default: break; + } + + return funcs; + }; + +}); |