Add a utility library for downconverting to fp16.
[movit] / fp16_test.cpp
1 #include "fp16.h"
2
3 #include <math.h>
4 #include <gtest/gtest.h>
5
6 namespace movit {
7
8 TEST(FP16Test, Simple) {
9         EXPECT_EQ(0x0000, fp64_to_fp16(0.0));
10         EXPECT_DOUBLE_EQ(0.0, fp16_to_fp64(0x0000));
11
12         EXPECT_EQ(0x3c00, fp64_to_fp16(1.0));
13         EXPECT_DOUBLE_EQ(1.0, fp16_to_fp64(0x3c00));
14
15         EXPECT_EQ(0x3555, fp64_to_fp16(1.0 / 3.0));
16         EXPECT_DOUBLE_EQ(0.333251953125, fp16_to_fp64(0x3555));
17 }
18
19 TEST(FP16Test, NaN) {
20         EXPECT_EQ(0xfe00, fp64_to_fp16(0.0 / 0.0));
21         EXPECT_TRUE(isnan(fp16_to_fp64(0xfe00)));
22 }
23
24 union fp64 {
25         double f;
26         unsigned long long ll;
27 };
28 union fp32 {
29         float f;
30         unsigned int u;
31 };
32
33 // Randomly test a large number of fp64 -> fp32 conversions, comparing
34 // against the FPU.
35 TEST(FP16Test, FP32ReferenceDownconvert) {
36         srand(12345);
37
38         for (int i = 0; i < 1000000; ++i) {
39                 unsigned r1 = rand();
40                 unsigned r2 = rand();
41                 unsigned r3 = rand();
42                 union fp64 src;
43                 union fp32 reference, result;
44
45                 src.ll = (((unsigned long long)r1) << 33) ^ ((unsigned long long)r2 << 16) ^ r3;
46                 reference.f = float(src.f);
47                 result.u = fp64_to_fp32(src.f);
48
49                 EXPECT_EQ(isnan(result.f), isnan(reference.f));
50                 if (!isnan(result.f)) {
51                         EXPECT_EQ(result.u, reference.u)
52                             << src.f << " got rounded to " << result.u << " (" << result.f << ")";
53                 }
54         }
55 }
56
57 // Randomly test a large number of fp32 -> fp64 conversions, comparing
58 // against the FPU.
59 TEST(FP16Test, FP32ReferenceUpconvert) {
60         srand(12345);
61
62         for (int i = 0; i < 1000000; ++i) {
63                 unsigned r1 = rand();
64                 unsigned r2 = rand();
65                 union fp32 src;
66                 union fp64 reference, result;
67
68                 src.u = ((unsigned long long)r1 << 16) ^ r2;
69                 reference.f = double(src.f);
70                 result.f = fp32_to_fp64(src.u);
71
72                 EXPECT_EQ(isnan(result.f), isnan(reference.f));
73                 if (!isnan(result.f)) {
74                         EXPECT_EQ(result.ll, reference.ll)
75                             << src.f << " got converted to " << result.ll << " (" << result.f << ")";
76                 }
77         }
78 }
79
80 }  // namespace movit