13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*------------------------------------------------------------------------- 23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program Tester Core 33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * ---------------------------------------- 43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project 63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License"); 83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License. 93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at 103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * http://www.apache.org/licenses/LICENSE-2.0 123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software 143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS, 153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and 173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License. 183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*! 203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file 213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Adjustable-precision floating point operations. 223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/ 233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuFloatFormat.hpp" 253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMath.h" 273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deUniquePtr.hpp" 283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <sstream> 303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <iomanip> 313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <limits> 323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 333c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace tcu 343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 353c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace 363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 383c827367444ee418f129b2c238299f49d3264554Jarkko PoyryInterval chooseInterval(YesNoMaybe choice, const Interval& no, const Interval& yes) 393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry switch (choice) 413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case NO: return no; 433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case YES: return yes; 443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry case MAYBE: return no | yes; 451cc61b7d03cad727bbddd00cea8d78f4f6cc9047Jarkko Pöyry default: DE_FATAL("Impossible case"); 463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return Interval(); 493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 513c827367444ee418f129b2c238299f49d3264554Jarkko Poyrydouble computeMaxValue (int maxExp, int fractionBits) 523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return (deLdExp(1.0, maxExp) + 543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deLdExp(double((1ull << fractionBits) - 1), maxExp - fractionBits)); 553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // anonymous 583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 593c827367444ee418f129b2c238299f49d3264554Jarkko PoyryFloatFormat::FloatFormat (int minExp, 603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int maxExp, 613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int fractionBits, 623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bool exactPrecision, 633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry YesNoMaybe hasSubnormal_, 644fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos YesNoMaybe hasInf_, 654fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos YesNoMaybe hasNaN_) 663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_minExp (minExp) 673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_maxExp (maxExp) 683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_fractionBits (fractionBits) 693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_hasSubnormal (hasSubnormal_) 704fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos , m_hasInf (hasInf_) 714fdcdd50d72a1317dbab9f75738e5bb9ccd30634Pyry Haulos , m_hasNaN (hasNaN_) 723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_exactPrecision (exactPrecision) 733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry , m_maxValue (computeMaxValue(maxExp, fractionBits)) 743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(minExp <= maxExp); 763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*------------------------------------------------------------------------- 793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * On the definition of ULP 803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * The GLSL spec does not define ULP. However, it refers to IEEE 754, which 823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * (reportedly) uses Harrison's definition: 833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * ULP(x) is the distance between the closest floating point numbers 853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * a and be such that a <= x <= b and a != b 863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Note that this means that when x = 2^n, ULP(x) = 2^(n-p-1), i.e. it is the 883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distance to the next lowest float, not next highest. 893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Furthermore, it is assumed that ULP is calculated relative to the exact 913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * value, not the approximation. This is because otherwise a less accurate 923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * approximation could be closer in ULPs, because its ULPs are bigger. 933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * For details, see "On the definition of ulp(x)" by Jean-Michel Muller 953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *-----------------------------------------------------------------------*/ 973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 983c827367444ee418f129b2c238299f49d3264554Jarkko Poyrydouble FloatFormat::ulp (double x, double count) const 993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int exp = 0; 1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const double frac = deFractExp(deAbs(x), &exp); 1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (deIsNaN(frac)) 1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return TCU_NAN; 1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (deIsInf(frac)) 1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return deLdExp(1.0, m_maxExp - m_fractionBits); 1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (frac == 1.0) 1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Harrison's ULP: choose distance to closest (i.e. next lower) at binade 1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // boundary. 1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry --exp; 1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (frac == 0.0) 1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry exp = m_minExp; 1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // ULP cannot be lower than the smallest quantum. 1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry exp = de::max(exp, m_minExp); 1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const double oneULP = deLdExp(1.0, exp - m_fractionBits); 1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ScopedRoundingMode ctx (DE_ROUNDINGMODE_TO_POSITIVE_INF); 1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return oneULP * count; 1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Return the difference between the given nominal exponent and 1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! the exponent of the lowest significand bit of the 1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! representation of a number with this format. 1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! For normal numbers this is the number of significand bits, but 1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! for subnormals it is less and for values of exp where 2^exp is too 1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! small to represent it is <0 1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint FloatFormat::exponentShift (int exp) const 1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return m_fractionBits - de::max(m_minExp - exp, 0); 1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Return the number closest to `d` that is exactly representable with the 1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! significand bits and minimum exponent of the floatformat. Round up if 1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! `upward` is true, otherwise down. 1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyrydouble FloatFormat::round (double d, bool upward) const 1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int exp = 0; 1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const double frac = deFractExp(d, &exp); 1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int shift = exponentShift(exp); 1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const double shiftFrac = deLdExp(frac, shift); 1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const double roundFrac = upward ? deCeil(shiftFrac) : deFloor(shiftFrac); 1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return deLdExp(roundFrac, exp - shift); 1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Return the range of numbers that `d` might be converted to in the 1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! floatformat, given its limitations with infinities, subnormals and maximum 1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! exponent. 1553c827367444ee418f129b2c238299f49d3264554Jarkko PoyryInterval FloatFormat::clampValue (double d) const 1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const double rSign = deSign(d); 1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int rExp = 0; 1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(!deIsNaN(d)); 1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deFractExp(d, &rExp); 1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (rExp < m_minExp) 1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return chooseInterval(m_hasSubnormal, rSign * 0.0, d); 1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (deIsInf(d) || rExp > m_maxExp) 1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return chooseInterval(m_hasInf, rSign * getMaxValue(), rSign * TCU_INFINITY); 1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return Interval(d); 1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Return the range of numbers that might be used with this format to 1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! represent a number within `x`. 1733c827367444ee418f129b2c238299f49d3264554Jarkko PoyryInterval FloatFormat::convert (const Interval& x) const 1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Interval ret; 1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Interval tmp = x; 1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (x.hasNaN()) 1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // If NaN might be supported, NaN is a legal return value 1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_hasNaN != NO) 1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ret |= TCU_NAN; 1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // If NaN might not be supported, any (non-NaN) value is legal, 1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // _subject_ to clamping. Hence we modify tmp, not ret. 1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m_hasNaN != YES) 1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tmp = Interval::unbounded(); 1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Round both bounds _inwards_ to closest representable values. 1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!tmp.empty()) 1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ret |= clampValue(round(tmp.lo(), true)) | clampValue(round(tmp.hi(), false)); 1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // If this format's precision is not exact, the (possibly out-of-bounds) 1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // original value is also a possible result. 1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!m_exactPrecision) 1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ret |= x; 1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return ret; 2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2022e751e3e77060f699c560104e82379d3ce54f67aPyry Haulosdouble FloatFormat::roundOut (double d, bool upward, bool roundUnderOverflow) const 2032e751e3e77060f699c560104e82379d3ce54f67aPyry Haulos{ 2042e751e3e77060f699c560104e82379d3ce54f67aPyry Haulos int exp = 0; 2052e751e3e77060f699c560104e82379d3ce54f67aPyry Haulos deFractExp(d, &exp); 2062e751e3e77060f699c560104e82379d3ce54f67aPyry Haulos 2072e751e3e77060f699c560104e82379d3ce54f67aPyry Haulos if (roundUnderOverflow && exp > m_maxExp && (upward == (d < 0.0))) 2082e751e3e77060f699c560104e82379d3ce54f67aPyry Haulos return deSign(d) * getMaxValue(); 2092e751e3e77060f699c560104e82379d3ce54f67aPyry Haulos else 2102e751e3e77060f699c560104e82379d3ce54f67aPyry Haulos return round(d, upward); 2112e751e3e77060f699c560104e82379d3ce54f67aPyry Haulos} 2122e751e3e77060f699c560104e82379d3ce54f67aPyry Haulos 2132e751e3e77060f699c560104e82379d3ce54f67aPyry Haulos//! Round output of an operation. 2142e751e3e77060f699c560104e82379d3ce54f67aPyry Haulos//! \param roundUnderOverflow Can +/-inf rounded to min/max representable; 2152e751e3e77060f699c560104e82379d3ce54f67aPyry Haulos//! should be false if any of operands was inf, true otherwise. 2162e751e3e77060f699c560104e82379d3ce54f67aPyry HaulosInterval FloatFormat::roundOut (const Interval& x, bool roundUnderOverflow) const 2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Interval ret = x.nan(); 2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!x.empty()) 2212e751e3e77060f699c560104e82379d3ce54f67aPyry Haulos ret |= Interval(roundOut(x.lo(), false, roundUnderOverflow), 2222e751e3e77060f699c560104e82379d3ce54f67aPyry Haulos roundOut(x.hi(), true, roundUnderOverflow)); 2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return ret; 2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string FloatFormat::floatToHex (double x) const 2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (deIsNaN(x)) 2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return "NaN"; 2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (deIsInf(x)) 2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return (x < 0.0 ? "-" : "+") + std::string("inf"); 2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (x == 0.0) // \todo [2014-03-27 lauri] Negative zero 2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return "0.0"; 2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int exp = 0; 2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const double frac = deFractExp(deAbs(x), &exp); 2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int shift = exponentShift(exp); 2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint64 bits = deUint64(deLdExp(frac, shift)); 2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint64 whole = bits >> m_fractionBits; 2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint64 fraction = bits & ((deUint64(1) << m_fractionBits) - 1); 2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int exponent = exp + m_fractionBits - shift; 2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int numDigits = (m_fractionBits + 3) / 4; 2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint64 aligned = fraction << (numDigits * 4 - m_fractionBits); 2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry std::ostringstream oss; 2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry oss << (x < 0 ? "-" : "") 2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "0x" << whole << "." 2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << std::hex << std::setw(numDigits) << std::setfill('0') << aligned 2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry << "p" << std::dec << std::setw(0) << exponent; 2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return oss.str(); 2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string FloatFormat::intervalToHex (const Interval& interval) const 2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (interval.empty()) 2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return interval.hasNaN() ? "{ NaN }" : "{}"; 2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (interval.lo() == interval.hi()) 2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return (std::string(interval.hasNaN() ? "{ NaN, " : "{ ") + 2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry floatToHex(interval.lo()) + " }"); 2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (interval == Interval::unbounded(true)) 2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return "<any>"; 2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return (std::string(interval.hasNaN() ? "{ NaN } | " : "") + 2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry "[" + floatToHex(interval.lo()) + ", " + floatToHex(interval.hi()) + "]"); 2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename T> 2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic FloatFormat nativeFormat (void) 2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry typedef std::numeric_limits<T> Limits; 2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(Limits::radix == 2); 2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return FloatFormat(Limits::min_exponent - 1, // These have a built-in offset of one 2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Limits::max_exponent - 1, 2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Limits::digits - 1, // don't count the hidden bit 2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Limits::has_denorm != std::denorm_absent, 2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Limits::has_infinity ? YES : NO, 2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Limits::has_quiet_NaN ? YES : NO, 2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ((Limits::has_denorm == std::denorm_present) ? YES : 2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (Limits::has_denorm == std::denorm_absent) ? NO : 2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry MAYBE)); 2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2883c827367444ee418f129b2c238299f49d3264554Jarkko PoyryFloatFormat FloatFormat::nativeFloat (void) 2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return nativeFormat<float>(); 2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2933c827367444ee418f129b2c238299f49d3264554Jarkko PoyryFloatFormat FloatFormat::nativeDouble (void) 2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return nativeFormat<double>(); 2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace 2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::string; 3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing std::ostringstream; 3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing de::MovePtr; 3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing de::UniquePtr; 3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Test 3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected: 3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Test (MovePtr<FloatFormat> fmt) : m_fmt(fmt) {} 3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry double p (int e) const { return deLdExp(1.0, e); } 3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void check (const string& expr, 3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry double result, 3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry double reference) const; 3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void testULP (double arg, double ref) const; 3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void testRound (double arg, double refDown, double refUp) const; 3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry UniquePtr<FloatFormat> m_fmt; 3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Test::check (const string& expr, double result, double reference) const 3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (result != reference) 3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ostringstream oss; 3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry oss << expr << " returned " << result << ", expected " << reference; 3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TCU_FAIL(oss.str().c_str()); 3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Test::testULP (double arg, double ref) const 3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ostringstream oss; 3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry oss << "ulp(" << arg << ")"; 3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry check(oss.str(), m_fmt->ulp(arg), ref); 3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Test::testRound (double arg, double refDown, double refUp) const 3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ostringstream oss; 3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry oss << "round(" << arg << ", false)"; 3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry check(oss.str(), m_fmt->round(arg, false), refDown); 3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry ostringstream oss; 3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry oss << "round(" << arg << ", true)"; 3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry check(oss.str(), m_fmt->round(arg, true), refUp); 3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass TestBinary32 : public Test 3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TestBinary32 (void) 3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : Test (MovePtr<FloatFormat>(new FloatFormat(-126, 127, 23, true))) {} 3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry void runTest (void) const; 3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid TestBinary32::runTest (void) const 3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry testULP(p(0), p(-24)); 3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry testULP(p(0) + p(-23), p(-23)); 3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry testULP(p(-124), p(-148)); 3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry testULP(p(-125), p(-149)); 3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry testULP(p(-125) + p(-140), p(-148)); 3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry testULP(p(-126), p(-149)); 3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry testULP(p(-130), p(-149)); 3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry testRound(p(0) + p(-20) + p(-40), p(0) + p(-20), p(0) + p(-20) + p(-23)); 3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry testRound(p(-126) - p(-150), p(-126) - p(-149), p(-126)); 3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TCU_CHECK(m_fmt->floatToHex(p(0)) == "0x1.000000p0"); 3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TCU_CHECK(m_fmt->floatToHex(p(8) + p(-4)) == "0x1.001000p8"); 3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TCU_CHECK(m_fmt->floatToHex(p(-140)) == "0x0.000400p-126"); 3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TCU_CHECK(m_fmt->floatToHex(p(-140)) == "0x0.000400p-126"); 3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TCU_CHECK(m_fmt->floatToHex(p(-126) + p(-125)) == "0x1.800000p-125"); 3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // anonymous 3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid FloatFormat_selfTest (void) 3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry TestBinary32 test32; 3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry test32.runTest(); 3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // tcu 391