summaryrefslogtreecommitdiffhomepage
path: root/lib
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2020-09-11 22:04:08 +0200
committerJo-Philipp Wich <jo@mein.io>2020-09-11 22:23:34 +0200
commitc06bab1cf39d378e4d99ffe89e8079ab817c51c0 (patch)
tree84fb8acb7f792e3fb88abae6cba1cdaa4ff78e9c /lib
parentf6978fcc04f84a461df627f450e398ec5ad163d8 (diff)
lib: move math functions to new module
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'lib')
-rw-r--r--lib/math.c185
1 files changed, 185 insertions, 0 deletions
diff --git a/lib/math.c b/lib/math.c
new file mode 100644
index 0000000..37bd33f
--- /dev/null
+++ b/lib/math.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2020 Jo-Philipp Wich <jo@mein.io>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "../module.h"
+
+#include <math.h>
+#include <sys/time.h>
+
+static const struct ut_ops *ops;
+
+static double
+to_double(struct json_object *v)
+{
+ int64_t n;
+ double d;
+
+ return (ops->cast_number(v, &n, &d) == json_type_double) ? d : (double)n;
+}
+
+static int64_t
+to_int64(struct json_object *v)
+{
+ int64_t n;
+ double d;
+
+ return (ops->cast_number(v, &n, &d) == json_type_double) ? (int64_t)d : n;
+}
+
+static struct json_object *
+ut_abs(struct ut_state *s, uint32_t off, struct json_object *args)
+{
+ struct json_object *v = json_object_array_get_idx(args, 0);
+ enum json_type t;
+ int64_t n;
+ double d;
+
+ if (json_object_is_type(v, json_type_null))
+ return ops->new_double(NAN);
+
+ t = ops->cast_number(v, &n, &d);
+
+ if (t == json_type_double)
+ return (isnan(d) || d < 0) ? ops->new_double(-d) : json_object_get(v);
+
+ return (n < 0) ? json_object_new_int64(-n) : json_object_get(v);
+}
+
+static struct json_object *
+ut_atan2(struct ut_state *s, uint32_t off, struct json_object *args)
+{
+ double d1 = to_double(json_object_array_get_idx(args, 0));
+ double d2 = to_double(json_object_array_get_idx(args, 1));
+
+ if (isnan(d1) || isnan(d2))
+ return ops->new_double(NAN);
+
+ return ops->new_double(atan2(d1, d2));
+}
+
+static struct json_object *
+ut_cos(struct ut_state *s, uint32_t off, struct json_object *args)
+{
+ double d = to_double(json_object_array_get_idx(args, 0));
+
+ if (isnan(d))
+ return ops->new_double(NAN);
+
+ return ops->new_double(cos(d));
+}
+
+static struct json_object *
+ut_exp(struct ut_state *s, uint32_t off, struct json_object *args)
+{
+ double d = to_double(json_object_array_get_idx(args, 0));
+
+ if (isnan(d))
+ return ops->new_double(NAN);
+
+ return ops->new_double(exp(d));
+}
+
+static struct json_object *
+ut_log(struct ut_state *s, uint32_t off, struct json_object *args)
+{
+ double d = to_double(json_object_array_get_idx(args, 0));
+
+ if (isnan(d))
+ return ops->new_double(NAN);
+
+ return ops->new_double(log(d));
+}
+
+static struct json_object *
+ut_sin(struct ut_state *s, uint32_t off, struct json_object *args)
+{
+ double d = to_double(json_object_array_get_idx(args, 0));
+
+ if (isnan(d))
+ return ops->new_double(NAN);
+
+ return ops->new_double(sin(d));
+}
+
+static struct json_object *
+ut_sqrt(struct ut_state *s, uint32_t off, struct json_object *args)
+{
+ double d = to_double(json_object_array_get_idx(args, 0));
+
+ if (isnan(d))
+ return ops->new_double(NAN);
+
+ return ops->new_double(sqrt(d));
+}
+
+static struct json_object *
+ut_pow(struct ut_state *s, uint32_t off, struct json_object *args)
+{
+ double x = to_double(json_object_array_get_idx(args, 0));
+ double y = to_double(json_object_array_get_idx(args, 1));
+
+ if (isnan(x) || isnan(y))
+ return ops->new_double(NAN);
+
+ return ops->new_double(pow(x, y));
+}
+
+static struct json_object *
+ut_rand(struct ut_state *s, uint32_t off, struct json_object *args)
+{
+ struct timeval tv;
+
+ if (!s->srand_called) {
+ gettimeofday(&tv, NULL);
+ srand((tv.tv_sec * 1000) + (tv.tv_usec / 1000));
+
+ s->srand_called = true;
+ }
+
+ return json_object_new_int64(rand());
+}
+
+static struct json_object *
+ut_srand(struct ut_state *s, uint32_t off, struct json_object *args)
+{
+
+ int64_t n = to_int64(json_object_array_get_idx(args, 0));
+
+ srand((unsigned int)n);
+ s->srand_called = true;
+
+ return NULL;
+}
+
+static const struct { const char *name; ut_c_fn *func; } global_fns[] = {
+ { "abs", ut_abs },
+ { "atan2", ut_atan2 },
+ { "cos", ut_cos },
+ { "exp", ut_exp },
+ { "log", ut_log },
+ { "sin", ut_sin },
+ { "sqrt", ut_sqrt },
+ { "pow", ut_pow },
+ { "rand", ut_rand },
+ { "srand", ut_srand },
+};
+
+void ut_module_init(const struct ut_ops *ut, struct ut_state *s, struct json_object *scope)
+{
+ ops = ut;
+
+ register_functions(ops, global_fns, scope);
+}