diff options
author | Jo-Philipp Wich <jo@mein.io> | 2020-09-11 22:04:08 +0200 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2020-09-11 22:23:34 +0200 |
commit | c06bab1cf39d378e4d99ffe89e8079ab817c51c0 (patch) | |
tree | 84fb8acb7f792e3fb88abae6cba1cdaa4ff78e9c | |
parent | f6978fcc04f84a461df627f450e398ec5ad163d8 (diff) |
lib: move math functions to new module
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
-rw-r--r-- | CMakeLists.txt | 16 | ||||
-rw-r--r-- | lib.c | 124 | ||||
-rw-r--r-- | lib/math.c | 185 |
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) @@ -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); +} |