8extern int kputs(
char *s);
12static int rig_kputs(
char *s) {
13 if (strstr(s,
": FAIL")) rig_failed = 1;
17#define kputs rig_kputs
19#define NOINL __attribute__((noinline))
21static volatile uint32_t vtbl[] = {
22 0x00000000u, 0x80000000u, 0x3f800000u, 0xbf800000u, 0x3f000000u, 0x40000000u,
23 0x40400000u, 0x41200000u, 0x3dcccccdu, 0x3a83126fu, 0x1e3ce508u, 0x60ad78ecu,
24 0x7f7fc99eu, 0xff7fc99eu, 0x0082ab1eu, 0x47f12065u, 0x3f800001u, 0x4b800000u,
25 0x3eaaaaaau, 0xc0f00000u, 0x42c80000u, 0x501502f9u, 0x2edbe6ffu, 0x477fe000u,
26 0xbf400000u, 0x40200000u, 0x3fc00000u, 0x47c35000u};
27#define N ((int)(sizeof(vtbl) / sizeof(vtbl[0])))
32static inline void mix(uint32_t v) { h = (h ^ v) * 16777619u; }
33static inline uint32_t bits(
float f) { uint32_t u; memcpy(&u, &f, 4);
return u; }
35static void hex8(uint32_t v,
char *o) {
36 for (
int i = 7; i >= 0; i--) { o[i] =
"0123456789abcdef"[v & 15]; v >>= 4; }
39static void report(
const char *name) {
42 while (name[n] && n < 40) { line[n] = name[n]; n++; }
50#define START() (h = 2166136261u)
52#define BIN(NAME, EXPR) \
53 NOINL static float NAME(float a, float b) { return EXPR; }
58BIN(k_max, __builtin_fmaxf(a, b))
59BIN(k_min, __builtin_fminf(a, b))
60BIN(k_tmax, a > b ? a : b)
61BIN(k_tmin, a < b ? a : b)
62BIN(k_adivsqrt, a / __builtin_sqrtf(b))
63BIN(k_lerp3, a + (b - a) * 0.25f)
64BIN(k_chain, (a * b + a) * b - a / (b + 1.5f))
65BIN(k_fma, a * b + 3.0f)
66BIN(k_msub, 3.0f - a * b)
68#define UN(NAME, EXPR) \
69 NOINL static float NAME(float a) { return EXPR; }
70UN(k_sqrt, __builtin_sqrtf(a))
71UN(k_rsqrt, 1.0f / __builtin_sqrtf(a))
73UN(k_abs, __builtin_fabsf(a))
74UN(k_clamp, a < 0.f ? 0.f : (a > 1.f ? 1.f : a))
77UN(k_half, a * 0.5f + 0x1.921f9ep+1f)
80#define CMP(NAME, EXPR) \
81 NOINL static int NAME(float a, float b) { return EXPR; }
92NOINL
static float s_lt(
float a,
float b,
float x,
float y) {
return a < b ? x : y; }
93NOINL
static float s_le(
float a,
float b,
float x,
float y) {
return a <= b ? x : y; }
94NOINL
static float s_gt(
float a,
float b,
float x,
float y) {
return a > b ? x : y; }
95NOINL
static float s_ge(
float a,
float b,
float x,
float y) {
return a >= b ? x : y; }
96NOINL
static float s_eq(
float a,
float b,
float x,
float y) {
return a == b ? x : y; }
97NOINL
static float s_ne(
float a,
float b,
float x,
float y) {
return a != b ? x : y; }
98CMP(br_lt, a < b ? 1 : 2)
99CMP(br_ge, a >= b ? 1 : 2)
100CMP(br_ule, !(a > b) ? 1 : 2)
101CMP(br_ugt, !(a <= b) ? 1 : 2)
102CMP(br_ne, a != b ? 1 : 2)
103CMP(br_eq, a == b ? 1 : 2)
105NOINL
static int f2i(
float a) {
return (
int)a; }
106NOINL
static float i2f(
int a) {
return (
float)a; }
107NOINL
static int f2i_sat(
float a) {
return a > 2e9f ? 2000000000 : (a < -2e9f ? -2000000000 : (int)a); }
109NOINL
static float dot4(
const float *a,
const float *b) {
110 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
112NOINL
static void axpy(
float *y,
const float *x,
float a,
int n) {
113 for (
int i = 0; i < n; i++) y[i] += a * x[i];
115NOINL
static void mat4vec(
float *o,
const float *m,
const float *v) {
116 for (
int r = 0; r < 4; r++)
117 o[r] = m[r] * v[0] + m[4 + r] * v[1] + m[8 + r] * v[2] + m[12 + r] * v[3];
119NOINL
static float sumf(
const float *a,
int n) {
121 for (
int i = 0; i < n; i++) s += a[i];
124NOINL
static float lensq(
const float *a,
int n) {
126 for (
int i = 0; i < n; i++) s += a[i] * a[i];
129NOINL
static float norm3(
const float *v) {
130 float l = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
131 return l / __builtin_sqrtf(l);
135NOINL
static uint32_t crc32_(
const uint8_t *p,
int n) {
136 uint32_t c = 0xffffffffu;
137 for (
int i = 0; i < n; i++) {
139 for (
int k = 0; k < 8; k++) c = (c >> 1) ^ (0xedb88320u & (0u - (c & 1)));
143NOINL
static int32_t imul(int32_t a, int32_t b) {
return a * b; }
144NOINL
static int64_t imul64(int64_t a, int64_t b) {
return a * b; }
145NOINL
static int32_t idiv(int32_t a, int32_t b) {
return b ? a / b : 0; }
146NOINL
static int32_t imod(int32_t a, int32_t b) {
return b ? a % b : 0; }
147NOINL
static uint32_t udiv(uint32_t a, uint32_t b) {
return b ? a / b : 0; }
148NOINL
static uint32_t umod(uint32_t a, uint32_t b) {
return b ? a % b : 0; }
149NOINL
static int64_t idiv64(int64_t a, int64_t b) {
return b ? a / b : 0; }
150NOINL
static uint64_t umul64(uint32_t a, uint32_t b) {
return (uint64_t)a * b; }
151NOINL
static void bsort(
int *a,
int n) {
152 for (
int i = 0; i < n; i++)
153 for (
int j = 0; j + 1 < n - i; j++)
154 if (a[j] > a[j + 1]) {
int x = a[j]; a[j] = a[j + 1]; a[j + 1] = x; }
156NOINL
static int fib(
int n) {
return n < 2 ? n : fib(n - 1) + fib(n - 2); }
157NOINL
static int sw(
int x) {
159 case 0:
return x * 3;
160 case 1:
return x + 100;
161 case 2:
return x ^ 0x5a5a;
162 case 3:
return x << 3;
164 case 5:
return x * x;
165 case 6:
return x >> 1;
169struct S { int8_t a; int16_t b; int32_t c; int64_t d;
float f; uint8_t g; };
170NOINL
static int64_t structs(
struct S *s,
int n) {
172 for (
int i = 0; i < n; i++) {
173 acc += s[i].a + s[i].b + s[i].c + s[i].d + (int)s[i].f + s[i].g;
174 s[i].c = (int32_t)acc;
178NOINL
static void copyl(
long long *d,
const long long *s,
int n) {
for (
int i = 0; i < n; i++) d[i] = s[i]; }
179NOINL
static int isum(
const int *a,
int n) {
int s = 0;
for (
int i = 0; i < n; i++) s += a[i];
return s; }
181static uint32_t rng = 12345;
182static uint32_t next(
void) { rng = rng * 1664525u + 1013904223u;
return rng; }
184#define RUN_BIN(K) do { START(); for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) mix(bits(K(t[i], t[j]))); report(#K); } while (0)
185#define RUN_UN(K) do { START(); for (int i = 0; i < N; i++) mix(bits(K(t[i]))); report(#K); } while (0)
186#define RUN_CMP(K) do { START(); for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) mix((uint32_t)K(t[i], t[j])); report(#K); } while (0)
187#define RUN_SEL(K) do { START(); for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) mix(bits(K(t[i], t[j], t[i], t[j]))); report(#K); } while (0)
189static int test_main(
void) {
190 for (
int i = 0; i < N; i++) { uint32_t u = vtbl[i]; memcpy(&t[i], &u, 4); }
191 for (
int i = 0; i < N; i++) {
192 char nm[8] = {
't', (char)(
'a' + i / 10), (char)(
'0' + i % 10), 0};
193 START(); mix(bits(t[i])); report(nm);
196 RUN_BIN(k_add); RUN_BIN(k_sub); RUN_BIN(k_mul); RUN_BIN(k_div);
197 RUN_BIN(k_max); RUN_BIN(k_min); RUN_BIN(k_tmax); RUN_BIN(k_tmin);
198 RUN_BIN(k_adivsqrt); RUN_BIN(k_lerp3); RUN_BIN(k_chain); RUN_BIN(k_fma); RUN_BIN(k_msub);
199 RUN_UN(k_sqrt); RUN_UN(k_rsqrt); RUN_UN(k_neg); RUN_UN(k_abs); RUN_UN(k_clamp);
200 RUN_UN(k_sq); RUN_UN(k_cube); RUN_UN(k_half); RUN_UN(k_recip);
201 RUN_CMP(c_lt); RUN_CMP(c_le); RUN_CMP(c_gt); RUN_CMP(c_ge); RUN_CMP(c_eq); RUN_CMP(c_ne);
202 RUN_CMP(c_nlt); RUN_CMP(c_nle); RUN_CMP(c_ngt); RUN_CMP(c_nge);
203 RUN_SEL(s_lt); RUN_SEL(s_le); RUN_SEL(s_gt); RUN_SEL(s_ge); RUN_SEL(s_eq); RUN_SEL(s_ne);
204 RUN_CMP(br_lt); RUN_CMP(br_ge); RUN_CMP(br_ule); RUN_CMP(br_ugt); RUN_CMP(br_ne); RUN_CMP(br_eq);
206 START();
for (
int i = 0; i < N; i++) mix((uint32_t)f2i_sat(t[i])); report(
"f2i_sat");
207 START();
for (
int i = 0; i < N; i++)
if (t[i] < 1e9f && t[i] > -1e9f) mix((uint32_t)f2i(t[i])); report(
"f2i");
208 START();
for (
int i = -200; i < 200; i++) mix(bits(i2f(i * 99991))); report(
"i2f");
211 for (
int i = 0; i + 4 <= N; i++)
for (
int j = 0; j + 4 <= N; j++) mix(bits(dot4(t + i, t + j)));
214 for (
int i = 0; i + 16 <= N; i++) {
216 mat4vec(o, t + i, t + (i % 8));
217 for (
int r = 0; r < 4; r++) mix(bits(o[r]));
223 for (
int a = 0; a < N; a++) {
224 for (
int i = 0; i < 16; i++) y[i] = t[(i + a) % N];
225 axpy(y, t, t[a], 16);
226 for (
int i = 0; i < 16; i++) mix(bits(y[i]));
230 START();
for (
int n = 0; n <= 16; n++)
for (
int i = 0; i + n <= N; i++) mix(bits(sumf(t + i, n))); report(
"sumf");
231 START();
for (
int n = 0; n <= 16; n++)
for (
int i = 0; i + n <= N; i++) mix(bits(lensq(t + i, n))); report(
"lensq");
232 START();
for (
int i = 0; i + 3 <= N; i++) mix(bits(norm3(t + i))); report(
"norm3");
236 for (
int i = 0; i < 256; i++) buf[i] = (uint8_t)next();
237 START();
for (
int n = 0; n < 256; n += 7) mix(crc32_(buf, n)); report(
"crc32");
239 START();
for (
int i = 0; i < 300; i++) { int32_t a = (int32_t)next(), b = (int32_t)next(); mix((uint32_t)imul(a, b)); } report(
"imul");
241 for (
int i = 0; i < 300; i++) {
242 int64_t a = ((int64_t)next() << 32) | next(), b = ((int64_t)next() << 16) | next();
243 int64_t r = imul64(a, b);
244 mix((uint32_t)r); mix((uint32_t)(r >> 32));
247 START();
for (
int i = 0; i < 300; i++) { int32_t a = (int32_t)next(), b = (int32_t)(next() >> (i & 31)); mix((uint32_t)idiv(a, b)); mix((uint32_t)imod(a, b)); } report(
"idivmod");
248 START();
for (
int i = 0; i < 300; i++) { uint32_t a = next(), b = next() >> (i & 31); mix(udiv(a, b)); mix(umod(a, b)); } report(
"udivmod");
250 for (
int i = 0; i < 100; i++) {
251 int64_t a = ((int64_t)next() << 32) | next();
252 int64_t b = (int64_t)(int32_t)next() >> (i & 15);
253 int64_t r = idiv64(a, b);
254 mix((uint32_t)r); mix((uint32_t)(r >> 32));
257 START();
for (
int i = 0; i < 100; i++) { uint64_t r = umul64(next(), next()); mix((uint32_t)r); mix((uint32_t)(r >> 32)); } report(
"umul64");
260 for (
int i = 0; i < 64; i++) a[i] = (
int)(next() >> 8);
262 START();
for (
int i = 0; i < 64; i++) mix((uint32_t)a[i]); report(
"bsort");
264 START(); mix((uint32_t)fib(20)); report(
"fib");
265 START();
for (
int i = 0; i < 400; i++) mix((uint32_t)sw(i * 7 + 3)); report(
"switch");
268 for (
int i = 0; i < 16; i++) {
269 s[i].a = (int8_t)next(); s[i].b = (int16_t)next(); s[i].c = (int32_t)next();
270 s[i].d = ((int64_t)next() << 32) | next(); s[i].f = (float)(int16_t)next(); s[i].g = (uint8_t)next();
273 int64_t r = structs(s, 16);
274 mix((uint32_t)r); mix((uint32_t)(r >> 32));
275 for (
int i = 0; i < 16; i++) mix((uint32_t)s[i].c);
279 long long a[32], b[32];
280 for (
int i = 0; i < 32; i++) a[i] = ((
long long)next() << 32) | next();
283 for (
int i = 0; i < 32; i++) { mix((uint32_t)b[i]); mix((uint32_t)(b[i] >> 32)); }
288 for (
int i = 0; i < 64; i++) a[i] = (
int)next();
289 START();
for (
int n = 0; n <= 64; n++) mix((uint32_t)isum(a, n)); report(
"isum");
292 kputs(
"fpdiff: PASS\n");
297 int result = test_main();
298 printf(
"[ps2rig] exit=%d\n", (result || rig_failed) ? 1 : 0);