/*------------------------------------------------------------------------- * drawElements Quality Program OpenGL ES Utilities * ------------------------------------------------ * * Copyright 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ 'use strict'; goog.provide('framework.common.tcuFloat'); goog.require('framework.delibs.debase.deMath'); goog.scope(function() { var tcuFloat = framework.common.tcuFloat; var deMath = framework.delibs.debase.deMath; var DE_ASSERT = function(x) { if (!x) throw new Error('Assert failed'); }; tcuFloat.FloatFlags = { FLOAT_HAS_SIGN: (1 << 0), FLOAT_SUPPORT_DENORM: (1 << 1) }; /** * Defines a tcuFloat.FloatDescription object, which is an essential part of the tcuFloat.deFloat type. * Holds the information that shapes the tcuFloat.deFloat. * @constructor */ tcuFloat.FloatDescription = function(exponentBits, mantissaBits, exponentBias, flags) { this.ExponentBits = exponentBits; this.MantissaBits = mantissaBits; this.ExponentBias = exponentBias; this.Flags = flags; this.totalBitSize = 1 + this.ExponentBits + this.MantissaBits; this.totalByteSize = Math.floor(this.totalBitSize / 8) + ((this.totalBitSize % 8) > 0 ? 1 : 0); }; /** * Builds a zero float of the current binary description. * @param {number} sign * @return {tcuFloat.deFloat} */ tcuFloat.FloatDescription.prototype.zero = function(sign) { return tcuFloat.newDeFloatFromParameters(this.zeroNumber(sign), this); }; tcuFloat.FloatDescription.prototype.zeroNumber = function(sign) { return deMath.shiftLeft((sign > 0 ? 0 : 1), (this.ExponentBits + this.MantissaBits)); }; /** * Builds an infinity float representation of the current binary description. * @param {number} sign * @return {tcuFloat.deFloat} */ tcuFloat.FloatDescription.prototype.inf = function(sign) { return tcuFloat.newDeFloatFromParameters(this.infNumber(sign), this); }; tcuFloat.FloatDescription.prototype.infNumber = function(sign) { return ((sign > 0 ? 0 : 1) << (this.ExponentBits + this.MantissaBits)) | deMath.shiftLeft(((1 << this.ExponentBits) - 1), this.MantissaBits); //Unless using very large exponent types, native shift is safe here, i guess. }; /** * Builds a NaN float representation of the current binary description. * @return {tcuFloat.deFloat} */ tcuFloat.FloatDescription.prototype.nan = function() { return tcuFloat.newDeFloatFromParameters(this.nanNumber(), this); }; tcuFloat.FloatDescription.prototype.nanNumber = function() { return deMath.shiftLeft(1, (this.ExponentBits + this.MantissaBits)) - 1; }; /** * Builds a tcuFloat.deFloat number based on the description and the given * sign, exponent and mantissa values. * @param {number} sign * @param {number} exponent * @param {number} mantissa * @return {tcuFloat.deFloat} */ tcuFloat.FloatDescription.prototype.construct = function(sign, exponent, mantissa) { // Repurpose this otherwise invalid input as a shorthand notation for zero (no need for caller to care about internal representation) /** @type {boolean} */ var isShorthandZero = exponent == 0 && mantissa == 0; // Handles the typical notation for zero (min exponent, mantissa 0). Note that the exponent usually used exponent (-ExponentBias) for zero/subnormals is not used. // Instead zero/subnormals have the (normally implicit) leading mantissa bit set to zero. /** @type {boolean} */ var isDenormOrZero = (exponent == 1 - this.ExponentBias) && (deMath.shiftRight(mantissa, this.MantissaBits) == 0); /** @type {number} */ var s = deMath.shiftLeft((sign < 0 ? 1 : 0), (this.ExponentBits + this.MantissaBits)); /** @type {number} */ var exp = (isShorthandZero || isDenormOrZero) ? 0 : exponent + this.ExponentBias; DE_ASSERT(sign == +1 || sign == -1); DE_ASSERT(isShorthandZero || isDenormOrZero || deMath.shiftRight(mantissa, this.MantissaBits) == 1); DE_ASSERT((exp >> this.ExponentBits) == 0); //Native shift is safe return tcuFloat.newDeFloatFromParameters( deMath.binaryOp( deMath.binaryOp( s, deMath.shiftLeft(exp, this.MantissaBits), deMath.BinaryOp.OR ), deMath.binaryOp( mantissa, deMath.shiftLeft(1, this.MantissaBits) - 1, deMath.BinaryOp.AND ), deMath.BinaryOp.OR ), this ); }; /** * Builds a tcuFloat.deFloat number based on the description and the given * sign, exponent and binary mantissa values. * @param {number} sign * @param {number} exponent * @param {number} mantissaBits The raw binary representation. * @return {tcuFloat.deFloat} */ tcuFloat.FloatDescription.prototype.constructBits = function(sign, exponent, mantissaBits) { /** @type {number} */ var signBit = sign < 0 ? 1 : 0; /** @type {number} */ var exponentBits = exponent + this.ExponentBias; DE_ASSERT(sign == +1 || sign == -1); DE_ASSERT((exponentBits >> this.ExponentBits) == 0); DE_ASSERT(deMath.shiftRight(mantissaBits, this.MantissaBits) == 0); return tcuFloat.newDeFloatFromParameters( deMath.binaryOp( deMath.binaryOp( deMath.shiftLeft( signBit, this.ExponentBits + this.MantissaBits ), deMath.shiftLeft(exponentBits, this.MantissaBits), deMath.BinaryOp.OR ), mantissaBits, deMath.BinaryOp.OR ), this ); }; /** * Converts a tcuFloat.deFloat from it's own format description into the format described * by this description. * @param {tcuFloat.deFloat} other Other float to convert to this format description. * @return {tcuFloat.deFloat} converted tcuFloat.deFloat */ tcuFloat.FloatDescription.prototype.convert = function(other) { /** @type {number} */ var otherExponentBits = other.description.ExponentBits; /** @type {number} */ var otherMantissaBits = other.description.MantissaBits; /** @type {number} */ var otherExponentBias = other.description.ExponentBias; /** @type {number} */ var otherFlags = other.description.Flags; /** @type {number} */ var bitDiff; /** @type {number} */ var half; /** @type {number} */ var bias; if (!(this.Flags & tcuFloat.FloatFlags.FLOAT_HAS_SIGN) && other.sign() < 0) { // Negative number, truncate to zero. return this.zero(+1); } else if (other.isInf()) { return this.inf(other.sign()); } else if (other.isNaN()) { return this.nan(); } else if (other.isZero()) { return this.zero(other.sign()); } else { /** @type {number} */ var eMin = 1 - this.ExponentBias; /** @type {number} */ var eMax = ((1 << this.ExponentBits) - 2) - this.ExponentBias; /** @type {number} */ var s = deMath.shiftLeft(other.signBit(), (this.ExponentBits + this.MantissaBits)); // \note Not sign, but sign bit. /** @type {number} */ var e = other.exponent(); /** @type {number} */ var m = other.mantissa(); // Normalize denormalized values prior to conversion. while (!deMath.binaryOp(m, deMath.shiftLeft(1, otherMantissaBits), deMath.BinaryOp.AND)) { m = deMath.shiftLeft(m, 1); e -= 1; } if (e < eMin) { // Underflow. if ((this.Flags & tcuFloat.FloatFlags.FLOAT_SUPPORT_DENORM) && (eMin - e - 1 <= this.MantissaBits)) { // Shift and round (RTE). bitDiff = (otherMantissaBits - this.MantissaBits) + (eMin - e); half = deMath.shiftLeft(1, (bitDiff - 1)) - 1; bias = deMath.binaryOp(deMath.shiftRight(m, bitDiff), 1, deMath.BinaryOp.AND); return tcuFloat.newDeFloatFromParameters( deMath.binaryOp( s, deMath.shiftRight( m + half + bias, bitDiff ), deMath.BinaryOp.OR ), this ); } else return this.zero(other.sign()); } else { // Remove leading 1. m = deMath.binaryOp(m, deMath.binaryNot(deMath.shiftLeft(1, otherMantissaBits)), deMath.BinaryOp.AND); if (this.MantissaBits < otherMantissaBits) { // Round mantissa (round to nearest even). bitDiff = otherMantissaBits - this.MantissaBits; half = deMath.shiftLeft(1, (bitDiff - 1)) - 1; bias = deMath.binaryOp(deMath.shiftRight(m, bitDiff), 1, deMath.BinaryOp.AND); m = deMath.shiftRight(m + half + bias, bitDiff); if (deMath.binaryOp(m, deMath.shiftLeft(1, this.MantissaBits), deMath.BinaryOp.AND)) { // Overflow in mantissa. m = 0; e += 1; } } else { bitDiff = this.MantissaBits - otherMantissaBits; m = deMath.shiftLeft(m, bitDiff); } if (e > eMax) { // Overflow. return this.inf(other.sign()); } else { DE_ASSERT(deMath.deInRange32(e, eMin, eMax)); DE_ASSERT(deMath.binaryOp((e + this.ExponentBias), deMath.binaryNot(deMath.shiftLeft(1, this.ExponentBits) - 1), deMath.BinaryOp.AND) == 0); DE_ASSERT(deMath.binaryOp(m, deMath.binaryNot(deMath.shiftLeft(1, this.MantissaBits) - 1), deMath.BinaryOp.AND) == 0); return tcuFloat.newDeFloatFromParameters( deMath.binaryOp( deMath.binaryOp( s, deMath.shiftLeft( e + this.ExponentBias, this.MantissaBits ), deMath.BinaryOp.OR ), m, deMath.BinaryOp.OR ), this ); } } } }; /** * tcuFloat.deFloat class - Empty constructor, builds a 32 bit float by default * @constructor */ tcuFloat.deFloat = function() { this.description = tcuFloat.description32; this.m_buffer = null; this.m_array = null; this.m_array32 = null; this.bitValue = undefined; this.signValue = undefined; this.expValue = undefined; this.mantissaValue = undefined; this.m_value = 0; }; /** * buffer - Get the deFloat's existing ArrayBuffer or create one if none exists. * @return {ArrayBuffer} */ tcuFloat.deFloat.prototype.buffer = function() { if (!this.m_buffer) this.m_buffer = new ArrayBuffer(this.description.totalByteSize); return this.m_buffer; }; /** * array - Get the deFloat's existing Uint8Array or create one if none exists. * @return {Uint8Array} */ tcuFloat.deFloat.prototype.array = function() { if (!this.m_array) this.m_array = new Uint8Array(this.buffer()); return this.m_array; }; /** * array32 - Get the deFloat's existing Uint32Array or create one if none exists. * @return {Uint32Array} */ tcuFloat.deFloat.prototype.array32 = function() { if (!this.m_array32) this.m_array32 = new Uint32Array(this.buffer()); return this.m_array32; }; /** * deFloatNumber - To be used immediately after constructor * Builds a 32-bit tcuFloat.deFloat based on a 64-bit JS number. * @param {number} jsnumber * @return {tcuFloat.deFloat} */ tcuFloat.deFloat.prototype.deFloatNumber = function(jsnumber) { var view32 = new DataView(this.buffer()); view32.setFloat32(0, jsnumber, true); //little-endian this.m_value = view32.getFloat32(0, true); //little-endian // Clear cached values this.bitValue = undefined; this.signValue = undefined; this.expValue = undefined; this.mantissaValue = undefined; return this; }; /** * deFloatNumber64 - To be used immediately after constructor * Builds a 64-bit tcuFloat.deFloat based on a 64-bit JS number. * @param {number} jsnumber * @return {tcuFloat.deFloat} */ tcuFloat.deFloat.prototype.deFloatNumber64 = function(jsnumber) { var view64 = new DataView(this.buffer()); view64.setFloat64(0, jsnumber, true); //little-endian this.m_value = view64.getFloat64(0, true); //little-endian // Clear cached values this.bitValue = undefined; this.signValue = undefined; this.expValue = undefined; this.mantissaValue = undefined; return this; }; /** * Convenience function to build a 32-bit tcuFloat.deFloat based on a 64-bit JS number * Builds a 32-bit tcuFloat.deFloat based on a 64-bit JS number. * @param {number} jsnumber * @return {tcuFloat.deFloat} */ tcuFloat.newDeFloatFromNumber = function(jsnumber) { return new tcuFloat.deFloat().deFloatNumber(jsnumber); }; /** * deFloatBuffer - To be used immediately after constructor * Builds a tcuFloat.deFloat based on a buffer and a format description. * The buffer is assumed to contain data of the given description. * @param {ArrayBuffer} buffer * @param {tcuFloat.FloatDescription} description * @return {tcuFloat.deFloat} */ tcuFloat.deFloat.prototype.deFloatBuffer = function(buffer, description) { this.m_buffer = buffer; this.m_array = new Uint8Array(this.m_buffer); this.m_array32 = new Uint32Array(this.m_buffer); this.m_value = deMath.arrayToNumber(this.m_array); // Clear cached values this.bitValue = undefined; this.signValue = undefined; this.expValue = undefined; this.mantissaValue = undefined; return this; }; /** * Convenience function to build a tcuFloat.deFloat based on a buffer and a format description * The buffer is assumed to contain data of the given description. * @param {ArrayBuffer} buffer * @param {tcuFloat.FloatDescription} description * @return {tcuFloat.deFloat} */ tcuFloat.newDeFloatFromBuffer = function(buffer, description) { return new tcuFloat.deFloat().deFloatBuffer(buffer, description); }; /** * Set the tcuFloat.deFloat from the given bitwise representation. * * @param {number} jsnumber This is taken to be the bitwise representation of * the floating point number represented by this deFloat. It must be an * integer, less than 2^52, and compatible with the existing description. * @return {tcuFloat.deFloat} **/ tcuFloat.deFloat.prototype.deFloatParametersNumber = function(jsnumber) { /** @type {number} */ var jsnumberMax = -1 >>> (32 - this.description.totalBitSize); DE_ASSERT(Number.isInteger(jsnumber) && jsnumber <= jsnumberMax); this.m_value = jsnumber; deMath.numberToArray(this.m_array, jsnumber); // Clear cached values this.bitValue = undefined; this.signValue = undefined; this.expValue = undefined; this.mantissaValue = undefined; return this; }; /** * Initializes a tcuFloat.deFloat from the given bitwise representation, * with the specified format description. * * @param {number} jsnumber This is taken to be the bitwise representation of * the floating point number represented by this deFloat. It must be an * integer, less than 2^52, and compatible with the new description. * @param {tcuFloat.FloatDescription} description * @return {tcuFloat.deFloat} **/ tcuFloat.deFloat.prototype.deFloatParameters = function(jsnumber, description) { /** @type {number} */ var maxUint52 = 0x10000000000000; DE_ASSERT(Number.isInteger(jsnumber) && jsnumber < maxUint52); if (description.totalBitSize > 52) { // The jsnumber representation for this number can't possibly be valid. // Make sure it has a sentinel 0 value. DE_ASSERT(jsnumber === 0); } this.description = description; this.m_buffer = new ArrayBuffer(this.description.totalByteSize); this.m_array = new Uint8Array(this.m_buffer); return this.deFloatParametersNumber(jsnumber); }; /** * Convenience function. Creates a tcuFloat.deFloat, then initializes it from * the given bitwise representation, with the specified format description. * * @param {number} jsnumber This is taken to be the bitwise representation of * the floating point number represented by this deFloat. It must be an * integer, less than 2^52, and compatible with the new description. * @param {tcuFloat.FloatDescription} description * @return {tcuFloat.deFloat} **/ tcuFloat.newDeFloatFromParameters = function(jsnumber, description) { return new tcuFloat.deFloat().deFloatParameters(jsnumber, description); }; /** * Returns bit range [begin, end) * @param {number} begin * @param {number} end * @return {number} */ tcuFloat.deFloat.prototype.getBitRange = function(begin, end) { if (this.description.totalBitSize <= 52) { // this.bits() is invalid for more than 52 bits. return deMath.getBitRange(this.bits(), begin, end); } else { return deMath.getArray32BitRange(this.array32(), begin, end); } }; /** * Returns the raw binary representation value of the tcuFloat.deFloat * @return {number} */ tcuFloat.deFloat.prototype.bits = function() { if (typeof this.bitValue === 'undefined') this.bitValue = deMath.arrayToNumber(this.array()); return this.bitValue; }; /** * Returns the raw binary sign bit * @return {number} */ tcuFloat.deFloat.prototype.signBit = function() { if (typeof this.signValue === 'undefined') this.signValue = this.getBitRange(this.description.totalBitSize - 1, this.description.totalBitSize); return this.signValue; }; /** * Returns the raw binary exponent bits * @return {number} */ tcuFloat.deFloat.prototype.exponentBits = function() { if (typeof this.expValue === 'undefined') this.expValue = this.getBitRange(this.description.MantissaBits, this.description.MantissaBits + this.description.ExponentBits); return this.expValue; }; /** * Returns the raw binary mantissa bits * @return {number} */ tcuFloat.deFloat.prototype.mantissaBits = function() { if (typeof this.mantissaValue === 'undefined') this.mantissaValue = this.getBitRange(0, this.description.MantissaBits); return this.mantissaValue; }; /** * Returns the sign as a factor (-1 or 1) * @return {number} */ tcuFloat.deFloat.prototype.sign = function() { var sign = this.signBit(); var signvalue = sign ? -1 : 1; return signvalue; }; /** * Returns the real exponent, checking if it's a denorm or zero number or not * @return {number} */ tcuFloat.deFloat.prototype.exponent = function() {return this.isDenorm() ? 1 - this.description.ExponentBias : this.exponentBits() - this.description.ExponentBias;}; /** * Returns the (still raw) mantissa, checking if it's a denorm or zero number or not * Makes the normally implicit bit explicit. * @return {number} */ 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);}; /** * Returns if the number is infinity or not. * @return {boolean} */ tcuFloat.deFloat.prototype.isInf = function() {return this.exponentBits() == ((1 << this.description.ExponentBits) - 1) && this.mantissaBits() == 0;}; /** * Returns if the number is NaN or not. * @return {boolean} */ tcuFloat.deFloat.prototype.isNaN = function() {return this.exponentBits() == ((1 << this.description.ExponentBits) - 1) && this.mantissaBits() != 0;}; /** * Returns if the number is zero or not. * @return {boolean} */ tcuFloat.deFloat.prototype.isZero = function() {return this.exponentBits() == 0 && this.mantissaBits() == 0;}; /** * Returns if the number is denormalized or not. * @return {boolean} */ tcuFloat.deFloat.prototype.isDenorm = function() {return this.exponentBits() == 0 && this.mantissaBits() != 0;}; /** * Builds a zero float of the current binary description. * @param {number} sign * @return {tcuFloat.deFloat} */ tcuFloat.deFloat.prototype.zero = function(sign) { return this.description.zero(sign); }; /** * Builds an infinity float representation of the current binary description. * @param {number} sign * @return {tcuFloat.deFloat} */ tcuFloat.deFloat.prototype.inf = function(sign) { return this.description.inf(sign); }; /** * Builds a NaN float representation of the current binary description. * @return {tcuFloat.deFloat} */ tcuFloat.deFloat.prototype.nan = function() { return this.description.nan(); }; /** * Builds a float of the current binary description. * Given a sign, exponent and mantissa. * @param {number} sign * @param {number} exponent * @param {number} mantissa * @return {tcuFloat.deFloat} */ tcuFloat.deFloat.prototype.construct = function(sign, exponent, mantissa) { return this.description.construct(sign, exponent, mantissa); }; /** * Builds a float of the current binary description. * Given a sign, exponent and a raw binary mantissa. * @param {number} sign * @param {number} exponent * @param {number} mantissaBits Raw binary mantissa. * @return {tcuFloat.deFloat} */ tcuFloat.deFloat.prototype.constructBits = function(sign, exponent, mantissaBits) { return this.description.constructBits(sign, exponent, mantissaBits); }; /** * Calculates the JS float number from the internal representation. * @return {number} The JS float value represented by this tcuFloat.deFloat. */ tcuFloat.deFloat.prototype.getValue = function() { if ((this.description.Flags | tcuFloat.FloatFlags.FLOAT_HAS_SIGN) === 0 && this.sign() < 0) return 0; if (this.isInf()) return Number.Infinity; if (this.isNaN()) return Number.NaN; if (this.isZero()) return this.sign() * 0; /**@type {number} */ var mymantissa = this.mantissa(); /**@type {number} */ var myexponent = this.exponent(); /**@type {number} */ var sign = this.sign(); /**@type {number} */ var value = mymantissa / Math.pow(2, this.description.MantissaBits) * Math.pow(2, myexponent); if (this.description.Flags | tcuFloat.FloatFlags.FLOAT_HAS_SIGN != 0) value = value * sign; return value; }; tcuFloat.description10 = new tcuFloat.FloatDescription(5, 5, 15, 0); tcuFloat.description11 = new tcuFloat.FloatDescription(5, 6, 15, 0); tcuFloat.description16 = new tcuFloat.FloatDescription(5, 10, 15, tcuFloat.FloatFlags.FLOAT_HAS_SIGN); tcuFloat.description32 = new tcuFloat.FloatDescription(8, 23, 127, tcuFloat.FloatFlags.FLOAT_HAS_SIGN | tcuFloat.FloatFlags.FLOAT_SUPPORT_DENORM); tcuFloat.description64 = new tcuFloat.FloatDescription(11, 52, 1023, tcuFloat.FloatFlags.FLOAT_HAS_SIGN | tcuFloat.FloatFlags.FLOAT_SUPPORT_DENORM); tcuFloat.convertFloat32Inline = (function() { var float32View = new Float32Array(1); var int32View = new Int32Array(float32View.buffer); return function(fval, description) { float32View[0] = fval; var fbits = int32View[0]; var exponentBits = (fbits >> 23) & 0xff; var mantissaBits = fbits & 0x7fffff; var signBit = (fbits & 0x80000000) ? 1 : 0; var sign = signBit ? -1 : 1; var isZero = exponentBits == 0 && mantissaBits == 0; var bitDiff; var half; var bias; if (!(description.Flags & tcuFloat.FloatFlags.FLOAT_HAS_SIGN) && sign < 0) { // Negative number, truncate to zero. return description.zeroNumber(+1); } else if (exponentBits == ((1 << tcuFloat.description32.ExponentBits) - 1) && mantissaBits == 0) { // isInf return description.infNumber(sign); } else if (exponentBits == ((1 << tcuFloat.description32.ExponentBits) - 1) && mantissaBits != 0) { // isNaN return description.nanNumber(); } else if (isZero) { return description.zeroNumber(sign); } else { var eMin = 1 - description.ExponentBias; var eMax = ((1 << description.ExponentBits) - 2) - description.ExponentBias; var isDenorm = exponentBits == 0 && mantissaBits != 0; var s = signBit << (description.ExponentBits + description.MantissaBits); // \note Not sign, but sign bit. var e = isDenorm ? 1 - tcuFloat.description32.ExponentBias : exponentBits - tcuFloat.description32.ExponentBias;// other.exponent(); var m = isZero || isDenorm ? mantissaBits : mantissaBits | (1 << tcuFloat.description32.MantissaBits); // other.mantissa(); // Normalize denormalized values prior to conversion. while (!(m & (1 << tcuFloat.description32.MantissaBits))) { m = deMath.shiftLeft(m, 1); e -= 1; } if (e < eMin) { // Underflow. if ((description.Flags & tcuFloat.FloatFlags.FLOAT_SUPPORT_DENORM) && (eMin - e - 1 <= description.MantissaBits)) { // Shift and round (RTE). bitDiff = (tcuFloat.description32.MantissaBits - description.MantissaBits) + (eMin - e); half = (1 << (bitDiff - 1)) - 1; bias = ((m >> bitDiff) & 1); return (s | ((m + half + bias) >> bitDiff)); } else return description.zeroNumber(sign); } else { // Remove leading 1. m = (m & ~(1 << tcuFloat.description32.MantissaBits)); if (description.MantissaBits < tcuFloat.description32.MantissaBits) { // Round mantissa (round to nearest even). bitDiff = tcuFloat.description32.MantissaBits - description.MantissaBits; half = (1 << (bitDiff - 1)) - 1; bias = ((m >> bitDiff) & 1); m = (m + half + bias) >> bitDiff; if ((m & (1 << description.MantissaBits))) { // Overflow in mantissa. m = 0; e += 1; } } else { bitDiff = description.MantissaBits - tcuFloat.description32.MantissaBits; m = (m << bitDiff); } if (e > eMax) { // Overflow. return description.infNumber(sign); } else { DE_ASSERT(deMath.deInRange32(e, eMin, eMax)); DE_ASSERT(((e + description.ExponentBias) & ~((1 << description.ExponentBits) - 1)) == 0); DE_ASSERT((m & ~((1 << description.MantissaBits) - 1)) == 0); return (s | ((e + description.ExponentBias) << description.MantissaBits)) | m; } } } }; })(); /** * Builds a 10 bit tcuFloat.deFloat * @param {number} value (64-bit JS float) * @return {tcuFloat.deFloat} */ tcuFloat.newFloat10 = function(value) { DE_ASSERT(Number.isInteger(value) && value <= 0x3ff); /**@type {tcuFloat.deFloat} */ var other32 = new tcuFloat.deFloat().deFloatNumber(value); return tcuFloat.description10.convert(other32); }; /** * Builds a 11 bit tcuFloat.deFloat * @param {number} value (64-bit JS float) * @return {tcuFloat.deFloat} */ tcuFloat.newFloat11 = function(value) { /**@type {tcuFloat.deFloat} */ var other32 = new tcuFloat.deFloat().deFloatNumber(value); return tcuFloat.description11.convert(other32); }; /** * Builds a 16 bit tcuFloat.deFloat * @param {number} value (64-bit JS float) * @return {tcuFloat.deFloat} */ tcuFloat.newFloat16 = function(value) { /**@type {tcuFloat.deFloat} */ var other32 = new tcuFloat.deFloat().deFloatNumber(value); return tcuFloat.description16.convert(other32); }; /** * Builds a 16 bit tcuFloat.deFloat from raw bits * @param {number} value (16-bit value) * @return {tcuFloat.deFloat} */ tcuFloat.newFloat32From16 = function(value) { var other16 = tcuFloat.newDeFloatFromParameters(value, tcuFloat.description16); return tcuFloat.description32.convert(other16); }; /** * Builds a 16 bit tcuFloat.deFloat with no denorm support * @param {number} value (64-bit JS float) * @return {tcuFloat.deFloat} */ tcuFloat.newFloat16NoDenorm = function(value) { /**@type {tcuFloat.deFloat} */ var other32 = new tcuFloat.deFloat().deFloatNumber(value); return tcuFloat.description16.convert(other32); }; /** * Builds a 32 bit tcuFloat.deFloat * @param {number} value (64-bit JS float) * @return {tcuFloat.deFloat} */ tcuFloat.newFloat32 = function(value) { return new tcuFloat.deFloat().deFloatNumber(value); }; tcuFloat.numberToFloat11 = function(value) { return tcuFloat.convertFloat32Inline(value, tcuFloat.description11); }; tcuFloat.float11ToNumber = (function() { var x = tcuFloat.newDeFloatFromParameters(0, tcuFloat.description11); return function(float11) { x.deFloatParametersNumber(float11); return x.getValue(); }; })(); tcuFloat.numberToFloat10 = function(value) { return tcuFloat.convertFloat32Inline(value, tcuFloat.description10); }; tcuFloat.float10ToNumber = (function() { var x = tcuFloat.newDeFloatFromParameters(0, tcuFloat.description10); return function(float10) { x.deFloatParametersNumber(float10); return x.getValue(); }; })(); tcuFloat.numberToHalfFloat = function(value) { return tcuFloat.convertFloat32Inline(value, tcuFloat.description16); }; tcuFloat.numberToHalfFloatNoDenorm = function(value) { return tcuFloat.newFloat16NoDenorm(value).bits(); }; tcuFloat.halfFloatToNumber = (function() { var x = tcuFloat.newDeFloatFromParameters(0, tcuFloat.description16); return function(half) { x.deFloatParametersNumber(half); return x.getValue(); }; })(); tcuFloat.halfFloatToNumberNoDenorm = tcuFloat.halfFloatToNumber; /** * Builds a 64 bit tcuFloat.deFloat * @param {number} value (64-bit JS float) * @return {tcuFloat.deFloat} */ tcuFloat.newFloat64 = function(value) { return new tcuFloat.deFloat().deFloatParameters(0, tcuFloat.description64) .deFloatNumber64(value); }; });