| #include <stdio.h> |
| #include <xmmintrin.h> |
| |
| #ifndef ARRAY_SIZE |
| #define ARRAY_SIZE(A) (sizeof (A) / sizeof ((A)[0])) |
| #endif |
| |
| #ifdef __SSE2__ |
| #include <emmintrin.h> |
| |
| 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; |
| unsigned int a[4]; |
| } union128i_ud; |
| |
| typedef union |
| { |
| __m128i x; |
| long long a[2]; |
| } union128i_q; |
| |
| typedef union |
| { |
| __m128i x; |
| unsigned long long a[2]; |
| } union128i_uq; |
| |
| |
| typedef union |
| { |
| __m128d x; |
| double a[2]; |
| } union128d; |
| #endif |
| |
| typedef union |
| { |
| __m128 x; |
| float a[4]; |
| } union128; |
| |
| #ifdef DEBUG |
| #define PRINTF printf |
| #else |
| #define PRINTF(...) |
| #endif |
| |
| #define CHECK_EXP(UNION_TYPE, VALUE_TYPE, FMT) \ |
| static int \ |
| __attribute__((noinline, unused)) \ |
| check_##UNION_TYPE (UNION_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_ud, unsigned int, "0x%x") |
| CHECK_EXP (union128i_q, long long, "0x%llx") |
| CHECK_EXP (union128i_uq, unsigned long long, "0x%llx") |
| CHECK_EXP (union128d, double, "%f") |
| #endif |
| |
| CHECK_EXP (union128, float, "%f") |
| |
| #ifndef ESP_FLOAT |
| #define ESP_FLOAT 0.000001 |
| #endif |
| #ifndef ESP_DOUBLE |
| #define ESP_DOUBLE 0.000001 |
| #endif |
| #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") |
| CHECK_ARRAY(uc, unsigned char, "0x%hhx") |
| CHECK_ARRAY(us, unsigned short, "0x%hx") |
| CHECK_ARRAY(ui, unsigned int, "0x%x") |
| CHECK_ARRAY(ul, unsigned 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(UNION_TYPE, VALUE_TYPE, ESP, FMT) \ |
| static int \ |
| __attribute__((noinline, unused)) \ |
| check_fp_##UNION_TYPE (UNION_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 |