source: trunk/test/half.cpp @ 914

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

test: get rid of the need for LOLUNIT_SETUP_FIXTURE().

  • Property svn:keywords set to Id
File size: 8.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#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
308} /* namespace lol */
309
Note: See TracBrowser for help on using the repository browser.