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

Last change on this file since 1502 was 1502, checked in by sam, 9 years ago

core: fix a few build warnings and remove useless operators from the
"half" class. The build is now 3% faster.

  • Property svn:keywords set to Id
File size: 6.3 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; }
123
124static inline half clamp(half x, half a, half b)
125{
126    return (x < a) ? a : (x > b) ? b : x;
127}
128
129
130#define DECLARE_COERCE_HALF_NUMERIC_OPS(op, type, ret, x2, h2) \
131    inline ret operator op(type x, half h) { return x2 op h2; } \
132    inline ret operator op(half h, type x) { return h2 op x2; } \
133    inline type &operator op##=(type &x, half h) { return x = x op h2; } \
134    inline half &operator op##=(half &h, type x) { return h = h op x2; }
135
136#define DECLARE_COERCE_HALF_BOOL_OPS(op, type, x2, h2) \
137    inline bool operator op(type x, half h) { return x2 op h2; } \
138    inline bool operator op(half h, type x) { return h2 op x2; }
139
140#define DECLARE_COERCE_HALF_OPS(type, ret, x2, h2) \
141    DECLARE_COERCE_HALF_NUMERIC_OPS(+, type, ret, x2, h2) \
142    DECLARE_COERCE_HALF_NUMERIC_OPS(-, type, ret, x2, h2) \
143    DECLARE_COERCE_HALF_NUMERIC_OPS(*, type, ret, x2, h2) \
144    DECLARE_COERCE_HALF_NUMERIC_OPS(/, type, ret, x2, h2) \
145    \
146    DECLARE_COERCE_HALF_BOOL_OPS(==, type, x2, h2) \
147    DECLARE_COERCE_HALF_BOOL_OPS(!=, type, x2, h2) \
148    DECLARE_COERCE_HALF_BOOL_OPS(>=, type, x2, h2) \
149    DECLARE_COERCE_HALF_BOOL_OPS(<=, type, x2, h2) \
150    DECLARE_COERCE_HALF_BOOL_OPS(>, type, x2, h2) \
151    DECLARE_COERCE_HALF_BOOL_OPS(<, type, x2, h2)
152
153#define DECLARE_COERCE_TO_HALF_OPS(type) \
154    DECLARE_COERCE_HALF_OPS(type, half, (half)(int)x, h)
155
156#define DECLARE_COERCE_FROM_HALF_OPS(type) \
157    DECLARE_COERCE_HALF_OPS(type, type, x, (type)h)
158
159/* Only provide coercion rules above int32_t, since the standard says
160 * all smaller base types are coerced to int. */
161DECLARE_COERCE_TO_HALF_OPS(int32_t)
162DECLARE_COERCE_TO_HALF_OPS(uint32_t)
163DECLARE_COERCE_TO_HALF_OPS(int64_t)
164DECLARE_COERCE_TO_HALF_OPS(uint64_t)
165
166DECLARE_COERCE_FROM_HALF_OPS(float)
167DECLARE_COERCE_FROM_HALF_OPS(double)
168DECLARE_COERCE_FROM_HALF_OPS(long double)
169
170#undef DECLARE_COERCE_HALF_NUMERIC_OPS
171#undef DECLARE_COERCE_HALF_OPS
172#undef DECLARE_COERCE_TO_HALF_OPS
173#undef DECLARE_COERCE_FROM_HALF_OPS
174
175} /* namespace lol */
176
177#endif // __LOL_HALF_H__
178
Note: See TracBrowser for help on using the repository browser.