source: trunk/test/half.cpp @ 912

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

test: replace CppUnit with our LolUnit test suite.

CppUnit is really too large for our needs, would require to be precompiled
for many platforms, in all combinations of debug and release modes, with
additional variants for libstdc++ versions. We replace it with our own
lightweight implementation, LolUnit. Good riddance.

  • Property svn:keywords set to Id
File size: 8.6 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_ASSERT_EQUAL(a.bits, b);
49        }
50    }
51
52    LOLUNIT_TEST(test_half_makeaccurate)
53    {
54        for (size_t i = 0; i < sizeof(pairs) / sizeof(*pairs); i++)
55        {
56            half a = half::makeaccurate(pairs[i].f);
57            uint16_t b = pairs[i].x;
58            LOLUNIT_ASSERT_EQUAL(a.bits, b);
59        }
60    }
61
62    LOLUNIT_TEST(test_half_makebits)
63    {
64        for (unsigned int i = 0; i < 0x10000; i++)
65        {
66            half a = half::makebits(i);
67            uint16_t b = 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            half h = half::makebits(i);
144            if (h.is_nan())
145            {
146                LOLUNIT_ASSERT(!h.is_inf());
147                LOLUNIT_ASSERT(!h.is_normal());
148                LOLUNIT_ASSERT(!h.is_finite());
149            }
150            else if (h.is_inf())
151            {
152                LOLUNIT_ASSERT(!h.is_normal());
153                LOLUNIT_ASSERT(!h.is_finite());
154            }
155            else
156            {
157                LOLUNIT_ASSERT(h.is_finite());
158            }
159        }
160    }
161
162    LOLUNIT_TEST(test_half_to_float)
163    {
164        for (size_t i = 0; i < sizeof(pairs) / sizeof(*pairs); i++)
165        {
166            float a = (float)half::makebits(pairs[i].x);
167            float b = pairs[i].f;
168            LOLUNIT_ASSERT_EQUAL(a, b);
169        }
170
171        for (uint32_t i = 0; i < 0x10000; i++)
172        {
173            half h = half::makebits(i);
174            float f = (float)h;
175            half g = (half)f;
176            if (h.is_nan())
177            {
178                LOLUNIT_ASSERT(isnan(f));
179                LOLUNIT_ASSERT(g.is_nan());
180            }
181            else
182            {
183                LOLUNIT_ASSERT(!isnan(f));
184                LOLUNIT_ASSERT_EQUAL(g.bits, h.bits);
185            }
186        }
187    }
188
189    LOLUNIT_TEST(test_half_to_int)
190    {
191        LOLUNIT_ASSERT_EQUAL((int)(half)(0.0f), 0);
192        LOLUNIT_ASSERT_EQUAL((int)(half)(-0.0f), 0);
193        LOLUNIT_ASSERT_EQUAL((int)(half)(0.9f), 0);
194        LOLUNIT_ASSERT_EQUAL((int)(half)(-0.9f), 0);
195        LOLUNIT_ASSERT_EQUAL((int)(half)(1.0f), 1);
196        LOLUNIT_ASSERT_EQUAL((int)(half)(-1.0f), -1);
197        LOLUNIT_ASSERT_EQUAL((int)(half)(1.9f), 1);
198        LOLUNIT_ASSERT_EQUAL((int)(half)(-1.9f), -1);
199        LOLUNIT_ASSERT_EQUAL((int)(half)(65504.0f), 65504);
200        LOLUNIT_ASSERT_EQUAL((int)(half)(-65504.0f), -65504);
201    }
202
203    LOLUNIT_TEST(test_float_op_half)
204    {
205        half zero = 0;
206        half one = 1;
207        half two = 2;
208
209        float a = zero + one;
210        LOLUNIT_ASSERT_EQUAL(1.0f, a);
211        a += zero;
212        LOLUNIT_ASSERT_EQUAL(1.0f, a);
213        a -= zero;
214        LOLUNIT_ASSERT_EQUAL(1.0f, a);
215        a *= one;
216        LOLUNIT_ASSERT_EQUAL(1.0f, a);
217        a /= one;
218        LOLUNIT_ASSERT_EQUAL(1.0f, a);
219
220        float b = one + zero;
221        LOLUNIT_ASSERT_EQUAL(1.0f, b);
222        b += one;
223        LOLUNIT_ASSERT_EQUAL(2.0f, b);
224        b *= two;
225        LOLUNIT_ASSERT_EQUAL(4.0f, b);
226        b -= two;
227        LOLUNIT_ASSERT_EQUAL(2.0f, b);
228        b /= two;
229        LOLUNIT_ASSERT_EQUAL(1.0f, b);
230
231        float c = one - zero;
232        LOLUNIT_ASSERT_EQUAL(1.0f, c);
233
234        float d = two - one;
235        LOLUNIT_ASSERT_EQUAL(1.0f, d);
236
237        float e = two + (-one);
238        LOLUNIT_ASSERT_EQUAL(1.0f, e);
239
240        float f = (two * two) / (one + one);
241        LOLUNIT_ASSERT_EQUAL(2.0f, f);
242    }
243
244    LOLUNIT_TEST(test_half_op_float)
245    {
246        half zero = 0;
247        half one = 1;
248        half two = 2;
249        half four = 4;
250
251        half a = one + 0.0f;
252        LOLUNIT_ASSERT_EQUAL(one.bits, a.bits);
253        a += 0.0f;
254        LOLUNIT_ASSERT_EQUAL(one.bits, a.bits);
255        a -= 0.0f;
256        LOLUNIT_ASSERT_EQUAL(one.bits, a.bits);
257        a *= 1.0f;
258        LOLUNIT_ASSERT_EQUAL(one.bits, a.bits);
259        a /= 1.0f;
260        LOLUNIT_ASSERT_EQUAL(one.bits, a.bits);
261
262        half b = one + 0.0f;
263        LOLUNIT_ASSERT_EQUAL(one.bits, b.bits);
264        b += 1.0f;
265        LOLUNIT_ASSERT_EQUAL(two.bits, b.bits);
266        b *= 2.0f;
267        LOLUNIT_ASSERT_EQUAL(four.bits, b.bits);
268        b -= 2.0f;
269        LOLUNIT_ASSERT_EQUAL(two.bits, b.bits);
270        b /= 2.0f;
271        LOLUNIT_ASSERT_EQUAL(one.bits, b.bits);
272
273        half c = 1.0f - zero;
274        LOLUNIT_ASSERT_EQUAL(one.bits, c.bits);
275
276        half d = 2.0f - one;
277        LOLUNIT_ASSERT_EQUAL(one.bits, d.bits);
278
279        half e = 2.0f + (-one);
280        LOLUNIT_ASSERT_EQUAL(one.bits, e.bits);
281
282        half f = (2.0f * two) / (1.0f + one);
283        LOLUNIT_ASSERT_EQUAL(two.bits, f.bits);
284    }
285
286private:
287    struct TestPair { float f; uint16_t x; };
288
289    static TestPair const pairs[11];
290};
291
292HalfTest::TestPair const HalfTest::pairs[] =
293{
294    /* All these values have exact half representations */
295    { 0.0f,      0x0000 },
296    { -0.0f,     0x8000 }, /* negative zero */
297    { 1.0f,      0x3c00 },
298    { -1.0f,     0xbc00 },
299    { 2.0f,      0x4000 },
300    { 0.5f,      0x3800 },
301    { 0.125f,    0x3000 },
302    { 15.9375f,  0x4bf8 },
303    { 31.0f / (1 << 14), 0x17c0 }, /* 0x1.fp-10 */
304    { 31.0f / (1 << 18), 0x07c0 }, /* 0x1.fp-14, denormal */
305    { 31.0f / (1 << 19), 0x03e0 }, /* 0x1.fp-15, denormal */
306};
307
308LOLUNIT_SETUP_FIXTURE(HalfTest);
309
310} /* namespace lol */
311
Note: See TracBrowser for help on using the repository browser.