Skip to content

Commit

Permalink
constexpr as much of half as possible (#87)
Browse files Browse the repository at this point in the history
This is the remaining section of `half` that can be easily constexpr.

The way they are currently implemented, the basic half-from-float ctr
and half-to-float cast are not able to be constexpr, and that in turn
prevents almost all the arithmetic operations (which convert to float,
do the math, then convert back) from being constexpr.

This is the closest we're going to get with the current implementations.
The most offensive parts to constexpr are the use of table lookups, and
the strange overflow() trying to raise a hardware overflow exception.
It's not hard to imagine alternate implementations that don't work the
same way at all, but we must leave that for another day (and maybe for
somebody who is more willing to chase down ever corner case of IEEE754
logic).

I added private mantissa() and exponent() helper methods, using those
helped me make some other public methods be constexpr in C++11 by
making their body be a single return statement (if you spread over
multiple statements, you become constexpr in C++14 only on some
compilers). We could make those public if people think there are other
uses for these helpers.

Signed-off-by: Larry Gritz <[email protected]>
  • Loading branch information
lgritz authored Feb 5, 2021
1 parent 31f93d3 commit 1e7bb58
Showing 1 changed file with 53 additions and 58 deletions.
111 changes: 53 additions & 58 deletions src/Imath/half.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ class half
constexpr half(FromBitsTag, unsigned short bits) noexcept;
// rule of 5
~half() noexcept = default;
half (const half&) noexcept = default;
half (half&&) noexcept = default;
constexpr half (const half&) noexcept = default;
constexpr half (half&&) noexcept = default;

//--------------------
// Conversion to float
Expand All @@ -98,7 +98,7 @@ class half
// Unary minus
//------------

half operator-() const noexcept;
constexpr half operator-() const noexcept;

//-----------
// Assignment
Expand Down Expand Up @@ -126,7 +126,7 @@ class half
// bits will be zero.
//---------------------------------------------------------

half round (unsigned int n) const noexcept;
IMATH_CONSTEXPR14 half round (unsigned int n) const noexcept;

//--------------------------------------------------------------------
// Classification:
Expand All @@ -149,13 +149,13 @@ class half
// is set (negative)
//--------------------------------------------------------------------

bool isFinite() const noexcept;
bool isNormalized() const noexcept;
bool isDenormalized() const noexcept;
bool isZero() const noexcept;
bool isNan() const noexcept;
bool isInfinity() const noexcept;
bool isNegative() const noexcept;
constexpr bool isFinite() const noexcept;
constexpr bool isNormalized() const noexcept;
constexpr bool isDenormalized() const noexcept;
constexpr bool isZero() const noexcept;
constexpr bool isNan() const noexcept;
constexpr bool isInfinity() const noexcept;
constexpr bool isNegative() const noexcept;

//--------------------------------------------
// Special values
Expand All @@ -171,10 +171,10 @@ class half
// pattern 0111110111111111
//--------------------------------------------

static half posInf() noexcept;
static half negInf() noexcept;
static half qNan() noexcept;
static half sNan() noexcept;
static constexpr half posInf() noexcept;
static constexpr half negInf() noexcept;
static constexpr half qNan() noexcept;
static constexpr half sNan() noexcept;

//--------------------------------------
// Access to the internal representation
Expand All @@ -193,6 +193,8 @@ class half
private:
IMATH_EXPORT static short convert (int i) noexcept;
IMATH_EXPORT static float overflow() noexcept;
constexpr unsigned short mantissa() const noexcept;
constexpr unsigned short exponent() const noexcept;

unsigned short _h;

Expand Down Expand Up @@ -464,7 +466,7 @@ inline half::operator float() const noexcept
// Round to n-bit precision
//-------------------------

inline half
inline IMATH_CONSTEXPR14 half
half::round (unsigned int n) const noexcept
{
//
Expand Down Expand Up @@ -512,8 +514,7 @@ half::round (unsigned int n) const noexcept
// Put the original sign bit back.
//

half h;
h._h = s | e;
half h(FromBits, s | e);

return h;
}
Expand All @@ -522,12 +523,10 @@ half::round (unsigned int n) const noexcept
// Other inline functions
//-----------------------

inline half
inline constexpr half
half::operator-() const noexcept
{
half h;
h._h = _h ^ 0x8000;
return h;
return half(FromBits, bits() ^ 0x8000);
}

inline half&
Expand Down Expand Up @@ -593,86 +592,82 @@ half::operator/= (float f) noexcept
return *this;
}

inline bool
inline constexpr unsigned short
half::mantissa() const noexcept
{
return _h & 0x3ff;
}

inline constexpr unsigned short
half::exponent() const noexcept
{
return (_h >> 10) & 0x001f;
}

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

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

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

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

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

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

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

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

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

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

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

inline constexpr unsigned short
Expand Down

0 comments on commit 1e7bb58

Please sign in to comment.