source: trunk/test/half.cpp @ 937

Last change on this file since 937 was 937, checked in by sam, 12 years ago

lolunit: rename a few methods for consistency.

  • Property svn:keywords set to Id
File size: 8.7 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#if defined HAVE_CONFIG_H
12#   include "config.h"
13#endif
14
15#include <cmath>
16
17#include "core.h"
18#include "lol/unit.h"
19
20/* Ensure isnan() is present even on systems that don't define it, or
21 * when -ffast-math is being used. */
22#if defined __FAST_MATH__
23#   undef isnan
24#endif
25#if !defined isnan
26static inline int isnan(float f)
27{
28    union { float f; uint32_t x; } u = { f };
29    return (u.x << 1) > 0xff000000u;
30}
31#endif
32
33namespace lol
34{
35
36LOLUNIT_FIXTURE(HalfTest)
37{
38public:
39    LOLUNIT_TEST(test_half_from_float)
40    {
41        for (size_t i = 0; i < sizeof(pairs) / sizeof(*pairs); i++)
42        {
43            half a = (half)pairs[i].f;
44            uint16_t b = pairs[i].x;
45            LOLUNIT_SET_CONTEXT(i);
46            LOLUNIT_ASSERT_EQUAL(a.bits, b);
47        }
48    }
49
50    LOLUNIT_TEST(test_half_makeaccurate)
51    {
52        for (size_t i = 0; i < sizeof(pairs) / sizeof(*pairs); i++)
53        {
54            half a = half::makeaccurate(pairs[i].f);
55            uint16_t b = pairs[i].x;
56            LOLUNIT_SET_CONTEXT(i);
57            LOLUNIT_ASSERT_EQUAL(a.bits, b);
58        }
59    }
60
61    LOLUNIT_TEST(test_half_makebits)
62    {
63        for (unsigned int i = 0; i < 0x10000; i++)
64        {
65            half a = half::makebits(i);
66            uint16_t b = i;
67            LOLUNIT_SET_CONTEXT(i);
68            LOLUNIT_ASSERT_EQUAL(a.bits, b);
69        }
70    }
71
72    LOLUNIT_TEST(test_half_is_nan)
73    {
74        LOLUNIT_ASSERT(half::makebits(0x7c01).is_nan());
75        LOLUNIT_ASSERT(half::makebits(0xfc01).is_nan());
76        LOLUNIT_ASSERT(half::makebits(0x7e00).is_nan());
77        LOLUNIT_ASSERT(half::makebits(0xfe00).is_nan());
78
79        LOLUNIT_ASSERT(!half::makebits(0x7c00).is_nan());
80        LOLUNIT_ASSERT(!half::makebits(0xfc00).is_nan());
81
82        LOLUNIT_ASSERT(!half(0.0f).is_nan());
83        LOLUNIT_ASSERT(!half(-0.0f).is_nan());
84        LOLUNIT_ASSERT(!half(2.0f).is_nan());
85        LOLUNIT_ASSERT(!half(-2.0f).is_nan());
86    }
87
88    LOLUNIT_TEST(test_half_is_inf)
89    {
90        LOLUNIT_ASSERT(half(65536.0f).is_inf());
91        LOLUNIT_ASSERT(half(-65536.0f).is_inf());
92
93        LOLUNIT_ASSERT(!half(0.0f).is_inf());
94        LOLUNIT_ASSERT(!half(-0.0f).is_inf());
95        LOLUNIT_ASSERT(!half(65535.0f).is_inf());
96        LOLUNIT_ASSERT(!half(-65535.0f).is_inf());
97
98        LOLUNIT_ASSERT(half::makebits(0x7c00).is_inf());
99        LOLUNIT_ASSERT(half::makebits(0xfc00).is_inf());
100
101        LOLUNIT_ASSERT(!half::makebits(0x7e00).is_inf());
102        LOLUNIT_ASSERT(!half::makebits(0xfe00).is_inf());
103    }
104
105    LOLUNIT_TEST(test_half_is_finite)
106    {
107        LOLUNIT_ASSERT(half(0.0f).is_finite());
108        LOLUNIT_ASSERT(half(-0.0f).is_finite());
109        LOLUNIT_ASSERT(half(65535.0f).is_finite());
110        LOLUNIT_ASSERT(half(-65535.0f).is_finite());
111
112        LOLUNIT_ASSERT(!half(65536.0f).is_finite());
113        LOLUNIT_ASSERT(!half(-65536.0f).is_finite());
114
115        LOLUNIT_ASSERT(!half::makebits(0x7c00).is_finite());
116        LOLUNIT_ASSERT(!half::makebits(0xfc00).is_finite());
117
118        LOLUNIT_ASSERT(!half::makebits(0x7e00).is_finite());
119        LOLUNIT_ASSERT(!half::makebits(0xfe00).is_finite());
120    }
121
122    LOLUNIT_TEST(test_half_is_normal)
123    {
124        LOLUNIT_ASSERT(half(0.0f).is_normal());
125        LOLUNIT_ASSERT(half(-0.0f).is_normal());
126        LOLUNIT_ASSERT(half(65535.0f).is_normal());
127        LOLUNIT_ASSERT(half(-65535.0f).is_normal());
128
129        LOLUNIT_ASSERT(!half(65536.0f).is_normal());
130        LOLUNIT_ASSERT(!half(-65536.0f).is_normal());
131
132        LOLUNIT_ASSERT(!half::makebits(0x7c00).is_normal());
133        LOLUNIT_ASSERT(!half::makebits(0xfc00).is_normal());
134
135        LOLUNIT_ASSERT(!half::makebits(0x7e00).is_normal());
136        LOLUNIT_ASSERT(!half::makebits(0xfe00).is_normal());
137    }
138
139    LOLUNIT_TEST(test_half_classify)
140    {
141        for (uint32_t i = 0; i < 0x10000; i++)
142        {
143            LOLUNIT_SET_CONTEXT(i);
144            half h = half::makebits(i);
145            if (h.is_nan())
146            {
147                LOLUNIT_ASSERT(!h.is_inf());
148                LOLUNIT_ASSERT(!h.is_normal());
149                LOLUNIT_ASSERT(!h.is_finite());
150            }
151            else if (h.is_inf())
152            {
153                LOLUNIT_ASSERT(!h.is_normal());
154                LOLUNIT_ASSERT(!h.is_finite());
155            }
156            else
157            {
158                LOLUNIT_ASSERT(h.is_finite());
159            }
160        }
161    }
162
163    LOLUNIT_TEST(test_half_to_float)
164    {
165        for (size_t i = 0; i < sizeof(pairs) / sizeof(*pairs); i++)
166        {
167            float a = (float)half::makebits(pairs[i].x);
168            float b = pairs[i].f;
169            LOLUNIT_SET_CONTEXT(i);
170            LOLUNIT_ASSERT_EQUAL(a, b);
171        }
172
173        for (uint32_t i = 0; i < 0x10000; i++)
174        {
175            half h = half::makebits(i);
176            float f = (float)h;
177            half g = (half)f;
178            LOLUNIT_SET_CONTEXT(i);
179            if (h.is_nan())
180            {
181                LOLUNIT_ASSERT(isnan(f));
182                LOLUNIT_ASSERT(g.is_nan());
183            }
184            else
185            {
186                LOLUNIT_ASSERT(!isnan(f));
187                LOLUNIT_ASSERT_EQUAL(g.bits, h.bits);
188            }
189        }
190    }
191
192    LOLUNIT_TEST(test_half_to_int)
193    {
194        LOLUNIT_ASSERT_EQUAL((int)(half)(0.0f), 0);
195        LOLUNIT_ASSERT_EQUAL((int)(half)(-0.0f), 0);
196        LOLUNIT_ASSERT_EQUAL((int)(half)(0.9f), 0);
197        LOLUNIT_ASSERT_EQUAL((int)(half)(-0.9f), 0);
198        LOLUNIT_ASSERT_EQUAL((int)(half)(1.0f), 1);
199        LOLUNIT_ASSERT_EQUAL((int)(half)(-1.0f), -1);
200        LOLUNIT_ASSERT_EQUAL((int)(half)(1.9f), 1);
201        LOLUNIT_ASSERT_EQUAL((int)(half)(-1.9f), -1);
202        LOLUNIT_ASSERT_EQUAL((int)(half)(65504.0f), 65504);
203        LOLUNIT_ASSERT_EQUAL((int)(half)(-65504.0f), -65504);
204    }
205
206    LOLUNIT_TEST(test_float_op_half)
207    {
208        half zero = 0;
209        half one = 1;
210        half two = 2;
211
212        float a = zero + one;
213        LOLUNIT_ASSERT_EQUAL(1.0f, a);
214        a += zero;
215        LOLUNIT_ASSERT_EQUAL(1.0f, a);
216        a -= zero;
217        LOLUNIT_ASSERT_EQUAL(1.0f, a);
218        a *= one;
219        LOLUNIT_ASSERT_EQUAL(1.0f, a);
220        a /= one;
221        LOLUNIT_ASSERT_EQUAL(1.0f, a);
222
223        float b = one + zero;
224        LOLUNIT_ASSERT_EQUAL(1.0f, b);
225        b += one;
226        LOLUNIT_ASSERT_EQUAL(2.0f, b);
227        b *= two;
228        LOLUNIT_ASSERT_EQUAL(4.0f, b);
229        b -= two;
230        LOLUNIT_ASSERT_EQUAL(2.0f, b);
231        b /= two;
232        LOLUNIT_ASSERT_EQUAL(1.0f, b);
233
234        float c = one - zero;
235        LOLUNIT_ASSERT_EQUAL(1.0f, c);
236
237        float d = two - one;
238        LOLUNIT_ASSERT_EQUAL(1.0f, d);
239
240        float e = two + (-one);
241        LOLUNIT_ASSERT_EQUAL(1.0f, e);
242
243        float f = (two * two) / (one + one);
244        LOLUNIT_ASSERT_EQUAL(2.0f, f);
245    }
246
247    LOLUNIT_TEST(test_half_op_float)
248    {
249        half zero = 0;
250        half one = 1;
251        half two = 2;
252        half four = 4;
253
254        half a = one + 0.0f;
255        LOLUNIT_ASSERT_EQUAL(one.bits, a.bits);
256        a += 0.0f;
257        LOLUNIT_ASSERT_EQUAL(one.bits, a.bits);
258        a -= 0.0f;
259        LOLUNIT_ASSERT_EQUAL(one.bits, a.bits);
260        a *= 1.0f;
261        LOLUNIT_ASSERT_EQUAL(one.bits, a.bits);
262        a /= 1.0f;
263        LOLUNIT_ASSERT_EQUAL(one.bits, a.bits);
264
265        half b = one + 0.0f;
266        LOLUNIT_ASSERT_EQUAL(one.bits, b.bits);
267        b += 1.0f;
268        LOLUNIT_ASSERT_EQUAL(two.bits, b.bits);
269        b *= 2.0f;
270        LOLUNIT_ASSERT_EQUAL(four.bits, b.bits);
271        b -= 2.0f;
272        LOLUNIT_ASSERT_EQUAL(two.bits, b.bits);
273        b /= 2.0f;
274        LOLUNIT_ASSERT_EQUAL(one.bits, b.bits);
275
276        half c = 1.0f - zero;
277        LOLUNIT_ASSERT_EQUAL(one.bits, c.bits);
278
279        half d = 2.0f - one;
280        LOLUNIT_ASSERT_EQUAL(one.bits, d.bits);
281
282        half e = 2.0f + (-one);
283        LOLUNIT_ASSERT_EQUAL(one.bits, e.bits);
284
285        half f = (2.0f * two) / (1.0f + one);
286        LOLUNIT_ASSERT_EQUAL(two.bits, f.bits);
287    }
288
289private:
290    struct TestPair { float f; uint16_t x; };
291
292    static TestPair const pairs[11];
293};
294
295HalfTest::TestPair const HalfTest::pairs[] =
296{
297    /* All these values have exact half representations */
298    { 0.0f,      0x0000 },
299    { -0.0f,     0x8000 }, /* negative zero */
300    { 1.0f,      0x3c00 },
301    { -1.0f,     0xbc00 },
302    { 2.0f,      0x4000 },
303    { 0.5f,      0x3800 },
304    { 0.125f,    0x3000 },
305    { 15.9375f,  0x4bf8 },
306    { 31.0f / (1 << 14), 0x17c0 }, /* 0x1.fp-10 */
307    { 31.0f / (1 << 18), 0x07c0 }, /* 0x1.fp-14, normal float, denormal half */
308    { 31.0f / (1 << 19), 0x03e0 }, /* 0x1.fp-15, normal float, denormal half */
309};
310
311} /* namespace lol */
312
Note: See TracBrowser for help on using the repository browser.