Browse Source

math: reduce macro madness in half.h.

undefined
Sam Hocevar 10 years ago
parent
commit
3c4c41b298
1 changed files with 86 additions and 42 deletions
  1. +86
    -42
      src/lol/math/half.h

+ 86
- 42
src/lol/math/half.h View File

@@ -26,7 +26,10 @@ namespace lol
#undef min
#undef max

namespace half_ops { struct base {}; }

class half
: half_ops::base
{
public:
/* Constructors. Always inline so that the code can work in registers
@@ -118,6 +121,10 @@ public:

static_assert(sizeof(half) == 2, "sizeof(half) == 2");

/*
* Standard math and GLSL functions
*/

static inline half min(half a, half b) { return a < b ? a : b; }
static inline half max(half a, half b) { return a > b ? a : b; }
static inline float fmod(half a, half b)
@@ -135,51 +142,88 @@ static inline half clamp(half x, half a, half b)
return (x < a) ? a : (x > b) ? b : x;
}

/*
* Standard math operators
*/

#define DECLARE_COERCE_HALF_NUMERIC_OPS(op, type, ret, x2, h2) \
inline ret operator op(type x, half h) { return x2 op h2; } \
inline ret operator op(half h, type x) { return h2 op x2; } \
inline type &operator op##=(type &x, half h) { return x = x op h2; } \
inline half &operator op##=(half &h, type x) { return h = h op x2; }

#define DECLARE_COERCE_HALF_BOOL_OPS(op, type, x2, h2) \
inline bool operator op(type x, half h) { return x2 op h2; } \
inline bool operator op(half h, type x) { return h2 op x2; }
namespace half_ops
{

#define DECLARE_COERCE_HALF_OPS(type, ret, x2, h2) \
DECLARE_COERCE_HALF_NUMERIC_OPS(+, type, ret, x2, h2) \
DECLARE_COERCE_HALF_NUMERIC_OPS(-, type, ret, x2, h2) \
DECLARE_COERCE_HALF_NUMERIC_OPS(*, type, ret, x2, h2) \
DECLARE_COERCE_HALF_NUMERIC_OPS(/, type, ret, x2, h2) \
#define DECLARE_HALF_NUMERIC_OPS(op) \
/* integral + half */ \
template<typename T> static inline \
typename std::enable_if<std::is_integral<T>::value,half>::type \
operator op(T x, half h) { return (half)(int)x op h; } \
\
template<typename T> static inline \
typename std::enable_if<std::is_integral<T>::value,T&>::type \
operator op##=(T &x, half h) { return x = x op h; } \
\
/* half + integral */ \
template<typename T> static inline \
typename std::enable_if<std::is_integral<T>::value,half>::type \
operator op(half h, T x) { return h op (half)(int)x; } \
\
template<typename T> static inline \
typename std::enable_if<std::is_integral<T>::value,half&>::type \
operator op##=(half &h, T x) { return h = h op x; } \
\
/* floating point + half */ \
template<typename T> static inline \
typename std::enable_if<std::is_floating_point<T>::value,T>::type \
operator op(T x, half h) { return x op (T)h; } \
\
DECLARE_COERCE_HALF_BOOL_OPS(==, type, x2, h2) \
DECLARE_COERCE_HALF_BOOL_OPS(!=, type, x2, h2) \
DECLARE_COERCE_HALF_BOOL_OPS(>=, type, x2, h2) \
DECLARE_COERCE_HALF_BOOL_OPS(<=, type, x2, h2) \
DECLARE_COERCE_HALF_BOOL_OPS(>, type, x2, h2) \
DECLARE_COERCE_HALF_BOOL_OPS(<, type, x2, h2)

#define DECLARE_COERCE_TO_HALF_OPS(type) \
DECLARE_COERCE_HALF_OPS(type, half, (half)(int)x, h)

#define DECLARE_COERCE_FROM_HALF_OPS(type) \
DECLARE_COERCE_HALF_OPS(type, type, x, (type)h)

/* Only provide coercion rules above int32_t, since the standard says
* all smaller base types are coerced to int. */
DECLARE_COERCE_TO_HALF_OPS(int32_t)
DECLARE_COERCE_TO_HALF_OPS(uint32_t)
DECLARE_COERCE_TO_HALF_OPS(int64_t)
DECLARE_COERCE_TO_HALF_OPS(uint64_t)

DECLARE_COERCE_FROM_HALF_OPS(float)
DECLARE_COERCE_FROM_HALF_OPS(double)
DECLARE_COERCE_FROM_HALF_OPS(ldouble)

#undef DECLARE_COERCE_HALF_NUMERIC_OPS
#undef DECLARE_COERCE_HALF_OPS
#undef DECLARE_COERCE_TO_HALF_OPS
#undef DECLARE_COERCE_FROM_HALF_OPS
template<typename T> static inline \
typename std::enable_if<std::is_floating_point<T>::value,T&>::type \
operator op##=(T &x, half h) { return x = x op h; } \
\
/* half + floating point */ \
template<typename T> static inline \
typename std::enable_if<std::is_floating_point<T>::value,T>::type \
operator op(half h, T x) { return (T)h op x; } \
\
template<typename T> static inline \
typename std::enable_if<std::is_floating_point<T>::value,half&>::type \
operator op##=(half &h, T x) { return h = h op x; }

DECLARE_HALF_NUMERIC_OPS(+)
DECLARE_HALF_NUMERIC_OPS(-)
DECLARE_HALF_NUMERIC_OPS(*)
DECLARE_HALF_NUMERIC_OPS(/)

#undef DECLARE_HALF_NUMERIC_OPS

#define DECLARE_HALF_BOOL_OPS(op) \
/* integral == half */ \
template<typename T> static inline \
typename std::enable_if<std::is_integral<T>::value,bool>::type \
operator op(T x, half h) { return (half)(int)x op h; } \
\
/* half == integral */ \
template<typename T> static inline \
typename std::enable_if<std::is_integral<T>::value,bool>::type \
operator op(half h, T x) { return h op (half)(int)x; } \
\
/* floating point == half */ \
template<typename T> static inline \
typename std::enable_if<std::is_floating_point<T>::value,bool>::type \
operator op(T x, half h) { return x op (T)h; } \
\
/* half == floating point */ \
template<typename T> static inline \
typename std::enable_if<std::is_floating_point<T>::value,bool>::type \
operator op(half h, T x) { return (T)h op x; }

DECLARE_HALF_BOOL_OPS(==)
DECLARE_HALF_BOOL_OPS(!=)
DECLARE_HALF_BOOL_OPS(>)
DECLARE_HALF_BOOL_OPS(<)
DECLARE_HALF_BOOL_OPS(>=)
DECLARE_HALF_BOOL_OPS(<=)

#undef DECLARE_HALF_BOOL_OPS

} /* namespace half_ops */

} /* namespace lol */



Loading…
Cancel
Save