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
);
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
));
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
)
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
);
48 JS_FreeValue(ctx
, clazz
);
52 static JSValue
liba_pid_fuzzy_get(JSContext
*ctx
, JSValueConst this_val
, int magic
)
54 a_pid_fuzzy
*const self
= (a_pid_fuzzy
*)JS_GetOpaque2(ctx
, this_val
, liba_pid_fuzzy_class_id
);
55 if (!self
) { return JS_EXCEPTION
; }
59 case 0: return JS_NewUint32(ctx
, self
->block
);
60 case 1: x
= (double)self
->kp
; break;
61 case 2: x
= (double)self
->ki
; break;
62 case 3: x
= (double)self
->kd
; break;
63 case 4: x
= (double)self
->pid
.summax
; break;
64 case 5: x
= (double)self
->pid
.summin
; break;
65 case 6: x
= (double)self
->pid
.outmax
; break;
66 case 7: x
= (double)self
->pid
.outmin
; break;
67 case 8: x
= (double)self
->pid
.out
; break;
68 case 9: x
= (double)self
->pid
.fdb
; break;
69 case 10: x
= (double)self
->pid
.err
; break;
70 case 11: return JS_NewUint32(ctx
, self
->order
);
71 default: return JS_UNDEFINED
;
73 return JS_NewFloat64(ctx
, x
);
76 static int liba_pid_fuzzy_block_(JSContext
*ctx
, a_pid_fuzzy
*self
, unsigned int block
)
78 void *ptr
= a_pid_fuzzy_block(self
);
79 if (block
> self
->block
)
81 ptr
= js_realloc(ctx
, ptr
, A_PID_FUZZY_BLOCK(block
));
82 if (!ptr
) { return ~0; }
84 a_pid_fuzzy_set_block(self
, ptr
, block
);
88 static JSValue
liba_pid_fuzzy_set(JSContext
*ctx
, JSValueConst this_val
, JSValueConst val
, int magic
)
90 a_pid_fuzzy
*const self
= (a_pid_fuzzy
*)JS_GetOpaque2(ctx
, this_val
, liba_pid_fuzzy_class_id
);
91 if (!self
) { return JS_EXCEPTION
; }
95 if (JS_ToUint32(ctx
, &u
, val
)) { return JS_EXCEPTION
; }
96 if (liba_pid_fuzzy_block_(ctx
, self
, (unsigned int)u
)) { return JS_EXCEPTION
; }
100 if (JS_ToFloat64(ctx
, &x
, val
)) { return JS_EXCEPTION
; }
103 case 1: self
->pid
.kp
= self
->kp
= (a_float
)x
; break;
104 case 2: self
->pid
.ki
= self
->ki
= (a_float
)x
; break;
105 case 3: self
->pid
.kd
= self
->kd
= (a_float
)x
; break;
106 case 4: self
->pid
.summax
= (a_float
)x
; break;
107 case 5: self
->pid
.summin
= (a_float
)x
; break;
108 case 6: self
->pid
.outmax
= (a_float
)x
; break;
109 case 7: self
->pid
.outmin
= (a_float
)x
; break;
115 static JSValue
liba_pid_fuzzy_op(JSContext
*ctx
, JSValueConst this_val
, int argc
, JSValueConst
*argv
)
118 a_pid_fuzzy
*const self
= (a_pid_fuzzy
*)JS_GetOpaque2(ctx
, this_val
, liba_pid_fuzzy_class_id
);
119 if (!self
) { return JS_EXCEPTION
; }
121 if (JS_ToUint32(ctx
, &op
, argv
[0])) { return JS_EXCEPTION
; }
122 a_pid_fuzzy_set_op(self
, (unsigned int)op
);
126 static JSValue
liba_pid_fuzzy_rule(JSContext
*ctx
, JSValueConst this_val
, int argc
, JSValueConst
*argv
)
129 a_pid_fuzzy
*const self
= (a_pid_fuzzy
*)JS_GetOpaque2(ctx
, this_val
, liba_pid_fuzzy_class_id
);
130 if (!self
) { return JS_EXCEPTION
; }
139 JSValue res
= JS_UNDEFINED
;
140 if (JS_IsArray(ctx
, argv
[0]))
142 if (js_array_length(ctx
, argv
[0], &order
)) { goto fail
; }
143 res
= js_concat(ctx
, argv
[0]);
144 if (js_array_length(ctx
, res
, &len
)) { goto fail
; }
147 a_float
*const me
= (a_float
*)js_realloc(ctx
, ((void)(u
.p
= self
->me
), u
.o
), sizeof(a_float
) * len
);
148 if (!me
) { goto fail
; }
150 if (js_array_num_get(ctx
, res
, me
, len
)) { goto fail
; }
152 JS_FreeValue(ctx
, res
);
155 if (JS_IsArray(ctx
, argv
[1]))
157 if (js_array_length(ctx
, argv
[1], &row
) || row
!= order
) { goto fail
; }
158 res
= js_concat(ctx
, argv
[1]);
159 if (js_array_length(ctx
, res
, &len
)) { goto fail
; }
162 a_float
*const mec
= (a_float
*)js_realloc(ctx
, ((void)(u
.p
= self
->mec
), u
.o
), sizeof(a_float
) * len
);
163 if (!mec
) { goto fail
; }
165 if (js_array_num_get(ctx
, res
, mec
, len
)) { goto fail
; }
167 JS_FreeValue(ctx
, res
);
170 if (JS_IsArray(ctx
, argv
[2]))
172 if (js_array_length(ctx
, argv
[2], &row
) || row
!= order
) { goto fail
; }
173 res
= js_concat(ctx
, argv
[2]);
174 if (js_array_length(ctx
, res
, &len
)) { goto fail
; }
177 a_float
*const mkp
= (a_float
*)js_realloc(ctx
, ((void)(u
.p
= self
->mkp
), u
.o
), sizeof(a_float
) * len
);
178 if (!mkp
) { goto fail
; }
180 if (js_array_num_get(ctx
, res
, mkp
, len
)) { goto fail
; }
182 JS_FreeValue(ctx
, res
);
185 if (JS_IsArray(ctx
, argv
[3]))
187 if (js_array_length(ctx
, argv
[3], &row
) || row
!= order
) { goto fail
; }
188 res
= js_concat(ctx
, argv
[3]);
189 if (js_array_length(ctx
, res
, &len
)) { goto fail
; }
192 a_float
*const mki
= (a_float
*)js_realloc(ctx
, ((void)(u
.p
= self
->mki
), u
.o
), sizeof(a_float
) * len
);
193 if (!mki
) { goto fail
; }
195 if (js_array_num_get(ctx
, res
, mki
, len
)) { goto fail
; }
197 JS_FreeValue(ctx
, res
);
200 if (JS_IsArray(ctx
, argv
[4]))
202 if (js_array_length(ctx
, argv
[4], &row
) || row
!= order
) { goto fail
; }
203 res
= js_concat(ctx
, argv
[4]);
204 if (js_array_length(ctx
, res
, &len
)) { goto fail
; }
207 a_float
*const mkd
= (a_float
*)js_realloc(ctx
, ((void)(u
.p
= self
->mkd
), u
.o
), sizeof(a_float
) * len
);
208 if (!mkd
) { goto fail
; }
210 if (js_array_num_get(ctx
, res
, mkd
, len
)) { goto fail
; }
212 JS_FreeValue(ctx
, res
);
217 JS_FreeValue(ctx
, res
);
221 static JSValue
liba_pid_fuzzy_block(JSContext
*ctx
, JSValueConst this_val
, int argc
, JSValueConst
*argv
)
224 a_pid_fuzzy
*const self
= (a_pid_fuzzy
*)JS_GetOpaque2(ctx
, this_val
, liba_pid_fuzzy_class_id
);
225 if (!self
) { return JS_EXCEPTION
; }
227 if (JS_ToUint32(ctx
, &block
, argv
[0])) { return JS_EXCEPTION
; }
228 if (liba_pid_fuzzy_block_(ctx
, self
, block
)) { return JS_EXCEPTION
; }
232 static JSValue
liba_pid_fuzzy_kpid(JSContext
*ctx
, JSValueConst this_val
, int argc
, JSValueConst
*argv
)
235 a_pid_fuzzy
*const self
= (a_pid_fuzzy
*)JS_GetOpaque2(ctx
, this_val
, liba_pid_fuzzy_class_id
);
236 if (!self
) { return JS_EXCEPTION
; }
237 double args
[] = {0, 0, 0};
238 for (unsigned int i
= 0; i
< A_LEN(args
); ++i
)
240 if (JS_ToFloat64(ctx
, &args
[i
], argv
[i
])) { return JS_EXCEPTION
; }
242 a_pid_fuzzy_kpid(self
, (a_float
)args
[0], (a_float
)args
[1], (a_float
)args
[2]);
246 static JSValue
liba_pid_fuzzy_zero(JSContext
*ctx
, JSValueConst this_val
, int argc
, JSValueConst
*argv
)
250 a_pid_fuzzy
*const self
= (a_pid_fuzzy
*)JS_GetOpaque2(ctx
, this_val
, liba_pid_fuzzy_class_id
);
251 if (!self
) { return JS_EXCEPTION
; }
252 a_pid_fuzzy_zero(self
);
256 static JSValue
liba_pid_fuzzy_run(JSContext
*ctx
, JSValueConst this_val
, int argc
, JSValueConst
*argv
)
259 a_pid_fuzzy
*const self
= (a_pid_fuzzy
*)JS_GetOpaque2(ctx
, this_val
, liba_pid_fuzzy_class_id
);
260 if (!self
) { return JS_EXCEPTION
; }
261 double args
[] = {0, 0};
262 for (unsigned int i
= 0; i
< A_LEN(args
); ++i
)
264 if (JS_ToFloat64(ctx
, &args
[i
], argv
[i
])) { return JS_EXCEPTION
; }
266 return JS_NewFloat64(ctx
, (double)a_pid_fuzzy_run(self
, (a_float
)args
[0], (a_float
)args
[1]));
269 static JSValue
liba_pid_fuzzy_pos(JSContext
*ctx
, JSValueConst this_val
, int argc
, JSValueConst
*argv
)
272 a_pid_fuzzy
*const self
= (a_pid_fuzzy
*)JS_GetOpaque2(ctx
, this_val
, liba_pid_fuzzy_class_id
);
273 if (!self
) { return JS_EXCEPTION
; }
274 double args
[] = {0, 0};
275 for (unsigned int i
= 0; i
< A_LEN(args
); ++i
)
277 if (JS_ToFloat64(ctx
, &args
[i
], argv
[i
])) { return JS_EXCEPTION
; }
279 return JS_NewFloat64(ctx
, (double)a_pid_fuzzy_pos(self
, (a_float
)args
[0], (a_float
)args
[1]));
282 static JSValue
liba_pid_fuzzy_inc(JSContext
*ctx
, JSValueConst this_val
, int argc
, JSValueConst
*argv
)
285 a_pid_fuzzy
*const self
= (a_pid_fuzzy
*)JS_GetOpaque2(ctx
, this_val
, liba_pid_fuzzy_class_id
);
286 if (!self
) { return JS_EXCEPTION
; }
287 double args
[] = {0, 0};
288 for (unsigned int i
= 0; i
< A_LEN(args
); ++i
)
290 if (JS_ToFloat64(ctx
, &args
[i
], argv
[i
])) { return JS_EXCEPTION
; }
292 return JS_NewFloat64(ctx
, (double)a_pid_fuzzy_inc(self
, (a_float
)args
[0], (a_float
)args
[1]));
295 static JSCFunctionListEntry
const liba_pid_fuzzy_proto
[] = {
296 JS_PROP_STRING_DEF("[Symbol.toStringTag]", "a.pid.fuzzy", 0),
297 JS_CGETSET_MAGIC_DEF("block", liba_pid_fuzzy_get
, liba_pid_fuzzy_set
, 0),
298 JS_CGETSET_MAGIC_DEF("kp", liba_pid_fuzzy_get
, liba_pid_fuzzy_set
, 1),
299 JS_CGETSET_MAGIC_DEF("ki", liba_pid_fuzzy_get
, liba_pid_fuzzy_set
, 2),
300 JS_CGETSET_MAGIC_DEF("kd", liba_pid_fuzzy_get
, liba_pid_fuzzy_set
, 3),
301 JS_CGETSET_MAGIC_DEF("summax", liba_pid_fuzzy_get
, liba_pid_fuzzy_set
, 4),
302 JS_CGETSET_MAGIC_DEF("summin", liba_pid_fuzzy_get
, liba_pid_fuzzy_set
, 5),
303 JS_CGETSET_MAGIC_DEF("outmax", liba_pid_fuzzy_get
, liba_pid_fuzzy_set
, 6),
304 JS_CGETSET_MAGIC_DEF("outmin", liba_pid_fuzzy_get
, liba_pid_fuzzy_set
, 7),
305 JS_CGETSET_MAGIC_DEF("out", liba_pid_fuzzy_get
, NULL
, 8),
306 JS_CGETSET_MAGIC_DEF("fdb", liba_pid_fuzzy_get
, NULL
, 9),
307 JS_CGETSET_MAGIC_DEF("err", liba_pid_fuzzy_get
, NULL
, 10),
308 JS_CGETSET_MAGIC_DEF("order", liba_pid_fuzzy_get
, NULL
, 11),
309 JS_CFUNC_DEF("op", 1, liba_pid_fuzzy_op
),
310 JS_CFUNC_DEF("rule", 5, liba_pid_fuzzy_rule
),
311 JS_CFUNC_DEF("set_block", 1, liba_pid_fuzzy_block
),
312 JS_CFUNC_DEF("kpid", 3, liba_pid_fuzzy_kpid
),
313 JS_CFUNC_DEF("zero", 0, liba_pid_fuzzy_zero
),
314 JS_CFUNC_DEF("run", 2, liba_pid_fuzzy_run
),
315 JS_CFUNC_DEF("pos", 2, liba_pid_fuzzy_pos
),
316 JS_CFUNC_DEF("inc", 2, liba_pid_fuzzy_inc
),
319 int js_liba_pid_fuzzy_init(JSContext
*ctx
, JSModuleDef
*m
)
321 JS_NewClassID(&liba_pid_fuzzy_class_id
);
322 JS_NewClass(JS_GetRuntime(ctx
), liba_pid_fuzzy_class_id
, &liba_pid_fuzzy_class
);
324 JSValue
const proto
= JS_NewObject(ctx
);
325 JS_SetPropertyFunctionList(ctx
, proto
, liba_pid_fuzzy_proto
, A_LEN(liba_pid_fuzzy_proto
));
327 JSValue
const clazz
= JS_NewCFunction2(ctx
, liba_pid_fuzzy_ctor
, "pid_fuzzy", 3, JS_CFUNC_constructor
, 0);
328 JS_SetConstructor(ctx
, clazz
, proto
);
329 JS_SetClassProto(ctx
, liba_pid_fuzzy_class_id
, proto
);
331 JS_DefinePropertyValueStr(ctx
, clazz
, "CAP", JS_NewUint32(ctx
, A_PID_FUZZY_CAP
), 0);
332 JS_DefinePropertyValueStr(ctx
, clazz
, "CAP_ALGEBRA", JS_NewUint32(ctx
, A_PID_FUZZY_CAP_ALGEBRA
), 0);
333 JS_DefinePropertyValueStr(ctx
, clazz
, "CAP_BOUNDED", JS_NewUint32(ctx
, A_PID_FUZZY_CAP_BOUNDED
), 0);
334 JS_DefinePropertyValueStr(ctx
, clazz
, "CUP", JS_NewUint32(ctx
, A_PID_FUZZY_CUP
), 0);
335 JS_DefinePropertyValueStr(ctx
, clazz
, "CUP_ALGEBRA", JS_NewUint32(ctx
, A_PID_FUZZY_CUP_ALGEBRA
), 0);
336 JS_DefinePropertyValueStr(ctx
, clazz
, "CUP_BOUNDED", JS_NewUint32(ctx
, A_PID_FUZZY_CUP_BOUNDED
), 0);
337 JS_DefinePropertyValueStr(ctx
, clazz
, "EQU", JS_NewUint32(ctx
, A_PID_FUZZY_EQU
), 0);
339 return JS_SetModuleExport(ctx
, m
, "pid_fuzzy", clazz
);