1 | #include <gtk/gtk.h> |
2 | |
3 | #include "gsk/gl/fp16private.h" |
4 | |
5 | static void |
6 | test_constants (void) |
7 | { |
8 | struct { |
9 | float f; |
10 | guint16 h; |
11 | } tests[] = { |
12 | { 0.0, FP16_ZERO }, |
13 | { 1.0, FP16_ONE }, |
14 | { -1.0, FP16_MINUS_ONE }, |
15 | }; |
16 | |
17 | for (int i = 0; i < G_N_ELEMENTS (tests); i++) |
18 | { |
19 | float f[4]; |
20 | guint16 h[4]; |
21 | |
22 | memset (s: f, c: 0, n: sizeof (f)); |
23 | f[0] = tests[i].f; |
24 | float_to_half4 (f, h); |
25 | g_assert_cmpuint (h[0], ==, tests[i].h); |
26 | |
27 | |
28 | memset (s: h, c: 0, n: sizeof (h)); |
29 | h[0] = tests[i].h; |
30 | half_to_float4 (h, f); |
31 | g_assert_cmpfloat (f[0], ==, tests[i].f); |
32 | } |
33 | } |
34 | |
35 | static float |
36 | random_representable_float (void) |
37 | { |
38 | guint16 h[4]; |
39 | float f[4]; |
40 | do |
41 | { |
42 | /* generate a random float thats representable as fp16 */ |
43 | memset (s: h, c: 0, n: sizeof (h)); |
44 | h[0] = g_random_int_range (G_MININT16, G_MAXINT16); |
45 | half_to_float4 (h, f); |
46 | } |
47 | while (!isnormal (f[0])); /* skip nans and infs since they don't compare well */ |
48 | |
49 | return f[0]; |
50 | } |
51 | |
52 | static void |
53 | test_roundtrip (void) |
54 | { |
55 | for (int i = 0; i < 100; i++) |
56 | { |
57 | float f[4]; |
58 | float f2[4]; |
59 | guint16 h[4]; |
60 | |
61 | f2[0] = random_representable_float (); |
62 | memset (s: f, c: 0, n: sizeof (f)); |
63 | f[0] = f2[0]; |
64 | |
65 | float_to_half4 (f, h); |
66 | half_to_float4 (h, f: f2); |
67 | |
68 | g_assert_cmpfloat (f[0], ==, f2[0]); |
69 | } |
70 | } |
71 | |
72 | /* Test that the array version work as expected, |
73 | * in particular with unaligned boundaries. |
74 | */ |
75 | static void |
76 | test_many (void) |
77 | { |
78 | for (int i = 0; i < 100; i++) |
79 | { |
80 | int size = g_random_int_range (begin: 100, end: 200); |
81 | int offset = g_random_int_range (begin: 0, end: 20); |
82 | |
83 | guint16 *h = g_new0 (guint16, size); |
84 | float *f = g_new0 (float, size); |
85 | float *f2 = g_new0 (float, size); |
86 | |
87 | for (int j = offset; j < size; j++) |
88 | f[j] = random_representable_float (); |
89 | |
90 | float_to_half (f: f + offset, h: h + offset, n: size - offset); |
91 | half_to_float (h: h + offset, f: f2 + offset, n: size - offset); |
92 | |
93 | for (int j = offset; j < size; j++) |
94 | g_assert_cmpfloat (f[j], ==, f2[j]); |
95 | } |
96 | } |
97 | |
98 | int |
99 | main (int argc, char *argv[]) |
100 | { |
101 | (g_test_init) (argc: &argc, argv: &argv, NULL); |
102 | |
103 | g_test_add_func (testpath: "/half-float/constants" , test_func: test_constants); |
104 | g_test_add_func (testpath: "/half-float/roundtrip" , test_func: test_roundtrip); |
105 | g_test_add_func (testpath: "/half-float/many" , test_func: test_many); |
106 | |
107 | return g_test_run (); |
108 | } |
109 | |