source: trunk/test/half.cpp @ 911

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

test: add a few Visual Studio 2010 project files and fix testsuite code
so that it builds properly.

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