rearrange fields and export the read-only variable `sum`
[liba.git] / quickjs / src / pid_fuzzy.c
blob364ac7cb008a36230f5b600c975944c1a35e24a4
1 #include "a.h"
2 #include "a/pid_fuzzy.h"
4 static JSClassID liba_pid_fuzzy_class_id;
6 static void liba_pid_fuzzy_finalizer(JSRuntime *rt, JSValue val)
8 a_pid_fuzzy *self = (a_pid_fuzzy *)JS_GetOpaque(val, liba_pid_fuzzy_class_id);
9 union
11 a_float const *p;
12 a_float *o;
13 } u;
14 js_free_rt(rt, ((void)(u.p = self->me), u.o));
15 js_free_rt(rt, ((void)(u.p = self->mec), u.o));
16 js_free_rt(rt, ((void)(u.p = self->mkp), u.o));
17 js_free_rt(rt, ((void)(u.p = self->mki), u.o));
18 js_free_rt(rt, ((void)(u.p = self->mkd), u.o));
19 js_free_rt(rt, a_pid_fuzzy_block(self));
20 js_free_rt(rt, self);
23 static JSClassDef liba_pid_fuzzy_class = {"pid_fuzzy", .finalizer = liba_pid_fuzzy_finalizer};
25 static JSValue liba_pid_fuzzy_ctor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv)
27 (void)argc;
28 (void)argv;
29 JSValue proto, clazz = JS_UNDEFINED;
30 a_pid_fuzzy *const self = (a_pid_fuzzy *)js_mallocz(ctx, sizeof(a_pid_fuzzy));
31 if (!self) { return JS_EXCEPTION; }
32 self->pid.summax = +A_FLOAT_INF;
33 self->pid.summin = -A_FLOAT_INF;
34 self->pid.outmax = +A_FLOAT_INF;
35 self->pid.outmin = -A_FLOAT_INF;
36 self->kp = self->pid.kp = 1;
37 self->op = a_fuzzy_equ;
38 a_pid_fuzzy_init(self);
39 proto = JS_GetPropertyStr(ctx, new_target, "prototype");
40 if (JS_IsException(proto)) { goto fail; }
41 clazz = JS_NewObjectProtoClass(ctx, proto, liba_pid_fuzzy_class_id);
42 JS_FreeValue(ctx, proto);
43 if (JS_IsException(clazz)) { goto fail; }
44 JS_SetOpaque(clazz, self);
45 return clazz;
46 fail:
47 js_free(ctx, self);
48 JS_FreeValue(ctx, clazz);
49 return JS_EXCEPTION;
52 enum
54 self_kp_,
55 self_ki_,
56 self_kd_,
57 self_summax_,
58 self_summin_,
59 self_sum_,
60 self_outmax_,
61 self_outmin_,
62 self_out_,
63 self_fdb_,
64 self_err_,
65 self_order_,
66 self_block_,
69 static JSValue liba_pid_fuzzy_get(JSContext *ctx, JSValueConst this_val, int magic)
71 a_pid_fuzzy *const self = (a_pid_fuzzy *)JS_GetOpaque2(ctx, this_val, liba_pid_fuzzy_class_id);
72 if (!self) { return JS_EXCEPTION; }
73 double x;
74 switch (magic)
76 case self_kp_: x = (double)self->kp; break;
77 case self_ki_: x = (double)self->ki; break;
78 case self_kd_: x = (double)self->kd; break;
79 case self_summax_: x = (double)self->pid.summax; break;
80 case self_summin_: x = (double)self->pid.summin; break;
81 case self_sum_: x = (double)self->pid.sum; break;
82 case self_outmax_: x = (double)self->pid.outmax; break;
83 case self_outmin_: x = (double)self->pid.outmin; break;
84 case self_out_: x = (double)self->pid.out; break;
85 case self_fdb_: x = (double)self->pid.fdb; break;
86 case self_err_: x = (double)self->pid.err; break;
87 case self_order_: return JS_NewUint32(ctx, self->order);
88 case self_block_: return JS_NewUint32(ctx, self->block);
89 default: return JS_UNDEFINED;
91 return JS_NewFloat64(ctx, x);
94 static int liba_pid_fuzzy_block_(JSContext *ctx, a_pid_fuzzy *self, unsigned int block)
96 void *ptr = a_pid_fuzzy_block(self);
97 if (block > self->block)
99 ptr = js_realloc(ctx, ptr, A_PID_FUZZY_BLOCK(block));
100 if (!ptr) { return ~0; }
102 a_pid_fuzzy_set_block(self, ptr, block);
103 return 0;
106 static JSValue liba_pid_fuzzy_set(JSContext *ctx, JSValueConst this_val, JSValueConst val, int magic)
108 a_pid_fuzzy *const self = (a_pid_fuzzy *)JS_GetOpaque2(ctx, this_val, liba_pid_fuzzy_class_id);
109 if (!self) { return JS_EXCEPTION; }
110 a_u32 u;
111 if (magic == self_block_)
113 if (JS_ToUint32(ctx, &u, val)) { return JS_EXCEPTION; }
114 if (liba_pid_fuzzy_block_(ctx, self, (unsigned int)u)) { return JS_EXCEPTION; }
115 return JS_UNDEFINED;
117 double x;
118 if (JS_ToFloat64(ctx, &x, val)) { return JS_EXCEPTION; }
119 switch (magic)
121 case self_kp_: self->pid.kp = self->kp = (a_float)x; break;
122 case self_ki_: self->pid.ki = self->ki = (a_float)x; break;
123 case self_kd_: self->pid.kd = self->kd = (a_float)x; break;
124 case self_summax_: self->pid.summax = (a_float)x; break;
125 case self_summin_: self->pid.summin = (a_float)x; break;
126 case self_outmax_: self->pid.outmax = (a_float)x; break;
127 case self_outmin_: self->pid.outmin = (a_float)x; break;
128 default: break;
130 return JS_UNDEFINED;
133 static JSValue liba_pid_fuzzy_op(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
135 (void)argc;
136 a_pid_fuzzy *const self = (a_pid_fuzzy *)JS_GetOpaque2(ctx, this_val, liba_pid_fuzzy_class_id);
137 if (!self) { return JS_EXCEPTION; }
138 a_u32 op;
139 if (JS_ToUint32(ctx, &op, argv[0])) { return JS_EXCEPTION; }
140 a_pid_fuzzy_set_op(self, (unsigned int)op);
141 return JS_UNDEFINED;
144 static JSValue liba_pid_fuzzy_rule(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
146 (void)argc;
147 a_pid_fuzzy *const self = (a_pid_fuzzy *)JS_GetOpaque2(ctx, this_val, liba_pid_fuzzy_class_id);
148 if (!self) { return JS_EXCEPTION; }
149 union
151 a_float const *p;
152 a_float *o;
153 } u;
154 a_u32 row;
155 a_u32 len = 0;
156 a_u32 order = 0;
157 JSValue res = JS_UNDEFINED;
158 if (JS_IsArray(ctx, argv[0]))
160 if (js_array_length(ctx, argv[0], &order)) { goto fail; }
161 res = js_concat(ctx, argv[0]);
162 if (js_array_length(ctx, res, &len)) { goto fail; }
163 if (len)
165 a_float *const me = (a_float *)js_realloc(ctx, ((void)(u.p = self->me), u.o), sizeof(a_float) * len);
166 if (!me) { goto fail; }
167 self->me = me;
168 if (js_array_num_get(ctx, res, me, len)) { goto fail; }
170 JS_FreeValue(ctx, res);
171 res = JS_UNDEFINED;
173 if (JS_IsArray(ctx, argv[1]))
175 if (js_array_length(ctx, argv[1], &row) || row != order) { goto fail; }
176 res = js_concat(ctx, argv[1]);
177 if (js_array_length(ctx, res, &len)) { goto fail; }
178 if (len)
180 a_float *const mec = (a_float *)js_realloc(ctx, ((void)(u.p = self->mec), u.o), sizeof(a_float) * len);
181 if (!mec) { goto fail; }
182 self->mec = mec;
183 if (js_array_num_get(ctx, res, mec, len)) { goto fail; }
185 JS_FreeValue(ctx, res);
186 res = JS_UNDEFINED;
188 if (JS_IsArray(ctx, argv[2]))
190 if (js_array_length(ctx, argv[2], &row) || row != order) { goto fail; }
191 res = js_concat(ctx, argv[2]);
192 if (js_array_length(ctx, res, &len)) { goto fail; }
193 if (len)
195 a_float *const mkp = (a_float *)js_realloc(ctx, ((void)(u.p = self->mkp), u.o), sizeof(a_float) * len);
196 if (!mkp) { goto fail; }
197 self->mkp = mkp;
198 if (js_array_num_get(ctx, res, mkp, len)) { goto fail; }
200 JS_FreeValue(ctx, res);
201 res = JS_UNDEFINED;
203 if (JS_IsArray(ctx, argv[3]))
205 if (js_array_length(ctx, argv[3], &row) || row != order) { goto fail; }
206 res = js_concat(ctx, argv[3]);
207 if (js_array_length(ctx, res, &len)) { goto fail; }
208 if (len)
210 a_float *const mki = (a_float *)js_realloc(ctx, ((void)(u.p = self->mki), u.o), sizeof(a_float) * len);
211 if (!mki) { goto fail; }
212 self->mki = mki;
213 if (js_array_num_get(ctx, res, mki, len)) { goto fail; }
215 JS_FreeValue(ctx, res);
216 res = JS_UNDEFINED;
218 if (JS_IsArray(ctx, argv[4]))
220 if (js_array_length(ctx, argv[4], &row) || row != order) { goto fail; }
221 res = js_concat(ctx, argv[4]);
222 if (js_array_length(ctx, res, &len)) { goto fail; }
223 if (len)
225 a_float *const mkd = (a_float *)js_realloc(ctx, ((void)(u.p = self->mkd), u.o), sizeof(a_float) * len);
226 if (!mkd) { goto fail; }
227 self->mkd = mkd;
228 if (js_array_num_get(ctx, res, mkd, len)) { goto fail; }
230 JS_FreeValue(ctx, res);
232 self->order = order;
233 return JS_UNDEFINED;
234 fail:
235 JS_FreeValue(ctx, res);
236 return JS_UNDEFINED;
239 static JSValue liba_pid_fuzzy_block(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
241 (void)argc;
242 a_pid_fuzzy *const self = (a_pid_fuzzy *)JS_GetOpaque2(ctx, this_val, liba_pid_fuzzy_class_id);
243 if (!self) { return JS_EXCEPTION; }
244 a_u32 block;
245 if (JS_ToUint32(ctx, &block, argv[0])) { return JS_EXCEPTION; }
246 if (liba_pid_fuzzy_block_(ctx, self, block)) { return JS_EXCEPTION; }
247 return JS_UNDEFINED;
250 static JSValue liba_pid_fuzzy_kpid(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
252 (void)argc;
253 a_pid_fuzzy *const self = (a_pid_fuzzy *)JS_GetOpaque2(ctx, this_val, liba_pid_fuzzy_class_id);
254 if (!self) { return JS_EXCEPTION; }
255 double args[] = {0, 0, 0};
256 for (unsigned int i = 0; i < A_LEN(args); ++i)
258 if (JS_ToFloat64(ctx, &args[i], argv[i])) { return JS_EXCEPTION; }
260 a_pid_fuzzy_kpid(self, (a_float)args[0], (a_float)args[1], (a_float)args[2]);
261 return JS_UNDEFINED;
264 static JSValue liba_pid_fuzzy_zero(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
266 (void)argc;
267 (void)argv;
268 a_pid_fuzzy *const self = (a_pid_fuzzy *)JS_GetOpaque2(ctx, this_val, liba_pid_fuzzy_class_id);
269 if (!self) { return JS_EXCEPTION; }
270 a_pid_fuzzy_zero(self);
271 return JS_UNDEFINED;
274 static JSValue liba_pid_fuzzy_run(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
276 (void)argc;
277 a_pid_fuzzy *const self = (a_pid_fuzzy *)JS_GetOpaque2(ctx, this_val, liba_pid_fuzzy_class_id);
278 if (!self) { return JS_EXCEPTION; }
279 double args[] = {0, 0};
280 for (unsigned int i = 0; i < A_LEN(args); ++i)
282 if (JS_ToFloat64(ctx, &args[i], argv[i])) { return JS_EXCEPTION; }
284 return JS_NewFloat64(ctx, (double)a_pid_fuzzy_run(self, (a_float)args[0], (a_float)args[1]));
287 static JSValue liba_pid_fuzzy_pos(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
289 (void)argc;
290 a_pid_fuzzy *const self = (a_pid_fuzzy *)JS_GetOpaque2(ctx, this_val, liba_pid_fuzzy_class_id);
291 if (!self) { return JS_EXCEPTION; }
292 double args[] = {0, 0};
293 for (unsigned int i = 0; i < A_LEN(args); ++i)
295 if (JS_ToFloat64(ctx, &args[i], argv[i])) { return JS_EXCEPTION; }
297 return JS_NewFloat64(ctx, (double)a_pid_fuzzy_pos(self, (a_float)args[0], (a_float)args[1]));
300 static JSValue liba_pid_fuzzy_inc(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
302 (void)argc;
303 a_pid_fuzzy *const self = (a_pid_fuzzy *)JS_GetOpaque2(ctx, this_val, liba_pid_fuzzy_class_id);
304 if (!self) { return JS_EXCEPTION; }
305 double args[] = {0, 0};
306 for (unsigned int i = 0; i < A_LEN(args); ++i)
308 if (JS_ToFloat64(ctx, &args[i], argv[i])) { return JS_EXCEPTION; }
310 return JS_NewFloat64(ctx, (double)a_pid_fuzzy_inc(self, (a_float)args[0], (a_float)args[1]));
313 static JSCFunctionListEntry const liba_pid_fuzzy_proto[] = {
314 JS_PROP_STRING_DEF("[Symbol.toStringTag]", "a.pid.fuzzy", 0),
315 JS_CGETSET_MAGIC_DEF("kp", liba_pid_fuzzy_get, liba_pid_fuzzy_set, self_kp_),
316 JS_CGETSET_MAGIC_DEF("ki", liba_pid_fuzzy_get, liba_pid_fuzzy_set, self_ki_),
317 JS_CGETSET_MAGIC_DEF("kd", liba_pid_fuzzy_get, liba_pid_fuzzy_set, self_kd_),
318 JS_CGETSET_MAGIC_DEF("summax", liba_pid_fuzzy_get, liba_pid_fuzzy_set, self_summax_),
319 JS_CGETSET_MAGIC_DEF("summin", liba_pid_fuzzy_get, liba_pid_fuzzy_set, self_summin_),
320 JS_CGETSET_MAGIC_DEF("sum", liba_pid_fuzzy_get, NULL, self_sum_),
321 JS_CGETSET_MAGIC_DEF("outmax", liba_pid_fuzzy_get, liba_pid_fuzzy_set, self_outmax_),
322 JS_CGETSET_MAGIC_DEF("outmin", liba_pid_fuzzy_get, liba_pid_fuzzy_set, self_outmin_),
323 JS_CGETSET_MAGIC_DEF("out", liba_pid_fuzzy_get, NULL, self_out_),
324 JS_CGETSET_MAGIC_DEF("fdb", liba_pid_fuzzy_get, NULL, self_fdb_),
325 JS_CGETSET_MAGIC_DEF("err", liba_pid_fuzzy_get, NULL, self_err_),
326 JS_CGETSET_MAGIC_DEF("order", liba_pid_fuzzy_get, NULL, self_order_),
327 JS_CGETSET_MAGIC_DEF("block", liba_pid_fuzzy_get, liba_pid_fuzzy_set, self_block_),
328 JS_CFUNC_DEF("op", 1, liba_pid_fuzzy_op),
329 JS_CFUNC_DEF("rule", 5, liba_pid_fuzzy_rule),
330 JS_CFUNC_DEF("set_block", 1, liba_pid_fuzzy_block),
331 JS_CFUNC_DEF("kpid", 3, liba_pid_fuzzy_kpid),
332 JS_CFUNC_DEF("zero", 0, liba_pid_fuzzy_zero),
333 JS_CFUNC_DEF("run", 2, liba_pid_fuzzy_run),
334 JS_CFUNC_DEF("pos", 2, liba_pid_fuzzy_pos),
335 JS_CFUNC_DEF("inc", 2, liba_pid_fuzzy_inc),
338 int js_liba_pid_fuzzy_init(JSContext *ctx, JSModuleDef *m)
340 JS_NewClassID(&liba_pid_fuzzy_class_id);
341 JS_NewClass(JS_GetRuntime(ctx), liba_pid_fuzzy_class_id, &liba_pid_fuzzy_class);
343 JSValue const proto = JS_NewObject(ctx);
344 JS_SetPropertyFunctionList(ctx, proto, liba_pid_fuzzy_proto, A_LEN(liba_pid_fuzzy_proto));
346 JSValue const clazz = JS_NewCFunction2(ctx, liba_pid_fuzzy_ctor, "pid_fuzzy", 3, JS_CFUNC_constructor, 0);
347 JS_SetConstructor(ctx, clazz, proto);
348 JS_SetClassProto(ctx, liba_pid_fuzzy_class_id, proto);
350 JS_DefinePropertyValueStr(ctx, clazz, "CAP", JS_NewUint32(ctx, A_PID_FUZZY_CAP), 0);
351 JS_DefinePropertyValueStr(ctx, clazz, "CAP_ALGEBRA", JS_NewUint32(ctx, A_PID_FUZZY_CAP_ALGEBRA), 0);
352 JS_DefinePropertyValueStr(ctx, clazz, "CAP_BOUNDED", JS_NewUint32(ctx, A_PID_FUZZY_CAP_BOUNDED), 0);
353 JS_DefinePropertyValueStr(ctx, clazz, "CUP", JS_NewUint32(ctx, A_PID_FUZZY_CUP), 0);
354 JS_DefinePropertyValueStr(ctx, clazz, "CUP_ALGEBRA", JS_NewUint32(ctx, A_PID_FUZZY_CUP_ALGEBRA), 0);
355 JS_DefinePropertyValueStr(ctx, clazz, "CUP_BOUNDED", JS_NewUint32(ctx, A_PID_FUZZY_CUP_BOUNDED), 0);
356 JS_DefinePropertyValueStr(ctx, clazz, "EQU", JS_NewUint32(ctx, A_PID_FUZZY_EQU), 0);
358 return JS_SetModuleExport(ctx, m, "pid_fuzzy", clazz);