source: trunk/test/half.cpp @ 927

Last change on this file since 927 was 927, checked in by sam, 8 years ago

lolunit: add a LOLUNIT_SET_CONTEXT / LOLUNIT_UNSET_CONTEXT macro pair.

This is useful when doing several asserts in one loop, for instance: there
isn't always a way to deduce the loop index from the assert failure, so
these macros allow the user to give more context information.

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