summaryrefslogtreecommitdiffhomepage
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
parentf6978fcc04f84a461df627f450e398ec5ad163d8 (diff)
lib: move math functions to new module
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
-rw-r--r--CMakeLists.txt16
-rw-r--r--lib.c124
-rw-r--r--lib/math.c185
3 files changed, 197 insertions, 128 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c792be4..8e4033d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,6 +6,7 @@ PROJECT(utpl C)
ADD_DEFINITIONS(-Os -Wall -Werror --std=gnu99 -Wmissing-declarations -Wno-error=unused-variable -ffunction-sections -D_GNU_SOURCE)
OPTION(FS_SUPPORT "Filesystem plugin support" ON)
+OPTION(MATH_SUPPORT "Math plugin support" ON)
OPTION(UBUS_SUPPORT "Ubus plugin support" ON)
OPTION(UCI_SUPPORT "UCI plugin support" ON)
@@ -50,11 +51,6 @@ SET_SOURCE_FILES_PROPERTIES("parser.c" PROPERTIES GENERATED TRUE COMPILE_FLAGS -
ADD_EXECUTABLE(utpl main.c ast.c lexer.c parser.c eval.c lib.c)
TARGET_LINK_LIBRARIES(utpl ${json})
-CHECK_FUNCTION_EXISTS(ceil CEIL_FUNCTION_EXISTS)
-IF (NOT CEIL_FUNCTION_EXISTS)
- TARGET_LINK_LIBRARIES(utpl m)
-ENDIF()
-
CHECK_FUNCTION_EXISTS(dlopen DLOPEN_FUNCTION_EXISTS)
IF (NOT DLOPEN_FUNCTION_EXISTS)
TARGET_LINK_LIBRARIES(utpl dl)
@@ -80,6 +76,16 @@ IF(FS_SUPPORT)
SET_TARGET_PROPERTIES(fs_lib PROPERTIES OUTPUT_NAME lib/fs PREFIX "")
ENDIF()
+IF(MATH_SUPPORT)
+ SET(LIBRARIES ${LIBRARIES} math_lib)
+ ADD_LIBRARY(math_lib MODULE lib/math.c)
+ SET_TARGET_PROPERTIES(math_lib PROPERTIES OUTPUT_NAME lib/math PREFIX "")
+ CHECK_FUNCTION_EXISTS(ceil CEIL_FUNCTION_EXISTS)
+ IF (NOT CEIL_FUNCTION_EXISTS)
+ TARGET_LINK_LIBRARIES(math_lib m)
+ ENDIF()
+ENDIF()
+
IF(UBUS_SUPPORT)
SET(LIBRARIES ${LIBRARIES} ubus_lib)
ADD_LIBRARY(ubus_lib MODULE lib/ubus.c)
diff --git a/lib.c b/lib.c
index c2764f3..ca59f04 100644
--- a/lib.c
+++ b/lib.c
@@ -31,7 +31,6 @@
#include <time.h>
#include <dlfcn.h>
#include <sys/stat.h>
-#include <sys/time.h>
#include <sys/types.h>
@@ -252,7 +251,7 @@ ut_cast_int64(struct json_object *v)
errno = EINVAL;
else if (!isfinite(d))
errno = EOVERFLOW;
- else if (ceil(d) != d)
+ else if ((double)(int64_t)d != d)
errno = ERANGE;
return (int64_t)d;
@@ -496,37 +495,6 @@ ut_unshift(struct ut_state *s, uint32_t off, struct json_object *args)
}
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 ut_new_double(NAN);
-
- t = ut_cast_number(v, &n, &d);
-
- if (t == json_type_double)
- return (isnan(d) || d < 0) ? ut_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 = ut_cast_double(json_object_array_get_idx(args, 0));
- double d2 = ut_cast_double(json_object_array_get_idx(args, 1));
-
- if (isnan(d1) || isnan(d2))
- return ut_new_double(NAN);
-
- return ut_new_double(atan2(d1, d2));
-}
-
-static struct json_object *
ut_chr(struct ut_state *s, uint32_t off, struct json_object *args)
{
size_t len = json_object_array_length(args);
@@ -557,17 +525,6 @@ ut_chr(struct ut_state *s, uint32_t off, struct json_object *args)
}
static struct json_object *
-ut_cos(struct ut_state *s, uint32_t off, struct json_object *args)
-{
- double d = ut_cast_double(json_object_array_get_idx(args, 0));
-
- if (isnan(d))
- return ut_new_double(NAN);
-
- return ut_new_double(cos(d));
-}
-
-static struct json_object *
ut_delete(struct ut_state *s, uint32_t off, struct json_object *args)
{
struct json_object *obj = json_object_array_get_idx(args, 0);
@@ -619,17 +576,6 @@ ut_exit(struct ut_state *s, uint32_t off, struct json_object *args)
}
static struct json_object *
-ut_exp(struct ut_state *s, uint32_t off, struct json_object *args)
-{
- double d = ut_cast_double(json_object_array_get_idx(args, 0));
-
- if (isnan(d))
- return ut_new_double(NAN);
-
- return ut_new_double(exp(d));
-}
-
-static struct json_object *
ut_getenv(struct ut_state *s, uint32_t off, struct json_object *args)
{
const char *key = json_object_get_string(json_object_array_get_idx(args, 0));
@@ -815,17 +761,6 @@ ut_lc(struct ut_state *s, uint32_t off, struct json_object *args)
}
static struct json_object *
-ut_log(struct ut_state *s, uint32_t off, struct json_object *args)
-{
- double d = ut_cast_double(json_object_array_get_idx(args, 0));
-
- if (isnan(d))
- return ut_new_double(NAN);
-
- return ut_new_double(log(d));
-}
-
-static struct json_object *
ut_map(struct ut_state *s, uint32_t off, struct json_object *args)
{
struct json_object *obj = json_object_array_get_idx(args, 0);
@@ -878,32 +813,6 @@ ut_ord(struct ut_state *s, uint32_t off, struct json_object *args)
}
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 = ut_cast_int64(json_object_array_get_idx(args, 0));
-
- srand((unsigned int)n);
- s->srand_called = true;
-
- return NULL;
-}
-
-static struct json_object *
ut_type(struct ut_state *s, uint32_t off, struct json_object *args)
{
struct json_object *v = json_object_array_get_idx(args, 0);
@@ -979,17 +888,6 @@ ut_reverse(struct ut_state *s, uint32_t off, struct json_object *args)
return rv;
}
-static struct json_object *
-ut_sin(struct ut_state *s, uint32_t off, struct json_object *args)
-{
- double d = ut_cast_double(json_object_array_get_idx(args, 0));
-
- if (isnan(d))
- return ut_new_double(NAN);
-
- return ut_new_double(sin(d));
-}
-
static struct {
struct ut_state *s;
@@ -1155,17 +1053,6 @@ ut_split(struct ut_state *s, uint32_t off, struct json_object *args)
}
static struct json_object *
-ut_sqrt(struct ut_state *s, uint32_t off, struct json_object *args)
-{
- double d = ut_cast_double(json_object_array_get_idx(args, 0));
-
- if (isnan(d))
- return ut_new_double(NAN);
-
- return ut_new_double(sqrt(d));
-}
-
-static struct json_object *
ut_substr(struct ut_state *s, uint32_t off, struct json_object *args)
{
struct json_object *str = json_object_array_get_idx(args, 0);
@@ -1767,15 +1654,11 @@ const struct ut_ops ut = {
};
static const struct { const char *name; ut_c_fn *func; } functions[] = {
- { "abs", ut_abs },
- { "atan2", ut_atan2 },
{ "chr", ut_chr },
- { "cos", ut_cos },
{ "delete", ut_delete },
{ "die", ut_die },
{ "exists", ut_exists },
{ "exit", ut_exit },
- { "exp", ut_exp },
{ "filter", ut_filter },
{ "getenv", ut_getenv },
{ "hex", ut_hex },
@@ -1785,24 +1668,19 @@ static const struct { const char *name; ut_c_fn *func; } functions[] = {
{ "keys", ut_keys },
{ "lc", ut_lc },
{ "length", ut_length },
- { "log", ut_log },
{ "ltrim", ut_ltrim },
{ "map", ut_map },
{ "ord", ut_ord },
{ "pop", ut_pop },
{ "print", ut_print },
{ "push", ut_push },
- { "rand", ut_rand },
{ "reverse", ut_reverse },
{ "rindex", ut_rindex },
{ "rtrim", ut_rtrim },
{ "shift", ut_shift },
- { "sin", ut_sin },
{ "sort", ut_sort },
{ "splice", ut_splice },
{ "split", ut_split },
- { "sqrt", ut_sqrt },
- { "srand", ut_srand },
{ "substr", ut_substr },
{ "time", ut_time },
{ "trim", ut_trim },
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);
+}