• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/ucode/lib/math.c

  1 /*
  2  * Copyright (C) 2020-2021 Jo-Philipp Wich <jo@mein.io>
  3  *
  4  * Permission to use, copy, modify, and/or distribute this software for any
  5  * purpose with or without fee is hereby granted, provided that the above
  6  * copyright notice and this permission notice appear in all copies.
  7  *
  8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 15  */
 16 
 17 #include <math.h>
 18 #include <errno.h>
 19 #include <sys/time.h>
 20 
 21 #include "ucode/module.h"
 22 
 23 static bool srand_called = false;
 24 
 25 static uc_value_t *
 26 uc_abs(uc_vm_t *vm, size_t nargs)
 27 {
 28         uc_value_t *v = uc_fn_arg(0), *nv, *res;
 29         int64_t n;
 30         double d;
 31 
 32         nv = v ? ucv_to_number(v) : NULL;
 33 
 34         switch (ucv_type(nv)) {
 35         case UC_INTEGER:
 36                 n = ucv_int64_get(nv);
 37 
 38                 if (n >= 0 || errno == ERANGE)
 39                         res = ucv_get(nv);
 40                 else if (n == INT64_MIN)
 41                         res = ucv_uint64_new((uint64_t)INT64_MAX + 1);
 42                 else
 43                         res = ucv_uint64_new(-n);
 44 
 45                 break;
 46 
 47         case UC_DOUBLE:
 48                 d = ucv_double_get(nv);
 49 
 50                 if (isnan(d) || d >= 0)
 51                         res = ucv_get(nv);
 52                 else
 53                         res = ucv_double_new(-d);
 54 
 55                 break;
 56 
 57         default:
 58                 res = ucv_double_new(NAN);
 59                 break;
 60         }
 61 
 62         ucv_put(nv);
 63 
 64         return res;
 65 }
 66 
 67 static uc_value_t *
 68 uc_atan2(uc_vm_t *vm, size_t nargs)
 69 {
 70         double d1 = ucv_to_double(uc_fn_arg(0));
 71         double d2 = ucv_to_double(uc_fn_arg(1));
 72 
 73         if (isnan(d1) || isnan(d2))
 74                 return ucv_double_new(NAN);
 75 
 76         return ucv_double_new(atan2(d1, d2));
 77 }
 78 
 79 static uc_value_t *
 80 uc_cos(uc_vm_t *vm, size_t nargs)
 81 {
 82         double d = ucv_to_double(uc_fn_arg(0));
 83 
 84         if (isnan(d))
 85                 return ucv_double_new(NAN);
 86 
 87         return ucv_double_new(cos(d));
 88 }
 89 
 90 static uc_value_t *
 91 uc_exp(uc_vm_t *vm, size_t nargs)
 92 {
 93         double d = ucv_to_double(uc_fn_arg(0));
 94 
 95         if (isnan(d))
 96                 return ucv_double_new(NAN);
 97 
 98         return ucv_double_new(exp(d));
 99 }
100 
101 static uc_value_t *
102 uc_log(uc_vm_t *vm, size_t nargs)
103 {
104         double d = ucv_to_double(uc_fn_arg(0));
105 
106         if (isnan(d))
107                 return ucv_double_new(NAN);
108 
109         return ucv_double_new(log(d));
110 }
111 
112 static uc_value_t *
113 uc_sin(uc_vm_t *vm, size_t nargs)
114 {
115         double d = ucv_to_double(uc_fn_arg(0));
116 
117         if (isnan(d))
118                 return ucv_double_new(NAN);
119 
120         return ucv_double_new(sin(d));
121 }
122 
123 static uc_value_t *
124 uc_sqrt(uc_vm_t *vm, size_t nargs)
125 {
126         double d = ucv_to_double(uc_fn_arg(0));
127 
128         if (isnan(d))
129                 return ucv_double_new(NAN);
130 
131         return ucv_double_new(sqrt(d));
132 }
133 
134 static uc_value_t *
135 uc_pow(uc_vm_t *vm, size_t nargs)
136 {
137         double x = ucv_to_double(uc_fn_arg(0));
138         double y = ucv_to_double(uc_fn_arg(1));
139 
140         if (isnan(x) || isnan(y))
141                 return ucv_double_new(NAN);
142 
143         return ucv_double_new(pow(x, y));
144 }
145 
146 static uc_value_t *
147 uc_rand(uc_vm_t *vm, size_t nargs)
148 {
149         struct timeval tv;
150 
151         if (!srand_called) {
152                 gettimeofday(&tv, NULL);
153                 srand((tv.tv_sec * 1000) + (tv.tv_usec / 1000));
154 
155                 srand_called = true;
156         }
157 
158         return ucv_int64_new(rand());
159 }
160 
161 static uc_value_t *
162 uc_srand(uc_vm_t *vm, size_t nargs)
163 {
164         int64_t n = ucv_to_integer(uc_fn_arg(0));
165 
166         srand((unsigned int)n);
167         srand_called = true;
168 
169         return NULL;
170 }
171 
172 static const uc_function_list_t math_fns[] = {
173         { "abs",        uc_abs },
174         { "atan2",      uc_atan2 },
175         { "cos",        uc_cos },
176         { "exp",        uc_exp },
177         { "log",        uc_log },
178         { "sin",        uc_sin },
179         { "sqrt",       uc_sqrt },
180         { "pow",        uc_pow },
181         { "rand",       uc_rand },
182         { "srand",      uc_srand },
183 };
184 
185 void uc_module_init(uc_vm_t *vm, uc_value_t *scope)
186 {
187         uc_function_list_register(scope, math_fns);
188 }
189 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt