#include #include "gsk/gl/fp16private.h" static void test_constants (void) { struct { float f; guint16 h; } tests[] = { { 0.0, FP16_ZERO }, { 1.0, FP16_ONE }, { -1.0, FP16_MINUS_ONE }, }; for (int i = 0; i < G_N_ELEMENTS (tests); i++) { float f[4]; guint16 h[4]; memset (f, 0, sizeof (f)); f[0] = tests[i].f; float_to_half4 (f, h); g_assert_cmpuint (h[0], ==, tests[i].h); memset (h, 0, sizeof (h)); h[0] = tests[i].h; half_to_float4 (h, f); g_assert_cmpfloat (f[0], ==, tests[i].f); } } static void test_constants_c (void) { struct { float f; guint16 h; } tests[] = { { 0.0, FP16_ZERO }, { 1.0, FP16_ONE }, { -1.0, FP16_MINUS_ONE }, }; for (int i = 0; i < G_N_ELEMENTS (tests); i++) { float f[4]; guint16 h[4]; memset (f, 0, sizeof (f)); f[0] = tests[i].f; float_to_half4_c (f, h); g_assert_cmpuint (h[0], ==, tests[i].h); memset (h, 0, sizeof (h)); h[0] = tests[i].h; half_to_float4_c (h, f); g_assert_cmpfloat (f[0], ==, tests[i].f); } } static float random_representable_float (void) { guint16 h[4]; float f[4]; do { /* generate a random float thats representable as fp16 */ memset (h, 0, sizeof (h)); h[0] = g_test_rand_int_range (G_MININT16, G_MAXINT16); half_to_float4 (h, f); } while (!isnormal (f[0])); /* skip nans and infs since they don't compare well */ return f[0]; } static void test_roundtrip (void) { for (int i = 0; i < 100; i++) { float f[4]; float f2[4]; guint16 h[4]; f2[0] = random_representable_float (); memset (f, 0, sizeof (f)); f[0] = f2[0]; float_to_half4 (f, h); half_to_float4 (h, f2); g_assert_cmpfloat (f[0], ==, f2[0]); } } static void test_roundtrip_c (void) { for (int i = 0; i < 100; i++) { float f[4]; float f2[4]; guint16 h[4]; f2[0] = random_representable_float (); memset (f, 0, sizeof (f)); f[0] = f2[0]; float_to_half4_c (f, h); half_to_float4_c (h, f2); g_assert_cmpfloat (f[0], ==, f2[0]); } } /* Test that the array version work as expected, * in particular with unaligned boundaries. */ static void test_many (void) { for (int i = 0; i < 100; i++) { int size = g_test_rand_int_range (100, 200); int offset = g_test_rand_int_range (0, 20); guint16 *h = g_new0 (guint16, size); float *f = g_new0 (float, size); float *f2 = g_new0 (float, size); for (int j = offset; j < size; j++) f[j] = random_representable_float (); float_to_half (f + offset, h + offset, size - offset); half_to_float (h + offset, f2 + offset, size - offset); for (int j = offset; j < size; j++) g_assert_cmpfloat (f[j], ==, f2[j]); } } static void test_many_c (void) { for (int i = 0; i < 100; i++) { int size = g_test_rand_int_range (100, 200); int offset = g_test_rand_int_range (0, 20); guint16 *h = g_new0 (guint16, size); float *f = g_new0 (float, size); float *f2 = g_new0 (float, size); for (int j = offset; j < size; j++) f[j] = random_representable_float (); float_to_half_c (f + offset, h + offset, size - offset); half_to_float_c (h + offset, f2 + offset, size - offset); for (int j = offset; j < size; j++) g_assert_cmpfloat (f[j], ==, f2[j]); } } int main (int argc, char *argv[]) { (g_test_init) (&argc, &argv, NULL); g_test_add_func ("/half-float/constants", test_constants); g_test_add_func ("/half-float/roundtrip", test_roundtrip); g_test_add_func ("/half-float/many", test_many); g_test_add_func ("/half-float/constants/c", test_constants_c); g_test_add_func ("/half-float/roundtrip/c", test_roundtrip_c); g_test_add_func ("/half-float/many/c", test_many_c); return g_test_run (); }