1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
#include <stdint.h>
#include <stdlib.h>
#include <math.h>
typedef int32_t i32;
typedef int64_t i64;
#define COMM_OP(name, op, typ) \
void oxarop_ ## name ## _ ## typ ## _sv(i64 n, typ *out, typ x, typ *y) { \
for (i64 i = 0; i < n; i++) out[i] = x op y[i]; \
} \
void oxarop_ ## name ## _ ## typ ## _vv(i64 n, typ *out, const typ *x, const typ *y) { \
for (i64 i = 0; i < n; i++) out[i] = x[i] op y[i]; \
}
#define NONCOMM_OP(name, op, typ) \
COMM_OP(name, op, typ) \
void oxarop_ ## name ## _ ## typ ## _vs(i64 n, typ *out, typ *x, typ y) { \
for (i64 i = 0; i < n; i++) out[i] = x[i] op y; \
}
#define UNARY_OP(name, op, typ) \
void oxarop_ ## name ## _ ## typ(i64 n, typ *out, typ *x) { \
for (i64 i = 0; i < n; i++) out[i] = op(x[i]); \
}
#define GEN_ABS(x) \
_Generic((x), \
int: abs, \
long: labs, \
long long: llabs, \
float: fabsf, \
double: fabs)(x)
// This does not result in multiple loads with GCC 13.
#define GEN_SIGNUM(x) ((x) < 0 ? -1 : (x) > 0 ? 1 : 0)
#define NUM_TYPES_LOOP_XLIST \
X(i32) X(i64) X(double) X(float)
#define X(typ) \
COMM_OP(add, +, typ) \
NONCOMM_OP(sub, -, typ) \
COMM_OP(mul, *, typ) \
UNARY_OP(neg, -, typ) \
UNARY_OP(abs, GEN_ABS, typ) \
UNARY_OP(signum, GEN_SIGNUM, typ)
NUM_TYPES_LOOP_XLIST
#undef X
|