// // Lol Engine // // Copyright: (c) 2010-2011 Sam Hocevar // This program is free software; you can redistribute it and/or // modify it under the terms of the Do What The Fuck You Want To // Public License, Version 2, as published by Sam Hocevar. See // http://sam.zoy.org/projects/COPYING.WTFPL for more details. // // // The Half class // -------------- // #if !defined __LOL_HALF_H__ #define __LOL_HALF_H__ #include #include namespace lol { class half { public: /* Constructors. Always inline so that the code can work in registers * instead of calling routines with the hidden "this" parameter. */ inline half() { } inline half(int f) { *this = makefast(f); } inline half(float f) { *this = makefast(f); } inline half(double f) { *this = makefast(f); } inline int is_nan() const { return ((bits & 0x7c00u) == 0x7c00u) && (bits & 0x03ffu); } inline int is_finite() const { return (bits & 0x7c00u) != 0x7c00u; } inline int is_inf() const { return (uint16_t)(bits << 1) == (0x7c00u << 1); } inline int is_normal() const { return (is_finite() && (bits & 0x7c00u)) || ((bits & 0x7fffu) == 0); } /* Cast to other types -- always inline, see constructors */ inline half &operator =(int f) { return *this = makefast(f); } inline half &operator =(float f) { return *this = makefast(f); } inline half &operator =(double f) { return *this = makefast(f); } inline operator int() const { return (int)tofloat(*this); } inline operator float() const { return tofloat(*this); } static float tofloat(half h); /* Array conversions */ static size_t convert(half *dst, float const *src, size_t nelem); static size_t convert(float *dst, half const *src, size_t nelem); /* Operations */ inline half operator -() { return makebits(bits ^ 0x8000u); } 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; } inline float operator /(half h) const { return (float)*this / (float)h; } /* Factories */ static half makefast(float f); static half makeaccurate(float f); static inline half makebits(uint16_t x) { half ret; ret.bits = x; return ret; } /* Internal representation */ 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; } } /* namespace lol */ #endif // __LOL_HALF_H__