source: trunk/src/lol/math/half.h @ 2056

Last change on this file since 2056 was 2056, checked in by sam, 10 years ago

math: reimplement min(), max(), abs() and fmod() in the lol:: namespace to
avoid conflicts with the C++ stdlib.

  • Property svn:keywords set to Id
File size: 6.5 KB
Line 
1//
2// Lol Engine
3//
4// Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net>
5//   This program is free software; you can redistribute it and/or
6//   modify it under the terms of the Do What The Fuck You Want To
7//   Public License, Version 2, as published by Sam Hocevar. See
8//   http://sam.zoy.org/projects/COPYING.WTFPL for more details.
9//
10
11//
12// The Half class
13// --------------
14//
15
16#if !defined __LOL_HALF_H__
17#define __LOL_HALF_H__
18
19#include <cstdio>
20#include <stdint.h>
21
22namespace lol
23{
24
25/* This is OUR namespace. Don't let Windows headers fuck with it. */
26#undef min
27#undef max
28
29class half
30{
31public:
32    /* Constructors. Always inline so that the code can work in registers
33     * instead of calling routines with the hidden "this" parameter. */
34    inline half() { }
35    inline half(int f) { *this = makefast((float)f); }
36    inline half(float f) { *this = makefast(f); }
37    inline half(double f) { *this = makefast((float)f); }
38    inline half(long double f) { *this = makefast((float)f); }
39
40    inline int is_nan() const
41    {
42        return ((bits & 0x7c00u) == 0x7c00u) && (bits & 0x03ffu);
43    }
44
45    inline int is_finite() const
46    {
47        return (bits & 0x7c00u) != 0x7c00u;
48    }
49
50    inline int is_inf() const
51    {
52        return (uint16_t)(bits << 1) == (0x7c00u << 1);
53    }
54
55    inline int is_normal() const
56    {
57        return (is_finite() && (bits & 0x7c00u)) || ((bits & 0x7fffu) == 0);
58    }
59
60    /* Cast to other types -- always inline, see constructors */
61    inline half &operator =(int f) { return *this = makefast((float)f); }
62    inline half &operator =(float f) { return *this = makefast(f); }
63    inline half &operator =(double f) { return *this = makefast((float)f); }
64    inline half &operator =(long double f) { return *this = makefast((float)f); }
65    inline operator int8_t() const { return (int8_t)(float)*this; }
66    inline operator uint8_t() const { return (uint8_t)(float)*this; }
67    inline operator int16_t() const { return (int16_t)(float)*this; }
68    inline operator uint16_t() const { return (uint16_t)(float)*this; }
69    inline operator int32_t() const { return (int32_t)(float)*this; }
70    inline operator uint32_t() const { return (uint32_t)(float)*this; }
71    inline operator int64_t() const { return (int64_t)(float)*this; }
72    inline operator uint64_t() const { return (uint64_t)(float)*this; }
73
74    inline operator float() const { return tofloat(*this); }
75    inline operator double() const { return tofloat(*this); }
76    inline operator long double() const { return tofloat(*this); }
77
78    static float tofloat(half h);
79
80    /* Array conversions */
81    static size_t convert(half *dst, float const *src, size_t nelem);
82    static size_t convert(float *dst, half const *src, size_t nelem);
83
84    /* Operations */
85    bool operator ==(half x) const { return (float)*this == (float)x; }
86    bool operator !=(half x) const { return (float)*this != (float)x; }
87    bool operator <(half x) const { return (float)*this < (float)x; }
88    bool operator >(half x) const { return (float)*this > (float)x; }
89    bool operator <=(half x) const { return (float)*this <= (float)x; }
90    bool operator >=(half x) const { return (float)*this >= (float)x; }
91
92    bool operator !() const { return !(bits & 0x7fffu); }
93    operator bool() const { return !!*this; }
94
95    inline half operator -() const { return makebits(bits ^ 0x8000u); }
96    inline half operator +() const { return *this; }
97    inline half &operator +=(half h) { return (*this = (half)(*this + h)); }
98    inline half &operator -=(half h) { return (*this = (half)(*this - h)); }
99    inline half &operator *=(half h) { return (*this = (half)(*this * h)); }
100    inline half &operator /=(half h) { return (*this = (half)(*this / h)); }
101
102    inline float operator +(half h) const { return (float)*this + (float)h; }
103    inline float operator -(half h) const { return (float)*this - (float)h; }
104    inline float operator *(half h) const { return (float)*this * (float)h; }
105    inline float operator /(half h) const { return (float)*this / (float)h; }
106
107    /* Factories */
108    static half makefast(float f);
109    static half makeaccurate(float f);
110    static inline half makebits(uint16_t x)
111    {
112        half ret;
113        ret.bits = x;
114        return ret;
115    }
116
117    /* Internal representation */
118    uint16_t bits;
119};
120
121static inline half min(half a, half b) { return a < b ? a : b; }
122static inline half max(half a, half b) { return a > b ? a : b; }
123static inline half fmod(half a, half b)
124{
125    using std::fmod;
126    return (half)fmod((float)a, (float)b);
127}
128static inline half abs(half a) { return half::makebits(a.bits & 0x7fffu); }
129
130static inline half clamp(half x, half a, half b)
131{
132    return (x < a) ? a : (x > b) ? b : x;
133}
134
135
136#define DECLARE_COERCE_HALF_NUMERIC_OPS(op, type, ret, x2, h2) \
137    inline ret operator op(type x, half h) { return x2 op h2; } \
138    inline ret operator op(half h, type x) { return h2 op x2; } \
139    inline type &operator op##=(type &x, half h) { return x = x op h2; } \
140    inline half &operator op##=(half &h, type x) { return h = h op x2; }
141
142#define DECLARE_COERCE_HALF_BOOL_OPS(op, type, x2, h2) \
143    inline bool operator op(type x, half h) { return x2 op h2; } \
144    inline bool operator op(half h, type x) { return h2 op x2; }
145
146#define DECLARE_COERCE_HALF_OPS(type, ret, x2, h2) \
147    DECLARE_COERCE_HALF_NUMERIC_OPS(+, type, ret, x2, h2) \
148    DECLARE_COERCE_HALF_NUMERIC_OPS(-, type, ret, x2, h2) \
149    DECLARE_COERCE_HALF_NUMERIC_OPS(*, type, ret, x2, h2) \
150    DECLARE_COERCE_HALF_NUMERIC_OPS(/, type, ret, x2, h2) \
151    \
152    DECLARE_COERCE_HALF_BOOL_OPS(==, type, x2, h2) \
153    DECLARE_COERCE_HALF_BOOL_OPS(!=, type, x2, h2) \
154    DECLARE_COERCE_HALF_BOOL_OPS(>=, type, x2, h2) \
155    DECLARE_COERCE_HALF_BOOL_OPS(<=, type, x2, h2) \
156    DECLARE_COERCE_HALF_BOOL_OPS(>, type, x2, h2) \
157    DECLARE_COERCE_HALF_BOOL_OPS(<, type, x2, h2)
158
159#define DECLARE_COERCE_TO_HALF_OPS(type) \
160    DECLARE_COERCE_HALF_OPS(type, half, (half)(int)x, h)
161
162#define DECLARE_COERCE_FROM_HALF_OPS(type) \
163    DECLARE_COERCE_HALF_OPS(type, type, x, (type)h)
164
165/* Only provide coercion rules above int32_t, since the standard says
166 * all smaller base types are coerced to int. */
167DECLARE_COERCE_TO_HALF_OPS(int32_t)
168DECLARE_COERCE_TO_HALF_OPS(uint32_t)
169DECLARE_COERCE_TO_HALF_OPS(int64_t)
170DECLARE_COERCE_TO_HALF_OPS(uint64_t)
171
172DECLARE_COERCE_FROM_HALF_OPS(float)
173DECLARE_COERCE_FROM_HALF_OPS(double)
174DECLARE_COERCE_FROM_HALF_OPS(long double)
175
176#undef DECLARE_COERCE_HALF_NUMERIC_OPS
177#undef DECLARE_COERCE_HALF_OPS
178#undef DECLARE_COERCE_TO_HALF_OPS
179#undef DECLARE_COERCE_FROM_HALF_OPS
180
181} /* namespace lol */
182
183#endif // __LOL_HALF_H__
184
Note: See TracBrowser for help on using the repository browser.