Hard-assert on something that has bitten me too many times now.
[movit] / fp16_test.cpp
1 #include "fp16.h"
2
3 #include <math.h>
4 #include <gtest/gtest.h>
5
6 namespace movit {
7 namespace {
8
9 fp16_int_t make_fp16(unsigned short x)
10 {
11         fp16_int_t ret;
12         ret.val = x;
13         return ret;
14 }
15
16 }  // namespace
17
18 TEST(FP16Test, Simple) {
19         EXPECT_EQ(0x0000, fp32_to_fp16(0.0).val);
20         EXPECT_DOUBLE_EQ(0.0, fp16_to_fp32(make_fp16(0x0000)));
21
22         EXPECT_EQ(0x3c00, fp32_to_fp16(1.0).val);
23         EXPECT_DOUBLE_EQ(1.0, fp16_to_fp32(make_fp16(0x3c00)));
24
25         EXPECT_EQ(0x3555, fp32_to_fp16(1.0 / 3.0).val);
26         EXPECT_DOUBLE_EQ(0.333251953125, fp16_to_fp32(make_fp16(0x3555)));
27 }
28
29 TEST(FP16Test, RoundToNearestEven) {
30         ASSERT_DOUBLE_EQ(1.0, fp16_to_fp32(make_fp16(0x3c00)));
31
32         double x0 = fp16_to_fp32(make_fp16(0x3c00));
33         double x1 = fp16_to_fp32(make_fp16(0x3c01));
34         double x2 = fp16_to_fp32(make_fp16(0x3c02));
35         double x3 = fp16_to_fp32(make_fp16(0x3c03));
36         double x4 = fp16_to_fp32(make_fp16(0x3c04));
37
38         EXPECT_EQ(0x3c00, fp32_to_fp16(0.5 * (x0 + x1)).val);
39         EXPECT_EQ(0x3c02, fp32_to_fp16(0.5 * (x1 + x2)).val);
40         EXPECT_EQ(0x3c02, fp32_to_fp16(0.5 * (x2 + x3)).val);
41         EXPECT_EQ(0x3c04, fp32_to_fp16(0.5 * (x3 + x4)).val);
42 }
43
44 union fp64 {
45         double f;
46         unsigned long long ll;
47 };
48 union fp32 {
49         float f;
50         unsigned int u;
51 };
52
53 TEST(FP16Test, NaN) {
54         // Ignore the sign bit.
55         EXPECT_EQ(0x7e00, fp32_to_fp16(0.0 / 0.0).val & 0x7fff);
56         EXPECT_TRUE(isnan(fp16_to_fp32(make_fp16(0xfe00))));
57
58         fp32 borderline_inf;
59         borderline_inf.u = 0x7f800000ull;
60         fp32 borderline_nan;
61         borderline_nan.u = 0x7f800001ull;
62
63         ASSERT_FALSE(isfinite(borderline_inf.f));
64         ASSERT_FALSE(isnan(borderline_inf.f));
65
66         ASSERT_FALSE(isfinite(borderline_nan.f));
67         ASSERT_TRUE(isnan(borderline_nan.f));
68
69         double borderline_inf_roundtrip = fp16_to_fp32(fp32_to_fp16(borderline_inf.f));
70         double borderline_nan_roundtrip = fp16_to_fp32(fp32_to_fp16(borderline_nan.f));
71
72         EXPECT_FALSE(isfinite(borderline_inf_roundtrip));
73         EXPECT_FALSE(isnan(borderline_inf_roundtrip));
74
75         EXPECT_FALSE(isfinite(borderline_nan_roundtrip));
76         EXPECT_TRUE(isnan(borderline_nan_roundtrip));
77 }
78
79 TEST(FP16Test, Denormals) {
80         const double smallest_fp16_denormal = 5.9604644775390625e-08;
81         EXPECT_EQ(0x0001, fp32_to_fp16(smallest_fp16_denormal).val);
82         EXPECT_EQ(0x0000, fp32_to_fp16(0.5 * smallest_fp16_denormal).val);  // Round-to-even.
83         EXPECT_EQ(0x0001, fp32_to_fp16(0.51 * smallest_fp16_denormal).val);
84         EXPECT_EQ(0x0002, fp32_to_fp16(1.5 * smallest_fp16_denormal).val);
85
86         const double smallest_fp16_non_denormal = 6.103515625e-05;
87         EXPECT_EQ(0x0400, fp32_to_fp16(smallest_fp16_non_denormal).val);
88         EXPECT_EQ(0x0400, fp32_to_fp16(smallest_fp16_non_denormal - 0.5 * smallest_fp16_denormal).val);  // Round-to-even.
89         EXPECT_EQ(0x03ff, fp32_to_fp16(smallest_fp16_non_denormal - smallest_fp16_denormal).val);
90 }
91
92 }  // namespace movit