#include #include #ifdef __SSE2__ #include typedef union { __m128i x; char a[16]; } union128i_b; typedef union { __m128i x; unsigned char a[16]; } union128i_ub; typedef union { __m128i x; short a[8]; } union128i_w; typedef union { __m128i x; unsigned short a[8]; } union128i_uw; typedef union { __m128i x; int a[4]; } union128i_d; typedef union { __m128i x; long long a[2]; } union128i_q; typedef union { __m128d x; double a[2]; } union128d; #endif typedef union { __m128 x; float a[4]; } union128; #ifndef ARRAY_SIZE #define ARRAY_SIZE(A) (sizeof (A) / sizeof ((A)[0])) #endif #ifdef DEBUG #define PRINTF printf #else #define PRINTF(...) #endif #define CHECK_EXP(UINON_TYPE, VALUE_TYPE, FMT) \ static int \ __attribute__((noinline, unused)) \ check_##UINON_TYPE (UINON_TYPE u, const VALUE_TYPE *v) \ { \ int i; \ int err = 0; \ \ for (i = 0; i < ARRAY_SIZE (u.a); i++) \ if (u.a[i] != v[i]) \ { \ err++; \ PRINTF ("%i: " FMT " != " FMT "\n", \ i, v[i], u.a[i]); \ } \ return err; \ } #ifdef __SSE2__ CHECK_EXP (union128i_b, char, "%d") CHECK_EXP (union128i_ub, unsigned char, "%d") CHECK_EXP (union128i_w, short, "%d") CHECK_EXP (union128i_uw, unsigned short, "%d") CHECK_EXP (union128i_d, int, "0x%x") CHECK_EXP (union128i_q, long long, "0x%llx") CHECK_EXP (union128d, double, "%f") #endif CHECK_EXP (union128, float, "%f") #define ESP_FLOAT 0.000001 #define ESP_DOUBLE 0.000001 #define CHECK_ARRAY(ARRAY, TYPE, FMT) \ static int \ __attribute__((noinline, unused)) \ checkV##ARRAY (const TYPE *v, const TYPE *e, int n) \ { \ int i; \ int err = 0; \ \ for (i = 0; i < n; i++) \ if (v[i] != e[i]) \ { \ err++; \ PRINTF ("%i: " FMT " != " FMT "\n", \ i, v[i], e[i]); \ } \ return err; \ } CHECK_ARRAY(c, char, "0x%hhx") CHECK_ARRAY(s, short, "0x%hx") CHECK_ARRAY(i, int, "0x%x") CHECK_ARRAY(l, long long, "0x%llx") #define CHECK_FP_ARRAY(ARRAY, TYPE, ESP, FMT) \ static int \ __attribute__((noinline, unused)) \ checkV##ARRAY (const TYPE *v, const TYPE *e, int n) \ { \ int i; \ int err = 0; \ \ for (i = 0; i < n; i++) \ if (v[i] > (e[i] + (ESP)) || v[i] < (e[i] - (ESP))) \ if (e[i] != v[i]) \ { \ err++; \ PRINTF ("%i: " FMT " != " FMT "\n", \ i, v[i], e[i]); \ } \ return err; \ } CHECK_FP_ARRAY (d, double, ESP_DOUBLE, "%f") CHECK_FP_ARRAY (f, float, ESP_FLOAT, "%f") #ifdef NEED_IEEE754_FLOAT union ieee754_float { float d; struct { unsigned long frac : 23; unsigned exp : 8; unsigned sign : 1; } bits __attribute__((packed)); }; #endif #ifdef NEED_IEEE754_DOUBLE union ieee754_double { double d; struct { unsigned long frac1 : 32; unsigned long frac0 : 20; unsigned exp : 11; unsigned sign : 1; } bits __attribute__((packed)); }; #endif #define CHECK_FP_EXP(UINON_TYPE, VALUE_TYPE, ESP, FMT) \ static int \ __attribute__((noinline, unused)) \ check_fp_##UINON_TYPE (UINON_TYPE u, const VALUE_TYPE *v) \ { \ int i; \ int err = 0; \ \ for (i = 0; i < ARRAY_SIZE (u.a); i++) \ if (u.a[i] > (v[i] + (ESP)) || u.a[i] < (v[i] - (ESP))) \ { \ err++; \ PRINTF ("%i: " FMT " != " FMT "\n", \ i, v[i], u.a[i]); \ } \ return err; \ } CHECK_FP_EXP (union128, float, ESP_FLOAT, "%f") #ifdef __SSE2__ CHECK_FP_EXP (union128d, double, ESP_DOUBLE, "%f") #endif