tor-browser

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

glsBuiltinPrecisionTests.js (204544B)


      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('modules.shared.glsBuiltinPrecisionTests');
     23 goog.require('framework.common.tcuFloatFormat');
     24 goog.require('framework.common.tcuInterval');
     25 goog.require('framework.common.tcuMatrix');
     26 goog.require('framework.common.tcuMatrixUtil');
     27 goog.require('framework.common.tcuTestCase');
     28 goog.require('framework.delibs.debase.deMath');
     29 goog.require('framework.delibs.debase.deRandom');
     30 goog.require('framework.delibs.debase.deUtil');
     31 goog.require('framework.opengl.gluShaderProgram');
     32 goog.require('framework.opengl.gluShaderUtil');
     33 goog.require('framework.opengl.gluVarType');
     34 goog.require('framework.opengl.simplereference.sglrGLContext');
     35 goog.require('modules.shared.glsBuiltinPrecisionTestsUnitTests');
     36 goog.require('modules.shared.glsShaderExecUtil');
     37 
     38 goog.scope(function() {
     39 
     40    var glsBuiltinPrecisionTests = modules.shared.glsBuiltinPrecisionTests;
     41    var tcuTestCase = framework.common.tcuTestCase;
     42    var gluShaderProgram = framework.opengl.gluShaderProgram;
     43    var gluShaderUtil = framework.opengl.gluShaderUtil;
     44    var tcuInterval = framework.common.tcuInterval;
     45    var tcuFloatFormat = framework.common.tcuFloatFormat;
     46    var deRandom = framework.delibs.debase.deRandom;
     47    var glsShaderExecUtil = modules.shared.glsShaderExecUtil;
     48    var sglrGLContext = framework.opengl.simplereference.sglrGLContext;
     49    var deMath = framework.delibs.debase.deMath;
     50    var deUtil = framework.delibs.debase.deUtil;
     51    var gluVarType = framework.opengl.gluVarType;
     52    var tcuMatrix = framework.common.tcuMatrix;
     53    var tcuMatrixUtil = framework.common.tcuMatrixUtil;
     54    var ref = modules.shared.glsBuiltinPrecisionTestsUnitTests.cppreference;
     55    var referenceComparison = modules.shared.glsBuiltinPrecisionTestsUnitTests.referenceComparison;
     56 
     57    var DE_ASSERT = function(x) {
     58        if (!x)
     59            throw new Error('Assert failed');
     60    };
     61 
     62 var setParentClass = function(child, parent) {
     63    child.prototype = Object.create(parent.prototype);
     64    child.prototype.constructor = child;
     65 };
     66 
     67    /** @typedef {(tcuInterval.Interval|Array<tcuInterval.Interval>|tcuMatrix.Matrix)} */
     68    glsBuiltinPrecisionTests.Intervals;
     69 
     70    /** @typedef {(number|Array<number>|tcuMatrix.Matrix)} */
     71    glsBuiltinPrecisionTests.Value;
     72 
     73    /** @typedef {(string)} */
     74    glsBuiltinPrecisionTests.Typename;
     75 
     76    //Change to true for WebGL unit testing
     77    var enableUnittests = false;
     78 
     79    /**
     80     * @param {number} value
     81     * @return {boolean}
     82     */
     83    glsBuiltinPrecisionTests.isFloat = function(value) {
     84        return value % 1 !== 0;
     85     };
     86 
     87    /**
     88     * @constructor
     89     * @param {string} R
     90     * @param {string=} P0
     91     * @param {string=} P1
     92     * @param {string=} P2
     93     * @param {string=} P3
     94     */
     95    glsBuiltinPrecisionTests.Signature = function(R, P0, P1, P2, P3) {
     96        this.Ret = R;
     97        this.Arg0 = P0 === undefined ? 'void' : P0;
     98        this.Arg1 = P1 === undefined ? 'void' : P1;
     99        this.Arg2 = P2 === undefined ? 'void' : P2;
    100        this.Arg3 = P3 === undefined ? 'void' : P3;
    101    };
    102 
    103    /** @typedef {Array<glsBuiltinPrecisionTests.FuncBase>} */
    104    glsBuiltinPrecisionTests.FuncSet;
    105 
    106    /**
    107     * @constructor
    108     * @template T
    109     * @param {T} A0
    110     * @param {T} A1
    111     * @param {T} A2
    112     * @param {T} A3
    113     */
    114    glsBuiltinPrecisionTests.Tuple4 = function(A0, A1, A2, A3) {
    115        this.a = A0;
    116        this.b = A1;
    117        this.c = A2;
    118        this.d = A3;
    119    };
    120 
    121    /**
    122     * @typedef {!glsBuiltinPrecisionTests.Tuple4<string>}
    123     */
    124    glsBuiltinPrecisionTests.ParamNames;
    125 
    126    /**
    127     * Returns true for all other types except Void
    128     * @param {string} typename
    129     */
    130    glsBuiltinPrecisionTests.isTypeValid = function(typename) {
    131        if (typename === 'void')
    132            return false;
    133        return true;
    134    };
    135 
    136    /**
    137     * Returns true for all other types except Void
    138     * @param {*} In
    139     * @return {number}
    140     */
    141    glsBuiltinPrecisionTests.numInputs = function(In) {
    142        return (!glsBuiltinPrecisionTests.isTypeValid(In.In0) ? 0 :
    143                !glsBuiltinPrecisionTests.isTypeValid(In.In1) ? 1 :
    144                !glsBuiltinPrecisionTests.isTypeValid(In.In2) ? 2 :
    145                !glsBuiltinPrecisionTests.isTypeValid(In.In3) ? 3 :
    146                4);
    147    };
    148 
    149    /**
    150     * Returns true for all other types except Void
    151     * @param {*} Out
    152     * @return {number}
    153     */
    154    glsBuiltinPrecisionTests.numOutputs = function(Out) {
    155        return (!glsBuiltinPrecisionTests.isTypeValid(Out.Out0) ? 0 :
    156                !glsBuiltinPrecisionTests.isTypeValid(Out.Out1) ? 1 :
    157                2);
    158    };
    159 
    160    /**
    161     * @constructor
    162     * @param {glsBuiltinPrecisionTests.Typename=} In0_
    163     * @param {glsBuiltinPrecisionTests.Typename=} In1_
    164     * @param {glsBuiltinPrecisionTests.Typename=} In2_
    165     * @param {glsBuiltinPrecisionTests.Typename=} In3_
    166     */
    167    glsBuiltinPrecisionTests.InTypes = function(In0_, In1_, In2_, In3_) {
    168        this.In0 = In0_ === undefined ? 'void' : In0_;
    169        this.In1 = In1_ === undefined ? 'void' : In1_;
    170        this.In2 = In2_ === undefined ? 'void' : In2_;
    171        this.In3 = In3_ === undefined ? 'void' : In3_;
    172    };
    173 
    174    /**
    175     * @constructor
    176     * @param {glsBuiltinPrecisionTests.Typename=} Out0_
    177     * @param {glsBuiltinPrecisionTests.Typename=} Out1_
    178     */
    179    glsBuiltinPrecisionTests.OutTypes = function(Out0_, Out1_) {
    180        this.Out0 = Out0_ === undefined ? 'void' : Out0_;
    181        this.Out1 = Out1_ === undefined ? 'void' : Out1_;
    182    };
    183 
    184    /**
    185     * @constructor
    186     */
    187    glsBuiltinPrecisionTests.Environment = function() {
    188        /** @type {Object} */ this.m_map = {};
    189    };
    190 
    191    /**
    192     * @param {glsBuiltinPrecisionTests.Variable} variable
    193     * @param {*} value
    194     */
    195    glsBuiltinPrecisionTests.Environment.prototype.bind = function(variable, value) {
    196        this.m_map[variable.getName()] = value;
    197    };
    198 
    199    /**
    200     * @param {*} variable
    201     * @return {glsBuiltinPrecisionTests.Intervals}
    202     */
    203    glsBuiltinPrecisionTests.Environment.prototype.lookup = function(variable) {
    204        if (variable instanceof glsBuiltinPrecisionTests.Variable)
    205           return this.m_map[variable.getName()];
    206 
    207        throw new Error('Invalid lookup input: ' + variable);
    208    };
    209 
    210    /**
    211     * @constructor
    212     * @param {tcuFloatFormat.FloatFormat} format_
    213     * @param {gluShaderUtil.precision} floatPrecision_
    214     * @param {glsBuiltinPrecisionTests.Environment} env_
    215     * @param {number=} callDepth_
    216     */
    217    glsBuiltinPrecisionTests.EvalContext = function(format_, floatPrecision_, env_, callDepth_) {
    218        this.format = format_;
    219        this.floatPrecision = floatPrecision_;
    220        this.env = env_;
    221        this.callDepth = callDepth_ === undefined ? 0 : callDepth_;
    222    };
    223 
    224    /**
    225     * @param {string} typename typename
    226     * @param {tcuFloatFormat.FloatFormat} fmt
    227     * @param {glsBuiltinPrecisionTests.Intervals} value
    228     * @return {glsBuiltinPrecisionTests.Intervals}
    229     */
    230     glsBuiltinPrecisionTests.convert = function(typename, fmt, value) {
    231        var traits = glsBuiltinPrecisionTests.Traits.traitsFactory(typename);
    232 
    233        if (value instanceof Array) {
    234            var ret = [];
    235            for (var i = 0; i < value.length; i++)
    236                ret.push(traits.doConvert(fmt, value[i]));
    237            return ret;
    238        }
    239 
    240        if (value instanceof tcuMatrix.Matrix) {
    241            var ret = new tcuMatrix.Matrix(value.rows, value.cols);
    242            for (var i = 0; i < value.rows; i++)
    243                for (var j = 0; j < value.cols; j++)
    244                    ret.set(i, j, traits.doConvert(fmt, value.get(i, j)));
    245            return ret;
    246        }
    247 
    248        return traits.doConvert(fmt, value);
    249    };
    250 
    251    /**
    252     * Returns true if every element of `ival` contains the corresponding element of `value`.
    253     * @param {string} typename typename
    254     * @param {glsBuiltinPrecisionTests.Intervals} ival
    255     * @param {*} value
    256     * @return {boolean}
    257     */
    258     glsBuiltinPrecisionTests.contains = function(typename, ival, value) {
    259        var traits = glsBuiltinPrecisionTests.Traits.traitsFactory(typename);
    260        var contains = true;
    261 
    262        if (value instanceof Array) {
    263            for (var i = 0; i < value.length; i++)
    264                contains &= traits.doContains(ival[i], value[i]);
    265            return contains;
    266        }
    267 
    268        if (value instanceof tcuMatrix.Matrix) {
    269            for (var i = 0; i < value.rows; i++)
    270                for (var j = 0; j < value.cols; j++)
    271                    contains &= traits.doContains(ival.get(i, j), value.get(i, j));
    272            return contains;
    273        }
    274 
    275        return traits.doContains(ival, value);
    276    };
    277 
    278    /**
    279     * @param {string} typename typename
    280     * @param {glsBuiltinPrecisionTests.Intervals} ival0
    281     * @param {glsBuiltinPrecisionTests.Intervals} ival1
    282     * @return {glsBuiltinPrecisionTests.Intervals}
    283     */
    284     glsBuiltinPrecisionTests.union = function(typename, ival0, ival1) {
    285        var traits = glsBuiltinPrecisionTests.Traits.traitsFactory(typename);
    286 
    287        if (ival0 instanceof Array) {
    288            var ret = [];
    289            for (var i = 0; i < ival0.length; i++)
    290                ret.push(traits.doUnion(ival0[i], ival1[i]));
    291            return ret;
    292        }
    293 
    294        if (ival0 instanceof tcuMatrix.Matrix) {
    295            var ret = new tcuMatrix.Matrix(ival0.rows, ival0.cols);
    296            for (var i = 0; i < ival0.rows; i++)
    297                for (var j = 0; j < ival0.cols; j++)
    298                    ret.set(i, j, traits.doUnion(ival0.get(i, j), ival1.get(i, j)));
    299            return ret;
    300        }
    301 
    302        return traits.doUnion(ival0, ival1);
    303    };
    304 
    305    /**
    306     * @param {string} typename
    307     * @constructor
    308     */
    309    glsBuiltinPrecisionTests.Traits = function(typename) {
    310        this.typename = typename;
    311        this.rows = 1;
    312        this.cols = 1;
    313    };
    314 
    315    glsBuiltinPrecisionTests.Traits.prototype.isScalar = function() {
    316        return this.rows == 1 && this.cols == 1;
    317    };
    318 
    319    glsBuiltinPrecisionTests.Traits.prototype.isVector = function() {
    320        return this.rows > 0 && this.cols == 1;
    321    };
    322 
    323    glsBuiltinPrecisionTests.Traits.prototype.isMatrix = function() {
    324        return this.rows > 0 && this.cols > 1;
    325    };
    326 
    327    /**
    328     * @param {string=} typename
    329     */
    330    glsBuiltinPrecisionTests.Traits.traitsFactory = function(typename) {
    331        switch (typename) {
    332            case 'boolean' : return new glsBuiltinPrecisionTests.TraitsBool();
    333            case 'float' : case 'vec2' : case 'vec3' : case 'vec4' :
    334            case 'mat2' : case 'mat2x3' : case 'mat2x4' :
    335            case 'mat3x2' : case 'mat3' : case 'mat3x4' :
    336            case 'mat4x2' : case 'mat4x3' : case 'mat4' :
    337                return new glsBuiltinPrecisionTests.TraitsFloat(typename);
    338            case 'int' : return new glsBuiltinPrecisionTests.TraitsInt();
    339            case 'void' : return new glsBuiltinPrecisionTests.TraitsVoid();
    340            default:
    341                throw new Error('Invalid typename:' + typename);
    342        }
    343    };
    344 
    345    glsBuiltinPrecisionTests.round = function(typename, fmt, value) {
    346        var traits = glsBuiltinPrecisionTests.Traits.traitsFactory(typename);
    347 
    348        if (value instanceof Array) {
    349            var ret = [];
    350            for (var i = 0; i < value.length; i++)
    351                ret.push(traits.doRound(fmt, value[i]));
    352            return ret;
    353        }
    354 
    355        if (value instanceof tcuMatrix.Matrix) {
    356            var ret = new tcuMatrix.Matrix(value.rows, value.cols);
    357            for (var i = 0; i < value.rows; i++)
    358                for (var j = 0; j < value.cols; j++)
    359                    ret.set(i, j, traits.doRound(fmt, value.get(i, j)));
    360            return ret;
    361        }
    362 
    363        return traits.doRound(fmt, value);
    364    };
    365 
    366    /**
    367     * cast the input typed array to correct type
    368     * @param {string} typename
    369     * @param {goog.TypedArray} input
    370     * @return {goog.TypedArray}
    371     */
    372    glsBuiltinPrecisionTests.cast = function(typename, input) {
    373        var traits = glsBuiltinPrecisionTests.Traits.traitsFactory(typename);
    374        return traits.doCast(input);
    375    };
    376 
    377    /**
    378     * @constructor
    379     * @extends {glsBuiltinPrecisionTests.Traits}
    380     */
    381    glsBuiltinPrecisionTests.TraitsVoid = function() {
    382        glsBuiltinPrecisionTests.Traits.call(this, 'void');
    383    };
    384 
    385    setParentClass(glsBuiltinPrecisionTests.TraitsVoid, glsBuiltinPrecisionTests.Traits);
    386 
    387    /**
    388     * @param {*} value
    389     * @return {tcuInterval.Interval}
    390     */
    391    glsBuiltinPrecisionTests.TraitsVoid.prototype.doMakeIVal = function(value) {
    392        return new tcuInterval.Interval();
    393    };
    394 
    395    /**
    396     * @param {*} value1
    397     * @param {*} value2
    398     * @return {tcuInterval.Interval}
    399     */
    400    glsBuiltinPrecisionTests.TraitsVoid.prototype.doUnion = function(value1, value2) {
    401        return new tcuInterval.Interval();
    402    };
    403 
    404    /**
    405     * @param {*} value
    406     * @return {boolean}
    407     */
    408    glsBuiltinPrecisionTests.TraitsVoid.prototype.doContains = function(value) {
    409        return true;
    410    };
    411 
    412    /**
    413     * @param {tcuFloatFormat.FloatFormat} fmt
    414     * @param {tcuInterval.Interval} ival
    415     * @return {tcuInterval.Interval}
    416     */
    417    glsBuiltinPrecisionTests.TraitsVoid.prototype.doConvert = function(fmt, ival) {
    418        return new tcuInterval.Interval();
    419    };
    420 
    421    /**
    422     * @param {tcuFloatFormat.FloatFormat} fmt
    423     * @param {*} ival
    424     * @return {tcuInterval.Interval}
    425     */
    426    glsBuiltinPrecisionTests.TraitsVoid.prototype.doRound = function(fmt, ival) {
    427        return new tcuInterval.Interval();
    428    };
    429 
    430    /**
    431     * @param {tcuFloatFormat.FloatFormat} fmt
    432     * @param {*} ival
    433     */
    434    glsBuiltinPrecisionTests.TraitsVoid.prototype.doPrintIVal = function(fmt, ival) {
    435        return '()';
    436    };
    437 
    438    /**
    439     * @param {tcuFloatFormat.FloatFormat} fmt
    440     * @param {*} value
    441     */
    442    glsBuiltinPrecisionTests.TraitsVoid.prototype.doPrintValue = function(fmt, value) {
    443        return '()';
    444    };
    445 
    446    glsBuiltinPrecisionTests.dataTypeSize = function(detailedType) {
    447        var size = [1, 1];
    448        switch (detailedType) {
    449            case 'vec2' : size[0] = 2; break;
    450            case 'vec3' : size[0] = 3; break;
    451            case 'vec4' : size[0] = 4; break;
    452            case 'mat2' : size = [2 , 2]; break;
    453            case 'mat2x3' : size = [3 , 2]; break;
    454            case 'mat2x4' : size = [4 , 2]; break;
    455 
    456            case 'mat3x2' : size = [2 , 3]; break;
    457            case 'mat3' : size = [3 , 3]; break;
    458            case 'mat3x4' : size = [4 , 3]; break;
    459 
    460            case 'mat4x2' : size = [2 , 4]; break;
    461            case 'mat4x3' : size = [3 , 4]; break;
    462            case 'mat4' : size = [4 , 4]; break;
    463        }
    464        return size;
    465    };
    466 
    467    /**
    468     * @constructor
    469     * @extends {glsBuiltinPrecisionTests.Traits}
    470     * @param {string} typename
    471     * @param {string=} detailedType
    472     */
    473    glsBuiltinPrecisionTests.ScalarTraits = function(typename, detailedType) {
    474        glsBuiltinPrecisionTests.Traits.call(this, typename);
    475        var size = glsBuiltinPrecisionTests.dataTypeSize(detailedType);
    476        this.rows = size[0];
    477        this.cols = size[1];
    478 
    479        /** type{tcuInterval.Interval} */ this.iVal;
    480    };
    481 
    482    setParentClass(glsBuiltinPrecisionTests.ScalarTraits, glsBuiltinPrecisionTests.Traits);
    483 
    484    glsBuiltinPrecisionTests.ScalarTraits.prototype = Object.create(glsBuiltinPrecisionTests.Traits.prototype);
    485    glsBuiltinPrecisionTests.ScalarTraits.prototype.constructor = glsBuiltinPrecisionTests.ScalarTraits;
    486 
    487    /**
    488     * @param {*} value
    489     * @return {tcuInterval.Interval}
    490     */
    491    glsBuiltinPrecisionTests.ScalarTraits.prototype.doMakeIVal = function(value) {
    492        // Thankfully all scalar types have a well-defined conversion to `double`,
    493        // hence Interval can represent their ranges without problems.
    494        return new tcuInterval.Interval(/** @type {number} */ (value));
    495    };
    496 
    497    /**
    498     * @param {tcuInterval.Interval} a
    499     * @param {tcuInterval.Interval} b
    500     * @return {tcuInterval.Interval}
    501     */
    502    glsBuiltinPrecisionTests.ScalarTraits.prototype.doUnion = function(a, b) {
    503        return a.operatorOrBinary(b);
    504    };
    505 
    506    /**
    507     * @param {tcuInterval.Interval} a
    508     * @param {number} value
    509     * @return {boolean}
    510     */
    511    glsBuiltinPrecisionTests.ScalarTraits.prototype.doContains = function(a, value) {
    512        return a.contains(new tcuInterval.Interval(value));
    513    };
    514 
    515    /**
    516     * @param {tcuFloatFormat.FloatFormat} fmt
    517     * @param {tcuInterval.Interval} ival
    518     * @return {tcuInterval.Interval}
    519     */
    520    glsBuiltinPrecisionTests.ScalarTraits.prototype.doConvert = function(fmt, ival) {
    521        return fmt.convert(ival);
    522    };
    523 
    524    /**
    525     * @param {tcuFloatFormat.FloatFormat} fmt
    526     * @param {number} value
    527     * @return {tcuInterval.Interval}
    528     */
    529    glsBuiltinPrecisionTests.ScalarTraits.prototype.doRound = function(fmt, value) {
    530        return fmt.roundOut(new tcuInterval.Interval(value), false);//TODO cast to double
    531    };
    532 
    533    /**
    534     * @constructor
    535     * @extends {glsBuiltinPrecisionTests.ScalarTraits}
    536     * @param {string} detailedType
    537     */
    538    glsBuiltinPrecisionTests.TraitsFloat = function(detailedType) {
    539        glsBuiltinPrecisionTests.ScalarTraits.call(this, 'float', detailedType);
    540    };
    541 
    542    glsBuiltinPrecisionTests.TraitsFloat.prototype = Object.create(glsBuiltinPrecisionTests.ScalarTraits.prototype);
    543    glsBuiltinPrecisionTests.TraitsFloat.prototype.constructor = glsBuiltinPrecisionTests.TraitsFloat;
    544 
    545    /**
    546     * @param {tcuFloatFormat.FloatFormat} fmt
    547     * @param {tcuInterval.Interval} ival
    548     */
    549    glsBuiltinPrecisionTests.TraitsFloat.prototype.doPrintIVal = function(fmt, ival) {
    550        return fmt.intervalToHex(ival);
    551    };
    552 
    553    /**
    554     * @param {goog.TypedArray} input
    555     * @return {goog.TypedArray}
    556     */
    557    glsBuiltinPrecisionTests.TraitsFloat.prototype.doCast = function(input) {
    558        return new Float32Array(input.buffer);
    559    };
    560 
    561    /**
    562     * @param {tcuFloatFormat.FloatFormat} fmt
    563     * @param {number} value
    564     */
    565    glsBuiltinPrecisionTests.TraitsFloat.prototype.doPrintValue = function(fmt, value) {
    566        return fmt.floatToHex(value);
    567    };
    568 
    569    /**
    570     * @constructor
    571     * @extends {glsBuiltinPrecisionTests.ScalarTraits}
    572     */
    573    glsBuiltinPrecisionTests.TraitsBool = function() {
    574        glsBuiltinPrecisionTests.ScalarTraits.call(this, 'boolean');
    575    };
    576 
    577    glsBuiltinPrecisionTests.TraitsBool.prototype = Object.create(glsBuiltinPrecisionTests.ScalarTraits.prototype);
    578    glsBuiltinPrecisionTests.TraitsBool.prototype.constructor = glsBuiltinPrecisionTests.TraitsBool;
    579 
    580    /**
    581     * @param {tcuFloatFormat.FloatFormat} fmt
    582     * @param {tcuInterval.Interval} ival
    583     */
    584    glsBuiltinPrecisionTests.TraitsBool.prototype.doPrintIVal = function(fmt, ival) {
    585        /** type{string} */ var os = '{';
    586        var ifalse = new tcuInterval.Interval(0);
    587        var itrue = new tcuInterval.Interval(1);
    588        if (ival.contains(ifalse))
    589            os += 'false';
    590        if (ival.contains(ifalse) && ival.contains(itrue))
    591            os += ', ';
    592        if (ival.contains(itrue))
    593            os += 'true';
    594        os += '}';
    595        return os;
    596    };
    597 
    598    /**
    599     * @param {tcuFloatFormat.FloatFormat} fmt
    600     * @param {boolean} value
    601     */
    602    glsBuiltinPrecisionTests.TraitsBool.prototype.doPrintValue = function(fmt, value) {
    603        return value ? 'true' : 'false';
    604    };
    605 
    606    /**
    607     * @constructor
    608     * @extends {glsBuiltinPrecisionTests.ScalarTraits}
    609     */
    610    glsBuiltinPrecisionTests.TraitsInt = function() {
    611        glsBuiltinPrecisionTests.ScalarTraits.call(this, 'int');
    612    };
    613 
    614    glsBuiltinPrecisionTests.TraitsInt.prototype = Object.create(glsBuiltinPrecisionTests.ScalarTraits.prototype);
    615    glsBuiltinPrecisionTests.TraitsInt.prototype.constructor = glsBuiltinPrecisionTests.TraitsInt;
    616 
    617    /**
    618     * @param {tcuFloatFormat.FloatFormat} fmt
    619     * @param {tcuInterval.Interval} ival
    620     */
    621    glsBuiltinPrecisionTests.TraitsInt.prototype.doPrintIVal = function(fmt, ival) {
    622        return '[' + (ival.lo()) + ', ' + (ival.hi()) + ']';
    623    };
    624 
    625    /**
    626     * @param {tcuFloatFormat.FloatFormat} fmt
    627     * @param {number} value
    628     */
    629    glsBuiltinPrecisionTests.TraitsInt.prototype.doPrintValue = function(fmt, value) {
    630        return value.toString(10);
    631    };
    632 
    633    /**
    634     * @constructor
    635     */
    636    glsBuiltinPrecisionTests.Statement = function() {
    637 
    638    };
    639 
    640    /**
    641     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
    642     */
    643    glsBuiltinPrecisionTests.Statement.prototype.execute = function(ctx) {
    644        this.doExecute(ctx);
    645    };
    646 
    647    /**
    648     * @return {string}
    649     */
    650    glsBuiltinPrecisionTests.Statement.prototype.print = function() {
    651        return this.doPrint();
    652    };
    653 
    654    glsBuiltinPrecisionTests.Statement.prototype.toString = function() {
    655        return this.print();
    656    };
    657 
    658    /**
    659     * Output the functions that this expression refers to
    660     * @param {glsBuiltinPrecisionTests.FuncSet} dst
    661     *
    662     */
    663    glsBuiltinPrecisionTests.Statement.prototype.getUsedFuncs = function(dst) {
    664        this.doGetUsedFuncs(dst);
    665    };
    666 
    667    /**
    668     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
    669     */
    670    glsBuiltinPrecisionTests.Statement.prototype.doExecute = function(ctx) {
    671        throw new Error('Virtual function. Please override.');
    672    };
    673 
    674    /**
    675     * @return {string}
    676     */
    677    glsBuiltinPrecisionTests.Statement.prototype.doPrint = function() {
    678        throw new Error('Virtual function. Please override.');
    679    };
    680 
    681    /**
    682     * Output the functions that this expression refers to
    683     * @param {glsBuiltinPrecisionTests.FuncSet} dst
    684     *
    685     */
    686    glsBuiltinPrecisionTests.Statement.prototype.doGetUsedFuncs = function(dst) {
    687        throw new Error('Virtual function. Please override.');
    688    };
    689 
    690    /**
    691     * @constructor
    692     * @extends {glsBuiltinPrecisionTests.Statement}
    693     * @param {glsBuiltinPrecisionTests.Variable} variable
    694     * @param {glsBuiltinPrecisionTests.Expr} value
    695     * @param {boolean} isDeclaration
    696     */
    697    glsBuiltinPrecisionTests.VariableStatement = function(variable, value, isDeclaration) {
    698        this.m_variable = variable;
    699        this.m_value = value;
    700        this.m_isDeclaration = isDeclaration;
    701 
    702    };
    703 
    704    setParentClass(glsBuiltinPrecisionTests.VariableStatement, glsBuiltinPrecisionTests.Statement);
    705 
    706    /**
    707     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
    708     */
    709    glsBuiltinPrecisionTests.VariableStatement.prototype.doExecute = function(ctx) {
    710        ctx.env.bind(this.m_variable, this.m_value.evaluate(ctx));
    711    };
    712 
    713    /**
    714     * @return {string}
    715     */
    716    glsBuiltinPrecisionTests.VariableStatement.prototype.doPrint = function() {
    717        var v = this.m_variable;
    718        var os = '';
    719        if (this.m_isDeclaration)
    720            os += gluVarType.declareVariable(gluVarType.getVarTypeOf(v.typename),
    721                        v.getName());
    722        else
    723            os += v.getName();
    724 
    725        os += ' = ' + this.m_value.printExpr() + ';\n';
    726 
    727        return os;
    728    };
    729 
    730    /**
    731     * Output the functions that this expression refers to
    732     * @param {glsBuiltinPrecisionTests.FuncSet} dst
    733     *
    734     */
    735    glsBuiltinPrecisionTests.VariableStatement.prototype.doGetUsedFuncs = function(dst) {
    736        this.m_value.getUsedFuncs(dst);
    737    };
    738 
    739    /**
    740     * @param {glsBuiltinPrecisionTests.Variable} variable
    741     * @param {glsBuiltinPrecisionTests.Expr} definiens
    742     * @return {glsBuiltinPrecisionTests.VariableStatement}
    743     */
    744    glsBuiltinPrecisionTests.variableDeclaration = function(variable, definiens) {
    745        return new glsBuiltinPrecisionTests.VariableStatement(variable, definiens, true);
    746    };
    747 
    748    /**
    749     * @param {string} typename
    750     * @param {string} name
    751     * @param {glsBuiltinPrecisionTests.ExpandContext} ctx
    752     * @param {glsBuiltinPrecisionTests.Expr} expr
    753     * @return {glsBuiltinPrecisionTests.Variable}
    754     */
    755    glsBuiltinPrecisionTests.bindExpression = function(typename, name, ctx, expr) {
    756        var variable = ctx.genSym(typename, name);
    757        ctx.addStatement(glsBuiltinPrecisionTests.variableDeclaration(variable, expr));
    758        return variable;
    759    };
    760 
    761    /**
    762     * Common base class for all expressions regardless of their type.
    763     * @constructor
    764     */
    765    glsBuiltinPrecisionTests.ExprBase = function() {};
    766 
    767    /**
    768     * @return {string}
    769     */
    770    glsBuiltinPrecisionTests.ExprBase.prototype.printExpr = function() {
    771        return this.doPrintExpr();
    772    };
    773 
    774    glsBuiltinPrecisionTests.ExprBase.prototype.toString = function() {
    775        return this.printExpr();
    776    };
    777 
    778    /**
    779     * @return {string}
    780     */
    781    glsBuiltinPrecisionTests.ExprBase.prototype.doPrintExpr = function() {
    782        throw new Error('Virtual function. Please override.');
    783    };
    784 
    785    /**
    786     * Output the functions that this expression refers to
    787     * @param {glsBuiltinPrecisionTests.FuncSet} dst
    788     *
    789     */
    790    glsBuiltinPrecisionTests.ExprBase.prototype.getUsedFuncs = function(/*FuncSet&*/ dst) {
    791        this.doGetUsedFuncs(dst);
    792    };
    793 
    794    /**
    795     * Output the functions that this expression refers to
    796     * @param {glsBuiltinPrecisionTests.FuncSet} dst
    797     *
    798     */
    799    glsBuiltinPrecisionTests.ExprBase.prototype.doGetUsedFuncs = function(/*FuncSet&*/ dst) {
    800        throw new Error('Virtual function. Please override.');
    801    };
    802 
    803    /**
    804     * Type-specific operations for an expression representing type typename.
    805     * @constructor
    806     * @extends {glsBuiltinPrecisionTests.ExprBase}
    807     * @param {glsBuiltinPrecisionTests.Typename} typename
    808     */
    809    glsBuiltinPrecisionTests.Expr = function(typename) {
    810        glsBuiltinPrecisionTests.ExprBase.call(this);
    811        this.typename = typename;
    812    };
    813 
    814    setParentClass(glsBuiltinPrecisionTests.Expr, glsBuiltinPrecisionTests.ExprBase);
    815 
    816    /**
    817     * Type-specific operations for an expression representing type typename.
    818     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
    819     */
    820    glsBuiltinPrecisionTests.Expr.prototype.evaluate = function(ctx) {
    821        return this.doEvaluate(ctx);
    822    };
    823 
    824    /**
    825     * Type-specific operations for an expression representing type typename.
    826     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
    827     */
    828    glsBuiltinPrecisionTests.Expr.prototype.doEvaluate = function(ctx) {
    829        throw new Error('Virtual function. Please override.');
    830    };
    831 
    832    /**
    833     * @constructor
    834     * @extends {glsBuiltinPrecisionTests.Expr}
    835     * @param {glsBuiltinPrecisionTests.Typename} typename
    836     * @param {string=} name
    837     */
    838    glsBuiltinPrecisionTests.Variable = function(typename, name) {
    839        glsBuiltinPrecisionTests.Expr.call(this, typename);
    840        /** @type {string} */ this.m_name = name || '<undefined>';
    841    };
    842 
    843    setParentClass(glsBuiltinPrecisionTests.Variable, glsBuiltinPrecisionTests.Expr);
    844 
    845    /**
    846     * @return {string}
    847     */
    848    glsBuiltinPrecisionTests.Variable.prototype.getName = function() {
    849        return this.m_name;
    850    };
    851 
    852    /**
    853     * @return {string}
    854     */
    855    glsBuiltinPrecisionTests.Variable.prototype.doPrintExpr = function() {
    856        return this.m_name;
    857    };
    858 
    859    glsBuiltinPrecisionTests.Variable.prototype.toString = function() {
    860        return this.doPrintExpr();
    861    };
    862 
    863    /**
    864     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
    865     * @return {*}
    866     */
    867    glsBuiltinPrecisionTests.Variable.prototype.doEvaluate = function(ctx) {
    868        return ctx.env.lookup(this);
    869    };
    870 
    871    /**
    872     * @constructor
    873     * @extends {glsBuiltinPrecisionTests.Variable}
    874     * @param {*=} t
    875     */
    876    glsBuiltinPrecisionTests.Void = function(t) {
    877        glsBuiltinPrecisionTests.Variable.call(this, 'void');
    878    };
    879 
    880    setParentClass(glsBuiltinPrecisionTests.Void, glsBuiltinPrecisionTests.Variable);
    881 
    882    glsBuiltinPrecisionTests.Void.prototype.doEvaluate = function(ctx) {
    883        return undefined;
    884    };
    885 
    886    /**
    887     * @constructor
    888     * @extends {glsBuiltinPrecisionTests.Variable}
    889     * @param {number} value
    890     */
    891    glsBuiltinPrecisionTests.Constant = function(value) {
    892        glsBuiltinPrecisionTests.Variable.call(this, 'float');
    893        this.m_value = value;
    894    };
    895 
    896    setParentClass(glsBuiltinPrecisionTests.Constant, glsBuiltinPrecisionTests.Variable);
    897 
    898    glsBuiltinPrecisionTests.Constant.prototype.doEvaluate = function(ctx) {
    899        return new tcuInterval.Interval(this.m_value);
    900    };
    901 
    902    /**
    903     * @constructor
    904     * @param {*} typename
    905     */
    906    glsBuiltinPrecisionTests.DefaultSampling = function(typename) {
    907        this.typename = typename;
    908    };
    909 
    910    /**
    911     * @constructor
    912     * @extends {glsBuiltinPrecisionTests.Expr}
    913     * @param {glsBuiltinPrecisionTests.Variable} vector
    914     * @param {number} index
    915     */
    916    glsBuiltinPrecisionTests.VectorVariable = function(vector, index) {
    917        glsBuiltinPrecisionTests.Expr.call(this, vector.typename);
    918        this.m_vector = vector;
    919        this.m_index = index;
    920    };
    921 
    922    setParentClass(glsBuiltinPrecisionTests.VectorVariable, glsBuiltinPrecisionTests.Expr);
    923 
    924    /**
    925     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
    926     * @return {tcuInterval.Interval}
    927     */
    928    glsBuiltinPrecisionTests.VectorVariable.prototype.doEvaluate = function(ctx) {
    929        var tmp = this.m_vector.doEvaluate(ctx);
    930        return tmp[this.m_index];
    931    };
    932 
    933    /**
    934     * @constructor
    935     * @extends {glsBuiltinPrecisionTests.Expr}
    936     * @param {glsBuiltinPrecisionTests.Variable} matrix
    937     * @param {number} row
    938     * @param {number} col
    939     */
    940    glsBuiltinPrecisionTests.MatrixVariable = function(matrix, row, col) {
    941        glsBuiltinPrecisionTests.Expr.call(this, matrix.typename);
    942        this.m_matrix = matrix;
    943        this.m_row = row;
    944        this.m_col = col;
    945    };
    946 
    947    setParentClass(glsBuiltinPrecisionTests.MatrixVariable, glsBuiltinPrecisionTests.Expr);
    948 
    949    /**
    950     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
    951     * @return {tcuInterval.Interval}
    952     */
    953    glsBuiltinPrecisionTests.MatrixVariable.prototype.doEvaluate = function(ctx) {
    954        var tmp = this.m_matrix.doEvaluate(ctx);
    955        return tmp.get(this.m_row, this.m_col);
    956    };
    957 
    958    /**
    959     * @constructor
    960     * @extends {glsBuiltinPrecisionTests.Expr}
    961     * @param {glsBuiltinPrecisionTests.Typename} typename
    962     * @param {glsBuiltinPrecisionTests.Func} func
    963     * @param {glsBuiltinPrecisionTests.Expr=} arg0
    964     * @param {glsBuiltinPrecisionTests.Expr=} arg1
    965     * @param {glsBuiltinPrecisionTests.Expr=} arg2
    966     * @param {glsBuiltinPrecisionTests.Expr=} arg3
    967     */
    968    glsBuiltinPrecisionTests.Apply = function(typename, func, arg0, arg1, arg2, arg3) {
    969        glsBuiltinPrecisionTests.Expr.call(this, typename);
    970        this.m_func = func;
    971        /** @type {glsBuiltinPrecisionTests.Tuple4} */ this.m_args;
    972        if (arg0 instanceof glsBuiltinPrecisionTests.Tuple4)
    973            this.m_args = /** @type {glsBuiltinPrecisionTests.Tuple4} */ (arg0);
    974        else {
    975            this.m_args = new glsBuiltinPrecisionTests.Tuple4(arg0 || new glsBuiltinPrecisionTests.Void(),
    976                                                              arg1 || new glsBuiltinPrecisionTests.Void(),
    977                                                              arg2 || new glsBuiltinPrecisionTests.Void(),
    978                                                              arg3 || new glsBuiltinPrecisionTests.Void());
    979        }
    980    };
    981 
    982    setParentClass(glsBuiltinPrecisionTests.Apply, glsBuiltinPrecisionTests.Expr);
    983 
    984    /**
    985     * @return {string}
    986     */
    987    glsBuiltinPrecisionTests.Apply.prototype.doPrintExpr = function() {
    988        var args = [this.m_args.a, this.m_args.b, this.m_args.c, this.m_args.d];
    989        return this.m_func.print(args);
    990    };
    991 
    992    /**
    993     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
    994     * @return {glsBuiltinPrecisionTests.Intervals}
    995     */
    996    glsBuiltinPrecisionTests.Apply.prototype.doEvaluate = function(ctx) {
    997        var debug = false;
    998 
    999        if (debug) {
   1000            glsBuiltinPrecisionTests.Apply.prototype.doEvaluate.level = glsBuiltinPrecisionTests.Apply.prototype.doEvaluate.level || 0;
   1001            var level = glsBuiltinPrecisionTests.Apply.prototype.doEvaluate.level;
   1002            glsBuiltinPrecisionTests.Apply.prototype.doEvaluate.level++;
   1003            var name = this.m_func.constructor.toString();
   1004            name = name.replace(/[\s\S]*glsBuiltinPrecisionTests\./m, '').replace(/\.call[\s\S]*/m, '');
   1005            if (this.m_func.getName)
   1006                name += ' ' + this.m_func.getName();
   1007            console.log('<' + level + '> Function ' + name);
   1008        }
   1009 
   1010        var a = this.m_args.a.evaluate(ctx);
   1011        var b = this.m_args.b.evaluate(ctx);
   1012        var c = this.m_args.c.evaluate(ctx);
   1013        var d = this.m_args.d.evaluate(ctx);
   1014        var retVal = this.m_func.applyFunction(ctx, a, b, c, d);
   1015 
   1016        if (debug) {
   1017            console.log('<' + level + '> a: ' + a);
   1018            console.log('<' + level + '> b: ' + b);
   1019            console.log('<' + level + '> returning: ' + retVal);
   1020            glsBuiltinPrecisionTests.Apply.prototype.doEvaluate.level--;
   1021        }
   1022        return retVal;
   1023    };
   1024 
   1025    /**
   1026     * @param {glsBuiltinPrecisionTests.Func} func
   1027     * @param {glsBuiltinPrecisionTests.Expr=} arg0
   1028     * @param {glsBuiltinPrecisionTests.Expr=} arg1
   1029     * @param {glsBuiltinPrecisionTests.Expr=} arg2
   1030     * @param {glsBuiltinPrecisionTests.Expr=} arg3
   1031     */
   1032    var app = function(func, arg0, arg1, arg2, arg3) {
   1033        return new glsBuiltinPrecisionTests.Apply('float', func, arg0, arg1, arg2, arg3);
   1034    };
   1035 
   1036    /**
   1037     * @param {glsBuiltinPrecisionTests.FuncSet} dst
   1038     */
   1039    glsBuiltinPrecisionTests.Apply.prototype.doGetUsedFuncs = function(dst) {
   1040        this.m_func.getUsedFuncs(dst);
   1041        this.m_args.a.getUsedFuncs(dst);
   1042        this.m_args.b.getUsedFuncs(dst);
   1043        this.m_args.c.getUsedFuncs(dst);
   1044        this.m_args.d.getUsedFuncs(dst);
   1045    };
   1046 
   1047    /**
   1048     * @constructor
   1049     * @extends {glsBuiltinPrecisionTests.Apply}
   1050     * @param {glsBuiltinPrecisionTests.Func} func
   1051     * @param {glsBuiltinPrecisionTests.Expr=} arg0
   1052     * @param {glsBuiltinPrecisionTests.Expr=} arg1
   1053     * @param {glsBuiltinPrecisionTests.Expr=} arg2
   1054     * @param {glsBuiltinPrecisionTests.Expr=} arg3
   1055     */
   1056    glsBuiltinPrecisionTests.ApplyScalar = function(func, arg0, arg1, arg2, arg3) {
   1057        glsBuiltinPrecisionTests.Apply.call(this, 'float', func, arg0, arg1, arg2, arg3);
   1058    };
   1059 
   1060    setParentClass(glsBuiltinPrecisionTests.ApplyScalar, glsBuiltinPrecisionTests.Apply);
   1061 
   1062    glsBuiltinPrecisionTests.ApplyScalar.prototype.doEvaluate = function(ctx) {
   1063        var debug = false;
   1064 
   1065        if (debug) {
   1066            glsBuiltinPrecisionTests.ApplyScalar.prototype.doEvaluate.level = glsBuiltinPrecisionTests.ApplyScalar.prototype.doEvaluate.level || 0;
   1067            var level = glsBuiltinPrecisionTests.ApplyScalar.prototype.doEvaluate.level;
   1068            glsBuiltinPrecisionTests.ApplyScalar.prototype.doEvaluate.level++;
   1069            var name = this.m_func.constructor.toString();
   1070            name = name.replace(/[\s\S]*glsBuiltinPrecisionTests\./m, '').replace(/\.call[\s\S]*/m, '');
   1071            if (this.m_func.getName)
   1072                name += ' ' + this.m_func.getName();
   1073            console.log('scalar<' + level + '> Function ' + name);
   1074        }
   1075 
   1076        var a = this.m_args.a.evaluate(ctx);
   1077        var b = this.m_args.b.evaluate(ctx);
   1078        var c = this.m_args.c.evaluate(ctx);
   1079        var d = this.m_args.d.evaluate(ctx);
   1080        if (a instanceof Array) {
   1081            var ret = [];
   1082            for (var i = 0; i < a.length; i++) {
   1083                var p0 = a instanceof Array ? a[i] : a;
   1084                var p1 = b instanceof Array ? b[i] : b;
   1085                var p2 = c instanceof Array ? c[i] : c;
   1086                var p3 = d instanceof Array ? d[i] : d;
   1087                ret.push(this.m_func.applyFunction(ctx, p0, p1, p2, p3));
   1088            }
   1089            return ret;
   1090        }
   1091 
   1092        var retVal = this.m_func.applyFunction(ctx, a, b, c, d);
   1093 
   1094        if (debug) {
   1095            console.log('scalar<' + level + '> a: ' + a);
   1096            console.log('scalar<' + level + '> b: ' + b);
   1097            console.log('scalar<' + level + '> return1: ' + ret);
   1098            console.log('scalar<' + level + '> return2: ' + retVal);
   1099            glsBuiltinPrecisionTests.Apply.prototype.doEvaluate.level--;
   1100        }
   1101 
   1102        return retVal;
   1103    };
   1104 
   1105    /**
   1106     * @constructor
   1107     * @extends {glsBuiltinPrecisionTests.Apply}
   1108     */
   1109    glsBuiltinPrecisionTests.ApplyVar = function(typename, func, arg0, arg1, arg2, arg3) {
   1110        glsBuiltinPrecisionTests.Apply.call(this, typename, func, arg0, arg1, arg2, arg3);
   1111    };
   1112 
   1113    setParentClass(glsBuiltinPrecisionTests.ApplyVar, glsBuiltinPrecisionTests.Apply);
   1114 
   1115    /**
   1116     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
   1117     * @return {glsBuiltinPrecisionTests.Intervals}
   1118     */
   1119    glsBuiltinPrecisionTests.ApplyVar.prototype.doEvaluate = function(ctx) {
   1120        return this.m_func.applyFunction(ctx,
   1121                    ctx.env.lookup(this.m_args.a), ctx.env.lookup(this.m_args.b),
   1122                    ctx.env.lookup(this.m_args.c), ctx.env.lookup(this.m_args.d),
   1123                    [this.m_args.a.getName(), this.m_args.b.getName(),
   1124                    this.m_args.c.getName(), this.m_args.d.getName()]);
   1125    };
   1126 
   1127    /**
   1128     * @constructor
   1129     */
   1130    glsBuiltinPrecisionTests.FuncBase = function() {};
   1131 
   1132    /**
   1133     * @return {string}
   1134     */
   1135    glsBuiltinPrecisionTests.FuncBase.prototype.getName = function() {
   1136        return '';
   1137    };
   1138 
   1139    /**
   1140     * @return {string}
   1141     */
   1142    glsBuiltinPrecisionTests.FuncBase.prototype.getRequiredExtension = function() {
   1143        return '';
   1144    };
   1145 
   1146    /**
   1147     * @param {Array<glsBuiltinPrecisionTests.ExprBase>} args
   1148     * @return {string}
   1149     */
   1150    glsBuiltinPrecisionTests.FuncBase.prototype.print = function(args) {
   1151        return '';
   1152    };
   1153 
   1154    /**
   1155     * Index of output parameter, or -1 if none of the parameters is output.
   1156     * @return {number}
   1157     */
   1158    glsBuiltinPrecisionTests.FuncBase.prototype.getOutParamIndex = function() {
   1159        return -1;
   1160    };
   1161 
   1162    /**
   1163     * @return {string}
   1164     */
   1165    glsBuiltinPrecisionTests.FuncBase.prototype.printDefinition = function() {
   1166        return this.doPrintDefinition();
   1167    };
   1168 
   1169    /**
   1170     * @return {string}
   1171     */
   1172    glsBuiltinPrecisionTests.FuncBase.prototype.doPrintDefinition = function() {
   1173        throw new Error('Virtual function. Please override.');
   1174    };
   1175 
   1176    /**
   1177     * typedef set<const FuncBase*> FuncSet;
   1178     * @param {glsBuiltinPrecisionTests.FuncSet} dst
   1179     */
   1180    glsBuiltinPrecisionTests.FuncBase.prototype.getUsedFuncs = function(dst) {
   1181        this.doGetUsedFuncs(dst);
   1182    };
   1183 
   1184    /**
   1185     * @param {glsBuiltinPrecisionTests.FuncSet} dst
   1186     */
   1187    glsBuiltinPrecisionTests.FuncBase.prototype.doGetUsedFuncs = function(dst) {};
   1188 
   1189    /*************************************/
   1190    /**
   1191     * \brief Function objects.
   1192     *
   1193     * Each Func object represents a GLSL function. It can be applied to interval
   1194     * arguments, and it returns the an interval that is a conservative
   1195     * approximation of the image of the GLSL function over the argument
   1196     * intervals. That is, it is given a set of possible arguments and it returns
   1197     * the set of possible values.
   1198     *
   1199     * @constructor
   1200     * @extends {glsBuiltinPrecisionTests.FuncBase}
   1201     * @param {glsBuiltinPrecisionTests.Signature} Sig_ template <typename Sig_>
   1202     */
   1203    glsBuiltinPrecisionTests.Func = function(Sig_) {
   1204        glsBuiltinPrecisionTests.FuncBase.call(this);
   1205        this.Sig = Sig_;
   1206        this.Ret = this.Sig.Ret;
   1207        this.Arg0 = this.Sig.Arg0;
   1208        this.Arg1 = this.Sig.Arg1;
   1209        this.Arg2 = this.Sig.Arg2;
   1210        this.Arg3 = this.Sig.Arg3;
   1211    };
   1212 
   1213    glsBuiltinPrecisionTests.Func.prototype = Object.create(glsBuiltinPrecisionTests.FuncBase.prototype);
   1214    glsBuiltinPrecisionTests.Func.prototype.constructor = glsBuiltinPrecisionTests.Func;
   1215 
   1216    /**
   1217     * @param {Array<glsBuiltinPrecisionTests.ExprBase>} args
   1218     * @return {string}
   1219     */
   1220    glsBuiltinPrecisionTests.Func.prototype.print = function(args) {
   1221        return this.doPrint(args);
   1222    };
   1223 
   1224    /**
   1225     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
   1226     * @param {glsBuiltinPrecisionTests.Intervals=} Iarg0
   1227     * @param {glsBuiltinPrecisionTests.Intervals=} Iarg1
   1228     * @param {glsBuiltinPrecisionTests.Intervals=} Iarg2
   1229     * @param {glsBuiltinPrecisionTests.Intervals=} Iarg3
   1230     * @return {glsBuiltinPrecisionTests.Intervals}
   1231     */
   1232    glsBuiltinPrecisionTests.Func.prototype.applyFunction = function(ctx, Iarg0, Iarg1, Iarg2, Iarg3, variablenames) {
   1233        return this.applyArgs(ctx, new glsBuiltinPrecisionTests.Tuple4(Iarg0, Iarg1, Iarg2, Iarg3), variablenames);
   1234    };
   1235 
   1236    /**
   1237     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
   1238     * @param {glsBuiltinPrecisionTests.Tuple4} args
   1239     * @return {glsBuiltinPrecisionTests.Intervals}
   1240     */
   1241    glsBuiltinPrecisionTests.Func.prototype.applyArgs = function(ctx, args, variablenames) {
   1242        return this.doApply(ctx, args, variablenames);
   1243    };
   1244 
   1245    /**
   1246     * @return {glsBuiltinPrecisionTests.ParamNames}
   1247     */
   1248    glsBuiltinPrecisionTests.Func.prototype.getParamNames = function() {
   1249        return this.doGetParamNames();
   1250    };
   1251 
   1252    /**
   1253     * @param {Array<glsBuiltinPrecisionTests.ExprBase>} args
   1254     * @return {string}
   1255     */
   1256    glsBuiltinPrecisionTests.Func.prototype.doPrint = function(args) {
   1257        /** type{string} */ var os = this.getName() + '(';
   1258 
   1259        // TODO: fix the generics
   1260        for (var i = 0; i < args.length; i++)
   1261            if (glsBuiltinPrecisionTests.isTypeValid(args[i].typename)) {
   1262                if (i != 0)
   1263                    os += ', ';
   1264                os += args[i];
   1265            }
   1266 
   1267        os += ')';
   1268 
   1269        return os;
   1270    };
   1271 
   1272    /**
   1273     * @return {glsBuiltinPrecisionTests.ParamNames} args
   1274     */
   1275    glsBuiltinPrecisionTests.Func.prototype.doGetParamNames = function() {
   1276        /** @type {glsBuiltinPrecisionTests.ParamNames} */ var names = new glsBuiltinPrecisionTests.Tuple4('a', 'b', 'c', 'd');
   1277        return names;
   1278    };
   1279 
   1280    /**
   1281     * @constructor
   1282     * @extends {glsBuiltinPrecisionTests.Func}
   1283     * @param {glsBuiltinPrecisionTests.Signature} Sig template <typename Sig>
   1284     *
   1285     */
   1286    glsBuiltinPrecisionTests.PrimitiveFunc = function(Sig) {
   1287        glsBuiltinPrecisionTests.Func.call(this, Sig);
   1288        this.Ret = Sig.Ret;
   1289    };
   1290 
   1291    glsBuiltinPrecisionTests.PrimitiveFunc.prototype = Object.create(glsBuiltinPrecisionTests.Func.prototype);
   1292    glsBuiltinPrecisionTests.PrimitiveFunc.prototype.constructor = glsBuiltinPrecisionTests.PrimitiveFunc;
   1293 
   1294    /**
   1295     * @constructor
   1296     * @extends {glsBuiltinPrecisionTests.PrimitiveFunc}
   1297     * @param {string} typename
   1298     *
   1299     */
   1300    glsBuiltinPrecisionTests.Cond = function(typename) {
   1301        var sig = new glsBuiltinPrecisionTests.Signature(typename, 'boolean', typename, typename);
   1302        glsBuiltinPrecisionTests.PrimitiveFunc.call(this, sig);
   1303    };
   1304 
   1305    setParentClass(glsBuiltinPrecisionTests.Cond, glsBuiltinPrecisionTests.PrimitiveFunc);
   1306 
   1307    glsBuiltinPrecisionTests.Cond.prototype.getName = function() {
   1308        return '_cond';
   1309    };
   1310 
   1311    glsBuiltinPrecisionTests.Cond.prototype.doPrint = function(args) {
   1312        var str = '(' + args[0] + ' ? ' + args[1] + ' : ' + args[2] + ')';
   1313        return str;
   1314    };
   1315 
   1316    glsBuiltinPrecisionTests.Cond.prototype.doApply = function(ctx, iargs) {
   1317        var ret;
   1318        if (glsBuiltinPrecisionTests.contains(this.Sig.Arg0, iargs.a, 1))
   1319            ret = iargs.b;
   1320        if (glsBuiltinPrecisionTests.contains(this.Sig.Arg0, iargs.a, 0)) {
   1321            if (ret)
   1322                ret = glsBuiltinPrecisionTests.union(this.Sig.Ret, ret, iargs.c);
   1323            else
   1324                ret = iargs.c;
   1325        }
   1326        if (ret)
   1327            return ret;
   1328        return new tcuInterval.Interval();
   1329    };
   1330 
   1331    /**
   1332     * If multipleInputs is false, GenVec duplicates first input to proper size
   1333     * @constructor
   1334     * @extends {glsBuiltinPrecisionTests.PrimitiveFunc}
   1335     * @param {number} size
   1336     * @param {boolean=} multipleInputs
   1337     */
   1338    glsBuiltinPrecisionTests.GenVec = function(size, multipleInputs) {
   1339        var vecName = glsBuiltinPrecisionTests.sizeToName(size);
   1340        var p = [
   1341            size >= 1 ? 'float' : undefined,
   1342            size >= 2 ? 'float' : undefined,
   1343            size >= 3 ? 'float' : undefined,
   1344            size >= 4 ? 'float' : undefined
   1345        ];
   1346        var sig = new glsBuiltinPrecisionTests.Signature(vecName, p[0], p[1], p[2], p[3]);
   1347        glsBuiltinPrecisionTests.PrimitiveFunc.call(this, sig);
   1348        this.size = size;
   1349        this.vecName = vecName;
   1350        this.multipleInputs = multipleInputs || false;
   1351    };
   1352 
   1353    setParentClass(glsBuiltinPrecisionTests.GenVec, glsBuiltinPrecisionTests.PrimitiveFunc);
   1354 
   1355    glsBuiltinPrecisionTests.GenVec.prototype.getName = function() {
   1356        return this.vecName;
   1357    };
   1358 
   1359    glsBuiltinPrecisionTests.GenVec.prototype.doApply = function(ctx, iargs) {
   1360        if (this.size == 1)
   1361            return iargs.a;
   1362 
   1363        var ret = this.multipleInputs ?
   1364                        [iargs.a, iargs.b, iargs.c, iargs.d] :
   1365                        [iargs.a, iargs.a, iargs.a, iargs.a];
   1366 
   1367        return ret.slice(0, this.size);
   1368    };
   1369 
   1370    /**
   1371     * @constructor
   1372     * @extends {glsBuiltinPrecisionTests.PrimitiveFunc}
   1373     * @param {number} rows
   1374     * @param {number} cols
   1375     */
   1376    glsBuiltinPrecisionTests.GenMat = function(rows, cols) {
   1377        var name = glsBuiltinPrecisionTests.dataTypeNameOfMatrix('float', rows, cols);
   1378        var vecName = glsBuiltinPrecisionTests.sizeToName(rows);
   1379        var p = [
   1380            cols >= 1 ? vecName : undefined,
   1381            cols >= 2 ? vecName : undefined,
   1382            cols >= 3 ? vecName : undefined,
   1383            cols >= 4 ? vecName : undefined
   1384        ];
   1385        var sig = new glsBuiltinPrecisionTests.Signature(name, p[0], p[1], p[2], p[3]);
   1386        glsBuiltinPrecisionTests.PrimitiveFunc.call(this, sig);
   1387        this.rows = rows;
   1388        this.cols = cols;
   1389        this.name = name;
   1390        this.vecName = vecName;
   1391    };
   1392 
   1393    setParentClass(glsBuiltinPrecisionTests.GenMat, glsBuiltinPrecisionTests.PrimitiveFunc);
   1394 
   1395    glsBuiltinPrecisionTests.GenMat.prototype.getName = function() {
   1396        return this.name;
   1397    };
   1398 
   1399    glsBuiltinPrecisionTests.GenMat.prototype.doApply = function(ctx, iargs) {
   1400        var ret = new tcuMatrix.Matrix(this.rows, this.cols);
   1401        var inputs = [iargs.a, iargs.b, iargs.c, iargs.d];
   1402 
   1403        for (var i = 0; i < this.rows; i++)
   1404            for (var j = 0; j < this.cols; j++)
   1405                ret.set(i, j, inputs[j][i]);
   1406        return ret;
   1407    };
   1408 
   1409    /**
   1410     * @constructor
   1411     * @extends {glsBuiltinPrecisionTests.PrimitiveFunc}
   1412     * @param {string} typename
   1413     *
   1414     */
   1415    glsBuiltinPrecisionTests.CompareOperator = function(typename) {
   1416        var sig = new glsBuiltinPrecisionTests.Signature('boolean', typename, typename);
   1417        glsBuiltinPrecisionTests.PrimitiveFunc.call(this, sig);
   1418    };
   1419 
   1420    setParentClass(glsBuiltinPrecisionTests.CompareOperator, glsBuiltinPrecisionTests.PrimitiveFunc);
   1421 
   1422    glsBuiltinPrecisionTests.CompareOperator.prototype.doPrint = function(args) {
   1423        var str = '(' + args[0] + this.getSymbol() + args[1] + ')';
   1424        return str;
   1425    };
   1426 
   1427    glsBuiltinPrecisionTests.CompareOperator.prototype.doApply = function(ctx, iargs) {
   1428        var arg0 = iargs.a;
   1429        var arg1 = iargs.b;
   1430 
   1431        var ret = new tcuInterval.Interval();
   1432 
   1433        if (this.canSucceed(arg0, arg1))
   1434            ret = new tcuInterval.Interval(1);
   1435        if (this.canFail(arg0, arg1))
   1436            ret.operatorOrAssignBinary(new tcuInterval.Interval(0));
   1437 
   1438        return ret;
   1439    };
   1440 
   1441    /**
   1442     * @return {string}
   1443     */
   1444    glsBuiltinPrecisionTests.CompareOperator.prototype.getSymbol = function() {
   1445        throw new Error('Virtual function. Please override.');
   1446    };
   1447 
   1448    /**
   1449     * @param {tcuInterval.Interval} arg0
   1450     * @param {tcuInterval.Interval} arg1
   1451     * @return {boolean}
   1452     */
   1453    glsBuiltinPrecisionTests.CompareOperator.prototype.canSucceed = function(arg0, arg1) {
   1454        throw new Error('Virtual function. Please override.');
   1455    };
   1456    /**
   1457     * @param {tcuInterval.Interval} arg0
   1458     * @param {tcuInterval.Interval} arg1
   1459     * @return {boolean}
   1460     */
   1461    glsBuiltinPrecisionTests.CompareOperator.prototype.canFail = function(arg0, arg1) {
   1462        throw new Error('Virtual function. Please override.');
   1463    };
   1464 
   1465    /**
   1466     * @constructor
   1467     * @extends {glsBuiltinPrecisionTests.CompareOperator}
   1468     * @param {string} typename
   1469     *
   1470     */
   1471    glsBuiltinPrecisionTests.LessThan = function(typename) {
   1472        glsBuiltinPrecisionTests.CompareOperator.call(this, typename);
   1473    };
   1474 
   1475    setParentClass(glsBuiltinPrecisionTests.LessThan, glsBuiltinPrecisionTests.CompareOperator);
   1476 
   1477    glsBuiltinPrecisionTests.LessThan.prototype.getSymbol = function() {
   1478        return '<';
   1479    };
   1480 
   1481    glsBuiltinPrecisionTests.LessThan.prototype.canSucceed = function(a, b) {
   1482       return (a.lo() < b.hi());
   1483    };
   1484 
   1485    glsBuiltinPrecisionTests.LessThan.prototype.canFail = function(a, b) {
   1486        return !(a.hi() < b.lo());
   1487    };
   1488 
   1489    /**
   1490     * @constructor
   1491     * @extends {glsBuiltinPrecisionTests.PrimitiveFunc}
   1492     *
   1493     */
   1494    glsBuiltinPrecisionTests.FloatFunc1 = function() {
   1495        var sig = new glsBuiltinPrecisionTests.Signature('float', 'float');
   1496        glsBuiltinPrecisionTests.PrimitiveFunc.call(this, sig);
   1497    };
   1498 
   1499    glsBuiltinPrecisionTests.FloatFunc1.prototype = Object.create(glsBuiltinPrecisionTests.PrimitiveFunc.prototype);
   1500    glsBuiltinPrecisionTests.FloatFunc1.prototype.constructor = glsBuiltinPrecisionTests.FloatFunc1;
   1501 
   1502    /**
   1503     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
   1504     * @param {glsBuiltinPrecisionTests.Tuple4} iargs
   1505     * @return {tcuInterval.Interval}
   1506     */
   1507    glsBuiltinPrecisionTests.FloatFunc1.prototype.doApply = function(ctx, iargs) {
   1508        var a = /** @type {tcuInterval.Interval} */ (iargs.a);
   1509        return this.applyMonotone(ctx, a);
   1510    };
   1511 
   1512    /**
   1513     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
   1514     * @param {tcuInterval.Interval} iarg0
   1515     * @return {tcuInterval.Interval}
   1516     */
   1517    glsBuiltinPrecisionTests.FloatFunc1.prototype.applyMonotone = function(ctx, iarg0) {
   1518        /** @type {tcuInterval.Interval} */ var ret = new tcuInterval.Interval();
   1519 
   1520        /**
   1521         * @param {number=} x
   1522         * @param {number=} y
   1523         * @return {tcuInterval.Interval}
   1524         */
   1525        var body = function(x, y) {
   1526            x = x || 0;
   1527            return this.applyPoint(ctx, x);
   1528        };
   1529        ret = tcuInterval.applyMonotone1(iarg0, body.bind(this));
   1530 
   1531        ret.operatorOrAssignBinary(this.innerExtrema(ctx, iarg0));
   1532 
   1533        ret.operatorAndAssignBinary(this.getCodomain().operatorOrBinary(new tcuInterval.Interval(NaN)));
   1534 
   1535        return ctx.format.convert(ret);
   1536    };
   1537 
   1538    /**
   1539     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
   1540     * @param {tcuInterval.Interval} iargs
   1541     * @return {tcuInterval.Interval}
   1542     */
   1543    glsBuiltinPrecisionTests.FloatFunc1.prototype.innerExtrema = function(ctx, iargs) {
   1544        return new tcuInterval.Interval(); // empty interval, i.e. no extrema
   1545    };
   1546 
   1547    /**
   1548     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
   1549     * @param {number} arg0
   1550     * @return {tcuInterval.Interval}
   1551     */
   1552    glsBuiltinPrecisionTests.FloatFunc1.prototype.applyPoint = function(ctx, arg0) {
   1553        var exact = this.applyExact(arg0);
   1554        var prec = this.precision(ctx, exact, arg0);
   1555 
   1556        var a = new tcuInterval.Interval(exact);
   1557        var b = tcuInterval.withNumbers(-prec, prec);
   1558        return tcuInterval.Interval.operatorSum(a, b);
   1559    };
   1560 
   1561    /**
   1562     * @param {number} x
   1563     * @return {number}
   1564     */
   1565    glsBuiltinPrecisionTests.FloatFunc1.prototype.applyExact = function(x) {
   1566        throw new Error('Internal error. Cannot apply');
   1567    };
   1568 
   1569    /**
   1570     * @return {tcuInterval.Interval}
   1571     */
   1572    glsBuiltinPrecisionTests.FloatFunc1.prototype.getCodomain = function() {
   1573        return tcuInterval.unbounded(true);
   1574    };
   1575 
   1576    /**
   1577     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
   1578     * @param {number} x
   1579     * @param {number} y
   1580     * @return {number}
   1581     */
   1582    glsBuiltinPrecisionTests.FloatFunc1.prototype.precision = function(ctx, x, y) {
   1583        return 0;
   1584    };
   1585 
   1586    /**
   1587     * @constructor
   1588     * @extends {glsBuiltinPrecisionTests.FloatFunc1}
   1589     */
   1590    glsBuiltinPrecisionTests.Negate = function() {
   1591        glsBuiltinPrecisionTests.FloatFunc1.call(this);
   1592    };
   1593 
   1594    setParentClass(glsBuiltinPrecisionTests.Negate, glsBuiltinPrecisionTests.FloatFunc1);
   1595 
   1596    glsBuiltinPrecisionTests.Negate.prototype.getName = function() {
   1597        return '_negate';
   1598    };
   1599 
   1600    glsBuiltinPrecisionTests.Negate.prototype.doPrint = function(args) {
   1601        return '-' + args[0];
   1602    };
   1603 
   1604    glsBuiltinPrecisionTests.Negate.prototype.precision = function(ctx, ret, x) {
   1605        return 0;
   1606    };
   1607    glsBuiltinPrecisionTests.Negate.prototype.applyExact = function(x) {
   1608        return -x;
   1609    };
   1610 
   1611    /**
   1612     * @constructor
   1613     * @extends {glsBuiltinPrecisionTests.FloatFunc1}
   1614     */
   1615    glsBuiltinPrecisionTests.InverseSqrt = function() {
   1616        glsBuiltinPrecisionTests.FloatFunc1.call(this);
   1617    };
   1618 
   1619    setParentClass(glsBuiltinPrecisionTests.InverseSqrt, glsBuiltinPrecisionTests.FloatFunc1);
   1620 
   1621    glsBuiltinPrecisionTests.InverseSqrt.prototype.getName = function() {
   1622        return 'inversesqrt';
   1623    };
   1624 
   1625    glsBuiltinPrecisionTests.InverseSqrt.prototype.precision = function(ctx, ret, x) {
   1626        if (x <= 0)
   1627            return NaN;
   1628        return ctx.format.ulp(ret, 2.0);
   1629    };
   1630 
   1631    glsBuiltinPrecisionTests.InverseSqrt.prototype.applyExact = function(x) {
   1632        return 1 / Math.sqrt(x);
   1633    };
   1634 
   1635    glsBuiltinPrecisionTests.InverseSqrt.prototype.getCodomain = function() {
   1636        return tcuInterval.withNumbers(0, Infinity);
   1637    };
   1638 
   1639    /**
   1640     * @constructor
   1641     * @extends {glsBuiltinPrecisionTests.FloatFunc1}
   1642     */
   1643    glsBuiltinPrecisionTests.Round = function() {
   1644        glsBuiltinPrecisionTests.FloatFunc1.call(this);
   1645    };
   1646 
   1647    setParentClass(glsBuiltinPrecisionTests.Round, glsBuiltinPrecisionTests.FloatFunc1);
   1648 
   1649    glsBuiltinPrecisionTests.Round.prototype.getName = function() {
   1650        return 'round';
   1651    };
   1652 
   1653    glsBuiltinPrecisionTests.Round.prototype.precision = function(ctx, ret, x) {
   1654        return 0;
   1655    };
   1656 
   1657    glsBuiltinPrecisionTests.Round.prototype.applyPoint = function(ctx, x) {
   1658        var truncated = Math.trunc(x);
   1659        var fract = x - truncated;
   1660        var ret = new tcuInterval.Interval();
   1661 
   1662        // When x is inf or -inf, truncated would be inf or -inf too. Then fract
   1663        // would be NaN (inf - inf). While in native c code, it would be 0 (inf) or -0 (-inf).
   1664        // This behavior in JS differs from that in native c code.
   1665        if (Math.abs(fract) <= 0.5 || isNaN(fract))
   1666            ret.operatorOrAssignBinary(new tcuInterval.Interval(truncated));
   1667        if (Math.abs(fract) >= 0.5)
   1668            ret.operatorOrAssignBinary(new tcuInterval.Interval(truncated + deMath.deSign(fract)));
   1669 
   1670        return ret;
   1671    };
   1672 
   1673    /**
   1674     * @constructor
   1675     * @extends {glsBuiltinPrecisionTests.FloatFunc1}
   1676     * @param {string} name
   1677     * @param {tcuInterval.DoubleFunc1} func
   1678     */
   1679    glsBuiltinPrecisionTests.CFloatFunc1 = function(name, func) {
   1680        glsBuiltinPrecisionTests.FloatFunc1.call(this);
   1681        /** @type {string} */ this.m_name = name;
   1682        /** @type {tcuInterval.DoubleFunc1} */this.m_func = func;
   1683    };
   1684 
   1685    glsBuiltinPrecisionTests.CFloatFunc1.prototype = Object.create(glsBuiltinPrecisionTests.FloatFunc1.prototype);
   1686    glsBuiltinPrecisionTests.CFloatFunc1.prototype.constructor = glsBuiltinPrecisionTests.CFloatFunc1;
   1687 
   1688    /**
   1689     * @return {string}
   1690     */
   1691    glsBuiltinPrecisionTests.CFloatFunc1.prototype.getName = function() {
   1692        return this.m_name;
   1693    };
   1694 
   1695    /**
   1696     * @param {number} x
   1697     * @return {number}
   1698     */
   1699    glsBuiltinPrecisionTests.CFloatFunc1.prototype.applyExact = function(x) {
   1700        return this.m_func(x);
   1701    };
   1702 
   1703    /**
   1704     * PrimitiveFunc<Signature<float, float, float> >
   1705     * @constructor
   1706     * @extends {glsBuiltinPrecisionTests.PrimitiveFunc}
   1707     */
   1708    glsBuiltinPrecisionTests.FloatFunc2 = function() {
   1709        /** @type {glsBuiltinPrecisionTests.Signature} */ var Sig = new glsBuiltinPrecisionTests.Signature('float', 'float', 'float');
   1710        glsBuiltinPrecisionTests.PrimitiveFunc.call(this, Sig);
   1711    };
   1712 
   1713    glsBuiltinPrecisionTests.FloatFunc2.prototype = Object.create(glsBuiltinPrecisionTests.PrimitiveFunc.prototype);
   1714    glsBuiltinPrecisionTests.FloatFunc2.prototype.constructor = glsBuiltinPrecisionTests.FloatFunc2;
   1715 
   1716    /**
   1717     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
   1718     * @param {glsBuiltinPrecisionTests.Tuple4} iargs
   1719     * @return {tcuInterval.Interval}
   1720     */
   1721    glsBuiltinPrecisionTests.FloatFunc2.prototype.doApply = function(ctx, iargs) {
   1722        var a = /** @type {tcuInterval.Interval} */ (iargs.a);
   1723        var b = /** @type {tcuInterval.Interval} */ (iargs.b);
   1724        return this.applyMonotone(ctx, a, b);
   1725    };
   1726 
   1727    /**
   1728     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
   1729     * @param {tcuInterval.Interval} xi
   1730     * @param {tcuInterval.Interval} yi
   1731     * @return {tcuInterval.Interval}
   1732     */
   1733    glsBuiltinPrecisionTests.FloatFunc2.prototype.applyMonotone = function(ctx, xi, yi) {
   1734        /** @type {tcuInterval.Interval} */ var ret = new tcuInterval.Interval();
   1735 
   1736        /**
   1737         * @param {number=} x
   1738         * @param {number=} y
   1739         * @return {tcuInterval.Interval}
   1740         */
   1741        var body = function(x, y) {
   1742            x = x || 0;
   1743            y = y || 0;
   1744            return this.applyPoint(ctx, x, y);
   1745        };
   1746        ret = tcuInterval.applyMonotone2(xi, yi, body.bind(this));
   1747 
   1748        ret.operatorOrAssignBinary(this.innerExtrema(ctx, xi, yi));
   1749 
   1750        ret.operatorAndAssignBinary(this.getCodomain().operatorOrBinary(new tcuInterval.Interval(NaN)));
   1751 
   1752        return ctx.format.convert(ret);
   1753    };
   1754 
   1755    /**
   1756     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
   1757     * @param {tcuInterval.Interval} xi
   1758     * @param {tcuInterval.Interval} yi
   1759     * @return {tcuInterval.Interval}
   1760     */
   1761    glsBuiltinPrecisionTests.FloatFunc2.prototype.innerExtrema = function(ctx, xi, yi) {
   1762        return new tcuInterval.Interval(); // empty interval, i.e. no extrema
   1763    };
   1764 
   1765    /**
   1766     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
   1767     * @param {number} x
   1768     * @param {number} y
   1769     * @return {tcuInterval.Interval}
   1770     */
   1771    glsBuiltinPrecisionTests.FloatFunc2.prototype.applyPoint = function(ctx, x, y) {
   1772        /** @type {number} */ var exact = this.applyExact(x, y);
   1773        var prec = this.precision(ctx, exact, x, y);
   1774 
   1775        var a = new tcuInterval.Interval(exact);
   1776        var b = tcuInterval.withNumbers(-prec, prec);
   1777        return tcuInterval.Interval.operatorSum(a, b);
   1778    };
   1779 
   1780    /**
   1781     * @param {number} x
   1782     * @param {number} y
   1783     * @return {number}
   1784     */
   1785    glsBuiltinPrecisionTests.FloatFunc2.prototype.applyExact = function(x, y) {
   1786        throw new Error('Virtual function. Please override');
   1787    };
   1788 
   1789    /**
   1790     * @return {tcuInterval.Interval}
   1791     */
   1792    glsBuiltinPrecisionTests.FloatFunc2.prototype.getCodomain = function() {
   1793        return tcuInterval.unbounded(true);
   1794    };
   1795 
   1796    /**
   1797     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
   1798     * @param {number} ret
   1799     * @param {number} x
   1800     * @param {number} y
   1801     * @return {number}
   1802     */
   1803    glsBuiltinPrecisionTests.FloatFunc2.prototype.precision = function(ctx, ret, x, y) {
   1804        throw new Error('Virtual function. Please override');
   1805    };
   1806 
   1807    /**
   1808     * @constructor
   1809     * @extends {glsBuiltinPrecisionTests.FloatFunc2}
   1810     * @param {string} name
   1811     * @param {tcuInterval.DoubleFunc2} func
   1812     */
   1813    glsBuiltinPrecisionTests.CFloatFunc2 = function(name, func) {
   1814        glsBuiltinPrecisionTests.FloatFunc2.call(this);
   1815        /** @type {string} */ this.m_name = name;
   1816        /** @type {tcuInterval.DoubleFunc2} */ this.m_func = func;
   1817    };
   1818 
   1819    glsBuiltinPrecisionTests.CFloatFunc2.prototype = Object.create(glsBuiltinPrecisionTests.FloatFunc2.prototype);
   1820    glsBuiltinPrecisionTests.CFloatFunc2.prototype.constructor = glsBuiltinPrecisionTests.CFloatFunc2;
   1821 
   1822    /**
   1823     * @return {string}
   1824     */
   1825    glsBuiltinPrecisionTests.CFloatFunc2.prototype.getName = function() {
   1826        return this.m_name;
   1827    };
   1828 
   1829    /**
   1830     * @param {number} x
   1831     * @param {number} y
   1832     * @return {number}
   1833     */
   1834    glsBuiltinPrecisionTests.CFloatFunc2.prototype.applyExact = function(x, y) {
   1835        return this.m_func(x, y);
   1836    };
   1837 
   1838    /**
   1839     * @constructor
   1840     * @extends {glsBuiltinPrecisionTests.FloatFunc2}
   1841     */
   1842    glsBuiltinPrecisionTests.InfixOperator = function() {
   1843        glsBuiltinPrecisionTests.FloatFunc2.call(this);
   1844    };
   1845 
   1846    glsBuiltinPrecisionTests.InfixOperator.prototype = Object.create(glsBuiltinPrecisionTests.FloatFunc2.prototype);
   1847    glsBuiltinPrecisionTests.InfixOperator.prototype.constructor = glsBuiltinPrecisionTests.InfixOperator;
   1848 
   1849    /**
   1850     * @return {string}
   1851     */
   1852    glsBuiltinPrecisionTests.InfixOperator.prototype.getSymbol = function() {
   1853        glsBuiltinPrecisionTests.FloatFunc2.call(this);
   1854        return '';
   1855    };
   1856 
   1857    /**
   1858     * @param {Array<glsBuiltinPrecisionTests.ExprBase>} args
   1859     * @return {string}
   1860     */
   1861    glsBuiltinPrecisionTests.InfixOperator.prototype.doPrint = function(args) {
   1862        return '(' + args[0] + ' ' + this.getSymbol() + ' ' + args[1] + ')';
   1863    };
   1864 
   1865    /**
   1866     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
   1867     * @param {number} x
   1868     * @param {number} y
   1869     * @return {tcuInterval.Interval}
   1870     */
   1871    glsBuiltinPrecisionTests.InfixOperator.prototype.applyPoint = function(ctx, x, y) {
   1872        /** @type {number} */ var exact = this.applyExact(x, y);
   1873 
   1874        // Allow either representable number on both sides of the exact value,
   1875        // but require exactly representable values to be preserved.
   1876        return ctx.format.roundOut(new tcuInterval.Interval(exact), isFinite(x) && isFinite(y));
   1877    };
   1878 
   1879    /**
   1880     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
   1881     * @param {number} x
   1882     * @param {number} y
   1883     * @param {number} z
   1884     * @return {number}
   1885     */
   1886    glsBuiltinPrecisionTests.InfixOperator.prototype.precision = function(ctx, x, y, z) {
   1887        return 0;
   1888    };
   1889 
   1890    /**
   1891     * Signature<float, float, float, float>
   1892     * @constructor
   1893     * @extends {glsBuiltinPrecisionTests.PrimitiveFunc}
   1894     */
   1895    glsBuiltinPrecisionTests.FloatFunc3 = function() {
   1896        /** @type {glsBuiltinPrecisionTests.Signature} */ var sig = new glsBuiltinPrecisionTests.Signature('float', 'float', 'float', 'float');
   1897        glsBuiltinPrecisionTests.PrimitiveFunc.call(this, sig);
   1898    };
   1899 
   1900    glsBuiltinPrecisionTests.FloatFunc3.prototype = Object.create(glsBuiltinPrecisionTests.PrimitiveFunc.prototype);
   1901    glsBuiltinPrecisionTests.FloatFunc3.prototype.constructor = glsBuiltinPrecisionTests.FloatFunc3;
   1902 
   1903    /**
   1904     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
   1905     * @param {glsBuiltinPrecisionTests.Tuple4} iargs
   1906     * @return {tcuInterval.Interval}
   1907     */
   1908    glsBuiltinPrecisionTests.FloatFunc3.prototype.doApply = function(ctx, iargs) {
   1909        var a = /** @type {tcuInterval.Interval} */ (iargs.a);
   1910        var b = /** @type {tcuInterval.Interval} */ (iargs.b);
   1911        var c = /** @type {tcuInterval.Interval} */ (iargs.c);
   1912        var retVal = this.applyMonotone(ctx, a, b, c);
   1913        return retVal;
   1914    };
   1915 
   1916    /**
   1917     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
   1918     * @param {tcuInterval.Interval} xi
   1919     * @param {tcuInterval.Interval} yi
   1920     * @param {tcuInterval.Interval} zi
   1921     * @return {tcuInterval.Interval}
   1922     */
   1923    glsBuiltinPrecisionTests.FloatFunc3.prototype.applyMonotone = function(ctx, xi, yi, zi) {
   1924        /**
   1925         * @param {number=} x
   1926         * @param {number=} y
   1927         * @param {number=} z
   1928         * @return {tcuInterval.Interval}
   1929         */
   1930        var body = function(x, y, z) {
   1931            x = x || 0;
   1932            y = y || 0;
   1933            z = z || 0;
   1934            return this.applyPoint(ctx, x, y, z);
   1935        };
   1936        var ret = tcuInterval.applyMonotone3(xi, yi, zi, body.bind(this));
   1937        var retVal;
   1938 
   1939        ret.operatorOrAssignBinary(this.innerExtrema(ctx, xi, yi, zi));
   1940 
   1941        ret.operatorAndAssignBinary(this.getCodomain().operatorOrBinary(new tcuInterval.Interval(NaN)));
   1942 
   1943        retVal = ctx.format.convert(ret);
   1944        return retVal;
   1945    };
   1946 
   1947    /**
   1948     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
   1949     * @param {tcuInterval.Interval} xi
   1950     * @param {tcuInterval.Interval} yi
   1951     * @param {tcuInterval.Interval} zi
   1952     * @return {tcuInterval.Interval}
   1953     */
   1954    glsBuiltinPrecisionTests.FloatFunc3.prototype.innerExtrema = function(ctx, xi, yi, zi) {
   1955        return new tcuInterval.Interval(); // empty interval, i.e. no extrema
   1956    };
   1957 
   1958    /**
   1959     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
   1960     * @param {number} x
   1961     * @param {number} y
   1962     * @param {number} z
   1963     * @return {tcuInterval.Interval}
   1964     */
   1965    glsBuiltinPrecisionTests.FloatFunc3.prototype.applyPoint = function(ctx, x, y, z) {
   1966        /** @type {number} */ var exact = this.applyExact(x, y, z);
   1967        /** @type {number} */ var prec = this.precision(ctx, exact, x, y, z);
   1968 
   1969        var a = new tcuInterval.Interval(exact);
   1970        var b = tcuInterval.withNumbers(-prec, prec);
   1971        return tcuInterval.Interval.operatorSum(a, b);
   1972    };
   1973 
   1974    /**
   1975     * @param {number} x
   1976     * @param {number} y
   1977     * @param {number} z
   1978     * @return {number}
   1979     */
   1980    glsBuiltinPrecisionTests.FloatFunc3.prototype.applyExact = function(x, y, z) {
   1981        throw new Error('Virtual function. Please override');
   1982    };
   1983 
   1984    /**
   1985     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
   1986     * @param {number} result
   1987     * @param {number} x
   1988     * @param {number} y
   1989     * @param {number} z
   1990     * @return {number}
   1991     */
   1992    glsBuiltinPrecisionTests.FloatFunc3.prototype.precision = function(ctx, result, x, y, z) {
   1993        throw new Error('Virtual function. Please override');
   1994    };
   1995 
   1996    /**
   1997     * @return {tcuInterval.Interval}
   1998     */
   1999    glsBuiltinPrecisionTests.FloatFunc3.prototype.getCodomain = function() {
   2000        return tcuInterval.unbounded(true);
   2001    };
   2002 
   2003    /**
   2004     * @constructor
   2005     * @extends {glsBuiltinPrecisionTests.FloatFunc3}
   2006     */
   2007    glsBuiltinPrecisionTests.Clamp = function() {
   2008        glsBuiltinPrecisionTests.FloatFunc3.call(this);
   2009    };
   2010 
   2011    setParentClass(glsBuiltinPrecisionTests.Clamp, glsBuiltinPrecisionTests.FloatFunc3);
   2012 
   2013    glsBuiltinPrecisionTests.Clamp.prototype.getName = function() {
   2014        return 'clamp';
   2015    };
   2016 
   2017    glsBuiltinPrecisionTests.Clamp.prototype.applyExact = function(x, minVal, maxVal) {
   2018        var debug = false;
   2019        var retVal;
   2020 
   2021        retVal = deMath.clamp(x, minVal, maxVal);
   2022        if (debug) {
   2023            console.log('> minVal: ' + minVal);
   2024            console.log('> maxVal: ' + maxVal);
   2025            console.log('> x: ' + x);
   2026            console.log('> ret: ' + retVal);
   2027        }
   2028        return retVal;
   2029 
   2030    };
   2031 
   2032    glsBuiltinPrecisionTests.Clamp.prototype.precision = function(ctx, result, x, minVal, maxVal) {
   2033        var debug = false;
   2034        var retVal;
   2035 
   2036        retVal = minVal > maxVal ? NaN : 0;
   2037 
   2038        if (debug) {
   2039            console.log('precision> minVal: ' + minVal);
   2040            console.log('precision> maxVal: ' + maxVal);
   2041            console.log('precision> x: ' + x);
   2042            console.log('precision> ret: ' + retVal);
   2043        }
   2044 
   2045        return retVal;
   2046    };
   2047 
   2048    /**
   2049     * @constructor
   2050     * @extends {glsBuiltinPrecisionTests.InfixOperator}
   2051     */
   2052    glsBuiltinPrecisionTests.Add = function() {
   2053        glsBuiltinPrecisionTests.InfixOperator.call(this);
   2054    };
   2055 
   2056    glsBuiltinPrecisionTests.Add.prototype = Object.create(glsBuiltinPrecisionTests.InfixOperator.prototype);
   2057    glsBuiltinPrecisionTests.Add.prototype.constructor = glsBuiltinPrecisionTests.Add;
   2058 
   2059    /**
   2060     * @return {string}
   2061     */
   2062    glsBuiltinPrecisionTests.Add.prototype.getName = function() {
   2063        return 'add';
   2064    };
   2065 
   2066    /**
   2067     * @return {string}
   2068     */
   2069    glsBuiltinPrecisionTests.Add.prototype.getSymbol = function() {
   2070        return '+';
   2071    };
   2072 
   2073    /**
   2074     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
   2075     * @param {glsBuiltinPrecisionTests.Tuple4} iargs
   2076     * @return {tcuInterval.Interval}
   2077     */
   2078    glsBuiltinPrecisionTests.Add.prototype.doApply = function(ctx, iargs) {
   2079        var a = /** @type {tcuInterval.Interval} */ (iargs.a);
   2080        var b = /** @type {tcuInterval.Interval} */ (iargs.b);
   2081        // Fast-path for common case
   2082        if (iargs.a.isOrdinary() && iargs.b.isOrdinary()) {
   2083            /** type{tcuInterval.Interval} */ var ret;
   2084            ret = tcuInterval.setIntervalBounds(
   2085                function(dummy) {
   2086                    return iargs.a.lo() + iargs.b.lo();
   2087                },
   2088                function(dummy) {
   2089                    return iargs.a.hi() + iargs.b.hi();
   2090                });
   2091            return ctx.format.convert(ctx.format.roundOut(ret, true));
   2092        }
   2093        return this.applyMonotone(ctx, a, b);
   2094    };
   2095 
   2096    /**
   2097     * @param {number} x
   2098     * @param {number} y
   2099     * @return {number}
   2100     */
   2101    glsBuiltinPrecisionTests.Add.prototype.applyExact = function(x, y) {
   2102        return x + y;
   2103    };
   2104 
   2105    /**
   2106     * @constructor
   2107     * @extends {glsBuiltinPrecisionTests.InfixOperator}
   2108     */
   2109    glsBuiltinPrecisionTests.Sub = function() {
   2110        glsBuiltinPrecisionTests.InfixOperator.call(this);
   2111    };
   2112 
   2113    glsBuiltinPrecisionTests.Sub.prototype = Object.create(glsBuiltinPrecisionTests.InfixOperator.prototype);
   2114    glsBuiltinPrecisionTests.Sub.prototype.constructor = glsBuiltinPrecisionTests.Sub;
   2115 
   2116    /**
   2117     * @return {string}
   2118     */
   2119    glsBuiltinPrecisionTests.Sub.prototype.getName = function() {
   2120        return 'sub';
   2121    };
   2122 
   2123    /**
   2124     * @return {string}
   2125     */
   2126    glsBuiltinPrecisionTests.Sub.prototype.getSymbol = function() {
   2127        return '-';
   2128    };
   2129 
   2130    /**
   2131     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
   2132     * @param {glsBuiltinPrecisionTests.Tuple4} iargs
   2133     * @return {tcuInterval.Interval}
   2134     */
   2135    glsBuiltinPrecisionTests.Sub.prototype.doApply = function(ctx, iargs) {
   2136        var a = /** @type {tcuInterval.Interval} */ (iargs.a);
   2137        var b = /** @type {tcuInterval.Interval} */ (iargs.b);
   2138        var retVal;
   2139 
   2140        // Fast-path for common case
   2141        if (iargs.a.isOrdinary() && iargs.b.isOrdinary()) {
   2142            /** type{tcuInterval.Interval} */ var ret;
   2143            ret = tcuInterval.setIntervalBounds(
   2144                function(dummy) {
   2145                    return iargs.a.lo() - iargs.b.hi();
   2146                },
   2147                function(dummy) {
   2148                    return iargs.a.hi() - iargs.b.lo();
   2149                });
   2150            return ctx.format.convert(ctx.format.roundOut(ret, true));
   2151        }
   2152        retVal = this.applyMonotone(ctx, a, b);
   2153        return retVal;
   2154    };
   2155 
   2156    /**
   2157     * @param {number} x
   2158     * @param {number} y
   2159     * @return {number}
   2160     */
   2161    glsBuiltinPrecisionTests.Sub.prototype.applyExact = function(x, y) {
   2162        return x - y;
   2163    };
   2164 
   2165    /**
   2166     * @constructor
   2167     * @extends {glsBuiltinPrecisionTests.InfixOperator}
   2168     */
   2169    glsBuiltinPrecisionTests.Mul = function() {
   2170        glsBuiltinPrecisionTests.InfixOperator.call(this);
   2171    };
   2172 
   2173    glsBuiltinPrecisionTests.Mul.prototype = Object.create(glsBuiltinPrecisionTests.InfixOperator.prototype);
   2174    glsBuiltinPrecisionTests.Mul.prototype.constructor = glsBuiltinPrecisionTests.Mul;
   2175 
   2176    /**
   2177     * @return {string}
   2178     */
   2179    glsBuiltinPrecisionTests.Mul.prototype.getName = function() {
   2180        return 'mul';
   2181    };
   2182 
   2183    /**
   2184     * @return {string}
   2185     */
   2186    glsBuiltinPrecisionTests.Mul.prototype.getSymbol = function() {
   2187        return '*';
   2188    };
   2189 
   2190    glsBuiltinPrecisionTests.isNegative = function(n) {
   2191        return ((n = +n) || 1 / n) < 0;
   2192    };
   2193 
   2194   /**
   2195     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
   2196     * @param {glsBuiltinPrecisionTests.Tuple4} iargs
   2197     * @return {tcuInterval.Interval}
   2198     */
   2199    glsBuiltinPrecisionTests.Mul.prototype.doApply = function(ctx, iargs) {
   2200        var a = /** @type {tcuInterval.Interval} */ (iargs.a);
   2201        var b = /** @type {tcuInterval.Interval} */ (iargs.b);
   2202        // Fast-path for common case
   2203        if (iargs.a.isOrdinary() && iargs.b.isOrdinary()) {
   2204            /** type{tcuInterval.Interval} */ var ret = new tcuInterval.Interval();
   2205            if (glsBuiltinPrecisionTests.isNegative(a.hi())) {
   2206                a = a.operatorNegative();
   2207                b = b.operatorNegative();
   2208            }
   2209            if (a.lo() >= 0 && b.lo() >= 0) {
   2210                ret = tcuInterval.setIntervalBounds(
   2211                    function(dummy) {
   2212                        return iargs.a.lo() * iargs.b.lo();
   2213                    },
   2214                    function(dummy) {
   2215                        return iargs.a.hi() * iargs.b.hi();
   2216                    });
   2217                return ctx.format.convert(ctx.format.roundOut(ret, true));
   2218            }
   2219            if (a.lo() >= 0 && b.hi() <= 0) {
   2220                ret = tcuInterval.setIntervalBounds(
   2221                    function(dummy) {
   2222                        return iargs.a.hi() * iargs.b.lo();
   2223                    },
   2224                    function(dummy) {
   2225                        return iargs.a.lo() * iargs.b.hi();
   2226                    });
   2227                return ctx.format.convert(ctx.format.roundOut(ret, true));
   2228            }
   2229        }
   2230 
   2231        return this.applyMonotone(ctx, a, b);
   2232    };
   2233 
   2234    /**
   2235     * @param {number} x
   2236     * @param {number} y
   2237     * @return {number}
   2238     */
   2239    glsBuiltinPrecisionTests.Mul.prototype.applyExact = function(x, y) {
   2240        return x * y;
   2241    };
   2242 
   2243    /**
   2244     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
   2245     * @param {tcuInterval.Interval} xi
   2246     * @param {tcuInterval.Interval} yi
   2247     * @return {tcuInterval.Interval}
   2248     */
   2249    glsBuiltinPrecisionTests.Mul.prototype.innerExtrema = function(ctx, xi, yi) {
   2250        if (((xi.contains(tcuInterval.NEGATIVE_INFINITY) || xi.contains(tcuInterval.POSITIVE_INFINITY)) && yi.contains(tcuInterval.ZERO)) ||
   2251            ((yi.contains(tcuInterval.NEGATIVE_INFINITY) || yi.contains(tcuInterval.POSITIVE_INFINITY)) && xi.contains(tcuInterval.ZERO)))
   2252            return new tcuInterval.Interval(NaN);
   2253 
   2254        return new tcuInterval.Interval(); // empty interval, i.e. no extrema
   2255    };
   2256 
   2257    /**
   2258     * @constructor
   2259     * @extends {glsBuiltinPrecisionTests.InfixOperator}
   2260     */
   2261    glsBuiltinPrecisionTests.Div = function() {
   2262        glsBuiltinPrecisionTests.InfixOperator.call(this);
   2263    };
   2264 
   2265    glsBuiltinPrecisionTests.Div.prototype = Object.create(glsBuiltinPrecisionTests.InfixOperator.prototype);
   2266    glsBuiltinPrecisionTests.Div.prototype.constructor = glsBuiltinPrecisionTests.Div;
   2267 
   2268    /**
   2269     * @return {string}
   2270     */
   2271    glsBuiltinPrecisionTests.Div.prototype.getName = function() {
   2272        return 'div';
   2273    };
   2274 
   2275    /**
   2276     * @return {string}
   2277     */
   2278    glsBuiltinPrecisionTests.Div.prototype.getSymbol = function() {
   2279        return '/';
   2280    };
   2281 
   2282    /**
   2283     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
   2284     * @param {tcuInterval.Interval} nom
   2285     * @param {tcuInterval.Interval} den
   2286     * @return {tcuInterval.Interval}
   2287     */
   2288    glsBuiltinPrecisionTests.Div.prototype.innerExtrema = function(ctx, nom, den) {
   2289        var ret = new tcuInterval.Interval();
   2290        if (den.contains(tcuInterval.ZERO)) {
   2291            if (nom.contains(tcuInterval.ZERO))
   2292                ret.operatorOrAssignBinary(tcuInterval.NAN);
   2293            if (nom.lo() < 0 || nom.hi() > 0.0)
   2294                ret.operatorOrAssignBinary(tcuInterval.unbounded());
   2295        }
   2296 
   2297        return ret;
   2298    };
   2299 
   2300    glsBuiltinPrecisionTests.Div.prototype.precision = function(ctx, ret, nom, den) {
   2301        var fmt = ctx.format;
   2302 
   2303        // \todo [2014-03-05 lauri] Check that the limits in GLSL 3.10 are actually correct.
   2304        // For now, we assume that division's precision is 2.5 ULP when the value is within
   2305        // [2^MINEXP, 2^MAXEXP-1]
   2306 
   2307        if (den === 0)
   2308            return 0; // Result must be exactly inf
   2309        else if (deMath.deInBounds32(Math.abs(den),
   2310                              deMath.deLdExp(1, fmt.getMinExp()),
   2311                              deMath.deLdExp(1, fmt.getMaxExp() - 1)))
   2312            return fmt.ulp(ret, 2.5);
   2313        else
   2314            return Infinity; // Can be any number, but must be a number.
   2315    };
   2316 
   2317    /**
   2318     * @param {number} x
   2319     * @param {number} y
   2320     * @return {number}
   2321     */
   2322    glsBuiltinPrecisionTests.Div.prototype.applyExact = function(x, y) {
   2323        return x / y;
   2324    };
   2325 
   2326    glsBuiltinPrecisionTests.Div.prototype.applyPoint = function(ctx, x, y) {
   2327        var ret = glsBuiltinPrecisionTests.FloatFunc2.prototype.applyPoint.call(this, ctx, x, y);
   2328        if (isFinite(x) && isFinite(y) && y != 0) {
   2329            var dst = ctx.format.convert(ret);
   2330            if (dst.contains(tcuInterval.NEGATIVE_INFINITY)) {
   2331                ret.operatorOrAssignBinary(-ctx.format.getMaxValue());
   2332            }
   2333            if (dst.contains(tcuInterval.POSITIVE_INFINITY)) {
   2334                ret.operatorOrAssignBinary(+ctx.format.getMaxValue());
   2335            }
   2336        }
   2337        return ret;
   2338    };
   2339 
   2340    /**
   2341     * @constructor
   2342     * @extends {glsBuiltinPrecisionTests.PrimitiveFunc}
   2343     */
   2344    glsBuiltinPrecisionTests.CompWiseFunc = function(typename, Sig) {
   2345        glsBuiltinPrecisionTests.PrimitiveFunc.call(this, Sig);
   2346        this.typename = typename;
   2347    };
   2348 
   2349    setParentClass(glsBuiltinPrecisionTests.CompWiseFunc, glsBuiltinPrecisionTests.PrimitiveFunc);
   2350 
   2351    /**
   2352     * @return {string}
   2353     */
   2354    glsBuiltinPrecisionTests.CompWiseFunc.prototype.getName = function() {
   2355        return this.doGetScalarFunc().getName();
   2356    };
   2357 
   2358    /**
   2359     * @param {Array<glsBuiltinPrecisionTests.ExprBase>} args
   2360     * @return {string}
   2361     */
   2362    glsBuiltinPrecisionTests.CompWiseFunc.prototype.doPrint = function(args) {
   2363        return this.doGetScalarFunc().print(args);
   2364    };
   2365 
   2366    /**
   2367     * @return {glsBuiltinPrecisionTests.Func}
   2368     */
   2369    glsBuiltinPrecisionTests.CompWiseFunc.prototype.doGetScalarFunc = function() {
   2370        throw new Error('Virtual function. Please override.');
   2371    };
   2372 
   2373    /**
   2374     * @constructor
   2375     * @extends {glsBuiltinPrecisionTests.CompWiseFunc}
   2376     * @param {number} rows
   2377     * @param {number} cols
   2378     */
   2379    glsBuiltinPrecisionTests.CompMatFuncBase = function(rows, cols) {
   2380        var name = glsBuiltinPrecisionTests.dataTypeNameOfMatrix('float', rows, cols);
   2381        glsBuiltinPrecisionTests.CompWiseFunc.call(this, 'float', new glsBuiltinPrecisionTests.Signature(name, name, name));
   2382        this.rows = rows;
   2383        this.cols = cols;
   2384    };
   2385 
   2386    setParentClass(glsBuiltinPrecisionTests.CompMatFuncBase, glsBuiltinPrecisionTests.CompWiseFunc);
   2387 
   2388    glsBuiltinPrecisionTests.CompMatFuncBase.prototype.doApply = function(ctx, iargs) {
   2389        var ret = new tcuMatrix.Matrix(this.rows, this.cols);
   2390        var fun = this.doGetScalarFunc();
   2391 
   2392        for (var row = 0; row < this.rows; ++row)
   2393            for (var col = 0; col < this.cols; ++col)
   2394                ret.set(row, col, fun.applyFunction(ctx,
   2395                                                  iargs.a.get(row, col),
   2396                                                  iargs.b.get(row, col)));
   2397 
   2398        return ret;
   2399    };
   2400 
   2401    /**
   2402     * @constructor
   2403     * @extends {glsBuiltinPrecisionTests.CompMatFuncBase}
   2404     * @param {function(new:glsBuiltinPrecisionTests.Func)} F
   2405     * @param {number} rows
   2406     * @param {number} cols
   2407     */
   2408    glsBuiltinPrecisionTests.CompMatFunc = function(F, rows, cols) {
   2409        glsBuiltinPrecisionTests.CompMatFuncBase.call(this, rows, cols);
   2410        this.m_function = F;
   2411    };
   2412 
   2413    setParentClass(glsBuiltinPrecisionTests.CompMatFunc, glsBuiltinPrecisionTests.CompMatFuncBase);
   2414 
   2415    /**
   2416     * @return {glsBuiltinPrecisionTests.Func}
   2417     */
   2418    glsBuiltinPrecisionTests.CompMatFunc.prototype.doGetScalarFunc = function() {
   2419        return new this.m_function();
   2420    };
   2421 
   2422    /**
   2423     * @constructor
   2424     * @extends {glsBuiltinPrecisionTests.Mul}
   2425     */
   2426    glsBuiltinPrecisionTests.ScalarMatrixCompMult = function() {
   2427       glsBuiltinPrecisionTests.Mul.call(this);
   2428    };
   2429 
   2430    setParentClass(glsBuiltinPrecisionTests.ScalarMatrixCompMult, glsBuiltinPrecisionTests.Mul);
   2431 
   2432    /**
   2433     * @return {string}
   2434     */
   2435    glsBuiltinPrecisionTests.ScalarMatrixCompMult.prototype.getName = function() {
   2436        return 'matrixCompMult';
   2437    };
   2438 
   2439    /**
   2440     * @param {Array<glsBuiltinPrecisionTests.ExprBase>} args
   2441     * @return {string}
   2442     */
   2443    glsBuiltinPrecisionTests.ScalarMatrixCompMult.prototype.doPrint = function(args) {
   2444        return glsBuiltinPrecisionTests.Func.prototype.doPrint.call(this, args);
   2445    };
   2446 
   2447    /**
   2448     * @constructor
   2449     * @extends {glsBuiltinPrecisionTests.CompMatFunc}
   2450     * @param {number} rows
   2451     * @param {number} cols
   2452     */
   2453    glsBuiltinPrecisionTests.MatrixCompMult = function(rows, cols) {
   2454        glsBuiltinPrecisionTests.CompMatFunc.call(this, glsBuiltinPrecisionTests.ScalarMatrixCompMult, rows, cols);
   2455    };
   2456 
   2457    setParentClass(glsBuiltinPrecisionTests.MatrixCompMult, glsBuiltinPrecisionTests.CompMatFunc);
   2458 
   2459    /**
   2460     * @constructor
   2461     * @extends {glsBuiltinPrecisionTests.PrimitiveFunc}
   2462     * @param {number} rows
   2463     * @param {number} cols
   2464     */
   2465    glsBuiltinPrecisionTests.OuterProduct = function(rows, cols) {
   2466        var name = glsBuiltinPrecisionTests.dataTypeNameOfMatrix('float', rows, cols);
   2467        var sig = new glsBuiltinPrecisionTests.Signature(name, 'vec' + rows, 'vec' + cols);
   2468        glsBuiltinPrecisionTests.PrimitiveFunc.call(this, sig);
   2469        this.rows = rows;
   2470        this.cols = cols;
   2471    };
   2472 
   2473    setParentClass(glsBuiltinPrecisionTests.OuterProduct, glsBuiltinPrecisionTests.PrimitiveFunc);
   2474 
   2475    /**
   2476     * @return {string}
   2477     */
   2478    glsBuiltinPrecisionTests.OuterProduct.prototype.getName = function() {
   2479        return 'outerProduct';
   2480    };
   2481 
   2482    glsBuiltinPrecisionTests.OuterProduct.prototype.doApply = function(ctx, iargs) {
   2483        var ret = new tcuMatrix.Matrix(this.rows, this.cols);
   2484        var mul = new glsBuiltinPrecisionTests.Mul();
   2485 
   2486        for (var row = 0; row < this.rows; ++row) {
   2487            for (var col = 0; col < this.cols; ++col)
   2488                ret.set(row, col, mul.applyFunction(ctx, iargs.a[row], iargs.b[col]));
   2489        }
   2490 
   2491        return ret;
   2492    };
   2493 
   2494    /**
   2495     * @constructor
   2496     * @extends {glsBuiltinPrecisionTests.PrimitiveFunc}
   2497     * @param {number} rows
   2498     * @param {number} cols
   2499     */
   2500    glsBuiltinPrecisionTests.Transpose = function(rows, cols) {
   2501        var nameRet = glsBuiltinPrecisionTests.dataTypeNameOfMatrix('float', rows, cols);
   2502        var nameParam = glsBuiltinPrecisionTests.dataTypeNameOfMatrix('float', cols, rows);
   2503        var sig = new glsBuiltinPrecisionTests.Signature(nameRet, nameParam);
   2504        glsBuiltinPrecisionTests.PrimitiveFunc.call(this, sig);
   2505        this.rows = rows;
   2506        this.cols = cols;
   2507    };
   2508 
   2509    setParentClass(glsBuiltinPrecisionTests.Transpose, glsBuiltinPrecisionTests.PrimitiveFunc);
   2510 
   2511    /**
   2512     * @return {string}
   2513     */
   2514    glsBuiltinPrecisionTests.Transpose.prototype.getName = function() {
   2515        return 'transpose';
   2516    };
   2517 
   2518    glsBuiltinPrecisionTests.Transpose.prototype.doApply = function(ctx, iargs) {
   2519        var ret = new tcuMatrix.Matrix(this.rows, this.cols);
   2520 
   2521        for (var row = 0; row < this.rows; ++row)
   2522            for (var col = 0; col < this.cols; ++col)
   2523                ret.set(row, col, iargs.a.get(col, row));
   2524 
   2525        return ret;
   2526    };
   2527 
   2528    /**
   2529     * @constructor
   2530     * @param {*} In
   2531     */
   2532    glsBuiltinPrecisionTests.Inputs = function(In) {
   2533        // vector<typename In::In0> in0;
   2534        // vector<typename In::In1> in1;
   2535        // vector<typename In::In2> in2;
   2536        // vector<typename In::In3> in3;
   2537        this.in0 = [];
   2538        this.in1 = [];
   2539        this.in2 = [];
   2540        this.in3 = [];
   2541    };
   2542 
   2543    /**
   2544     * @constructor
   2545     * @param {number} size
   2546     * @param {*} Out
   2547     */
   2548    glsBuiltinPrecisionTests.Outputs = function(size, Out) {
   2549        // Outputs (size_t size) : out0(size), out1(size) {}
   2550        this.out0 = [];
   2551        this.out1 = [];
   2552    };
   2553 
   2554    /**
   2555     * @constructor
   2556     * @param {*} In
   2557     * @param {*} Out
   2558     */
   2559     glsBuiltinPrecisionTests.Variables = function(In, Out) {
   2560        this.in0 = new glsBuiltinPrecisionTests.Variable(In.In0);
   2561        this.in1 = new glsBuiltinPrecisionTests.Variable(In.In1);
   2562        this.in2 = new glsBuiltinPrecisionTests.Variable(In.In2);
   2563        this.in3 = new glsBuiltinPrecisionTests.Variable(In.In3);
   2564        this.out0 = new glsBuiltinPrecisionTests.Variable(Out.Out0);
   2565        this.out1 = new glsBuiltinPrecisionTests.Variable(Out.Out1);
   2566    };
   2567 
   2568    /**
   2569     * @constructor
   2570     * @param {function(new:glsBuiltinPrecisionTests.Func)} F
   2571     * @return {glsBuiltinPrecisionTests.GenFuncs}
   2572     */
   2573    glsBuiltinPrecisionTests.makeVectorizedFuncs = function(F) {
   2574        return new glsBuiltinPrecisionTests.GenFuncs(
   2575                new F(),
   2576                new glsBuiltinPrecisionTests.VectorizedFunc(new F(), 2),
   2577                new glsBuiltinPrecisionTests.VectorizedFunc(new F(), 3),
   2578                new glsBuiltinPrecisionTests.VectorizedFunc(new F(), 4));
   2579    };
   2580 
   2581    /**
   2582     * @constructor
   2583     * @param {glsBuiltinPrecisionTests.Typename} typename
   2584     */
   2585    glsBuiltinPrecisionTests.Sampling = function(typename) {
   2586        this.typename = typename;
   2587    };
   2588 
   2589    /**
   2590     * @param {glsBuiltinPrecisionTests.Typename} typename
   2591     * @param {number=} size
   2592     * @return {glsBuiltinPrecisionTests.Sampling}
   2593     */
   2594    glsBuiltinPrecisionTests.SamplingFactory = function(typename, size) {
   2595        if (size > 1)
   2596            return new glsBuiltinPrecisionTests.DefaultSamplingVector(typename, size);
   2597        switch (typename) {
   2598            case 'vec4' : return new glsBuiltinPrecisionTests.DefaultSamplingVector('float', 4);
   2599            case 'vec3' : return new glsBuiltinPrecisionTests.DefaultSamplingVector('float', 3);
   2600            case 'vec2' : return new glsBuiltinPrecisionTests.DefaultSamplingVector('float', 2);
   2601            case 'boolean' : return new glsBuiltinPrecisionTests.DefaultSamplingBool(typename);
   2602            case 'float' : return new glsBuiltinPrecisionTests.DefaultSamplingFloat(typename);
   2603            case 'mat2': return new glsBuiltinPrecisionTests.DefaultSamplingMatrix('float', 2, 2);
   2604            case 'mat2x3': return new glsBuiltinPrecisionTests.DefaultSamplingMatrix('float', 3, 2);
   2605            case 'mat2x4': return new glsBuiltinPrecisionTests.DefaultSamplingMatrix('float', 4, 2);
   2606            case 'mat3x2': return new glsBuiltinPrecisionTests.DefaultSamplingMatrix('float', 2, 3);
   2607            case 'mat3': return new glsBuiltinPrecisionTests.DefaultSamplingMatrix('float', 3, 3);
   2608            case 'mat3x4': return new glsBuiltinPrecisionTests.DefaultSamplingMatrix('float', 4, 3);
   2609            case 'mat4x2': return new glsBuiltinPrecisionTests.DefaultSamplingMatrix('float', 2, 4);
   2610            case 'mat4x3': return new glsBuiltinPrecisionTests.DefaultSamplingMatrix('float', 3, 4);
   2611            case 'mat4': return new glsBuiltinPrecisionTests.DefaultSamplingMatrix('float', 4, 4);
   2612            case 'int' : return new glsBuiltinPrecisionTests.DefaultSamplingInt(typename);
   2613        }
   2614        return new glsBuiltinPrecisionTests.DefaultSamplingVoid(typename);
   2615    };
   2616 
   2617    /**
   2618     * @param {tcuFloatFormat.FloatFormat} fmt
   2619     * @param {Array<*>} arr
   2620     */
   2621    glsBuiltinPrecisionTests.Sampling.prototype.genFixeds = function(fmt, arr) {
   2622        throw new Error('Virtual function. Please override.');
   2623    };
   2624 
   2625    /**
   2626     * @param {tcuFloatFormat.FloatFormat} fmt
   2627     * @param {gluShaderUtil.precision} precision
   2628     * @param {deRandom.Random} random
   2629     * @return {*}
   2630     */
   2631    glsBuiltinPrecisionTests.Sampling.prototype.genRandom = function(fmt, precision, random) {
   2632        return 0;
   2633    };
   2634 
   2635    /**
   2636     * @return {number}
   2637     */
   2638    glsBuiltinPrecisionTests.Sampling.prototype.getWeight = function() {
   2639        return 0;
   2640    };
   2641 
   2642    /**
   2643     * @constructor
   2644     * @extends {glsBuiltinPrecisionTests.Sampling}
   2645     * @param {glsBuiltinPrecisionTests.Typename} typename
   2646     */
   2647     glsBuiltinPrecisionTests.DefaultSamplingVoid = function(typename) {
   2648         glsBuiltinPrecisionTests.Sampling.call(this, typename);
   2649     };
   2650 
   2651     glsBuiltinPrecisionTests.DefaultSamplingVoid.prototype = Object.create(glsBuiltinPrecisionTests.Sampling.prototype);
   2652     glsBuiltinPrecisionTests.DefaultSamplingVoid.prototype.constructor = glsBuiltinPrecisionTests.DefaultSamplingVoid;
   2653 
   2654    /**
   2655     * @param {tcuFloatFormat.FloatFormat} fmt
   2656     * @param {Array<number>} dst
   2657     */
   2658    glsBuiltinPrecisionTests.DefaultSamplingVoid.prototype.genFixeds = function(fmt, dst) {
   2659        dst.push(NaN);
   2660    };
   2661 
   2662    /**
   2663     * @constructor
   2664     * @extends {glsBuiltinPrecisionTests.Sampling}
   2665     * @param {glsBuiltinPrecisionTests.Typename} typename
   2666     */
   2667    glsBuiltinPrecisionTests.DefaultSamplingBool = function(typename) {
   2668        glsBuiltinPrecisionTests.Sampling.call(this, typename);
   2669    };
   2670 
   2671    glsBuiltinPrecisionTests.DefaultSamplingBool.prototype = Object.create(glsBuiltinPrecisionTests.Sampling.prototype);
   2672    glsBuiltinPrecisionTests.DefaultSamplingBool.prototype.constructor = glsBuiltinPrecisionTests.DefaultSamplingBool;
   2673 
   2674    /**
   2675     * @param {tcuFloatFormat.FloatFormat} fmt
   2676     * @param {Array<Boolean>} dst
   2677     */
   2678    glsBuiltinPrecisionTests.DefaultSamplingBool.prototype.genFixeds = function(fmt, dst) {
   2679        dst.push(true);
   2680        dst.push(false);
   2681    };
   2682 
   2683    /**
   2684     * @constructor
   2685     * @extends {glsBuiltinPrecisionTests.Sampling}
   2686     * @param {glsBuiltinPrecisionTests.Typename} typename
   2687     */
   2688    glsBuiltinPrecisionTests.DefaultSamplingInt = function(typename) {
   2689        glsBuiltinPrecisionTests.Sampling.call(this, typename);
   2690    };
   2691 
   2692    glsBuiltinPrecisionTests.DefaultSamplingInt.prototype = Object.create(glsBuiltinPrecisionTests.Sampling.prototype);
   2693    glsBuiltinPrecisionTests.DefaultSamplingInt.prototype.constructor = glsBuiltinPrecisionTests.DefaultSamplingInt;
   2694 
   2695    glsBuiltinPrecisionTests.DefaultSamplingInt.prototype.genRandom = function(fmt, prec, rnd) {
   2696        /** @type {number} */ var exp = rnd.getInt(0, this.getNumBits(prec) - 2);
   2697        /** @type {number} */ var sign = rnd.getBool() ? -1 : 1;
   2698 
   2699        return sign * rnd.getInt(0, 1 << exp);
   2700    };
   2701 
   2702    glsBuiltinPrecisionTests.DefaultSamplingInt.prototype.genFixeds = function(fmt, dst) {
   2703        dst.push(0);
   2704        dst.push(-1);
   2705        dst.push(1);
   2706    };
   2707 
   2708    glsBuiltinPrecisionTests.DefaultSamplingInt.prototype.getWeight = function() {
   2709        return 1.0;
   2710    };
   2711 
   2712    /**
   2713     * @param {gluShaderUtil.precision} prec
   2714     * @return {number}
   2715     */
   2716    glsBuiltinPrecisionTests.DefaultSamplingInt.prototype.getNumBits = function(prec) {
   2717        switch (prec) {
   2718            case gluShaderUtil.precision.PRECISION_LOWP: return 8;
   2719            case gluShaderUtil.precision.PRECISION_MEDIUMP: return 16;
   2720            case gluShaderUtil.precision.PRECISION_HIGHP: return 32;
   2721            default:
   2722                throw new Error('Invalid precision: ' + prec);
   2723        }
   2724    };
   2725 
   2726    /**
   2727     * @constructor
   2728     * @extends {glsBuiltinPrecisionTests.Sampling}
   2729     * @param {glsBuiltinPrecisionTests.Typename} typename
   2730     */
   2731    glsBuiltinPrecisionTests.DefaultSamplingFloat = function(typename) {
   2732        glsBuiltinPrecisionTests.Sampling.call(this, typename);
   2733    };
   2734 
   2735    glsBuiltinPrecisionTests.DefaultSamplingFloat.prototype = Object.create(glsBuiltinPrecisionTests.Sampling.prototype);
   2736    glsBuiltinPrecisionTests.DefaultSamplingFloat.prototype.constructor = glsBuiltinPrecisionTests.DefaultSamplingFloat;
   2737 
   2738    glsBuiltinPrecisionTests.DefaultSamplingFloat.prototype.genRandom = function(format, prec, rnd) {
   2739        /** type{number} */ var minExp = format.getMinExp();
   2740        /** type{number} */ var maxExp = format.getMaxExp();
   2741        /** type{boolean} */ var haveSubnormal = format.hasSubnormal() != tcuFloatFormat.YesNoMaybe.NO;
   2742 
   2743        // Choose exponent so that the cumulative distribution is cubic.
   2744        // This makes the probability distribution quadratic, with the peak centered on zero.
   2745        /** type{number} */ var minRoot = deMath.deCbrt(minExp - 0.5 - (haveSubnormal ? 1.0 : 0.0));
   2746        /** type{number} */ var maxRoot = deMath.deCbrt(maxExp + 0.5);
   2747        /** type{number} */ var fractionBits = format.getFractionBits();
   2748        /** type{number} */ var exp = deMath.rint(Math.pow(rnd.getFloat(minRoot, maxRoot),
   2749                                                                3.0));
   2750        /** type{number} */ var base = 0.0; // integral power of two
   2751        /** type{number} */ var quantum = 0.0; // smallest representable difference in the binade
   2752        /** type{number} */ var significand = 0.0; // Significand.
   2753 
   2754        // DE_ASSERT(fractionBits < std::numeric_limits<float>::digits);
   2755 
   2756        // Generate some occasional special numbers
   2757        switch (rnd.getInt(0, 64)) {
   2758            case 0: return 0;
   2759            case 1: return Number.POSITIVE_INFINITY;
   2760            case 2: return Number.NEGATIVE_INFINITY;
   2761            case 3: return NaN;
   2762            default: break;
   2763        }
   2764 
   2765        if (exp >= minExp) {
   2766            // Normal number
   2767            base = deMath.deFloatLdExp(1.0, exp);
   2768            quantum = deMath.deFloatLdExp(1.0, exp - fractionBits);
   2769        } else {
   2770            // Subnormal
   2771            base = 0.0;
   2772            quantum = deMath.deFloatLdExp(1.0, minExp - fractionBits);
   2773        }
   2774 
   2775        switch (rnd.getInt(0, 16)) {
   2776            // The highest number in this binade, significand is all bits one.
   2777            case 0:
   2778                significand = base - quantum;
   2779                break;
   2780            // Significand is one.
   2781            case 1:
   2782                significand = quantum;
   2783                break;
   2784            // Significand is zero.
   2785            case 2:
   2786                significand = 0.0;
   2787                break;
   2788            // Random (evenly distributed) significand.
   2789            default: {
   2790                /** type{number} */ var intFraction = rnd.getInt() & ((1 << fractionBits) - 1);
   2791                significand = intFraction * quantum;
   2792            }
   2793        }
   2794 
   2795        // Produce positive numbers more often than negative.
   2796        return (rnd.getInt(0, 3) == 0 ? -1.0 : 1.0) * (base + significand);
   2797    };
   2798 
   2799    glsBuiltinPrecisionTests.DefaultSamplingFloat.prototype.genFixeds = function(format, dst) {
   2800        /** @type {number} */ var minExp = format.getMinExp();
   2801        /** @type {number} */ var maxExp = format.getMaxExp();
   2802        /** @type {number} */ var fractionBits = format.getFractionBits();
   2803        /** @type {number} */ var minQuantum = deMath.deFloatLdExp(1.0, minExp - fractionBits);
   2804        /** @type {number} */ var minNormalized = deMath.deFloatLdExp(1.0, minExp);
   2805        /** @type {number} */ var maxQuantum = deMath.deFloatLdExp(1.0, maxExp - fractionBits);
   2806 
   2807        // If unit testing is enabled, include exact numbers
   2808        if (enableUnittests) {
   2809            dst.push(0.2);
   2810            dst.push(0.5);
   2811        }
   2812 
   2813        // NaN
   2814        dst.push(NaN);
   2815        // Zero
   2816        dst.push(0.0);
   2817 
   2818        for (var sign = -1; sign <= 1; sign += 2) {
   2819            // Smallest subnormal
   2820            dst.push(sign * minQuantum);
   2821 
   2822            // Largest subnormal
   2823            dst.push(sign * (minNormalized - minQuantum));
   2824 
   2825            // Smallest normalized
   2826            dst.push(sign * minNormalized);
   2827 
   2828            // Next smallest normalized
   2829            dst.push(sign * (minNormalized + minQuantum));
   2830 
   2831            dst.push(sign * 0.5);
   2832            dst.push(sign * 1.0);
   2833            dst.push(sign * 2.0);
   2834 
   2835            // Largest number
   2836            dst.push(sign * (deMath.deFloatLdExp(1.0, maxExp) +
   2837                                  (deMath.deFloatLdExp(1.0, maxExp) - maxQuantum)));
   2838 
   2839            dst.push(sign * Number.POSITIVE_INFINITY);
   2840        }
   2841    };
   2842 
   2843    /**
   2844     * @constructor
   2845     * @extends {glsBuiltinPrecisionTests.Sampling}
   2846     * @param {glsBuiltinPrecisionTests.Typename} typename
   2847     * @param {number} size
   2848     */
   2849    glsBuiltinPrecisionTests.DefaultSamplingVector = function(typename, size) {
   2850        glsBuiltinPrecisionTests.Sampling.call(this, typename);
   2851        this.size = size;
   2852    };
   2853 
   2854    glsBuiltinPrecisionTests.DefaultSamplingVector.prototype = Object.create(glsBuiltinPrecisionTests.Sampling.prototype);
   2855    glsBuiltinPrecisionTests.DefaultSamplingVector.prototype.constructor = glsBuiltinPrecisionTests.DefaultSamplingVector;
   2856 
   2857    glsBuiltinPrecisionTests.DefaultSamplingVector.prototype.genRandom = function(fmt, prec, rnd) {
   2858        /** @type {Array<*>} */ var ret = [];
   2859 
   2860        for (var ndx = 0; ndx < this.size; ++ndx)
   2861            ret[ndx] = glsBuiltinPrecisionTests.SamplingFactory(this.typename).genRandom(fmt, prec, rnd);
   2862 
   2863        return ret;
   2864    };
   2865 
   2866    glsBuiltinPrecisionTests.DefaultSamplingVector.prototype.genFixeds = function(fmt, dst) {
   2867        /** @type {Array<*>} */ var scalars = [];
   2868 
   2869        glsBuiltinPrecisionTests.SamplingFactory(this.typename).genFixeds(fmt, scalars);
   2870 
   2871        for (var scalarNdx = 0; scalarNdx < scalars.length; ++scalarNdx) {
   2872            var value = [];
   2873            for (var i = 0; i < this.size; i++)
   2874                value[i] = scalars[scalarNdx];
   2875            dst.push(value);
   2876        }
   2877    };
   2878 
   2879    glsBuiltinPrecisionTests.DefaultSamplingVector.prototype.getWeight = function() {
   2880        return Math.pow(glsBuiltinPrecisionTests.SamplingFactory(this.typename).getWeight(), this.size);
   2881    };
   2882 
   2883    /**
   2884     * @constructor
   2885     * @extends {glsBuiltinPrecisionTests.Sampling}
   2886     * @param {glsBuiltinPrecisionTests.Typename} typename
   2887     * @param {number} rows
   2888     * @param {number} cols
   2889     */
   2890    glsBuiltinPrecisionTests.DefaultSamplingMatrix = function(typename, rows, cols) {
   2891        glsBuiltinPrecisionTests.Sampling.call(this, typename);
   2892        this.rows = rows;
   2893        this.cols = cols;
   2894    };
   2895 
   2896    glsBuiltinPrecisionTests.DefaultSamplingMatrix.prototype = Object.create(glsBuiltinPrecisionTests.Sampling.prototype);
   2897    glsBuiltinPrecisionTests.DefaultSamplingMatrix.prototype.constructor = glsBuiltinPrecisionTests.DefaultSamplingMatrix;
   2898 
   2899    glsBuiltinPrecisionTests.DefaultSamplingMatrix.prototype.genRandom = function(fmt, prec, rnd) {
   2900        /** @type {tcuMatrix.Matrix} */ var ret = new tcuMatrix.Matrix(this.rows, this.cols);
   2901        var sampler = glsBuiltinPrecisionTests.SamplingFactory(this.typename);
   2902 
   2903        for (var rowNdx = 0; rowNdx < this.rows; ++rowNdx)
   2904            for (var colNdx = 0; colNdx < this.cols; ++colNdx)
   2905                ret.set(rowNdx, colNdx, sampler.genRandom(fmt, prec, rnd));
   2906 
   2907        return ret;
   2908    };
   2909 
   2910    glsBuiltinPrecisionTests.DefaultSamplingMatrix.prototype.genFixeds = function(fmt, dst) {
   2911        /** @type {Array<number>} */ var scalars = [];
   2912 
   2913        glsBuiltinPrecisionTests.SamplingFactory(this.typename).genFixeds(fmt, scalars);
   2914 
   2915        for (var scalarNdx = 0; scalarNdx < scalars.length; ++scalarNdx)
   2916            dst.push(new tcuMatrix.Matrix(this.rows, this.cols, scalars[scalarNdx]));
   2917 
   2918        if (this.cols == this.rows) {
   2919            var mat = new tcuMatrix.Matrix(this.rows, this.cols, 0);
   2920            var x = 1;
   2921            mat.set(0, 0, x);
   2922            for (var ndx = 0; ndx < this.cols; ++ndx) {
   2923                mat.set(this.cols - 1 - ndx, ndx, x);
   2924                x *= 2;
   2925            }
   2926            dst.push(mat);
   2927        }
   2928    };
   2929 
   2930    glsBuiltinPrecisionTests.DefaultSamplingMatrix.prototype.getWeight = function() {
   2931        return Math.pow(glsBuiltinPrecisionTests.SamplingFactory(this.typename).getWeight(), this.rows * this.cols);
   2932    };
   2933 
   2934    /**
   2935     * @constructor
   2936     * @param {number=} size
   2937     * @param {glsBuiltinPrecisionTests.InTypes} In
   2938     */
   2939     glsBuiltinPrecisionTests.Samplings = function(In, size) {
   2940        this.in0 = glsBuiltinPrecisionTests.SamplingFactory(In.In0, size);
   2941        this.in1 = glsBuiltinPrecisionTests.SamplingFactory(In.In1, size);
   2942        this.in2 = glsBuiltinPrecisionTests.SamplingFactory(In.In2, size);
   2943        this.in3 = glsBuiltinPrecisionTests.SamplingFactory(In.In3, size);
   2944    };
   2945 
   2946    /**
   2947     * @param {glsBuiltinPrecisionTests.InTypes} In
   2948     * @param {number=} size
   2949     * @constructor
   2950     * @extends {glsBuiltinPrecisionTests.Samplings}
   2951     */
   2952     glsBuiltinPrecisionTests.DefaultSamplings = function(In, size) {
   2953        glsBuiltinPrecisionTests.Samplings.call(this, In, size);
   2954    };
   2955 
   2956    /**
   2957     * @constructor
   2958     * @extends {tcuTestCase.DeqpTest}
   2959     * @param {glsBuiltinPrecisionTests.Context} context
   2960     * @param {string} name
   2961     * @param {string} extension
   2962     */
   2963    glsBuiltinPrecisionTests.PrecisionCase = function(context, name, extension) {
   2964        /** @type {string} */ this.m_extension = extension === undefined ? '' : extension;
   2965        /** @type {glsBuiltinPrecisionTests.Context} */ this.m_ctx = context;
   2966        /** @type {*} */ this.m_status;
   2967        /** @type {deRandom.Random} */ this.m_rnd = new deRandom.Random(1234); //    (0xdeadbeefu + context.testContext.getCommandLine().getBaseSeed())
   2968        tcuTestCase.DeqpTest.call(this, name, extension);
   2969    };
   2970 
   2971    glsBuiltinPrecisionTests.PrecisionCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
   2972    glsBuiltinPrecisionTests.PrecisionCase.prototype.constructor = glsBuiltinPrecisionTests.PrecisionCase;
   2973 
   2974    /**
   2975     * @return {tcuFloatFormat.FloatFormat}
   2976     */
   2977    glsBuiltinPrecisionTests.PrecisionCase.prototype.getFormat = function() {
   2978        return this.m_ctx.floatFormat;
   2979    };
   2980 
   2981    /**
   2982     * Return an output value extracted from flat array
   2983     * @param {goog.NumberArray} output
   2984     * @param {number} index Index of the element to extract
   2985     * @param {*} reference Reference for type informaion
   2986     * @return {glsBuiltinPrecisionTests.Value}
   2987     */
   2988    glsBuiltinPrecisionTests.getOutput = function(output, index, reference) {
   2989        if (reference instanceof Array) {
   2990            var ret = [];
   2991            var size = reference.length;
   2992            for (var i = 0; i < size; i++)
   2993                ret[i] = output[size * index + i];
   2994            return ret;
   2995        }
   2996        if (reference instanceof tcuMatrix.Matrix) {
   2997            var ret = new tcuMatrix.Matrix(reference.rows, reference.cols);
   2998            var size = reference.rows * reference.cols;
   2999            for (var i = 0; i < reference.rows; i++)
   3000                for (var j = 0; j < reference.cols; j++)
   3001                    ret.set(i, j, output[size * index + j * reference.rows + i]);
   3002            return ret;
   3003        }
   3004 
   3005        return output[index];
   3006    };
   3007    /**
   3008     * @param {glsBuiltinPrecisionTests.Variables} variables Variables<In, Out>
   3009     * @param {glsBuiltinPrecisionTests.Inputs} inputs Inputs<In>
   3010     * @param {glsBuiltinPrecisionTests.Statement} stmt
   3011     */
   3012    glsBuiltinPrecisionTests.PrecisionCase.prototype.testStatement = function(variables, inputs, stmt) {
   3013        /** @type {tcuFloatFormat.FloatFormat} */ var fmt = this.getFormat();
   3014        /** @type {number} */ var inCount = glsBuiltinPrecisionTests.numInputs(this.In);
   3015        /** @type {number} */ var outCount = glsBuiltinPrecisionTests.numOutputs(this.Out);
   3016        /** @type {number} */ var numValues = (inCount > 0) ? inputs.in0.length : 1;
   3017        /** @type {tcuFloatFormat.FloatFormat} */ var highpFmt = this.m_ctx.highpFormat;
   3018        var outputs = [];
   3019        /** @type {number} */ var maxMsgs = 100;
   3020        /** @type {number} */ var numErrors = 0;
   3021        /** @type {glsShaderExecUtil.ShaderSpec} */ var spec = new glsShaderExecUtil.ShaderSpec();
   3022        /** @type {glsBuiltinPrecisionTests.Environment} */ var env = new glsBuiltinPrecisionTests.Environment(); // Hoisted out of the inner loop for optimization.
   3023 
   3024        switch (inCount) {
   3025            case 4: DE_ASSERT(inputs.in3.length == numValues);
   3026            case 3: DE_ASSERT(inputs.in2.length == numValues);
   3027            case 2: DE_ASSERT(inputs.in1.length == numValues);
   3028            case 1: DE_ASSERT(inputs.in0.length == numValues);
   3029            default: break;
   3030        }
   3031        if (enableUnittests)
   3032            numValues = 2;
   3033 
   3034        // TODO: Fix logging
   3035        //Print out the statement and its definitions
   3036        // bufferedLogToConsole("Statement: " + stmt);
   3037        // var funcInfo = ''
   3038        // var funcs = {};
   3039        // stmt.getUsedFuncs(funcs);
   3040        // for (var key in funcs) {
   3041        //     var func = funcs[key];
   3042        //     funcInfo += func.printDefinition();
   3043        // };
   3044        // if (funcInfo.length > 0)
   3045        //     bufferedLogToConsole('Reference definitions:' + funcInfo);
   3046 
   3047        // Initialize ShaderSpec from precision, variables and statement.
   3048 
   3049        spec.globalDeclarations = 'precision ' + gluShaderUtil.getPrecisionName(this.m_ctx.precision) + ' float;\n';
   3050 
   3051        if (this.m_extension.length > 0)
   3052            spec.globalDeclarations += '#extension ' + this.m_extension + ' : require\n';
   3053 
   3054        spec.inputs = [];
   3055 
   3056        switch (inCount) {
   3057            case 4: spec.inputs[3] = this.makeSymbol(variables.in3);
   3058            case 3: spec.inputs[2] = this.makeSymbol(variables.in2);
   3059            case 2: spec.inputs[1] = this.makeSymbol(variables.in1);
   3060            case 1: spec.inputs[0] = this.makeSymbol(variables.in0);
   3061            default: break;
   3062        }
   3063 
   3064        spec.outputs = [];
   3065 
   3066        switch (outCount) {
   3067            case 2: spec.outputs[1] = this.makeSymbol(variables.out1);
   3068            case 1: spec.outputs[0] = this.makeSymbol(variables.out0);
   3069            default: break;
   3070        }
   3071 
   3072        spec.source = stmt;
   3073 
   3074        if (enableUnittests == false) {
   3075            // Run the shader with inputs.
   3076            /** @type {glsShaderExecUtil.ShaderExecutor} */
   3077            var executor = glsShaderExecUtil.createExecutor(this.m_ctx.shaderType, spec);
   3078            /** @type {Array<*>} */ var inputArr =
   3079            [
   3080            tcuMatrixUtil.flatten(inputs.in0), tcuMatrixUtil.flatten(inputs.in1), tcuMatrixUtil.flatten(inputs.in2), tcuMatrixUtil.flatten(inputs.in3)
   3081            ];
   3082 
   3083            // executor.log(log());
   3084            if (!executor.isOk())
   3085                testFailed('Shader compilation failed');
   3086 
   3087            executor.useProgram();
   3088            var outputArray = executor.execute(numValues, inputArr);
   3089 
   3090            switch (outCount) {
   3091                case 2:
   3092                    outputs[1] = glsBuiltinPrecisionTests.cast(this.Out.Out1, outputArray[1]);
   3093                case 1:
   3094                    outputs[0] = glsBuiltinPrecisionTests.cast(this.Out.Out0, outputArray[0]);
   3095                default: break;
   3096            }
   3097        }
   3098 
   3099        // Initialize environment with dummy values so we don't need to bind in inner loop.
   3100 
   3101        var in0 = new tcuInterval.Interval();
   3102        var in1 = new tcuInterval.Interval();
   3103        var in2 = new tcuInterval.Interval();
   3104        var in3 = new tcuInterval.Interval();
   3105        var reference0 = new tcuInterval.Interval();
   3106        var reference1 = new tcuInterval.Interval();
   3107 
   3108        env.bind(variables.in0, in0);
   3109        env.bind(variables.in1, in1);
   3110        env.bind(variables.in2, in2);
   3111        env.bind(variables.in3, in3);
   3112        env.bind(variables.out0, reference0);
   3113        env.bind(variables.out1, reference1);
   3114 
   3115        // For each input tuple, compute output reference interval and compare
   3116        // shader output to the reference.
   3117        for (var valueNdx = 0; valueNdx < numValues; valueNdx++) {
   3118            /** @type {boolean} */ var result = true;
   3119            var value0, value1;
   3120            var msg = '';
   3121 
   3122            var in0_ = glsBuiltinPrecisionTests.convert(this.Arg0, fmt, glsBuiltinPrecisionTests.round(this.Arg0, fmt, inputs.in0[valueNdx]));
   3123            var in1_ = glsBuiltinPrecisionTests.convert(this.Arg1, fmt, glsBuiltinPrecisionTests.round(this.Arg1, fmt, inputs.in1[valueNdx]));
   3124            var in2_ = glsBuiltinPrecisionTests.convert(this.Arg2, fmt, glsBuiltinPrecisionTests.round(this.Arg2, fmt, inputs.in2[valueNdx]));
   3125            var in3_ = glsBuiltinPrecisionTests.convert(this.Arg3, fmt, glsBuiltinPrecisionTests.round(this.Arg3, fmt, inputs.in3[valueNdx]));
   3126 
   3127            env.bind(variables.in0, in0_);
   3128            env.bind(variables.in1, in1_);
   3129            env.bind(variables.in2, in2_);
   3130            env.bind(variables.in3, in3_);
   3131 
   3132            stmt.execute(new glsBuiltinPrecisionTests.EvalContext(fmt, this.m_ctx.precision, env));
   3133 
   3134            switch (outCount) {
   3135                case 2:
   3136                    reference1 = glsBuiltinPrecisionTests.convert(this.Out.Out1, highpFmt, env.lookup(variables.out1));
   3137                    if (enableUnittests)
   3138                        result = referenceComparison(reference1, valueNdx + outCount - 1, this.m_ctx.floatFormat);
   3139                    else {
   3140                        value1 = glsBuiltinPrecisionTests.getOutput(outputs[1], valueNdx, reference1);
   3141                        if (!glsBuiltinPrecisionTests.contains(this.Out.Out1, reference1, value1)) {
   3142                        msg = 'Shader output 1 (' + value1 + ') is outside acceptable range: ' + reference1;
   3143                            result = false;
   3144                        }
   3145                    }
   3146                case 1:
   3147                    reference0 = glsBuiltinPrecisionTests.convert(this.Out.Out0, highpFmt, env.lookup(variables.out0));
   3148                    if (enableUnittests)
   3149                        result = referenceComparison(reference0, valueNdx + outCount - 1, this.m_ctx.floatFormat);
   3150                    else {
   3151                        value0 = glsBuiltinPrecisionTests.getOutput(outputs[0], valueNdx, reference0);
   3152                        if (!glsBuiltinPrecisionTests.contains(this.Out.Out0, reference0, value0)) {
   3153                        msg = 'Shader output 0 (' + value0 + ') is outside acceptable range: ' + reference0;
   3154                            result = false;
   3155                        }
   3156                    }
   3157                default: break;
   3158            }
   3159 
   3160            if (!result)
   3161                ++numErrors;
   3162 
   3163            if (!result && numErrors <= maxMsgs) {
   3164                /** @type {string} */ var builder = '';
   3165 
   3166                builder += (result ? 'Passed' : 'Failed') + '\n' + msg + '\n sample:\n' + valueNdx;
   3167 
   3168                if (inCount > 0) {
   3169                    builder += '\t' + variables.in0.getName() + ' = ' +
   3170                            inputs.in0[valueNdx] + '\n';
   3171                }
   3172 
   3173                if (inCount > 1) {
   3174                    builder += '\t' + variables.in1.getName() + ' = ' +
   3175                            inputs.in1[valueNdx] + '\n';
   3176                }
   3177 
   3178                if (inCount > 2) {
   3179                    builder += '\t' + variables.in2.getName() + ' = ' +
   3180                            inputs.in2[valueNdx] + '\n';
   3181                }
   3182 
   3183                if (inCount > 3) {
   3184                    builder += '\t' + variables.in3.getName() + ' = ' +
   3185                            inputs.in3[valueNdx] + '\n';
   3186                }
   3187 
   3188                if (enableUnittests == false) {
   3189                    if (outCount > 0) {
   3190                        builder += '\t' + variables.out0.getName() + ' = ' +
   3191                            value0 + '\n' +
   3192                                '\tExpected range: ' +
   3193                                reference0 + '\n';
   3194                    }
   3195 
   3196                    if (outCount > 1) {
   3197                        builder += '\t' + variables.out1.getName() + ' = ' +
   3198                            value1 + '\n' +
   3199                                '\tExpected range: ' +
   3200                                reference1 + '\n';
   3201                    }
   3202                }
   3203                bufferedLogToConsole(builder);
   3204            }
   3205        }
   3206 
   3207        if (numErrors > maxMsgs) {
   3208            bufferedLogToConsole('(Skipped ' + (numErrors - maxMsgs) + ' messages.)');
   3209        }
   3210 
   3211        if (numErrors == 0) {
   3212            testPassed('All ' + numValues + ' inputs passed.');
   3213        } else {
   3214            testFailed('' + numErrors + '/' + numValues + ' inputs failed.');
   3215        }
   3216    };
   3217 
   3218    /**
   3219     * @param {glsBuiltinPrecisionTests.Variable} variable Variable<typename>
   3220     * @return {glsShaderExecUtil.Symbol}
   3221     */
   3222    glsBuiltinPrecisionTests.PrecisionCase.prototype.makeSymbol = function(variable) {
   3223        var v = variable;
   3224        return new glsShaderExecUtil.Symbol(v.getName(), gluVarType.getVarTypeOf(v.typename, this.m_size, this.m_ctx.precision));
   3225    };
   3226 
   3227    /**
   3228     * @constructor
   3229     * @extends {glsBuiltinPrecisionTests.Tuple4}
   3230     * @param {*} in0
   3231     * @param {*} in1
   3232     * @param {*} in2
   3233     * @param {*} in3
   3234     */
   3235    glsBuiltinPrecisionTests.InTuple = function(in0, in1, in2, in3) {
   3236        glsBuiltinPrecisionTests.Tuple4.call(this, in0, in1, in2, in3);
   3237    };
   3238 
   3239    glsBuiltinPrecisionTests.InTuple.prototype = Object.create(glsBuiltinPrecisionTests.Tuple4.prototype);
   3240    glsBuiltinPrecisionTests.InTuple.prototype.constructor = glsBuiltinPrecisionTests.InTuple;
   3241 
   3242    /**
   3243     * @param {*} In
   3244     * @param {glsBuiltinPrecisionTests.Samplings} samplings Samplings<In>
   3245     * @param {tcuFloatFormat.FloatFormat} floatFormat
   3246     * @param {gluShaderUtil.precision} intPrecision
   3247     * @param {number} numSamples
   3248     * @param {deRandom.Random} rnd
   3249     * @return {glsBuiltinPrecisionTests.Inputs}
   3250     */
   3251    glsBuiltinPrecisionTests.generateInputs = function(In, samplings, floatFormat, intPrecision, numSamples, rnd) {
   3252        /*Inputs<In>*/ var ret = new glsBuiltinPrecisionTests.Inputs(In);
   3253        /*Inputs<In>*/ var fixedInputs = new glsBuiltinPrecisionTests.Inputs(In);
   3254        // set<InTuple<In>, InputLess<InTuple<In> > > seenInputs;
   3255        /** @type {Array<glsBuiltinPrecisionTests.InTuple,glsBuiltinPrecisionTests.InputLess>} */
   3256        var seenInputs = [];
   3257 
   3258        samplings.in0.genFixeds(floatFormat, fixedInputs.in0);
   3259        samplings.in1.genFixeds(floatFormat, fixedInputs.in1);
   3260        samplings.in2.genFixeds(floatFormat, fixedInputs.in2);
   3261        samplings.in3.genFixeds(floatFormat, fixedInputs.in3);
   3262 
   3263        for (var ndx0 = 0; ndx0 < fixedInputs.in0.length; ++ndx0) {
   3264            for (var ndx1 = 0; ndx1 < fixedInputs.in1.length; ++ndx1) {
   3265                for (var ndx2 = 0; ndx2 < fixedInputs.in2.length; ++ndx2) {
   3266                    for (var ndx3 = 0; ndx3 < fixedInputs.in3.length; ++ndx3) {
   3267                        var tuple = new glsBuiltinPrecisionTests.InTuple(fixedInputs.in0[ndx0],
   3268                                                     fixedInputs.in1[ndx1],
   3269                                                     fixedInputs.in2[ndx2],
   3270                                                     fixedInputs.in3[ndx3]);
   3271 
   3272                        seenInputs.push(tuple);
   3273                        ret.in0.push(tuple.a);
   3274                        ret.in1.push(tuple.b);
   3275                        ret.in2.push(tuple.c);
   3276                        ret.in3.push(tuple.d);
   3277                    }
   3278                }
   3279            }
   3280        }
   3281 
   3282        for (var ndx = 0; ndx < numSamples; ++ndx) {
   3283            var in0 = samplings.in0.genRandom(floatFormat, intPrecision, rnd);
   3284            var in1 = samplings.in1.genRandom(floatFormat, intPrecision, rnd);
   3285            var in2 = samplings.in2.genRandom(floatFormat, intPrecision, rnd);
   3286            var in3 = samplings.in3.genRandom(floatFormat, intPrecision, rnd);
   3287            var tuple = new glsBuiltinPrecisionTests.InTuple(in0, in1, in2, in3);
   3288 
   3289            // if (de::contains(seenInputs, tuple))
   3290            //     continue;
   3291 
   3292            seenInputs.push(tuple);
   3293            ret.in0.push(in0);
   3294            ret.in1.push(in1);
   3295            ret.in2.push(in2);
   3296            ret.in3.push(in3);
   3297        }
   3298 
   3299        return ret;
   3300    };
   3301 
   3302    /**
   3303     * @constructor
   3304     * @extends {glsBuiltinPrecisionTests.PrecisionCase}
   3305     * @param {string} name
   3306     * @param {glsBuiltinPrecisionTests.FuncBase} func
   3307     */
   3308    glsBuiltinPrecisionTests.FuncCaseBase = function(context, name, func) {
   3309        glsBuiltinPrecisionTests.PrecisionCase.call(this, context, name, func.getRequiredExtension());
   3310    };
   3311 
   3312    glsBuiltinPrecisionTests.FuncCaseBase.prototype = Object.create(glsBuiltinPrecisionTests.PrecisionCase.prototype);
   3313    glsBuiltinPrecisionTests.FuncCaseBase.prototype.constructor = glsBuiltinPrecisionTests.FuncCaseBase;
   3314 
   3315    glsBuiltinPrecisionTests.FuncCaseBase.prototype.iterate = function() {
   3316 
   3317        assertMsgOptions(!(this.m_extension !== undefined && this.m_extension.trim() !== '') &&
   3318            !sglrGLContext.isExtensionSupported(gl, this.m_extension),
   3319                'Unsupported extension: ' + this.m_extension, false, true);
   3320 
   3321        this.runTest();
   3322 
   3323        // m_status.setTestContextResult(m_testCtx);
   3324        return tcuTestCase.IterateResult.STOP;
   3325    };
   3326 
   3327    /**
   3328     * @constructor
   3329     * @extends {glsBuiltinPrecisionTests.FuncCaseBase}
   3330     * @param {glsBuiltinPrecisionTests.Context} context
   3331     * @param {string} name
   3332     * @param {glsBuiltinPrecisionTests.Func} func
   3333     */
   3334    glsBuiltinPrecisionTests.InOutFuncCase = function(context, name, func) {
   3335        glsBuiltinPrecisionTests.FuncCaseBase.call(this, context, name, func);
   3336        this.Sig = func.Sig;
   3337        this.m_func = func;
   3338        this.Ret = func.Sig.Ret;
   3339        this.Arg0 = func.Sig.Arg0;
   3340        this.Arg1 = func.Sig.Arg1;
   3341        this.Arg2 = func.Sig.Arg2;
   3342        this.Arg3 = func.Sig.Arg3;
   3343        this.In = new glsBuiltinPrecisionTests.InTypes(this.Arg0, this.Arg2, this.Arg3);
   3344        this.Out = new glsBuiltinPrecisionTests.OutTypes(this.Ret, this.Arg1);
   3345        this.m_size = this.m_func.m_size;
   3346    };
   3347 
   3348    glsBuiltinPrecisionTests.InOutFuncCase.prototype = Object.create(glsBuiltinPrecisionTests.FuncCaseBase.prototype);
   3349    glsBuiltinPrecisionTests.InOutFuncCase.prototype.constructor = glsBuiltinPrecisionTests.InOutFuncCase;
   3350 
   3351    /**
   3352     * Samplings<In>
   3353     * @return {glsBuiltinPrecisionTests.Samplings}
   3354     */
   3355    glsBuiltinPrecisionTests.InOutFuncCase.prototype.getSamplings = function() {
   3356        return new glsBuiltinPrecisionTests.DefaultSamplings(this.In, this.m_size);
   3357    };
   3358 
   3359    /**
   3360     * @param {glsBuiltinPrecisionTests.Signature} Sig_
   3361     */
   3362    glsBuiltinPrecisionTests.InOutFuncCase.prototype.runTest = function(Sig_) {
   3363        /** @type {glsBuiltinPrecisionTests.Inputs} */ var inputs = (glsBuiltinPrecisionTests.generateInputs(
   3364                                                    this.In,
   3365                                                    this.getSamplings(),
   3366                                                    this.m_ctx.floatFormat,
   3367                                                    this.m_ctx.precision,
   3368                                                    this.m_ctx.numRandoms,
   3369                                                    this.m_rnd));
   3370 
   3371        var variables = new glsBuiltinPrecisionTests.Variables(this.In, this.Out);
   3372        // Variables<In, Out> variables;
   3373        //
   3374        variables.out0 = new glsBuiltinPrecisionTests.Variable(this.Out.Out0, 'out0');
   3375        variables.out1 = new glsBuiltinPrecisionTests.Variable(this.Arg1, 'out1');
   3376        variables.in0 = new glsBuiltinPrecisionTests.Variable(this.Arg0, 'in0');
   3377        variables.in1 = new glsBuiltinPrecisionTests.Variable(this.Arg2, 'in1');
   3378        variables.in2 = new glsBuiltinPrecisionTests.Variable(this.Arg3, 'in2');
   3379        variables.in3 = new glsBuiltinPrecisionTests.Variable('void', 'in3');
   3380 
   3381        var expr = glsBuiltinPrecisionTests.applyVar(this.m_func,
   3382                                       variables.in0, variables.out1,
   3383                                       variables.in1, variables.in2);
   3384        var stmt = glsBuiltinPrecisionTests.variableAssignment(variables.out0, expr);
   3385 
   3386        this.testStatement(variables, inputs, stmt);
   3387    };
   3388 
   3389    /**
   3390     * @constructor
   3391     * @extends {glsBuiltinPrecisionTests.FuncCaseBase}
   3392     * @param {glsBuiltinPrecisionTests.Context} context
   3393     * @param {string} name
   3394     * @param {glsBuiltinPrecisionTests.Func} func
   3395     */
   3396    glsBuiltinPrecisionTests.FuncCase = function(context, name, func) {
   3397        glsBuiltinPrecisionTests.FuncCaseBase.call(this, context, name, func);
   3398        this.Sig = func.Sig;
   3399        this.m_func = func;
   3400        this.Ret = func.Sig.Ret;
   3401        this.Arg0 = func.Sig.Arg0;
   3402        this.Arg1 = func.Sig.Arg1;
   3403        this.Arg2 = func.Sig.Arg2;
   3404        this.Arg3 = func.Sig.Arg3;
   3405        this.In = new glsBuiltinPrecisionTests.InTypes(this.Arg0, this.Arg1, this.Arg2, this.Arg3);
   3406        this.Out = new glsBuiltinPrecisionTests.OutTypes(this.Ret);
   3407        this.m_size = this.m_func.m_size;
   3408    };
   3409 
   3410    glsBuiltinPrecisionTests.FuncCase.prototype = Object.create(glsBuiltinPrecisionTests.FuncCaseBase.prototype);
   3411    glsBuiltinPrecisionTests.FuncCase.prototype.constructor = glsBuiltinPrecisionTests.FuncCase;
   3412 
   3413    /**
   3414     * Samplings<In>
   3415     * @return {glsBuiltinPrecisionTests.Samplings}
   3416     */
   3417    glsBuiltinPrecisionTests.FuncCase.prototype.getSamplings = function() {
   3418        return new glsBuiltinPrecisionTests.DefaultSamplings(this.In, this.m_size);
   3419    };
   3420 
   3421    /**
   3422     * @param {glsBuiltinPrecisionTests.Signature} Sig_
   3423     */
   3424    glsBuiltinPrecisionTests.FuncCase.prototype.runTest = function(Sig_) {
   3425        /** @type {glsBuiltinPrecisionTests.Inputs} */ var inputs = (glsBuiltinPrecisionTests.generateInputs(
   3426                                                    this.In,
   3427                                                    this.getSamplings(),
   3428                                                    this.m_ctx.floatFormat,
   3429                                                    this.m_ctx.precision,
   3430                                                    this.m_ctx.numRandoms,
   3431                                                    this.m_rnd));
   3432 
   3433        var variables = new glsBuiltinPrecisionTests.Variables(this.In, this.Out);
   3434        // Variables<In, Out> variables;
   3435        //
   3436        variables.out0 = new glsBuiltinPrecisionTests.Variable(this.Ret, 'out0');
   3437        variables.out1 = new glsBuiltinPrecisionTests.Variable('void', 'out1');
   3438        variables.in0 = new glsBuiltinPrecisionTests.Variable(this.Arg0, 'in0');
   3439        variables.in1 = new glsBuiltinPrecisionTests.Variable(this.Arg1, 'in1');
   3440        variables.in2 = new glsBuiltinPrecisionTests.Variable(this.Arg2, 'in2');
   3441        variables.in3 = new glsBuiltinPrecisionTests.Variable(this.Arg3, 'in3');
   3442 
   3443        var expr = glsBuiltinPrecisionTests.applyVar(this.m_func,
   3444                                       variables.in0, variables.in1,
   3445                                       variables.in2, variables.in3);
   3446        var stmt = glsBuiltinPrecisionTests.variableAssignment(variables.out0, expr);
   3447 
   3448        this.testStatement(variables, inputs, stmt);
   3449    };
   3450 
   3451    /**
   3452     * @param {glsBuiltinPrecisionTests.Func} func
   3453     * @param {glsBuiltinPrecisionTests.Variable} arg0
   3454     * @param {glsBuiltinPrecisionTests.Variable} arg1
   3455     * @param {glsBuiltinPrecisionTests.Variable} arg2
   3456     * @param {glsBuiltinPrecisionTests.Variable} arg3
   3457     * @return {glsBuiltinPrecisionTests.ApplyVar}
   3458     */
   3459    glsBuiltinPrecisionTests.applyVar = function(func, arg0, arg1, arg2, arg3) {
   3460        return new glsBuiltinPrecisionTests.ApplyVar(func.Sig, func, arg0, arg1, arg2, arg3);
   3461    };
   3462 
   3463    /**
   3464     * @param {glsBuiltinPrecisionTests.Variable} variable
   3465     * @param {glsBuiltinPrecisionTests.ApplyVar} value
   3466     * @param {boolean} isDeclaration
   3467     */
   3468    glsBuiltinPrecisionTests.variableStatement = function(variable, value, isDeclaration) {
   3469        return new glsBuiltinPrecisionTests.VariableStatement(variable, value, isDeclaration);
   3470    };
   3471 
   3472    /**
   3473     * @param {glsBuiltinPrecisionTests.Variable} variable
   3474     * @param {glsBuiltinPrecisionTests.ApplyVar} value
   3475     */
   3476    glsBuiltinPrecisionTests.variableAssignment = function(variable, value) {
   3477        return glsBuiltinPrecisionTests.variableStatement(variable, value, false);
   3478    };
   3479 
   3480    /**
   3481     * @constructor
   3482     */
   3483    glsBuiltinPrecisionTests.CaseFactories = function() {};
   3484 
   3485    /**
   3486     * @return {Array<glsBuiltinPrecisionTests.CaseFactory>}
   3487     */
   3488    glsBuiltinPrecisionTests.CaseFactories.prototype.getFactories = function() {};
   3489 
   3490    /**
   3491     * @constructor
   3492     * @extends {glsBuiltinPrecisionTests.CaseFactories}
   3493     */
   3494    glsBuiltinPrecisionTests.BuiltinFuncs = function() {
   3495        /** @type {Array<glsBuiltinPrecisionTests.CaseFactory>} */ this.m_factories = [];
   3496    };
   3497 
   3498    glsBuiltinPrecisionTests.BuiltinFuncs.prototype = Object.create(glsBuiltinPrecisionTests.CaseFactories.prototype);
   3499    glsBuiltinPrecisionTests.BuiltinFuncs.prototype.constructor = glsBuiltinPrecisionTests.BuiltinFuncs;
   3500 
   3501    /**
   3502     * @return {Array<glsBuiltinPrecisionTests.CaseFactory>}
   3503     */
   3504    glsBuiltinPrecisionTests.BuiltinFuncs.prototype.getFactories = function() {
   3505        return this.m_factories.slice();
   3506    };
   3507 
   3508    /**
   3509     * @param {glsBuiltinPrecisionTests.CaseFactory} fact
   3510     */
   3511    glsBuiltinPrecisionTests.BuiltinFuncs.prototype.addFactory = function(fact) {
   3512        this.m_factories.push(fact);
   3513    };
   3514 
   3515    /**
   3516     * @param {glsBuiltinPrecisionTests.Context} context
   3517     * @param {string} name
   3518     * @param {glsBuiltinPrecisionTests.Func} func
   3519     * @return {glsBuiltinPrecisionTests.PrecisionCase}
   3520     */
   3521    glsBuiltinPrecisionTests.createFuncCase = function(context, name, func) {
   3522        switch (func.getOutParamIndex()) {
   3523            case -1:
   3524                return new glsBuiltinPrecisionTests.FuncCase(context, name, func);
   3525            case 1:
   3526                return new glsBuiltinPrecisionTests.InOutFuncCase(context, name, func);
   3527            default:
   3528                throw new Error(!'Impossible');
   3529        }
   3530    };
   3531 
   3532    /**
   3533     * @constructor
   3534     */
   3535    glsBuiltinPrecisionTests.CaseFactory = function() {};
   3536 
   3537    /**
   3538     * @return {string}
   3539     */
   3540    glsBuiltinPrecisionTests.CaseFactory.prototype.getName = function() {
   3541        return '';
   3542    };
   3543 
   3544    /**
   3545     * @return {string}
   3546     */
   3547    glsBuiltinPrecisionTests.CaseFactory.prototype.getDesc = function() {
   3548        return '';
   3549    };
   3550 
   3551    /**
   3552     * @param {glsBuiltinPrecisionTests.Context} ctx
   3553     */
   3554    glsBuiltinPrecisionTests.CaseFactory.prototype.createCase = function(ctx) {
   3555        throw new Error('Virtual function. Please override.');
   3556    };
   3557 
   3558    /**
   3559     * @constructor
   3560     * @extends {glsBuiltinPrecisionTests.CaseFactory}
   3561     * @param {glsBuiltinPrecisionTests.Func} func
   3562     */
   3563    glsBuiltinPrecisionTests.SimpleFuncCaseFactory = function(func) {
   3564        glsBuiltinPrecisionTests.CaseFactory.call(this);
   3565        this.m_func = func;
   3566    };
   3567 
   3568    setParentClass(glsBuiltinPrecisionTests.SimpleFuncCaseFactory, glsBuiltinPrecisionTests.CaseFactory);
   3569 
   3570    glsBuiltinPrecisionTests.SimpleFuncCaseFactory.prototype.getName = function() {
   3571        return this.m_func.getName().toLowerCase();
   3572    };
   3573 
   3574    glsBuiltinPrecisionTests.SimpleFuncCaseFactory.prototype.getDesc = function() {
   3575        return "Function '" + this.getName() + "'";
   3576    };
   3577 
   3578    glsBuiltinPrecisionTests.SimpleFuncCaseFactory.prototype.createCase = function(ctx) {
   3579        return glsBuiltinPrecisionTests.createFuncCase(ctx, ctx.name, this.m_func);
   3580    };
   3581 
   3582    /**
   3583     * @constructor
   3584     * @extends {glsBuiltinPrecisionTests.CaseFactory}
   3585     */
   3586    glsBuiltinPrecisionTests.FuncCaseFactory = function() {
   3587        glsBuiltinPrecisionTests.CaseFactory.call(this);
   3588    };
   3589 
   3590    setParentClass(glsBuiltinPrecisionTests.FuncCaseFactory, glsBuiltinPrecisionTests.CaseFactory);
   3591 
   3592    glsBuiltinPrecisionTests.FuncCaseFactory.prototype.getFunc = function() {
   3593        throw new Error('Virtual function. Please override.');
   3594    };
   3595 
   3596    glsBuiltinPrecisionTests.FuncCaseFactory.prototype.getName = function() {
   3597        return this.getFunc().getName().toLowerCase();
   3598    };
   3599 
   3600    glsBuiltinPrecisionTests.FuncCaseFactory.prototype.getDesc = function() {
   3601        return "Function '" + this.getFunc().getName() + "'";
   3602    };
   3603 
   3604    /**
   3605     * @constructor
   3606     * @extends {glsBuiltinPrecisionTests.FuncCaseFactory}
   3607     */
   3608    glsBuiltinPrecisionTests.TemplateFuncCaseFactory = function(genF) {
   3609        glsBuiltinPrecisionTests.FuncCaseFactory.call(this);
   3610        this.m_genF = genF;
   3611    };
   3612 
   3613    setParentClass(glsBuiltinPrecisionTests.TemplateFuncCaseFactory, glsBuiltinPrecisionTests.FuncCaseFactory);
   3614 
   3615    glsBuiltinPrecisionTests.TemplateFuncCaseFactory.prototype.getFunc = function() {
   3616        return new this.m_genF(1);
   3617    };
   3618 
   3619    /**
   3620     * @param {glsBuiltinPrecisionTests.Context} ctx
   3621     */
   3622    glsBuiltinPrecisionTests.TemplateFuncCaseFactory.prototype.createCase = function(ctx) {
   3623        var group = tcuTestCase.newTest(ctx.name, ctx.name);
   3624        group.addChild(glsBuiltinPrecisionTests.createFuncCase(ctx, 'scalar', new this.m_genF(1)));
   3625        group.addChild(glsBuiltinPrecisionTests.createFuncCase(ctx, 'vec2', new this.m_genF(2)));
   3626        group.addChild(glsBuiltinPrecisionTests.createFuncCase(ctx, 'vec3', new this.m_genF(3)));
   3627        group.addChild(glsBuiltinPrecisionTests.createFuncCase(ctx, 'vec4', new this.m_genF(4)));
   3628 
   3629        return group;
   3630    };
   3631 
   3632    /**
   3633     * @constructor
   3634     * @extends {glsBuiltinPrecisionTests.FuncCaseFactory}
   3635     */
   3636    glsBuiltinPrecisionTests.MatrixFuncCaseFactory = function(genF) {
   3637        glsBuiltinPrecisionTests.FuncCaseFactory.call(this);
   3638        this.m_genF = genF;
   3639    };
   3640 
   3641    setParentClass(glsBuiltinPrecisionTests.MatrixFuncCaseFactory, glsBuiltinPrecisionTests.FuncCaseFactory);
   3642 
   3643    glsBuiltinPrecisionTests.MatrixFuncCaseFactory.prototype.getFunc = function() {
   3644        return new this.m_genF(2, 2);
   3645    };
   3646 
   3647    /**
   3648     * @param {glsBuiltinPrecisionTests.Context} ctx
   3649     */
   3650    glsBuiltinPrecisionTests.MatrixFuncCaseFactory.prototype.createCase = function(ctx) {
   3651        var group = tcuTestCase.newTest(ctx.name, ctx.name);
   3652        this.addCase(ctx, group, 2, 2);
   3653        this.addCase(ctx, group, 3, 2);
   3654        this.addCase(ctx, group, 4, 2);
   3655        this.addCase(ctx, group, 2, 3);
   3656        this.addCase(ctx, group, 3, 3);
   3657        this.addCase(ctx, group, 4, 3);
   3658        this.addCase(ctx, group, 2, 4);
   3659        this.addCase(ctx, group, 3, 4);
   3660        this.addCase(ctx, group, 4, 4);
   3661 
   3662        return group;
   3663    };
   3664 
   3665   /**
   3666     * @param {glsBuiltinPrecisionTests.Context} ctx
   3667     * @param {tcuTestCase.DeqpTest} group
   3668     * @param {number} rows
   3669     * @param {number} cols
   3670     */
   3671    glsBuiltinPrecisionTests.MatrixFuncCaseFactory.prototype.addCase = function(ctx, group, rows, cols) {
   3672        var name = glsBuiltinPrecisionTests.dataTypeNameOfMatrix('float', rows, cols);
   3673        group.addChild(glsBuiltinPrecisionTests.createFuncCase(ctx, name, new this.m_genF(rows, cols)));
   3674    };
   3675 
   3676    glsBuiltinPrecisionTests.dataTypeNameOfMatrix = function(typename, rows, cols) {
   3677        switch (typename) {
   3678            case 'float':
   3679                if (rows === cols)
   3680                    return 'mat' + rows;
   3681                else
   3682                    return 'mat' + cols + 'x' + rows;
   3683        }
   3684        throw new Error('Invalid arguments (' + typename + ', ' + rows + ', ' + cols + ')');
   3685    };
   3686 
   3687    /**
   3688     * @constructor
   3689     * @extends {glsBuiltinPrecisionTests.FuncCaseFactory}
   3690     */
   3691    glsBuiltinPrecisionTests.SquareMatrixFuncCaseFactory = function(genF) {
   3692        glsBuiltinPrecisionTests.FuncCaseFactory.call(this);
   3693        this.m_genF = genF;
   3694    };
   3695 
   3696    setParentClass(glsBuiltinPrecisionTests.SquareMatrixFuncCaseFactory, glsBuiltinPrecisionTests.FuncCaseFactory);
   3697 
   3698    glsBuiltinPrecisionTests.SquareMatrixFuncCaseFactory.prototype.getFunc = function() {
   3699        return new this.m_genF(2);
   3700    };
   3701 
   3702    /**
   3703     * @param {glsBuiltinPrecisionTests.Context} ctx
   3704     */
   3705    glsBuiltinPrecisionTests.SquareMatrixFuncCaseFactory.prototype.createCase = function(ctx) {
   3706        var group = tcuTestCase.newTest(ctx.name, ctx.name);
   3707 
   3708        group.addChild(glsBuiltinPrecisionTests.createFuncCase(ctx, 'mat2', new this.m_genF(2)));
   3709        return group;
   3710    };
   3711 
   3712    /**
   3713     * @constructor
   3714     * @extends {glsBuiltinPrecisionTests.PrimitiveFunc}
   3715     * @param {glsBuiltinPrecisionTests.Func} scalarFunc
   3716     * @param {number=} size
   3717     */
   3718    glsBuiltinPrecisionTests.GenFunc = function(scalarFunc, size) {
   3719        glsBuiltinPrecisionTests.PrimitiveFunc.call(this, scalarFunc.Sig);
   3720        this.m_func = scalarFunc;
   3721        this.m_size = size;
   3722    };
   3723 
   3724    glsBuiltinPrecisionTests.GenFunc.prototype = Object.create(glsBuiltinPrecisionTests.PrimitiveFunc.prototype);
   3725    glsBuiltinPrecisionTests.GenFunc.prototype.constructor = glsBuiltinPrecisionTests.GenFunc;
   3726 
   3727    /**
   3728     * @return {string}
   3729     */
   3730    glsBuiltinPrecisionTests.GenFunc.prototype.getName = function() {
   3731       return this.m_func.getName();
   3732    };
   3733 
   3734    /**
   3735     * @return {number}
   3736     */
   3737    glsBuiltinPrecisionTests.GenFunc.prototype.getOutParamIndex = function() {
   3738       return this.m_func.getOutParamIndex();
   3739    };
   3740 
   3741    /**
   3742     * @return {string}
   3743     */
   3744    glsBuiltinPrecisionTests.GenFunc.prototype.getRequiredExtension = function() {
   3745       return this.m_func.getRequiredExtension();
   3746    };
   3747 
   3748    /**
   3749     * @param {Array<glsBuiltinPrecisionTests.ExprBase>} args
   3750     */
   3751    glsBuiltinPrecisionTests.GenFunc.prototype.doPrint = function(args) {
   3752       return this.m_func.print(args);
   3753    };
   3754 
   3755    /**
   3756     * @param {glsBuiltinPrecisionTests.EvalContext} ctx
   3757     * @param {glsBuiltinPrecisionTests.Tuple4} iargs
   3758     * @return {*}
   3759     */
   3760    glsBuiltinPrecisionTests.GenFunc.prototype.doApply = function(ctx, iargs) {
   3761        /** @type {Array<*>} */ var ret = [];
   3762 
   3763        if (this.m_size > 1) {
   3764            for (var ndx = 0; ndx < this.m_size; ++ndx) {
   3765                var a = iargs.a === undefined ? undefined : iargs.a[ndx];
   3766                var b = iargs.b === undefined ? undefined : iargs.b[ndx];
   3767                var c = iargs.c === undefined ? undefined : iargs.c[ndx];
   3768                var d = iargs.d === undefined ? undefined : iargs.d[ndx];
   3769                ret[ndx] = this.m_func.applyFunction(ctx, a, b, c, d);
   3770            }
   3771        } else
   3772            ret[0] = this.m_func.applyFunction(ctx, iargs.a, iargs.b, iargs.c, iargs.d);
   3773 
   3774        return ret;
   3775    };
   3776 
   3777    /**
   3778     * @param {glsBuiltinPrecisionTests.FuncSet} dst
   3779     */
   3780    glsBuiltinPrecisionTests.GenFunc.prototype.doGetUsedFuncs = function(dst) {
   3781        this.m_func.getUsedFuncs(dst);
   3782    };
   3783 
   3784    /**
   3785     * @constructor
   3786     * @extends {glsBuiltinPrecisionTests.GenFunc}
   3787     * @param {glsBuiltinPrecisionTests.Func} func
   3788     * @param {number} size
   3789     */
   3790     glsBuiltinPrecisionTests.VectorizedFunc = function(func, size) {
   3791         glsBuiltinPrecisionTests.GenFunc.call(this, func, size);
   3792    };
   3793 
   3794    glsBuiltinPrecisionTests.VectorizedFunc.prototype = Object.create(glsBuiltinPrecisionTests.GenFunc.prototype);
   3795    glsBuiltinPrecisionTests.VectorizedFunc.prototype.constructor = glsBuiltinPrecisionTests.VectorizedFunc;
   3796 
   3797    /**
   3798     * @constructor
   3799     * @param {glsBuiltinPrecisionTests.Func} func_
   3800     * @param {glsBuiltinPrecisionTests.GenFunc} func2_
   3801     * @param {glsBuiltinPrecisionTests.GenFunc} func3_
   3802     * @param {glsBuiltinPrecisionTests.GenFunc} func4_
   3803     */
   3804    glsBuiltinPrecisionTests.GenFuncs = function(func_, func2_, func3_, func4_) {
   3805        this.func = func_;
   3806        this.func2 = func2_;
   3807        this.func3 = func3_;
   3808        this.func4 = func4_;
   3809    };
   3810 
   3811    /**
   3812     * @constructor
   3813     * @extends {glsBuiltinPrecisionTests.CaseFactory}
   3814     * @param {glsBuiltinPrecisionTests.GenFuncs} funcs
   3815     * @param {string} name
   3816     */
   3817    glsBuiltinPrecisionTests.GenFuncCaseFactory = function(funcs, name) {
   3818        glsBuiltinPrecisionTests.CaseFactory.call(this);
   3819        this.m_funcs = funcs;
   3820        this.m_name = name;
   3821    };
   3822 
   3823    glsBuiltinPrecisionTests.GenFuncCaseFactory.prototype = Object.create(glsBuiltinPrecisionTests.CaseFactory.prototype);
   3824    glsBuiltinPrecisionTests.GenFuncCaseFactory.prototype.constructor = glsBuiltinPrecisionTests.GenFuncCaseFactory;
   3825 
   3826    /**
   3827     * @param {glsBuiltinPrecisionTests.Context} ctx
   3828     * @return {tcuTestCase.DeqpTest}
   3829     */
   3830    glsBuiltinPrecisionTests.GenFuncCaseFactory.prototype.createCase = function(ctx) {
   3831        /** @type {tcuTestCase.DeqpTest} */
   3832        var group = tcuTestCase.newTest(ctx.name, ctx.name);
   3833        group.addChild(glsBuiltinPrecisionTests.createFuncCase(ctx, 'scalar', this.m_funcs.func));
   3834        group.addChild(glsBuiltinPrecisionTests.createFuncCase(ctx, 'vec2', this.m_funcs.func2));
   3835        group.addChild(glsBuiltinPrecisionTests.createFuncCase(ctx, 'vec3', this.m_funcs.func3));
   3836        group.addChild(glsBuiltinPrecisionTests.createFuncCase(ctx, 'vec4', this.m_funcs.func4));
   3837 
   3838        return group;
   3839    };
   3840 
   3841    /**
   3842     * @return {string}
   3843     */
   3844    glsBuiltinPrecisionTests.GenFuncCaseFactory.prototype.getName = function() {
   3845        return this.m_name;
   3846    };
   3847 
   3848    /**
   3849     * @return {string}
   3850     */
   3851    glsBuiltinPrecisionTests.GenFuncCaseFactory.prototype.getDesc = function() {
   3852        return "Function '" + this.m_funcs.func.getName() + "'";
   3853    };
   3854 
   3855    /**
   3856     * @constructor
   3857     * @param {string} name_
   3858     * @param {tcuFloatFormat.FloatFormat} floatFormat_
   3859     * @param {tcuFloatFormat.FloatFormat} highpFormat_
   3860     * @param {gluShaderUtil.precision} precision_
   3861     * @param {gluShaderProgram.shaderType} shaderType_
   3862     * @param {number} numRandoms_
   3863     */
   3864    glsBuiltinPrecisionTests.Context = function(name_, floatFormat_, highpFormat_, precision_, shaderType_, numRandoms_) {
   3865        /** @type {string} */ this.name = name_;
   3866        /** @type {tcuFloatFormat.FloatFormat} */ this.floatFormat = floatFormat_;
   3867        /** @type {tcuFloatFormat.FloatFormat} */ this.highpFormat = highpFormat_;
   3868        /** @type {gluShaderUtil.precision} */ this.precision = precision_;
   3869        /** @type {gluShaderProgram.shaderType} */ this.shaderType = shaderType_;
   3870        /** @type {number} */ this.numRandoms = numRandoms_;
   3871    };
   3872 
   3873    /**
   3874     * @constructor
   3875     * @param {tcuFloatFormat.FloatFormat} highp_
   3876     * @param {tcuFloatFormat.FloatFormat} mediump_
   3877     * @param {tcuFloatFormat.FloatFormat} lowp_
   3878     * @param {Array<gluShaderProgram.shaderType>} shaderTypes_
   3879     * @param {number} numRandoms_
   3880     */
   3881    glsBuiltinPrecisionTests.PrecisionTestContext = function(highp_, mediump_, lowp_, shaderTypes_, numRandoms_) {
   3882        /** @type {Array<gluShaderProgram.shaderType>} */ this.shaderTypes = shaderTypes_;
   3883        /** @type {Array<tcuFloatFormat.FloatFormat>} */ this.formats = [];
   3884        this.formats[gluShaderUtil.precision.PRECISION_HIGHP] = highp_;
   3885        this.formats[gluShaderUtil.precision.PRECISION_MEDIUMP] = mediump_;
   3886        this.formats[gluShaderUtil.precision.PRECISION_LOWP] = lowp_;
   3887        /** @type {number} */ this.numRandoms = numRandoms_;
   3888    };
   3889 
   3890    /**
   3891     * \brief Simple incremental counter.
   3892     *
   3893     * This is used to make sure that different ExpandContexts will not produce
   3894     * overlapping temporary names.
   3895     * @constructor
   3896     *
   3897     */
   3898    glsBuiltinPrecisionTests.Counter = function() {
   3899        this.m_count = 0;
   3900    };
   3901 
   3902    glsBuiltinPrecisionTests.Counter.prototype.get = function() {
   3903        return this.m_count++;
   3904    };
   3905 
   3906    /**
   3907     * @constructor
   3908     */
   3909    glsBuiltinPrecisionTests.ExpandContext = function(counter) {
   3910        this.m_counter = counter;
   3911        this.m_statements = [];
   3912    };
   3913 
   3914    /**
   3915     * @param {string} typename
   3916     * @param {string} baseName
   3917     * @return {glsBuiltinPrecisionTests.Variable}
   3918     */
   3919    glsBuiltinPrecisionTests.ExpandContext.prototype.genSym = function(typename, baseName) {
   3920        return new glsBuiltinPrecisionTests.Variable(typename, baseName + this.m_counter.get());
   3921    };
   3922 
   3923    glsBuiltinPrecisionTests.ExpandContext.prototype.addStatement = function(/*const StatementP&*/ stmt) {
   3924        this.m_statements.push(stmt);
   3925    };
   3926 
   3927    glsBuiltinPrecisionTests.ExpandContext.prototype.getStatements = function() {
   3928        return this.m_statements;
   3929    };
   3930 
   3931    /**
   3932     * @constructor
   3933     * @extends {glsBuiltinPrecisionTests.Func}
   3934     * @param {glsBuiltinPrecisionTests.Signature} Sig_ template <typename Sig_>
   3935     */
   3936    glsBuiltinPrecisionTests.DerivedFunc = function(Sig_) {
   3937        glsBuiltinPrecisionTests.Func.call(this, Sig_);
   3938    };
   3939 
   3940    setParentClass(glsBuiltinPrecisionTests.DerivedFunc, glsBuiltinPrecisionTests.Func);
   3941 
   3942    glsBuiltinPrecisionTests.DerivedFunc.prototype.doPrintDefinition = function() {
   3943        var os = '';
   3944        var paramNames = this.getParamNames();
   3945 
   3946        this.initialize();
   3947 
   3948        os += this.Ret + ' ' + this.getName() +
   3949            '(';
   3950        if (glsBuiltinPrecisionTests.isTypeValid(this.Arg0))
   3951            os += this.Arg0 + ' ' + paramNames.a;
   3952        if (glsBuiltinPrecisionTests.isTypeValid(this.Arg1))
   3953            os += ', ' + this.Arg1 + ' ' + paramNames.b;
   3954        if (glsBuiltinPrecisionTests.isTypeValid(this.Arg2))
   3955            os += ', ' + this.Arg2 + ' ' + paramNames.c;
   3956        if (glsBuiltinPrecisionTests.isTypeValid(this.Arg3))
   3957            os += ', ' + this.Arg3 + ' ' + paramNames.d;
   3958        os += ')\n{\n';
   3959 
   3960        for (var ndx = 0; ndx < this.m_body.length; ++ndx)
   3961            os += this.m_body[ndx];
   3962        os += 'return ' + this.m_ret + ';\n';
   3963        os += '}\n';
   3964 
   3965        return os;
   3966    };
   3967 
   3968    glsBuiltinPrecisionTests.DerivedFunc.prototype.doApply = function(ctx, args) {
   3969        var funEnv = new glsBuiltinPrecisionTests.Environment();
   3970        this.initialize();
   3971 
   3972        funEnv.bind(this.m_var0, args.a);
   3973        funEnv.bind(this.m_var1, args.b);
   3974        funEnv.bind(this.m_var2, args.c);
   3975        funEnv.bind(this.m_var3, args.d);
   3976 
   3977        var funCtx = new glsBuiltinPrecisionTests.EvalContext(ctx.format, ctx.floatPrecision, funEnv, ctx.callDepth);
   3978 
   3979        for (var ndx = 0; ndx < this.m_body.length; ++ndx)
   3980            this.m_body[ndx].execute(funCtx);
   3981 
   3982        var ret = this.m_ret.evaluate(funCtx);
   3983 
   3984        // \todo [lauri] Store references instead of values in environment
   3985        args.a = funEnv.lookup(this.m_var0);
   3986        args.b = funEnv.lookup(this.m_var1);
   3987        args.c = funEnv.lookup(this.m_var2);
   3988        args.d = funEnv.lookup(this.m_var3);
   3989 
   3990        return ret;
   3991    };
   3992 
   3993    glsBuiltinPrecisionTests.DerivedFunc.prototype.initialize = function() {
   3994        if (!this.m_ret) {
   3995            var paramNames = this.getParamNames();
   3996            var symCounter = new glsBuiltinPrecisionTests.Counter();
   3997            var ctx = new glsBuiltinPrecisionTests.ExpandContext(symCounter);
   3998 
   3999            this.m_var0 = new glsBuiltinPrecisionTests.Variable(this.Arg0, paramNames.a);
   4000            this.m_var1 = new glsBuiltinPrecisionTests.Variable(this.Arg1, paramNames.b);
   4001            this.m_var2 = new glsBuiltinPrecisionTests.Variable(this.Arg2, paramNames.c);
   4002            this.m_var3 = new glsBuiltinPrecisionTests.Variable(this.Arg3, paramNames.d);
   4003            var args = new glsBuiltinPrecisionTests.Tuple4(this.m_var0,
   4004                this.m_var1, this.m_var2, this.m_var3);
   4005 
   4006            this.m_ret = this.doExpand(ctx, args);
   4007            this.m_body = ctx.getStatements();
   4008        }
   4009    };
   4010 
   4011    /**
   4012     * @constructor
   4013     * @extends {glsBuiltinPrecisionTests.Func}
   4014     * @param {glsBuiltinPrecisionTests.Signature} Sig_ template <typename Sig_>
   4015     */
   4016    glsBuiltinPrecisionTests.Alternatives = function(Sig_) {
   4017         glsBuiltinPrecisionTests.Func.call(this, Sig_);
   4018    };
   4019 
   4020    setParentClass(glsBuiltinPrecisionTests.Alternatives,glsBuiltinPrecisionTests.Func);
   4021 
   4022    glsBuiltinPrecisionTests.Alternatives.prototype.getName = function() {
   4023        return 'alternatives';
   4024    };
   4025 
   4026    glsBuiltinPrecisionTests.Alternatives.prototype.doPrintDefinition = function() {};
   4027 
   4028    glsBuiltinPrecisionTests.Alternatives.prototype.doGetUsedFuncs = function(dst) {};
   4029 
   4030    glsBuiltinPrecisionTests.Alternatives.prototype.doApply = function(ctx,args) {
   4031        return glsBuiltinPrecisionTests.union(this.Sig.Ret,args.a,args.b);
   4032    };
   4033 
   4034    glsBuiltinPrecisionTests.Alternatives.prototype.doPrint = function(args) {
   4035        return '{' + args[0] + '|' + args[1] + '}';
   4036    };
   4037 
   4038    glsBuiltinPrecisionTests.sizeToName = function(size) {
   4039        switch (size) {
   4040            case 4: return 'vec4';
   4041            case 3: return 'vec3';
   4042            case 2: return 'vec2';
   4043        }
   4044        return 'float';
   4045    };
   4046 
   4047    /**
   4048     * @constructor
   4049     * @param {number} size
   4050     * @extends {glsBuiltinPrecisionTests.DerivedFunc}
   4051     */
   4052    glsBuiltinPrecisionTests.Dot = function(size) {
   4053        var name = glsBuiltinPrecisionTests.sizeToName(size);
   4054        var sig = new glsBuiltinPrecisionTests.Signature('float', name, name);
   4055        glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
   4056        this.m_inputSize = size;
   4057    };
   4058 
   4059    setParentClass(glsBuiltinPrecisionTests.Dot, glsBuiltinPrecisionTests.DerivedFunc);
   4060 
   4061    glsBuiltinPrecisionTests.Dot.prototype.getName = function() {
   4062        return 'dot';
   4063    };
   4064 
   4065    glsBuiltinPrecisionTests.Dot.prototype.doExpand = function(ctx, args) {
   4066        if (this.m_inputSize > 1) {
   4067            var val = app(new glsBuiltinPrecisionTests.Mul(),
   4068                new glsBuiltinPrecisionTests.VectorVariable(args.a, 0), new glsBuiltinPrecisionTests.VectorVariable(args.b, 0));
   4069            for (var i = 1; i < this.m_inputSize; i++) {
   4070                var tmp = new glsBuiltinPrecisionTests.Apply('float', new glsBuiltinPrecisionTests.Mul(),
   4071                    new glsBuiltinPrecisionTests.VectorVariable(args.a, i), new glsBuiltinPrecisionTests.VectorVariable(args.b, i));
   4072                val = app(new glsBuiltinPrecisionTests.Add(), val, tmp);
   4073            }
   4074            return val;
   4075        } else {
   4076            // args.a * args.b
   4077            var ret = app(new glsBuiltinPrecisionTests.Mul(), args.a, args.b);
   4078            return ret;
   4079        }
   4080    };
   4081 
   4082    /**
   4083     * @constructor
   4084     * @param {number} size
   4085     * @extends {glsBuiltinPrecisionTests.DerivedFunc}
   4086     */
   4087    glsBuiltinPrecisionTests.Length = function(size) {
   4088        var name = glsBuiltinPrecisionTests.sizeToName(size);
   4089        var sig = new glsBuiltinPrecisionTests.Signature('float', name);
   4090        glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
   4091        this.m_inputSize = size;
   4092    };
   4093 
   4094    setParentClass(glsBuiltinPrecisionTests.Length, glsBuiltinPrecisionTests.DerivedFunc);
   4095 
   4096    glsBuiltinPrecisionTests.Length.prototype.getName = function() {
   4097        return 'length';
   4098    };
   4099 
   4100    glsBuiltinPrecisionTests.Length.prototype.doExpand = function(ctx, args) {
   4101        //sqrt(dot(args.a, args.a));
   4102        var v0 = app(new glsBuiltinPrecisionTests.Dot(this.m_inputSize), args.a, args.a);
   4103        var v1 = app(new glsBuiltinPrecisionTests.Sqrt(), v0);
   4104        return v1;
   4105    };
   4106 
   4107    /**
   4108     * @constructor
   4109     * @param {number} size
   4110     * @extends {glsBuiltinPrecisionTests.DerivedFunc}
   4111     */
   4112    glsBuiltinPrecisionTests.Distance = function(size) {
   4113        var name = glsBuiltinPrecisionTests.sizeToName(size);
   4114        var sig = new glsBuiltinPrecisionTests.Signature('float', name, name);
   4115        glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
   4116        this.m_inputSize = size;
   4117    };
   4118 
   4119    setParentClass(glsBuiltinPrecisionTests.Distance, glsBuiltinPrecisionTests.DerivedFunc);
   4120 
   4121    glsBuiltinPrecisionTests.Distance.prototype.getName = function() {
   4122        return 'distance';
   4123    };
   4124 
   4125    glsBuiltinPrecisionTests.Distance.prototype.doExpand = function(ctx, args) {
   4126        //length(args.a - args.b);
   4127        var v0 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Sub(), args.a, args.b);
   4128        var v1 = app(new glsBuiltinPrecisionTests.Length(this.m_inputSize), v0);
   4129        return v1;
   4130    };
   4131 
   4132   /**
   4133     * @constructor
   4134     * @extends {glsBuiltinPrecisionTests.DerivedFunc}
   4135     */
   4136    glsBuiltinPrecisionTests.Cross = function() {
   4137        var sig = new glsBuiltinPrecisionTests.Signature('vec3', 'vec3', 'vec3');
   4138        glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
   4139        this.m_inputSize = 3;
   4140    };
   4141 
   4142    setParentClass(glsBuiltinPrecisionTests.Cross, glsBuiltinPrecisionTests.DerivedFunc);
   4143 
   4144    glsBuiltinPrecisionTests.Cross.prototype.getName = function() {
   4145        return 'cross';
   4146    };
   4147 
   4148    glsBuiltinPrecisionTests.Cross.prototype.doExpand = function(ctx, args) {
   4149        // vec3(x.a[1] * x.b[2] - x.b[1] * x.a[2],
   4150        //      x.a[2] * x.b[0] - x.b[2] * x.a[0],
   4151        //      x.a[0] * x.b[1] - x.b[0] * x.a[1]);
   4152        var a = [], b = [];
   4153        for (var i = 0; i < this.m_inputSize; i++) {
   4154            a[i] = new glsBuiltinPrecisionTests.VectorVariable(args.a, i);
   4155            b[i] = new glsBuiltinPrecisionTests.VectorVariable(args.b, i);
   4156        }
   4157        var v0 = app(new glsBuiltinPrecisionTests.Mul(), a[1], b[2]);
   4158        var v1 = app(new glsBuiltinPrecisionTests.Mul(), b[1], a[2]);
   4159        var v2 = app(new glsBuiltinPrecisionTests.Sub(), v0, v1);
   4160 
   4161        var v3 = app(new glsBuiltinPrecisionTests.Mul(), a[2], b[0]);
   4162        var v4 = app(new glsBuiltinPrecisionTests.Mul(), b[2], a[0]);
   4163        var v5 = app(new glsBuiltinPrecisionTests.Sub(), v3, v4);
   4164 
   4165        var v6 = app(new glsBuiltinPrecisionTests.Mul(), a[0], b[1]);
   4166        var v7 = app(new glsBuiltinPrecisionTests.Mul(), b[0], a[1]);
   4167        var v8 = app(new glsBuiltinPrecisionTests.Sub(), v6, v7);
   4168 
   4169        var v9 = app(new glsBuiltinPrecisionTests.GenVec(this.m_inputSize, true), v2, v5, v8);
   4170        return v9;
   4171    };
   4172 
   4173    /**
   4174     * @constructor
   4175     * @param {number} size
   4176     * @extends {glsBuiltinPrecisionTests.DerivedFunc}
   4177     */
   4178    glsBuiltinPrecisionTests.Normalize = function(size) {
   4179        var name = glsBuiltinPrecisionTests.sizeToName(size);
   4180        var sig = new glsBuiltinPrecisionTests.Signature(name, name);
   4181        glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
   4182        this.m_inputSize = size;
   4183    };
   4184 
   4185    setParentClass(glsBuiltinPrecisionTests.Normalize, glsBuiltinPrecisionTests.DerivedFunc);
   4186 
   4187    glsBuiltinPrecisionTests.Normalize.prototype.getName = function() {
   4188        return 'normalize';
   4189    };
   4190 
   4191    glsBuiltinPrecisionTests.Normalize.prototype.doExpand = function(ctx, args) {
   4192        //args.a / length<Size>(args.a);
   4193        var v0 = app(new glsBuiltinPrecisionTests.Length(this.m_inputSize), args.a);
   4194        var v1 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Div(), args.a, v0);
   4195        return v1;
   4196    };
   4197 
   4198    /**
   4199     * @constructor
   4200     * @param {number} size
   4201     * @extends {glsBuiltinPrecisionTests.DerivedFunc}
   4202     */
   4203    glsBuiltinPrecisionTests.FaceForward = function(size) {
   4204        var name = glsBuiltinPrecisionTests.sizeToName(size);
   4205        var sig = new glsBuiltinPrecisionTests.Signature(name, name, name, name);
   4206        glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
   4207        this.m_inputSize = size;
   4208        this.typename = name;
   4209    };
   4210 
   4211    setParentClass(glsBuiltinPrecisionTests.FaceForward, glsBuiltinPrecisionTests.DerivedFunc);
   4212 
   4213    glsBuiltinPrecisionTests.FaceForward.prototype.getName = function() {
   4214        return 'faceforward';
   4215    };
   4216 
   4217    glsBuiltinPrecisionTests.FaceForward.prototype.doExpand = function(ctx, args) {
   4218        //cond(dot(args.c, args.b) < constant(0.0f), args.a, -args.a);
   4219        var zero = new glsBuiltinPrecisionTests.Constant(0);
   4220        var v0 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Negate(), args.a);
   4221        var v1 = app(new glsBuiltinPrecisionTests.Dot(this.m_inputSize), args.c, args.b);
   4222        var v2 = app(new glsBuiltinPrecisionTests.LessThan('float'), v1, zero);
   4223        var v3 = app(new glsBuiltinPrecisionTests.Cond(this.typename), v2, args.a, v0);
   4224        return v3;
   4225    };
   4226 
   4227    /**
   4228     * @constructor
   4229     * @param {number} size
   4230     * @extends {glsBuiltinPrecisionTests.DerivedFunc}
   4231     */
   4232    glsBuiltinPrecisionTests.Reflect = function(size) {
   4233        var name = glsBuiltinPrecisionTests.sizeToName(size);
   4234        var sig = new glsBuiltinPrecisionTests.Signature(name, name, name);
   4235        glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
   4236        this.m_inputSize = size;
   4237    };
   4238 
   4239    setParentClass(glsBuiltinPrecisionTests.Reflect, glsBuiltinPrecisionTests.DerivedFunc);
   4240 
   4241    glsBuiltinPrecisionTests.Reflect.prototype.getName = function() {
   4242        return 'reflect';
   4243    };
   4244 
   4245    glsBuiltinPrecisionTests.Reflect.prototype.doExpand = function(ctx, args) {
   4246        //args.a - (args.b * dot(args.b, args.a) * constant(2.0f));
   4247        var two = new glsBuiltinPrecisionTests.Constant(2);
   4248        var v0 = app(new glsBuiltinPrecisionTests.Dot(this.m_inputSize), args.b, args.a);
   4249        var v1 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Mul(), args.b, v0);
   4250        var v2 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Mul(), v1, two);
   4251        var v3 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Sub(), args.a, v2);
   4252        return v3;
   4253    };
   4254 
   4255    /**
   4256     * @constructor
   4257     * @param {number} size
   4258     * @extends {glsBuiltinPrecisionTests.DerivedFunc}
   4259     */
   4260    glsBuiltinPrecisionTests.Refract = function(size) {
   4261        var name = glsBuiltinPrecisionTests.sizeToName(size);
   4262        var sig = new glsBuiltinPrecisionTests.Signature(name, name, name, 'float');
   4263        glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
   4264        this.m_inputSize = size;
   4265        this.typename = name;
   4266    };
   4267 
   4268    setParentClass(glsBuiltinPrecisionTests.Refract, glsBuiltinPrecisionTests.DerivedFunc);
   4269 
   4270    glsBuiltinPrecisionTests.Refract.prototype.getName = function() {
   4271        return 'refract';
   4272    };
   4273 
   4274    glsBuiltinPrecisionTests.Refract.prototype.doExpand = function(ctx, args) {
   4275        var i = args.a;
   4276        var n = args.b;
   4277        var eta = args.c;
   4278        var zero = new glsBuiltinPrecisionTests.Constant(0);
   4279        var one = new glsBuiltinPrecisionTests.Constant(1);
   4280        // dotNI = dot(n, i)
   4281        var v0 = app(new glsBuiltinPrecisionTests.Dot(this.m_inputSize), n, i);
   4282        var dotNI = glsBuiltinPrecisionTests.bindExpression('float', 'dotNI', ctx, v0);
   4283        // k = 1 - eta * eta * (1 - dotNI * dotNI)
   4284        var v1 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Mul(), dotNI, dotNI);
   4285        var v2 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Sub(), one, v1);
   4286        var v3 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Mul(), eta, eta);
   4287        var v4 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Mul(), v3, v2);
   4288        var v5 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Sub(), one, v4);
   4289        var k = glsBuiltinPrecisionTests.bindExpression('float', 'k', ctx, v5);
   4290 
   4291        // i * eta - n * (eta * dotNI + sqrt(k))
   4292        var v6 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Mul(), eta, dotNI);
   4293        var v7 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Sqrt(), k);
   4294        var v8 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Add(), v6, v7);
   4295        var v9 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Mul(), n, v8);
   4296        var v10 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Mul(), i, eta);
   4297    var v11 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.Sub(), v10, v9);
   4298 
   4299        var v12 = new glsBuiltinPrecisionTests.ApplyScalar(new glsBuiltinPrecisionTests.LessThan('float'), k, zero);
   4300 
   4301        var zeroVector = app(new glsBuiltinPrecisionTests.GenVec(this.m_inputSize), zero);
   4302        var v13 = app(new glsBuiltinPrecisionTests.Cond(this.typename), v12, zeroVector, v11);
   4303        return v13;
   4304    };
   4305 
   4306    /**
   4307     * @constructor
   4308     * @extends {glsBuiltinPrecisionTests.DerivedFunc}
   4309     */
   4310    glsBuiltinPrecisionTests.Radians = function() {
   4311        var sig = new glsBuiltinPrecisionTests.Signature('float', 'float');
   4312        glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
   4313    };
   4314 
   4315    setParentClass(glsBuiltinPrecisionTests.Radians, glsBuiltinPrecisionTests.DerivedFunc);
   4316 
   4317    glsBuiltinPrecisionTests.Radians.prototype.getName = function() {
   4318        return 'radians';
   4319    };
   4320 
   4321    glsBuiltinPrecisionTests.Radians.prototype.doExpand = function(ctx, args) {
   4322        var val = app(new glsBuiltinPrecisionTests.Div(),
   4323                                                      new glsBuiltinPrecisionTests.Constant(Math.PI),
   4324                                                      new glsBuiltinPrecisionTests.Constant(180));
   4325        return new glsBuiltinPrecisionTests.Apply('float',
   4326                                                  new glsBuiltinPrecisionTests.Mul(),
   4327                                                  val,
   4328                                                  args.a);
   4329 
   4330    };
   4331 
   4332    /**
   4333     * @constructor
   4334     * @extends {glsBuiltinPrecisionTests.DerivedFunc}
   4335     */
   4336    glsBuiltinPrecisionTests.Degrees = function() {
   4337        var sig = new glsBuiltinPrecisionTests.Signature('float', 'float');
   4338        glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
   4339    };
   4340 
   4341    setParentClass(glsBuiltinPrecisionTests.Degrees, glsBuiltinPrecisionTests.DerivedFunc);
   4342 
   4343    glsBuiltinPrecisionTests.Degrees.prototype.getName = function() {
   4344        return 'degrees';
   4345    };
   4346 
   4347    glsBuiltinPrecisionTests.Degrees.prototype.doExpand = function(ctx, args) {
   4348        var val = app(new glsBuiltinPrecisionTests.Div(),
   4349                                                      new glsBuiltinPrecisionTests.Constant(180),
   4350                                                      new glsBuiltinPrecisionTests.Constant(Math.PI));
   4351        return new glsBuiltinPrecisionTests.Apply('float',
   4352                                                  new glsBuiltinPrecisionTests.Mul(),
   4353                                                  val,
   4354                                                  args.a);
   4355 
   4356    };
   4357 
   4358    /**
   4359     * @constructor
   4360     * @extends {glsBuiltinPrecisionTests.DerivedFunc}
   4361     */
   4362    glsBuiltinPrecisionTests.Sinh = function() {
   4363        var sig = new glsBuiltinPrecisionTests.Signature('float', 'float');
   4364        glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
   4365    };
   4366 
   4367    setParentClass(glsBuiltinPrecisionTests.Sinh, glsBuiltinPrecisionTests.DerivedFunc);
   4368 
   4369    glsBuiltinPrecisionTests.Sinh.prototype.getName = function() {
   4370        return 'sinh';
   4371    };
   4372 
   4373    glsBuiltinPrecisionTests.Sinh.prototype.doExpand = function(ctx, args) {
   4374        // (exp(x) - exp(-x)) / constant(2.0f)
   4375        var x = args.a;
   4376        var v0 = app(new glsBuiltinPrecisionTests.Exp(), x);
   4377        var v1 = app(new glsBuiltinPrecisionTests.Negate(), x);
   4378        var v2 = app(new glsBuiltinPrecisionTests.Exp(), v1);
   4379        var v3 = app(new glsBuiltinPrecisionTests.Sub(), v0, v2);
   4380        var v4 = new glsBuiltinPrecisionTests.Constant(2);
   4381        var v5 = new glsBuiltinPrecisionTests.Apply('float', new glsBuiltinPrecisionTests.Div, v3, v4);
   4382        return v5;
   4383    };
   4384 
   4385    /**
   4386     * @constructor
   4387     * @extends {glsBuiltinPrecisionTests.DerivedFunc}
   4388     */
   4389    glsBuiltinPrecisionTests.Cosh = function() {
   4390        var sig = new glsBuiltinPrecisionTests.Signature('float', 'float');
   4391        glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
   4392    };
   4393 
   4394    setParentClass(glsBuiltinPrecisionTests.Cosh, glsBuiltinPrecisionTests.DerivedFunc);
   4395 
   4396    glsBuiltinPrecisionTests.Cosh.prototype.getName = function() {
   4397        return 'cosh';
   4398    };
   4399 
   4400    glsBuiltinPrecisionTests.Cosh.prototype.doExpand = function(ctx, args) {
   4401        // (exp(x) + exp(-x)) / constant(2.0f)
   4402        var x = args.a;
   4403        var v0 = app(new glsBuiltinPrecisionTests.Exp(), x);
   4404        var v1 = app(new glsBuiltinPrecisionTests.Negate(), x);
   4405        var v2 = app(new glsBuiltinPrecisionTests.Exp(), v1);
   4406        var v3 = app(new glsBuiltinPrecisionTests.Add(), v0, v2);
   4407        var v4 = new glsBuiltinPrecisionTests.Constant(2);
   4408        var v5 = new glsBuiltinPrecisionTests.Apply('float', new glsBuiltinPrecisionTests.Div, v3, v4);
   4409        return v5;
   4410    };
   4411 
   4412    /**
   4413     * @constructor
   4414     * @extends {glsBuiltinPrecisionTests.DerivedFunc}
   4415     */
   4416    glsBuiltinPrecisionTests.Tanh = function() {
   4417        var sig = new glsBuiltinPrecisionTests.Signature('float', 'float');
   4418        glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
   4419    };
   4420 
   4421    setParentClass(glsBuiltinPrecisionTests.Tanh, glsBuiltinPrecisionTests.DerivedFunc);
   4422 
   4423    glsBuiltinPrecisionTests.Tanh.prototype.getName = function() {
   4424        return 'tanh';
   4425    };
   4426 
   4427    glsBuiltinPrecisionTests.Tanh.prototype.doExpand = function(ctx, args) {
   4428        // sinh(x) / cosh(x)
   4429        var x = args.a;
   4430        var v0 = app(new glsBuiltinPrecisionTests.Sinh(), x);
   4431        var v1 = app(new glsBuiltinPrecisionTests.Cosh(), x);
   4432        var v2 = new glsBuiltinPrecisionTests.Apply('float', new glsBuiltinPrecisionTests.Div, v0, v1);
   4433        return v2;
   4434    };
   4435 
   4436    /**
   4437     * @constructor
   4438     * @extends {glsBuiltinPrecisionTests.DerivedFunc}
   4439     */
   4440    glsBuiltinPrecisionTests.ASinh = function() {
   4441        var sig = new glsBuiltinPrecisionTests.Signature('float', 'float');
   4442        glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
   4443    };
   4444 
   4445    setParentClass(glsBuiltinPrecisionTests.ASinh, glsBuiltinPrecisionTests.DerivedFunc);
   4446 
   4447    glsBuiltinPrecisionTests.ASinh.prototype.getName = function() {
   4448        return 'asinh';
   4449    };
   4450 
   4451    glsBuiltinPrecisionTests.ASinh.prototype.doExpand = function(ctx, args) {
   4452        // log(x + sqrt(x * x + constant(1.0f)))
   4453        var x = args.a;
   4454        var v0 = app(new glsBuiltinPrecisionTests.Mul(), x, x);
   4455        var v1 = new glsBuiltinPrecisionTests.Constant(1);
   4456        var v2 = app(new glsBuiltinPrecisionTests.Add(), v0, v1);
   4457        var v3 = app(new glsBuiltinPrecisionTests.Sqrt(), v2);
   4458        var v4 = app(new glsBuiltinPrecisionTests.Add(), x, v3);
   4459        var v5 = app(new glsBuiltinPrecisionTests.Log(), v4);
   4460        return v5;
   4461    };
   4462 
   4463    /**
   4464     * @constructor
   4465     * @extends {glsBuiltinPrecisionTests.DerivedFunc}
   4466     */
   4467    glsBuiltinPrecisionTests.ACosh = function() {
   4468        var sig = new glsBuiltinPrecisionTests.Signature('float', 'float');
   4469        glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
   4470    };
   4471 
   4472    setParentClass(glsBuiltinPrecisionTests.ACosh, glsBuiltinPrecisionTests.DerivedFunc);
   4473 
   4474    glsBuiltinPrecisionTests.ACosh.prototype.getName = function() {
   4475        return 'acosh';
   4476    };
   4477 
   4478    glsBuiltinPrecisionTests.ACosh.prototype.doExpand = function(ctx, args) {
   4479        // log(x + sqrt((x + constant(1.0f)) * (x - constant(1.0f))))
   4480        var x = args.a;
   4481        var one = new glsBuiltinPrecisionTests.Constant(1);
   4482        var v0 = app(new glsBuiltinPrecisionTests.Add(), x, one);
   4483        var v1 = app(new glsBuiltinPrecisionTests.Sub(), x, one);
   4484        var v2 = app(new glsBuiltinPrecisionTests.Mul(), v0, v1);
   4485        var v3 = app(new glsBuiltinPrecisionTests.Sqrt(), v2);
   4486        var v4 = app(new glsBuiltinPrecisionTests.Add(), x, v3);
   4487        var v5 = app(new glsBuiltinPrecisionTests.Log(), v4);
   4488        return v5;
   4489    };
   4490 
   4491    /**
   4492     * @constructor
   4493     * @extends {glsBuiltinPrecisionTests.DerivedFunc}
   4494     */
   4495    glsBuiltinPrecisionTests.ATanh = function() {
   4496        var sig = new glsBuiltinPrecisionTests.Signature('float', 'float');
   4497        glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
   4498    };
   4499 
   4500    setParentClass(glsBuiltinPrecisionTests.ATanh, glsBuiltinPrecisionTests.DerivedFunc);
   4501 
   4502    glsBuiltinPrecisionTests.ATanh.prototype.getName = function() {
   4503        return 'atanh';
   4504    };
   4505 
   4506    glsBuiltinPrecisionTests.ATanh.prototype.doExpand = function(ctx, args) {
   4507        // constant(0.5f) * log((constant(1.0f) + x) / (constant(1.0f) - x))
   4508        var x = args.a;
   4509        var one = new glsBuiltinPrecisionTests.Constant(1);
   4510        var half = new glsBuiltinPrecisionTests.Constant(0.5);
   4511        var v0 = app(new glsBuiltinPrecisionTests.Add(), one, x);
   4512        var v1 = app(new glsBuiltinPrecisionTests.Sub(), one, x);
   4513        var v2 = app(new glsBuiltinPrecisionTests.Div(), v0, v1);
   4514        var v3 = app(new glsBuiltinPrecisionTests.Log(), v2);
   4515        var v4 = app(new glsBuiltinPrecisionTests.Mul(), half, v3);
   4516        return v4;
   4517    };
   4518 
   4519    /**
   4520     * @constructor
   4521     * @extends {glsBuiltinPrecisionTests.DerivedFunc}
   4522     */
   4523    glsBuiltinPrecisionTests.Sqrt = function() {
   4524        var sig = new glsBuiltinPrecisionTests.Signature('float', 'float');
   4525        glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
   4526    };
   4527 
   4528    setParentClass(glsBuiltinPrecisionTests.Sqrt, glsBuiltinPrecisionTests.DerivedFunc);
   4529 
   4530    glsBuiltinPrecisionTests.Sqrt.prototype.getName = function() {
   4531        return 'sqrt';
   4532    };
   4533 
   4534    glsBuiltinPrecisionTests.Sqrt.prototype.doExpand = function(ctx, args) {
   4535        // constant(1.0f) / app<InverseSqrt>(x)
   4536        var x = args.a;
   4537        var one = new glsBuiltinPrecisionTests.Constant(1);
   4538        var v0 = app(new glsBuiltinPrecisionTests.InverseSqrt(), x);
   4539        var v1 = app(new glsBuiltinPrecisionTests.Div(), one, v0);
   4540        return v1;
   4541    };
   4542 
   4543    /**
   4544     * @constructor
   4545     * @extends {glsBuiltinPrecisionTests.DerivedFunc}
   4546     */
   4547    glsBuiltinPrecisionTests.Fract = function() {
   4548        var sig = new glsBuiltinPrecisionTests.Signature('float', 'float');
   4549        glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
   4550    };
   4551 
   4552    setParentClass(glsBuiltinPrecisionTests.Fract, glsBuiltinPrecisionTests.DerivedFunc);
   4553 
   4554    glsBuiltinPrecisionTests.Fract.prototype.getName = function() {
   4555        return 'fract';
   4556    };
   4557 
   4558    glsBuiltinPrecisionTests.Fract.prototype.doExpand = function(ctx, args) {
   4559        // x - floor(x)
   4560        var x = args.a;
   4561        var v0 = app(new glsBuiltinPrecisionTests.Floor(), x);
   4562        var v1 = app(new glsBuiltinPrecisionTests.Sub(), x, v0);
   4563        return v1;
   4564    };
   4565 
   4566    /**
   4567     * @constructor
   4568     * @extends {glsBuiltinPrecisionTests.DerivedFunc}
   4569     */
   4570    glsBuiltinPrecisionTests.Mod = function() {
   4571        var sig = new glsBuiltinPrecisionTests.Signature('float', 'float', 'float');
   4572        glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
   4573    };
   4574 
   4575    setParentClass(glsBuiltinPrecisionTests.Mod, glsBuiltinPrecisionTests.DerivedFunc);
   4576 
   4577    glsBuiltinPrecisionTests.Mod.prototype.getName = function() {
   4578        return 'mod';
   4579    };
   4580 
   4581    glsBuiltinPrecisionTests.Mod.prototype.doExpand = function(ctx, args) {
   4582        // x - y * floor(x/y)
   4583        var x = args.a;
   4584        var y = args.b;
   4585        var v0 = app(new glsBuiltinPrecisionTests.Div(), x, y);
   4586        var v1 = app(new glsBuiltinPrecisionTests.Floor(), v0);
   4587        var v2 = app(new glsBuiltinPrecisionTests.Mul(), y, v1);
   4588        var v3 = app(new glsBuiltinPrecisionTests.Sub(), x, v2);
   4589        return v3;
   4590    };
   4591 
   4592    /**
   4593     * @constructor
   4594     * @extends {glsBuiltinPrecisionTests.PrimitiveFunc}
   4595     */
   4596    glsBuiltinPrecisionTests.Modf = function() {
   4597        var sig = new glsBuiltinPrecisionTests.Signature('float', 'float', 'float');
   4598        glsBuiltinPrecisionTests.PrimitiveFunc.call(this, sig);
   4599    };
   4600    setParentClass(glsBuiltinPrecisionTests.Modf, glsBuiltinPrecisionTests.PrimitiveFunc);
   4601 
   4602    glsBuiltinPrecisionTests.Modf.prototype.getName = function() {
   4603        return 'modf';
   4604    };
   4605 
   4606    glsBuiltinPrecisionTests.Modf.prototype.doApply = function(ctx, iargs, variablenames) {
   4607        var intPart;
   4608        var func1 = function(x) {
   4609            intPart = Math.trunc(x);
   4610            return x - intPart;
   4611        };
   4612        var func2 = function(x) {
   4613            return Math.trunc(x);
   4614        };
   4615 
   4616        var fracIV = tcuInterval.applyMonotone1p(func1, iargs.a);
   4617        var wholeIV = tcuInterval.applyMonotone1p(func2, iargs.a);
   4618 
   4619        if (!iargs.a.isFinite()) {
   4620            // Behavior on modf(Inf) not well-defined, allow anything as a fractional part
   4621            // See Khronos bug 13907
   4622            fracIV.operatorOrAssignBinary(tcuInterval.NAN);
   4623        }
   4624 
   4625        ctx.env.m_map[variablenames[1]] = wholeIV;
   4626        return fracIV;
   4627    };
   4628 
   4629    glsBuiltinPrecisionTests.Modf.prototype.getOutParamIndex = function() {
   4630        return 1;
   4631    };
   4632 
   4633    /**
   4634     * @constructor
   4635     * @extends {glsBuiltinPrecisionTests.DerivedFunc}
   4636     */
   4637    glsBuiltinPrecisionTests.Mix = function() {
   4638        var sig = new glsBuiltinPrecisionTests.Signature('float', 'float', 'float', 'float');
   4639        glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
   4640    };
   4641 
   4642    setParentClass(glsBuiltinPrecisionTests.Mix, glsBuiltinPrecisionTests.DerivedFunc);
   4643 
   4644    glsBuiltinPrecisionTests.Mix.prototype.getName = function() {
   4645        return 'mix';
   4646    };
   4647 
   4648    glsBuiltinPrecisionTests.Mix.prototype.operation1 = function(ctx, args) {
   4649        // (x * (constant(1.0f) - a)) + y * a
   4650        var x = args.a;
   4651        var y = args.b;
   4652        var a = args.c;
   4653        var one = new glsBuiltinPrecisionTests.Constant(1);
   4654        var v0 = app(new glsBuiltinPrecisionTests.Sub(), one, a);
   4655        var v1 = app(new glsBuiltinPrecisionTests.Mul(), x, v0);
   4656        var v2 = app(new glsBuiltinPrecisionTests.Mul(), y, a);
   4657        var v3 = app(new glsBuiltinPrecisionTests.Add(), v1, v2);
   4658        return v3;
   4659    };
   4660 
   4661    glsBuiltinPrecisionTests.Mix.prototype.operation2 = function(ctx, args) {
   4662        // x + (y - x) * a
   4663        var x = args.a;
   4664        var y = args.b;
   4665        var a = args.c;
   4666        var v0 = app(new glsBuiltinPrecisionTests.Sub(), y, x);
   4667        var v1 = app(new glsBuiltinPrecisionTests.Mul(), a, v0);
   4668        var v2 = app(new glsBuiltinPrecisionTests.Add(), x, v1);
   4669        return v2;
   4670    };
   4671 
   4672    glsBuiltinPrecisionTests.Mix.prototype.doExpand = function(ctx, args){
   4673        return app(new glsBuiltinPrecisionTests.Alternatives(this.Sig), this.operation1(ctx, args), this.operation2(ctx, args), new glsBuiltinPrecisionTests.Void(), new glsBuiltinPrecisionTests.Void());
   4674    }
   4675 
   4676    /**
   4677     * @constructor
   4678     * @extends {glsBuiltinPrecisionTests.DerivedFunc}
   4679     */
   4680    glsBuiltinPrecisionTests.SmoothStep = function() {
   4681        var sig = new glsBuiltinPrecisionTests.Signature('float', 'float', 'float', 'float');
   4682        glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
   4683    };
   4684 
   4685    setParentClass(glsBuiltinPrecisionTests.SmoothStep, glsBuiltinPrecisionTests.DerivedFunc);
   4686 
   4687    glsBuiltinPrecisionTests.SmoothStep.prototype.getName = function() {
   4688        return 'smoothstep';
   4689    };
   4690 
   4691    glsBuiltinPrecisionTests.SmoothStep.prototype.doExpand = function(ctx, args) {
   4692        var edge0 = args.a;
   4693        var edge1 = args.b;
   4694        var x = args.c;
   4695        var zero = new glsBuiltinPrecisionTests.Constant(0);
   4696        var one = new glsBuiltinPrecisionTests.Constant(1);
   4697        //clamp((x - edge0) / (edge1 - edge0), constant(0.0f), constant(1.0f));
   4698        var v0 = app(new glsBuiltinPrecisionTests.Sub(), x, edge0);
   4699        var v1 = app(new glsBuiltinPrecisionTests.Sub(), edge1, edge0);
   4700        var v2 = app(new glsBuiltinPrecisionTests.Div(), v0, v1);
   4701        var v3 = app(new glsBuiltinPrecisionTests.Clamp(), v2, zero, one);
   4702        var t = glsBuiltinPrecisionTests.bindExpression('float', 't', ctx, v3);
   4703        //(t * t * (constant(3.0f) - constant(2.0f) * t))
   4704        var two = new glsBuiltinPrecisionTests.Constant(2);
   4705        var three = new glsBuiltinPrecisionTests.Constant(3);
   4706        var v4 = app(new glsBuiltinPrecisionTests.Mul(), v3, v3);
   4707        var v5 = app(new glsBuiltinPrecisionTests.Mul(), two, v3);
   4708        var v6 = app(new glsBuiltinPrecisionTests.Sub(), three, v5);
   4709        var v7 = app(new glsBuiltinPrecisionTests.Mul(), v4, v6);
   4710        return v7;
   4711    };
   4712 
   4713    /**
   4714     * @constructor
   4715     * @extends {glsBuiltinPrecisionTests.DerivedFunc}
   4716     */
   4717    glsBuiltinPrecisionTests.Pow = function() {
   4718        var sig = new glsBuiltinPrecisionTests.Signature('float', 'float', 'float');
   4719        glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
   4720    };
   4721 
   4722    setParentClass(glsBuiltinPrecisionTests.Pow, glsBuiltinPrecisionTests.DerivedFunc);
   4723 
   4724    glsBuiltinPrecisionTests.Pow.prototype.getName = function() {
   4725        return 'pow';
   4726    };
   4727 
   4728    glsBuiltinPrecisionTests.Pow.prototype.doExpand = function(ctx, args) {
   4729        // exp2(y * log2(x))
   4730        var x = args.a;
   4731        var y = args.b;
   4732        var v0 = app(new glsBuiltinPrecisionTests.Log2(), x);
   4733        var v1 = app(new glsBuiltinPrecisionTests.Mul(), y, v0);
   4734        var v2 = app(new glsBuiltinPrecisionTests.Exp2(), v1);
   4735        return v2;
   4736    };
   4737 
   4738    /**
   4739     * @constructor
   4740     * @extends {glsBuiltinPrecisionTests.CFloatFunc1}
   4741     */
   4742    glsBuiltinPrecisionTests.ExpFunc = function(name, func) {
   4743        glsBuiltinPrecisionTests.CFloatFunc1.call(this, name, func);
   4744    };
   4745 
   4746    setParentClass(glsBuiltinPrecisionTests.ExpFunc, glsBuiltinPrecisionTests.CFloatFunc1);
   4747 
   4748    glsBuiltinPrecisionTests.ExpFunc.prototype.getCodomain = function() {
   4749        return tcuInterval.withNumbers(0, Infinity);
   4750    };
   4751 
   4752    glsBuiltinPrecisionTests.ExpFunc.prototype.precision = function(ctx, ret, x) {
   4753        switch (ctx.floatPrecision) {
   4754            case gluShaderUtil.precision.PRECISION_HIGHP:
   4755                return ctx.format.ulp(ret, 3.0 + 2.0 * Math.abs(x));
   4756            case gluShaderUtil.precision.PRECISION_MEDIUMP:
   4757                return ctx.format.ulp(ret, 2.0 + 2.0 * Math.abs(x));
   4758            case gluShaderUtil.precision.PRECISION_LOWP:
   4759                return ctx.format.ulp(ret, 2.0);
   4760            default:
   4761                throw new Error(!'Impossible');
   4762        }
   4763    };
   4764 
   4765   /**
   4766     * @constructor
   4767     * @extends {glsBuiltinPrecisionTests.ExpFunc}
   4768     */
   4769    glsBuiltinPrecisionTests.Exp = function() {
   4770        glsBuiltinPrecisionTests.ExpFunc.call(this, 'exp', Math.exp);
   4771    };
   4772 
   4773    setParentClass(glsBuiltinPrecisionTests.Exp, glsBuiltinPrecisionTests.ExpFunc);
   4774 
   4775   /**
   4776     * @constructor
   4777     * @extends {glsBuiltinPrecisionTests.ExpFunc}
   4778     */
   4779    glsBuiltinPrecisionTests.Exp2 = function() {
   4780        /**
   4781         * @param {number} x
   4782         * @return {number}
   4783         */
   4784        var exp2 = function(x) {
   4785            return Math.exp(x * Math.LN2);
   4786        };
   4787        glsBuiltinPrecisionTests.ExpFunc.call(this, 'exp2', exp2);
   4788    };
   4789 
   4790    setParentClass(glsBuiltinPrecisionTests.Exp2, glsBuiltinPrecisionTests.ExpFunc);
   4791 
   4792    /**
   4793     * @constructor
   4794     * @extends {glsBuiltinPrecisionTests.CFloatFunc1}
   4795     */
   4796    glsBuiltinPrecisionTests.LogFunc = function(name, func) {
   4797        glsBuiltinPrecisionTests.CFloatFunc1.call(this, name, func);
   4798    };
   4799 
   4800    setParentClass(glsBuiltinPrecisionTests.LogFunc, glsBuiltinPrecisionTests.CFloatFunc1);
   4801 
   4802    glsBuiltinPrecisionTests.LogFunc.prototype.precision = function(ctx, ret, x) {
   4803        if (x <= 0)
   4804            return NaN;
   4805        switch (ctx.floatPrecision) {
   4806            case gluShaderUtil.precision.PRECISION_HIGHP:
   4807                return (0.5 <= x && x <= 2.0) ? deMath.deLdExp(1.0, -21) : ctx.format.ulp(ret, 3.0);
   4808            case gluShaderUtil.precision.PRECISION_MEDIUMP:
   4809                return (0.5 <= x && x <= 2.0) ? deMath.deLdExp(1.0, -7) : ctx.format.ulp(ret, 2.0);
   4810            case gluShaderUtil.precision.PRECISION_LOWP:
   4811                return ctx.format.ulp(ret, 2.0);
   4812            default:
   4813                throw new Error(!'Impossible');
   4814        }
   4815    };
   4816 
   4817   /**
   4818     * @constructor
   4819     * @extends {glsBuiltinPrecisionTests.LogFunc}
   4820     */
   4821    glsBuiltinPrecisionTests.Log = function() {
   4822        glsBuiltinPrecisionTests.LogFunc.call(this, 'log', Math.log);
   4823    };
   4824 
   4825    setParentClass(glsBuiltinPrecisionTests.Log, glsBuiltinPrecisionTests.LogFunc);
   4826 
   4827   /**
   4828     * @constructor
   4829     * @extends {glsBuiltinPrecisionTests.LogFunc}
   4830     */
   4831    glsBuiltinPrecisionTests.Log2 = function() {
   4832        glsBuiltinPrecisionTests.LogFunc.call(this, 'log2', Math.log2);
   4833    };
   4834 
   4835    setParentClass(glsBuiltinPrecisionTests.Log2, glsBuiltinPrecisionTests.LogFunc);
   4836 
   4837    /**
   4838     * @constructor
   4839     * @extends {glsBuiltinPrecisionTests.CFloatFunc1}
   4840     */
   4841    glsBuiltinPrecisionTests.PreciseFunc1 = function(name, func) {
   4842        glsBuiltinPrecisionTests.CFloatFunc1.call(this, name, func);
   4843    };
   4844 
   4845    setParentClass(glsBuiltinPrecisionTests.PreciseFunc1, glsBuiltinPrecisionTests.CFloatFunc1);
   4846 
   4847    glsBuiltinPrecisionTests.PreciseFunc1.prototype.precision = function(ctx, ret, x) {
   4848        return 0;
   4849    };
   4850 
   4851    /**
   4852     * @constructor
   4853     * @extends {glsBuiltinPrecisionTests.PreciseFunc1}
   4854     */
   4855    glsBuiltinPrecisionTests.Abs = function() {
   4856        glsBuiltinPrecisionTests.PreciseFunc1.call(this, 'abs', Math.abs);
   4857    };
   4858    setParentClass(glsBuiltinPrecisionTests.Abs, glsBuiltinPrecisionTests.PreciseFunc1);
   4859 
   4860    /**
   4861     * @constructor
   4862     * @extends {glsBuiltinPrecisionTests.PreciseFunc1}
   4863     */
   4864    glsBuiltinPrecisionTests.Sign = function() {
   4865        glsBuiltinPrecisionTests.PreciseFunc1.call(this, 'sign', Math.sign);
   4866    };
   4867    setParentClass(glsBuiltinPrecisionTests.Sign, glsBuiltinPrecisionTests.PreciseFunc1);
   4868 
   4869    /**
   4870     * @constructor
   4871     * @extends {glsBuiltinPrecisionTests.PreciseFunc1}
   4872     */
   4873    glsBuiltinPrecisionTests.Floor = function() {
   4874        glsBuiltinPrecisionTests.PreciseFunc1.call(this, 'floor', Math.floor);
   4875    };
   4876    setParentClass(glsBuiltinPrecisionTests.Floor, glsBuiltinPrecisionTests.PreciseFunc1);
   4877 
   4878    /**
   4879     * @constructor
   4880     * @extends {glsBuiltinPrecisionTests.PreciseFunc1}
   4881     */
   4882    glsBuiltinPrecisionTests.RoundEven = function() {
   4883        glsBuiltinPrecisionTests.PreciseFunc1.call(this, 'roundEven', deMath.rint);
   4884    };
   4885    setParentClass(glsBuiltinPrecisionTests.RoundEven, glsBuiltinPrecisionTests.PreciseFunc1);
   4886 
   4887    /**
   4888     * @constructor
   4889     * @extends {glsBuiltinPrecisionTests.PreciseFunc1}
   4890     */
   4891    glsBuiltinPrecisionTests.Ceil = function() {
   4892        glsBuiltinPrecisionTests.PreciseFunc1.call(this, 'ceil', Math.ceil);
   4893    };
   4894    setParentClass(glsBuiltinPrecisionTests.Ceil, glsBuiltinPrecisionTests.PreciseFunc1);
   4895 
   4896    /**
   4897     * @constructor
   4898     * @extends {glsBuiltinPrecisionTests.PreciseFunc1}
   4899     */
   4900    glsBuiltinPrecisionTests.Trunc = function() {
   4901        glsBuiltinPrecisionTests.PreciseFunc1.call(this, 'trunc', Math.trunc);
   4902    };
   4903    setParentClass(glsBuiltinPrecisionTests.Trunc, glsBuiltinPrecisionTests.PreciseFunc1);
   4904 
   4905    /**
   4906     * @constructor
   4907     * @extends {glsBuiltinPrecisionTests.CFloatFunc2}
   4908     */
   4909    glsBuiltinPrecisionTests.PreciseFunc2 = function(name, func) {
   4910        glsBuiltinPrecisionTests.CFloatFunc2.call(this, name, func);
   4911    };
   4912 
   4913    setParentClass(glsBuiltinPrecisionTests.PreciseFunc2, glsBuiltinPrecisionTests.CFloatFunc2);
   4914 
   4915    glsBuiltinPrecisionTests.PreciseFunc2.prototype.precision = function(ctx, ret, x, y) {
   4916        return 0;
   4917    };
   4918 
   4919    /**
   4920     * @constructor
   4921     * @extends {glsBuiltinPrecisionTests.PreciseFunc2}
   4922     */
   4923    glsBuiltinPrecisionTests.Min = function() {
   4924        glsBuiltinPrecisionTests.PreciseFunc2.call(this, 'min', Math.min);
   4925    };
   4926    setParentClass(glsBuiltinPrecisionTests.Min, glsBuiltinPrecisionTests.PreciseFunc2);
   4927 
   4928    /**
   4929     * @constructor
   4930     * @extends {glsBuiltinPrecisionTests.PreciseFunc2}
   4931     */
   4932    glsBuiltinPrecisionTests.Max = function() {
   4933        glsBuiltinPrecisionTests.PreciseFunc2.call(this, 'max', Math.max);
   4934    };
   4935    setParentClass(glsBuiltinPrecisionTests.Max, glsBuiltinPrecisionTests.PreciseFunc2);
   4936 
   4937    /**
   4938     * @constructor
   4939     * @extends {glsBuiltinPrecisionTests.PreciseFunc2}
   4940     */
   4941    glsBuiltinPrecisionTests.Step = function() {
   4942        /**
   4943         * @param {number} edge
   4944         * @param {number} x
   4945         * return number
   4946         */
   4947        var step = function(edge, x) {
   4948            return x < edge ? 0.0 : 1.0;
   4949        };
   4950        glsBuiltinPrecisionTests.PreciseFunc2.call(this, 'step', step);
   4951    };
   4952    setParentClass(glsBuiltinPrecisionTests.Step, glsBuiltinPrecisionTests.PreciseFunc2);
   4953 
   4954    /**
   4955     * @constructor
   4956     * @extends {glsBuiltinPrecisionTests.CFloatFunc1}
   4957     */
   4958    glsBuiltinPrecisionTests.TrigFunc = function(name, func, loEx, hiEx) {
   4959        glsBuiltinPrecisionTests.CFloatFunc1.call(this, name, func);
   4960        this.m_loExtremum = loEx;
   4961        this.m_hiExtremum = hiEx;
   4962    };
   4963 
   4964    setParentClass(glsBuiltinPrecisionTests.TrigFunc, glsBuiltinPrecisionTests.CFloatFunc1);
   4965 
   4966    glsBuiltinPrecisionTests.TrigFunc.prototype.innerExtrema = function(ctx, angle) {
   4967        var lo = angle.lo();
   4968        var hi = angle.hi();
   4969        var loSlope = this.doGetSlope(lo);
   4970        var hiSlope = this.doGetSlope(hi);
   4971 
   4972        // Detect the high and low values the function can take between the
   4973        // interval endpoints.
   4974        if (angle.length() >= 2.0 * Math.PI) {
   4975            // The interval is longer than a full cycle, so it must get all possible values.
   4976            return this.m_hiExtremum.operatorOrBinary(this.m_loExtremum);
   4977        } else if (loSlope == 1 && hiSlope == -1) {
   4978            // The slope can change from positive to negative only at the maximum value.
   4979            return this.m_hiExtremum;
   4980        } else if (loSlope == -1 && hiSlope == 1) {
   4981            // The slope can change from negative to positive only at the maximum value.
   4982            return this.m_loExtremum;
   4983        } else if (loSlope == hiSlope &&
   4984                 deMath.deSign(this.applyExact(hi) - this.applyExact(lo)) * loSlope == -1) {
   4985            // The slope has changed twice between the endpoints, so both extrema are included.
   4986            return this.m_hiExtremum.operatorOrBinary(this.m_loExtremum);
   4987        }
   4988 
   4989        return new tcuInterval.Interval();
   4990    };
   4991 
   4992    glsBuiltinPrecisionTests.TrigFunc.prototype.getCodomain = function() {
   4993        // Ensure that result is always within [-1, 1], or NaN (for +-inf)
   4994        var v = tcuInterval.withIntervals(new tcuInterval.Interval(-1), new tcuInterval.Interval(1));
   4995        return v.operatorOrBinary(tcuInterval.NAN);
   4996    };
   4997 
   4998    glsBuiltinPrecisionTests.TrigFunc.prototype.precision = function(ctx, ret, arg) {
   4999        if (ctx.floatPrecision == gluShaderUtil.precision.PRECISION_HIGHP) {
   5000            // Use precision from OpenCL fast relaxed math
   5001            if (-Math.PI <= arg && arg <= Math.PI) {
   5002                return deMath.deLdExp(1.0, -11);
   5003            } else {
   5004                // "larger otherwise", let's pick |x| * 2^-12 , which is slightly over
   5005                // 2^-11 at x == pi.
   5006                return deMath.deLdExp(Math.abs(arg), -12);
   5007            }
   5008        } else if (ctx.floatPrecision == gluShaderUtil.precision.PRECISION_MEDIUMP) {
   5009            if (-Math.PI <= arg && arg <= Math.PI) {
   5010                // from OpenCL half-float extension specification
   5011                return ctx.format.ulp(ret, 2.0);
   5012            } else {
   5013                // |x| * 2^-10 , slightly larger than 2 ULP at x == pi
   5014                return deMath.deLdExp(Math.abs(arg), -10);
   5015            }
   5016        } else {
   5017            // from OpenCL half-float extension specification
   5018            return ctx.format.ulp(ret, 2.0);
   5019        }
   5020    };
   5021 
   5022    /**
   5023     * @param {number} angle
   5024     * @return number
   5025     */
   5026    glsBuiltinPrecisionTests.TrigFunc.prototype.doGetSlope = function(angle) {
   5027        throw new Error('Virtual function. Please override.');
   5028    };
   5029 
   5030    /**
   5031     * @constructor
   5032     * @extends {glsBuiltinPrecisionTests.TrigFunc}
   5033     */
   5034    glsBuiltinPrecisionTests.Sin = function() {
   5035        glsBuiltinPrecisionTests.TrigFunc.call(this, 'sin', Math.sin, new tcuInterval.Interval(-1), new tcuInterval.Interval(1));
   5036    };
   5037 
   5038    setParentClass(glsBuiltinPrecisionTests.Sin, glsBuiltinPrecisionTests.TrigFunc);
   5039 
   5040    glsBuiltinPrecisionTests.Sin.prototype.doGetSlope = function(angle) {
   5041        return deMath.deSign(Math.cos(angle));
   5042    };
   5043 
   5044    /**
   5045     * @constructor
   5046     * @extends {glsBuiltinPrecisionTests.TrigFunc}
   5047     */
   5048    glsBuiltinPrecisionTests.Cos = function() {
   5049        glsBuiltinPrecisionTests.TrigFunc.call(this, 'cos', Math.cos, new tcuInterval.Interval(-1), new tcuInterval.Interval(1));
   5050    };
   5051 
   5052    setParentClass(glsBuiltinPrecisionTests.Cos, glsBuiltinPrecisionTests.TrigFunc);
   5053 
   5054    glsBuiltinPrecisionTests.Cos.prototype.doGetSlope = function(angle) {
   5055        return -deMath.deSign(Math.sin(angle));
   5056    };
   5057 
   5058    /**
   5059     * @constructor
   5060     * @extends {glsBuiltinPrecisionTests.DerivedFunc}
   5061     */
   5062    glsBuiltinPrecisionTests.Tan = function() {
   5063        var sig = new glsBuiltinPrecisionTests.Signature('float', 'float');
   5064        glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
   5065    };
   5066 
   5067    setParentClass(glsBuiltinPrecisionTests.Tan, glsBuiltinPrecisionTests.DerivedFunc);
   5068 
   5069    glsBuiltinPrecisionTests.Tan.prototype.getName = function() {
   5070        return 'tan';
   5071    };
   5072 
   5073    glsBuiltinPrecisionTests.Tan.prototype.doExpand = function(ctx, args) {
   5074        //  sin(x) * (constant(1.0f) / cos(x)
   5075        var x = args.a;
   5076        var sin = app(new glsBuiltinPrecisionTests.Sin(), x);
   5077        var cos = app(new glsBuiltinPrecisionTests.Cos(), x);
   5078        var expr = app(new glsBuiltinPrecisionTests.Div(),
   5079                                                      new glsBuiltinPrecisionTests.Constant(1),
   5080                                                      cos);
   5081 
   5082        expr = new glsBuiltinPrecisionTests.Apply('float', new glsBuiltinPrecisionTests.Mul(),
   5083                                                    sin,
   5084                                                    expr);
   5085        return expr;
   5086    };
   5087 
   5088    /**
   5089     * @constructor
   5090     * @extends {glsBuiltinPrecisionTests.CFloatFunc1}
   5091     */
   5092    glsBuiltinPrecisionTests.ASin = function() {
   5093        glsBuiltinPrecisionTests.CFloatFunc1.call(this, 'asin', Math.asin);
   5094    };
   5095 
   5096    setParentClass(glsBuiltinPrecisionTests.ASin, glsBuiltinPrecisionTests.CFloatFunc1);
   5097 
   5098    glsBuiltinPrecisionTests.ASin.prototype.precision = function(ctx, ret, x) {
   5099        if (!deMath.deInBounds32(x, -1.0, 1.0))
   5100            return NaN;
   5101 
   5102        if (ctx.floatPrecision == gluShaderUtil.precision.PRECISION_HIGHP) {
   5103            // Absolute error of 2^-11
   5104            return deMath.deLdExp(1.0, -11);
   5105        } else {
   5106            // Absolute error of 2^-8
   5107            return deMath.deLdExp(1.0, -8);
   5108        }
   5109    };
   5110 
   5111    /**
   5112     * @constructor
   5113     * @extends {glsBuiltinPrecisionTests.CFloatFunc1}
   5114     */
   5115    glsBuiltinPrecisionTests.ArcTrigFunc = function(name, func, precisionULPs, domain, coddomain) {
   5116        glsBuiltinPrecisionTests.CFloatFunc1.call(this, name, func);
   5117        this.m_precision = precisionULPs;
   5118        this.m_domain = domain;
   5119        this.m_codomain = coddomain;
   5120    };
   5121 
   5122    setParentClass(glsBuiltinPrecisionTests.ArcTrigFunc, glsBuiltinPrecisionTests.CFloatFunc1);
   5123 
   5124    glsBuiltinPrecisionTests.ArcTrigFunc.prototype.precision = function(ctx, ret, x) {
   5125        if (!this.m_domain.contains(new tcuInterval.Interval(x)))
   5126            return NaN;
   5127 
   5128        if (ctx.floatPrecision == gluShaderUtil.precision.PRECISION_HIGHP) {
   5129            // Use OpenCL's precision
   5130            return ctx.format.ulp(ret, this.m_precision);
   5131        } else {
   5132            // Use OpenCL half-float spec
   5133            return ctx.format.ulp(ret, 2.0);
   5134        }
   5135    };
   5136 
   5137    /**
   5138     * @constructor
   5139     * @extends {glsBuiltinPrecisionTests.ArcTrigFunc}
   5140     */
   5141    glsBuiltinPrecisionTests.ACos = function() {
   5142        glsBuiltinPrecisionTests.ArcTrigFunc.call(this, 'acos', Math.acos, 4096.0,
   5143                                                tcuInterval.withNumbers(-1, 1),
   5144                                                tcuInterval.withNumbers(0, Math.PI));
   5145    };
   5146 
   5147    setParentClass(glsBuiltinPrecisionTests.ACos, glsBuiltinPrecisionTests.ArcTrigFunc);
   5148 
   5149    /**
   5150     * @constructor
   5151     * @extends {glsBuiltinPrecisionTests.ArcTrigFunc}
   5152     */
   5153    glsBuiltinPrecisionTests.ATan = function() {
   5154        glsBuiltinPrecisionTests.ArcTrigFunc.call(this, 'atan', Math.atan, 4096.0,
   5155                                                tcuInterval.unbounded(),
   5156                                                tcuInterval.withNumbers(-Math.PI * 0.5, Math.PI * 0.5));
   5157    };
   5158 
   5159    setParentClass(glsBuiltinPrecisionTests.ATan, glsBuiltinPrecisionTests.ArcTrigFunc);
   5160 
   5161    /**
   5162     * @constructor
   5163     * @extends {glsBuiltinPrecisionTests.CFloatFunc2}
   5164     */
   5165    glsBuiltinPrecisionTests.ATan2 = function() {
   5166        glsBuiltinPrecisionTests.CFloatFunc2.call(this, 'atan', Math.atan2);
   5167    };
   5168 
   5169    setParentClass(glsBuiltinPrecisionTests.ATan2, glsBuiltinPrecisionTests.CFloatFunc2);
   5170 
   5171    glsBuiltinPrecisionTests.ATan2.prototype.innerExtrema = function(ctx, xi, yi) {
   5172        var ret = new tcuInterval.Interval();
   5173 
   5174        if (yi.contains(tcuInterval.ZERO)) {
   5175            if (xi.contains(tcuInterval.ZERO))
   5176                ret.operatorOrAssignBinary(tcuInterval.NAN);
   5177            if (xi.intersects(tcuInterval.withNumbers(-Infinity, 0)))
   5178                ret.operatorOrAssignBinary(tcuInterval.withNumbers(-Math.PI, Math.PI));
   5179        }
   5180 
   5181        if (ctx.format.hasInf() != tcuFloatFormat.YesNoMaybe.YES && (!yi.isFinite() || !xi.isFinite())) {
   5182            // Infinities may not be supported, allow anything, including NaN
   5183            ret.operatorOrAssignBinary(tcuInterval.NAN);
   5184        }
   5185 
   5186        return ret;
   5187    };
   5188 
   5189    glsBuiltinPrecisionTests.ATan2.prototype.precision = function(ctx, ret, x, y) {
   5190        if (ctx.floatPrecision == gluShaderUtil.precision.PRECISION_HIGHP)
   5191            return ctx.format.ulp(ret, 4096.0);
   5192        else
   5193            return ctx.format.ulp(ret, 2.0);
   5194    };
   5195 
   5196    /**
   5197     * @constructor
   5198     * @param {number} size
   5199     * @extends {glsBuiltinPrecisionTests.DerivedFunc}
   5200     */
   5201    glsBuiltinPrecisionTests.DeterminantBase = function(size) {
   5202        var sig = new glsBuiltinPrecisionTests.Signature('float', 'mat' + size);
   5203        glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
   5204    };
   5205 
   5206    setParentClass(glsBuiltinPrecisionTests.DeterminantBase, glsBuiltinPrecisionTests.DerivedFunc);
   5207 
   5208    glsBuiltinPrecisionTests.DeterminantBase.prototype.getName = function() {
   5209        return 'determinant';
   5210    };
   5211 
   5212   /**
   5213     * @constructor
   5214     * @extends {glsBuiltinPrecisionTests.DeterminantBase}
   5215     */
   5216    glsBuiltinPrecisionTests.Determinant = function() {
   5217        // TODO: Support sizes 3 and 4
   5218        this.size = 2;
   5219        glsBuiltinPrecisionTests.DeterminantBase.call(this, this.size);
   5220    };
   5221 
   5222    setParentClass(glsBuiltinPrecisionTests.Determinant, glsBuiltinPrecisionTests.DeterminantBase);
   5223 
   5224    glsBuiltinPrecisionTests.Determinant.prototype.doExpand = function(ctx, args) {
   5225        //  mat[0][0] * mat[1][1] - mat[1][0] * mat[0][1]
   5226        var elem0_0 = new glsBuiltinPrecisionTests.MatrixVariable(args.a, 0, 0);
   5227        var elem0_1 = new glsBuiltinPrecisionTests.MatrixVariable(args.a, 0, 1);
   5228        var elem1_0 = new glsBuiltinPrecisionTests.MatrixVariable(args.a, 1, 0);
   5229        var elem1_1 = new glsBuiltinPrecisionTests.MatrixVariable(args.a, 1, 1);
   5230 
   5231        var val0 = app(new glsBuiltinPrecisionTests.Mul(), elem0_0, elem1_1);
   5232        var val1 = app(new glsBuiltinPrecisionTests.Mul(), elem0_1, elem1_0);
   5233        return new glsBuiltinPrecisionTests.Apply('float', new glsBuiltinPrecisionTests.Sub(), val0, val1);
   5234    };
   5235 
   5236    /**
   5237     * @constructor
   5238     * @extends {glsBuiltinPrecisionTests.DerivedFunc}
   5239     */
   5240    glsBuiltinPrecisionTests.Inverse = function() {
   5241        this.size = 2;
   5242        var name = 'mat' + this.size;
   5243        var sig = new glsBuiltinPrecisionTests.Signature(name, name);
   5244        glsBuiltinPrecisionTests.DerivedFunc.call(this, sig);
   5245    };
   5246 
   5247    setParentClass(glsBuiltinPrecisionTests.Inverse, glsBuiltinPrecisionTests.DerivedFunc);
   5248 
   5249    glsBuiltinPrecisionTests.Inverse.prototype.getName = function() {
   5250        return 'inverse';
   5251    };
   5252 
   5253    glsBuiltinPrecisionTests.Inverse.prototype.doExpand = function(ctx, args) {
   5254        var mat = args.a;
   5255        var v0 = app(new glsBuiltinPrecisionTests.Determinant(), mat);
   5256        var det = glsBuiltinPrecisionTests.bindExpression('float', 'det', ctx, v0);
   5257 
   5258        var elem0_0 = new glsBuiltinPrecisionTests.MatrixVariable(args.a, 0, 0);
   5259        var elem0_1 = new glsBuiltinPrecisionTests.MatrixVariable(args.a, 0, 1);
   5260        var elem1_0 = new glsBuiltinPrecisionTests.MatrixVariable(args.a, 1, 0);
   5261        var elem1_1 = new glsBuiltinPrecisionTests.MatrixVariable(args.a, 1, 1);
   5262 
   5263        var result0_0 = app(new glsBuiltinPrecisionTests.Div(), elem1_1, det);
   5264        var result0_1 = app(new glsBuiltinPrecisionTests.Div(), elem0_1, det);
   5265        result0_1 = app(new glsBuiltinPrecisionTests.Negate(), result0_1);
   5266        var result1_0 = app(new glsBuiltinPrecisionTests.Div(), elem1_0, det);
   5267        result1_0 = app(new glsBuiltinPrecisionTests.Negate(), result1_0);
   5268        var result1_1 = app(new glsBuiltinPrecisionTests.Div(), elem0_0, det);
   5269 
   5270        var col0 = app(new glsBuiltinPrecisionTests.GenVec(this.size, true), result0_0, result1_0);
   5271        var col1 = app(new glsBuiltinPrecisionTests.GenVec(this.size, true), result0_1, result1_1);
   5272        var ret = app(new glsBuiltinPrecisionTests.GenMat(this.size, this.size), col0, col1);
   5273 
   5274        return ret;
   5275    };
   5276 
   5277    /**
   5278     * @param {glsBuiltinPrecisionTests.PrecisionTestContext} ctx
   5279     * @param {glsBuiltinPrecisionTests.CaseFactory} factory
   5280     * @return {tcuTestCase.DeqpTest}
   5281     */
   5282    glsBuiltinPrecisionTests.createFuncGroup = function(ctx, factory) {
   5283        /** @type {tcuTestCase.DeqpTest} */ var group = tcuTestCase.newTest(factory.getName(), factory.getDesc());
   5284 
   5285        for (var precNdx in gluShaderUtil.precision) {
   5286            /** @type {gluShaderUtil.precision} */ var precision = gluShaderUtil.precision[precNdx];
   5287            /** @type {string} */ var precName = gluShaderUtil.getPrecisionName(precision);
   5288            /** @type {tcuFloatFormat.FloatFormat} */ var fmt = ctx.formats[precision];
   5289            /** @type {tcuFloatFormat.FloatFormat} */ var highpFmt = ctx.formats[gluShaderUtil.precision.PRECISION_HIGHP];
   5290 
   5291            for (var shaderNdx in ctx.shaderTypes) {
   5292                /** @type {gluShaderProgram.shaderType} */ var shaderType = ctx.shaderTypes[shaderNdx];
   5293                /** @type {string} */ var shaderName = gluShaderProgram.getShaderTypeName(shaderType);
   5294                /** @type {string} */ var name = precName + '_' + shaderName;
   5295                /** @type {glsBuiltinPrecisionTests.Context} */ var caseCtx = new glsBuiltinPrecisionTests.Context(name, fmt, highpFmt,
   5296                                                 precision, shaderType, ctx.numRandoms);
   5297 
   5298                group.addChild(factory.createCase(caseCtx));
   5299            }
   5300        }
   5301 
   5302        return group;
   5303    };
   5304 
   5305    /**
   5306     * @param {glsBuiltinPrecisionTests.CaseFactories} cases
   5307     * @param {Array<gluShaderProgram.shaderType>} shaderTypes
   5308     * @param {tcuTestCase.DeqpTest} dstGroup
   5309     */
   5310    glsBuiltinPrecisionTests.addBuiltinPrecisionTests = function(cases, shaderTypes, dstGroup) {
   5311        /** @type {tcuFloatFormat.FloatFormat} */ var highp = new tcuFloatFormat.FloatFormat(-126, 127, 23, true,
   5312                                                 tcuFloatFormat.YesNoMaybe.MAYBE, // subnormals
   5313                                                 tcuFloatFormat.YesNoMaybe.YES, // infinities
   5314                                                 tcuFloatFormat.YesNoMaybe.MAYBE); // NaN
   5315        // \todo [2014-04-01 lauri] Check these once Khronos bug 11840 is resolved.
   5316        /** @type {tcuFloatFormat.FloatFormat} */ var mediump = new tcuFloatFormat.FloatFormat(-13, 13, 9, false);
   5317        // A fixed-point format is just a floating point format with a fixed
   5318        // exponent and support for subnormals.
   5319        /** @type {tcuFloatFormat.FloatFormat} */ var lowp = new tcuFloatFormat.FloatFormat(0, 0, 7, false, tcuFloatFormat.YesNoMaybe.YES);
   5320        /** @type {glsBuiltinPrecisionTests.PrecisionTestContext} */ var ctx = new glsBuiltinPrecisionTests.PrecisionTestContext(highp, mediump, lowp,
   5321                                                 shaderTypes, 16384);
   5322 
   5323        for (var ndx = 0; ndx < cases.getFactories().length; ++ndx)
   5324            dstGroup.addChild(glsBuiltinPrecisionTests.createFuncGroup(ctx, cases.getFactories()[ndx]));
   5325    };
   5326 
   5327    /**
   5328     * @param {function(new:glsBuiltinPrecisionTests.Func)} F
   5329     * @param {glsBuiltinPrecisionTests.CaseFactories} funcs
   5330     * @param {string=} name
   5331     */
   5332    glsBuiltinPrecisionTests.addScalarFactory = function(F, funcs, name) {
   5333        if (name === undefined)
   5334            name = (new F()).getName();
   5335 
   5336        funcs.addFactory(new glsBuiltinPrecisionTests.GenFuncCaseFactory(glsBuiltinPrecisionTests.makeVectorizedFuncs(F), name));
   5337    };
   5338 
   5339    /**
   5340     * @param {function(new:glsBuiltinPrecisionTests.Func)} F
   5341     */
   5342    glsBuiltinPrecisionTests.createSimpleFuncCaseFactory = function(F) {
   5343        return new glsBuiltinPrecisionTests.SimpleFuncCaseFactory(new F());
   5344    };
   5345 
   5346    /**
   5347     * @param {number} caseId test case Id
   5348     * @return {glsBuiltinPrecisionTests.CaseFactories}
   5349     */
   5350    glsBuiltinPrecisionTests.createES3BuiltinCases = function(caseId) {
   5351        /** @type {glsBuiltinPrecisionTests.CaseFactories} */ var funcs = new glsBuiltinPrecisionTests.BuiltinFuncs();
   5352 
   5353        switch (caseId) {
   5354            case 0: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Add, funcs); break;
   5355            case 1: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Sub, funcs); break;
   5356            case 2: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Mul, funcs); break;
   5357            case 3: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Div, funcs); break;
   5358            case 4: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Radians, funcs); break;
   5359            case 5: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Degrees, funcs); break;
   5360            case 6: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Sin, funcs); break;
   5361            case 7: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Cos, funcs); break;
   5362            case 8: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Tan, funcs); break;
   5363            case 9: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.ASin, funcs); break;
   5364            case 10: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.ACos, funcs); break;
   5365            case 11: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.ATan, funcs); break;
   5366            case 12: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.ATan2, funcs, 'atan2'); break;
   5367            case 13: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Sinh, funcs); break;
   5368            case 14: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Cosh, funcs); break;
   5369            case 15: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Tanh, funcs); break;
   5370            case 16: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.ASinh, funcs); break;
   5371            case 17: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.ACosh, funcs); break;
   5372            case 18: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.ATanh, funcs); break;
   5373            case 19: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Pow, funcs); break;
   5374            case 20: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Exp, funcs); break;
   5375            case 21: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Exp2, funcs); break;
   5376            case 22: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Log, funcs); break;
   5377            case 23: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Log2, funcs); break;
   5378            case 24: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Sqrt, funcs); break;
   5379            case 25: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.InverseSqrt, funcs); break;
   5380            case 26: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Abs, funcs); break;
   5381            case 27: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Sign, funcs); break;
   5382            case 28: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Floor, funcs); break;
   5383            case 29: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Trunc, funcs); break;
   5384            case 30: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Round, funcs); break;
   5385            case 31: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.RoundEven, funcs); break;
   5386            case 32: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Ceil, funcs); break;
   5387            case 33: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Fract, funcs); break;
   5388            case 34: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Mod, funcs); break;
   5389            case 35: funcs.addFactory(glsBuiltinPrecisionTests.createSimpleFuncCaseFactory(glsBuiltinPrecisionTests.Modf)); break;
   5390            case 36: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Min, funcs); break;
   5391            case 37: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Max, funcs); break;
   5392            case 38: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Mix, funcs); break;
   5393            case 39: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Step, funcs); break;
   5394            case 40: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.SmoothStep, funcs); break;
   5395            case 41: glsBuiltinPrecisionTests.addScalarFactory(glsBuiltinPrecisionTests.Clamp, funcs); break;
   5396            case 42: funcs.addFactory(new glsBuiltinPrecisionTests.TemplateFuncCaseFactory(glsBuiltinPrecisionTests.Length)); break;
   5397            case 43: funcs.addFactory(new glsBuiltinPrecisionTests.TemplateFuncCaseFactory(glsBuiltinPrecisionTests.Distance)); break;
   5398            case 44: funcs.addFactory(new glsBuiltinPrecisionTests.TemplateFuncCaseFactory(glsBuiltinPrecisionTests.Dot)); break;
   5399            case 45: funcs.addFactory(glsBuiltinPrecisionTests.createSimpleFuncCaseFactory(glsBuiltinPrecisionTests.Cross)); break;
   5400            case 46: funcs.addFactory(new glsBuiltinPrecisionTests.TemplateFuncCaseFactory(glsBuiltinPrecisionTests.Normalize)); break;
   5401            case 47: funcs.addFactory(new glsBuiltinPrecisionTests.TemplateFuncCaseFactory(glsBuiltinPrecisionTests.FaceForward)); break;
   5402            case 48: funcs.addFactory(new glsBuiltinPrecisionTests.TemplateFuncCaseFactory(glsBuiltinPrecisionTests.Reflect)); break;
   5403            case 49: funcs.addFactory(new glsBuiltinPrecisionTests.TemplateFuncCaseFactory(glsBuiltinPrecisionTests.Refract)); break;
   5404            case 50: funcs.addFactory(new glsBuiltinPrecisionTests.MatrixFuncCaseFactory(glsBuiltinPrecisionTests.MatrixCompMult)); break;
   5405            case 51: funcs.addFactory(new glsBuiltinPrecisionTests.MatrixFuncCaseFactory(glsBuiltinPrecisionTests.OuterProduct)); break;
   5406            case 52: funcs.addFactory(new glsBuiltinPrecisionTests.MatrixFuncCaseFactory(glsBuiltinPrecisionTests.Transpose)); break;
   5407            case 53: funcs.addFactory(new glsBuiltinPrecisionTests.SquareMatrixFuncCaseFactory(glsBuiltinPrecisionTests.Determinant)); break;
   5408            case 54: funcs.addFactory(new glsBuiltinPrecisionTests.SquareMatrixFuncCaseFactory(glsBuiltinPrecisionTests.Inverse)); break;
   5409            default: break;
   5410        }
   5411 
   5412        return funcs;
   5413    };
   5414 
   5415 });