2 An algorithm library based on C/C++
6 Add this to your `Cargo.toml`:
14 #![warn(missing_docs)]
15 #![allow(non_camel_case_types)]
16 #![cfg_attr(not(features = "std"), no_std)]
18 /// Equivalent to C's int type.
19 pub type int = core::ffi::c_int;
20 /// Equivalent to C's unsigned int type.
21 pub type uint = core::ffi::c_uint;
22 /// floating-point number stored using `f64`
23 #[cfg(not(feature = "float"))]
25 /// floating-point number stored using `f32`
26 #[cfg(feature = "float")]
30 fn a_u32_sqrt(x: u32) -> u16;
31 fn a_u64_sqrt(x: u64) -> u32;
34 /// square root of an unsigned integer
36 pub fn u32_sqrt(x: u32) -> u16 {
37 unsafe { a_u32_sqrt(x) }
39 /// square root of an unsigned integer
41 pub fn u64_sqrt(x: u64) -> u32 {
42 unsafe { a_u64_sqrt(x) }
46 fn a_f32_rsqrt(x: f32) -> f32;
47 fn a_f64_rsqrt(x: f64) -> f64;
50 /// reciprocal of square-root, `\frac{1}{\sqrt{x}}`
52 pub fn f32_rsqrt(x: f32) -> f32 {
53 unsafe { a_f32_rsqrt(x) }
55 /// reciprocal of square-root, `\frac{1}{\sqrt{x}}`
57 pub fn f64_rsqrt(x: f64) -> f64 {
58 unsafe { a_f64_rsqrt(x) }
62 fn a_hash_bkdr_(pdata: *const u8, nbyte: usize, value: u32) -> u32;
63 fn a_hash_sdbm_(pdata: *const u8, nbyte: usize, value: u32) -> u32;
66 /// a hash function whose prime number is 131
68 pub fn hash_bkdr(block: &[u8], value: u32) -> u32 {
69 unsafe { a_hash_bkdr_(block.as_ptr(), block.len(), value) }
71 /// a hash function whose prime number is 65599
73 pub fn hash_sdbm(block: &[u8], value: u32) -> u32 {
74 unsafe { a_hash_sdbm_(block.as_ptr(), block.len(), value) }
81 std::println!("{}", crate::u32_sqrt(u32::MAX));
82 std::println!("{}", crate::u64_sqrt(u64::MAX));
86 std::println!("1/sqrt({})={}", 4, crate::f32_rsqrt(4.0));
87 std::println!("1/sqrt({})={}", 4, crate::f64_rsqrt(4.0));
91 let text: [u8; 10] = *b"0123456789";
92 std::println!("{}", crate::hash_bkdr(&text, 0));
93 std::println!("{}", crate::hash_sdbm(&text, 0));
97 /// Cyclic Redundancy Check for 8 bits
100 /// Cyclic Redundancy Check comparison table
101 pub table: [u8; 0x100],
105 fn a_crc8m_init(table: *mut u8, poly: u8);
106 fn a_crc8l_init(table: *mut u8, poly: u8);
107 fn a_crc8(table: *const u8, pdate: *const u8, nbyte: usize, value: u8) -> u8;
111 /// initialize for MSB CRC-8
113 pub fn new_msb(poly: u8) -> Self {
114 let mut ctx: Self = Self { table: [0; 0x100] };
115 unsafe { a_crc8m_init(ctx.table.as_mut_ptr(), poly) };
118 /// initialize for LSB CRC-8
120 pub fn new_lsb(poly: u8) -> Self {
121 let mut ctx: Self = Self { table: [0; 0x100] };
122 unsafe { a_crc8l_init(ctx.table.as_mut_ptr(), poly) };
125 /// generate for MSB CRC-8
127 pub fn gen_msb(&mut self, poly: u8) -> &mut Self {
128 unsafe { a_crc8m_init(self.table.as_mut_ptr(), poly) };
131 /// generate for LSB CRC-8
133 pub fn gen_lsb(&mut self, poly: u8) -> &mut Self {
134 unsafe { a_crc8l_init(self.table.as_mut_ptr(), poly) };
137 /// calculate for CRC-8
139 pub fn eval(self, block: &[u8], value: u8) -> u8 {
140 unsafe { a_crc8(self.table.as_ptr(), block.as_ptr(), block.len(), value) }
148 let ctx = crate::crc8::new_msb(0x07);
149 assert_eq!(ctx.eval(b"0123456789", 0), 0x45);
152 let ctx = crate::crc8::new_lsb(0x31);
153 assert_eq!(ctx.eval(b"0123456789", 0), 0x75);
157 /// Cyclic Redundancy Check for 16 bits
160 /// Cyclic Redundancy Check comparison table
161 pub table: [u16; 0x100],
162 eval: unsafe extern "C" fn(*const u16, *const u8, usize, u16) -> u16,
166 fn a_crc16m_init(table: *mut u16, poly: u16);
167 fn a_crc16l_init(table: *mut u16, poly: u16);
168 fn a_crc16m(table: *const u16, pdate: *const u8, nbyte: usize, value: u16) -> u16;
169 fn a_crc16l(table: *const u16, pdate: *const u8, nbyte: usize, value: u16) -> u16;
173 /// initialize for MSB CRC-16
175 pub fn new_msb(poly: u16) -> Self {
176 let mut ctx: Self = Self {
180 unsafe { a_crc16m_init(ctx.table.as_mut_ptr(), poly) };
183 /// initialize for LSB CRC-16
185 pub fn new_lsb(poly: u16) -> Self {
186 let mut ctx: Self = Self {
190 unsafe { a_crc16l_init(ctx.table.as_mut_ptr(), poly) };
193 /// generate for MSB CRC-16
195 pub fn gen_msb(&mut self, poly: u16) -> &mut Self {
196 unsafe { a_crc16m_init(self.table.as_mut_ptr(), poly) };
197 self.eval = a_crc16m;
200 /// generate for LSB CRC-16
202 pub fn gen_lsb(&mut self, poly: u16) -> &mut Self {
203 unsafe { a_crc16l_init(self.table.as_mut_ptr(), poly) };
204 self.eval = a_crc16l;
207 /// calculate for CRC-16
209 pub fn eval(self, block: &[u8], value: u16) -> u16 {
210 unsafe { (self.eval)(self.table.as_ptr(), block.as_ptr(), block.len(), value) }
218 let ctx = crate::crc16::new_msb(0x1021);
219 assert_eq!(ctx.eval(b"0123456789", 0), 0x9C58);
222 let ctx = crate::crc16::new_lsb(0x8005);
223 assert_eq!(ctx.eval(b"0123456789", 0), 0x443D);
227 /// Cyclic Redundancy Check for 32 bits
230 /// Cyclic Redundancy Check comparison table
231 pub table: [u32; 0x100],
232 eval: unsafe extern "C" fn(*const u32, *const u8, usize, u32) -> u32,
236 fn a_crc32m_init(table: *mut u32, poly: u32);
237 fn a_crc32l_init(table: *mut u32, poly: u32);
238 fn a_crc32m(table: *const u32, pdate: *const u8, nbyte: usize, value: u32) -> u32;
239 fn a_crc32l(table: *const u32, pdate: *const u8, nbyte: usize, value: u32) -> u32;
243 /// initialize for MSB CRC-32
245 pub fn new_msb(poly: u32) -> Self {
246 let mut ctx: Self = Self {
250 unsafe { a_crc32m_init(ctx.table.as_mut_ptr(), poly) };
253 /// initialize for LSB CRC-32
255 pub fn new_lsb(poly: u32) -> Self {
256 let mut ctx: Self = Self {
260 unsafe { a_crc32l_init(ctx.table.as_mut_ptr(), poly) };
263 /// generate for MSB CRC-32
265 pub fn gen_msb(&mut self, poly: u32) -> &mut Self {
266 unsafe { a_crc32m_init(self.table.as_mut_ptr(), poly) };
267 self.eval = a_crc32m;
270 /// generate for LSB CRC-32
272 pub fn gen_lsb(&mut self, poly: u32) -> &mut Self {
273 unsafe { a_crc32l_init(self.table.as_mut_ptr(), poly) };
274 self.eval = a_crc32l;
277 /// calculate for CRC-32
279 pub fn eval(self, block: &[u8], value: u32) -> u32 {
280 unsafe { (self.eval)(self.table.as_ptr(), block.as_ptr(), block.len(), value) }
288 let ctx = crate::crc32::new_msb(0x1EDC6F41);
289 assert_eq!(ctx.eval(b"0123456789", 0), 0x512B456E);
292 let ctx = crate::crc32::new_lsb(0x04C11DB7);
293 assert_eq!(ctx.eval(b"0123456789", 0), 0x450EAFB0);
297 /// Cyclic Redundancy Check for 64 bits
300 /// Cyclic Redundancy Check comparison table
301 pub table: [u64; 0x100],
302 eval: unsafe extern "C" fn(*const u64, *const u8, usize, u64) -> u64,
306 fn a_crc64m_init(table: *mut u64, poly: u64);
307 fn a_crc64l_init(table: *mut u64, poly: u64);
308 fn a_crc64m(table: *const u64, pdate: *const u8, nbyte: usize, value: u64) -> u64;
309 fn a_crc64l(table: *const u64, pdate: *const u8, nbyte: usize, value: u64) -> u64;
313 /// initialize for MSB CRC-64
315 pub fn new_msb(poly: u64) -> Self {
316 let mut ctx: Self = Self {
320 unsafe { a_crc64m_init(ctx.table.as_mut_ptr(), poly) };
323 /// initialize for LSB CRC-64
325 pub fn new_lsb(poly: u64) -> Self {
326 let mut ctx: Self = Self {
330 unsafe { a_crc64l_init(ctx.table.as_mut_ptr(), poly) };
333 /// generate for MSB CRC-64
335 pub fn gen_msb(&mut self, poly: u64) -> &mut Self {
336 unsafe { a_crc64m_init(self.table.as_mut_ptr(), poly) };
337 self.eval = a_crc64m;
340 /// generate for LSB CRC-64
342 pub fn gen_lsb(&mut self, poly: u64) -> &mut Self {
343 unsafe { a_crc64l_init(self.table.as_mut_ptr(), poly) };
344 self.eval = a_crc64l;
347 /// calculate for CRC-64
349 pub fn eval(self, block: &[u8], value: u64) -> u64 {
350 unsafe { (self.eval)(self.table.as_ptr(), block.as_ptr(), block.len(), value) }
358 let ctx = crate::crc64::new_msb(0x000000000000001B);
359 assert_eq!(ctx.eval(b"0123456789", 0), 0xE4FFBEA588AFC790);
362 let ctx = crate::crc64::new_lsb(0x42F0E1EBA9EA3693);
363 assert_eq!(ctx.eval(b"0123456789", 0), 0xDA60676A5CDE0008);
367 #[allow(clippy::excessive_precision)]
368 const TAU: float = 6.28318530717958647692528676655900577;
373 /// filter coefficient
382 /// initialize for High Pass Filter
384 pub fn new(fc: float, ts: float) -> Self {
386 alpha: 1.0 / (TAU * fc * ts + 1.0),
391 /// generate for High Pass Filter
393 pub fn gen(&mut self, fc: float, ts: float) -> &mut Self {
394 self.alpha = 1.0 / (TAU * fc * ts + 1.0);
397 /// calculate for High Pass Filter
399 pub fn iter(&mut self, x: float) -> float {
400 self.output = self.alpha * (self.output + x - self.input);
404 /// zeroing for High Pass Filter
406 pub fn zero(&mut self) -> &mut Self {
416 let mut a = crate::hpf::new(10.0, 0.01);
417 a.gen(10.0, 0.01).zero().iter(1.0);
420 #[allow(clippy::excessive_precision)]
421 const _1_TAU: float = 0.159154943091895335768883763372514362;
426 /// filter coefficient
433 /// initialize for Low Pass Filter
435 pub fn new(fc: float, ts: float) -> Self {
437 alpha: ts / (_1_TAU / fc + ts),
441 /// generate for Low Pass Filter
443 pub fn gen(&mut self, fc: float, ts: float) -> &mut Self {
444 self.alpha = ts / (_1_TAU / fc + ts);
447 /// calculate for Low Pass Filter
449 pub fn iter(&mut self, x: float) -> float {
450 self.output *= 1.0 - self.alpha;
451 self.output += x * self.alpha;
454 /// zeroing for Low Pass Filter
456 pub fn zero(&mut self) -> &mut Self {
465 let mut a = crate::lpf::new(10.0, 0.01);
466 a.gen(10.0, 0.01).zero().iter(1.0);
469 /// membership function
473 pub const NUL: int = 0;
474 /// gaussian membership function
475 pub const GAUSS: int = 1;
476 /// gaussian combination membership function
477 pub const GAUSS2: int = 2;
478 /// generalized bell-shaped membership function
479 pub const GBELL: int = 3;
480 /// sigmoidal membership function
481 pub const SIG: int = 4;
482 /// difference between two sigmoidal membership functions
483 pub const DSIG: int = 5;
484 /// product of two sigmoidal membership functions
485 pub const PSIG: int = 6;
486 /// trapezoidal membership function
487 pub const TRAP: int = 7;
488 /// triangular membership function
489 pub const TRI: int = 8;
490 /// linear s-shaped saturation membership function
491 pub const LINS: int = 9;
492 /// linear z-shaped saturation membership function
493 pub const LINZ: int = 10;
494 /// s-shaped membership function
495 pub const S: int = 11;
496 /// z-shaped membership function
497 pub const Z: int = 12;
498 /// pi-shaped membership function
499 pub const PI: int = 13;
503 fn a_mf_gauss(x: float, sigma: float, c: float) -> float;
504 fn a_mf_gauss2(x: float, sigma1: float, c1: float, sigma2: float, c2: float) -> float;
505 fn a_mf_gbell(x: float, a: float, b: float, c: float) -> float;
506 fn a_mf_sig(x: float, a: float, c: float) -> float;
507 fn a_mf_dsig(x: float, a1: float, c1: float, a2: float, c2: float) -> float;
508 fn a_mf_psig(x: float, a1: float, c1: float, a2: float, c2: float) -> float;
509 fn a_mf_trap(x: float, a: float, b: float, c: float, d: float) -> float;
510 fn a_mf_tri(x: float, a: float, b: float, c: float) -> float;
511 fn a_mf_lins(x: float, a: float, b: float) -> float;
512 fn a_mf_linz(x: float, a: float, b: float) -> float;
513 fn a_mf_s(x: float, a: float, b: float) -> float;
514 fn a_mf_z(x: float, a: float, b: float) -> float;
515 fn a_mf_pi(x: float, a: float, b: float, c: float, d: float) -> float;
518 /// gaussian membership function
520 pub fn gauss(x: float, sigma: float, c: float) -> float {
521 unsafe { a_mf_gauss(x, sigma, c) }
523 /// gaussian combination membership function
525 pub fn gauss2(x: float, sigma1: float, c1: float, sigma2: float, c2: float) -> float {
526 unsafe { a_mf_gauss2(x, sigma1, c1, sigma2, c2) }
528 /// generalized bell-shaped membership function
530 pub fn gbell(x: float, a: float, b: float, c: float) -> float {
531 unsafe { a_mf_gbell(x, a, b, c) }
533 /// sigmoidal membership function
535 pub fn sig(x: float, a: float, c: float) -> float {
536 unsafe { a_mf_sig(x, a, c) }
538 /// difference between two sigmoidal membership functions
540 pub fn dsig(x: float, a1: float, c1: float, a2: float, c2: float) -> float {
541 unsafe { a_mf_dsig(x, a1, c1, a2, c2) }
543 /// product of two sigmoidal membership functions
545 pub fn psig(x: float, a1: float, c1: float, a2: float, c2: float) -> float {
546 unsafe { a_mf_psig(x, a1, c1, a2, c2) }
548 /// trapezoidal membership function
550 pub fn trap(x: float, a: float, b: float, c: float, d: float) -> float {
551 unsafe { a_mf_trap(x, a, b, c, d) }
553 /// triangular membership function
555 pub fn tri(x: float, a: float, b: float, c: float) -> float {
556 unsafe { a_mf_tri(x, a, b, c) }
558 /// linear s-shaped saturation membership function
560 pub fn lins(x: float, a: float, b: float) -> float {
561 unsafe { a_mf_lins(x, a, b) }
563 /// linear z-shaped saturation membership function
565 pub fn linz(x: float, a: float, b: float) -> float {
566 unsafe { a_mf_linz(x, a, b) }
568 /// s-shaped membership function
570 pub fn s(x: float, a: float, b: float) -> float {
571 unsafe { a_mf_s(x, a, b) }
573 /// z-shaped membership function
575 pub fn z(x: float, a: float, b: float) -> float {
576 unsafe { a_mf_z(x, a, b) }
578 /// pi-shaped membership function
580 pub fn pi(x: float, a: float, b: float, c: float, d: float) -> float {
581 unsafe { a_mf_pi(x, a, b, c, d) }
590 let x = i as crate::float;
591 std::println!("{:+} {}", x, crate::mf::gauss2(x, 1.0, -1.0, 1.0, 1.0));
597 let x = i as crate::float;
598 std::println!("{:+} {}", x, crate::mf::gbell(x, 2.0, 4.0, 0.0));
604 let x = i as crate::float;
605 std::println!("{:+} {}", x, crate::mf::sig(x, 2.0, 0.0));
611 let x = i as crate::float;
612 std::println!("{:+} {}", x, crate::mf::dsig(x, 5.0, -2.0, 5.0, 2.0));
618 let x = i as crate::float;
619 std::println!("{:+} {}", x, crate::mf::psig(x, 5.0, -2.0, -5.0, 2.0));
625 let x = i as crate::float;
626 std::println!("{:+} {}", x, crate::mf::trap(x, -2.0, -1.0, 1.0, 2.0));
632 let x = i as crate::float;
633 std::println!("{:+} {}", x, crate::mf::tri(x, -1.0, 0.0, 1.0));
639 let x = i as crate::float;
640 std::println!("{:+} {}", x, crate::mf::lins(x, -1.0, 1.0));
646 let x = i as crate::float;
647 std::println!("{:+} {}", x, crate::mf::linz(x, -1.0, 1.0));
653 let x = i as crate::float;
654 std::println!("{:+} {}", x, crate::mf::s(x, -1.0, 1.0));
660 let x = i as crate::float;
661 std::println!("{:+} {}", x, crate::mf::z(x, -1.0, 1.0));
667 let x = i as crate::float;
668 std::println!("{:+} {}", x, crate::mf::pi(x, -2.0, -1.0, 1.0, 2.0));
674 /// proportional integral derivative controller
677 /// proportional constant
679 /// integral constant
681 /// derivative constant
683 /// maximum integral output
685 /// minimum integral output
687 /// controller integral output
689 /// maximum final output
691 /// minimum final output
693 /// controller final output
696 pub(crate) var: float,
703 impl Default for pid {
705 fn default() -> Self {
710 summax: float::INFINITY,
711 summin: -float::INFINITY,
713 outmax: float::INFINITY,
714 outmin: -float::INFINITY,
724 fn a_pid_kpid(ctx: *mut pid, kp: float, ki: float, kd: float);
725 fn a_pid_run(ctx: *mut pid, set: float, fdb: float) -> float;
726 fn a_pid_pos(ctx: *mut pid, set: float, fdb: float) -> float;
727 fn a_pid_inc(ctx: *mut pid, set: float, fdb: float) -> float;
728 fn a_pid_zero(ctx: *mut pid);
732 /// initialize for PID controller
734 pub fn new() -> Self {
737 /// set proportional integral derivative constant for PID controller
739 pub fn kpid(&mut self, kp: float, ki: float, kd: float) -> &mut Self {
740 unsafe { a_pid_kpid(self, kp, ki, kd) };
743 /// calculate for PID controller
745 pub fn run(&mut self, set: float, fdb: float) -> float {
746 unsafe { a_pid_run(self, set, fdb) }
748 /// calculate for positional PID controller
750 pub fn pos(&mut self, set: float, fdb: float) -> float {
751 unsafe { a_pid_pos(self, set, fdb) }
753 /// calculate for incremental PID controller
755 pub fn inc(&mut self, set: float, fdb: float) -> float {
756 unsafe { a_pid_inc(self, set, fdb) }
758 /// zeroing for PID controller
760 pub fn zero(&mut self) -> &mut Self {
761 unsafe { a_pid_zero(self) };
769 let mut a = crate::pid::new();
770 a.kpid(10.0, 0.1, 1.0);
771 std::println!("{}", a.zero().pos(1.0, 0.0));
772 std::println!("{}", a.zero().inc(1.0, 0.0));
775 /// fuzzy PID controller operator
779 pub const CAP: uint = 1;
781 pub const CAP_ALGEBRA: uint = 2;
783 pub const CAP_BOUNDED: uint = 3;
785 pub const CUP: uint = 4;
787 pub const CUP_ALGEBRA: uint = 5;
789 pub const CUP_BOUNDED: uint = 6;
790 /// sqrt(a,b)*sqrt(1-(1-a)*(1-b))
791 pub const EQU: uint = 0;
795 /// compute size of memory block for fuzzy PID controller
796 macro_rules! PID_FUZZY_BLOCK {
798 core::mem::size_of::<uint>() * $n * 2 + core::mem::size_of::<float>() * $n * (2 + $n)
802 /// fuzzy proportional integral derivative controller
804 pub struct pid_fuzzy {
805 /// proportional integral derivative controller
807 pub(crate) me: *const float,
808 pub(crate) mec: *const float,
809 pub(crate) mkp: *const float,
810 pub(crate) mki: *const float,
811 pub(crate) mkd: *const float,
812 pub(crate) idx: *mut uint,
813 pub(crate) val: *mut float,
814 /// fuzzy relational operator
815 pub(crate) op: extern "C" fn(float, float) -> float,
816 /// base proportional constant
818 /// base integral constant
820 /// base derivative constant
822 /// number of order in the square matrix
823 pub(crate) order: uint,
824 /// maximum number triggered by the rule
825 pub(crate) block: uint,
828 impl Default for pid_fuzzy {
830 fn default() -> Self {
833 me: core::ptr::null(),
834 mec: core::ptr::null(),
835 mkp: core::ptr::null(),
836 mki: core::ptr::null(),
837 mkd: core::ptr::null(),
838 idx: core::ptr::null_mut(),
839 val: core::ptr::null_mut(),
840 op: unsafe { a_pid_fuzzy_op(fuzzy::EQU) },
851 fn a_pid_fuzzy_op(op: uint) -> extern "C" fn(float, float) -> float;
852 fn a_pid_fuzzy_set_op(ctx: *mut pid_fuzzy, op: uint);
862 fn a_pid_fuzzy_block(ctx: *mut pid_fuzzy) -> *mut u8;
863 fn a_pid_fuzzy_set_block(ctx: *mut pid_fuzzy, ptr: *mut u8, num: usize);
864 fn a_pid_fuzzy_kpid(ctx: *mut pid_fuzzy, kp: float, ki: float, kd: float);
865 fn a_pid_fuzzy_run(ctx: *mut pid_fuzzy, set: float, fdb: float) -> float;
866 fn a_pid_fuzzy_pos(ctx: *mut pid_fuzzy, set: float, fdb: float) -> float;
867 fn a_pid_fuzzy_inc(ctx: *mut pid_fuzzy, set: float, fdb: float) -> float;
868 fn a_pid_fuzzy_zero(ctx: *mut pid_fuzzy);
872 /// initialize for fuzzy PID controller
874 pub fn new() -> Self {
877 /// set rule base for fuzzy PID controller
901 /// set proportional integral derivative constant for fuzzy PID controller
903 pub fn kpid(&mut self, kp: float, ki: float, kd: float) -> &mut Self {
904 unsafe { a_pid_fuzzy_kpid(self, kp, ki, kd) };
907 /// set memory block for fuzzy PID controller
909 pub fn set_block(&mut self, ptr: &mut [u8], num: usize) -> &mut Self {
910 unsafe { a_pid_fuzzy_set_block(self, ptr.as_mut_ptr(), num) };
913 /// get memory block for fuzzy PID controller
915 pub fn block(&mut self) -> &mut [u8] {
917 core::slice::from_raw_parts_mut(
918 a_pid_fuzzy_block(self),
919 PID_FUZZY_BLOCK!(self.block as usize),
923 /// set fuzzy relational operator for fuzzy PID controller
925 pub fn op(&mut self, op: uint) -> &mut Self {
926 unsafe { a_pid_fuzzy_set_op(self, op) };
929 /// calculate for fuzzy PID controller
931 pub fn run(&mut self, set: float, fdb: float) -> float {
932 unsafe { a_pid_fuzzy_run(self, set, fdb) }
934 /// calculate for positional fuzzy PID controller
936 pub fn pos(&mut self, set: float, fdb: float) -> float {
937 unsafe { a_pid_fuzzy_pos(self, set, fdb) }
939 /// calculate for incremental fuzzy PID controller
941 pub fn inc(&mut self, set: float, fdb: float) -> float {
942 unsafe { a_pid_fuzzy_inc(self, set, fdb) }
944 /// zeroing for fuzzy PID controller
946 pub fn zero(&mut self) -> &mut Self {
947 unsafe { a_pid_fuzzy_zero(self) };
953 #[allow(non_snake_case)]
956 let NL: float = -3.0;
957 let NM: float = -2.0;
958 let NS: float = -1.0;
964 [crate::mf::TRI as float, NL, NL, NM],
965 [crate::mf::TRI as float, NL, NM, NS],
966 [crate::mf::TRI as float, NM, NS, ZO],
967 [crate::mf::TRI as float, NS, ZO, PS],
968 [crate::mf::TRI as float, ZO, PS, PM],
969 [crate::mf::TRI as float, PS, PM, PL],
970 [crate::mf::TRI as float, PM, PL, PL],
972 let NL: float = -3.0;
973 let NM: float = -2.0;
974 let NS: float = -1.0;
980 [crate::mf::TRI as float, NL, NL, NM],
981 [crate::mf::TRI as float, NL, NM, NS],
982 [crate::mf::TRI as float, NM, NS, ZO],
983 [crate::mf::TRI as float, NS, ZO, PS],
984 [crate::mf::TRI as float, ZO, PS, PM],
985 [crate::mf::TRI as float, PS, PM, PL],
986 [crate::mf::TRI as float, PM, PL, PL],
988 let NL: float = -15.0;
989 let NM: float = -10.0;
990 let NS: float = -5.0;
993 let PM: float = 10.0;
994 let PL: float = 15.0;
996 [NL, NL, NM, NM, NS, ZO, ZO],
997 [NL, NL, NM, NS, NS, ZO, PS],
998 [NM, NM, NM, NS, ZO, PS, PS],
999 [NM, NM, NS, ZO, PS, PM, PM],
1000 [NS, NS, ZO, PS, PS, PM, PM],
1001 [NS, ZO, PS, PM, PM, PM, PL],
1002 [ZO, ZO, PM, PM, PM, PL, PL],
1004 let NL: float = -3.0;
1005 let NM: float = -2.0;
1006 let NS: float = -1.0;
1007 let ZO: float = 0.0;
1008 let PS: float = 1.0;
1009 let PM: float = 2.0;
1010 let PL: float = 3.0;
1012 [PL, PL, PM, PM, PS, ZO, ZO],
1013 [PL, PL, PM, PS, PS, ZO, ZO],
1014 [PL, PM, PS, PS, ZO, NS, NS],
1015 [PM, PM, PS, ZO, NS, NM, NM],
1016 [PM, PS, ZO, NS, NS, NM, NL],
1017 [ZO, ZO, NS, NS, NM, NL, NL],
1018 [ZO, ZO, NS, NM, NM, NL, NL],
1021 [NS, PS, PL, PL, PL, PM, NS],
1022 [NS, PS, PL, PM, PM, PS, ZO],
1023 [ZO, PS, PM, PM, PS, PS, ZO],
1024 [ZO, PS, PS, PS, PS, PS, ZO],
1025 [ZO, ZO, ZO, ZO, ZO, ZO, ZO],
1026 [NL, NS, NS, NS, NS, NS, NL],
1027 [NL, NM, NM, NM, NS, NS, NL],
1029 let mut block = [0u8; crate::PID_FUZZY_BLOCK!(2)];
1030 let mut a = pid_fuzzy::new();
1039 .kpid(10.0, 0.1, 1.0)
1040 .set_block(&mut block, 2);
1041 a.op(crate::fuzzy::EQU).zero();
1042 std::println!("{} {}", a.pos(1.0, 0.0), a.pos(1.0, 0.0));
1043 a.op(crate::fuzzy::EQU).zero();
1044 std::println!("{} {}", a.inc(1.0, 0.0), a.inc(1.0, 0.0));
1047 /// single neuron proportional integral derivative controller
1049 pub struct pid_neuro {
1050 /// proportional integral derivative controller
1052 /// proportional coefficient
1054 /// proportional weight
1058 /// derivative weight
1064 impl Default for pid_neuro {
1066 fn default() -> Self {
1068 pid: pid::default(),
1079 fn a_pid_neuro_kpid(ctx: *mut pid_neuro, k: float, kp: float, ki: float, kd: float);
1080 fn a_pid_neuro_wpid(ctx: *mut pid_neuro, wp: float, wi: float, wd: float);
1081 fn a_pid_neuro_run(ctx: *mut pid_neuro, set: float, fdb: float) -> float;
1082 fn a_pid_neuro_inc(ctx: *mut pid_neuro, set: float, fdb: float) -> float;
1083 fn a_pid_neuro_zero(ctx: *mut pid_neuro);
1087 /// initialize for single neuron PID controller
1089 pub fn new() -> Self {
1092 /// set proportional integral derivative constant for single neuron PID controller
1094 pub fn kpid(&mut self, k: float, kp: float, ki: float, kd: float) -> &mut Self {
1095 unsafe { a_pid_neuro_kpid(self, k, kp, ki, kd) };
1098 /// set proportional integral derivative weight for single neuron PID controller
1100 pub fn wpid(&mut self, wp: float, wi: float, wd: float) -> &mut Self {
1101 unsafe { a_pid_neuro_wpid(self, wp, wi, wd) };
1104 /// calculate for single neuron PID controller
1106 pub fn run(&mut self, set: float, fdb: float) -> float {
1107 unsafe { a_pid_neuro_run(self, set, fdb) }
1109 /// calculate for incremental single neuron PID controller
1111 pub fn inc(&mut self, set: float, fdb: float) -> float {
1112 unsafe { a_pid_neuro_inc(self, set, fdb) }
1114 /// zeroing for single neuron PID controller
1116 pub fn zero(&mut self) -> &mut Self {
1117 unsafe { a_pid_neuro_zero(self) };
1125 let mut a = crate::pid_neuro::new();
1126 a.kpid(10.0, 1.0, 0.1, 1.0).wpid(1.0, 0.0, 0.0);
1127 std::println!("{}", a.inc(1.0, 0.0));
1131 /// transfer function
1139 num_p: *const float,
1141 den_p: *const float,
1142 /// numerator number
1144 /// denominator number
1149 fn a_tf_set_num(ctx: *mut tf, num_n: uint, num_p: *const float, input: *mut float);
1150 fn a_tf_set_den(ctx: *mut tf, den_n: uint, den_p: *const float, output: *mut float);
1154 num_p: *const float,
1157 den_p: *const float,
1160 fn a_tf_iter(ctx: *const tf, x: float) -> float;
1161 fn a_tf_zero(ctx: *const tf);
1165 /// initialize for transfer function
1167 pub fn new(num: &[float], input: &mut [float], den: &[float], output: &mut [float]) -> Self {
1168 let mut ctx: Self = Self {
1169 input: core::ptr::null_mut(),
1170 output: core::ptr::null_mut(),
1171 num_p: core::ptr::null(),
1172 den_p: core::ptr::null(),
1184 output.as_mut_ptr(),
1189 /// calculate for transfer function
1191 pub fn iter(&mut self, x: float) -> float {
1192 unsafe { a_tf_iter(self, x) }
1194 /// zeroing for transfer function
1196 pub fn zero(&mut self) -> &mut Self {
1197 unsafe { a_tf_zero(self) };
1200 /// get input for transfer function
1202 pub fn input(&self) -> &[float] {
1203 unsafe { core::slice::from_raw_parts(self.input, self.num_n as usize) }
1205 /// get numerator for transfer function
1207 pub fn num(&self) -> &[float] {
1208 unsafe { core::slice::from_raw_parts(self.num_p, self.num_n as usize) }
1210 /// set numerator for transfer function
1212 pub fn set_num(&mut self, num: &[float], input: &mut [float]) -> &mut Self {
1213 unsafe { a_tf_set_num(self, num.len() as uint, num.as_ptr(), input.as_mut_ptr()) };
1216 /// get output for transfer function
1218 pub fn output(&self) -> &[float] {
1219 unsafe { core::slice::from_raw_parts(self.output, self.den_n as usize) }
1221 /// get denominator for transfer function
1223 pub fn den(&self) -> &[float] {
1224 unsafe { core::slice::from_raw_parts(self.den_p, self.den_n as usize) }
1226 /// set denominator for transfer function
1228 pub fn set_den(&mut self, den: &[float], output: &mut [float]) -> &mut Self {
1229 unsafe { a_tf_set_den(self, den.len() as uint, den.as_ptr(), output.as_mut_ptr()) };
1237 let num = [6.59492796e-05, 6.54019884e-05];
1238 let den = [-1.97530991, 0.97530991];
1239 let mut input = [0.0; 2];
1240 let mut output = [0.0; 2];
1241 let mut a = crate::tf::new(&num, &mut input, &den, &mut output);
1242 a.set_num(&num, &mut input).set_den(&den, &mut output);
1243 std::println!("{} {}", a.iter(10.0), a.iter(10.0));
1244 std::println!("{:?} {:?}", a.num(), a.input());
1245 std::println!("{:?} {:?}", a.den(), a.output());
1249 /// bell-shaped velocity trajectory
1251 pub struct trajbell {
1254 /// constant velocity phase
1256 /// acceleration phase
1258 /// deceleration phase
1260 /// time-interval in which the jerk is constant (j max or j min ) during the acceleration phase
1262 /// time-interval in which the jerk is constant (j max or j min ) during the deceleration phase
1264 /// initial position
1268 /// initial velocity
1272 /// maximum velocity
1276 /// maximum acceleration
1278 /// maximum deceleration
1282 impl Default for trajbell {
1284 fn default() -> Self {
1315 fn a_trajbell_pos(ctx: *const trajbell, x: float) -> float;
1316 fn a_trajbell_vel(ctx: *const trajbell, x: float) -> float;
1317 fn a_trajbell_acc(ctx: *const trajbell, x: float) -> float;
1318 fn a_trajbell_jer(ctx: *const trajbell, x: float) -> float;
1322 /// initialize for bell-shaped velocity trajectory
1324 pub fn new() -> Self {
1327 /// generate for bell-shaped velocity trajectory
1328 #[allow(clippy::too_many_arguments)]
1340 unsafe { a_trajbell_gen(self, jm, am, vm, p0, p1, v0, v1) }
1342 /// calculate position for bell-shaped velocity trajectory
1344 pub fn pos(&mut self, x: float) -> float {
1345 unsafe { a_trajbell_pos(self, x) }
1347 /// calculate velocity for bell-shaped velocity trajectory
1349 pub fn vel(&mut self, x: float) -> float {
1350 unsafe { a_trajbell_vel(self, x) }
1352 /// calculate acceleration for bell-shaped velocity trajectory
1354 pub fn acc(&mut self, x: float) -> float {
1355 unsafe { a_trajbell_acc(self, x) }
1357 /// calculate jerk for bell-shaped velocity trajectory
1359 pub fn jer(&mut self, x: float) -> float {
1360 unsafe { a_trajbell_jer(self, x) }
1369 let mut a = crate::trajbell::new();
1370 std::print!("{} ", a.gen(3.0, 2.0, 3.0, 0.0, 10.0, 0.0, 0.0));
1371 std::println!("[{}, {}, {}, {}]", a.pos(x), a.vel(x), a.acc(x), a.jer(x));
1375 /// cubic polynomial trajectory
1377 pub struct trajpoly3 {
1378 /// coefficients of position
1380 /// coefficients of velocity
1382 /// coefficients of acceleration
1387 fn a_trajpoly3_gen(ctx: *mut trajpoly3, ts: float, p0: float, p1: float, v0: float, v1: float);
1388 fn a_trajpoly3_pos(ctx: *const trajpoly3, x: float) -> float;
1389 fn a_trajpoly3_vel(ctx: *const trajpoly3, x: float) -> float;
1390 fn a_trajpoly3_acc(ctx: *const trajpoly3, x: float) -> float;
1394 /// initialize for cubic polynomial trajectory
1396 pub fn new(ts: float, p0: float, p1: float, v0: float, v1: float) -> Self {
1397 let mut ctx: Self = Self {
1402 unsafe { a_trajpoly3_gen(&mut ctx, ts, p0, p1, v0, v1) };
1405 /// generate for cubic polynomial trajectory
1407 pub fn gen(&mut self, ts: float, p0: float, p1: float, v0: float, v1: float) -> &mut Self {
1408 unsafe { a_trajpoly3_gen(self, ts, p0, p1, v0, v1) };
1411 /// calculate position for cubic polynomial trajectory
1413 pub fn pos(&mut self, x: float) -> float {
1414 unsafe { a_trajpoly3_pos(self, x) }
1416 /// calculate velocity for cubic polynomial trajectory
1418 pub fn vel(&mut self, x: float) -> float {
1419 unsafe { a_trajpoly3_vel(self, x) }
1421 /// calculate acceleration for cubic polynomial trajectory
1423 pub fn acc(&mut self, x: float) -> float {
1424 unsafe { a_trajpoly3_acc(self, x) }
1433 let mut a = crate::trajpoly3::new(1.0, 0.0, 1.0, 0.0, 1.0);
1434 std::println!("[{}, {}, {}]", a.pos(x), a.vel(x), a.acc(x));
1438 /// quintic polynomial trajectory
1440 pub struct trajpoly5 {
1441 /// coefficients of position
1443 /// coefficients of velocity
1445 /// coefficients of acceleration
1451 ctx: *mut trajpoly5,
1460 fn a_trajpoly5_pos(ctx: *const trajpoly5, x: float) -> float;
1461 fn a_trajpoly5_vel(ctx: *const trajpoly5, x: float) -> float;
1462 fn a_trajpoly5_acc(ctx: *const trajpoly5, x: float) -> float;
1466 /// initialize for quintic polynomial trajectory
1467 #[allow(clippy::too_many_arguments)]
1478 let mut ctx: Self = Self {
1483 unsafe { a_trajpoly5_gen(&mut ctx, ts, p0, p1, v0, v1, a0, a1) };
1486 /// generate for quintic polynomial trajectory
1487 #[allow(clippy::too_many_arguments)]
1499 unsafe { a_trajpoly5_gen(self, ts, p0, p1, v0, v1, a0, a1) };
1502 /// calculate position for quintic polynomial trajectory
1504 pub fn pos(&mut self, x: float) -> float {
1505 unsafe { a_trajpoly5_pos(self, x) }
1507 /// calculate velocity for quintic polynomial trajectory
1509 pub fn vel(&mut self, x: float) -> float {
1510 unsafe { a_trajpoly5_vel(self, x) }
1512 /// calculate acceleration for quintic polynomial trajectory
1514 pub fn acc(&mut self, x: float) -> float {
1515 unsafe { a_trajpoly5_acc(self, x) }
1524 let mut a = crate::trajpoly5::new(1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0);
1525 std::println!("[{}, {}, {}]", a.pos(x), a.vel(x), a.acc(x));
1529 /// hepta polynomial trajectory
1531 pub struct trajpoly7 {
1532 /// coefficients of position
1534 /// coefficients of velocity
1536 /// coefficients of acceleration
1538 /// coefficients of jerk
1544 ctx: *mut trajpoly7,
1555 fn a_trajpoly7_pos(ctx: *const trajpoly7, x: float) -> float;
1556 fn a_trajpoly7_vel(ctx: *const trajpoly7, x: float) -> float;
1557 fn a_trajpoly7_acc(ctx: *const trajpoly7, x: float) -> float;
1558 fn a_trajpoly7_jer(ctx: *const trajpoly7, x: float) -> float;
1562 /// initialize for hepta polynomial trajectory
1563 #[allow(clippy::too_many_arguments)]
1576 let mut ctx: Self = Self {
1582 unsafe { a_trajpoly7_gen(&mut ctx, ts, p0, p1, v0, v1, a0, a1, j0, j1) };
1585 /// generate for hepta polynomial trajectory
1586 #[allow(clippy::too_many_arguments)]
1600 unsafe { a_trajpoly7_gen(self, ts, p0, p1, v0, v1, a0, a1, j0, j1) };
1603 /// calculate position for hepta polynomial trajectory
1605 pub fn pos(&mut self, x: float) -> float {
1606 unsafe { a_trajpoly7_pos(self, x) }
1608 /// calculate velocity for hepta polynomial trajectory
1610 pub fn vel(&mut self, x: float) -> float {
1611 unsafe { a_trajpoly7_vel(self, x) }
1613 /// calculate acceleration for hepta polynomial trajectory
1615 pub fn acc(&mut self, x: float) -> float {
1616 unsafe { a_trajpoly7_acc(self, x) }
1618 /// calculate jerk for hepta polynomial trajectory
1620 pub fn jer(&mut self, x: float) -> float {
1621 unsafe { a_trajpoly7_jer(self, x) }
1630 let mut a = crate::trajpoly7::new(1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0);
1631 std::println!("[{}, {}, {}, {}]", a.pos(x), a.vel(x), a.acc(x), a.jer(x));
1635 /// trapezoidal velocity trajectory
1637 pub struct trajtrap {
1640 /// initial position
1644 /// initial velocity
1648 /// constant velocity
1650 /// time before constant velocity
1652 /// time after constant velocity
1654 /// position before constant velocity
1656 /// position after constant velocity
1658 /// acceleration before constant velocity
1660 /// acceleration after constant velocity
1664 impl Default for trajtrap {
1666 fn default() -> Self {
1695 fn a_trajtrap_pos(ctx: *const trajtrap, x: float) -> float;
1696 fn a_trajtrap_vel(ctx: *const trajtrap, x: float) -> float;
1697 fn a_trajtrap_acc(ctx: *const trajtrap, x: float) -> float;
1701 /// initialize for trapezoidal velocity trajectory
1703 pub fn new() -> Self {
1706 /// generate for trapezoidal velocity trajectory
1707 #[allow(clippy::too_many_arguments)]
1719 unsafe { a_trajtrap_gen(self, vm, ac, de, p0, p1, v0, v1) }
1721 /// calculate position for trapezoidal velocity trajectory
1723 pub fn pos(&mut self, x: float) -> float {
1724 unsafe { a_trajtrap_pos(self, x) }
1726 /// calculate velocity for trapezoidal velocity trajectory
1728 pub fn vel(&mut self, x: float) -> float {
1729 unsafe { a_trajtrap_vel(self, x) }
1731 /// calculate acceleration for trapezoidal velocity trajectory
1733 pub fn acc(&mut self, x: float) -> float {
1734 unsafe { a_trajtrap_acc(self, x) }
1743 let mut a = crate::trajtrap::new();
1744 std::print!("{} ", a.gen(2.0, 2.0, -2.0, 0.0, 2.0, 0.0, 0.0));
1745 std::println!("[{}, {}, {}]", a.pos(x), a.vel(x), a.acc(x));
1755 /// "version {}.{}.{}+{}",
1756 /// liba::version::major(),
1757 /// liba::version::minor(),
1758 /// liba::version::patch(),
1759 /// liba::version::tweak()
1763 pub struct version {
1777 static a_version_major: uint;
1778 static a_version_minor: uint;
1779 static a_version_patch: uint;
1780 static a_version_tweak: u32;
1781 fn a_version_set_alpha(ctx: *mut version, alpha: *const u8);
1782 fn a_version_alpha(ctx: *const version, alpha: &mut [u8; 5]);
1783 fn a_version_parse(ctx: *mut version, ver: *const u8) -> uint;
1784 fn a_version_tostr(ctx: *const version, p: *mut u8, n: usize) -> int;
1785 fn a_version_cmp(ctx: *const version, rhs: *const version) -> int;
1786 fn a_version_lt(ctx: *const version, rhs: *const version) -> bool;
1787 fn a_version_gt(ctx: *const version, rhs: *const version) -> bool;
1788 fn a_version_le(ctx: *const version, rhs: *const version) -> bool;
1789 fn a_version_ge(ctx: *const version, rhs: *const version) -> bool;
1790 fn a_version_eq(ctx: *const version, rhs: *const version) -> bool;
1791 fn a_version_check(major: uint, minor: uint, patch: uint) -> int;
1795 /// initialize for version
1797 pub fn new(major: uint, minor: uint, third: uint) -> Self {
1803 alpha: [b'.', 0, 0, 0],
1806 /// set alphabet for version
1808 pub fn set_alpha(&mut self, alpha: &[u8]) {
1809 unsafe { a_version_set_alpha(self, alpha.as_ptr()) }
1811 /// get alphabet for version
1813 pub fn alpha(&self, alpha: &mut [u8; 5]) {
1814 unsafe { a_version_alpha(self, alpha) }
1816 /// parse version string to version
1818 pub fn parse(&mut self, ver: &str) -> uint {
1819 unsafe { a_version_parse(self, ver.as_ptr()) }
1821 /// convert version to string
1823 pub fn tostr(&mut self, ver: &mut [u8]) -> int {
1824 unsafe { a_version_tostr(self, ver.as_mut_ptr(), ver.len()) }
1826 /// algorithm library version check
1828 pub fn check(major: uint, minor: uint, patch: uint) -> int {
1829 unsafe { a_version_check(major, minor, patch) }
1831 /// algorithm library version major
1833 pub fn major() -> uint {
1834 unsafe { a_version_major }
1836 /// algorithm library version minor
1838 pub fn minor() -> uint {
1839 unsafe { a_version_minor }
1841 /// algorithm library version patch
1843 pub fn patch() -> uint {
1844 unsafe { a_version_patch }
1846 /// algorithm library version tweak
1848 pub fn tweak() -> u32 {
1849 unsafe { a_version_tweak }
1853 impl PartialOrd for version {
1855 fn partial_cmp(&self, that: &version) -> Option<core::cmp::Ordering> {
1856 let ok: int = unsafe { a_version_cmp(self, that) };
1858 return Some(core::cmp::Ordering::Greater);
1861 return Some(core::cmp::Ordering::Less);
1863 Some(core::cmp::Ordering::Equal)
1866 fn lt(&self, that: &version) -> bool {
1867 unsafe { a_version_lt(self, that) }
1870 fn gt(&self, that: &version) -> bool {
1871 unsafe { a_version_gt(self, that) }
1874 fn le(&self, that: &version) -> bool {
1875 unsafe { a_version_le(self, that) }
1878 fn ge(&self, that: &version) -> bool {
1879 unsafe { a_version_ge(self, that) }
1883 impl PartialEq for version {
1885 fn eq(&self, that: &version) -> bool {
1886 unsafe { a_version_eq(self, that) }
1893 impl core::fmt::Debug for version {
1894 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1895 let mut alpha = [0u8; 5];
1896 self.alpha(&mut alpha);
1897 f.debug_struct("version")
1898 .field("major", &self.major)
1899 .field("minor", &self.minor)
1900 .field("third", &self.third)
1901 .field("extra", &self.extra)
1902 .field("alpha", &std::str::from_utf8(&alpha).unwrap())
1906 std::println!("{}", crate::version::check(0, 0, 0));
1907 std::println!("major {}", crate::version::major());
1908 std::println!("minor {}", crate::version::minor());
1909 std::println!("patch {}", crate::version::patch());
1910 std::println!("tweak {}", crate::version::tweak());
1911 let v000 = version::new(0, 0, 0);
1912 let mut v001 = version::new(0, 0, 0);
1913 let mut ver = [0u8; 48];
1914 v001.parse("0.0.1-a.1");
1915 v001.tostr(&mut ver);
1916 std::println!("{:?}", v001);
1917 std::println!("{}", std::str::from_utf8(&ver).unwrap());
1918 assert!(v001 > v000);
1919 assert!(v000 < v001);
1920 assert!(v000 >= v000);
1921 assert!(v000 <= v000);
1922 assert!(v000 == v000);
1923 assert!(v000 != v001);