xref: /aosp_15_r20/external/angle/src/common/mathutil_unittest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // mathutil_unittest:
7 //   Unit tests for the utils defined in mathutil.h
8 //
9 
10 #include "mathutil.h"
11 
12 #include <gtest/gtest.h>
13 
14 using namespace gl;
15 
16 namespace
17 {
18 
19 // Test the correctness of packSnorm2x16 and unpackSnorm2x16 functions.
20 // For floats f1 and f2, unpackSnorm2x16(packSnorm2x16(f1, f2)) should be same as f1 and f2.
TEST(MathUtilTest,packAndUnpackSnorm2x16)21 TEST(MathUtilTest, packAndUnpackSnorm2x16)
22 {
23     const float input[8][2] = {
24         {0.0f, 0.0f},    {1.0f, 1.0f},          {-1.0f, 1.0f},           {-1.0f, -1.0f},
25         {0.875f, 0.75f}, {0.00392f, -0.99215f}, {-0.000675f, 0.004954f}, {-0.6937f, -0.02146f}};
26     const float floatFaultTolerance = 0.0001f;
27     float outputVal1, outputVal2;
28 
29     for (size_t i = 0; i < 8; i++)
30     {
31         unpackSnorm2x16(packSnorm2x16(input[i][0], input[i][1]), &outputVal1, &outputVal2);
32         EXPECT_NEAR(input[i][0], outputVal1, floatFaultTolerance);
33         EXPECT_NEAR(input[i][1], outputVal2, floatFaultTolerance);
34     }
35 }
36 
37 // Test the correctness of packSnorm2x16 and unpackSnorm2x16 functions with infinity values,
38 // result should be clamped to [-1, 1].
TEST(MathUtilTest,packAndUnpackSnorm2x16Infinity)39 TEST(MathUtilTest, packAndUnpackSnorm2x16Infinity)
40 {
41     const float floatFaultTolerance = 0.0001f;
42     float outputVal1, outputVal2;
43 
44     unpackSnorm2x16(packSnorm2x16(std::numeric_limits<float>::infinity(),
45                                   std::numeric_limits<float>::infinity()),
46                     &outputVal1, &outputVal2);
47     EXPECT_NEAR(1.0f, outputVal1, floatFaultTolerance);
48     EXPECT_NEAR(1.0f, outputVal2, floatFaultTolerance);
49 
50     unpackSnorm2x16(packSnorm2x16(std::numeric_limits<float>::infinity(),
51                                   -std::numeric_limits<float>::infinity()),
52                     &outputVal1, &outputVal2);
53     EXPECT_NEAR(1.0f, outputVal1, floatFaultTolerance);
54     EXPECT_NEAR(-1.0f, outputVal2, floatFaultTolerance);
55 
56     unpackSnorm2x16(packSnorm2x16(-std::numeric_limits<float>::infinity(),
57                                   -std::numeric_limits<float>::infinity()),
58                     &outputVal1, &outputVal2);
59     EXPECT_NEAR(-1.0f, outputVal1, floatFaultTolerance);
60     EXPECT_NEAR(-1.0f, outputVal2, floatFaultTolerance);
61 }
62 
63 // Test the correctness of packUnorm2x16 and unpackUnorm2x16 functions.
64 // For floats f1 and f2, unpackUnorm2x16(packUnorm2x16(f1, f2)) should be same as f1 and f2.
TEST(MathUtilTest,packAndUnpackUnorm2x16)65 TEST(MathUtilTest, packAndUnpackUnorm2x16)
66 {
67     const float input[8][2] = {
68         {0.0f, 0.0f},    {1.0f, 1.0f},          {-1.0f, 1.0f},           {-1.0f, -1.0f},
69         {0.875f, 0.75f}, {0.00392f, -0.99215f}, {-0.000675f, 0.004954f}, {-0.6937f, -0.02146f}};
70     const float floatFaultTolerance = 0.0001f;
71     float outputVal1, outputVal2;
72 
73     for (size_t i = 0; i < 8; i++)
74     {
75         unpackUnorm2x16(packUnorm2x16(input[i][0], input[i][1]), &outputVal1, &outputVal2);
76         float expected = input[i][0] < 0.0f ? 0.0f : input[i][0];
77         EXPECT_NEAR(expected, outputVal1, floatFaultTolerance);
78         expected = input[i][1] < 0.0f ? 0.0f : input[i][1];
79         EXPECT_NEAR(expected, outputVal2, floatFaultTolerance);
80     }
81 }
82 
83 // Test the correctness of packUnorm2x16 and unpackUnorm2x16 functions with infinity values,
84 // result should be clamped to [0, 1].
TEST(MathUtilTest,packAndUnpackUnorm2x16Infinity)85 TEST(MathUtilTest, packAndUnpackUnorm2x16Infinity)
86 {
87     const float floatFaultTolerance = 0.0001f;
88     float outputVal1, outputVal2;
89 
90     unpackUnorm2x16(packUnorm2x16(std::numeric_limits<float>::infinity(),
91                                   std::numeric_limits<float>::infinity()),
92                     &outputVal1, &outputVal2);
93     EXPECT_NEAR(1.0f, outputVal1, floatFaultTolerance);
94     EXPECT_NEAR(1.0f, outputVal2, floatFaultTolerance);
95 
96     unpackUnorm2x16(packUnorm2x16(std::numeric_limits<float>::infinity(),
97                                   -std::numeric_limits<float>::infinity()),
98                     &outputVal1, &outputVal2);
99     EXPECT_NEAR(1.0f, outputVal1, floatFaultTolerance);
100     EXPECT_NEAR(0.0f, outputVal2, floatFaultTolerance);
101 
102     unpackUnorm2x16(packUnorm2x16(-std::numeric_limits<float>::infinity(),
103                                   -std::numeric_limits<float>::infinity()),
104                     &outputVal1, &outputVal2);
105     EXPECT_NEAR(0.0f, outputVal1, floatFaultTolerance);
106     EXPECT_NEAR(0.0f, outputVal2, floatFaultTolerance);
107 }
108 
109 // Test the correctness of packHalf2x16 and unpackHalf2x16 functions.
110 // For floats f1 and f2, unpackHalf2x16(packHalf2x16(f1, f2)) should be same as f1 and f2.
TEST(MathUtilTest,packAndUnpackHalf2x16)111 TEST(MathUtilTest, packAndUnpackHalf2x16)
112 {
113     const float input[8][2] = {
114         {0.0f, 0.0f},    {1.0f, 1.0f},          {-1.0f, 1.0f},           {-1.0f, -1.0f},
115         {0.875f, 0.75f}, {0.00392f, -0.99215f}, {-0.000675f, 0.004954f}, {-0.6937f, -0.02146f},
116     };
117     const float floatFaultTolerance = 0.0005f;
118     float outputVal1, outputVal2;
119 
120     for (size_t i = 0; i < 8; i++)
121     {
122         unpackHalf2x16(packHalf2x16(input[i][0], input[i][1]), &outputVal1, &outputVal2);
123         EXPECT_NEAR(input[i][0], outputVal1, floatFaultTolerance);
124         EXPECT_NEAR(input[i][1], outputVal2, floatFaultTolerance);
125     }
126 }
127 
128 // Test the correctness of packUnorm4x8 and unpackUnorm4x8 functions.
129 // For floats f1 to f4, unpackUnorm4x8(packUnorm4x8(f1, f2, f3, f4)) should be same as f1 to f4.
TEST(MathUtilTest,packAndUnpackUnorm4x8)130 TEST(MathUtilTest, packAndUnpackUnorm4x8)
131 {
132     const float input[5][4] = {{0.0f, 0.0f, 0.0f, 0.0f},
133                                {1.0f, 1.0f, 1.0f, 1.0f},
134                                {-1.0f, 1.0f, -1.0f, 1.0f},
135                                {-1.0f, -1.0f, -1.0f, -1.0f},
136                                {64.0f / 255.0f, 128.0f / 255.0f, 32.0f / 255.0f, 16.0f / 255.0f}};
137 
138     const float floatFaultTolerance = 0.005f;
139     float outputVals[4];
140 
141     for (size_t i = 0; i < 5; i++)
142     {
143         UnpackUnorm4x8(PackUnorm4x8(input[i][0], input[i][1], input[i][2], input[i][3]),
144                        outputVals);
145         for (size_t j = 0; j < 4; j++)
146         {
147             float expected = input[i][j] < 0.0f ? 0.0f : input[i][j];
148             EXPECT_NEAR(expected, outputVals[j], floatFaultTolerance);
149         }
150     }
151 }
152 
153 // Test the correctness of packSnorm4x8 and unpackSnorm4x8 functions.
154 // For floats f1 to f4, unpackSnorm4x8(packSnorm4x8(f1, f2, f3, f4)) should be same as f1 to f4.
TEST(MathUtilTest,packAndUnpackSnorm4x8)155 TEST(MathUtilTest, packAndUnpackSnorm4x8)
156 {
157     const float input[5][4] = {{0.0f, 0.0f, 0.0f, 0.0f},
158                                {1.0f, 1.0f, 1.0f, 1.0f},
159                                {-1.0f, 1.0f, -1.0f, 1.0f},
160                                {-1.0f, -1.0f, -1.0f, -1.0f},
161                                {64.0f / 127.0f, -8.0f / 127.0f, 32.0f / 127.0f, 16.0f / 127.0f}};
162 
163     const float floatFaultTolerance = 0.01f;
164     float outputVals[4];
165 
166     for (size_t i = 0; i < 5; i++)
167     {
168         UnpackSnorm4x8(PackSnorm4x8(input[i][0], input[i][1], input[i][2], input[i][3]),
169                        outputVals);
170         for (size_t j = 0; j < 4; j++)
171         {
172             float expected = input[i][j];
173             EXPECT_NEAR(expected, outputVals[j], floatFaultTolerance);
174         }
175     }
176 }
177 
178 // Test the correctness of gl::isNaN function.
TEST(MathUtilTest,isNaN)179 TEST(MathUtilTest, isNaN)
180 {
181     EXPECT_TRUE(isNaN(bitCast<float>(0xffu << 23 | 1u)));
182     EXPECT_TRUE(isNaN(bitCast<float>(1u << 31 | 0xffu << 23 | 1u)));
183     EXPECT_TRUE(isNaN(bitCast<float>(1u << 31 | 0xffu << 23 | 0x400000u)));
184     EXPECT_TRUE(isNaN(bitCast<float>(1u << 31 | 0xffu << 23 | 0x7fffffu)));
185     EXPECT_FALSE(isNaN(0.0f));
186     EXPECT_FALSE(isNaN(bitCast<float>(1u << 31 | 0xffu << 23)));
187     EXPECT_FALSE(isNaN(bitCast<float>(0xffu << 23)));
188 }
189 
190 // Test the correctness of gl::isInf function.
TEST(MathUtilTest,isInf)191 TEST(MathUtilTest, isInf)
192 {
193     EXPECT_TRUE(isInf(bitCast<float>(0xffu << 23)));
194     EXPECT_TRUE(isInf(bitCast<float>(1u << 31 | 0xffu << 23)));
195     EXPECT_FALSE(isInf(0.0f));
196     EXPECT_FALSE(isInf(bitCast<float>(0xffu << 23 | 1u)));
197     EXPECT_FALSE(isInf(bitCast<float>(1u << 31 | 0xffu << 23 | 1u)));
198     EXPECT_FALSE(isInf(bitCast<float>(1u << 31 | 0xffu << 23 | 0x400000u)));
199     EXPECT_FALSE(isInf(bitCast<float>(1u << 31 | 0xffu << 23 | 0x7fffffu)));
200     EXPECT_FALSE(isInf(bitCast<float>(0xfeu << 23 | 0x7fffffu)));
201     EXPECT_FALSE(isInf(bitCast<float>(1u << 31 | 0xfeu << 23 | 0x7fffffu)));
202 }
203 
TEST(MathUtilTest,CountLeadingZeros)204 TEST(MathUtilTest, CountLeadingZeros)
205 {
206     for (unsigned int i = 0; i < 32u; ++i)
207     {
208         uint32_t iLeadingZeros = 1u << (31u - i);
209         EXPECT_EQ(i, CountLeadingZeros(iLeadingZeros));
210     }
211     EXPECT_EQ(32u, CountLeadingZeros(0));
212 }
213 
214 // Some basic tests. Pow2 roundUp test and test that rounding up zero produces zero.
TEST(MathUtilTest,Pow2RoundUp)215 TEST(MathUtilTest, Pow2RoundUp)
216 {
217     EXPECT_EQ(0u, rx::roundUpPow2(0u, 4u));
218     EXPECT_EQ(4u, rx::roundUpPow2(1u, 4u));
219     EXPECT_EQ(4u, rx::roundUpPow2(4u, 4u));
220 }
221 
222 // Non-pow2 test.
TEST(MathUtilTest,BasicRoundUp)223 TEST(MathUtilTest, BasicRoundUp)
224 {
225     EXPECT_EQ(0u, rx::roundUp(0u, 5u));
226     EXPECT_EQ(5u, rx::roundUp(1u, 5u));
227     EXPECT_EQ(5u, rx::roundUp(4u, 5u));
228     EXPECT_EQ(5u, rx::roundUp(5u, 5u));
229 }
230 
231 // Test that rounding up zero produces zero for checked ints.
TEST(MathUtilTest,CheckedRoundUpZero)232 TEST(MathUtilTest, CheckedRoundUpZero)
233 {
234     auto checkedValue = rx::CheckedRoundUp(0u, 4u);
235     ASSERT_TRUE(checkedValue.IsValid());
236     ASSERT_EQ(0u, checkedValue.ValueOrDie());
237 }
238 
239 // Test out-of-bounds with CheckedRoundUp
TEST(MathUtilTest,CheckedRoundUpInvalid)240 TEST(MathUtilTest, CheckedRoundUpInvalid)
241 {
242     // The answer to this query is out of bounds.
243     auto limit        = std::numeric_limits<unsigned int>::max();
244     auto checkedValue = rx::CheckedRoundUp(limit, limit - 1);
245     ASSERT_FALSE(checkedValue.IsValid());
246 
247     // Our implementation can't handle this query, despite the parameters being in range.
248     auto checkedLimit = rx::CheckedRoundUp(limit - 1, limit);
249     ASSERT_FALSE(checkedLimit.IsValid());
250 }
251 
252 // Test BitfieldReverse which reverses the order of the bits in an integer.
TEST(MathUtilTest,BitfieldReverse)253 TEST(MathUtilTest, BitfieldReverse)
254 {
255     EXPECT_EQ(0u, gl::BitfieldReverse(0u));
256     EXPECT_EQ(0x80000000u, gl::BitfieldReverse(1u));
257     EXPECT_EQ(0x1u, gl::BitfieldReverse(0x80000000u));
258     uint32_t bits     = (1u << 4u) | (1u << 7u);
259     uint32_t reversed = (1u << (31u - 4u)) | (1u << (31u - 7u));
260     EXPECT_EQ(reversed, gl::BitfieldReverse(bits));
261 }
262 
263 // Test BitCount, which counts 1 bits in an integer.
TEST(MathUtilTest,BitCount)264 TEST(MathUtilTest, BitCount)
265 {
266     EXPECT_EQ(0, gl::BitCount(0u));
267     EXPECT_EQ(32, gl::BitCount(0xFFFFFFFFu));
268     EXPECT_EQ(10, gl::BitCount(0x17103121u));
269 
270     EXPECT_EQ(0, gl::BitCount(static_cast<uint64_t>(0ull)));
271     EXPECT_EQ(32, gl::BitCount(static_cast<uint64_t>(0xFFFFFFFFull)));
272     EXPECT_EQ(10, gl::BitCount(static_cast<uint64_t>(0x17103121ull)));
273 
274     EXPECT_EQ(33, gl::BitCount(static_cast<uint64_t>(0xFFFFFFFF80000000ull)));
275     EXPECT_EQ(11, gl::BitCount(static_cast<uint64_t>(0x1710312180000000ull)));
276 }
277 
278 // Test ScanForward, which scans for the least significant 1 bit from a non-zero integer.
TEST(MathUtilTest,ScanForward)279 TEST(MathUtilTest, ScanForward)
280 {
281     EXPECT_EQ(0ul, gl::ScanForward(1u));
282     EXPECT_EQ(16ul, gl::ScanForward(0x80010000u));
283     EXPECT_EQ(31ul, gl::ScanForward(0x80000000u));
284 
285     EXPECT_EQ(0ul, gl::ScanForward(static_cast<uint64_t>(1ull)));
286     EXPECT_EQ(16ul, gl::ScanForward(static_cast<uint64_t>(0x80010000ull)));
287     EXPECT_EQ(31ul, gl::ScanForward(static_cast<uint64_t>(0x80000000ull)));
288 
289     EXPECT_EQ(32ul, gl::ScanForward(static_cast<uint64_t>(0x100000000ull)));
290     EXPECT_EQ(48ul, gl::ScanForward(static_cast<uint64_t>(0x8001000000000000ull)));
291     EXPECT_EQ(63ul, gl::ScanForward(static_cast<uint64_t>(0x8000000000000000ull)));
292 }
293 
294 // Test ScanReverse, which scans for the most significant 1 bit from a non-zero integer.
TEST(MathUtilTest,ScanReverse)295 TEST(MathUtilTest, ScanReverse)
296 {
297     EXPECT_EQ(0ul, gl::ScanReverse(1u));
298     EXPECT_EQ(16ul, gl::ScanReverse(static_cast<uint64_t>(0x00010030ull)));
299     EXPECT_EQ(31ul, gl::ScanReverse(static_cast<uint64_t>(0x80000000ull)));
300 
301     EXPECT_EQ(32ul, gl::ScanReverse(static_cast<uint64_t>(0x100000000ull)));
302     EXPECT_EQ(48ul, gl::ScanReverse(static_cast<uint64_t>(0x0001080000000000ull)));
303     EXPECT_EQ(63ul, gl::ScanReverse(static_cast<uint64_t>(0x8000000000000000ull)));
304 }
305 
306 // Test FindLSB, which finds the least significant 1 bit.
TEST(MathUtilTest,FindLSB)307 TEST(MathUtilTest, FindLSB)
308 {
309     EXPECT_EQ(-1, gl::FindLSB(0u));
310     EXPECT_EQ(0, gl::FindLSB(1u));
311     EXPECT_EQ(16, gl::FindLSB(0x80010000u));
312     EXPECT_EQ(31, gl::FindLSB(0x80000000u));
313 }
314 
315 // Test FindMSB, which finds the most significant 1 bit.
TEST(MathUtilTest,FindMSB)316 TEST(MathUtilTest, FindMSB)
317 {
318     EXPECT_EQ(-1, gl::FindMSB(0u));
319     EXPECT_EQ(0, gl::FindMSB(1u));
320     EXPECT_EQ(16, gl::FindMSB(0x00010030u));
321     EXPECT_EQ(31, gl::FindMSB(0x80000000u));
322 }
323 
324 // Test Ldexp, which combines mantissa and exponent into a floating-point number.
TEST(MathUtilTest,Ldexp)325 TEST(MathUtilTest, Ldexp)
326 {
327     EXPECT_EQ(2.5f, Ldexp(0.625f, 2));
328     EXPECT_EQ(-5.0f, Ldexp(-0.625f, 3));
329     EXPECT_EQ(std::numeric_limits<float>::infinity(), Ldexp(0.625f, 129));
330     EXPECT_EQ(0.0f, Ldexp(1.0f, -129));
331 }
332 
333 // Test that Range::extend works as expected.
TEST(MathUtilTest,RangeExtend)334 TEST(MathUtilTest, RangeExtend)
335 {
336     RangeI range(0, 0);
337 
338     range.extend(5);
339     EXPECT_EQ(0, range.low());
340     EXPECT_EQ(6, range.high());
341     EXPECT_EQ(6, range.length());
342 
343     range.extend(-1);
344     EXPECT_EQ(-1, range.low());
345     EXPECT_EQ(6, range.high());
346     EXPECT_EQ(7, range.length());
347 
348     range.extend(10);
349     EXPECT_EQ(-1, range.low());
350     EXPECT_EQ(11, range.high());
351     EXPECT_EQ(12, range.length());
352 }
353 
354 // Test that Range::merge works as expected.
TEST(MathUtilTest,RangMerge)355 TEST(MathUtilTest, RangMerge)
356 {
357     // merge valid range to invalid range
358     RangeI range1;
359     range1.invalidate();
360     RangeI range2(1, 2);
361     range1.merge(range2);
362     EXPECT_EQ(1, range1.low());
363     EXPECT_EQ(2, range1.high());
364     EXPECT_EQ(1, range1.length());
365 
366     // merge invalid range to valid range
367     RangeI range3(1, 2);
368     RangeI range4;
369     range4.invalidate();
370     range3.merge(range4);
371     EXPECT_EQ(1, range3.low());
372     EXPECT_EQ(2, range3.high());
373     EXPECT_EQ(1, range3.length());
374 
375     // merge two valid non-overlapping ranges
376     RangeI range5(1, 2);
377     RangeI range6(3, 4);
378     range5.merge(range6);
379     EXPECT_EQ(1, range5.low());
380     EXPECT_EQ(4, range5.high());
381     EXPECT_EQ(3, range5.length());
382 
383     // merge two valid non-overlapping ranges
384     RangeI range7(2, 3);
385     RangeI range8(1, 2);
386     range7.merge(range8);
387     EXPECT_EQ(1, range7.low());
388     EXPECT_EQ(3, range7.high());
389     EXPECT_EQ(2, range7.length());
390 
391     // merge two valid overlapping ranges
392     RangeI range9(2, 4);
393     RangeI range10(1, 3);
394     range9.merge(range10);
395     EXPECT_EQ(1, range9.low());
396     EXPECT_EQ(4, range9.high());
397     EXPECT_EQ(3, range9.length());
398 
399     // merge two valid overlapping ranges
400     RangeI range11(1, 3);
401     RangeI range12(2, 4);
402     range11.merge(range12);
403     EXPECT_EQ(1, range11.low());
404     EXPECT_EQ(4, range11.high());
405     EXPECT_EQ(3, range11.length());
406 }
407 
408 // Test that Range::intersectsOrContinuous works as expected.
TEST(MathUtilTest,RangIntersectsOrContinuous)409 TEST(MathUtilTest, RangIntersectsOrContinuous)
410 {
411     // Two non-overlapping ranges
412     RangeI range1(1, 2);
413     RangeI range2(3, 4);
414     EXPECT_EQ(false, range1.intersectsOrContinuous(range2));
415     EXPECT_EQ(false, range2.intersectsOrContinuous(range1));
416 
417     // Two overlapping ranges
418     RangeI range3(1, 3);
419     RangeI range4(2, 4);
420     EXPECT_EQ(true, range3.intersectsOrContinuous(range4));
421     EXPECT_EQ(true, range4.intersectsOrContinuous(range3));
422 
423     // Two overlapping ranges
424     RangeI range5(1, 4);
425     RangeI range6(2, 3);
426     EXPECT_EQ(true, range5.intersectsOrContinuous(range6));
427     EXPECT_EQ(true, range6.intersectsOrContinuous(range5));
428 
429     // Two continuous ranges
430     RangeI range7(1, 3);
431     RangeI range8(3, 4);
432     EXPECT_EQ(true, range7.intersectsOrContinuous(range8));
433     EXPECT_EQ(true, range8.intersectsOrContinuous(range7));
434 
435     // Two identical ranges
436     RangeI range9(1, 3);
437     RangeI range10(1, 3);
438     EXPECT_EQ(true, range9.intersectsOrContinuous(range10));
439 }
440 
441 // Test that Range iteration works as expected.
TEST(MathUtilTest,RangeIteration)442 TEST(MathUtilTest, RangeIteration)
443 {
444     RangeI range(0, 10);
445     int expected = 0;
446     for (int value : range)
447     {
448         EXPECT_EQ(expected, value);
449         expected++;
450     }
451     EXPECT_EQ(range.length(), expected);
452 }
453 
454 // Tests for clampForBitCount
TEST(MathUtilTest,ClampForBitCount)455 TEST(MathUtilTest, ClampForBitCount)
456 {
457     constexpr uint64_t kUnsignedMax = std::numeric_limits<uint64_t>::max();
458     constexpr int64_t kSignedMax    = std::numeric_limits<int64_t>::max();
459     constexpr int64_t kSignedMin    = std::numeric_limits<int64_t>::min();
460     constexpr int64_t kRandomValue  = 0x4D34A0B1;
461 
462     ASSERT_EQ(clampForBitCount<uint64_t>(kUnsignedMax, 64), std::numeric_limits<uint64_t>::max());
463     ASSERT_EQ(clampForBitCount<uint64_t>(kUnsignedMax, 32),
464               static_cast<uint64_t>(std::numeric_limits<uint32_t>::max()));
465     ASSERT_EQ(clampForBitCount<uint64_t>(kUnsignedMax, 16),
466               static_cast<uint64_t>(std::numeric_limits<uint16_t>::max()));
467     ASSERT_EQ(clampForBitCount<uint64_t>(kUnsignedMax, 8),
468               static_cast<uint64_t>(std::numeric_limits<uint8_t>::max()));
469     ASSERT_EQ(clampForBitCount<uint64_t>(kUnsignedMax, 4), 15u);
470     ASSERT_EQ(clampForBitCount<uint64_t>(kUnsignedMax, 2), 3u);
471     ASSERT_EQ(clampForBitCount<uint64_t>(kUnsignedMax, 1), 1u);
472     ASSERT_EQ(clampForBitCount<uint64_t>(kUnsignedMax, 0), 0u);
473 
474     ASSERT_EQ(clampForBitCount<int64_t>(kSignedMax, 64), std::numeric_limits<int64_t>::max());
475     ASSERT_EQ(clampForBitCount<uint64_t>(static_cast<uint64_t>(kSignedMax), 64),
476               static_cast<uint64_t>(std::numeric_limits<int64_t>::max()));
477     ASSERT_EQ(clampForBitCount<int64_t>(kSignedMax, 32),
478               static_cast<int64_t>(std::numeric_limits<int32_t>::max()));
479     ASSERT_EQ(clampForBitCount<int64_t>(kSignedMax, 16),
480               static_cast<int64_t>(std::numeric_limits<int16_t>::max()));
481     ASSERT_EQ(clampForBitCount<int64_t>(kSignedMax, 8),
482               static_cast<int64_t>(std::numeric_limits<int8_t>::max()));
483     ASSERT_EQ(clampForBitCount<int64_t>(kSignedMax, 4), 7);
484     ASSERT_EQ(clampForBitCount<int64_t>(kSignedMax, 2), 1);
485     ASSERT_EQ(clampForBitCount<int64_t>(kSignedMax, 0), 0);
486 
487     ASSERT_EQ(clampForBitCount<int64_t>(kRandomValue, 64), kRandomValue);
488     ASSERT_EQ(clampForBitCount<int64_t>(kRandomValue, 32), kRandomValue);
489     ASSERT_EQ(clampForBitCount<int64_t>(kRandomValue, 16),
490               static_cast<int64_t>(std::numeric_limits<int16_t>::max()));
491     ASSERT_EQ(clampForBitCount<int64_t>(kRandomValue, 8),
492               static_cast<int64_t>(std::numeric_limits<int8_t>::max()));
493     ASSERT_EQ(clampForBitCount<int64_t>(kRandomValue, 4), 7);
494     ASSERT_EQ(clampForBitCount<int64_t>(kRandomValue, 2), 1);
495     ASSERT_EQ(clampForBitCount<int64_t>(kRandomValue, 0), 0);
496 
497     ASSERT_EQ(clampForBitCount<int64_t>(kSignedMin, 64), std::numeric_limits<int64_t>::min());
498     ASSERT_EQ(clampForBitCount<int64_t>(kSignedMin, 32),
499               static_cast<int64_t>(std::numeric_limits<int32_t>::min()));
500     ASSERT_EQ(clampForBitCount<int64_t>(kSignedMin, 16),
501               static_cast<int64_t>(std::numeric_limits<int16_t>::min()));
502     ASSERT_EQ(clampForBitCount<int64_t>(kSignedMin, 8),
503               static_cast<int64_t>(std::numeric_limits<int8_t>::min()));
504     ASSERT_EQ(clampForBitCount<int64_t>(kSignedMin, 4), -8);
505     ASSERT_EQ(clampForBitCount<int64_t>(kSignedMin, 2), -2);
506     ASSERT_EQ(clampForBitCount<int64_t>(kSignedMin, 0), 0);
507 }
508 
509 // Tests for float32 to float16 conversion
TEST(MathUtilTest,Float32ToFloat16)510 TEST(MathUtilTest, Float32ToFloat16)
511 {
512     ASSERT_EQ(float32ToFloat16(0.0f), 0x0000);
513     ASSERT_EQ(float32ToFloat16(-0.0f), 0x8000);
514 
515     float inf = std::numeric_limits<float>::infinity();
516 
517     ASSERT_EQ(float32ToFloat16(inf), 0x7C00);
518     ASSERT_EQ(float32ToFloat16(-inf), 0xFC00);
519 
520     // Check that NaN is converted to a value in one of the float16 NaN ranges
521     float nan      = std::numeric_limits<float>::quiet_NaN();
522     uint16_t nan16 = float32ToFloat16(nan);
523     ASSERT_TRUE(nan16 > 0xFC00 || (nan16 < 0x8000 && nan16 > 0x7C00));
524 
525     ASSERT_EQ(float32ToFloat16(1.0f), 0x3C00);
526 }
527 
528 // Tests the RGB float to 999E5 conversion
TEST(MathUtilTest,convertRGBFloatsTo999E5)529 TEST(MathUtilTest, convertRGBFloatsTo999E5)
530 {
531     const int numTests                  = 18;
532     const float input[numTests][3]      = {// The basics
533                                       {0.0f, 0.0f, 0.0f},
534                                       {0.0f, 0.0f, 1.0f},
535                                       {0.0f, 1.0f, 0.0f},
536                                       {0.0f, 1.0f, 1.0f},
537                                       {1.0f, 0.0f, 0.0f},
538                                       {1.0f, 0.0f, 1.0f},
539                                       {1.0f, 1.0f, 0.0f},
540                                       {1.0f, 1.0f, 1.0f},
541                                       // Extended range
542                                       {0.0f, 0.0f, 1.5f},
543                                       {0.0f, 2.0f, 0.0f},
544                                       {0.0f, 2.5f, 3.0f},
545                                       {3.5f, 0.0f, 0.0f},
546                                       {4.0f, 0.0f, 4.5f},
547                                       {5.0f, 5.5f, 0.0f},
548                                       {6.0f, 6.5f, 7.0f},
549                                       // Random
550                                       {0.1f, 9.6f, 3.2f},
551                                       {2.0f, 1.7f, 8.6f},
552                                       {0.7f, 4.2f, 9.1f}};
553     const unsigned int result[numTests] = {// The basics
554                                            0x00000000, 0x84000000, 0x80020000, 0x84020000,
555                                            0x80000100, 0x84000100, 0x80020100, 0x84020100,
556                                            // Extended range
557                                            0x86000000, 0x88020000, 0x8E028000, 0x880001C0,
558                                            0x94800100, 0x9002C140, 0x97034180,
559                                            // Random
560                                            0x999A6603, 0x9C4C6C40, 0x9C8D0C16};
561 
562     for (int i = 0; i < numTests; i++)
563     {
564         EXPECT_EQ(convertRGBFloatsTo999E5(input[i][0], input[i][1], input[i][2]), result[i]);
565     }
566 }
567 
568 // Tests the 999E5 to RGB float conversion
TEST(MathUtilTest,convert999E5toRGBFloats)569 TEST(MathUtilTest, convert999E5toRGBFloats)
570 {
571     const int numTests                 = 18;
572     const float result[numTests][3]    = {// The basics
573                                        {0.0f, 0.0f, 0.0f},
574                                        {0.0f, 0.0f, 1.0f},
575                                        {0.0f, 1.0f, 0.0f},
576                                        {0.0f, 1.0f, 1.0f},
577                                        {1.0f, 0.0f, 0.0f},
578                                        {1.0f, 0.0f, 1.0f},
579                                        {1.0f, 1.0f, 0.0f},
580                                        {1.0f, 1.0f, 1.0f},
581                                        // Extended range
582                                        {0.0f, 0.0f, 1.5f},
583                                        {0.0f, 2.0f, 0.0f},
584                                        {0.0f, 2.5f, 3.0f},
585                                        {3.5f, 0.0f, 0.0f},
586                                        {4.0f, 0.0f, 4.5f},
587                                        {5.0f, 5.5f, 0.0f},
588                                        {6.0f, 6.5f, 7.0f},
589                                        // Random
590                                        {0.1f, 9.6f, 3.2f},
591                                        {2.0f, 1.7f, 8.6f},
592                                        {0.7f, 4.2f, 9.1f}};
593     const unsigned int input[numTests] = {// The basics
594                                           0x00000000, 0x84000000, 0x80020000, 0x84020000,
595                                           0x80000100, 0x84000100, 0x80020100, 0x84020100,
596                                           // Extended range
597                                           0x86000000, 0x88020000, 0x8E028000, 0x880001C0,
598                                           0x94800100, 0x9002C140, 0x97034180,
599                                           // Random
600                                           0x999A6603, 0x9C4C6C40, 0x9C8D0C16};
601     // Note: quite a low tolerance is required
602     const float floatFaultTolerance = 0.05f;
603     float outR, outG, outB;
604 
605     for (int i = 0; i < numTests; i++)
606     {
607         convert999E5toRGBFloats(input[i], &outR, &outG, &outB);
608         EXPECT_NEAR(result[i][0], outR, floatFaultTolerance);
609         EXPECT_NEAR(result[i][1], outG, floatFaultTolerance);
610         EXPECT_NEAR(result[i][2], outB, floatFaultTolerance);
611     }
612 }
613 
614 // Test sRGB conversions
TEST(MathUtilTest,sRGB)615 TEST(MathUtilTest, sRGB)
616 {
617     // Check simple roundtrip
618     for (size_t c = 0; c < 256; c++)
619     {
620         ASSERT_EQ(c, linearToSRGB(sRGBToLinear(c)));
621     }
622 
623     // Check average of identical values
624     for (size_t c = 0; c < 256; c++)
625     {
626         ASSERT_EQ(c, linearToSRGB((sRGBToLinear(c) + sRGBToLinear(c)) * 0.5));
627     }
628 
629     // Check that all average values are in range
630     for (size_t a = 0; a < 256; a++)
631     {
632         for (size_t b = 0; b < 256; b++)
633         {
634             const float avg = (sRGBToLinear(a) + sRGBToLinear(b)) * 0.5f;
635             ASSERT_GE(avg, 0.0f);
636             ASSERT_LE(avg, 1.0f);
637         }
638     }
639 }
640 
641 // Test roundToNearest with boundary values
TEST(MathUtilTest,RoundToNearest)642 TEST(MathUtilTest, RoundToNearest)
643 {
644     EXPECT_EQ((roundToNearest<float, uint8_t>(0.00000000f)), 0u);
645     EXPECT_EQ((roundToNearest<float, uint8_t>(0.49999997f)), 0u);
646     EXPECT_EQ((roundToNearest<float, uint8_t>(0.50000000f)), 1u);
647 
648     EXPECT_EQ((roundToNearest<float, int8_t>(-0.50000000f)), -1);
649     EXPECT_EQ((roundToNearest<float, int8_t>(-0.49999997f)), 0);
650     EXPECT_EQ((roundToNearest<float, int8_t>(-0.00000000f)), 0);
651     EXPECT_EQ((roundToNearest<float, int8_t>(+0.00000000f)), 0);
652     EXPECT_EQ((roundToNearest<float, int8_t>(+0.49999997f)), 0);
653     EXPECT_EQ((roundToNearest<float, int8_t>(+0.50000000f)), +1);
654 
655     EXPECT_EQ((roundToNearest<double, uint8_t>(0.00000000000000000)), 0u);
656     EXPECT_EQ((roundToNearest<double, uint8_t>(0.49999999999999994)), 0u);
657     EXPECT_EQ((roundToNearest<double, uint8_t>(0.50000000000000000)), 1u);
658 
659     EXPECT_EQ((roundToNearest<double, int8_t>(-0.50000000000000000)), -1);
660     EXPECT_EQ((roundToNearest<double, int8_t>(-0.49999999999999994)), 0);
661     EXPECT_EQ((roundToNearest<double, int8_t>(-0.00000000000000000)), 0);
662     EXPECT_EQ((roundToNearest<double, int8_t>(+0.00000000000000000)), 0);
663     EXPECT_EQ((roundToNearest<double, int8_t>(+0.49999999999999994)), 0);
664     EXPECT_EQ((roundToNearest<double, int8_t>(+0.50000000000000000)), +1);
665 }
666 
667 // Test floatToNormalized conversions with uint8_t
TEST(MathUtilTest,FloatToNormalizedUnorm8)668 TEST(MathUtilTest, FloatToNormalizedUnorm8)
669 {
670     // Check exact values
671     EXPECT_EQ(floatToNormalized<uint8_t>(0.00f), 0u);
672     EXPECT_EQ(floatToNormalized<uint8_t>(0.25f), 64u);
673     EXPECT_EQ(floatToNormalized<uint8_t>(0.75f), 191u);
674     EXPECT_EQ(floatToNormalized<uint8_t>(1.00f), 255u);
675 
676     // Check near values
677     EXPECT_NEAR(floatToNormalized<uint8_t>(0.50f), 127u, 1);
678 }
679 
680 // Test floatToNormalized conversions with int8_t
TEST(MathUtilTest,FloatToNormalizedSnorm8)681 TEST(MathUtilTest, FloatToNormalizedSnorm8)
682 {
683     // Check exact values
684     EXPECT_EQ(floatToNormalized<int8_t>(-1.00f), -127);
685     EXPECT_EQ(floatToNormalized<int8_t>(-0.75f), -95);
686     EXPECT_EQ(floatToNormalized<int8_t>(-0.25f), -32);
687     EXPECT_EQ(floatToNormalized<int8_t>(+0.00f), 0);
688     EXPECT_EQ(floatToNormalized<int8_t>(+0.25f), +32);
689     EXPECT_EQ(floatToNormalized<int8_t>(+0.75f), +95);
690     EXPECT_EQ(floatToNormalized<int8_t>(+1.00f), +127);
691 
692     // Check near values
693     EXPECT_NEAR(floatToNormalized<int8_t>(-0.50f), -63, 1);
694     EXPECT_NEAR(floatToNormalized<int8_t>(+0.50f), +63, 1);
695 }
696 
697 // Test floatToNormalized conversions with uint16_t
TEST(MathUtilTest,FloatToNormalizedUnorm16)698 TEST(MathUtilTest, FloatToNormalizedUnorm16)
699 {
700     // Check exact values
701     EXPECT_EQ(floatToNormalized<uint16_t>(0.00f), 0u);
702     EXPECT_EQ(floatToNormalized<uint16_t>(0.25f), 16384u);
703     EXPECT_EQ(floatToNormalized<uint16_t>(0.75f), 49151u);
704     EXPECT_EQ(floatToNormalized<uint16_t>(1.00f), 65535u);
705 
706     // Check near values
707     EXPECT_NEAR(floatToNormalized<uint16_t>(0.50f), 32767u, 1);
708 }
709 
710 // Test floatToNormalized conversions with int16_t
TEST(MathUtilTest,FloatToNormalizedSnorm16)711 TEST(MathUtilTest, FloatToNormalizedSnorm16)
712 {
713     // Check exact values
714     EXPECT_EQ(floatToNormalized<int16_t>(-1.00f), -32767);
715     EXPECT_EQ(floatToNormalized<int16_t>(-0.75f), -24575);
716     EXPECT_EQ(floatToNormalized<int16_t>(-0.25f), -8192);
717     EXPECT_EQ(floatToNormalized<int16_t>(+0.00f), 0);
718     EXPECT_EQ(floatToNormalized<int16_t>(+0.25f), +8192);
719     EXPECT_EQ(floatToNormalized<int16_t>(+0.75f), +24575);
720     EXPECT_EQ(floatToNormalized<int16_t>(+1.00f), +32767);
721 
722     // Check near values
723     EXPECT_NEAR(floatToNormalized<int16_t>(-0.50f), -16383, 1);
724     EXPECT_NEAR(floatToNormalized<int16_t>(+0.50f), +16383, 1);
725 }
726 
727 // Test floatToNormalized conversions with uint32_t
TEST(MathUtilTest,FloatToNormalizedUnorm32)728 TEST(MathUtilTest, FloatToNormalizedUnorm32)
729 {
730     // Check exact values
731     EXPECT_EQ(floatToNormalized<uint32_t>(0.00f), 0u);
732     EXPECT_EQ(floatToNormalized<uint32_t>(0.25f), 1073741824u);
733     EXPECT_EQ(floatToNormalized<uint32_t>(0.75f), 3221225471u);
734     EXPECT_EQ(floatToNormalized<uint32_t>(1.00f), 4294967295u);
735 
736     // Check near values
737     EXPECT_NEAR(floatToNormalized<uint32_t>(0.50f), 2147483647u, 1);
738 }
739 
740 // Test floatToNormalized conversions with int32_t
TEST(MathUtilTest,FloatToNormalizedSnorm32)741 TEST(MathUtilTest, FloatToNormalizedSnorm32)
742 {
743     // Check exact values
744     EXPECT_EQ(floatToNormalized<int32_t>(-1.00f), -2147483647);
745     EXPECT_EQ(floatToNormalized<int32_t>(-0.75f), -1610612735);
746     EXPECT_EQ(floatToNormalized<int32_t>(-0.25f), -536870912);
747     EXPECT_EQ(floatToNormalized<int32_t>(+0.00f), 0);
748     EXPECT_EQ(floatToNormalized<int32_t>(+0.25f), +536870912);
749     EXPECT_EQ(floatToNormalized<int32_t>(+0.75f), +1610612735);
750     EXPECT_EQ(floatToNormalized<int32_t>(+1.00f), +2147483647);
751 
752     // Check near values
753     EXPECT_NEAR(floatToNormalized<int32_t>(-0.50f), -1073741823, 1);
754     EXPECT_NEAR(floatToNormalized<int32_t>(+0.50f), +1073741823, 1);
755 }
756 
757 // Test floatToNormalized conversions with 2-bit unsigned
TEST(MathUtilTest,FloatToNormalizedUnorm2)758 TEST(MathUtilTest, FloatToNormalizedUnorm2)
759 {
760     // Check exact values
761     EXPECT_EQ((floatToNormalized<2, uint8_t>(0.00f)), 0u);
762     EXPECT_EQ((floatToNormalized<2, uint8_t>(0.25f)), 1u);
763     EXPECT_EQ((floatToNormalized<2, uint8_t>(0.75f)), 2u);
764     EXPECT_EQ((floatToNormalized<2, uint8_t>(1.00f)), 3u);
765 
766     // Check near values
767     EXPECT_NEAR((floatToNormalized<2, uint8_t>(0.50f)), 1u, 1);
768 }
769 
770 // Test floatToNormalized conversions with 2-bit signed
TEST(MathUtilTest,FloatToNormalizedSnorm2)771 TEST(MathUtilTest, FloatToNormalizedSnorm2)
772 {
773     // Check exact values
774     EXPECT_EQ((floatToNormalized<2, int8_t>(-1.00f)), -1);
775     EXPECT_EQ((floatToNormalized<2, int8_t>(-0.75f)), -1);
776     EXPECT_EQ((floatToNormalized<2, int8_t>(-0.25f)), 0);
777     EXPECT_EQ((floatToNormalized<2, int8_t>(+0.00f)), 0);
778     EXPECT_EQ((floatToNormalized<2, int8_t>(+0.25f)), 0);
779     EXPECT_EQ((floatToNormalized<2, int8_t>(+0.75f)), +1);
780     EXPECT_EQ((floatToNormalized<2, int8_t>(+1.00f)), +1);
781 
782     // Check near values
783     EXPECT_NEAR((floatToNormalized<2, int8_t>(-0.50f)), 0, 1);
784     EXPECT_NEAR((floatToNormalized<2, int8_t>(+0.50f)), 0, 1);
785 }
786 
787 // Test floatToNormalized conversions with 10-bit unsigned
TEST(MathUtilTest,FloatToNormalizedUnorm10)788 TEST(MathUtilTest, FloatToNormalizedUnorm10)
789 {
790     // Check exact values
791     EXPECT_EQ((floatToNormalized<10, uint16_t>(0.00f)), 0u);
792     EXPECT_EQ((floatToNormalized<10, uint16_t>(0.25f)), 256u);
793     EXPECT_EQ((floatToNormalized<10, uint16_t>(0.75f)), 767u);
794     EXPECT_EQ((floatToNormalized<10, uint16_t>(1.00f)), 1023u);
795 
796     // Check near values
797     EXPECT_NEAR((floatToNormalized<10, uint16_t>(0.50f)), 511u, 1);
798 }
799 
800 // Test floatToNormalized conversions with 10-bit signed
TEST(MathUtilTest,FloatToNormalizedSnorm10)801 TEST(MathUtilTest, FloatToNormalizedSnorm10)
802 {
803     // Check exact values
804     EXPECT_EQ((floatToNormalized<10, int16_t>(-1.00f)), -511);
805     EXPECT_EQ((floatToNormalized<10, int16_t>(-0.75f)), -383);
806     EXPECT_EQ((floatToNormalized<10, int16_t>(-0.25f)), -128);
807     EXPECT_EQ((floatToNormalized<10, int16_t>(+0.00f)), 0);
808     EXPECT_EQ((floatToNormalized<10, int16_t>(+0.25f)), +128);
809     EXPECT_EQ((floatToNormalized<10, int16_t>(+0.75f)), +383);
810     EXPECT_EQ((floatToNormalized<10, int16_t>(+1.00f)), +511);
811 
812     // Check near values
813     EXPECT_NEAR((floatToNormalized<10, int16_t>(-0.50f)), -255, 1);
814     EXPECT_NEAR((floatToNormalized<10, int16_t>(+0.50f)), +255, 1);
815 }
816 
817 // Test floatToNormalized conversions with 30-bit unsigned
TEST(MathUtilTest,FloatToNormalizedUnorm30)818 TEST(MathUtilTest, FloatToNormalizedUnorm30)
819 {
820     // Check exact values
821     EXPECT_EQ((floatToNormalized<30, uint32_t>(0.00f)), 0u);
822     EXPECT_EQ((floatToNormalized<30, uint32_t>(0.25f)), 268435456u);
823     EXPECT_EQ((floatToNormalized<30, uint32_t>(0.75f)), 805306367u);
824     EXPECT_EQ((floatToNormalized<30, uint32_t>(1.00f)), 1073741823u);
825 
826     // Check near values
827     EXPECT_NEAR((floatToNormalized<30, uint32_t>(0.50f)), 536870911u, 1);
828 }
829 
830 // Test floatToNormalized conversions with 30-bit signed
TEST(MathUtilTest,FloatToNormalizedSnorm30)831 TEST(MathUtilTest, FloatToNormalizedSnorm30)
832 {
833     // Check exact values
834     EXPECT_EQ((floatToNormalized<30, int32_t>(-1.00f)), -536870911);
835     EXPECT_EQ((floatToNormalized<30, int32_t>(-0.75f)), -402653183);
836     EXPECT_EQ((floatToNormalized<30, int32_t>(-0.25f)), -134217728);
837     EXPECT_EQ((floatToNormalized<30, int32_t>(+0.00f)), 0);
838     EXPECT_EQ((floatToNormalized<30, int32_t>(+0.25f)), +134217728);
839     EXPECT_EQ((floatToNormalized<30, int32_t>(+0.75f)), +402653183);
840     EXPECT_EQ((floatToNormalized<30, int32_t>(+1.00f)), +536870911);
841 
842     // Check near values
843     EXPECT_NEAR((floatToNormalized<30, int32_t>(-0.50f)), -268435455, 1);
844     EXPECT_NEAR((floatToNormalized<30, int32_t>(+0.50f)), +268435455, 1);
845 }
846 
847 }  // anonymous namespace
848