aboutsummaryrefslogtreecommitdiff
path: root/cbits/arith.c
diff options
context:
space:
mode:
authorTom Smeding <tom@tomsmeding.com>2024-05-23 00:18:17 +0200
committerTom Smeding <tom@tomsmeding.com>2024-05-23 00:18:17 +0200
commita0010622885dcb55a916bf3514c0e9040f6871e9 (patch)
tree9e10c18eaf5c873d50e1f88a3bf114179c151769 /cbits/arith.c
parent4b74d1b1f7c46a4b3907838bee11f669060d3a23 (diff)
Fast numeric operations for Num
Diffstat (limited to 'cbits/arith.c')
-rw-r--r--cbits/arith.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/cbits/arith.c b/cbits/arith.c
new file mode 100644
index 0000000..02c8ce1
--- /dev/null
+++ b/cbits/arith.c
@@ -0,0 +1,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