tor-browser

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

tcuFloat.js (30890B)


      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('framework.common.tcuFloat');
     23 goog.require('framework.delibs.debase.deMath');
     24 
     25 goog.scope(function() {
     26 
     27 var tcuFloat = framework.common.tcuFloat;
     28 var deMath = framework.delibs.debase.deMath;
     29 
     30 var DE_ASSERT = function(x) {
     31    if (!x)
     32        throw new Error('Assert failed');
     33 };
     34 
     35 tcuFloat.FloatFlags = {
     36    FLOAT_HAS_SIGN: (1 << 0),
     37    FLOAT_SUPPORT_DENORM: (1 << 1)
     38 };
     39 
     40 /**
     41 * Defines a tcuFloat.FloatDescription object, which is an essential part of the tcuFloat.deFloat type.
     42 * Holds the information that shapes the tcuFloat.deFloat.
     43 * @constructor
     44 */
     45 tcuFloat.FloatDescription = function(exponentBits, mantissaBits, exponentBias, flags) {
     46    this.ExponentBits = exponentBits;
     47    this.MantissaBits = mantissaBits;
     48    this.ExponentBias = exponentBias;
     49    this.Flags = flags;
     50 
     51    this.totalBitSize = 1 + this.ExponentBits + this.MantissaBits;
     52    this.totalByteSize = Math.floor(this.totalBitSize / 8) + ((this.totalBitSize % 8) > 0 ? 1 : 0);
     53 };
     54 
     55 /**
     56 * Builds a zero float of the current binary description.
     57 * @param {number} sign
     58 * @return {tcuFloat.deFloat}
     59 */
     60 tcuFloat.FloatDescription.prototype.zero = function(sign) {
     61    return tcuFloat.newDeFloatFromParameters(this.zeroNumber(sign), this);
     62 };
     63 
     64 tcuFloat.FloatDescription.prototype.zeroNumber = function(sign) {
     65    return deMath.shiftLeft((sign > 0 ? 0 : 1), (this.ExponentBits + this.MantissaBits));
     66 };
     67 
     68 /**
     69 * Builds an infinity float representation of the current binary description.
     70 * @param {number} sign
     71 * @return {tcuFloat.deFloat}
     72 */
     73 tcuFloat.FloatDescription.prototype.inf = function(sign) {
     74    return tcuFloat.newDeFloatFromParameters(this.infNumber(sign), this);
     75 };
     76 
     77 tcuFloat.FloatDescription.prototype.infNumber = function(sign) {
     78    return ((sign > 0 ? 0 : 1) << (this.ExponentBits + this.MantissaBits)) |
     79        deMath.shiftLeft(((1 << this.ExponentBits) - 1), this.MantissaBits); //Unless using very large exponent types, native shift is safe here, i guess.
     80 };
     81 
     82 /**
     83 * Builds a NaN float representation of the current binary description.
     84 * @return {tcuFloat.deFloat}
     85 */
     86 tcuFloat.FloatDescription.prototype.nan = function() {
     87    return tcuFloat.newDeFloatFromParameters(this.nanNumber(), this);
     88 };
     89 
     90 tcuFloat.FloatDescription.prototype.nanNumber = function() {
     91    return deMath.shiftLeft(1, (this.ExponentBits + this.MantissaBits)) - 1;
     92 };
     93 
     94 /**
     95 * Builds a tcuFloat.deFloat number based on the description and the given
     96 * sign, exponent and mantissa values.
     97 * @param {number} sign
     98 * @param {number} exponent
     99 * @param {number} mantissa
    100 * @return {tcuFloat.deFloat}
    101 */
    102 tcuFloat.FloatDescription.prototype.construct = function(sign, exponent, mantissa) {
    103    // Repurpose this otherwise invalid input as a shorthand notation for zero (no need for caller to care about internal representation)
    104    /** @type {boolean} */ var isShorthandZero = exponent == 0 && mantissa == 0;
    105 
    106    // Handles the typical notation for zero (min exponent, mantissa 0). Note that the exponent usually used exponent (-ExponentBias) for zero/subnormals is not used.
    107    // Instead zero/subnormals have the (normally implicit) leading mantissa bit set to zero.
    108 
    109    /** @type {boolean} */ var isDenormOrZero = (exponent == 1 - this.ExponentBias) && (deMath.shiftRight(mantissa, this.MantissaBits) == 0);
    110    /** @type {number} */ var s = deMath.shiftLeft((sign < 0 ? 1 : 0), (this.ExponentBits + this.MantissaBits));
    111    /** @type {number} */ var exp = (isShorthandZero || isDenormOrZero) ? 0 : exponent + this.ExponentBias;
    112 
    113    DE_ASSERT(sign == +1 || sign == -1);
    114    DE_ASSERT(isShorthandZero || isDenormOrZero || deMath.shiftRight(mantissa, this.MantissaBits) == 1);
    115    DE_ASSERT((exp >> this.ExponentBits) == 0); //Native shift is safe
    116 
    117    return tcuFloat.newDeFloatFromParameters(
    118        deMath.binaryOp(
    119            deMath.binaryOp(
    120                s,
    121                deMath.shiftLeft(exp, this.MantissaBits),
    122                deMath.BinaryOp.OR
    123            ),
    124            deMath.binaryOp(
    125                mantissa,
    126                deMath.shiftLeft(1, this.MantissaBits) - 1,
    127                deMath.BinaryOp.AND
    128            ),
    129            deMath.BinaryOp.OR
    130        ),
    131        this
    132    );
    133 };
    134 
    135 /**
    136 * Builds a tcuFloat.deFloat number based on the description and the given
    137 * sign, exponent and binary mantissa values.
    138 * @param {number} sign
    139 * @param {number} exponent
    140 * @param {number} mantissaBits The raw binary representation.
    141 * @return {tcuFloat.deFloat}
    142 */
    143 tcuFloat.FloatDescription.prototype.constructBits = function(sign, exponent, mantissaBits) {
    144    /** @type {number} */ var signBit = sign < 0 ? 1 : 0;
    145    /** @type {number} */ var exponentBits = exponent + this.ExponentBias;
    146 
    147    DE_ASSERT(sign == +1 || sign == -1);
    148    DE_ASSERT((exponentBits >> this.ExponentBits) == 0);
    149    DE_ASSERT(deMath.shiftRight(mantissaBits, this.MantissaBits) == 0);
    150 
    151    return tcuFloat.newDeFloatFromParameters(
    152        deMath.binaryOp(
    153            deMath.binaryOp(
    154                deMath.shiftLeft(
    155                    signBit,
    156                    this.ExponentBits + this.MantissaBits
    157                ),
    158                deMath.shiftLeft(exponentBits, this.MantissaBits),
    159                deMath.BinaryOp.OR
    160            ),
    161            mantissaBits,
    162            deMath.BinaryOp.OR
    163        ),
    164        this
    165    );
    166 };
    167 
    168 /**
    169 * Converts a tcuFloat.deFloat from it's own format description into the format described
    170 * by this description.
    171 * @param {tcuFloat.deFloat} other Other float to convert to this format description.
    172 * @return {tcuFloat.deFloat} converted tcuFloat.deFloat
    173 */
    174 tcuFloat.FloatDescription.prototype.convert = function(other) {
    175    /** @type {number} */ var otherExponentBits = other.description.ExponentBits;
    176    /** @type {number} */ var otherMantissaBits = other.description.MantissaBits;
    177    /** @type {number} */ var otherExponentBias = other.description.ExponentBias;
    178    /** @type {number} */ var otherFlags = other.description.Flags;
    179 
    180    /** @type {number} */ var bitDiff;
    181    /** @type {number} */ var half;
    182    /** @type {number} */ var bias;
    183 
    184    if (!(this.Flags & tcuFloat.FloatFlags.FLOAT_HAS_SIGN) && other.sign() < 0) {
    185        // Negative number, truncate to zero.
    186        return this.zero(+1);
    187    } else if (other.isInf()) {
    188        return this.inf(other.sign());
    189    } else if (other.isNaN()) {
    190        return this.nan();
    191    } else if (other.isZero()) {
    192        return this.zero(other.sign());
    193    } else {
    194        /** @type {number} */ var eMin = 1 - this.ExponentBias;
    195        /** @type {number} */ var eMax = ((1 << this.ExponentBits) - 2) - this.ExponentBias;
    196 
    197        /** @type {number} */ var s = deMath.shiftLeft(other.signBit(), (this.ExponentBits + this.MantissaBits)); // \note Not sign, but sign bit.
    198        /** @type {number} */ var e = other.exponent();
    199        /** @type {number} */ var m = other.mantissa();
    200 
    201        // Normalize denormalized values prior to conversion.
    202        while (!deMath.binaryOp(m, deMath.shiftLeft(1, otherMantissaBits), deMath.BinaryOp.AND)) {
    203            m = deMath.shiftLeft(m, 1);
    204            e -= 1;
    205        }
    206 
    207        if (e < eMin) {
    208            // Underflow.
    209            if ((this.Flags & tcuFloat.FloatFlags.FLOAT_SUPPORT_DENORM) && (eMin - e - 1 <= this.MantissaBits)) {
    210                // Shift and round (RTE).
    211                bitDiff = (otherMantissaBits - this.MantissaBits) + (eMin - e);
    212                half = deMath.shiftLeft(1, (bitDiff - 1)) - 1;
    213                bias = deMath.binaryOp(deMath.shiftRight(m, bitDiff), 1, deMath.BinaryOp.AND);
    214 
    215                return tcuFloat.newDeFloatFromParameters(
    216                    deMath.binaryOp(
    217                        s,
    218                        deMath.shiftRight(
    219                            m + half + bias,
    220                            bitDiff
    221                        ),
    222                        deMath.BinaryOp.OR
    223                    ),
    224                    this
    225                );
    226            } else
    227                return this.zero(other.sign());
    228        } else {
    229            // Remove leading 1.
    230            m = deMath.binaryOp(m, deMath.binaryNot(deMath.shiftLeft(1, otherMantissaBits)), deMath.BinaryOp.AND);
    231 
    232            if (this.MantissaBits < otherMantissaBits) {
    233                // Round mantissa (round to nearest even).
    234                bitDiff = otherMantissaBits - this.MantissaBits;
    235                half = deMath.shiftLeft(1, (bitDiff - 1)) - 1;
    236                bias = deMath.binaryOp(deMath.shiftRight(m, bitDiff), 1, deMath.BinaryOp.AND);
    237 
    238                m = deMath.shiftRight(m + half + bias, bitDiff);
    239 
    240                if (deMath.binaryOp(m, deMath.shiftLeft(1, this.MantissaBits), deMath.BinaryOp.AND)) {
    241                    // Overflow in mantissa.
    242                    m = 0;
    243                    e += 1;
    244                }
    245            } else {
    246                bitDiff = this.MantissaBits - otherMantissaBits;
    247                m = deMath.shiftLeft(m, bitDiff);
    248            }
    249 
    250            if (e > eMax) {
    251                // Overflow.
    252                return this.inf(other.sign());
    253            } else {
    254                DE_ASSERT(deMath.deInRange32(e, eMin, eMax));
    255                DE_ASSERT(deMath.binaryOp((e + this.ExponentBias), deMath.binaryNot(deMath.shiftLeft(1, this.ExponentBits) - 1), deMath.BinaryOp.AND) == 0);
    256                DE_ASSERT(deMath.binaryOp(m, deMath.binaryNot(deMath.shiftLeft(1, this.MantissaBits) - 1), deMath.BinaryOp.AND) == 0);
    257 
    258                return tcuFloat.newDeFloatFromParameters(
    259                    deMath.binaryOp(
    260                        deMath.binaryOp(
    261                            s,
    262                            deMath.shiftLeft(
    263                                e + this.ExponentBias,
    264                                this.MantissaBits
    265                            ),
    266                            deMath.BinaryOp.OR
    267                        ),
    268                        m,
    269                        deMath.BinaryOp.OR
    270                    ),
    271                    this
    272                );
    273            }
    274        }
    275    }
    276 };
    277 
    278 /**
    279 * tcuFloat.deFloat class - Empty constructor, builds a 32 bit float by default
    280 * @constructor
    281 */
    282 tcuFloat.deFloat = function() {
    283    this.description = tcuFloat.description32;
    284 
    285    this.m_buffer = null;
    286    this.m_array = null;
    287    this.m_array32 = null;
    288    this.bitValue = undefined;
    289    this.signValue = undefined;
    290    this.expValue = undefined;
    291    this.mantissaValue = undefined;
    292 
    293    this.m_value = 0;
    294 };
    295 
    296 /**
    297 * buffer - Get the deFloat's existing ArrayBuffer or create one if none exists.
    298 * @return {ArrayBuffer}
    299 */
    300 tcuFloat.deFloat.prototype.buffer = function() {
    301    if (!this.m_buffer)
    302        this.m_buffer = new ArrayBuffer(this.description.totalByteSize);
    303    return this.m_buffer;
    304 };
    305 
    306 /**
    307 * array - Get the deFloat's existing Uint8Array or create one if none exists.
    308 * @return {Uint8Array}
    309 */
    310 tcuFloat.deFloat.prototype.array = function() {
    311    if (!this.m_array)
    312        this.m_array = new Uint8Array(this.buffer());
    313    return this.m_array;
    314 };
    315 
    316 /**
    317 * array32 - Get the deFloat's existing Uint32Array or create one if none exists.
    318 * @return {Uint32Array}
    319 */
    320 tcuFloat.deFloat.prototype.array32 = function() {
    321    if (!this.m_array32)
    322        this.m_array32 = new Uint32Array(this.buffer());
    323    return this.m_array32;
    324 };
    325 
    326 /**
    327 * deFloatNumber - To be used immediately after constructor
    328 * Builds a 32-bit tcuFloat.deFloat based on a 64-bit JS number.
    329 * @param {number} jsnumber
    330 * @return {tcuFloat.deFloat}
    331 */
    332 tcuFloat.deFloat.prototype.deFloatNumber = function(jsnumber) {
    333    var view32 = new DataView(this.buffer());
    334    view32.setFloat32(0, jsnumber, true); //little-endian
    335    this.m_value = view32.getFloat32(0, true); //little-endian
    336 
    337    // Clear cached values
    338    this.bitValue = undefined;
    339    this.signValue = undefined;
    340    this.expValue = undefined;
    341    this.mantissaValue = undefined;
    342 
    343    return this;
    344 };
    345 
    346 /**
    347 * deFloatNumber64 - To be used immediately after constructor
    348 * Builds a 64-bit tcuFloat.deFloat based on a 64-bit JS number.
    349 * @param {number} jsnumber
    350 * @return {tcuFloat.deFloat}
    351 */
    352 tcuFloat.deFloat.prototype.deFloatNumber64 = function(jsnumber) {
    353    var view64 = new DataView(this.buffer());
    354    view64.setFloat64(0, jsnumber, true); //little-endian
    355    this.m_value = view64.getFloat64(0, true); //little-endian
    356 
    357    // Clear cached values
    358    this.bitValue = undefined;
    359    this.signValue = undefined;
    360    this.expValue = undefined;
    361    this.mantissaValue = undefined;
    362 
    363    return this;
    364 };
    365 
    366 /**
    367 * Convenience function to build a 32-bit tcuFloat.deFloat based on a 64-bit JS number
    368 * Builds a 32-bit tcuFloat.deFloat based on a 64-bit JS number.
    369 * @param {number} jsnumber
    370 * @return {tcuFloat.deFloat}
    371 */
    372 tcuFloat.newDeFloatFromNumber = function(jsnumber) {
    373    return new tcuFloat.deFloat().deFloatNumber(jsnumber);
    374 };
    375 
    376 /**
    377 * deFloatBuffer - To be used immediately after constructor
    378 * Builds a tcuFloat.deFloat based on a buffer and a format description.
    379 * The buffer is assumed to contain data of the given description.
    380 * @param {ArrayBuffer} buffer
    381 * @param {tcuFloat.FloatDescription} description
    382 * @return {tcuFloat.deFloat}
    383 */
    384 tcuFloat.deFloat.prototype.deFloatBuffer = function(buffer, description) {
    385    this.m_buffer = buffer;
    386    this.m_array = new Uint8Array(this.m_buffer);
    387    this.m_array32 = new Uint32Array(this.m_buffer);
    388 
    389    this.m_value = deMath.arrayToNumber(this.m_array);
    390 
    391    // Clear cached values
    392    this.bitValue = undefined;
    393    this.signValue = undefined;
    394    this.expValue = undefined;
    395    this.mantissaValue = undefined;
    396 
    397    return this;
    398 };
    399 
    400 /**
    401 * Convenience function to build a tcuFloat.deFloat based on a buffer and a format description
    402 * The buffer is assumed to contain data of the given description.
    403 * @param {ArrayBuffer} buffer
    404 * @param {tcuFloat.FloatDescription} description
    405 * @return {tcuFloat.deFloat}
    406 */
    407 tcuFloat.newDeFloatFromBuffer = function(buffer, description) {
    408    return new tcuFloat.deFloat().deFloatBuffer(buffer, description);
    409 };
    410 
    411 /**
    412 * Set the tcuFloat.deFloat from the given bitwise representation.
    413 *
    414 * @param {number} jsnumber  This is taken to be the bitwise representation of
    415 *   the floating point number represented by this deFloat. It must be an
    416 *   integer, less than 2^52, and compatible with the existing description.
    417 * @return {tcuFloat.deFloat}
    418 **/
    419 tcuFloat.deFloat.prototype.deFloatParametersNumber = function(jsnumber) {
    420    /** @type {number} */ var jsnumberMax = -1 >>> (32 - this.description.totalBitSize);
    421    DE_ASSERT(Number.isInteger(jsnumber) && jsnumber <= jsnumberMax);
    422 
    423    this.m_value = jsnumber;
    424    deMath.numberToArray(this.m_array, jsnumber);
    425 
    426    // Clear cached values
    427    this.bitValue = undefined;
    428    this.signValue = undefined;
    429    this.expValue = undefined;
    430    this.mantissaValue = undefined;
    431 
    432    return this;
    433 };
    434 
    435 /**
    436 * Initializes a tcuFloat.deFloat from the given bitwise representation,
    437 * with the specified format description.
    438 *
    439 * @param {number} jsnumber  This is taken to be the bitwise representation of
    440 *   the floating point number represented by this deFloat. It must be an
    441 *   integer, less than 2^52, and compatible with the new description.
    442 * @param {tcuFloat.FloatDescription} description
    443 * @return {tcuFloat.deFloat}
    444 **/
    445 tcuFloat.deFloat.prototype.deFloatParameters = function(jsnumber, description) {
    446    /** @type {number} */ var maxUint52 = 0x10000000000000;
    447    DE_ASSERT(Number.isInteger(jsnumber) && jsnumber < maxUint52);
    448    if (description.totalBitSize > 52) {
    449        // The jsnumber representation for this number can't possibly be valid.
    450        // Make sure it has a sentinel 0 value.
    451        DE_ASSERT(jsnumber === 0);
    452    }
    453 
    454    this.description = description;
    455 
    456    this.m_buffer = new ArrayBuffer(this.description.totalByteSize);
    457    this.m_array = new Uint8Array(this.m_buffer);
    458 
    459    return this.deFloatParametersNumber(jsnumber);
    460 };
    461 
    462 /**
    463 * Convenience function. Creates a tcuFloat.deFloat, then initializes it from
    464 * the given bitwise representation, with the specified format description.
    465 *
    466 * @param {number} jsnumber  This is taken to be the bitwise representation of
    467 *   the floating point number represented by this deFloat. It must be an
    468 *   integer, less than 2^52, and compatible with the new description.
    469 * @param {tcuFloat.FloatDescription} description
    470 * @return {tcuFloat.deFloat}
    471 **/
    472 tcuFloat.newDeFloatFromParameters = function(jsnumber, description) {
    473    return new tcuFloat.deFloat().deFloatParameters(jsnumber, description);
    474 };
    475 
    476 /**
    477 * Returns bit range [begin, end)
    478 * @param {number} begin
    479 * @param {number} end
    480 * @return {number}
    481 */
    482 tcuFloat.deFloat.prototype.getBitRange = function(begin, end) {
    483    if (this.description.totalBitSize <= 52) {
    484        // this.bits() is invalid for more than 52 bits.
    485        return deMath.getBitRange(this.bits(), begin, end);
    486    } else {
    487        return deMath.getArray32BitRange(this.array32(), begin, end);
    488    }
    489 };
    490 
    491 /**
    492 * Returns the raw binary representation value of the tcuFloat.deFloat
    493 * @return {number}
    494 */
    495 tcuFloat.deFloat.prototype.bits = function() {
    496    if (typeof this.bitValue === 'undefined')
    497        this.bitValue = deMath.arrayToNumber(this.array());
    498    return this.bitValue;
    499 };
    500 
    501 /**
    502 * Returns the raw binary sign bit
    503 * @return {number}
    504 */
    505 tcuFloat.deFloat.prototype.signBit = function() {
    506    if (typeof this.signValue === 'undefined')
    507        this.signValue = this.getBitRange(this.description.totalBitSize - 1, this.description.totalBitSize);
    508    return this.signValue;
    509 };
    510 
    511 /**
    512 * Returns the raw binary exponent bits
    513 * @return {number}
    514 */
    515 tcuFloat.deFloat.prototype.exponentBits = function() {
    516    if (typeof this.expValue === 'undefined')
    517        this.expValue = this.getBitRange(this.description.MantissaBits, this.description.MantissaBits + this.description.ExponentBits);
    518    return this.expValue;
    519 };
    520 
    521 /**
    522 * Returns the raw binary mantissa bits
    523 * @return {number}
    524 */
    525 tcuFloat.deFloat.prototype.mantissaBits = function() {
    526    if (typeof this.mantissaValue === 'undefined')
    527        this.mantissaValue = this.getBitRange(0, this.description.MantissaBits);
    528    return this.mantissaValue;
    529 };
    530 
    531 /**
    532 * Returns the sign as a factor (-1 or 1)
    533 * @return {number}
    534 */
    535 tcuFloat.deFloat.prototype.sign = function() {
    536    var sign = this.signBit();
    537    var signvalue = sign ? -1 : 1;
    538    return signvalue;
    539 };
    540 
    541 /**
    542 * Returns the real exponent, checking if it's a denorm or zero number or not
    543 * @return {number}
    544 */
    545 tcuFloat.deFloat.prototype.exponent = function() {return this.isDenorm() ? 1 - this.description.ExponentBias : this.exponentBits() - this.description.ExponentBias;};
    546 
    547 /**
    548 * Returns the (still raw) mantissa, checking if it's a denorm or zero number or not
    549 * Makes the normally implicit bit explicit.
    550 * @return {number}
    551 */
    552 tcuFloat.deFloat.prototype.mantissa = function() {return this.isZero() || this.isDenorm() ? this.mantissaBits() : deMath.binaryOp(this.mantissaBits(), deMath.shiftLeft(1, this.description.MantissaBits), deMath.BinaryOp.OR);};
    553 
    554 /**
    555 * Returns if the number is infinity or not.
    556 * @return {boolean}
    557 */
    558 tcuFloat.deFloat.prototype.isInf = function() {return this.exponentBits() == ((1 << this.description.ExponentBits) - 1) && this.mantissaBits() == 0;};
    559 
    560 /**
    561 * Returns if the number is NaN or not.
    562 * @return {boolean}
    563 */
    564 tcuFloat.deFloat.prototype.isNaN = function() {return this.exponentBits() == ((1 << this.description.ExponentBits) - 1) && this.mantissaBits() != 0;};
    565 
    566 /**
    567 * Returns if the number is zero or not.
    568 * @return {boolean}
    569 */
    570 tcuFloat.deFloat.prototype.isZero = function() {return this.exponentBits() == 0 && this.mantissaBits() == 0;};
    571 
    572 /**
    573 * Returns if the number is denormalized or not.
    574 * @return {boolean}
    575 */
    576 tcuFloat.deFloat.prototype.isDenorm = function() {return this.exponentBits() == 0 && this.mantissaBits() != 0;};
    577 
    578 /**
    579 * Builds a zero float of the current binary description.
    580 * @param {number} sign
    581 * @return {tcuFloat.deFloat}
    582 */
    583 tcuFloat.deFloat.prototype.zero = function(sign) {
    584    return this.description.zero(sign);
    585 };
    586 
    587 /**
    588 * Builds an infinity float representation of the current binary description.
    589 * @param {number} sign
    590 * @return {tcuFloat.deFloat}
    591 */
    592 tcuFloat.deFloat.prototype.inf = function(sign) {
    593    return this.description.inf(sign);
    594 };
    595 
    596 /**
    597 * Builds a NaN float representation of the current binary description.
    598 * @return {tcuFloat.deFloat}
    599 */
    600 tcuFloat.deFloat.prototype.nan = function() {
    601    return this.description.nan();
    602 };
    603 
    604 /**
    605 * Builds a float of the current binary description.
    606 * Given a sign, exponent and mantissa.
    607 * @param {number} sign
    608 * @param {number} exponent
    609 * @param {number} mantissa
    610 * @return {tcuFloat.deFloat}
    611 */
    612 tcuFloat.deFloat.prototype.construct = function(sign, exponent, mantissa) {
    613    return this.description.construct(sign, exponent, mantissa);
    614 };
    615 
    616 /**
    617 * Builds a float of the current binary description.
    618 * Given a sign, exponent and a raw binary mantissa.
    619 * @param {number} sign
    620 * @param {number} exponent
    621 * @param {number} mantissaBits Raw binary mantissa.
    622 * @return {tcuFloat.deFloat}
    623 */
    624 tcuFloat.deFloat.prototype.constructBits = function(sign, exponent, mantissaBits) {
    625    return this.description.constructBits(sign, exponent, mantissaBits);
    626 };
    627 
    628 /**
    629 * Calculates the JS float number from the internal representation.
    630 * @return {number} The JS float value represented by this tcuFloat.deFloat.
    631 */
    632 tcuFloat.deFloat.prototype.getValue = function() {
    633    if ((this.description.Flags | tcuFloat.FloatFlags.FLOAT_HAS_SIGN) === 0 && this.sign() < 0)
    634        return 0;
    635    if (this.isInf())
    636        return Number.Infinity;
    637    if (this.isNaN())
    638        return Number.NaN;
    639    if (this.isZero())
    640        return this.sign() * 0;
    641    /**@type {number} */ var mymantissa = this.mantissa();
    642    /**@type {number} */ var myexponent = this.exponent();
    643    /**@type {number} */ var sign = this.sign();
    644 
    645    /**@type {number} */ var value = mymantissa / Math.pow(2, this.description.MantissaBits) * Math.pow(2, myexponent);
    646 
    647    if (this.description.Flags | tcuFloat.FloatFlags.FLOAT_HAS_SIGN != 0)
    648        value = value * sign;
    649 
    650    return value;
    651 };
    652 
    653 tcuFloat.description10 = new tcuFloat.FloatDescription(5, 5, 15, 0);
    654 tcuFloat.description11 = new tcuFloat.FloatDescription(5, 6, 15, 0);
    655 tcuFloat.description16 = new tcuFloat.FloatDescription(5, 10, 15, tcuFloat.FloatFlags.FLOAT_HAS_SIGN);
    656 tcuFloat.description32 = new tcuFloat.FloatDescription(8, 23, 127, tcuFloat.FloatFlags.FLOAT_HAS_SIGN | tcuFloat.FloatFlags.FLOAT_SUPPORT_DENORM);
    657 tcuFloat.description64 = new tcuFloat.FloatDescription(11, 52, 1023, tcuFloat.FloatFlags.FLOAT_HAS_SIGN | tcuFloat.FloatFlags.FLOAT_SUPPORT_DENORM);
    658 
    659 tcuFloat.convertFloat32Inline = (function() {
    660    var float32View = new Float32Array(1);
    661    var int32View = new Int32Array(float32View.buffer);
    662 
    663    return function(fval, description) {
    664        float32View[0] = fval;
    665        var fbits = int32View[0];
    666 
    667        var exponentBits = (fbits >> 23) & 0xff;
    668        var mantissaBits = fbits & 0x7fffff;
    669        var signBit = (fbits & 0x80000000) ? 1 : 0;
    670        var sign = signBit ? -1 : 1;
    671 
    672        var isZero = exponentBits == 0 && mantissaBits == 0;
    673 
    674        var bitDiff;
    675        var half;
    676        var bias;
    677 
    678        if (!(description.Flags & tcuFloat.FloatFlags.FLOAT_HAS_SIGN) && sign < 0) {
    679            // Negative number, truncate to zero.
    680            return description.zeroNumber(+1);
    681        } else if (exponentBits == ((1 << tcuFloat.description32.ExponentBits) - 1) && mantissaBits == 0) { // isInf
    682            return description.infNumber(sign);
    683        } else if (exponentBits == ((1 << tcuFloat.description32.ExponentBits) - 1) && mantissaBits != 0) { // isNaN
    684            return description.nanNumber();
    685        } else if (isZero) {
    686            return description.zeroNumber(sign);
    687        } else {
    688            var eMin = 1 - description.ExponentBias;
    689            var eMax = ((1 << description.ExponentBits) - 2) - description.ExponentBias;
    690 
    691            var isDenorm = exponentBits == 0 && mantissaBits != 0;
    692 
    693            var s = signBit << (description.ExponentBits + description.MantissaBits); // \note Not sign, but sign bit.
    694            var e = isDenorm ? 1 - tcuFloat.description32.ExponentBias : exponentBits - tcuFloat.description32.ExponentBias;// other.exponent();
    695            var m = isZero || isDenorm ? mantissaBits : mantissaBits | (1 << tcuFloat.description32.MantissaBits); // other.mantissa();
    696 
    697            // Normalize denormalized values prior to conversion.
    698            while (!(m & (1 << tcuFloat.description32.MantissaBits))) {
    699                m = deMath.shiftLeft(m, 1);
    700                e -= 1;
    701            }
    702 
    703            if (e < eMin) {
    704                // Underflow.
    705                if ((description.Flags & tcuFloat.FloatFlags.FLOAT_SUPPORT_DENORM) && (eMin - e - 1 <= description.MantissaBits)) {
    706                    // Shift and round (RTE).
    707                    bitDiff = (tcuFloat.description32.MantissaBits - description.MantissaBits) + (eMin - e);
    708                    half = (1 << (bitDiff - 1)) - 1;
    709                    bias = ((m >> bitDiff) & 1);
    710                    return (s | ((m + half + bias) >> bitDiff));
    711                } else
    712                    return description.zeroNumber(sign);
    713            } else {
    714                // Remove leading 1.
    715                m = (m & ~(1 << tcuFloat.description32.MantissaBits));
    716 
    717                if (description.MantissaBits < tcuFloat.description32.MantissaBits) {
    718                    // Round mantissa (round to nearest even).
    719                    bitDiff = tcuFloat.description32.MantissaBits - description.MantissaBits;
    720                    half = (1 << (bitDiff - 1)) - 1;
    721                    bias = ((m >> bitDiff) & 1);
    722 
    723                    m = (m + half + bias) >> bitDiff;
    724 
    725                    if ((m & (1 << description.MantissaBits))) {
    726                        // Overflow in mantissa.
    727                        m = 0;
    728                        e += 1;
    729                    }
    730                } else {
    731                    bitDiff = description.MantissaBits - tcuFloat.description32.MantissaBits;
    732                    m = (m << bitDiff);
    733                }
    734 
    735                if (e > eMax) {
    736                    // Overflow.
    737                    return description.infNumber(sign);
    738                } else {
    739                    DE_ASSERT(deMath.deInRange32(e, eMin, eMax));
    740                    DE_ASSERT(((e + description.ExponentBias) & ~((1 << description.ExponentBits) - 1)) == 0);
    741                    DE_ASSERT((m & ~((1 << description.MantissaBits) - 1)) == 0);
    742 
    743                    return (s | ((e + description.ExponentBias) << description.MantissaBits)) | m;
    744                }
    745            }
    746        }
    747    };
    748 })();
    749 
    750 /**
    751 * Builds a 10 bit tcuFloat.deFloat
    752 * @param {number} value (64-bit JS float)
    753 * @return {tcuFloat.deFloat}
    754 */
    755 tcuFloat.newFloat10 = function(value) {
    756    DE_ASSERT(Number.isInteger(value) && value <= 0x3ff);
    757    /**@type {tcuFloat.deFloat} */ var other32 = new tcuFloat.deFloat().deFloatNumber(value);
    758    return tcuFloat.description10.convert(other32);
    759 };
    760 
    761 /**
    762 * Builds a 11 bit tcuFloat.deFloat
    763 * @param {number} value (64-bit JS float)
    764 * @return {tcuFloat.deFloat}
    765 */
    766 tcuFloat.newFloat11 = function(value) {
    767    /**@type {tcuFloat.deFloat} */ var other32 = new tcuFloat.deFloat().deFloatNumber(value);
    768    return tcuFloat.description11.convert(other32);
    769 };
    770 
    771 /**
    772 * Builds a 16 bit tcuFloat.deFloat
    773 * @param {number} value (64-bit JS float)
    774 * @return {tcuFloat.deFloat}
    775 */
    776 tcuFloat.newFloat16 = function(value) {
    777    /**@type {tcuFloat.deFloat} */ var other32 = new tcuFloat.deFloat().deFloatNumber(value);
    778    return tcuFloat.description16.convert(other32);
    779 };
    780 
    781 /**
    782 * Builds a 16 bit tcuFloat.deFloat from raw bits
    783 * @param {number} value (16-bit value)
    784 * @return {tcuFloat.deFloat}
    785 */
    786 tcuFloat.newFloat32From16 = function(value) {
    787    var other16 = tcuFloat.newDeFloatFromParameters(value, tcuFloat.description16);
    788    return tcuFloat.description32.convert(other16);
    789 };
    790 
    791 /**
    792 * Builds a 16 bit tcuFloat.deFloat with no denorm support
    793 * @param {number} value (64-bit JS float)
    794 * @return {tcuFloat.deFloat}
    795 */
    796 tcuFloat.newFloat16NoDenorm = function(value) {
    797    /**@type {tcuFloat.deFloat} */ var other32 = new tcuFloat.deFloat().deFloatNumber(value);
    798    return tcuFloat.description16.convert(other32);
    799 };
    800 
    801 /**
    802 * Builds a 32 bit tcuFloat.deFloat
    803 * @param {number} value (64-bit JS float)
    804 * @return {tcuFloat.deFloat}
    805 */
    806 tcuFloat.newFloat32 = function(value) {
    807    return new tcuFloat.deFloat().deFloatNumber(value);
    808 };
    809 
    810 tcuFloat.numberToFloat11 = function(value) {
    811    return tcuFloat.convertFloat32Inline(value, tcuFloat.description11);
    812 };
    813 
    814 tcuFloat.float11ToNumber = (function() {
    815    var x = tcuFloat.newDeFloatFromParameters(0, tcuFloat.description11);
    816    return function(float11) {
    817        x.deFloatParametersNumber(float11);
    818        return x.getValue();
    819    };
    820 })();
    821 
    822 tcuFloat.numberToFloat10 = function(value) {
    823    return tcuFloat.convertFloat32Inline(value, tcuFloat.description10);
    824 };
    825 
    826 tcuFloat.float10ToNumber = (function() {
    827    var x = tcuFloat.newDeFloatFromParameters(0, tcuFloat.description10);
    828    return function(float10) {
    829        x.deFloatParametersNumber(float10);
    830        return x.getValue();
    831    };
    832 })();
    833 
    834 tcuFloat.numberToHalfFloat = function(value) {
    835    return tcuFloat.convertFloat32Inline(value, tcuFloat.description16);
    836 };
    837 
    838 tcuFloat.numberToHalfFloatNoDenorm = function(value) {
    839    return tcuFloat.newFloat16NoDenorm(value).bits();
    840 };
    841 
    842 tcuFloat.halfFloatToNumber = (function() {
    843    var x = tcuFloat.newDeFloatFromParameters(0, tcuFloat.description16);
    844    return function(half) {
    845        x.deFloatParametersNumber(half);
    846        return x.getValue();
    847    };
    848 })();
    849 
    850 tcuFloat.halfFloatToNumberNoDenorm = tcuFloat.halfFloatToNumber;
    851 
    852 /**
    853 * Builds a 64 bit tcuFloat.deFloat
    854 * @param {number} value (64-bit JS float)
    855 * @return {tcuFloat.deFloat}
    856 */
    857 tcuFloat.newFloat64 = function(value) {
    858    return new tcuFloat.deFloat().deFloatParameters(0, tcuFloat.description64)
    859        .deFloatNumber64(value);
    860 };
    861 
    862 });