tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

es3fShaderCommonFunctionTests.js (95022B)


      1 /*-------------------------------------------------------------------------
      2 * drawElements Quality Program OpenGL ES Utilities
      3 * ------------------------------------------------
      4 *
      5 * Copyright 2014 The Android Open Source Project
      6 *
      7 * Licensed under the Apache License, Version 2.0 (the 'License');
      8 * you may not use this file except in compliance with the License.
      9 * You may obtain a copy of the License at
     10 *
     11 *      http://www.apache.org/licenses/LICENSE-2.0
     12 *
     13 * Unless required by applicable law or agreed to in writing, software
     14 * distributed under the License is distributed on an 'AS IS' BASIS,
     15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16 * See the License for the specific language governing permissions and
     17 * limitations under the License.
     18 *
     19 */
     20 
     21 'use strict';
     22 goog.provide('functional.gles3.es3fShaderCommonFunctionTests');
     23 goog.require('framework.common.tcuFloat');
     24 goog.require('framework.common.tcuTestCase');
     25 goog.require('framework.delibs.debase.deMath');
     26 goog.require('framework.delibs.debase.deRandom');
     27 goog.require('framework.delibs.debase.deString');
     28 goog.require('framework.opengl.gluShaderProgram');
     29 goog.require('framework.opengl.gluShaderUtil');
     30 goog.require('framework.opengl.gluVarType');
     31 goog.require('modules.shared.glsShaderExecUtil');
     32 goog.scope(function() {
     33    var es3fShaderCommonFunctionTests = functional.gles3.es3fShaderCommonFunctionTests;
     34    var tcuFloat = framework.common.tcuFloat;
     35    var tcuTestCase = framework.common.tcuTestCase;
     36    var gluShaderProgram = framework.opengl.gluShaderProgram;
     37    var gluShaderUtil = framework.opengl.gluShaderUtil;
     38    var gluVarType = framework.opengl.gluVarType;
     39    var deRandom = framework.delibs.debase.deRandom;
     40    var deMath = framework.delibs.debase.deMath;
     41    var deString = framework.delibs.debase.deString;
     42    var glsShaderExecUtil = modules.shared.glsShaderExecUtil;
     43 
     44    /** @typedef {function(new: es3fShaderCommonFunctionTests.CommonFunctionCase, gluShaderUtil.DataType, gluShaderUtil.precision, gluShaderProgram.shaderType)} */ es3fShaderCommonFunctionTests.TestClass;
     45 
     46    /**
     47     * @enum
     48     */
     49    es3fShaderCommonFunctionTests.Types = {
     50        FLOAT: 0,
     51        INT: 1,
     52        UINT: 2
     53    };
     54 
     55    /**
     56     * @param {Array<number>} values
     57     */
     58    es3fShaderCommonFunctionTests.vecToFloat16 = function(values) {
     59        for (var ndx = 0; ndx < values.length; ndx++)
     60            values[ndx] = tcuFloat.newFloat16(values[ndx]).getValue();
     61    };
     62 
     63    /**
     64     * @param {es3fShaderCommonFunctionTests.Types} type
     65     * @param {deRandom.Random} rnd
     66     * @param {number} minValue
     67     * @param {number} maxValue
     68     * @return {number}
     69     */
     70    es3fShaderCommonFunctionTests.randomScalar = function(type, rnd, minValue, maxValue) {
     71        switch (type) {
     72            case es3fShaderCommonFunctionTests.Types.FLOAT: return rnd.getFloat(minValue, maxValue);
     73            case es3fShaderCommonFunctionTests.Types.INT: return rnd.getInt(minValue, maxValue);
     74            case es3fShaderCommonFunctionTests.Types.UINT: return Math.abs(rnd.getInt(minValue, maxValue));
     75            default: throw new Error('Only FLOAT, INT, and UINT are supported.');
     76        }
     77    };
     78 
     79    /**
     80     * @param {es3fShaderCommonFunctionTests.Types} type
     81     * @param {Array<number>} size
     82     * @param {deRandom.Random} rnd
     83     * @param {Array<number>} minValue
     84     * @param {Array<number>} maxValue
     85     * @return {Array<number>}
     86     */
     87    es3fShaderCommonFunctionTests.randomVector = function(type, size, rnd, minValue, maxValue) {
     88        /** @type {Array<number>} */ var res = [];
     89        for (var ndx = 0; ndx < size; ndx++)
     90            res.push(es3fShaderCommonFunctionTests.randomScalar(type, rnd, minValue[ndx], maxValue[ndx]));
     91        return res;
     92    };
     93 
     94    /**
     95     * @param {es3fShaderCommonFunctionTests.Types} type
     96     * @param {Array<number>} size
     97     * @param {deRandom.Random} rnd
     98     * @param {Array<number>} minValue
     99     * @param {Array<number>} maxValue
    100     * @param {number} numValues
    101     * @param {number=} offset
    102     * @return {Array<Array<number>>}
    103     */
    104    es3fShaderCommonFunctionTests.fillRandomVectors = function(type, size, rnd, minValue, maxValue, numValues, offset) {
    105        offset = offset === undefined ? 0 : offset;
    106        /** @type {Array<Array<number>>} */ var access;
    107        for (var ndx = 0; ndx < numValues; ndx++)
    108            access[offset + ndx] = es3fShaderCommonFunctionTests.randomVector(type, size, rnd, minValue, maxValue);
    109        return access;
    110    };
    111 
    112    /**
    113     * @param {es3fShaderCommonFunctionTests.Types} type
    114     * @param {deRandom.Random} rnd
    115     * @param {number} minValue
    116     * @param {number} maxValue
    117     * @param {number} numValues
    118     * @param {number=} offset
    119     * @return {Array<number>}
    120     */
    121    es3fShaderCommonFunctionTests.fillRandomScalars = function(type, rnd, minValue, maxValue, numValues, offset) {
    122        offset = offset === undefined ? 0 : offset;
    123        /** @type {Array<number>} */ var access = [];
    124        for (var ndx = 0; ndx < numValues; ndx++)
    125            access[offset + ndx] = es3fShaderCommonFunctionTests.randomScalar(type, rnd, minValue, maxValue);
    126        return access;
    127    };
    128 
    129    /**
    130     * @param {number} input
    131     * @param {number} output
    132     * @return {number}
    133     */
    134    es3fShaderCommonFunctionTests.numBitsLostInOp = function(input, output) {
    135        /** @type {number} */ var inExp = tcuFloat.newFloat32(input).exponent();
    136        /** @type {number} */ var outExp = tcuFloat.newFloat32(output).exponent();
    137        return Math.max(0, inExp - outExp); // Lost due to mantissa shift.
    138    };
    139 
    140    /**
    141     * @param {number} a
    142     * @param {number} b
    143     * @return {number}
    144     */
    145    es3fShaderCommonFunctionTests.getUlpDiff = function(a, b) {
    146        /** @type {number} */ var aBits = tcuFloat.newFloat32(a).bits();
    147        /** @type {number} */ var bBits = tcuFloat.newFloat32(b).bits();
    148        return aBits > bBits ? aBits - bBits : bBits - aBits;
    149    };
    150 
    151    /**
    152     * @param {number} a
    153     * @param {number} b
    154     * @return {number}
    155     */
    156    es3fShaderCommonFunctionTests.getUlpDiffIgnoreZeroSign = function(a, b) {
    157        if (tcuFloat.newFloat32(a).isZero())
    158            return es3fShaderCommonFunctionTests.getUlpDiff(new tcuFloat.deFloat().construct(tcuFloat.newFloat32(b).sign(), 0, 0).getValue(), b);
    159        else if (tcuFloat.newFloat32(b).isZero())
    160            return es3fShaderCommonFunctionTests.getUlpDiff(a, new tcuFloat.deFloat().construct(tcuFloat.newFloat32(a).sign(), 0, 0).getValue());
    161        else
    162            return es3fShaderCommonFunctionTests.getUlpDiff(a, b);
    163    };
    164 
    165    /**
    166     * @param {gluShaderUtil.precision} precision
    167     * @return {boolean}
    168     */
    169    es3fShaderCommonFunctionTests.supportsSignedZero = function(precision) {
    170        // \note GLSL ES 3.0 doesn't really require support for -0, but we require it for highp
    171        //         as it is very widely supported.
    172        return precision == gluShaderUtil.precision.PRECISION_HIGHP;
    173    };
    174 
    175    /**
    176     * @param {number} value
    177     * @param {number} ulpDiff
    178     * @return {number}
    179     */
    180    es3fShaderCommonFunctionTests.getEpsFromMaxUlpDiff = function(value, ulpDiff) {
    181        /** @type {number} */ var exp = tcuFloat.newFloat32(value).exponent();
    182        return new tcuFloat.deFloat().construct(+1, exp, (1 << 23) | ulpDiff).getValue() - new tcuFloat.deFloat().construct(+1, exp, 1 << 23).getValue();
    183    };
    184 
    185    /**
    186     * @param {number} numAccurateBits
    187     * @return {number}
    188     */
    189    es3fShaderCommonFunctionTests.getMaxUlpDiffFromBits = function(numAccurateBits) {
    190        /** @type {number} */ var numGarbageBits = 23 - numAccurateBits;
    191        /** @type {number} */ var mask = (1 << numGarbageBits) - 1;
    192 
    193        return mask;
    194    };
    195 
    196    /**
    197     * @param {number} value
    198     * @param {number} numAccurateBits
    199     * @return {number}
    200     */
    201    es3fShaderCommonFunctionTests.getEpsFromBits = function(value, numAccurateBits) {
    202        return es3fShaderCommonFunctionTests.getEpsFromMaxUlpDiff(value, es3fShaderCommonFunctionTests.getMaxUlpDiffFromBits(numAccurateBits));
    203    };
    204 
    205    /**
    206     * @param {gluShaderUtil.precision} precision
    207     * @return {number}
    208     */
    209    es3fShaderCommonFunctionTests.getMinMantissaBits = function(precision) {
    210        /** @type {Array<number>} */ var bits = [
    211            7, // lowp
    212            10, // mediump
    213            23 // highp
    214        ];
    215 
    216        assertMsgOptions(deMath.deInBounds32(precision, 0, bits.length), 'Unexpected precision option.', false, true);
    217        return bits[precision];
    218    };
    219 
    220    /**
    221     * @constructor
    222     * @extends {tcuTestCase.DeqpTest}
    223     * @param {string} name
    224     * @param {string} description
    225     * @param {gluShaderProgram.shaderType} shaderType
    226     */
    227    es3fShaderCommonFunctionTests.CommonFunctionCase = function(name, description, shaderType) {
    228        tcuTestCase.DeqpTest.call(this, name, description);
    229        /** @type {gluShaderProgram.shaderType} */ this.m_shaderType = shaderType;
    230        /** @type {number} */ this.m_numValues = 100;
    231        /** @type {glsShaderExecUtil.ShaderExecutor} */ this.m_executor = null;
    232        /** @type {glsShaderExecUtil.ShaderSpec} */ this.m_spec = new glsShaderExecUtil.ShaderSpec();
    233        this.m_spec.version = gluShaderUtil.GLSLVersion.V300_ES;
    234        /** @type {string} */ this.m_failMsg; //!< Comparison failure help message.
    235    };
    236 
    237    es3fShaderCommonFunctionTests.CommonFunctionCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
    238    es3fShaderCommonFunctionTests.CommonFunctionCase.prototype.constructor = es3fShaderCommonFunctionTests.CommonFunctionCase;
    239 
    240    es3fShaderCommonFunctionTests.CommonFunctionCase.prototype.init = function() {
    241        assertMsgOptions(!this.m_executor, 'Shader executor should be null at this point', false, true);
    242        this.m_executor = glsShaderExecUtil.createExecutor(this.m_shaderType, this.m_spec);
    243        if (!this.m_executor.isOk())
    244            throw new Error('Compile failed');
    245    };
    246 
    247    es3fShaderCommonFunctionTests.CommonFunctionCase.prototype.deinit = function() {
    248        this.m_executor = null;
    249    };
    250 
    251    /**
    252     * @param {Array<glsShaderExecUtil.Symbol>} symbols
    253     * @return {Array<number>}
    254     */
    255    es3fShaderCommonFunctionTests.getScalarSizes = function(symbols) {
    256        /** @type {Array<number>} */ var sizes = [];
    257        for (var ndx = 0; ndx < symbols.length; ++ndx)
    258            sizes.push(symbols[ndx].varType.getScalarSize());
    259        return sizes;
    260    };
    261 
    262    /**
    263     * @param {Array<glsShaderExecUtil.Symbol>} symbols
    264     * @return {number}
    265     */
    266    es3fShaderCommonFunctionTests.computeTotalScalarSize = function(symbols) {
    267        /** @type {number} */ var totalSize = 0;
    268        for (var sym in symbols)
    269            totalSize += symbols[sym].varType.getScalarSize();
    270        return totalSize;
    271    };
    272 
    273    /**
    274     * @param {boolean} value
    275     * @return {string}
    276     */
    277    es3fShaderCommonFunctionTests.ToBoolString = function(value) {
    278        return value ? "true" : "false";
    279    };
    280 
    281    /**
    282     * @param {gluVarType.VarType} varType
    283     * @param {Array<*>} values
    284     * @return {string}
    285     */
    286    es3fShaderCommonFunctionTests.VarValue = function(varType, values) {
    287        /** @type {gluShaderUtil.DataType} */ var basicType = varType.getBasicType();
    288        /** @type {gluShaderUtil.DataType} */ var scalarType = gluShaderUtil.getDataTypeScalarTypeAsDataType(basicType);
    289        /** @type {number} */ var numComponents = gluShaderUtil.getDataTypeScalarSize(basicType);
    290        /** @type {string} */ var outputStr = "";
    291 
    292        if (numComponents > 1) {
    293            outputStr += gluShaderUtil.getDataTypeName(basicType) + "(";
    294        }
    295 
    296        for (var compNdx = 0; compNdx < numComponents; ++compNdx) {
    297            if (compNdx != 0) {
    298                outputStr += ", ";
    299            }
    300 
    301            // tcu::toHex() is all commented out in this project.
    302            // e.g. Line 199 of es3fShaderPackingFunctionTests.js
    303            switch (scalarType) {
    304                case gluShaderUtil.DataType.FLOAT:
    305                case gluShaderUtil.DataType.INT:
    306                case gluShaderUtil.DataType.UINT:
    307                    outputStr += values[compNdx];
    308                    break;
    309                case gluShaderUtil.DataType.BOOL:
    310                    outputStr += es3fShaderCommonFunctionTests.ToBoolString(values[compNdx]);
    311                    break;
    312 
    313                default:
    314                    throw Error('Unrecognized dataType ' + scalarType);
    315            }
    316        }
    317 
    318        if (numComponents > 1) {
    319            outputStr += ")";
    320        }
    321 
    322        return outputStr;
    323    }
    324 
    325    /**
    326     * @return {tcuTestCase.IterateResult}
    327     */
    328    es3fShaderCommonFunctionTests.CommonFunctionCase.prototype.iterate = function() {
    329        /** @type {number} */ var numInputScalars = es3fShaderCommonFunctionTests.computeTotalScalarSize(this.m_spec.inputs);
    330        /** @type {number} */ var numOutputScalars = es3fShaderCommonFunctionTests.computeTotalScalarSize(this.m_spec.outputs);
    331        /** @type {Array<goog.TypedArray>} */ var inputData = [];
    332        /** @type {Array<goog.TypedArray>} */ var outputData = [];
    333        /** @type {gluShaderUtil.DataType} */ var inputType = this.m_spec.inputs[0].varType.getBasicType();
    334        /** @type {gluShaderUtil.DataType} */ var outputType = this.m_spec.outputs[0].varType.getBasicType();
    335        /** @type {Array<Array<number>>} */ var inputValues;
    336        /** @type {ArrayBuffer} */ var outputValues;
    337        inputValues = this.getInputValues(this.m_numValues);
    338 
    339        for (var inNdx = 0; inNdx < inputValues.length; inNdx++) {
    340            var data = inputType >= gluShaderUtil.DataType.FLOAT && inputType <= gluShaderUtil.DataType.FLOAT_VEC4 ? new Float32Array(inputValues[inNdx]) :
    341                       inputType >= gluShaderUtil.DataType.INT && inputType <= gluShaderUtil.DataType.INT_VEC4 ? new Int32Array(inputValues[inNdx]) :
    342                       inputType >= gluShaderUtil.DataType.UINT && inputType <= gluShaderUtil.DataType.UINT_VEC4 ? new Uint32Array(inputValues[inNdx]) :
    343                       null;
    344            inputData.push(data);
    345        }
    346 
    347        // Execute shader.
    348        this.m_executor.useProgram();
    349        outputValues = this.m_executor.execute(this.m_numValues, inputData);
    350        for (var outNdx = 0; outNdx < outputValues.length; outNdx++) {
    351            var data = outputType >= gluShaderUtil.DataType.FLOAT && outputType <= gluShaderUtil.DataType.FLOAT_VEC4 ? new Float32Array(outputValues[outNdx].buffer) :
    352                        outputType >= gluShaderUtil.DataType.INT && outputType <= gluShaderUtil.DataType.INT_VEC4 ? new Int32Array(outputValues[outNdx].buffer) :
    353                        outputType >= gluShaderUtil.DataType.UINT && outputType <= gluShaderUtil.DataType.UINT_VEC4 ? new Uint32Array(outputValues[outNdx].buffer) :
    354                        outputType >= gluShaderUtil.DataType.BOOL && outputType <= gluShaderUtil.DataType.BOOL_VEC4 ? new Int32Array(outputValues[outNdx].buffer) :
    355                        null;
    356            outputData.push(data);
    357        }
    358 
    359        // TODO: verify proper TypedArray for BOOL types; defaulting to Int32Array in the mean time (outputValues returns 400 bytes, we need 100 elements)
    360        // Compare results.
    361        /** @type {Array<number>} */ var inScalarSizes = es3fShaderCommonFunctionTests.getScalarSizes(this.m_spec.inputs);
    362        /** @type {Array<number>} */ var outScalarSizes = es3fShaderCommonFunctionTests.getScalarSizes(this.m_spec.outputs);
    363        /** @type {Array<*>} */ var curInputPtr = [];
    364        /** @type {Array<*>} */ var curOutputPtr = [];
    365        /** @type {number} */ var numFailed = 0;
    366 
    367        for (var inNdx = 0; inNdx < inputData.length; inNdx++) {
    368            curInputPtr[inNdx] = [];
    369            for (var valNdx = 0; valNdx < inputData[inNdx].length; valNdx += inScalarSizes[inNdx])
    370                curInputPtr[inNdx].push(inputData[inNdx].slice(valNdx, valNdx + inScalarSizes[inNdx]));
    371        }
    372 
    373        for (var outNdx = 0; outNdx < outputData.length; outNdx++) {
    374            curOutputPtr[outNdx] = [];
    375            for (var valNdx = 0; valNdx < outputData[outNdx].length; valNdx += outScalarSizes[outNdx])
    376                curOutputPtr[outNdx].push(outputData[outNdx].slice(valNdx, valNdx + outScalarSizes[outNdx]));
    377        }
    378 
    379        this.m_failMsg = '';
    380        for (var valNdx = 0; valNdx < this.m_numValues; valNdx++) {
    381            var curInputValues = [];
    382            var curOutputValues = [];
    383            for (var inNdx = 0; inNdx < inputData.length; inNdx++) {
    384                curInputValues.push(curInputPtr[inNdx][valNdx]);
    385            }
    386            for (var outNdx = 0; outNdx < outputData.length; outNdx++) {
    387                curOutputValues.push(curOutputPtr[outNdx][valNdx]);
    388            }
    389            if (!this.compare(curInputValues, curOutputValues)) {
    390                // \todo [2013-08-08 pyry] We probably want to log reference value as well?
    391 
    392                bufferedLogToConsole('ERROR: comparison failed for value ' + valNdx + ':\n ' + this.m_failMsg);
    393                bufferedLogToConsole(' inputs:');
    394                for (var inNdx = 0; inNdx < inputData.length; ++inNdx) {
    395                    var varValue = es3fShaderCommonFunctionTests.VarValue(this.m_spec.inputs[0].varType, curInputValues[inNdx]);
    396                    bufferedLogToConsole(' ' + this.m_spec.inputs[inNdx].name + ' = ' + varValue);
    397                }
    398 
    399                bufferedLogToConsole(' outputs:');
    400                for (var outNdx = 0; outNdx < outputData.length; ++outNdx) {
    401                    var varValue = es3fShaderCommonFunctionTests.VarValue(this.m_spec.inputs[0].varType, curOutputValues[outNdx]);
    402                    bufferedLogToConsole(' ' + this.m_spec.outputs[outNdx].name + ' = ' + varValue);
    403                }
    404 
    405                this.m_failMsg = '';
    406                numFailed += 1;
    407            }
    408        }
    409 
    410        bufferedLogToConsole((this.m_numValues - numFailed) + ' / ' + this.m_numValues + ' values passed');
    411 
    412        /** @type {boolean} */ var isOk = numFailed === 0;
    413 
    414        if (!isOk)
    415            testFailedOptions('Result comparison failed', false);
    416        else
    417            testPassedOptions('Pass', true);
    418 
    419        return tcuTestCase.IterateResult.STOP;
    420    };
    421 
    422    /**
    423     * @param {gluShaderUtil.precision} precision
    424     * @return {string}
    425     */
    426    es3fShaderCommonFunctionTests.getPrecisionPostfix = function(precision) {
    427        /** @type {Array<string>} */ var s_postfix = [
    428            '_lowp',
    429            '_mediump',
    430            '_highp'
    431        ];
    432        assertMsgOptions(0 <= precision && precision < s_postfix.length, 'Error: Out of range', false, true);
    433        return s_postfix[precision];
    434    };
    435 
    436    /**
    437     * @param {gluShaderProgram.shaderType} shaderType
    438     * @return {string}
    439     */
    440    es3fShaderCommonFunctionTests.getShaderTypePostfix = function(shaderType) {
    441        /** @type {Array<string>} */ var s_postfix = [
    442            '_vertex',
    443            '_fragment'
    444        ];
    445        assertMsgOptions(0 <= shaderType && shaderType < s_postfix.length, 'Error Out of range', false, true);
    446        return s_postfix[shaderType];
    447    };
    448 
    449    /**
    450     * @param {gluShaderUtil.DataType} baseType
    451     * @param {gluShaderUtil.precision} precision
    452     * @param {gluShaderProgram.shaderType} shaderType
    453     * @return {string}
    454     */
    455    es3fShaderCommonFunctionTests.getCommonFuncCaseName = function(baseType, precision, shaderType) {
    456        return gluShaderUtil.getDataTypeName(baseType) +
    457            es3fShaderCommonFunctionTests.getPrecisionPostfix(precision) +
    458            es3fShaderCommonFunctionTests.getShaderTypePostfix(shaderType);
    459    };
    460 
    461    /**
    462     * @constructor
    463     * @extends {es3fShaderCommonFunctionTests.CommonFunctionCase}
    464     * @param {gluShaderUtil.DataType} baseType
    465     * @param {gluShaderUtil.precision} precision
    466     * @param {gluShaderProgram.shaderType} shaderType
    467     */
    468    es3fShaderCommonFunctionTests.AbsCase = function(baseType, precision, shaderType) {
    469        es3fShaderCommonFunctionTests.CommonFunctionCase.call(this,
    470            es3fShaderCommonFunctionTests.getCommonFuncCaseName(baseType, precision, shaderType),
    471            'abs', shaderType);
    472        this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(baseType, precision)));
    473        this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(baseType, precision)));
    474        this.m_spec.source = 'out0 = abs(in0);';
    475    };
    476 
    477    es3fShaderCommonFunctionTests.AbsCase.prototype = Object.create(es3fShaderCommonFunctionTests.CommonFunctionCase.prototype);
    478    es3fShaderCommonFunctionTests.AbsCase.prototype.constructor = es3fShaderCommonFunctionTests.AbsCase;
    479 
    480    /**
    481     * @param {number} numValues
    482     * @return {*}
    483     */
    484    es3fShaderCommonFunctionTests.AbsCase.prototype.getInputValues = function(numValues) {
    485        /** @type {Array<Array<number>>} */ var floatRanges = [
    486            [-2.0, 2.0], // lowp
    487            [-1e3, 1e3], // mediump
    488            [-1e7, 1e7] // highp
    489        ];
    490 
    491        /** @type {Array<Array<number>>} */ var intRanges = [
    492            [-(1 << 7) + 1, (1 << 7) - 1],
    493            [-(1 << 15) + 1, (1 << 15) - 1],
    494            [-0x80000000 + 1, 0x7fffffff]
    495        ];
    496 
    497        /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0x235fac);
    498 
    499        /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
    500        /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
    501        /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
    502        /** @type {Array<Array<number>>} */ var values = [];
    503        values[0] = [];
    504 
    505        if (gluShaderUtil.isDataTypeFloatOrVec(type))
    506            values[0] = es3fShaderCommonFunctionTests.fillRandomScalars(es3fShaderCommonFunctionTests.Types.FLOAT, rnd, floatRanges[precision][0], floatRanges[precision][1], numValues * scalarSize);
    507        else
    508            values[0] = es3fShaderCommonFunctionTests.fillRandomScalars(es3fShaderCommonFunctionTests.Types.INT, rnd, intRanges[precision][0], intRanges[precision][1], numValues * scalarSize);
    509 
    510        return values;
    511    };
    512 
    513    /**
    514     * @param {*} inputs
    515     * @param {*} outputs
    516     * @return {boolean}
    517     */
    518    es3fShaderCommonFunctionTests.AbsCase.prototype.compare = function(inputs, outputs) {
    519        /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
    520        /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
    521        /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
    522 
    523        /** @type {number} */ var in0;
    524        /** @type {number} */ var out0;
    525        /** @type {number} */ var ref0;
    526 
    527        if (gluShaderUtil.isDataTypeFloatOrVec(type)) {
    528            /** @type {number} */ var mantissaBits = es3fShaderCommonFunctionTests.getMinMantissaBits(precision);
    529            /** @type {number} */ var maxUlpDiff = (1 << (23 - mantissaBits)) - 1;
    530 
    531            for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
    532                in0 = inputs[0][compNdx];
    533                out0 = outputs[0][compNdx];
    534                ref0 = Math.abs(in0);
    535                /** @type {number} */ var ulpDiff0 = es3fShaderCommonFunctionTests.getUlpDiff(out0, ref0);
    536 
    537                if (ulpDiff0 > maxUlpDiff) {
    538                    this.m_failMsg += 'Expected [' + compNdx + '] = ' + ref0 /*HexFloat(ref0)*/ + ' with ULP threshold ' + maxUlpDiff + ', got ULP diff ' + ulpDiff0;
    539                    return false;
    540                }
    541            }
    542        } else
    543            for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
    544                in0 = inputs[0][compNdx];
    545                out0 = outputs[0][compNdx];
    546                ref0 = Math.abs(in0);
    547 
    548                if (out0 != ref0) {
    549                    this.m_failMsg += 'Expected [' + compNdx + '] = ' + ref0;
    550                    return false;
    551                }
    552            }
    553 
    554        return true;
    555    };
    556 
    557    /**
    558     * @constructor
    559     * @extends {es3fShaderCommonFunctionTests.CommonFunctionCase}
    560     * @param {gluShaderUtil.DataType} baseType
    561     * @param {gluShaderUtil.precision} precision
    562     * @param {gluShaderProgram.shaderType} shaderType
    563     */
    564    es3fShaderCommonFunctionTests.SignCase = function(baseType, precision, shaderType) {
    565        es3fShaderCommonFunctionTests.CommonFunctionCase.call(this,
    566            es3fShaderCommonFunctionTests.getCommonFuncCaseName(baseType, precision, shaderType),
    567            'sign', shaderType);
    568        this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(baseType, precision)));
    569        this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(baseType, precision)));
    570        this.m_spec.source = 'out0 = sign(in0);';
    571    };
    572 
    573    es3fShaderCommonFunctionTests.SignCase.prototype = Object.create(es3fShaderCommonFunctionTests.CommonFunctionCase.prototype);
    574    es3fShaderCommonFunctionTests.SignCase.prototype.constructor = es3fShaderCommonFunctionTests.SignCase;
    575 
    576    /**
    577     * @param {number} numValues
    578     * @return {*}
    579     */
    580    es3fShaderCommonFunctionTests.SignCase.prototype.getInputValues = function(numValues) {
    581        /** @type {Array<Array<number>>} */ var floatRanges = [
    582            [-2.0, 2.0], // lowp
    583            [-1e4, 1e4], // mediump
    584            [-1e8, 1e8] // highp
    585        ];
    586 
    587        /** @type {Array<Array<number>>} */ var intRanges = [
    588            [-(1 << 7), (1 << 7) - 1],
    589            [-(1 << 15), (1 << 15) - 1],
    590            [0x80000000, 0x7fffffff]
    591        ];
    592 
    593        /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0x324);
    594 
    595        /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
    596        /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
    597        /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
    598        /** @type {Array<Array<number>>} */ var values = [];
    599        values[0] = [];
    600 
    601        if (gluShaderUtil.isDataTypeFloatOrVec(type)) {
    602            // Special cases.
    603            // [dag] The special cases are 1, -1, and 0
    604            var specialCases = [1.0, -1.0, 0.0];
    605            for (var caseNdx = 0; caseNdx < specialCases.length; caseNdx++)
    606                for (var scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++) {
    607                    values[0].push(specialCases[caseNdx]);
    608                }
    609            values[0] = values[0].concat(es3fShaderCommonFunctionTests.fillRandomScalars(es3fShaderCommonFunctionTests.Types.FLOAT, rnd, floatRanges[precision][0], floatRanges[precision][1], (numValues - 3) * scalarSize));
    610        } else {
    611            var specialCases = [1, -1, 0];
    612            for (var caseNdx = 0; caseNdx < specialCases.length; caseNdx++)
    613                for (var scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++) {
    614                    values[0].push(specialCases[caseNdx]);
    615                }
    616            values[0] = values[0].concat(es3fShaderCommonFunctionTests.fillRandomScalars(es3fShaderCommonFunctionTests.Types.INT, rnd, intRanges[precision][0], intRanges[precision][1], (numValues - 3) * scalarSize));
    617        }
    618 
    619        return values;
    620    };
    621 
    622    /**
    623     * @param {*} inputs
    624     * @param {*} outputs
    625     * @return {boolean}
    626     */
    627    es3fShaderCommonFunctionTests.SignCase.prototype.compare = function(inputs, outputs) {
    628        /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
    629        /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
    630        /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
    631 
    632        /** @type {number} */ var in0;
    633        /** @type {number} */ var out0;
    634        /** @type {number} */ var ref0;
    635 
    636        if (gluShaderUtil.isDataTypeFloatOrVec(type)) {
    637            // Both highp and mediump should be able to represent -1, 0, and +1 exactly
    638            /** @type {number} */ var maxUlpDiff = precision === gluShaderUtil.precision.PRECISION_LOWP ?
    639                es3fShaderCommonFunctionTests.getMaxUlpDiffFromBits(es3fShaderCommonFunctionTests.getMinMantissaBits(precision)) :
    640                0;
    641 
    642            for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
    643                in0 = inputs[0][compNdx];
    644                out0 = outputs[0][compNdx];
    645                ref0 = in0 < 0.0 ? -1.0 :
    646                       in0 > 0.0 ? 1.0 : 0.0;
    647                /** @type {number} */ var ulpDiff0 = es3fShaderCommonFunctionTests.getUlpDiff(out0, ref0);
    648 
    649                if (ulpDiff0 > maxUlpDiff) {
    650                    this.m_failMsg += 'Expected [' + compNdx + '] = ' + ref0 /*HexFloat(ref0)*/ + ' with ULP threshold ' + maxUlpDiff + ', got ULP diff ' + ulpDiff0;
    651                    return false;
    652                }
    653            }
    654        } else {
    655            for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
    656                in0 = inputs[0][compNdx];
    657                out0 = outputs[0][compNdx];
    658                ref0 = in0 < 0 ? -1 :
    659                       in0 > 0 ? 1 : 0;
    660 
    661                if (out0 != ref0) {
    662                    this.m_failMsg += 'Expected [' + compNdx + '] = ' + ref0;
    663                    return false;
    664                }
    665            }
    666        }
    667 
    668        return true;
    669    };
    670 
    671    /**
    672     * @param {number} v
    673     * @return {number}
    674     */
    675    es3fShaderCommonFunctionTests.roundEven = function(v) {
    676        /** @type {number} */ var q = deMath.deFloatFrac(v);
    677        /** @type {number} */ var truncated = Math.trunc(v - q);
    678        /** @type {number} */ var rounded = (q > 0.5) ? (truncated + 1) : // Rounded up
    679            (q == 0.5 && (truncated % 2 != 0)) ? (truncated + 1) : // Round to nearest even at 0.5
    680            truncated; // Rounded down
    681        return rounded;
    682    };
    683 
    684    /**
    685     * @constructor
    686     * @extends {es3fShaderCommonFunctionTests.CommonFunctionCase}
    687     * @param {gluShaderUtil.DataType} baseType
    688     * @param {gluShaderUtil.precision} precision
    689     * @param {gluShaderProgram.shaderType} shaderType
    690     */
    691    es3fShaderCommonFunctionTests.RoundEvenCase = function(baseType, precision, shaderType) {
    692        es3fShaderCommonFunctionTests.CommonFunctionCase.call(this,
    693            es3fShaderCommonFunctionTests.getCommonFuncCaseName(baseType, precision, shaderType),
    694            'roundEven', shaderType);
    695        this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(baseType, precision)));
    696        this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(baseType, precision)));
    697        this.m_spec.source = 'out0 = roundEven(in0);';
    698    };
    699 
    700    es3fShaderCommonFunctionTests.RoundEvenCase.prototype = Object.create(es3fShaderCommonFunctionTests.CommonFunctionCase.prototype);
    701    es3fShaderCommonFunctionTests.RoundEvenCase.prototype.constructor = es3fShaderCommonFunctionTests.RoundEvenCase;
    702 
    703    /**
    704     * @param {number} numValues
    705     * @return {*}
    706     */
    707    es3fShaderCommonFunctionTests.RoundEvenCase.prototype.getInputValues = function(numValues) {
    708        /** @type {Array<Array<number>>} */ var ranges = [
    709            [-2.0, 2.0], // lowp
    710            [-1e3, 1e3], // mediump
    711            [-1e7, 1e7] // highp
    712        ];
    713 
    714        /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0xac23f);
    715 
    716        /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
    717        /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
    718        /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
    719        /** @type {number} */ var numSpecialCases = 0;
    720        /** @type {Array<Array<number>>} */ var values = [];
    721        values[0] = [];
    722        // Special cases.
    723        if (precision !== gluShaderUtil.precision.PRECISION_LOWP) {
    724            assertMsgOptions(numValues >= 20, 'numValues should be greater or equal than 20', false, true);
    725            for (var ndx = 0; ndx < 20; ndx++) {
    726                /** @type {number} */ var v = deMath.clamp(ndx - 10.5, ranges[precision][0], ranges[precision][1]);
    727                for (var scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++) {
    728                    values[0].push(v);
    729                }
    730                numSpecialCases += 1;
    731            }
    732        }
    733 
    734        // Random cases.
    735        values[0] = values[0].concat(es3fShaderCommonFunctionTests.fillRandomScalars(es3fShaderCommonFunctionTests.Types.FLOAT, rnd, ranges[precision][0], ranges[precision][1], (numValues - numSpecialCases) * scalarSize));
    736 
    737        // If precision is mediump, make sure values can be represented in fp16 exactly
    738        if (precision === gluShaderUtil.precision.PRECISION_MEDIUMP)
    739            es3fShaderCommonFunctionTests.vecToFloat16(values[0]);
    740 
    741        return values;
    742    };
    743 
    744    /**
    745     * @param {*} inputs
    746     * @param {*} outputs
    747     * @return {boolean}
    748     */
    749    es3fShaderCommonFunctionTests.RoundEvenCase.prototype.compare = function(inputs, outputs) {
    750        /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
    751        /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
    752        /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
    753        /** @type {number} */ var in0;
    754        /** @type {number} */ var out0;
    755 
    756        if (precision == gluShaderUtil.precision.PRECISION_HIGHP || precision == gluShaderUtil.precision.PRECISION_MEDIUMP) {
    757            // Require exact rounding result.
    758            for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
    759                in0 = inputs[0][compNdx];
    760                out0 = outputs[0][compNdx];
    761                /** @type {number} */ var ref = es3fShaderCommonFunctionTests.roundEven(in0);
    762 
    763                /** @type {number} */ var ulpDiff = es3fShaderCommonFunctionTests.getUlpDiffIgnoreZeroSign(out0, ref);
    764 
    765                if (ulpDiff > 0) {
    766                    this.m_failMsg += 'Expected [' + compNdx + '] = ' + ref + ', got ULP diff ' + ulpDiff;
    767                    return false;
    768                }
    769            }
    770        } else {
    771            /** @type {number} */ var mantissaBits = es3fShaderCommonFunctionTests.getMinMantissaBits(precision);
    772            /** @type {number} */ var maxUlpDiff = es3fShaderCommonFunctionTests.getMaxUlpDiffFromBits(mantissaBits); // ULP diff for rounded integer value.
    773            /** @type {number} */ var eps = es3fShaderCommonFunctionTests.getEpsFromBits(1.0, mantissaBits); // epsilon for rounding bounds
    774 
    775            for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
    776                in0 = inputs[0][compNdx];
    777                out0 = outputs[0][compNdx];
    778                /** @type {number} */ var minRes = Math.floor(es3fShaderCommonFunctionTests.roundEven(in0 - eps));
    779                /** @type {number} */ var maxRes = Math.floor(es3fShaderCommonFunctionTests.roundEven(in0 + eps));
    780                /** @type {boolean} */ var anyOk = false;
    781 
    782                for (var roundedVal = minRes; roundedVal <= maxRes; roundedVal++) {
    783                    ulpDiff = es3fShaderCommonFunctionTests.getUlpDiffIgnoreZeroSign(out0, roundedVal);
    784 
    785                    if (ulpDiff <= maxUlpDiff) {
    786                        anyOk = true;
    787                        break;
    788                    }
    789                }
    790 
    791                if (!anyOk) {
    792                    this.m_failMsg += 'Expected [' + compNdx + '] = [' + minRes + ', ' + maxRes + '] with ULP threshold ' + maxUlpDiff;
    793                    return false;
    794                }
    795            }
    796        }
    797 
    798        return true;
    799    };
    800 
    801    /**
    802     * @constructor
    803     * @extends {es3fShaderCommonFunctionTests.CommonFunctionCase}
    804     * @param {gluShaderUtil.DataType} baseType
    805     * @param {gluShaderUtil.precision} precision
    806     * @param {gluShaderProgram.shaderType} shaderType
    807     */
    808    es3fShaderCommonFunctionTests.ModfCase = function(baseType, precision, shaderType) {
    809        es3fShaderCommonFunctionTests.CommonFunctionCase.call(this,
    810            es3fShaderCommonFunctionTests.getCommonFuncCaseName(baseType, precision, shaderType),
    811            'modf', shaderType);
    812        this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(baseType, precision)));
    813        this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(baseType, precision)));
    814        this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out1', gluVarType.newTypeBasic(baseType, precision)));
    815        this.m_spec.source = 'out0 = modf(in0, out1);';
    816    };
    817 
    818    es3fShaderCommonFunctionTests.ModfCase.prototype = Object.create(es3fShaderCommonFunctionTests.CommonFunctionCase.prototype);
    819    es3fShaderCommonFunctionTests.ModfCase.prototype.constructor = es3fShaderCommonFunctionTests.ModfCase;
    820 
    821    /**
    822     * @param {number} numValues
    823     * @return {*}
    824     */
    825    es3fShaderCommonFunctionTests.ModfCase.prototype.getInputValues = function(numValues) {
    826        /** @type {Array<Array<number>>} */ var ranges = [
    827            [-2.0, 2.0], // lowp
    828            [-1e3, 1e3], // mediump
    829            [-1e7, 1e7] // highp
    830        ];
    831 
    832        /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0xac23f);
    833 
    834        /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
    835        /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
    836        /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
    837        /** @type {Array<Array<number>>} */ var values = [];
    838        values[0] = es3fShaderCommonFunctionTests.fillRandomScalars(es3fShaderCommonFunctionTests.Types.FLOAT, rnd, ranges[precision][0], ranges[precision][1], numValues * scalarSize);
    839 
    840        return values;
    841    };
    842 
    843    /**
    844     * @param {*} inputs
    845     * @param {*} outputs
    846     * @return {boolean}
    847     */
    848    es3fShaderCommonFunctionTests.ModfCase.prototype.compare = function(inputs, outputs) {
    849        /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
    850        /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
    851        /** @type {boolean} */ var hasZeroSign = es3fShaderCommonFunctionTests.supportsSignedZero(precision);
    852        /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
    853        /** @type {number} */ var mantissaBits = es3fShaderCommonFunctionTests.getMinMantissaBits(precision);
    854        /** @type {number} */ var in0;
    855        /** @type {number} */ var out0;
    856        /** @type {number} */ var out1;
    857 
    858        for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
    859            in0 = inputs[0][compNdx];
    860            out0 = outputs[0][compNdx];
    861            out1 = outputs[1][compNdx];
    862 
    863            /** @type {number} */ var refOut1 = Math.floor(in0);
    864            /** @type {number} */ var refOut0 = in0 - refOut1;
    865 
    866            /** @type {number} */ var bitsLost = precision != gluShaderUtil.precision.PRECISION_HIGHP ? es3fShaderCommonFunctionTests.numBitsLostInOp(in0, refOut0) : 0;
    867            /** @type {number} */ var maxUlpDiff = es3fShaderCommonFunctionTests.getMaxUlpDiffFromBits(Math.max(mantissaBits - bitsLost, 0));
    868 
    869            /** @type {number} */ var resSum = out0 + out1;
    870 
    871            /** @type {number} */ var ulpDiff = hasZeroSign ? es3fShaderCommonFunctionTests.getUlpDiff(resSum, in0) : es3fShaderCommonFunctionTests.getUlpDiffIgnoreZeroSign(resSum, in0);
    872 
    873            if (ulpDiff > maxUlpDiff) {
    874                this.m_failMsg += 'Expected [' + compNdx + '] = (' + refOut0 + ') + (' + refOut1 + ') = ' + in0 + ' with ULP threshold ' +
    875                            maxUlpDiff + ', got ULP diff ' + ulpDiff;
    876                return false;
    877            }
    878        }
    879 
    880        return true;
    881    };
    882 
    883    /**
    884     * @constructor
    885     * @extends {es3fShaderCommonFunctionTests.CommonFunctionCase}
    886     * @param {gluShaderUtil.DataType} baseType
    887     * @param {gluShaderUtil.precision} precision
    888     * @param {gluShaderProgram.shaderType} shaderType
    889     */
    890    es3fShaderCommonFunctionTests.IsnanCase = function(baseType, precision, shaderType) {
    891        es3fShaderCommonFunctionTests.CommonFunctionCase.call(this,
    892            es3fShaderCommonFunctionTests.getCommonFuncCaseName(baseType, precision, shaderType),
    893            'isnan', shaderType);
    894        assertMsgOptions(gluShaderUtil.isDataTypeFloatOrVec(baseType), 'Assert error.', false, true);
    895 
    896        /** @type {number} */ var vecSize = gluShaderUtil.getDataTypeScalarSize(baseType);
    897        /** @type {gluShaderUtil.DataType} */ var boolType = vecSize > 1 ?
    898            gluShaderUtil.getDataTypeVector(gluShaderUtil.DataType.BOOL, vecSize) :
    899            gluShaderUtil.DataType.BOOL;
    900 
    901        this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(baseType, precision)));
    902        this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(boolType)));
    903        this.m_spec.source = 'out0 = isnan(in0);';
    904    };
    905 
    906    es3fShaderCommonFunctionTests.IsnanCase.prototype = Object.create(es3fShaderCommonFunctionTests.CommonFunctionCase.prototype);
    907    es3fShaderCommonFunctionTests.IsnanCase.prototype.constructor = es3fShaderCommonFunctionTests.IsnanCase;
    908 
    909    /**
    910     * @param {number} numValues
    911     * @return {*}
    912     */
    913    es3fShaderCommonFunctionTests.IsnanCase.prototype.getInputValues = function(numValues) {
    914        /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0xc2a39f);
    915 
    916        /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
    917        /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
    918        /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
    919        /** @type {number} */ var mantissaBits = es3fShaderCommonFunctionTests.getMinMantissaBits(precision);
    920        /** @type {number} */ var mantissaMask = (~es3fShaderCommonFunctionTests.getMaxUlpDiffFromBits(mantissaBits)) & ((1 << 23) - 1);
    921        /** @type {Array<Array<number>>} */ var values = [];
    922        values[0] = [];
    923 
    924        for (var valNdx = 0; valNdx < numValues * scalarSize; valNdx++) {
    925            /** @type {boolean} */ var isNan = rnd.getFloat() > 0.3;
    926            /** @type {boolean} */ var isInf = !isNan && rnd.getFloat() > 0.4;
    927            /** @type {number} */ var mantissa = !isInf ? ((1 << 22) | (Math.abs(rnd.getInt()) & mantissaMask)) : 0;
    928            /** @type {number} */ var exp = !isNan && !isInf ? (Math.abs(rnd.getInt()) & 0x7f) : 0xff;
    929            /** @type {number} */ var sign = Math.abs(rnd.getInt()) & 0x1;
    930            /** @type {number} */ var value = (sign << 31) | (exp << 23) | mantissa;
    931 
    932            // Convert int to float.
    933            var view = new DataView(new ArrayBuffer(4));
    934            view.setInt32(0, value, true);
    935            value = view.getFloat32(0, true);
    936 
    937            assertMsgOptions(tcuFloat.newFloat32(value).isInf() === isInf && tcuFloat.newFloat32(value).isNaN() === isNan, 'Assert error.', false, true);
    938 
    939            values[0].push(value);
    940        }
    941 
    942        return values;
    943    };
    944 
    945    /**
    946     * @param {*} inputs
    947     * @param {*} outputs
    948     * @return {boolean}
    949     */
    950    es3fShaderCommonFunctionTests.IsnanCase.prototype.compare = function(inputs, outputs) {
    951        /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
    952        /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
    953        /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
    954 
    955        /** @type {number} */ var in0;
    956        /** @type {number} */ var out0;
    957        /** @type {number} */ var ref;
    958 
    959        if (precision === gluShaderUtil.precision.PRECISION_HIGHP) {
    960            for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
    961                in0 = inputs[0][compNdx];
    962                out0 = outputs[0][compNdx];
    963                ref = tcuFloat.newFloat32(in0).isNaN() ? 1 : 0;
    964 
    965                if (out0 !== ref) {
    966                    this.m_failMsg += 'Expected [' + compNdx + '] = ' + ref;
    967                    return false;
    968                }
    969            }
    970        } else {
    971            for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
    972                out0 = outputs[0][compNdx];
    973 
    974                if (out0 !== 0 && out0 !== 1) {
    975                    this.m_failMsg += 'Expected [' + compNdx + '] = 0 / 1';
    976                    return false;
    977                }
    978            }
    979        }
    980        return true;
    981    };
    982 
    983    /**
    984     * @constructor
    985     * @extends {es3fShaderCommonFunctionTests.CommonFunctionCase}
    986     * @param {gluShaderUtil.DataType} baseType
    987     * @param {gluShaderUtil.precision} precision
    988     * @param {gluShaderProgram.shaderType} shaderType
    989     */
    990    es3fShaderCommonFunctionTests.IsinfCase = function(baseType, precision, shaderType) {
    991        es3fShaderCommonFunctionTests.CommonFunctionCase.call(this,
    992            es3fShaderCommonFunctionTests.getCommonFuncCaseName(baseType, precision, shaderType),
    993            'isinf', shaderType);
    994        assertMsgOptions(gluShaderUtil.isDataTypeFloatOrVec(baseType), 'Assert error.', false, true);
    995 
    996        /** @type {number} */ var vecSize = gluShaderUtil.getDataTypeScalarSize(baseType);
    997        /** @type {gluShaderUtil.DataType} */ var boolType = vecSize > 1 ?
    998            gluShaderUtil.getDataTypeVector(gluShaderUtil.DataType.BOOL, vecSize) :
    999            gluShaderUtil.DataType.BOOL;
   1000 
   1001        this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(baseType, precision)));
   1002        this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(boolType)));
   1003        this.m_spec.source = 'out0 = isinf(in0);';
   1004    };
   1005 
   1006    es3fShaderCommonFunctionTests.IsinfCase.prototype = Object.create(es3fShaderCommonFunctionTests.CommonFunctionCase.prototype);
   1007    es3fShaderCommonFunctionTests.IsinfCase.prototype.constructor = es3fShaderCommonFunctionTests.IsinfCase;
   1008 
   1009    /**
   1010     * @param {number} numValues
   1011     * @return {*}
   1012     */
   1013    es3fShaderCommonFunctionTests.IsinfCase.prototype.getInputValues = function(numValues) {
   1014        /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0xc2a39f);
   1015 
   1016        /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
   1017        /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
   1018        /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
   1019        /** @type {number} */ var mantissaBits = es3fShaderCommonFunctionTests.getMinMantissaBits(precision);
   1020        /** @type {number} */ var mantissaMask = (~es3fShaderCommonFunctionTests.getMaxUlpDiffFromBits(mantissaBits)) & ((1 << 23) - 1);
   1021        /** @type {Array<Array<number>>} */ var values = [];
   1022        values[0] = [];
   1023 
   1024        for (var valNdx = 0; valNdx < numValues * scalarSize; valNdx++) {
   1025            /** @type {boolean} */ var isInf = rnd.getFloat() > 0.3;
   1026            /** @type {boolean} */ var isNan = !isInf && rnd.getFloat() > 0.4;
   1027            /** @type {number} */ var mantissa = !isInf ? ((1 << 22) | (Math.abs(rnd.getInt()) & mantissaMask)) : 0;
   1028            /** @type {number} */ var exp = !isNan && !isInf ? (Math.abs(rnd.getInt()) & 0x7f) : 0xff;
   1029            /** @type {number} */ var sign = Math.abs(rnd.getInt()) & 0x1;
   1030            /** @type {number} */ var value = (sign << 31) | (exp << 23) | mantissa;
   1031 
   1032            // Convert int to float.
   1033            var view = new DataView(new ArrayBuffer(4));
   1034            view.setInt32(0, value, true);
   1035            value = view.getFloat32(0, true);
   1036 
   1037            assertMsgOptions(tcuFloat.newFloat32(value).isInf() === isInf && tcuFloat.newFloat32(value).isNaN() === isNan, 'Assert error.', false, true);
   1038 
   1039            values[0].push(value);
   1040        }
   1041 
   1042        return values;
   1043    };
   1044 
   1045    /**
   1046     * @param {*} inputs
   1047     * @param {*} outputs
   1048     * @return {boolean}
   1049     */
   1050    es3fShaderCommonFunctionTests.IsinfCase.prototype.compare = function(inputs, outputs) {
   1051        /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
   1052        /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
   1053        /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
   1054 
   1055        /** @type {number} */ var in0;
   1056        /** @type {number} */ var out0;
   1057        /** @type {number} */ var ref;
   1058 
   1059        if (precision === gluShaderUtil.precision.PRECISION_HIGHP) {
   1060            for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
   1061                in0 = inputs[0][compNdx];
   1062                out0 = outputs[0][compNdx];
   1063                ref = tcuFloat.newFloat32(in0).isInf() ? 1 : 0;
   1064 
   1065                if (out0 !== ref) {
   1066                    this.m_failMsg += 'Expected [' + compNdx + '] = ' + ref;
   1067                    return false;
   1068                }
   1069            }
   1070        } else {
   1071            for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
   1072                out0 = outputs[0][compNdx];
   1073 
   1074                if (out0 !== 0 && out0 !== 1) {
   1075                    this.m_failMsg += 'Expected [' + compNdx + '] = 0 / 1';
   1076                    return false;
   1077                }
   1078            }
   1079        }
   1080        return true;
   1081    };
   1082 
   1083    /**
   1084     * @constructor
   1085     * @extends {es3fShaderCommonFunctionTests.CommonFunctionCase}
   1086     * @param {gluShaderUtil.DataType} baseType
   1087     * @param {gluShaderUtil.precision} precision
   1088     * @param {gluShaderProgram.shaderType} shaderType
   1089     * @param {boolean} outIsSigned
   1090     */
   1091    es3fShaderCommonFunctionTests.FloatBitsToUintIntCase = function(baseType, precision, shaderType, outIsSigned) {
   1092        es3fShaderCommonFunctionTests.CommonFunctionCase.call(this,
   1093            es3fShaderCommonFunctionTests.getCommonFuncCaseName(baseType, precision, shaderType),
   1094            outIsSigned ? 'floatBitsToInt' : 'floatBitsToUint', shaderType);
   1095 
   1096        /** @type {number} */ var vecSize = gluShaderUtil.getDataTypeScalarSize(baseType);
   1097        /** @type {gluShaderUtil.DataType} */ var intType = outIsSigned ?
   1098            (vecSize > 1 ? gluShaderUtil.getDataTypeVector(gluShaderUtil.DataType.INT, vecSize) : gluShaderUtil.DataType.INT) :
   1099            (vecSize > 1 ? gluShaderUtil.getDataTypeVector(gluShaderUtil.DataType.UINT, vecSize) : gluShaderUtil.DataType.UINT);
   1100 
   1101        this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(baseType, precision)));
   1102        this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(intType, gluShaderUtil.precision.PRECISION_HIGHP)));
   1103        this.m_spec.source = outIsSigned ? 'out0 = floatBitsToInt(in0);' : 'out0 = floatBitsToUint(in0);';
   1104    };
   1105 
   1106    es3fShaderCommonFunctionTests.FloatBitsToUintIntCase.prototype = Object.create(es3fShaderCommonFunctionTests.CommonFunctionCase.prototype);
   1107    es3fShaderCommonFunctionTests.FloatBitsToUintIntCase.prototype.constructor = es3fShaderCommonFunctionTests.FloatBitsToUintIntCase;
   1108 
   1109    /**
   1110     * @param {number} numValues
   1111     * @return {*}
   1112     */
   1113    es3fShaderCommonFunctionTests.FloatBitsToUintIntCase.prototype.getInputValues = function(numValues) {
   1114 
   1115        /** @type {Array<number>} */ var ranges = [
   1116                [-2.0, 2.0], // lowp
   1117                [-1e3, 1e3], // mediump
   1118                [-1e7, 1e7] // highp
   1119        ];
   1120 
   1121        /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0x2790a);
   1122 
   1123        /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
   1124        /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
   1125        /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
   1126        /** @type {Array<Array<number>>} */ var values = [];
   1127 
   1128        values[0] = es3fShaderCommonFunctionTests.fillRandomScalars(es3fShaderCommonFunctionTests.Types.FLOAT, rnd, ranges[precision][0], ranges[precision][1], numValues * scalarSize);
   1129        return values;
   1130    };
   1131 
   1132    /**
   1133     * @param {*} inputs
   1134     * @param {*} outputs
   1135     * @return {boolean}
   1136     */
   1137    es3fShaderCommonFunctionTests.FloatBitsToUintIntCase.prototype.compare = function(inputs, outputs) {
   1138        /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
   1139        /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
   1140        /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
   1141        /** @type {number} */ var mantissaBits = es3fShaderCommonFunctionTests.getMinMantissaBits(precision);
   1142        /** @type {number} */ var maxUlpDiff = es3fShaderCommonFunctionTests.getMaxUlpDiffFromBits(mantissaBits);
   1143 
   1144        /** @type {number} */ var in0;
   1145        /** @type {number} */ var out0;
   1146        /** @type {number} */ var refOut0;
   1147        /** @type {number} */ var ulpDiff;
   1148 
   1149        for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
   1150            in0 = inputs[0][compNdx];
   1151            out0 = outputs[0][compNdx];
   1152 
   1153            // Convert int to uint because ref out is in uint format.
   1154            var view = new DataView(new ArrayBuffer(4));
   1155            view.setInt32(0, out0, true);
   1156            out0 = view.getUint32(0, true);
   1157 
   1158            refOut0 = tcuFloat.newFloat32(in0).bits();
   1159            ulpDiff = Math.abs(out0 - refOut0);
   1160            if (ulpDiff > maxUlpDiff) {
   1161                this.m_failMsg += 'Expected [' + compNdx + '] = ' + refOut0 + ' with threshold ' +
   1162                            maxUlpDiff + ', got diff ' + ulpDiff;
   1163                return false;
   1164            }
   1165        }
   1166        return true;
   1167    };
   1168 
   1169    /**
   1170      * @constructor
   1171      * @extends {es3fShaderCommonFunctionTests.FloatBitsToUintIntCase}
   1172      * @param {gluShaderUtil.DataType} baseType
   1173      * @param {gluShaderUtil.precision} precision
   1174      * @param {gluShaderProgram.shaderType} shaderType
   1175      */
   1176    es3fShaderCommonFunctionTests.FloatBitsToIntCase = function(baseType, precision, shaderType) {
   1177        es3fShaderCommonFunctionTests.FloatBitsToUintIntCase.call(this, baseType, precision, shaderType, true);
   1178    };
   1179 
   1180    es3fShaderCommonFunctionTests.FloatBitsToIntCase.prototype = Object.create(es3fShaderCommonFunctionTests.FloatBitsToUintIntCase.prototype);
   1181    es3fShaderCommonFunctionTests.FloatBitsToIntCase.prototype.constructor = es3fShaderCommonFunctionTests.FloatBitsToIntCase;
   1182 
   1183    /**
   1184      * @constructor
   1185      * @extends {es3fShaderCommonFunctionTests.FloatBitsToUintIntCase}
   1186      * @param {gluShaderUtil.DataType} baseType
   1187      * @param {gluShaderUtil.precision} precision
   1188      * @param {gluShaderProgram.shaderType} shaderType
   1189      */
   1190    es3fShaderCommonFunctionTests.FloatBitsToUintCase = function(baseType, precision, shaderType) {
   1191        es3fShaderCommonFunctionTests.FloatBitsToUintIntCase.call(this, baseType, precision, shaderType, false);
   1192    };
   1193 
   1194    es3fShaderCommonFunctionTests.FloatBitsToUintCase.prototype = Object.create(es3fShaderCommonFunctionTests.FloatBitsToUintIntCase.prototype);
   1195    es3fShaderCommonFunctionTests.FloatBitsToUintCase.prototype.constructor = es3fShaderCommonFunctionTests.FloatBitsToUintCase;
   1196 
   1197    /**
   1198     * @constructor
   1199     * @extends {es3fShaderCommonFunctionTests.CommonFunctionCase}
   1200     * @param {gluShaderUtil.DataType} baseType
   1201     * @param {gluShaderProgram.shaderType} shaderType
   1202     */
   1203    es3fShaderCommonFunctionTests.BitsToFloatCase = function(baseType, shaderType) {
   1204        es3fShaderCommonFunctionTests.CommonFunctionCase.call(this,
   1205            es3fShaderCommonFunctionTests.getCommonFuncCaseName(baseType, gluShaderUtil.precision.PRECISION_HIGHP, shaderType),
   1206            gluShaderUtil.isDataTypeIntOrIVec(baseType) ? 'intBitsToFloat' : 'uintBitsToFloat', shaderType);
   1207        /** @type {boolean} */ var inIsSigned = gluShaderUtil.isDataTypeIntOrIVec(baseType);
   1208        /** @type {number} */ var vecSize = gluShaderUtil.getDataTypeScalarSize(baseType);
   1209        /** @type {gluShaderUtil.DataType} */ var floatType = vecSize > 1 ? gluShaderUtil.getDataTypeFloatVec(vecSize) : gluShaderUtil.DataType.FLOAT;
   1210 
   1211        this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(baseType, gluShaderUtil.precision.PRECISION_HIGHP)));
   1212        this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(floatType, gluShaderUtil.precision.PRECISION_HIGHP)));
   1213        this.m_spec.source = inIsSigned ? 'out0 = intBitsToFloat(in0);' : 'out0 = uintBitsToFloat(in0);';
   1214    };
   1215 
   1216    es3fShaderCommonFunctionTests.BitsToFloatCase.prototype = Object.create(es3fShaderCommonFunctionTests.CommonFunctionCase.prototype);
   1217    es3fShaderCommonFunctionTests.BitsToFloatCase.prototype.constructor = es3fShaderCommonFunctionTests.BitsToFloatCase;
   1218 
   1219    /**
   1220     * @param {number} numValues
   1221     * @return {*}
   1222     */
   1223    es3fShaderCommonFunctionTests.BitsToFloatCase.prototype.getInputValues = function(numValues) {
   1224        /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0xbbb225);
   1225 
   1226        /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
   1227        /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
   1228        /** @type {Array<number>} */ var range = [-1e8, 1e8];
   1229        /** @type {Array<Array<number>>} */ var values = [];
   1230 
   1231        values[0] = es3fShaderCommonFunctionTests.fillRandomScalars(es3fShaderCommonFunctionTests.Types.FLOAT, rnd, range[0], range[1], numValues * scalarSize);
   1232        return values;
   1233    };
   1234 
   1235    /**
   1236     * @param {*} inputs
   1237     * @param {*} outputs
   1238     * @return {boolean}
   1239     */
   1240    es3fShaderCommonFunctionTests.BitsToFloatCase.prototype.compare = function(inputs, outputs) {
   1241        /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
   1242        /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
   1243        /** @type {number} */ var maxUlpDiff = 0;
   1244 
   1245        /** @type {number} */ var in0;
   1246        /** @type {number} */ var out0;
   1247        /** @type {number} */ var ulpDiff;
   1248        /** @type {number} */ var refOut0;
   1249 
   1250        for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
   1251            in0 = inputs[0][compNdx];
   1252            out0 = outputs[0][compNdx];
   1253 
   1254            // Convert int to float
   1255            var view = new DataView(new ArrayBuffer(4));
   1256            view.setInt32(0, in0, true);
   1257            in0 = view.getFloat32(0, true);
   1258 
   1259            ulpDiff = es3fShaderCommonFunctionTests.getUlpDiff(in0, out0);
   1260            if (ulpDiff > maxUlpDiff) {
   1261                this.m_failMsg += 'Expected [' + compNdx + '] = ' + in0 + ' with ULP threshold ' +
   1262                            maxUlpDiff + ', got ULP diff ' + ulpDiff;
   1263                return false;
   1264            }
   1265        }
   1266        return true;
   1267    };
   1268 
   1269    /**
   1270     * @constructor
   1271     * @extends {es3fShaderCommonFunctionTests.CommonFunctionCase}
   1272     * @param {gluShaderUtil.DataType} baseType
   1273     * @param {gluShaderUtil.precision} precision
   1274     * @param {gluShaderProgram.shaderType} shaderType
   1275     */
   1276    es3fShaderCommonFunctionTests.FloorCase = function(baseType, precision, shaderType) {
   1277        es3fShaderCommonFunctionTests.CommonFunctionCase.call(this,
   1278            es3fShaderCommonFunctionTests.getCommonFuncCaseName(baseType, precision, shaderType),
   1279            'floor', shaderType);
   1280        this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(baseType, precision)));
   1281        this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(baseType, precision)));
   1282        this.m_spec.source = 'out0 = floor(in0);';
   1283    };
   1284 
   1285    es3fShaderCommonFunctionTests.FloorCase.prototype = Object.create(es3fShaderCommonFunctionTests.CommonFunctionCase.prototype);
   1286    es3fShaderCommonFunctionTests.FloorCase.prototype.constructor = es3fShaderCommonFunctionTests.FloorCase;
   1287 
   1288    /**
   1289     * @param {number} numValues
   1290     * @return {*}
   1291     */
   1292    es3fShaderCommonFunctionTests.FloorCase.prototype.getInputValues = function(numValues) {
   1293        /** @type {Array<Array<number>>} */ var ranges = [
   1294            [-2.0, 2.0], // lowp
   1295            [-1e3, 1e3], // mediump
   1296            [-1e7, 1e7] // highp
   1297        ];
   1298 
   1299        /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0xac23f);
   1300 
   1301        /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
   1302        /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
   1303        /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
   1304        /** @type {Array<Array<number>>} */ var values = [];
   1305        // Random cases.
   1306        values[0] = es3fShaderCommonFunctionTests.fillRandomScalars(es3fShaderCommonFunctionTests.Types.FLOAT, rnd, ranges[precision][0], ranges[precision][1], numValues * scalarSize);
   1307 
   1308        // If precision is mediump, make sure values can be represented in fp16 exactly
   1309        if (precision === gluShaderUtil.precision.PRECISION_MEDIUMP)
   1310            es3fShaderCommonFunctionTests.vecToFloat16(values[0]);
   1311 
   1312        return values;
   1313    };
   1314 
   1315    /**
   1316     * @param {*} inputs
   1317     * @param {*} outputs
   1318     * @return {boolean}
   1319     */
   1320    es3fShaderCommonFunctionTests.FloorCase.prototype.compare = function(inputs, outputs) {
   1321        /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
   1322        /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
   1323        /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
   1324 
   1325        /** @type {number} */ var in0;
   1326        /** @type {number} */ var out0;
   1327        /** @type {number} */ var ref;
   1328        /** @type {number} */ var ulpDiff;
   1329 
   1330        if (precision === gluShaderUtil.precision.PRECISION_HIGHP || precision === gluShaderUtil.precision.PRECISION_MEDIUMP) {
   1331            // Require exact result.
   1332            for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
   1333                in0 = inputs[0][compNdx];
   1334                out0 = outputs[0][compNdx];
   1335                ref = Math.floor(in0);
   1336 
   1337                ulpDiff = es3fShaderCommonFunctionTests.getUlpDiff(out0, ref);
   1338 
   1339                if (ulpDiff > 0) {
   1340                    this.m_failMsg += 'Expected [' + compNdx + '] = ' + ref + ', got ULP diff ' + ulpDiff;
   1341                    return false;
   1342                }
   1343            }
   1344        } else {
   1345            /** @type {number} */ var mantissaBits = es3fShaderCommonFunctionTests.getMinMantissaBits(precision);
   1346            /** @type {number} */ var maxUlpDiff = es3fShaderCommonFunctionTests.getMaxUlpDiffFromBits(mantissaBits); // ULP diff for rounded integer value.
   1347            /** @type {number} */ var eps = es3fShaderCommonFunctionTests.getEpsFromBits(1.0, mantissaBits); // epsilon for rounding bounds
   1348 
   1349            for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
   1350                in0 = inputs[0][compNdx];
   1351                out0 = outputs[0][compNdx];
   1352                /** @type {number} */ var minRes = Math.floor(in0 - eps);
   1353                /** @type {number} */ var maxRes = Math.floor(in0 + eps);
   1354                /** @type {boolean} */ var anyOk = false;
   1355 
   1356                for (var roundedVal = minRes; roundedVal <= maxRes; roundedVal++) {
   1357                    ulpDiff = es3fShaderCommonFunctionTests.getUlpDiff(out0, roundedVal);
   1358 
   1359                    if (ulpDiff <= maxUlpDiff) {
   1360                        anyOk = true;
   1361                        break;
   1362                    }
   1363                }
   1364 
   1365                if (!anyOk) {
   1366                    this.m_failMsg += 'Expected [' + compNdx + '] = [' + minRes + ', ' + maxRes + '] with ULP threshold ' + maxUlpDiff;
   1367                    return false;
   1368                }
   1369            }
   1370        }
   1371 
   1372        return true;
   1373    };
   1374 
   1375    /**
   1376     * @constructor
   1377     * @extends {es3fShaderCommonFunctionTests.CommonFunctionCase}
   1378     * @param {gluShaderUtil.DataType} baseType
   1379     * @param {gluShaderUtil.precision} precision
   1380     * @param {gluShaderProgram.shaderType} shaderType
   1381     */
   1382    es3fShaderCommonFunctionTests.TruncCase = function(baseType, precision, shaderType) {
   1383        es3fShaderCommonFunctionTests.CommonFunctionCase.call(this,
   1384            es3fShaderCommonFunctionTests.getCommonFuncCaseName(baseType, precision, shaderType),
   1385            'trunc', shaderType);
   1386        this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(baseType, precision)));
   1387        this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(baseType, precision)));
   1388        this.m_spec.source = 'out0 = trunc(in0);';
   1389    };
   1390 
   1391    es3fShaderCommonFunctionTests.TruncCase.prototype = Object.create(es3fShaderCommonFunctionTests.CommonFunctionCase.prototype);
   1392    es3fShaderCommonFunctionTests.TruncCase.prototype.constructor = es3fShaderCommonFunctionTests.TruncCase;
   1393 
   1394    /**
   1395     * @param {number} numValues
   1396     * @return {*}
   1397     */
   1398    es3fShaderCommonFunctionTests.TruncCase.prototype.getInputValues = function(numValues) {
   1399        /** @type {Array<Array<number>>} */ var ranges = [
   1400            [-2.0, 2.0], // lowp
   1401            [-1e3, 1e3], // mediump
   1402            [-1e7, 1e7] // highp
   1403        ];
   1404 
   1405        /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0xac23f);
   1406 
   1407        /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
   1408        /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
   1409        /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
   1410 
   1411        /** @type {Array<number>} */ var specialCases = [0.0, -0.0, -0.9, 0.9, 1.0, -1.0];
   1412        /** @type {Array<Array<number>>} */ var values = [];
   1413        values[0] = [];
   1414 
   1415        // Special cases
   1416        for (var caseNdx = 0; caseNdx < specialCases.length; caseNdx++)
   1417        for (var scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
   1418            values[0].push(specialCases[caseNdx]);
   1419 
   1420        // Random cases.
   1421        values[0] = values[0].concat(es3fShaderCommonFunctionTests.fillRandomScalars(es3fShaderCommonFunctionTests.Types.FLOAT, rnd, ranges[precision][0], ranges[precision][1], (numValues - specialCases.length) * scalarSize));
   1422 
   1423        // If precision is mediump, make sure values can be represented in fp16 exactly
   1424        if (precision === gluShaderUtil.precision.PRECISION_MEDIUMP)
   1425            es3fShaderCommonFunctionTests.vecToFloat16(values[0]);
   1426 
   1427        return values;
   1428    };
   1429 
   1430    /**
   1431     * @param {*} inputs
   1432     * @param {*} outputs
   1433     * @return {boolean}
   1434     */
   1435    es3fShaderCommonFunctionTests.TruncCase.prototype.compare = function(inputs, outputs) {
   1436        /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
   1437        /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
   1438        /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
   1439 
   1440        /** @type {number} */ var in0;
   1441        /** @type {number} */ var out0;
   1442        /** @type {number} */ var ref;
   1443        /** @type {number} */ var ulpDiff;
   1444 
   1445        if (precision === gluShaderUtil.precision.PRECISION_HIGHP || precision === gluShaderUtil.precision.PRECISION_MEDIUMP) {
   1446            // Require exact result.
   1447            for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
   1448                in0 = inputs[0][compNdx];
   1449                out0 = outputs[0][compNdx];
   1450                /** @type {boolean} */ var isNeg = tcuFloat.newFloat32(in0).sign() < 0;
   1451                ref = isNeg ? (-Math.floor(-in0)) : Math.floor(in0);
   1452 
   1453                // \note: trunc() function definition is a bit broad on negative zeros. Ignore result sign if zero.
   1454                ulpDiff = es3fShaderCommonFunctionTests.getUlpDiffIgnoreZeroSign(out0, ref);
   1455 
   1456                if (ulpDiff > 0) {
   1457                    this.m_failMsg += 'Expected [' + compNdx + '] = ' + ref + ', got ULP diff ' + ulpDiff;
   1458                    return false;
   1459                }
   1460            }
   1461        } else {
   1462            /** @type {number} */ var mantissaBits = es3fShaderCommonFunctionTests.getMinMantissaBits(precision);
   1463            /** @type {number} */ var maxUlpDiff = es3fShaderCommonFunctionTests.getMaxUlpDiffFromBits(mantissaBits); // ULP diff for rounded integer value.
   1464            /** @type {number} */ var eps = es3fShaderCommonFunctionTests.getEpsFromBits(1.0, mantissaBits); // epsilon for rounding bounds
   1465 
   1466            for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
   1467                in0 = inputs[0][compNdx];
   1468                out0 = outputs[0][compNdx];
   1469                /** @type {number} */ var minRes = Math.trunc(in0 - eps);
   1470                /** @type {number} */ var maxRes = Math.trunc(in0 + eps);
   1471                /** @type {boolean} */ var anyOk = false;
   1472 
   1473                for (var roundedVal = minRes; roundedVal <= maxRes; roundedVal++) {
   1474                    ulpDiff = es3fShaderCommonFunctionTests.getUlpDiffIgnoreZeroSign(out0, roundedVal);
   1475 
   1476                    if (ulpDiff <= maxUlpDiff) {
   1477                        anyOk = true;
   1478                        break;
   1479                    }
   1480                }
   1481 
   1482                if (!anyOk) {
   1483                    this.m_failMsg += 'Expected [' + compNdx + '] = [' + minRes + ', ' + maxRes + '] with ULP threshold ' + maxUlpDiff;
   1484                    return false;
   1485                }
   1486            }
   1487        }
   1488 
   1489        return true;
   1490    };
   1491 
   1492    /**
   1493     * @constructor
   1494     * @extends {es3fShaderCommonFunctionTests.CommonFunctionCase}
   1495     * @param {gluShaderUtil.DataType} baseType
   1496     * @param {gluShaderUtil.precision} precision
   1497     * @param {gluShaderProgram.shaderType} shaderType
   1498     */
   1499    es3fShaderCommonFunctionTests.RoundCase = function(baseType, precision, shaderType) {
   1500        es3fShaderCommonFunctionTests.CommonFunctionCase.call(this,
   1501            es3fShaderCommonFunctionTests.getCommonFuncCaseName(baseType, precision, shaderType),
   1502            'round', shaderType);
   1503        this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(baseType, precision)));
   1504        this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(baseType, precision)));
   1505        this.m_spec.source = 'out0 = round(in0);';
   1506    };
   1507 
   1508    es3fShaderCommonFunctionTests.RoundCase.prototype = Object.create(es3fShaderCommonFunctionTests.CommonFunctionCase.prototype);
   1509    es3fShaderCommonFunctionTests.RoundCase.prototype.constructor = es3fShaderCommonFunctionTests.RoundCase;
   1510 
   1511    /**
   1512     * @param {number} numValues
   1513     * @return {*}
   1514     */
   1515    es3fShaderCommonFunctionTests.RoundCase.prototype.getInputValues = function(numValues) {
   1516        /** @type {Array<Array<number>>} */ var ranges = [
   1517            [-2.0, 2.0], // lowp
   1518            [-1e3, 1e3], // mediump
   1519            [-1e7, 1e7] // highp
   1520        ];
   1521 
   1522        /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0xac23f);
   1523 
   1524        /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
   1525        /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
   1526        /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
   1527        /** @type {number} */ var numSpecialCases = 0;
   1528 
   1529        /** @type {Array<Array<number>>} */ var values = [];
   1530        values[0] = []
   1531 
   1532        // Special cases.
   1533        if (precision === gluShaderUtil.precision.PRECISION_LOWP) {
   1534            assertMsgOptions(numValues >= 10, 'Sample too small.', false, true);
   1535            for (var ndx = 0; ndx < 10; ndx++) {
   1536                /** @type {number} */ var v = deMath.clamp(ndx - 5.5, ranges[precision][0], ranges[precision][1]);
   1537                for (var iter = 1; iter <= scalarSize; iter++)
   1538                    values[0].push(v);
   1539                numSpecialCases += 1;
   1540            }
   1541        }
   1542 
   1543        // Random cases.
   1544        values[0] = values[0].concat(es3fShaderCommonFunctionTests.fillRandomScalars(es3fShaderCommonFunctionTests.Types.FLOAT, rnd, ranges[precision][0], ranges[precision][1], (numValues - numSpecialCases) * scalarSize));
   1545 
   1546        // If precision is mediump, make sure values can be represented in fp16 exactly
   1547        if (precision === gluShaderUtil.precision.PRECISION_MEDIUMP)
   1548            es3fShaderCommonFunctionTests.vecToFloat16(values[0]);
   1549 
   1550        return values;
   1551    };
   1552 
   1553    /**
   1554     * @param {*} inputs
   1555     * @param {*} outputs
   1556     * @return {boolean}
   1557     */
   1558    es3fShaderCommonFunctionTests.RoundCase.prototype.compare = function(inputs, outputs) {
   1559        /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
   1560        /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
   1561        /** @type {boolean} */ var hasZeroSign = es3fShaderCommonFunctionTests.supportsSignedZero(precision);
   1562        /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
   1563 
   1564        /** @type {number} */ var in0;
   1565        /** @type {number} */ var out0;
   1566        /** @type {number} */ var ulpDiff;
   1567 
   1568        if (precision === gluShaderUtil.precision.PRECISION_HIGHP || precision === gluShaderUtil.precision.PRECISION_MEDIUMP) {
   1569            // Require exact result.
   1570            for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
   1571                in0 = inputs[0][compNdx];
   1572                out0 = outputs[0][compNdx];
   1573 
   1574                if ((in0 - Math.floor(in0)) === 0.5) {
   1575                    /** @type {number} */ var ref0 = Math.floor(in0);
   1576                    /** @type {number} */ var ref1 = Math.ceil(in0);
   1577                    /** @type {number} */ var ulpDiff0 = hasZeroSign ? es3fShaderCommonFunctionTests.getUlpDiff(out0, ref0) : es3fShaderCommonFunctionTests.getUlpDiffIgnoreZeroSign(out0, ref0);
   1578                    /** @type {number} */ var ulpDiff1 = hasZeroSign ? es3fShaderCommonFunctionTests.getUlpDiff(out0, ref1) : es3fShaderCommonFunctionTests.getUlpDiffIgnoreZeroSign(out0, ref1);
   1579                    if (ulpDiff0 > 0 && ulpDiff1 > 0) {
   1580                        this.m_failMsg += 'Expected [' + compNdx + '] = ' + ref0 + ' or ' + ref1 + ', got ULP diff ' + Math.min(ulpDiff0, ulpDiff1);
   1581                        return false;
   1582                    }
   1583                } else {
   1584                    // Require exact result
   1585                    /** @type {number} */ var ref = es3fShaderCommonFunctionTests.roundEven(in0);
   1586                    ulpDiff = hasZeroSign ? es3fShaderCommonFunctionTests.getUlpDiff(out0, ref) : es3fShaderCommonFunctionTests.getUlpDiffIgnoreZeroSign(out0, ref);
   1587 
   1588                    if (ulpDiff > 0) {
   1589                        this.m_failMsg += 'Expected [' + compNdx + '] = ' + ref + ', got ULP diff ' + ulpDiff;
   1590                        return false;
   1591                    }
   1592                }
   1593            }
   1594        } else {
   1595            /** @type {number} */ var mantissaBits = es3fShaderCommonFunctionTests.getMinMantissaBits(precision);
   1596            /** @type {number} */ var maxUlpDiff = es3fShaderCommonFunctionTests.getMaxUlpDiffFromBits(mantissaBits); // ULP diff for rounded integer value.
   1597            /** @type {number} */ var eps = es3fShaderCommonFunctionTests.getEpsFromBits(1.0, mantissaBits); // epsilon for rounding bounds
   1598 
   1599            for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
   1600                in0 = inputs[0][compNdx];
   1601                out0 = outputs[0][compNdx];
   1602                /** @type {number} */ var minRes = Math.floor(es3fShaderCommonFunctionTests.roundEven(in0 - eps));
   1603                /** @type {number} */ var maxRes = Math.floor(es3fShaderCommonFunctionTests.roundEven(in0 + eps));
   1604                /** @type {boolean} */ var anyOk = false;
   1605 
   1606                for (var roundedVal = minRes; roundedVal <= maxRes; roundedVal++) {
   1607                    ulpDiff = es3fShaderCommonFunctionTests.getUlpDiffIgnoreZeroSign(out0, roundedVal);
   1608 
   1609                    if (ulpDiff <= maxUlpDiff) {
   1610                        anyOk = true;
   1611                        break;
   1612                    }
   1613                }
   1614 
   1615                if (!anyOk) {
   1616                    this.m_failMsg += 'Expected [' + compNdx + '] = [' + minRes + ', ' + maxRes + '] with ULP threshold ' + maxUlpDiff;
   1617                    return false;
   1618                }
   1619            }
   1620        }
   1621 
   1622        return true;
   1623    };
   1624 
   1625    /**
   1626     * @constructor
   1627     * @extends {es3fShaderCommonFunctionTests.CommonFunctionCase}
   1628     * @param {gluShaderUtil.DataType} baseType
   1629     * @param {gluShaderUtil.precision} precision
   1630     * @param {gluShaderProgram.shaderType} shaderType
   1631     */
   1632    es3fShaderCommonFunctionTests.CeilCase = function(baseType, precision, shaderType) {
   1633        es3fShaderCommonFunctionTests.CommonFunctionCase.call(this,
   1634            es3fShaderCommonFunctionTests.getCommonFuncCaseName(baseType, precision, shaderType),
   1635            'ceil', shaderType);
   1636        this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(baseType, precision)));
   1637        this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(baseType, precision)));
   1638        this.m_spec.source = 'out0 = ceil(in0);';
   1639    };
   1640 
   1641    es3fShaderCommonFunctionTests.CeilCase.prototype = Object.create(es3fShaderCommonFunctionTests.CommonFunctionCase.prototype);
   1642    es3fShaderCommonFunctionTests.CeilCase.prototype.constructor = es3fShaderCommonFunctionTests.CeilCase;
   1643 
   1644    /**
   1645     * @param {number} numValues
   1646     * @return {*}
   1647     */
   1648    es3fShaderCommonFunctionTests.CeilCase.prototype.getInputValues = function(numValues) {
   1649        /** @type {Array<Array<number>>} */ var ranges = [
   1650            [-2.0, 2.0], // lowp
   1651            [-1e3, 1e3], // mediump
   1652            [-1e7, 1e7] // highp
   1653        ];
   1654 
   1655        /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0xac23f);
   1656 
   1657        /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
   1658        /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
   1659        /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
   1660 
   1661        /** @type {Array<Array<number>>} */ var values = [];
   1662 
   1663        // Random cases.
   1664        values[0] = es3fShaderCommonFunctionTests.fillRandomScalars(es3fShaderCommonFunctionTests.Types.FLOAT, rnd, ranges[precision][0], ranges[precision][1], numValues * scalarSize);
   1665 
   1666        // If precision is mediump, make sure values can be represented in fp16 exactly
   1667        if (precision === gluShaderUtil.precision.PRECISION_MEDIUMP)
   1668            es3fShaderCommonFunctionTests.vecToFloat16(values[0]);
   1669 
   1670        return values;
   1671    };
   1672 
   1673    /**
   1674     * @param {*} inputs
   1675     * @param {*} outputs
   1676     * @return {boolean}
   1677     */
   1678    es3fShaderCommonFunctionTests.CeilCase.prototype.compare = function(inputs, outputs) {
   1679        /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
   1680        /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
   1681        /** @type {boolean} */ var hasZeroSign = es3fShaderCommonFunctionTests.supportsSignedZero(precision);
   1682        /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
   1683 
   1684        /** @type {number} */ var in0;
   1685        /** @type {number} */ var out0;
   1686        /** @type {number} */ var ref;
   1687        /** @type {number} */ var ulpDiff;
   1688 
   1689        if (precision === gluShaderUtil.precision.PRECISION_HIGHP || precision === gluShaderUtil.precision.PRECISION_MEDIUMP) {
   1690            // Require exact result.
   1691            for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
   1692                in0 = inputs[0][compNdx];
   1693                out0 = outputs[0][compNdx];
   1694                ref = Math.ceil(in0);
   1695                ulpDiff = hasZeroSign ? es3fShaderCommonFunctionTests.getUlpDiff(out0, ref) : es3fShaderCommonFunctionTests.getUlpDiffIgnoreZeroSign(out0, ref);
   1696 
   1697                if (ulpDiff > 0) {
   1698                    this.m_failMsg += 'Expected [' + compNdx + '] = ' + ref + ', got ULP diff ' + ulpDiff;
   1699                    return false;
   1700                }
   1701            }
   1702        } else {
   1703            /** @type {number} */ var mantissaBits = es3fShaderCommonFunctionTests.getMinMantissaBits(precision);
   1704            /** @type {number} */ var maxUlpDiff = es3fShaderCommonFunctionTests.getMaxUlpDiffFromBits(mantissaBits); // ULP diff for rounded integer value.
   1705            /** @type {number} */ var eps = es3fShaderCommonFunctionTests.getEpsFromBits(1.0, mantissaBits); // epsilon for rounding bounds
   1706 
   1707            for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
   1708                in0 = inputs[0][compNdx];
   1709                out0 = outputs[0][compNdx];
   1710                /** @type {number} */ var minRes = Math.ceil(in0 - eps);
   1711                /** @type {number} */ var maxRes = Math.ceil(in0 + eps);
   1712                /** @type {boolean} */ var anyOk = false;
   1713 
   1714                for (var roundedVal = minRes; roundedVal <= maxRes; roundedVal++) {
   1715                    ulpDiff = es3fShaderCommonFunctionTests.getUlpDiffIgnoreZeroSign(out0, roundedVal);
   1716 
   1717                    if (ulpDiff <= maxUlpDiff) {
   1718                        anyOk = true;
   1719                        break;
   1720                    }
   1721                }
   1722 
   1723                if (!anyOk & deMath.deInRange32(0, minRes, maxRes)) {
   1724                    ulpDiff = Math.abs(Math.floor(tcuFloat.newFloat32(out0).bits()) - 0x80000000);
   1725                    anyOk = ulpDiff <= maxUlpDiff;
   1726                }
   1727 
   1728                if (!anyOk) {
   1729                    this.m_failMsg += 'Expected [' + compNdx + '] = [' + minRes + ', ' + maxRes + '] with ULP threshold ' + maxUlpDiff;
   1730                    return false;
   1731                }
   1732            }
   1733        }
   1734 
   1735        return true;
   1736    };
   1737 
   1738    /**
   1739     * @constructor
   1740     * @extends {es3fShaderCommonFunctionTests.CommonFunctionCase}
   1741     * @param {gluShaderUtil.DataType} baseType
   1742     * @param {gluShaderUtil.precision} precision
   1743     * @param {gluShaderProgram.shaderType} shaderType
   1744     */
   1745    es3fShaderCommonFunctionTests.FractCase = function(baseType, precision, shaderType) {
   1746        es3fShaderCommonFunctionTests.CommonFunctionCase.call(this,
   1747            es3fShaderCommonFunctionTests.getCommonFuncCaseName(baseType, precision, shaderType),
   1748            'fract', shaderType);
   1749        this.m_spec.inputs.push(new glsShaderExecUtil.Symbol('in0', gluVarType.newTypeBasic(baseType, precision)));
   1750        this.m_spec.outputs.push(new glsShaderExecUtil.Symbol('out0', gluVarType.newTypeBasic(baseType, precision)));
   1751        this.m_spec.source = 'out0 = fract(in0);';
   1752    };
   1753 
   1754    es3fShaderCommonFunctionTests.FractCase.prototype = Object.create(es3fShaderCommonFunctionTests.CommonFunctionCase.prototype);
   1755    es3fShaderCommonFunctionTests.FractCase.prototype.constructor = es3fShaderCommonFunctionTests.FractCase;
   1756 
   1757    /**
   1758     * @param {number} numValues
   1759     * @return {*}
   1760     */
   1761    es3fShaderCommonFunctionTests.FractCase.prototype.getInputValues = function(numValues) {
   1762        /** @type {Array<Array<number>>} */ var ranges = [
   1763            [-2.0, 2.0], // lowp
   1764            [-1e3, 1e3], // mediump
   1765            [-1e7, 1e7] // highp
   1766        ];
   1767 
   1768        /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name) ^ 0xac23f);
   1769 
   1770        /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
   1771        /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
   1772        /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
   1773        /** @type {number} */ var numSpecialCases = 0;
   1774 
   1775        /** @type {Array<Array<number>>} */ var values = [];
   1776        values[0] = [];
   1777 
   1778        // Special cases.
   1779        if (precision !== gluShaderUtil.precision.PRECISION_LOWP) {
   1780            assertMsgOptions(numValues >= 10, 'Sample too small.', false, true);
   1781            for (var ndx = 0; ndx < 10; ndx++) {
   1782                /** @type {number} */ var v = deMath.clamp(ndx - 5.5, ranges[precision][0], ranges[precision][1]);
   1783                for (var scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++) {
   1784                    values[0].push(v);
   1785                }
   1786                numSpecialCases += 1;
   1787            }
   1788        }
   1789 
   1790        // Random cases.
   1791        values[0] = values[0].concat(es3fShaderCommonFunctionTests.fillRandomScalars(es3fShaderCommonFunctionTests.Types.FLOAT, rnd, ranges[precision][0], ranges[precision][1], (numValues - numSpecialCases) * scalarSize));
   1792 
   1793        // If precision is mediump, make sure values can be represented in fp16 exactly
   1794        if (precision === gluShaderUtil.precision.PRECISION_MEDIUMP)
   1795            es3fShaderCommonFunctionTests.vecToFloat16(values[0])
   1796 
   1797        return values;
   1798    };
   1799 
   1800    /**
   1801     * @param {*} inputs
   1802     * @param {*} outputs
   1803     * @return {boolean}
   1804     */
   1805    es3fShaderCommonFunctionTests.FractCase.prototype.compare = function(inputs, outputs) {
   1806        /** @type {gluShaderUtil.DataType} */ var type = this.m_spec.inputs[0].varType.getBasicType();
   1807        /** @type {gluShaderUtil.precision} */ var precision = this.m_spec.inputs[0].varType.getPrecision();
   1808        /** @type {boolean} */ var hasZeroSign = es3fShaderCommonFunctionTests.supportsSignedZero(precision);
   1809        /** @type {number} */ var scalarSize = gluShaderUtil.getDataTypeScalarSize(type);
   1810 
   1811        /** @type {number} */ var in0;
   1812        /** @type {number} */ var out0;
   1813        /** @type {number} */ var ref;
   1814        /** @type {number} */ var ulpDiff;
   1815 
   1816        if (precision === gluShaderUtil.precision.PRECISION_HIGHP || precision === gluShaderUtil.precision.PRECISION_MEDIUMP) {
   1817            // Require exact result.
   1818            for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
   1819                in0 = inputs[0][compNdx];
   1820                out0 = outputs[0][compNdx];
   1821                ref = in0 - Math.floor(in0);
   1822                ulpDiff = hasZeroSign ? es3fShaderCommonFunctionTests.getUlpDiff(out0, ref) : es3fShaderCommonFunctionTests.getUlpDiffIgnoreZeroSign(out0, ref);
   1823 
   1824                if (ulpDiff > 0) {
   1825                    this.m_failMsg += 'Expected [' + compNdx + '] = ' + ref + ', got ULP diff ' + ulpDiff;
   1826                    return false;
   1827                }
   1828            }
   1829        } else {
   1830            /** @type {number} */ var mantissaBits = es3fShaderCommonFunctionTests.getMinMantissaBits(precision);
   1831            /** @type {number} */ var eps = es3fShaderCommonFunctionTests.getEpsFromBits(1.0, mantissaBits); // epsilon for rounding bounds
   1832 
   1833            for (var compNdx = 0; compNdx < scalarSize; compNdx++) {
   1834                in0 = inputs[0][compNdx];
   1835                out0 = outputs[0][compNdx];
   1836 
   1837                if (Math.floor(in0 - eps) == Math.floor(in0 + eps)) {
   1838                    ref = in0 - Math.floor(in0);
   1839                    /** @type {number} */ var bitsLost = es3fShaderCommonFunctionTests.numBitsLostInOp(in0, ref);
   1840                    /** @type {number} */ var maxUlpDiff = es3fShaderCommonFunctionTests.getMaxUlpDiffFromBits(Math.max(0, mantissaBits - bitsLost)); // ULP diff for rounded integer value.
   1841                    ulpDiff = es3fShaderCommonFunctionTests.getUlpDiffIgnoreZeroSign(out0, ref);
   1842                    if (ulpDiff > maxUlpDiff) {
   1843                        this.m_failMsg += 'Expected [' + compNdx + '] = ' + ref + ' with ULP threshold ' + maxUlpDiff + ', got diff ' + ulpDiff;
   1844                        return false;
   1845                    }
   1846                } else {
   1847                    if (out0 >= 1.0) {
   1848                        this.m_failMsg += 'Expected [' + compNdx + '] < 1.0';
   1849                        return false;
   1850                    }
   1851                }
   1852            }
   1853        }
   1854 
   1855        return true;
   1856    };
   1857 
   1858    /**
   1859     * @constructor
   1860     * @extends {tcuTestCase.DeqpTest}
   1861     */
   1862    es3fShaderCommonFunctionTests.ShaderCommonFunctionTests = function() {
   1863        tcuTestCase.DeqpTest.call(this, 'common', 'Common function tests');
   1864    };
   1865 
   1866    es3fShaderCommonFunctionTests.ShaderCommonFunctionTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
   1867    es3fShaderCommonFunctionTests.ShaderCommonFunctionTests.prototype.constructor = es3fShaderCommonFunctionTests.ShaderCommonFunctionTests;
   1868 
   1869    /**
   1870     * @param {tcuTestCase.DeqpTest} parent
   1871     * @param {es3fShaderCommonFunctionTests.TestClass} testClass
   1872     * @param {string} functionName
   1873     * @param {boolean} floatTypes
   1874     * @param {boolean} intTypes
   1875     * @param {boolean} uintTypes
   1876     */
   1877    es3fShaderCommonFunctionTests.addFunctionCases = function(parent, testClass, functionName, floatTypes, intTypes, uintTypes) {
   1878        /** @type {tcuTestCase.DeqpTest} */ var group = tcuTestCase.newTest(functionName, functionName);
   1879        parent.addChild(group);
   1880 
   1881        /** @type {Array<gluShaderUtil.DataType>} */ var scalarTypes = [
   1882            gluShaderUtil.DataType.FLOAT,
   1883            gluShaderUtil.DataType.INT,
   1884            gluShaderUtil.DataType.UINT
   1885        ];
   1886 
   1887        for (var scalarTypeNdx = 0; scalarTypeNdx < scalarTypes.length; scalarTypeNdx++) {
   1888            /** @type {gluShaderUtil.DataType} */ var scalarType = scalarTypes[scalarTypeNdx];
   1889 
   1890            if ((!floatTypes && scalarType == gluShaderUtil.DataType.FLOAT) ||
   1891                (!intTypes && scalarType == gluShaderUtil.DataType.INT) ||
   1892                (!uintTypes && scalarType == gluShaderUtil.DataType.UINT))
   1893                continue;
   1894 
   1895            for (var vecSize = 1; vecSize <= 4; vecSize++)
   1896            for (var prec = gluShaderUtil.precision.PRECISION_LOWP; prec <= gluShaderUtil.precision.PRECISION_HIGHP; prec++)
   1897            for (var shaderType = gluShaderProgram.shaderType.VERTEX; shaderType <= gluShaderProgram.shaderType.FRAGMENT; shaderType++)
   1898                group.addChild(new testClass(/** @type {gluShaderUtil.DataType} */ (scalarType + vecSize - 1), prec, shaderType));
   1899        }
   1900    };
   1901 
   1902    es3fShaderCommonFunctionTests.ShaderCommonFunctionTests.prototype.init = function() {
   1903        var testGroup = tcuTestCase.runner.testCases;
   1904 
   1905        es3fShaderCommonFunctionTests.addFunctionCases(testGroup, es3fShaderCommonFunctionTests.AbsCase, 'abs', true, true, false);
   1906        es3fShaderCommonFunctionTests.addFunctionCases(testGroup, es3fShaderCommonFunctionTests.SignCase, 'sign', true, true, false);
   1907        es3fShaderCommonFunctionTests.addFunctionCases(testGroup, es3fShaderCommonFunctionTests.FloorCase, 'floor', true, false, false);
   1908        es3fShaderCommonFunctionTests.addFunctionCases(testGroup, es3fShaderCommonFunctionTests.TruncCase, 'trunc', true, false, false);
   1909        es3fShaderCommonFunctionTests.addFunctionCases(testGroup, es3fShaderCommonFunctionTests.RoundCase, 'round', true, false, false);
   1910        es3fShaderCommonFunctionTests.addFunctionCases(testGroup, es3fShaderCommonFunctionTests.RoundEvenCase, 'roundeven', true, false, false);
   1911        es3fShaderCommonFunctionTests.addFunctionCases(testGroup, es3fShaderCommonFunctionTests.CeilCase, 'ceil', true, false, false);
   1912        es3fShaderCommonFunctionTests.addFunctionCases(testGroup, es3fShaderCommonFunctionTests.FractCase, 'fract', true, false, false);
   1913        // mod
   1914        es3fShaderCommonFunctionTests.addFunctionCases(testGroup, es3fShaderCommonFunctionTests.ModfCase, 'modf', true, false, false);
   1915        // min, max, clamp, mix, step, smoothstep
   1916        es3fShaderCommonFunctionTests.addFunctionCases(testGroup, es3fShaderCommonFunctionTests.IsnanCase, 'isnan', true, false, false);
   1917        es3fShaderCommonFunctionTests.addFunctionCases(testGroup, es3fShaderCommonFunctionTests.IsinfCase, 'isinf', true, false, false);
   1918        es3fShaderCommonFunctionTests.addFunctionCases(testGroup, es3fShaderCommonFunctionTests.FloatBitsToIntCase, 'floatbitstoint', true, false, false);
   1919        es3fShaderCommonFunctionTests.addFunctionCases(testGroup, es3fShaderCommonFunctionTests.FloatBitsToUintCase, 'floatbitstouint', true, false, false);
   1920 
   1921        // (u)intBitsToFloat()
   1922        /** @type {tcuTestCase.DeqpTest} */ var intGroup = tcuTestCase.newTest('intbitstofloat', 'intBitsToFloat() Tests');
   1923        /** @type {tcuTestCase.DeqpTest} */ var uintGroup = tcuTestCase.newTest('uintbitstofloat', 'uintBitsToFloat() Tests');
   1924 
   1925        testGroup.addChild(intGroup);
   1926        testGroup.addChild(uintGroup);
   1927 
   1928        /** @type {Array<gluShaderProgram.shaderType>} */ var shaderTypes = [
   1929            gluShaderProgram.shaderType.VERTEX,
   1930            gluShaderProgram.shaderType.FRAGMENT
   1931        ];
   1932 
   1933        for (var vecSize = 1; vecSize < 4; vecSize++) {
   1934            /** @type {gluShaderUtil.DataType} */ var intType = vecSize > 1 ?
   1935                gluShaderUtil.getDataTypeVector(gluShaderUtil.DataType.INT, vecSize) :
   1936                gluShaderUtil.DataType.INT;
   1937 
   1938            /** @type {gluShaderUtil.DataType} */ var uintType = vecSize > 1 ?
   1939                gluShaderUtil.getDataTypeVector(gluShaderUtil.DataType.UINT, vecSize) :
   1940                gluShaderUtil.DataType.UINT;
   1941 
   1942            for (var shaderType in shaderTypes) {
   1943                intGroup.addChild(new es3fShaderCommonFunctionTests.BitsToFloatCase(intType, shaderTypes[shaderType]));
   1944                uintGroup.addChild(new es3fShaderCommonFunctionTests.BitsToFloatCase(uintType, shaderTypes[shaderType]));
   1945            }
   1946        }
   1947    };
   1948 
   1949    /**
   1950    * Run test
   1951    * @param {WebGL2RenderingContext} context
   1952    */
   1953    es3fShaderCommonFunctionTests.run = function(context) {
   1954        gl = context;
   1955        //Set up Test Root parameters
   1956        var state = tcuTestCase.runner;
   1957        state.setRoot(new es3fShaderCommonFunctionTests.ShaderCommonFunctionTests());
   1958 
   1959        //Set up name and description of this test series.
   1960        setCurrentTestName(state.testCases.fullName());
   1961        description(state.testCases.getDescription());
   1962 
   1963        try {
   1964            //Run test cases
   1965            tcuTestCase.runTestCases();
   1966        }
   1967        catch (err) {
   1968            testFailedOptions('Failed to es3fShaderCommonFunctionTests.run tests', false);
   1969            tcuTestCase.runner.terminate();
   1970        }
   1971    };
   1972 
   1973 });