summaryrefslogtreecommitdiffhomepage
path: root/lib/math.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/math.c')
-rw-r--r--lib/math.c40
1 files changed, 32 insertions, 8 deletions
diff --git a/lib/math.c b/lib/math.c
index c4a08e3..f16d309 100644
--- a/lib/math.c
+++ b/lib/math.c
@@ -15,6 +15,7 @@
*/
#include <math.h>
+#include <errno.h>
#include <sys/time.h>
#include "ucode/module.h"
@@ -24,20 +25,43 @@ static bool srand_called = false;
static uc_value_t *
uc_abs(uc_vm_t *vm, size_t nargs)
{
- uc_value_t *v = uc_fn_arg(0);
- uc_type_t t;
+ uc_value_t *v = uc_fn_arg(0), *nv, *res;
int64_t n;
double d;
- if (ucv_type(v) == UC_NULL)
- return ucv_double_new(NAN);
+ nv = v ? ucv_to_number(v) : NULL;
+
+ switch (ucv_type(nv)) {
+ case UC_INTEGER:
+ n = ucv_int64_get(nv);
+
+ if (n >= 0 || errno == ERANGE)
+ res = ucv_get(nv);
+ else if (n == INT64_MIN)
+ res = ucv_uint64_new((uint64_t)INT64_MAX + 1);
+ else
+ res = ucv_uint64_new(-n);
+
+ break;
- t = ucv_cast_number(v, &n, &d);
+ case UC_DOUBLE:
+ d = ucv_double_get(nv);
+
+ if (isnan(d) || d >= 0)
+ res = ucv_get(nv);
+ else
+ res = ucv_double_new(-d);
+
+ break;
+
+ default:
+ res = ucv_double_new(NAN);
+ break;
+ }
- if (t == UC_DOUBLE)
- return (isnan(d) || d < 0) ? ucv_double_new(-d) : ucv_get(v);
+ ucv_put(nv);
- return (n < 0) ? ucv_int64_new(-n) : ucv_get(v);
+ return res;
}
static uc_value_t *