diff --git a/src/lol/math/half.h b/src/lol/math/half.h index f5c6f597..23031e7e 100644 --- a/src/lol/math/half.h +++ b/src/lol/math/half.h @@ -31,6 +31,7 @@ public: inline half(int f) { *this = makefast((float)f); } inline half(float f) { *this = makefast(f); } inline half(double f) { *this = makefast((float)f); } + inline half(long double f) { *this = makefast((float)f); } inline int is_nan() const { @@ -56,8 +57,19 @@ public: inline half &operator =(int f) { return *this = makefast((float)f); } inline half &operator =(float f) { return *this = makefast(f); } inline half &operator =(double f) { return *this = makefast((float)f); } - inline operator int() const { return (int)tofloat(*this); } + inline half &operator =(long double f) { return *this = makefast((float)f); } + inline operator int8_t() const { return (int8_t)(float)*this; } + inline operator uint8_t() const { return (uint8_t)(float)*this; } + inline operator int16_t() const { return (int16_t)(float)*this; } + inline operator uint16_t() const { return (uint16_t)(float)*this; } + inline operator int32_t() const { return (int32_t)(float)*this; } + inline operator uint32_t() const { return (uint32_t)(float)*this; } + inline operator int64_t() const { return (int64_t)(float)*this; } + inline operator uint64_t() const { return (uint64_t)(float)*this; } + inline operator float() const { return tofloat(*this); } + inline operator double() const { return tofloat(*this); } + inline operator long double() const { return tofloat(*this); } static float tofloat(half h); @@ -78,19 +90,11 @@ public: inline half operator -() const { return makebits(bits ^ 0x8000u); } inline half operator +() const { return *this; } - inline half &operator +=(float f) { return (*this = (half)(*this + f)); } - inline half &operator -=(float f) { return (*this = (half)(*this - f)); } - inline half &operator *=(float f) { return (*this = (half)(*this * f)); } - inline half &operator /=(float f) { return (*this = (half)(*this / f)); } inline half &operator +=(half h) { return (*this = (half)(*this + h)); } inline half &operator -=(half h) { return (*this = (half)(*this - h)); } inline half &operator *=(half h) { return (*this = (half)(*this * h)); } inline half &operator /=(half h) { return (*this = (half)(*this / h)); } - inline float operator +(float f) const { return (float)*this + f; } - inline float operator -(float f) const { return (float)*this - f; } - inline float operator *(float f) const { return (float)*this * f; } - inline float operator /(float f) const { return (float)*this / f; } inline float operator +(half h) const { return (float)*this + (float)h; } inline float operator -(half h) const { return (float)*this - (float)h; } inline float operator *(half h) const { return (float)*this * (float)h; } @@ -110,15 +114,52 @@ public: uint16_t bits; }; -inline float &operator +=(float &f, half h) { return f += (float)h; } -inline float &operator -=(float &f, half h) { return f -= (float)h; } -inline float &operator *=(float &f, half h) { return f *= (float)h; } -inline float &operator /=(float &f, half h) { return f /= (float)h; } - -inline float operator +(float f, half h) { return f + (float)h; } -inline float operator -(float f, half h) { return f - (float)h; } -inline float operator *(float f, half h) { return f * (float)h; } -inline float operator /(float f, half h) { return f / (float)h; } +#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; } + +#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) \ + \ + 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) + +DECLARE_COERCE_TO_HALF_OPS(int8_t) +DECLARE_COERCE_TO_HALF_OPS(uint8_t) +DECLARE_COERCE_TO_HALF_OPS(int16_t) +DECLARE_COERCE_TO_HALF_OPS(uint16_t) +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(long double) + +#undef DECLARE_COERCE_HALF_NUMERIC_OPS +#undef DECLARE_COERCE_HALF_OPS +#undef DECLARE_COERCE_TO_HALF_OPS +#undef DECLARE_COERCE_FROM_HALF_OPS } /* namespace lol */ diff --git a/src/lol/math/vector.h b/src/lol/math/vector.h index dffcaa55..a66f1bb5 100644 --- a/src/lol/math/vector.h +++ b/src/lol/math/vector.h @@ -1123,7 +1123,7 @@ static inline Quat operator /(Quat x, Quat const &y) \ DECLARE_VEC_3_COERCE_OPS(Vec3, static, type, type, type) -#define DECLARE_ALL_VECTOR_COERCE_OPS_INNER(tname, tlow, thigh) \ +#define DECLARE_VEC_ANY_COERCE_OPS(tname, tlow, thigh) \ DECLARE_BINARY_COERCE_OPS(tname, static, tlow, thigh, thigh) \ DECLARE_BINARY_COERCE_OPS(tname, static, thigh, tlow, thigh) \ \ @@ -1131,22 +1131,22 @@ static inline Quat operator /(Quat x, Quat const &y) DECLARE_VECTOR_COERCE_OPS(tname, static, thigh, tlow, thigh) #define DECLARE_ALL_VECTOR_COERCE_OPS(tlow, thigh) \ - DECLARE_ALL_VECTOR_COERCE_OPS_INNER(Vec2, tlow, thigh) \ - DECLARE_ALL_VECTOR_COERCE_OPS_INNER(Vec3, tlow, thigh) \ - DECLARE_ALL_VECTOR_COERCE_OPS_INNER(Vec4, tlow, thigh) \ + DECLARE_VEC_ANY_COERCE_OPS(Vec2, tlow, thigh) \ + DECLARE_VEC_ANY_COERCE_OPS(Vec3, tlow, thigh) \ + DECLARE_VEC_ANY_COERCE_OPS(Vec4, tlow, thigh) \ \ DECLARE_VEC_3_COERCE_OPS(Vec3, static, tlow, thigh, thigh) \ DECLARE_VEC_3_COERCE_OPS(Vec3, static, thigh, tlow, thigh) +DECLARE_ALL_NONVECTOR_OPS(Cmplx) +DECLARE_ALL_NONVECTOR_OPS(Quat) + /* Disable warning about unary operator applied to unsigned type */ #if defined _MSC_VER # pragma warning(push) # pragma warning(disable: 4146) #endif -DECLARE_ALL_NONVECTOR_OPS(Cmplx) -DECLARE_ALL_NONVECTOR_OPS(Quat) - DECLARE_ALL_VECTOR_OPS(half) DECLARE_ALL_VECTOR_OPS(float) DECLARE_ALL_VECTOR_OPS(double) @@ -1178,10 +1178,9 @@ DECLARE_ALL_VECTOR_OPS(uint64_t) # pragma warning(disable: 4018) #endif -/* Apply the same coercion rules as in the C++ standard. However, */ -/* instead of promoting int8_t etc. to int, we apply our own rules. */ -/* FIXME: "half" and "real" are deactivated for now, because we do */ -/* not implement all combinations of operators for these types yet. */ +/* Apply the same coercion rules as in the C++ standard. However, instead + * of always promoting smaller types to int, we allow int8_t op int16_t to + * return an int16_t. */ DECLARE_ALL_VECTOR_COERCE_OPS(int8_t, uint8_t) DECLARE_ALL_VECTOR_COERCE_OPS(int8_t, int16_t) DECLARE_ALL_VECTOR_COERCE_OPS(int8_t, uint16_t) @@ -1189,11 +1188,9 @@ DECLARE_ALL_VECTOR_COERCE_OPS(int8_t, int32_t) DECLARE_ALL_VECTOR_COERCE_OPS(int8_t, uint32_t) DECLARE_ALL_VECTOR_COERCE_OPS(int8_t, int64_t) DECLARE_ALL_VECTOR_COERCE_OPS(int8_t, uint64_t) -/* DECLARE_ALL_VECTOR_COERCE_OPS(int8_t, half) */ DECLARE_ALL_VECTOR_COERCE_OPS(int8_t, float) DECLARE_ALL_VECTOR_COERCE_OPS(int8_t, double) DECLARE_ALL_VECTOR_COERCE_OPS(int8_t, long double) -/* DECLARE_ALL_VECTOR_COERCE_OPS(int8_t, real) */ DECLARE_ALL_VECTOR_COERCE_OPS(uint8_t, int16_t) DECLARE_ALL_VECTOR_COERCE_OPS(uint8_t, uint16_t) @@ -1201,76 +1198,87 @@ DECLARE_ALL_VECTOR_COERCE_OPS(uint8_t, int32_t) DECLARE_ALL_VECTOR_COERCE_OPS(uint8_t, uint32_t) DECLARE_ALL_VECTOR_COERCE_OPS(uint8_t, int64_t) DECLARE_ALL_VECTOR_COERCE_OPS(uint8_t, uint64_t) -/* DECLARE_ALL_VECTOR_COERCE_OPS(uint8_t, half) */ DECLARE_ALL_VECTOR_COERCE_OPS(uint8_t, float) DECLARE_ALL_VECTOR_COERCE_OPS(uint8_t, double) DECLARE_ALL_VECTOR_COERCE_OPS(uint8_t, long double) -/* DECLARE_ALL_VECTOR_COERCE_OPS(uint8_t, real) */ DECLARE_ALL_VECTOR_COERCE_OPS(int16_t, uint16_t) DECLARE_ALL_VECTOR_COERCE_OPS(int16_t, int32_t) DECLARE_ALL_VECTOR_COERCE_OPS(int16_t, uint32_t) DECLARE_ALL_VECTOR_COERCE_OPS(int16_t, int64_t) DECLARE_ALL_VECTOR_COERCE_OPS(int16_t, uint64_t) -/* DECLARE_ALL_VECTOR_COERCE_OPS(int16_t, half) */ DECLARE_ALL_VECTOR_COERCE_OPS(int16_t, float) DECLARE_ALL_VECTOR_COERCE_OPS(int16_t, double) DECLARE_ALL_VECTOR_COERCE_OPS(int16_t, long double) -/* DECLARE_ALL_VECTOR_COERCE_OPS(int16_t, real) */ DECLARE_ALL_VECTOR_COERCE_OPS(uint16_t, int32_t) DECLARE_ALL_VECTOR_COERCE_OPS(uint16_t, uint32_t) DECLARE_ALL_VECTOR_COERCE_OPS(uint16_t, int64_t) DECLARE_ALL_VECTOR_COERCE_OPS(uint16_t, uint64_t) -/* DECLARE_ALL_VECTOR_COERCE_OPS(uint16_t, half) */ DECLARE_ALL_VECTOR_COERCE_OPS(uint16_t, float) DECLARE_ALL_VECTOR_COERCE_OPS(uint16_t, double) DECLARE_ALL_VECTOR_COERCE_OPS(uint16_t, long double) -/* DECLARE_ALL_VECTOR_COERCE_OPS(uint16_t, real) */ DECLARE_ALL_VECTOR_COERCE_OPS(int32_t, uint32_t) DECLARE_ALL_VECTOR_COERCE_OPS(int32_t, int64_t) DECLARE_ALL_VECTOR_COERCE_OPS(int32_t, uint64_t) -/* DECLARE_ALL_VECTOR_COERCE_OPS(int32_t, half) */ DECLARE_ALL_VECTOR_COERCE_OPS(int32_t, float) DECLARE_ALL_VECTOR_COERCE_OPS(int32_t, double) DECLARE_ALL_VECTOR_COERCE_OPS(int32_t, long double) -/* DECLARE_ALL_VECTOR_COERCE_OPS(int32_t, real) */ DECLARE_ALL_VECTOR_COERCE_OPS(uint32_t, int64_t) DECLARE_ALL_VECTOR_COERCE_OPS(uint32_t, uint64_t) -/* DECLARE_ALL_VECTOR_COERCE_OPS(uint32_t, half) */ DECLARE_ALL_VECTOR_COERCE_OPS(uint32_t, float) DECLARE_ALL_VECTOR_COERCE_OPS(uint32_t, double) DECLARE_ALL_VECTOR_COERCE_OPS(uint32_t, long double) -/* DECLARE_ALL_VECTOR_COERCE_OPS(uint32_t, real) */ DECLARE_ALL_VECTOR_COERCE_OPS(int64_t, uint64_t) -/* DECLARE_ALL_VECTOR_COERCE_OPS(int64_t, half) */ DECLARE_ALL_VECTOR_COERCE_OPS(int64_t, float) DECLARE_ALL_VECTOR_COERCE_OPS(int64_t, double) DECLARE_ALL_VECTOR_COERCE_OPS(int64_t, long double) -/* DECLARE_ALL_VECTOR_COERCE_OPS(int64_t, real) */ -/* DECLARE_ALL_VECTOR_COERCE_OPS(uint64_t, half) */ DECLARE_ALL_VECTOR_COERCE_OPS(uint64_t, float) DECLARE_ALL_VECTOR_COERCE_OPS(uint64_t, double) DECLARE_ALL_VECTOR_COERCE_OPS(uint64_t, long double) -/* DECLARE_ALL_VECTOR_COERCE_OPS(uint64_t, real) */ - -/* DECLARE_ALL_VECTOR_COERCE_OPS(half, float) */ -/* DECLARE_ALL_VECTOR_COERCE_OPS(half, double) */ -/* DECLARE_ALL_VECTOR_COERCE_OPS(half, long double) */ -/* DECLARE_ALL_VECTOR_COERCE_OPS(half, real) */ DECLARE_ALL_VECTOR_COERCE_OPS(float, double) DECLARE_ALL_VECTOR_COERCE_OPS(float, long double) -/* DECLARE_ALL_VECTOR_COERCE_OPS(float, real) */ DECLARE_ALL_VECTOR_COERCE_OPS(double, long double) -/* DECLARE_ALL_VECTOR_COERCE_OPS(double, real) */ -/* DECLARE_ALL_VECTOR_COERCE_OPS(long double, real) */ +/* All integer types are promoted to half; all floating point types + * cause half to be promoted. */ +DECLARE_ALL_VECTOR_COERCE_OPS(int8_t, half) +DECLARE_ALL_VECTOR_COERCE_OPS(uint8_t, half) +DECLARE_ALL_VECTOR_COERCE_OPS(int16_t, half) +DECLARE_ALL_VECTOR_COERCE_OPS(uint16_t, half) +DECLARE_ALL_VECTOR_COERCE_OPS(int32_t, half) +DECLARE_ALL_VECTOR_COERCE_OPS(uint32_t, half) +DECLARE_ALL_VECTOR_COERCE_OPS(int64_t, half) +DECLARE_ALL_VECTOR_COERCE_OPS(uint64_t, half) + +DECLARE_ALL_VECTOR_COERCE_OPS(half, float) +DECLARE_ALL_VECTOR_COERCE_OPS(half, double) +DECLARE_ALL_VECTOR_COERCE_OPS(half, long double) + +/* FIXME: vectors of "real" are deactivated for now, because we do + * not implement all combinations of operators for these types yet. */ + +#if 0 +/* All types are promoted to real */ +DECLARE_ALL_VECTOR_COERCE_OPS(int8_t, real) +DECLARE_ALL_VECTOR_COERCE_OPS(uint8_t, real) +DECLARE_ALL_VECTOR_COERCE_OPS(int16_t, real) +DECLARE_ALL_VECTOR_COERCE_OPS(uint16_t, real) +DECLARE_ALL_VECTOR_COERCE_OPS(int32_t, real) +DECLARE_ALL_VECTOR_COERCE_OPS(uint32_t, real) +DECLARE_ALL_VECTOR_COERCE_OPS(int64_t, real) +DECLARE_ALL_VECTOR_COERCE_OPS(uint64_t, real) +DECLARE_ALL_VECTOR_COERCE_OPS(half, real) +DECLARE_ALL_VECTOR_COERCE_OPS(float, real) +DECLARE_ALL_VECTOR_COERCE_OPS(double, real) +DECLARE_ALL_VECTOR_COERCE_OPS(long double, real) +#endif #if defined __GNUC__ && (__GNUC__ >= 4) # pragma GCC diagnostic pop