aboutsummaryrefslogtreecommitdiff
path: root/cbits/arith.c
blob: 02c8ce13f8b440e0a96649758b39ca33505f6bad (plain)
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