⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 half.h

📁 对gif
💻 H
📖 第 1 页 / 共 2 页
字号:
//	If e is 0, and m is not zero, h is a denormalized number:
//
//	            S    -14
//	    h = (-1)  * 2     * 0.m
//
//	If e and m are both zero, h is zero:
//
//	    h = 0.0
//
//	If e is 31, h is an "infinity" or "not a number" (NAN),
//	depending on whether m is zero or not.
//
//	Examples:
//
//	    0 00000 0000000000 = 0.0
//	    0 01110 0000000000 = 0.5
//	    0 01111 0000000000 = 1.0
//	    0 10000 0000000000 = 2.0
//	    0 10000 1000000000 = 3.0
//	    1 10101 1111000001 = -124.0625
//	    0 11111 0000000000 = +infinity
//	    1 11111 0000000000 = -infinity
//	    0 11111 1000000000 = NAN
//	    1 11111 1111111111 = NAN
//
// Conversion:
//
//	Converting from a float to a half requires some non-trivial bit
//	manipulations.  In some cases, this makes conversion relatively
//	slow, but the most common case is accelerated via table lookups.
//
//	Converting back from a half to a float is easier because we don't
//	have to do any rounding.  In addition, there are only 65536
//	different half numbers; we can convert each of those numbers once
//	and store the results in a table.  Later, all conversions can be
//	done using only simple table lookups.
//
//---------------------------------------------------------------------------


//--------------------
// Simple constructors
//--------------------

inline
half::half ()
{
    // no initialization
}


//----------------------------
// Half-from-float constructor
//----------------------------

inline
half::half (float f)
{
    uif x;

    x.f = f;

    if (f == 0)
    {
	//
	// Common special case - zero.
	// Preserve the zero's sign bit.
	//

	_h = (x.i >> 16);
    }
    else
    {
	//
	// We extract the combined sign and exponent, e, from our
	// floating-point number, f.  Then we convert e to the sign
	// and exponent of the half number via a table lookup.
	//
	// For the most common case, where a normalized half is produced,
	// the table lookup returns a non-zero value; in this case, all
	// we have to do is round f's significand to 10 bits and combine
	// the result with e.
	//
	// For all other cases (overflow, zeroes, denormalized numbers
	// resulting from underflow, infinities and NANs), the table
	// lookup returns zero, and we call a longer, non-inline function
	// to do the float-to-half conversion.
	//

	register int e = (x.i >> 23) & 0x000001ff;

	e = _eLut[e];

	if (e)
	{
	    //
	    // Simple case - round the significand, m, to 10
	    // bits and combine it with the sign and exponent.
	    //

	    register int m = x.i & 0x007fffff;
	    _h = e + ((m + 0x00000fff + ((m >> 13) & 1)) >> 13);
	}
	else
	{
	    //
	    // Difficult case - call a function.
	    //

	    _h = convert (x.i);
	}
    }
}


//------------------------------------------
// Half-to-float conversion via table lookup
//------------------------------------------

inline
half::operator float () const
{
    return _toFloat[_h].f;
}


//-------------------------
// Round to n-bit precision
//-------------------------

inline half
half::round (unsigned int n) const
{
    //
    // Parameter check.
    //

    if (n >= 10)
	return *this;

    //
    // Disassemble h into the sign, s,
    // and the combined exponent and significand, e.
    //

    unsigned short s = _h & 0x8000;
    unsigned short e = _h & 0x7fff;

    //
    // Round the exponent and significand to the nearest value
    // where ones occur only in the (10-n) most significant bits.
    // Note that the exponent adjusts automatically if rounding
    // up causes the significand to overflow.
    //

    e >>= 9 - n;
    e  += e & 1;
    e <<= 9 - n;

    //
    // Check for exponent overflow.
    //

    if (e >= 0x7c00)
    {
	//
	// Overflow occurred -- truncate instead of rounding.
	//

	e = _h;
	e >>= 10 - n;
	e <<= 10 - n;
    }

    //
    // Put the original sign bit back.
    //

    half h;
    h._h = s | e;

    return h;
}


//-----------------------
// Other inline functions
//-----------------------

inline half	
half::operator - () const
{
    half h;
    h._h = _h ^ 0x8000;
    return h;
}


inline half &
half::operator = (half h)
{
    _h = h._h;
    return *this;
}


inline half &
half::operator = (float f)
{
    *this = half (f);
    return *this;
}


inline half &
half::operator += (half h)
{
    *this = half (float (*this) + float (h));
    return *this;
}


inline half &
half::operator += (float f)
{
    *this = half (float (*this) + f);
    return *this;
}


inline half &
half::operator -= (half h)
{
    *this = half (float (*this) - float (h));
    return *this;
}


inline half &
half::operator -= (float f)
{
    *this = half (float (*this) - f);
    return *this;
}


inline half &
half::operator *= (half h)
{
    *this = half (float (*this) * float (h));
    return *this;
}


inline half &
half::operator *= (float f)
{
    *this = half (float (*this) * f);
    return *this;
}


inline half &
half::operator /= (half h)
{
    *this = half (float (*this) / float (h));
    return *this;
}


inline half &
half::operator /= (float f)
{
    *this = half (float (*this) / f);
    return *this;
}


inline bool	
half::isFinite () const
{
    unsigned short e = (_h >> 10) & 0x001f;
    return e < 31;
}


inline bool
half::isNormalized () const
{
    unsigned short e = (_h >> 10) & 0x001f;
    return e > 0 && e < 31;
}


inline bool
half::isDenormalized () const
{
    unsigned short e = (_h >> 10) & 0x001f;
    unsigned short m =  _h & 0x3ff;
    return e == 0 && m != 0;
}


inline bool
half::isZero () const
{
    return (_h & 0x7fff) == 0;
}


inline bool
half::isNan () const
{
    unsigned short e = (_h >> 10) & 0x001f;
    unsigned short m =  _h & 0x3ff;
    return e == 31 && m != 0;
}


inline bool
half::isInfinity () const
{
    unsigned short e = (_h >> 10) & 0x001f;
    unsigned short m =  _h & 0x3ff;
    return e == 31 && m == 0;
}


inline bool	
half::isNegative () const
{
    return (_h & 0x8000) != 0;
}


inline half
half::posInf ()
{
    half h;
    h._h = 0x7c00;
    return h;
}


inline half
half::negInf ()
{
    half h;
    h._h = 0xfc00;
    return h;
}


inline half
half::qNan ()
{
    half h;
    h._h = 0x7fff;
    return h;
}


inline half
half::sNan ()
{
    half h;
    h._h = 0x7dff;
    return h;
}


inline unsigned short
half::bits () const
{
    return _h;
}


inline void
half::setBits (unsigned short bits)
{
    _h = bits;
}

#undef HALF_EXPORT_CONST

#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -