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