13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifndef _TCUFLOAT_HPP 23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#define _TCUFLOAT_HPP 33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*------------------------------------------------------------------------- 43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program Tester Core 53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * ---------------------------------------- 63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project 83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License"); 103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License. 113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at 123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * http://www.apache.org/licenses/LICENSE-2.0 143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software 163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS, 173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and 193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License. 203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*! 223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file 233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Reconfigurable floating-point value template. 243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/ 253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuDefs.hpp" 273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// For memcpy(). 293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <string.h> 303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 313c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace tcu 323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 343c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum FloatFlags 353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry FLOAT_HAS_SIGN = (1<<0), 373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry FLOAT_SUPPORT_DENORM = (1<<1) 383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*! 413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Floating-point format template 423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * This template implements arbitrary floating-point handling. Template 443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * can be used for conversion between different formats and checking 453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * various properties of floating-point values. 463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/ 473c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename StorageType_, int ExponentBits, int MantissaBits, int ExponentBias, deUint32 Flags> 483c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Float 493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 503c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic: 513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry typedef StorageType_ StorageType; 523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry enum 543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry EXPONENT_BITS = ExponentBits, 563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry MANTISSA_BITS = MantissaBits, 573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry EXPONENT_BIAS = ExponentBias, 583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry FLAGS = Flags, 593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry }; 603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry Float (void); 623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry explicit Float (StorageType value); 633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry explicit Float (float v); 643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry explicit Float (double v); 653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry template <typename OtherStorageType, int OtherExponentBits, int OtherMantissaBits, int OtherExponentBias, deUint32 OtherFlags> 673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static Float convert (const Float<OtherStorageType, OtherExponentBits, OtherMantissaBits, OtherExponentBias, OtherFlags>& src); 683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static inline Float convert (const Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags>& src) { return src; } 703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry /*--------------------------------------------------------------------*//*! 723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Construct floating point value 733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param sign Sign. Must be +1/-1 743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param exponent Exponent in range [1-ExponentBias, ExponentBias+1] 753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param mantissa Mantissa bits with implicit leading bit explicitly set 763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \return The specified float 773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * This function constructs a floating point value from its inputs. 793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * The normally implicit leading bit of the mantissa must be explicitly set. 803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * The exponent normally used for zero/subnormals is an invalid input. Such 813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * values are specified with the leading mantissa bit of zero and the lowest 823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * normal exponent (1-ExponentBias). Additionally having both exponent and 833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * mantissa set to zero is a shorthand notation for the correctly signed 843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * floating point zero. Inf and NaN must be specified directly with an 853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * exponent of ExponentBias+1 and the appropriate mantissa (with leading 863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * bit set) 873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/ 883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static inline Float construct (int sign, int exponent, StorageType mantissa); 893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry /*--------------------------------------------------------------------*//*! 913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Construct floating point value. Explicit version 923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param sign Sign. Must be +1/-1 933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param exponent Exponent in range [-ExponentBias, ExponentBias+1] 943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param mantissa Mantissa bits 953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \return The specified float 963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * This function constructs a floating point value from its inputs with 983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * minimal intervention. 993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * The sign is turned into a sign bit and the exponent bias is added. 1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See IEEE-754 for additional information on the inputs and 1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * the encoding of special values. 1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/ 1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static Float constructBits (int sign, int exponent, StorageType mantissaBits); 1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry StorageType bits (void) const { return m_value; } 1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry float asFloat (void) const; 1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry double asDouble (void) const; 1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry inline int signBit (void) const { return (m_value >> (ExponentBits+MantissaBits)) & 1; } 1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry inline StorageType exponentBits (void) const { return (m_value >> MantissaBits) & ((StorageType(1)<<ExponentBits)-1); } 1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry inline StorageType mantissaBits (void) const { return m_value & ((StorageType(1)<<MantissaBits)-1); } 1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry inline int sign (void) const { return signBit() ? -1 : 1; } 1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry inline int exponent (void) const { return isDenorm() ? 1 - ExponentBias : (int)exponentBits() - ExponentBias; } 1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry inline StorageType mantissa (void) const { return isZero() || isDenorm() ? mantissaBits() : (mantissaBits() | (StorageType(1)<<MantissaBits)); } 1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry inline bool isInf (void) const { return exponentBits() == ((1<<ExponentBits)-1) && mantissaBits() == 0; } 1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry inline bool isNaN (void) const { return exponentBits() == ((1<<ExponentBits)-1) && mantissaBits() != 0; } 1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry inline bool isZero (void) const { return exponentBits() == 0 && mantissaBits() == 0; } 1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry inline bool isDenorm (void) const { return exponentBits() == 0 && mantissaBits() != 0; } 1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static Float zero (int sign); 1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static Float inf (int sign); 1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry static Float nan (void); 1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate: 1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry StorageType m_value; 1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}; 1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Common floating-point types. 1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypedef Float<deUint16, 5, 10, 15, FLOAT_HAS_SIGN|FLOAT_SUPPORT_DENORM> Float16; //!< IEEE 754-2008 16-bit floating-point value 1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypedef Float<deUint32, 8, 23, 127, FLOAT_HAS_SIGN|FLOAT_SUPPORT_DENORM> Float32; //!< IEEE 754 32-bit floating-point value 1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypedef Float<deUint64, 11, 52, 1023, FLOAT_HAS_SIGN|FLOAT_SUPPORT_DENORM> Float64; //!< IEEE 754 64-bit floating-point value 1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename StorageType, int ExponentBits, int MantissaBits, int ExponentBias, deUint32 Flags> 1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags>::Float (void) 1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_value(0) 1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename StorageType, int ExponentBits, int MantissaBits, int ExponentBias, deUint32 Flags> 1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags>::Float (StorageType value) 1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_value(value) 1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename StorageType, int ExponentBits, int MantissaBits, int ExponentBias, deUint32 Flags> 1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags>::Float (float value) 1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_value(0) 1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint32 u32; 1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry memcpy(&u32, &value, sizeof(deUint32)); 1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *this = convert(Float32(u32)); 1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename StorageType, int ExponentBits, int MantissaBits, int ExponentBias, deUint32 Flags> 1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags>::Float (double value) 1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry : m_value(0) 1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint64 u64; 1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry memcpy(&u64, &value, sizeof(deUint64)); 1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *this = convert(Float64(u64)); 1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename StorageType, int ExponentBits, int MantissaBits, int ExponentBias, deUint32 Flags> 1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline float Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags>::asFloat (void) const 1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry float v; 1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint32 u32 = Float32::convert(*this).bits(); 1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry memcpy(&v, &u32, sizeof(deUint32)); 1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return v; 1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename StorageType, int ExponentBits, int MantissaBits, int ExponentBias, deUint32 Flags> 1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline double Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags>::asDouble (void) const 1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry double v; 1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint64 u64 = Float64::convert(*this).bits(); 1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry memcpy(&v, &u64, sizeof(deUint64)); 1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return v; 1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename StorageType, int ExponentBits, int MantissaBits, int ExponentBias, deUint32 Flags> 1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags> Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags>::zero (int sign) 1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(sign == 1 || ((Flags & FLOAT_HAS_SIGN) && sign == -1)); 1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return Float(StorageType((sign > 0 ? 0ull : 1ull) << (ExponentBits+MantissaBits))); 1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename StorageType, int ExponentBits, int MantissaBits, int ExponentBias, deUint32 Flags> 1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags> Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags>::inf (int sign) 1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(sign == 1 || ((Flags & FLOAT_HAS_SIGN) && sign == -1)); 1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return Float(StorageType(((sign > 0 ? 0ull : 1ull) << (ExponentBits+MantissaBits)) | (((1ull<<ExponentBits)-1) << MantissaBits))); 1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename StorageType, int ExponentBits, int MantissaBits, int ExponentBias, deUint32 Flags> 1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyryinline Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags> Float<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags>::nan (void) 1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return Float(StorageType((1ull<<(ExponentBits+MantissaBits))-1)); 2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename StorageType, int ExponentBits, int MantissaBits, int ExponentBias, deUint32 Flags> 2043c827367444ee418f129b2c238299f49d3264554Jarkko PoyryFloat<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags> 2053c827367444ee418f129b2c238299f49d3264554Jarkko PoyryFloat<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags>::construct 2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (int sign, int exponent, StorageType mantissa) 2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Repurpose this otherwise invalid input as a shorthand notation for zero (no need for caller to care about internal representation) 2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isShorthandZero = exponent == 0 && mantissa == 0; 2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Handles the typical notation for zero (min exponent, mantissa 0). Note that the exponent usually used exponent (-ExponentBias) for zero/subnormals is not used. 2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Instead zero/subnormals have the (normally implicit) leading mantissa bit set to zero. 2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const bool isDenormOrZero = (exponent == 1 - ExponentBias) && (mantissa >> MantissaBits == 0); 2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const StorageType s = StorageType(sign < 0 ? 1 : 0) << (ExponentBits+MantissaBits); 2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const StorageType exp = (isShorthandZero || isDenormOrZero) ? StorageType(0) : StorageType(exponent + ExponentBias); 2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(sign == +1 || sign == -1); 2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(isShorthandZero || isDenormOrZero || mantissa >> MantissaBits == 1); 2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(exp >> ExponentBits == 0); 2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return Float(StorageType(s | (exp << MantissaBits) | (mantissa & ((StorageType(1)<<MantissaBits)-1)))); 2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename StorageType, int ExponentBits, int MantissaBits, int ExponentBias, deUint32 Flags> 2253c827367444ee418f129b2c238299f49d3264554Jarkko PoyryFloat<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags> 2263c827367444ee418f129b2c238299f49d3264554Jarkko PoyryFloat<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags>::constructBits 2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (int sign, int exponent, StorageType mantissaBits) 2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const StorageType signBit = sign < 0 ? 1 : 0; 2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const StorageType exponentBits = exponent + ExponentBias; 2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(sign == +1 || sign == -1 ); 2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(exponentBits >> ExponentBits == 0); 2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(mantissaBits >> MantissaBits == 0); 2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return Float(StorageType((signBit << (ExponentBits+MantissaBits)) | (exponentBits << MantissaBits) | (mantissaBits))); 2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename StorageType, int ExponentBits, int MantissaBits, int ExponentBias, deUint32 Flags> 2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate <typename OtherStorageType, int OtherExponentBits, int OtherMantissaBits, int OtherExponentBias, deUint32 OtherFlags> 2413c827367444ee418f129b2c238299f49d3264554Jarkko PoyryFloat<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags> 2423c827367444ee418f129b2c238299f49d3264554Jarkko PoyryFloat<StorageType, ExponentBits, MantissaBits, ExponentBias, Flags>::convert 2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry (const Float<OtherStorageType, OtherExponentBits, OtherMantissaBits, OtherExponentBias, OtherFlags>& other) 2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!(Flags & FLOAT_HAS_SIGN) && other.sign() < 0) 2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Negative number, truncate to zero. 2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return zero(+1); 2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (other.isInf()) 2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return inf(other.sign()); 2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (other.isNaN()) 2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return nan(); 2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else if (other.isZero()) 2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return zero(other.sign()); 2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int eMin = 1 - ExponentBias; 2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const int eMax = ((1<<ExponentBits)-2) - ExponentBias; 2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const StorageType s = StorageType(other.signBit()) << (ExponentBits+MantissaBits); // \note Not sign, but sign bit. 2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int e = other.exponent(); 2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint64 m = other.mantissa(); 2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Normalize denormalized values prior to conversion. 2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry while (!(m & (1ull<<OtherMantissaBits))) 2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m <<= 1; 2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry e -= 1; 2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (e < eMin) 2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Underflow. 2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if ((Flags & FLOAT_SUPPORT_DENORM) && (eMin-e-1 <= MantissaBits)) 2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Shift and round (RTE). 2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int bitDiff = (OtherMantissaBits-MantissaBits) + (eMin-e); 2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint64 half = (1ull << (bitDiff - 1)) - 1; 2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint64 bias = (m >> bitDiff) & 1; 2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return Float(StorageType(s | (m + half + bias) >> bitDiff)); 2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return zero(other.sign()); 2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Remove leading 1. 2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m = m & ~(1ull<<OtherMantissaBits); 2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (MantissaBits < OtherMantissaBits) 2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Round mantissa (round to nearest even). 3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int bitDiff = OtherMantissaBits-MantissaBits; 3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint64 half = (1ull << (bitDiff - 1)) - 1; 3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint64 bias = (m >> bitDiff) & 1; 3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m = (m + half + bias) >> bitDiff; 3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (m & (1ull<<MantissaBits)) 3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Overflow in mantissa. 3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m = 0; 3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry e += 1; 3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int bitDiff = MantissaBits-OtherMantissaBits; 3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry m = m << bitDiff; 3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (e > eMax) 3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry // Overflow. 3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return inf(other.sign()); 3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(de::inRange(e, eMin, eMax)); 3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(((e + ExponentBias) & ~((1ull<<ExponentBits)-1)) == 0); 3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT((m & ~((1ull<<MantissaBits)-1)) == 0); 3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return Float(StorageType(s | (StorageType(e + ExponentBias) << MantissaBits) | m)); 3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // tcu 3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif // _TCUFLOAT_HPP 340