summaryrefslogtreecommitdiffstats
path: root/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuFloatFormat.js
diff options
context:
space:
mode:
Diffstat (limited to 'dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuFloatFormat.js')
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuFloatFormat.js349
1 files changed, 349 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuFloatFormat.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuFloatFormat.js
new file mode 100644
index 0000000000..a0b4dc82cf
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/common/tcuFloatFormat.js
@@ -0,0 +1,349 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program Tester Core
+ * ----------------------------------------
+ *
+ * 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.
+ *
+ *//*!
+ * \file
+ * \brief Adjustable-precision floating point operations.
+ *//*--------------------------------------------------------------------*/
+ 'use strict';
+ goog.provide('framework.common.tcuFloatFormat');
+
+ goog.require('framework.common.tcuInterval');
+goog.require('framework.delibs.debase.deMath');
+
+ goog.scope(function() {
+
+ var tcuFloatFormat = framework.common.tcuFloatFormat;
+ var deMath = framework.delibs.debase.deMath;
+ var tcuInterval = framework.common.tcuInterval;
+
+ /**
+ * @param {tcuFloatFormat.YesNoMaybe} choice
+ * @param {tcuInterval.Interval} no
+ * @param {tcuInterval.Interval} yes
+ * @return {tcuInterval.Interval}
+ */
+ tcuFloatFormat.chooseInterval = function(choice, no, yes) {
+ switch (choice) {
+ case tcuFloatFormat.YesNoMaybe.NO: return no;
+ case tcuFloatFormat.YesNoMaybe.YES: return yes;
+ case tcuFloatFormat.YesNoMaybe.MAYBE: return no.operatorOrBinary(yes);
+ default: throw new Error('Impossible case');
+ }
+ };
+
+ /**
+ * @param {number} maxExp
+ * @param {number} fractionBits
+ * @return {number}
+ */
+ tcuFloatFormat.computeMaxValue = function(maxExp, fractionBits) {
+ return deMath.deLdExp(1, maxExp) + deMath.deLdExp(Math.pow(2, fractionBits) - 1, maxExp - fractionBits);
+ };
+
+ /**
+ * @enum {number}
+ */
+ tcuFloatFormat.YesNoMaybe = {
+ NO: 0,
+ MAYBE: 1,
+ YES: 2
+ };
+
+ /**
+ * @constructor
+ * @param {number} minExp
+ * @param {number} maxExp
+ * @param {number} fractionBits
+ * @param {boolean} exactPrecision
+ * @param {tcuFloatFormat.YesNoMaybe=} hasSubnormal
+ * @param {tcuFloatFormat.YesNoMaybe=} hasInf
+ * @param {tcuFloatFormat.YesNoMaybe=} hasNaN
+ */
+ tcuFloatFormat.FloatFormat = function(minExp, maxExp, fractionBits, exactPrecision, hasSubnormal, hasInf, hasNaN) {
+ // /** @type{number} */ var exponentShift (int exp) const;
+ // Interval clampValue (double d) const;
+
+ /** @type {number} */ this.m_minExp = minExp; // Minimum exponent, inclusive
+ /** @type {number} */ this.m_maxExp = maxExp; // Maximum exponent, inclusive
+ /** @type {number} */ this.m_fractionBits = fractionBits; // Number of fractional bits in significand
+ /** @type {tcuFloatFormat.YesNoMaybe} */ this.m_hasSubnormal = hasSubnormal === undefined ? tcuFloatFormat.YesNoMaybe.MAYBE : hasSubnormal; // Does the format support denormalized numbers?
+ /** @type {tcuFloatFormat.YesNoMaybe} */ this.m_hasInf = hasInf === undefined ? tcuFloatFormat.YesNoMaybe.MAYBE : hasInf; // Does the format support infinities?
+ /** @type {tcuFloatFormat.YesNoMaybe} */ this.m_hasNaN = hasNaN === undefined ? tcuFloatFormat.YesNoMaybe.MAYBE : hasNaN; // Does the format support NaNs?
+ /** @type {boolean} */ this.m_exactPrecision = exactPrecision; // Are larger precisions disallowed?
+ /** @type {number} */ this.m_maxValue = tcuFloatFormat.computeMaxValue(maxExp, fractionBits);
+ };
+
+ /**
+ * @return {number}
+ */
+ tcuFloatFormat.FloatFormat.prototype.getMinExp = function() {
+ return this.m_minExp;
+ };
+
+ /**
+ * @return {number}
+ */
+ tcuFloatFormat.FloatFormat.prototype.getMaxExp = function() {
+ return this.m_maxExp;
+ };
+
+ /**
+ * @return {number}
+ */
+ tcuFloatFormat.FloatFormat.prototype.getMaxValue = function() {
+ return this.m_maxValue;
+ };
+
+ /**
+ * @return {number}
+ */
+ tcuFloatFormat.FloatFormat.prototype.getFractionBits = function() {
+ return this.m_fractionBits;
+ };
+
+ /**
+ * @return {tcuFloatFormat.YesNoMaybe}
+ */
+ tcuFloatFormat.FloatFormat.prototype.hasSubnormal = function() {
+ return this.m_hasSubnormal;
+ };
+
+ /**
+ * @return {tcuFloatFormat.YesNoMaybe}
+ */
+ tcuFloatFormat.FloatFormat.prototype.hasInf = function() {
+ return this.m_hasInf;
+ };
+
+ /**
+ * @param {number} x
+ * @param {number} count
+ * @return {number}
+ */
+ tcuFloatFormat.FloatFormat.prototype.ulp = function(x, count) {
+ var breakdown = deMath.deFractExp(Math.abs(x));
+ /** @type {number} */ var exp = breakdown.exponent;
+ /** @type {number} */ var frac = breakdown.significand;
+
+ if (isNaN(frac))
+ return NaN;
+ else if (!isFinite(frac))
+ return deMath.deLdExp(1.0, this.m_maxExp - this.m_fractionBits);
+ else if (frac == 1.0) {
+ // Harrison's ULP: choose distance to closest (i.e. next lower) at binade
+ // boundary.
+ --exp;
+ } else if (frac == 0.0)
+ exp = this.m_minExp;
+
+ // ULP cannot be lower than the smallest quantum.
+ exp = Math.max(exp, this.m_minExp);
+
+ /** @type {number} */ var oneULP = deMath.deLdExp(1.0, exp - this.m_fractionBits);
+ // ScopedRoundingMode ctx (DE_ROUNDINGMODE_TO_POSITIVE_INF);
+
+ return oneULP * count;
+ };
+
+ /**
+ * Return the difference between the given nominal exponent and
+ * the exponent of the lowest significand bit of the
+ * representation of a number with this format.
+ * For normal numbers this is the number of significand bits, but
+ * for subnormals it is less and for values of exp where 2^exp is too
+ * small to represent it is <0
+ * @param {number} exp
+ * @return {number}
+ */
+ tcuFloatFormat.FloatFormat.prototype.exponentShift = function(exp) {
+ return this.m_fractionBits - Math.max(this.m_minExp - exp, 0);
+ };
+
+ /**
+ * @param {number} d
+ * @param {boolean} upward
+ * @return {number}
+ */
+ tcuFloatFormat.FloatFormat.prototype.round = function(d, upward) {
+ var breakdown = deMath.deFractExp(d);
+ /** @type {number} */ var exp = breakdown.exponent;
+ /** @type {number} */ var frac = breakdown.significand;
+
+ var shift = this.exponentShift(exp);
+ var shiftFrac = deMath.deLdExp(frac, shift);
+ var roundFrac = upward ? Math.ceil(shiftFrac) : Math.floor(shiftFrac);
+
+ return deMath.deLdExp(roundFrac, exp - shift);
+ };
+
+ /**
+ * Return the range of numbers that `d` might be converted to in the
+ * floatformat, given its limitations with infinities, subnormals and maximum
+ * exponent.
+ * @param {number} d
+ * @return {tcuInterval.Interval}
+ */
+ tcuFloatFormat.FloatFormat.prototype.clampValue = function(d) {
+ /** @type {number} */ var rSign = deMath.deSign(d);
+ /** @type {number} */ var rExp = 0;
+
+ // DE_ASSERT(!isNaN(d));
+
+ var breakdown = deMath.deFractExp(d);
+ rExp = breakdown.exponent;
+ if (rExp < this.m_minExp)
+ return tcuFloatFormat.chooseInterval(this.m_hasSubnormal, new tcuInterval.Interval(rSign * 0.0), new tcuInterval.Interval(d));
+ else if (!isFinite(d) || rExp > this.m_maxExp)
+ return tcuFloatFormat.chooseInterval(this.m_hasInf, new tcuInterval.Interval(rSign * this.getMaxValue()), new tcuInterval.Interval(rSign * Number.POSITIVE_INFINITY));
+
+ return new tcuInterval.Interval(d);
+ };
+
+ /**
+ * @param {number} d
+ * @param {boolean} upward
+ * @param {boolean} roundUnderOverflow
+ * @return {number}
+ */
+ tcuFloatFormat.FloatFormat.prototype.roundOutDir = function(d, upward, roundUnderOverflow) {
+ var breakdown = deMath.deFractExp(d);
+ var exp = breakdown.exponent;
+
+ if (roundUnderOverflow && exp > this.m_maxExp && (upward == (d < 0.0)))
+ return deMath.deSign(d) * this.getMaxValue();
+ else
+ return this.round(d, upward);
+ };
+
+ /**
+ * @param {tcuInterval.Interval} x
+ * @param {boolean} roundUnderOverflow
+ * @return {tcuInterval.Interval}
+ */
+ tcuFloatFormat.FloatFormat.prototype.roundOut = function(x, roundUnderOverflow) {
+ /** @type {tcuInterval.Interval} */ var ret = x.nan();
+
+ if (!x.empty()) {
+ var a = new tcuInterval.Interval(this.roundOutDir(x.lo(), false, roundUnderOverflow));
+ var b = new tcuInterval.Interval(this.roundOutDir(x.hi(), true, roundUnderOverflow));
+ ret.operatorOrAssignBinary(tcuInterval.withIntervals(a, b));
+ }
+ return ret;
+ };
+
+ //! Return the range of numbers that might be used with this format to
+ //! represent a number within `x`.
+ /**
+ * @param {tcuInterval.Interval} x
+ * @return {tcuInterval.Interval}
+ */
+ tcuFloatFormat.FloatFormat.prototype.convert = function(x) {
+ /** @type {tcuInterval.Interval} */ var ret = new tcuInterval.Interval();
+ /** @type {tcuInterval.Interval} */ var tmp = x;
+
+ if (x.hasNaN()) {
+ // If NaN might be supported, NaN is a legal return value
+ if (this.m_hasNaN != tcuFloatFormat.YesNoMaybe.NO)
+ ret.operatorOrAssignBinary(new tcuInterval.Interval(NaN));
+
+ // If NaN might not be supported, any (non-NaN) value is legal,
+ // _subject_ to clamping. Hence we modify tmp, not ret.
+ if (this.m_hasNaN != tcuFloatFormat.YesNoMaybe.YES)
+ tmp = tcuInterval.unbounded();
+ }
+
+ // Round both bounds _inwards_ to closest representable values.
+ if (!tmp.empty())
+ ret.operatorOrAssignBinary(
+ this.clampValue(this.round(tmp.lo(), true)).operatorOrBinary(
+ this.clampValue(this.round(tmp.hi(), false))));
+
+ // If this format's precision is not exact, the (possibly out-of-bounds)
+ // original value is also a possible result.
+ if (!this.m_exactPrecision)
+ ret.operatorOrAssignBinary(x);
+
+ return ret;
+ };
+
+ /**
+ * @param {number} x
+ * @return {string}
+ */
+ tcuFloatFormat.FloatFormat.prototype.floatToHex = function(x) {
+ if (isNaN(x))
+ return 'NaN';
+ else if (!isFinite(x))
+ return (x < 0.0 ? '-' : '+') + ('inf');
+ else if (x == 0.0) // \todo [2014-03-27 lauri] Negative zero
+ return '0.0';
+
+ return x.toString(10);
+ // TODO
+ // var breakdown = deMath.deFractExp(deAbs(x));
+ // /** @type{number} */ var exp = breakdown.exponent;
+ // /** @type{number} */ var frac = breakdown.significand;
+ // /** @type{number} */ var shift = this.exponentShift(exp);
+ // /** @type{number} */ var bits = deUint64(deLdExp(frac, shift));
+ // /** @type{number} */ var whole = bits >> m_fractionBits;
+ // /** @type{number} */ var fraction = bits & ((deUint64(1) << m_fractionBits) - 1);
+ // /** @type{number} */ var exponent = exp + m_fractionBits - shift;
+ // /** @type{number} */ var numDigits = (this.m_fractionBits + 3) / 4;
+ // /** @type{number} */ var aligned = fraction << (numDigits * 4 - m_fractionBits);
+ // /** @type{string} */ var oss = '';
+
+ // oss + (x < 0 ? '-' : '')
+ // + '0x' + whole + '.'
+ // + std::hex + std::setw(numDigits) + std::setfill('0') + aligned
+ // + 'p' + std::dec + std::setw(0) + exponent;
+ //return oss;
+ };
+
+ /**
+ * @param {tcuInterval.Interval} interval
+ * @return {string}
+ */
+ tcuFloatFormat.FloatFormat.prototype.intervalToHex = function(interval) {
+ if (interval.empty())
+ return interval.hasNaN() ? '{ NaN }' : '{}';
+
+ else if (interval.lo() == interval.hi())
+ return ((interval.hasNaN() ? '{ NaN, ' : '{ ') +
+ this.floatToHex(interval.lo()) + ' }');
+ else if (interval == tcuInterval.unbounded(true))
+ return '<any>';
+
+ return ((interval.hasNaN() ? '{ NaN } | ' : '') +
+ '[' + this.floatToHex(interval.lo()) + ', ' + this.floatToHex(interval.hi()) + ']');
+ };
+
+ /**
+ * @return {tcuFloatFormat.FloatFormat}
+ */
+ tcuFloatFormat.nativeDouble = function() {
+ return new tcuFloatFormat.FloatFormat(-1021 - 1, // min_exponent
+ 1024 - 1, // max_exponent
+ 53 - 1, // digits
+ true, // has_denorm
+ tcuFloatFormat.YesNoMaybe.YES, // has_infinity
+ tcuFloatFormat.YesNoMaybe.YES, // has_quiet_nan
+ tcuFloatFormat.YesNoMaybe.YES); // has_denorm
+ };
+
+});