create functions a_float_sum{,sq,abs}
[liba.git] / src / lib.rs
blobf88fbd2fe9d3b39c7941c38c14fac3ba6b3d2057
1 /*!
2 An algorithm library based on C/C++
4 ## Installation
6 Add this to your `Cargo.toml`:
8 ```toml
9 [dependencies]
10 liba = "0.1"
11 ```
14 #![warn(missing_docs)]
15 #![allow(non_camel_case_types)]
16 #![cfg_attr(not(feature = "std"), no_std)]
18 /// floating-point number stored using `f64`
19 #[cfg(not(feature = "float"))]
20 pub type float = f64;
21 /// floating-point number stored using `f32`
22 #[cfg(feature = "float")]
23 pub type float = f32;
25 #[cfg(feature = "std")]
26 extern crate std;
28 #[cfg(not(feature = "std"))]
29 pub use core::ffi::c_int;
30 #[cfg(feature = "std")]
31 pub use std::os::raw::c_int;
33 #[cfg(not(feature = "std"))]
34 pub use core::ffi::c_uint;
35 #[cfg(feature = "std")]
36 pub use std::os::raw::c_uint;
38 #[cfg(not(feature = "std"))]
39 use core::mem::size_of;
40 #[cfg(feature = "std")]
41 use std::mem::size_of;
43 #[cfg(not(feature = "std"))]
44 use core::cmp::Ordering;
45 #[cfg(feature = "std")]
46 use std::cmp::Ordering;
48 #[cfg(not(feature = "std"))]
49 use core::ptr::{null, null_mut};
50 #[cfg(feature = "std")]
51 use std::ptr::{null, null_mut};
53 #[cfg(not(feature = "std"))]
54 use core::slice::{from_raw_parts, from_raw_parts_mut};
55 #[cfg(feature = "std")]
56 use std::slice::{from_raw_parts, from_raw_parts_mut};
58 extern "C" {
59     fn a_u32_sqrt(x: u32) -> u16;
60     fn a_u64_sqrt(x: u64) -> u32;
63 /// square root of an unsigned integer
64 #[inline(always)]
65 pub fn u32_sqrt(x: u32) -> u16 {
66     unsafe { a_u32_sqrt(x) }
68 /// square root of an unsigned integer
69 #[inline(always)]
70 pub fn u64_sqrt(x: u64) -> u32 {
71     unsafe { a_u64_sqrt(x) }
74 extern "C" {
75     fn a_f32_rsqrt(x: f32) -> f32;
76     fn a_f64_rsqrt(x: f64) -> f64;
79 /// reciprocal of square-root, `\frac{1}{\sqrt{x}}`
80 #[inline(always)]
81 pub fn f32_rsqrt(x: f32) -> f32 {
82     unsafe { a_f32_rsqrt(x) }
84 /// reciprocal of square-root, `\frac{1}{\sqrt{x}}`
85 #[inline(always)]
86 pub fn f64_rsqrt(x: f64) -> f64 {
87     unsafe { a_f64_rsqrt(x) }
90 extern "C" {
91     fn a_hash_bkdr_(pdata: *const u8, nbyte: usize, value: u32) -> u32;
92     fn a_hash_sdbm_(pdata: *const u8, nbyte: usize, value: u32) -> u32;
95 /// a hash function whose prime number is 131
96 #[inline(always)]
97 pub fn hash_bkdr(block: &[u8], value: u32) -> u32 {
98     unsafe { a_hash_bkdr_(block.as_ptr(), block.len(), value) }
100 /// a hash function whose prime number is 65599
101 #[inline(always)]
102 pub fn hash_sdbm(block: &[u8], value: u32) -> u32 {
103     unsafe { a_hash_sdbm_(block.as_ptr(), block.len(), value) }
106 /// Cyclic Redundancy Check for 8 bits
107 #[repr(C)]
108 pub struct crc8 {
109     /// Cyclic Redundancy Check comparison table
110     pub table: [u8; 0x100],
113 extern "C" {
114     fn a_crc8m_init(table: *mut u8, poly: u8);
115     fn a_crc8l_init(table: *mut u8, poly: u8);
116     fn a_crc8(table: *const u8, pdate: *const u8, nbyte: usize, value: u8) -> u8;
119 impl crc8 {
120     /// initialize for MSB CRC-8
121     #[inline(always)]
122     pub fn new_msb(poly: u8) -> Self {
123         let mut ctx: Self = Self { table: [0; 0x100] };
124         unsafe { a_crc8m_init(ctx.table.as_mut_ptr(), poly) };
125         ctx
126     }
127     /// initialize for LSB CRC-8
128     #[inline(always)]
129     pub fn new_lsb(poly: u8) -> Self {
130         let mut ctx: Self = Self { table: [0; 0x100] };
131         unsafe { a_crc8l_init(ctx.table.as_mut_ptr(), poly) };
132         ctx
133     }
134     /// generate for MSB CRC-8
135     #[inline(always)]
136     pub fn gen_msb(&mut self, poly: u8) -> &mut Self {
137         unsafe { a_crc8m_init(self.table.as_mut_ptr(), poly) };
138         self
139     }
140     /// generate for LSB CRC-8
141     #[inline(always)]
142     pub fn gen_lsb(&mut self, poly: u8) -> &mut Self {
143         unsafe { a_crc8l_init(self.table.as_mut_ptr(), poly) };
144         self
145     }
146     /// calculate for CRC-8
147     #[inline(always)]
148     pub fn eval(self, block: &[u8], value: u8) -> u8 {
149         unsafe { a_crc8(self.table.as_ptr(), block.as_ptr(), block.len(), value) }
150     }
153 /// Cyclic Redundancy Check for 16 bits
154 #[repr(C)]
155 pub struct crc16 {
156     /// Cyclic Redundancy Check comparison table
157     pub table: [u16; 0x100],
158     eval: unsafe extern "C" fn(*const u16, *const u8, usize, u16) -> u16,
161 extern "C" {
162     fn a_crc16m_init(table: *mut u16, poly: u16);
163     fn a_crc16l_init(table: *mut u16, poly: u16);
164     fn a_crc16m(table: *const u16, pdate: *const u8, nbyte: usize, value: u16) -> u16;
165     fn a_crc16l(table: *const u16, pdate: *const u8, nbyte: usize, value: u16) -> u16;
168 impl crc16 {
169     /// initialize for MSB CRC-16
170     #[inline(always)]
171     pub fn new_msb(poly: u16) -> Self {
172         let mut ctx: Self = Self {
173             table: [0; 0x100],
174             eval: a_crc16m,
175         };
176         unsafe { a_crc16m_init(ctx.table.as_mut_ptr(), poly) };
177         ctx
178     }
179     /// initialize for LSB CRC-16
180     #[inline(always)]
181     pub fn new_lsb(poly: u16) -> Self {
182         let mut ctx: Self = Self {
183             table: [0; 0x100],
184             eval: a_crc16l,
185         };
186         unsafe { a_crc16l_init(ctx.table.as_mut_ptr(), poly) };
187         ctx
188     }
189     /// generate for MSB CRC-16
190     #[inline(always)]
191     pub fn gen_msb(&mut self, poly: u16) -> &mut Self {
192         unsafe { a_crc16m_init(self.table.as_mut_ptr(), poly) };
193         self.eval = a_crc16m;
194         self
195     }
196     /// generate for LSB CRC-16
197     #[inline(always)]
198     pub fn gen_lsb(&mut self, poly: u16) -> &mut Self {
199         unsafe { a_crc16l_init(self.table.as_mut_ptr(), poly) };
200         self.eval = a_crc16l;
201         self
202     }
203     /// calculate for CRC-16
204     #[inline(always)]
205     pub fn eval(self, block: &[u8], value: u16) -> u16 {
206         unsafe { (self.eval)(self.table.as_ptr(), block.as_ptr(), block.len(), value) }
207     }
210 /// Cyclic Redundancy Check for 32 bits
211 #[repr(C)]
212 pub struct crc32 {
213     /// Cyclic Redundancy Check comparison table
214     pub table: [u32; 0x100],
215     eval: unsafe extern "C" fn(*const u32, *const u8, usize, u32) -> u32,
218 extern "C" {
219     fn a_crc32m_init(table: *mut u32, poly: u32);
220     fn a_crc32l_init(table: *mut u32, poly: u32);
221     fn a_crc32m(table: *const u32, pdate: *const u8, nbyte: usize, value: u32) -> u32;
222     fn a_crc32l(table: *const u32, pdate: *const u8, nbyte: usize, value: u32) -> u32;
225 impl crc32 {
226     /// initialize for MSB CRC-32
227     #[inline(always)]
228     pub fn new_msb(poly: u32) -> Self {
229         let mut ctx: Self = Self {
230             table: [0; 0x100],
231             eval: a_crc32m,
232         };
233         unsafe { a_crc32m_init(ctx.table.as_mut_ptr(), poly) };
234         ctx
235     }
236     /// initialize for LSB CRC-32
237     #[inline(always)]
238     pub fn new_lsb(poly: u32) -> Self {
239         let mut ctx: Self = Self {
240             table: [0; 0x100],
241             eval: a_crc32l,
242         };
243         unsafe { a_crc32l_init(ctx.table.as_mut_ptr(), poly) };
244         ctx
245     }
246     /// generate for MSB CRC-32
247     #[inline(always)]
248     pub fn gen_msb(&mut self, poly: u32) -> &mut Self {
249         unsafe { a_crc32m_init(self.table.as_mut_ptr(), poly) };
250         self.eval = a_crc32m;
251         self
252     }
253     /// generate for LSB CRC-32
254     #[inline(always)]
255     pub fn gen_lsb(&mut self, poly: u32) -> &mut Self {
256         unsafe { a_crc32l_init(self.table.as_mut_ptr(), poly) };
257         self.eval = a_crc32l;
258         self
259     }
260     /// calculate for CRC-32
261     #[inline(always)]
262     pub fn eval(self, block: &[u8], value: u32) -> u32 {
263         unsafe { (self.eval)(self.table.as_ptr(), block.as_ptr(), block.len(), value) }
264     }
267 /// Cyclic Redundancy Check for 64 bits
268 #[repr(C)]
269 pub struct crc64 {
270     /// Cyclic Redundancy Check comparison table
271     pub table: [u64; 0x100],
272     eval: unsafe extern "C" fn(*const u64, *const u8, usize, u64) -> u64,
275 extern "C" {
276     fn a_crc64m_init(table: *mut u64, poly: u64);
277     fn a_crc64l_init(table: *mut u64, poly: u64);
278     fn a_crc64m(table: *const u64, pdate: *const u8, nbyte: usize, value: u64) -> u64;
279     fn a_crc64l(table: *const u64, pdate: *const u8, nbyte: usize, value: u64) -> u64;
282 impl crc64 {
283     /// initialize for MSB CRC-64
284     #[inline(always)]
285     pub fn new_msb(poly: u64) -> Self {
286         let mut ctx: Self = Self {
287             table: [0; 0x100],
288             eval: a_crc64m,
289         };
290         unsafe { a_crc64m_init(ctx.table.as_mut_ptr(), poly) };
291         ctx
292     }
293     /// initialize for LSB CRC-64
294     #[inline(always)]
295     pub fn new_lsb(poly: u64) -> Self {
296         let mut ctx: Self = Self {
297             table: [0; 0x100],
298             eval: a_crc64l,
299         };
300         unsafe { a_crc64l_init(ctx.table.as_mut_ptr(), poly) };
301         ctx
302     }
303     /// generate for MSB CRC-64
304     #[inline(always)]
305     pub fn gen_msb(&mut self, poly: u64) -> &mut Self {
306         unsafe { a_crc64m_init(self.table.as_mut_ptr(), poly) };
307         self.eval = a_crc64m;
308         self
309     }
310     /// generate for LSB CRC-64
311     #[inline(always)]
312     pub fn gen_lsb(&mut self, poly: u64) -> &mut Self {
313         unsafe { a_crc64l_init(self.table.as_mut_ptr(), poly) };
314         self.eval = a_crc64l;
315         self
316     }
317     /// calculate for CRC-64
318     #[inline(always)]
319     pub fn eval(self, block: &[u8], value: u64) -> u64 {
320         unsafe { (self.eval)(self.table.as_ptr(), block.as_ptr(), block.len(), value) }
321     }
324 #[allow(clippy::excessive_precision)]
325 const TAU: float = 6.28318530717958647692528676655900577;
327 /// High Pass Filter
328 #[repr(C)]
329 pub struct hpf {
330     /// filter coefficient
331     pub alpha: float,
332     /// filter output
333     pub output: float,
334     /// filter input
335     pub input: float,
338 impl hpf {
339     /// initialize for High Pass Filter
340     #[inline(always)]
341     pub fn new(fc: float, ts: float) -> Self {
342         Self {
343             alpha: 1.0 / (TAU * fc * ts + 1.0),
344             output: 0.0,
345             input: 0.0,
346         }
347     }
348     /// generate for High Pass Filter
349     #[inline(always)]
350     pub fn gen(&mut self, fc: float, ts: float) -> &mut Self {
351         self.alpha = 1.0 / (TAU * fc * ts + 1.0);
352         self
353     }
354     /// calculate for High Pass Filter
355     #[inline(always)]
356     pub fn iter(&mut self, x: float) -> float {
357         self.output = self.alpha * (self.output + x - self.input);
358         self.input = x;
359         self.output
360     }
361     /// zeroing for High Pass Filter
362     #[inline(always)]
363     pub fn zero(&mut self) -> &mut Self {
364         self.output = 0.0;
365         self.input = 0.0;
366         self
367     }
370 #[allow(clippy::excessive_precision)]
371 const _1_TAU: float = 0.159154943091895335768883763372514362;
373 /// Low Pass Filter
374 #[repr(C)]
375 pub struct lpf {
376     /// filter coefficient
377     pub alpha: float,
378     /// filter output
379     pub output: float,
382 impl lpf {
383     /// initialize for Low Pass Filter
384     #[inline(always)]
385     pub fn new(fc: float, ts: float) -> Self {
386         Self {
387             alpha: ts / (_1_TAU / fc + ts),
388             output: 0.0,
389         }
390     }
391     /// generate for Low Pass Filter
392     #[inline(always)]
393     pub fn gen(&mut self, fc: float, ts: float) -> &mut Self {
394         self.alpha = ts / (_1_TAU / fc + ts);
395         self
396     }
397     /// calculate for Low Pass Filter
398     #[inline(always)]
399     pub fn iter(&mut self, x: float) -> float {
400         self.output *= 1.0 - self.alpha;
401         self.output += x * self.alpha;
402         self.output
403     }
404     /// zeroing for Low Pass Filter
405     #[inline(always)]
406     pub fn zero(&mut self) -> &mut Self {
407         self.output = 0.0;
408         self
409     }
412 /// membership function
413 pub mod mf {
414     use crate::c_int;
415     /// none
416     pub const NUL: c_int = 0;
417     /// gaussian membership function
418     pub const GAUSS: c_int = 1;
419     /// gaussian combination membership function
420     pub const GAUSS2: c_int = 2;
421     /// generalized bell-shaped membership function
422     pub const GBELL: c_int = 3;
423     /// sigmoidal membership function
424     pub const SIG: c_int = 4;
425     /// difference between two sigmoidal membership functions
426     pub const DSIG: c_int = 5;
427     /// product of two sigmoidal membership functions
428     pub const PSIG: c_int = 6;
429     /// trapezoidal membership function
430     pub const TRAP: c_int = 7;
431     /// triangular membership function
432     pub const TRI: c_int = 8;
433     /// linear s-shaped saturation membership function
434     pub const LINS: c_int = 9;
435     /// linear z-shaped saturation membership function
436     pub const LINZ: c_int = 10;
437     /// s-shaped membership function
438     pub const S: c_int = 11;
439     /// z-shaped membership function
440     pub const Z: c_int = 12;
441     /// pi-shaped membership function
442     pub const PI: c_int = 13;
444     use crate::float;
445     extern "C" {
446         fn a_mf_gauss(x: float, sigma: float, c: float) -> float;
447         fn a_mf_gauss2(x: float, sigma1: float, c1: float, sigma2: float, c2: float) -> float;
448         fn a_mf_gbell(x: float, a: float, b: float, c: float) -> float;
449         fn a_mf_sig(x: float, a: float, c: float) -> float;
450         fn a_mf_dsig(x: float, a1: float, c1: float, a2: float, c2: float) -> float;
451         fn a_mf_psig(x: float, a1: float, c1: float, a2: float, c2: float) -> float;
452         fn a_mf_trap(x: float, a: float, b: float, c: float, d: float) -> float;
453         fn a_mf_tri(x: float, a: float, b: float, c: float) -> float;
454         fn a_mf_lins(x: float, a: float, b: float) -> float;
455         fn a_mf_linz(x: float, a: float, b: float) -> float;
456         fn a_mf_s(x: float, a: float, b: float) -> float;
457         fn a_mf_z(x: float, a: float, b: float) -> float;
458         fn a_mf_pi(x: float, a: float, b: float, c: float, d: float) -> float;
459     }
461     /// gaussian membership function
462     #[inline(always)]
463     pub fn gauss(x: float, sigma: float, c: float) -> float {
464         unsafe { a_mf_gauss(x, sigma, c) }
465     }
466     /// gaussian combination membership function
467     #[inline(always)]
468     pub fn gauss2(x: float, sigma1: float, c1: float, sigma2: float, c2: float) -> float {
469         unsafe { a_mf_gauss2(x, sigma1, c1, sigma2, c2) }
470     }
471     /// generalized bell-shaped membership function
472     #[inline(always)]
473     pub fn gbell(x: float, a: float, b: float, c: float) -> float {
474         unsafe { a_mf_gbell(x, a, b, c) }
475     }
476     /// sigmoidal membership function
477     #[inline(always)]
478     pub fn sig(x: float, a: float, c: float) -> float {
479         unsafe { a_mf_sig(x, a, c) }
480     }
481     /// difference between two sigmoidal membership functions
482     #[inline(always)]
483     pub fn dsig(x: float, a1: float, c1: float, a2: float, c2: float) -> float {
484         unsafe { a_mf_dsig(x, a1, c1, a2, c2) }
485     }
486     /// product of two sigmoidal membership functions
487     #[inline(always)]
488     pub fn psig(x: float, a1: float, c1: float, a2: float, c2: float) -> float {
489         unsafe { a_mf_psig(x, a1, c1, a2, c2) }
490     }
491     /// trapezoidal membership function
492     #[inline(always)]
493     pub fn trap(x: float, a: float, b: float, c: float, d: float) -> float {
494         unsafe { a_mf_trap(x, a, b, c, d) }
495     }
496     /// triangular membership function
497     #[inline(always)]
498     pub fn tri(x: float, a: float, b: float, c: float) -> float {
499         unsafe { a_mf_tri(x, a, b, c) }
500     }
501     /// linear s-shaped saturation membership function
502     #[inline(always)]
503     pub fn lins(x: float, a: float, b: float) -> float {
504         unsafe { a_mf_lins(x, a, b) }
505     }
506     /// linear z-shaped saturation membership function
507     #[inline(always)]
508     pub fn linz(x: float, a: float, b: float) -> float {
509         unsafe { a_mf_linz(x, a, b) }
510     }
511     /// s-shaped membership function
512     #[inline(always)]
513     pub fn s(x: float, a: float, b: float) -> float {
514         unsafe { a_mf_s(x, a, b) }
515     }
516     /// z-shaped membership function
517     #[inline(always)]
518     pub fn z(x: float, a: float, b: float) -> float {
519         unsafe { a_mf_z(x, a, b) }
520     }
521     /// pi-shaped membership function
522     #[inline(always)]
523     pub fn pi(x: float, a: float, b: float, c: float, d: float) -> float {
524         unsafe { a_mf_pi(x, a, b, c, d) }
525     }
528 /// proportional integral derivative controller
529 #[repr(C)]
530 pub struct pid {
531     /// proportional constant
532     pub kp: float,
533     /// integral constant
534     pub ki: float,
535     /// derivative constant
536     pub kd: float,
537     /// maximum integral output
538     pub summax: float,
539     /// minimum integral output
540     pub summin: float,
541     /// controller integral output
542     pub sum: float,
543     /// maximum final output
544     pub outmax: float,
545     /// minimum final output
546     pub outmin: float,
547     /// controller final output
548     pub out: float,
549     /// cache variable
550     var: float,
551     /// cache feedback
552     pub fdb: float,
553     /// cache error
554     pub err: float,
557 impl Default for pid {
558     #[inline(always)]
559     fn default() -> Self {
560         Self {
561             kp: 0.0,
562             ki: 0.0,
563             kd: 0.0,
564             summax: float::INFINITY,
565             summin: -float::INFINITY,
566             sum: 0.0,
567             outmax: float::INFINITY,
568             outmin: -float::INFINITY,
569             out: 0.0,
570             var: 0.0,
571             fdb: 0.0,
572             err: 0.0,
573         }
574     }
577 extern "C" {
578     fn a_pid_set_kpid(ctx: *mut pid, kp: float, ki: float, kd: float);
579     fn a_pid_run(ctx: *mut pid, set: float, fdb: float) -> float;
580     fn a_pid_pos(ctx: *mut pid, set: float, fdb: float) -> float;
581     fn a_pid_inc(ctx: *mut pid, set: float, fdb: float) -> float;
582     fn a_pid_zero(ctx: *mut pid);
585 impl pid {
586     /// initialize for PID controller
587     #[inline(always)]
588     pub fn new() -> Self {
589         Self::default()
590     }
591     /// set proportional integral derivative constant for PID controller
592     #[inline(always)]
593     pub fn set_kpid(&mut self, kp: float, ki: float, kd: float) -> &mut Self {
594         unsafe { a_pid_set_kpid(self, kp, ki, kd) };
595         self
596     }
597     /// calculate for PID controller
598     #[inline(always)]
599     pub fn run(&mut self, set: float, fdb: float) -> float {
600         unsafe { a_pid_run(self, set, fdb) }
601     }
602     /// calculate for positional PID controller
603     #[inline(always)]
604     pub fn pos(&mut self, set: float, fdb: float) -> float {
605         unsafe { a_pid_pos(self, set, fdb) }
606     }
607     /// calculate for incremental PID controller
608     #[inline(always)]
609     pub fn inc(&mut self, set: float, fdb: float) -> float {
610         unsafe { a_pid_inc(self, set, fdb) }
611     }
612     /// zeroing for PID controller
613     #[inline(always)]
614     pub fn zero(&mut self) -> &mut Self {
615         unsafe { a_pid_zero(self) };
616         self
617     }
620 /// fuzzy PID controller operator
621 pub mod fuzzy {
622     use crate::c_uint;
623     /// min(a,b)
624     pub const CAP: c_uint = 1;
625     /// a*b
626     pub const CAP_ALGEBRA: c_uint = 2;
627     /// max(a+b-1,0)
628     pub const CAP_BOUNDED: c_uint = 3;
629     /// max(a,b)
630     pub const CUP: c_uint = 4;
631     /// a+b-a*b
632     pub const CUP_ALGEBRA: c_uint = 5;
633     /// min(a+b,1)
634     pub const CUP_BOUNDED: c_uint = 6;
635     /// sqrt(a,b)*sqrt(1-(1-a)*(1-b))
636     pub const EQU: c_uint = 0;
639 /// fuzzy proportional integral derivative controller
640 #[repr(C)]
641 pub struct pid_fuzzy {
642     /// proportional integral derivative controller
643     pub pid: pid,
644     me: *const float,
645     mec: *const float,
646     mkp: *const float,
647     mki: *const float,
648     mkd: *const float,
649     idx: *mut c_uint,
650     val: *mut float,
651     /// fuzzy relational operator
652     opr: extern "C" fn(float, float) -> float,
653     /// base proportional constant
654     pub kp: float,
655     /// base integral constant
656     pub ki: float,
657     /// base derivative constant
658     pub kd: float,
659     /// number of order in the square matrix
660     nrule: c_uint,
661     /// maximum number triggered by the rule
662     nfuzz: c_uint,
665 impl Default for pid_fuzzy {
666     #[inline(always)]
667     fn default() -> Self {
668         Self {
669             pid: pid::default(),
670             me: null(),
671             mec: null(),
672             mkp: null(),
673             mki: null(),
674             mkd: null(),
675             idx: null_mut(),
676             val: null_mut(),
677             opr: unsafe { a_pid_fuzzy_opr(fuzzy::EQU) },
678             kp: 0.0,
679             ki: 0.0,
680             kd: 0.0,
681             nrule: 0,
682             nfuzz: 0,
683         }
684     }
687 extern "C" {
688     fn a_pid_fuzzy_opr(opr: c_uint) -> extern "C" fn(float, float) -> float;
689     fn a_pid_fuzzy_set_opr(ctx: *mut pid_fuzzy, opr: c_uint);
690     fn a_pid_fuzzy_bfuzz(ctx: *const pid_fuzzy) -> *mut u8;
691     fn a_pid_fuzzy_set_bfuzz(ctx: *mut pid_fuzzy, ptr: *mut u8, num: usize);
692     fn a_pid_fuzzy_set_rule(
693         ctx: *mut pid_fuzzy,
694         num: c_uint,
695         me: *const float,
696         mec: *const float,
697         mkp: *const float,
698         mki: *const float,
699         mkd: *const float,
700     );
701     fn a_pid_fuzzy_set_kpid(ctx: *mut pid_fuzzy, kp: float, ki: float, kd: float);
702     fn a_pid_fuzzy_run(ctx: *mut pid_fuzzy, set: float, fdb: float) -> float;
703     fn a_pid_fuzzy_pos(ctx: *mut pid_fuzzy, set: float, fdb: float) -> float;
704     fn a_pid_fuzzy_inc(ctx: *mut pid_fuzzy, set: float, fdb: float) -> float;
705     fn a_pid_fuzzy_zero(ctx: *mut pid_fuzzy);
708 impl pid_fuzzy {
709     /// initialize for fuzzy PID controller
710     #[inline(always)]
711     pub fn new() -> Self {
712         Self::default()
713     }
714     /// set fuzzy relational operator for fuzzy PID controller
715     #[inline(always)]
716     pub fn set_opr(&mut self, opr: c_uint) -> &mut Self {
717         unsafe { a_pid_fuzzy_set_opr(self, opr) };
718         self
719     }
720     /// compute size of memory block for fuzzy PID controller
721     #[inline(always)]
722     #[allow(non_snake_case)]
723     pub const fn BFUZZ(n: usize) -> usize {
724         size_of::<c_uint>() * n * 2 + size_of::<float>() * n * (2 + n)
725     }
726     /// get memory block for fuzzy PID controller
727     #[inline(always)]
728     pub fn bfuzz(&mut self) -> &mut [u8] {
729         unsafe { from_raw_parts_mut(a_pid_fuzzy_bfuzz(self), Self::BFUZZ(self.nfuzz as usize)) }
730     }
731     /// set memory block for fuzzy PID controller
732     #[inline(always)]
733     pub fn set_bfuzz(&mut self, ptr: &mut [u8], num: usize) -> &mut Self {
734         unsafe { a_pid_fuzzy_set_bfuzz(self, ptr.as_mut_ptr(), num) };
735         self
736     }
737     /// set rule base for fuzzy PID controller
738     #[inline(always)]
739     pub fn set_rule(
740         &mut self,
741         col: usize,
742         me: &[float],
743         mec: &[float],
744         mkp: &[float],
745         mki: &[float],
746         mkd: &[float],
747     ) -> &mut Self {
748         unsafe {
749             a_pid_fuzzy_set_rule(
750                 self,
751                 col as c_uint,
752                 me.as_ptr(),
753                 mec.as_ptr(),
754                 mkp.as_ptr(),
755                 mki.as_ptr(),
756                 mkd.as_ptr(),
757             )
758         };
759         self
760     }
761     /// set proportional integral derivative constant for fuzzy PID controller
762     #[inline(always)]
763     pub fn set_kpid(&mut self, kp: float, ki: float, kd: float) -> &mut Self {
764         unsafe { a_pid_fuzzy_set_kpid(self, kp, ki, kd) };
765         self
766     }
767     /// calculate for fuzzy PID controller
768     #[inline(always)]
769     pub fn run(&mut self, set: float, fdb: float) -> float {
770         unsafe { a_pid_fuzzy_run(self, set, fdb) }
771     }
772     /// calculate for positional fuzzy PID controller
773     #[inline(always)]
774     pub fn pos(&mut self, set: float, fdb: float) -> float {
775         unsafe { a_pid_fuzzy_pos(self, set, fdb) }
776     }
777     /// calculate for incremental fuzzy PID controller
778     #[inline(always)]
779     pub fn inc(&mut self, set: float, fdb: float) -> float {
780         unsafe { a_pid_fuzzy_inc(self, set, fdb) }
781     }
782     /// zeroing for fuzzy PID controller
783     #[inline(always)]
784     pub fn zero(&mut self) -> &mut Self {
785         unsafe { a_pid_fuzzy_zero(self) };
786         self
787     }
790 /// single neuron proportional integral derivative controller
791 #[repr(C)]
792 pub struct pid_neuro {
793     /// proportional integral derivative controller
794     pub pid: pid,
795     /// proportional coefficient
796     pub k: float,
797     /// proportional weight
798     pub wp: float,
799     /// integral weight
800     pub wi: float,
801     /// derivative weight
802     pub wd: float,
803     /// error change
804     pub ec: float,
807 impl Default for pid_neuro {
808     #[inline(always)]
809     fn default() -> Self {
810         Self {
811             pid: pid::default(),
812             k: 0.0,
813             wp: 0.0,
814             wi: 0.0,
815             wd: 0.0,
816             ec: 0.0,
817         }
818     }
821 extern "C" {
822     fn a_pid_neuro_set_kpid(ctx: *mut pid_neuro, k: float, kp: float, ki: float, kd: float);
823     fn a_pid_neuro_set_wpid(ctx: *mut pid_neuro, wp: float, wi: float, wd: float);
824     fn a_pid_neuro_run(ctx: *mut pid_neuro, set: float, fdb: float) -> float;
825     fn a_pid_neuro_inc(ctx: *mut pid_neuro, set: float, fdb: float) -> float;
826     fn a_pid_neuro_zero(ctx: *mut pid_neuro);
829 impl pid_neuro {
830     /// initialize for single neuron PID controller
831     #[inline(always)]
832     pub fn new() -> Self {
833         Self::default()
834     }
835     /// set proportional integral derivative constant for single neuron PID controller
836     #[inline(always)]
837     pub fn set_kpid(&mut self, k: float, kp: float, ki: float, kd: float) -> &mut Self {
838         unsafe { a_pid_neuro_set_kpid(self, k, kp, ki, kd) };
839         self
840     }
841     /// set proportional integral derivative weight for single neuron PID controller
842     #[inline(always)]
843     pub fn set_wpid(&mut self, wp: float, wi: float, wd: float) -> &mut Self {
844         unsafe { a_pid_neuro_set_wpid(self, wp, wi, wd) };
845         self
846     }
847     /// calculate for single neuron PID controller
848     #[inline(always)]
849     pub fn run(&mut self, set: float, fdb: float) -> float {
850         unsafe { a_pid_neuro_run(self, set, fdb) }
851     }
852     /// calculate for incremental single neuron PID controller
853     #[inline(always)]
854     pub fn inc(&mut self, set: float, fdb: float) -> float {
855         unsafe { a_pid_neuro_inc(self, set, fdb) }
856     }
857     /// zeroing for single neuron PID controller
858     #[inline(always)]
859     pub fn zero(&mut self) -> &mut Self {
860         unsafe { a_pid_neuro_zero(self) };
861         self
862     }
865 /// transfer function
866 #[repr(C)]
867 pub struct tf {
868     /// input
869     input: *mut float,
870     /// output
871     output: *mut float,
872     /// numerator
873     num_p: *const float,
874     /// denominator
875     den_p: *const float,
876     /// numerator number
877     num_n: c_uint,
878     /// denominator number
879     den_n: c_uint,
882 extern "C" {
883     fn a_tf_set_num(ctx: *mut tf, num_n: c_uint, num_p: *const float, input: *mut float);
884     fn a_tf_set_den(ctx: *mut tf, den_n: c_uint, den_p: *const float, output: *mut float);
885     fn a_tf_init(
886         ctx: *mut tf,
887         num_n: c_uint,
888         num_p: *const float,
889         input: *mut float,
890         den_n: c_uint,
891         den_p: *const float,
892         output: *mut float,
893     );
894     fn a_tf_iter(ctx: *const tf, x: float) -> float;
895     fn a_tf_zero(ctx: *const tf);
898 impl tf {
899     /// initialize for transfer function
900     #[inline(always)]
901     pub fn new(num: &[float], input: &mut [float], den: &[float], output: &mut [float]) -> Self {
902         let mut ctx: Self = Self {
903             input: null_mut(),
904             output: null_mut(),
905             num_p: null(),
906             den_p: null(),
907             num_n: 0,
908             den_n: 0,
909         };
910         unsafe {
911             a_tf_init(
912                 &mut ctx,
913                 num.len() as c_uint,
914                 num.as_ptr(),
915                 input.as_mut_ptr(),
916                 den.len() as c_uint,
917                 den.as_ptr(),
918                 output.as_mut_ptr(),
919             )
920         };
921         ctx
922     }
923     /// calculate for transfer function
924     #[inline(always)]
925     pub fn iter(&mut self, x: float) -> float {
926         unsafe { a_tf_iter(self, x) }
927     }
928     /// zeroing for transfer function
929     #[inline(always)]
930     pub fn zero(&mut self) -> &mut Self {
931         unsafe { a_tf_zero(self) };
932         self
933     }
934     /// get input for transfer function
935     #[inline(always)]
936     pub fn input(&self) -> &[float] {
937         unsafe { from_raw_parts(self.input, self.num_n as usize) }
938     }
939     /// get numerator for transfer function
940     #[inline(always)]
941     pub fn num(&self) -> &[float] {
942         unsafe { from_raw_parts(self.num_p, self.num_n as usize) }
943     }
944     /// set numerator for transfer function
945     #[inline(always)]
946     pub fn set_num(&mut self, num: &[float], input: &mut [float]) -> &mut Self {
947         unsafe { a_tf_set_num(self, num.len() as c_uint, num.as_ptr(), input.as_mut_ptr()) };
948         self
949     }
950     /// get output for transfer function
951     #[inline(always)]
952     pub fn output(&self) -> &[float] {
953         unsafe { from_raw_parts(self.output, self.den_n as usize) }
954     }
955     /// get denominator for transfer function
956     #[inline(always)]
957     pub fn den(&self) -> &[float] {
958         unsafe { from_raw_parts(self.den_p, self.den_n as usize) }
959     }
960     /// set denominator for transfer function
961     #[inline(always)]
962     pub fn set_den(&mut self, den: &[float], output: &mut [float]) -> &mut Self {
963         unsafe { a_tf_set_den(self, den.len() as c_uint, den.as_ptr(), output.as_mut_ptr()) };
964         self
965     }
968 /// bell-shaped velocity trajectory
969 #[repr(C)]
970 pub struct trajbell {
971     /// total duration
972     pub t: float,
973     /// constant velocity phase
974     pub tv: float,
975     /// acceleration phase
976     pub ta: float,
977     /// deceleration phase
978     pub td: float,
979     /// time-interval in which the jerk is constant (j max or j min ) during the acceleration phase
980     pub taj: float,
981     /// time-interval in which the jerk is constant (j max or j min ) during the deceleration phase
982     pub tdj: float,
983     /// initial position
984     pub p0: float,
985     /// final position
986     pub p1: float,
987     /// initial velocity
988     pub v0: float,
989     /// final velocity
990     pub v1: float,
991     /// maximum velocity
992     pub vm: float,
993     /// maximum jerk
994     pub jm: float,
995     /// maximum acceleration
996     pub am: float,
997     /// maximum deceleration
998     pub dm: float,
1001 impl Default for trajbell {
1002     #[inline(always)]
1003     fn default() -> Self {
1004         Self {
1005             t: 0.0,
1006             tv: 0.0,
1007             ta: 0.0,
1008             td: 0.0,
1009             taj: 0.0,
1010             tdj: 0.0,
1011             p0: 0.0,
1012             p1: 0.0,
1013             v0: 0.0,
1014             v1: 0.0,
1015             vm: 0.0,
1016             jm: 0.0,
1017             am: 0.0,
1018             dm: 0.0,
1019         }
1020     }
1023 extern "C" {
1024     fn a_trajbell_gen(
1025         ctx: *mut trajbell,
1026         jm: float,
1027         am: float,
1028         vm: float,
1029         p0: float,
1030         p1: float,
1031         v0: float,
1032         v1: float,
1033     ) -> float;
1034     fn a_trajbell_pos(ctx: *const trajbell, x: float) -> float;
1035     fn a_trajbell_vel(ctx: *const trajbell, x: float) -> float;
1036     fn a_trajbell_acc(ctx: *const trajbell, x: float) -> float;
1037     fn a_trajbell_jer(ctx: *const trajbell, x: float) -> float;
1040 impl trajbell {
1041     /// initialize for bell-shaped velocity trajectory
1042     #[inline(always)]
1043     pub fn new() -> Self {
1044         Self::default()
1045     }
1046     /// generate for bell-shaped velocity trajectory
1047     #[allow(clippy::too_many_arguments)]
1048     #[inline(always)]
1049     pub fn gen(
1050         &mut self,
1051         jm: float,
1052         am: float,
1053         vm: float,
1054         p0: float,
1055         p1: float,
1056         v0: float,
1057         v1: float,
1058     ) -> float {
1059         unsafe { a_trajbell_gen(self, jm, am, vm, p0, p1, v0, v1) }
1060     }
1061     /// calculate position for bell-shaped velocity trajectory
1062     #[inline(always)]
1063     pub fn pos(&mut self, x: float) -> float {
1064         unsafe { a_trajbell_pos(self, x) }
1065     }
1066     /// calculate velocity for bell-shaped velocity trajectory
1067     #[inline(always)]
1068     pub fn vel(&mut self, x: float) -> float {
1069         unsafe { a_trajbell_vel(self, x) }
1070     }
1071     /// calculate acceleration for bell-shaped velocity trajectory
1072     #[inline(always)]
1073     pub fn acc(&mut self, x: float) -> float {
1074         unsafe { a_trajbell_acc(self, x) }
1075     }
1076     /// calculate jerk for bell-shaped velocity trajectory
1077     #[inline(always)]
1078     pub fn jer(&mut self, x: float) -> float {
1079         unsafe { a_trajbell_jer(self, x) }
1080     }
1083 /// cubic polynomial trajectory
1084 #[repr(C)]
1085 pub struct trajpoly3 {
1086     /// coefficients of position
1087     pub p: [float; 4],
1088     /// coefficients of velocity
1089     pub v: [float; 3],
1090     /// coefficients of acceleration
1091     pub a: [float; 2],
1094 extern "C" {
1095     fn a_trajpoly3_gen(ctx: *mut trajpoly3, ts: float, p0: float, p1: float, v0: float, v1: float);
1096     fn a_trajpoly3_pos(ctx: *const trajpoly3, x: float) -> float;
1097     fn a_trajpoly3_vel(ctx: *const trajpoly3, x: float) -> float;
1098     fn a_trajpoly3_acc(ctx: *const trajpoly3, x: float) -> float;
1101 impl trajpoly3 {
1102     /// initialize for cubic polynomial trajectory
1103     #[inline(always)]
1104     pub fn new(ts: float, p0: float, p1: float, v0: float, v1: float) -> Self {
1105         let mut ctx: Self = Self {
1106             p: [0.0; 4],
1107             v: [0.0; 3],
1108             a: [0.0; 2],
1109         };
1110         unsafe { a_trajpoly3_gen(&mut ctx, ts, p0, p1, v0, v1) };
1111         ctx
1112     }
1113     /// generate for cubic polynomial trajectory
1114     #[inline(always)]
1115     pub fn gen(&mut self, ts: float, p0: float, p1: float, v0: float, v1: float) -> &mut Self {
1116         unsafe { a_trajpoly3_gen(self, ts, p0, p1, v0, v1) };
1117         self
1118     }
1119     /// calculate position for cubic polynomial trajectory
1120     #[inline(always)]
1121     pub fn pos(&mut self, x: float) -> float {
1122         unsafe { a_trajpoly3_pos(self, x) }
1123     }
1124     /// calculate velocity for cubic polynomial trajectory
1125     #[inline(always)]
1126     pub fn vel(&mut self, x: float) -> float {
1127         unsafe { a_trajpoly3_vel(self, x) }
1128     }
1129     /// calculate acceleration for cubic polynomial trajectory
1130     #[inline(always)]
1131     pub fn acc(&mut self, x: float) -> float {
1132         unsafe { a_trajpoly3_acc(self, x) }
1133     }
1136 /// quintic polynomial trajectory
1137 #[repr(C)]
1138 pub struct trajpoly5 {
1139     /// coefficients of position
1140     pub p: [float; 6],
1141     /// coefficients of velocity
1142     pub v: [float; 5],
1143     /// coefficients of acceleration
1144     pub a: [float; 4],
1147 extern "C" {
1148     fn a_trajpoly5_gen(
1149         ctx: *mut trajpoly5,
1150         ts: float,
1151         p0: float,
1152         p1: float,
1153         v0: float,
1154         v1: float,
1155         a0: float,
1156         a1: float,
1157     );
1158     fn a_trajpoly5_pos(ctx: *const trajpoly5, x: float) -> float;
1159     fn a_trajpoly5_vel(ctx: *const trajpoly5, x: float) -> float;
1160     fn a_trajpoly5_acc(ctx: *const trajpoly5, x: float) -> float;
1163 impl trajpoly5 {
1164     /// initialize for quintic polynomial trajectory
1165     #[allow(clippy::too_many_arguments)]
1166     #[inline(always)]
1167     pub fn new(
1168         ts: float,
1169         p0: float,
1170         p1: float,
1171         v0: float,
1172         v1: float,
1173         a0: float,
1174         a1: float,
1175     ) -> Self {
1176         let mut ctx: Self = Self {
1177             p: [0.0; 6],
1178             v: [0.0; 5],
1179             a: [0.0; 4],
1180         };
1181         unsafe { a_trajpoly5_gen(&mut ctx, ts, p0, p1, v0, v1, a0, a1) };
1182         ctx
1183     }
1184     /// generate for quintic polynomial trajectory
1185     #[allow(clippy::too_many_arguments)]
1186     #[inline(always)]
1187     pub fn gen(
1188         &mut self,
1189         ts: float,
1190         p0: float,
1191         p1: float,
1192         v0: float,
1193         v1: float,
1194         a0: float,
1195         a1: float,
1196     ) -> &mut Self {
1197         unsafe { a_trajpoly5_gen(self, ts, p0, p1, v0, v1, a0, a1) };
1198         self
1199     }
1200     /// calculate position for quintic polynomial trajectory
1201     #[inline(always)]
1202     pub fn pos(&mut self, x: float) -> float {
1203         unsafe { a_trajpoly5_pos(self, x) }
1204     }
1205     /// calculate velocity for quintic polynomial trajectory
1206     #[inline(always)]
1207     pub fn vel(&mut self, x: float) -> float {
1208         unsafe { a_trajpoly5_vel(self, x) }
1209     }
1210     /// calculate acceleration for quintic polynomial trajectory
1211     #[inline(always)]
1212     pub fn acc(&mut self, x: float) -> float {
1213         unsafe { a_trajpoly5_acc(self, x) }
1214     }
1217 /// hepta polynomial trajectory
1218 #[repr(C)]
1219 pub struct trajpoly7 {
1220     /// coefficients of position
1221     pub p: [float; 8],
1222     /// coefficients of velocity
1223     pub v: [float; 7],
1224     /// coefficients of acceleration
1225     pub a: [float; 6],
1226     /// coefficients of jerk
1227     pub j: [float; 5],
1230 extern "C" {
1231     fn a_trajpoly7_gen(
1232         ctx: *mut trajpoly7,
1233         ts: float,
1234         p0: float,
1235         p1: float,
1236         v0: float,
1237         v1: float,
1238         a0: float,
1239         a1: float,
1240         j0: float,
1241         j1: float,
1242     );
1243     fn a_trajpoly7_pos(ctx: *const trajpoly7, x: float) -> float;
1244     fn a_trajpoly7_vel(ctx: *const trajpoly7, x: float) -> float;
1245     fn a_trajpoly7_acc(ctx: *const trajpoly7, x: float) -> float;
1246     fn a_trajpoly7_jer(ctx: *const trajpoly7, x: float) -> float;
1249 impl trajpoly7 {
1250     /// initialize for hepta polynomial trajectory
1251     #[allow(clippy::too_many_arguments)]
1252     #[inline(always)]
1253     pub fn new(
1254         ts: float,
1255         p0: float,
1256         p1: float,
1257         v0: float,
1258         v1: float,
1259         a0: float,
1260         a1: float,
1261         j0: float,
1262         j1: float,
1263     ) -> Self {
1264         let mut ctx: Self = Self {
1265             p: [0.0; 8],
1266             v: [0.0; 7],
1267             a: [0.0; 6],
1268             j: [0.0; 5],
1269         };
1270         unsafe { a_trajpoly7_gen(&mut ctx, ts, p0, p1, v0, v1, a0, a1, j0, j1) };
1271         ctx
1272     }
1273     /// generate for hepta polynomial trajectory
1274     #[allow(clippy::too_many_arguments)]
1275     #[inline(always)]
1276     pub fn gen(
1277         &mut self,
1278         ts: float,
1279         p0: float,
1280         p1: float,
1281         v0: float,
1282         v1: float,
1283         a0: float,
1284         a1: float,
1285         j0: float,
1286         j1: float,
1287     ) -> &mut Self {
1288         unsafe { a_trajpoly7_gen(self, ts, p0, p1, v0, v1, a0, a1, j0, j1) };
1289         self
1290     }
1291     /// calculate position for hepta polynomial trajectory
1292     #[inline(always)]
1293     pub fn pos(&mut self, x: float) -> float {
1294         unsafe { a_trajpoly7_pos(self, x) }
1295     }
1296     /// calculate velocity for hepta polynomial trajectory
1297     #[inline(always)]
1298     pub fn vel(&mut self, x: float) -> float {
1299         unsafe { a_trajpoly7_vel(self, x) }
1300     }
1301     /// calculate acceleration for hepta polynomial trajectory
1302     #[inline(always)]
1303     pub fn acc(&mut self, x: float) -> float {
1304         unsafe { a_trajpoly7_acc(self, x) }
1305     }
1306     /// calculate jerk for hepta polynomial trajectory
1307     #[inline(always)]
1308     pub fn jer(&mut self, x: float) -> float {
1309         unsafe { a_trajpoly7_jer(self, x) }
1310     }
1313 /// trapezoidal velocity trajectory
1314 #[repr(C)]
1315 pub struct trajtrap {
1316     /// total duration
1317     pub t: float,
1318     /// initial position
1319     pub p0: float,
1320     /// final position
1321     pub p1: float,
1322     /// initial velocity
1323     pub v0: float,
1324     /// final velocity
1325     pub v1: float,
1326     /// constant velocity
1327     pub vc: float,
1328     /// time before constant velocity
1329     pub ta: float,
1330     /// time after constant velocity
1331     pub td: float,
1332     /// position before constant velocity
1333     pub pa: float,
1334     /// position after constant velocity
1335     pub pd: float,
1336     /// acceleration before constant velocity
1337     pub ac: float,
1338     /// acceleration after constant velocity
1339     pub de: float,
1342 impl Default for trajtrap {
1343     #[inline(always)]
1344     fn default() -> Self {
1345         Self {
1346             t: 0.0,
1347             p0: 0.0,
1348             p1: 0.0,
1349             v0: 0.0,
1350             v1: 0.0,
1351             vc: 0.0,
1352             ta: 0.0,
1353             td: 0.0,
1354             pa: 0.0,
1355             pd: 0.0,
1356             ac: 0.0,
1357             de: 0.0,
1358         }
1359     }
1362 extern "C" {
1363     fn a_trajtrap_gen(
1364         ctx: *mut trajtrap,
1365         vm: float,
1366         ac: float,
1367         de: float,
1368         p0: float,
1369         p1: float,
1370         v0: float,
1371         v1: float,
1372     ) -> float;
1373     fn a_trajtrap_pos(ctx: *const trajtrap, x: float) -> float;
1374     fn a_trajtrap_vel(ctx: *const trajtrap, x: float) -> float;
1375     fn a_trajtrap_acc(ctx: *const trajtrap, x: float) -> float;
1378 impl trajtrap {
1379     /// initialize for trapezoidal velocity trajectory
1380     #[inline(always)]
1381     pub fn new() -> Self {
1382         Self::default()
1383     }
1384     /// generate for trapezoidal velocity trajectory
1385     #[allow(clippy::too_many_arguments)]
1386     #[inline(always)]
1387     pub fn gen(
1388         &mut self,
1389         vm: float,
1390         ac: float,
1391         de: float,
1392         p0: float,
1393         p1: float,
1394         v0: float,
1395         v1: float,
1396     ) -> float {
1397         unsafe { a_trajtrap_gen(self, vm, ac, de, p0, p1, v0, v1) }
1398     }
1399     /// calculate position for trapezoidal velocity trajectory
1400     #[inline(always)]
1401     pub fn pos(&mut self, x: float) -> float {
1402         unsafe { a_trajtrap_pos(self, x) }
1403     }
1404     /// calculate velocity for trapezoidal velocity trajectory
1405     #[inline(always)]
1406     pub fn vel(&mut self, x: float) -> float {
1407         unsafe { a_trajtrap_vel(self, x) }
1408     }
1409     /// calculate acceleration for trapezoidal velocity trajectory
1410     #[inline(always)]
1411     pub fn acc(&mut self, x: float) -> float {
1412         unsafe { a_trajtrap_acc(self, x) }
1413     }
1416 /// version
1417 #[repr(C)]
1418 pub struct version {
1419     /// major number
1420     pub major: c_uint,
1421     /// minor number
1422     pub minor: c_uint,
1423     /// third number
1424     pub third: c_uint,
1425     /// extra number
1426     pub extra: c_uint,
1427     /// alphabet
1428     pub alpha: [u8; 4],
1431 impl Default for version {
1432     #[inline(always)]
1433     fn default() -> Self {
1434         Self {
1435             major: 0,
1436             minor: 0,
1437             third: 0,
1438             extra: 0,
1439             alpha: [b'.', 0, 0, 0],
1440         }
1441     }
1444 extern "C" {
1445     static a_version_major: c_uint;
1446     static a_version_minor: c_uint;
1447     static a_version_patch: c_uint;
1448     static a_version_tweak: u32;
1449     fn a_version_set_alpha(ctx: *mut version, alpha: *const u8);
1450     fn a_version_alpha(ctx: *const version, alpha: &mut [u8; 5]);
1451     fn a_version_parse(ctx: *mut version, ver: *const u8) -> c_uint;
1452     fn a_version_tostr(ctx: *const version, p: *mut u8, n: usize) -> c_int;
1453     fn a_version_cmp(ctx: *const version, rhs: *const version) -> c_int;
1454     fn a_version_lt(ctx: *const version, rhs: *const version) -> bool;
1455     fn a_version_gt(ctx: *const version, rhs: *const version) -> bool;
1456     fn a_version_le(ctx: *const version, rhs: *const version) -> bool;
1457     fn a_version_ge(ctx: *const version, rhs: *const version) -> bool;
1458     fn a_version_eq(ctx: *const version, rhs: *const version) -> bool;
1459     fn a_version_check(major: c_uint, minor: c_uint, patch: c_uint) -> c_int;
1462 impl version {
1463     /// initialize for version
1464     #[inline(always)]
1465     pub fn new(major: c_uint, minor: c_uint, third: c_uint) -> Self {
1466         Self {
1467             major,
1468             minor,
1469             third,
1470             ..Default::default()
1471         }
1472     }
1473     /// set alphabet for version
1474     #[inline(always)]
1475     pub fn set_alpha(&mut self, alpha: &[u8]) {
1476         unsafe { a_version_set_alpha(self, alpha.as_ptr()) }
1477     }
1478     /// get alphabet for version
1479     #[inline(always)]
1480     pub fn alpha(&self, alpha: &mut [u8; 5]) {
1481         unsafe { a_version_alpha(self, alpha) }
1482     }
1483     /// parse version string to version
1484     #[inline(always)]
1485     pub fn parse(&mut self, ver: &str) -> c_uint {
1486         unsafe { a_version_parse(self, ver.as_ptr()) }
1487     }
1488     /// convert version to string
1489     #[inline(always)]
1490     pub fn tostr(&mut self, ver: &mut [u8]) -> c_int {
1491         unsafe { a_version_tostr(self, ver.as_mut_ptr(), ver.len()) }
1492     }
1493     /// algorithm library version check
1494     #[inline(always)]
1495     pub fn check(major: c_uint, minor: c_uint, patch: c_uint) -> c_int {
1496         unsafe { a_version_check(major, minor, patch) }
1497     }
1498     /// algorithm library version major
1499     #[inline(always)]
1500     pub fn major() -> c_uint {
1501         unsafe { a_version_major }
1502     }
1503     /// algorithm library version minor
1504     #[inline(always)]
1505     pub fn minor() -> c_uint {
1506         unsafe { a_version_minor }
1507     }
1508     /// algorithm library version patch
1509     #[inline(always)]
1510     pub fn patch() -> c_uint {
1511         unsafe { a_version_patch }
1512     }
1513     /// algorithm library version tweak
1514     #[inline(always)]
1515     pub fn tweak() -> u32 {
1516         unsafe { a_version_tweak }
1517     }
1520 impl PartialOrd for version {
1521     #[inline(always)]
1522     fn partial_cmp(&self, other: &version) -> Option<Ordering> {
1523         let ok: c_int = unsafe { a_version_cmp(self, other) };
1524         if ok > 0 {
1525             return Some(Ordering::Greater);
1526         }
1527         if ok < 0 {
1528             return Some(Ordering::Less);
1529         }
1530         Some(Ordering::Equal)
1531     }
1532     #[inline(always)]
1533     fn lt(&self, other: &version) -> bool {
1534         unsafe { a_version_lt(self, other) }
1535     }
1536     #[inline(always)]
1537     fn gt(&self, other: &version) -> bool {
1538         unsafe { a_version_gt(self, other) }
1539     }
1540     #[inline(always)]
1541     fn le(&self, other: &version) -> bool {
1542         unsafe { a_version_le(self, other) }
1543     }
1544     #[inline(always)]
1545     fn ge(&self, other: &version) -> bool {
1546         unsafe { a_version_ge(self, other) }
1547     }
1550 impl PartialEq for version {
1551     #[inline(always)]
1552     fn eq(&self, other: &version) -> bool {
1553         unsafe { a_version_eq(self, other) }
1554     }