rust_fuzzylogic/membership/
trapezoidal.rs1use super::{slope, validate_order, Float, MembershipFn};
2
3#[derive(Clone, Copy, PartialEq, Debug)]
6pub struct Trapezoidal {
7 left_leg: Float,
8 left_base: Float,
9 right_base: Float,
10 right_leg: Float,
11}
12
13impl MembershipFn for Trapezoidal {
14 fn eval(&self, x: Float) -> Float {
16 let eps = crate::Float::EPSILON;
17
18 if x <= self.left_leg {
20 return 0.0;
21 }
22 if x >= self.right_leg {
23 return 0.0;
24 }
25
26 if (x - self.left_base).abs() < eps || (x - self.right_base).abs() < eps {
28 1.0
29 } else if x < self.left_base {
30 slope(x, self.left_leg, self.left_base, 1.0)
31 } else if x > self.left_base && x < self.right_base {
32 1.0
33 } else {
34 slope(x, self.right_base, self.right_leg, -1.0)
35 }
36 }
37}
38
39impl Trapezoidal {
40 pub fn new(ll: Float, lb: Float, rb: Float, rl: Float) -> crate::error::Result<Self> {
42 validate_order(&[ll, lb, rb, rl])?;
43 return Ok(Trapezoidal {
44 left_leg: ll,
45 left_base: lb,
46 right_base: rb,
47 right_leg: rl,
48 });
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55
56 #[test]
57 fn test_trapezoidal() {
58 let membership_func = Trapezoidal::new(-1.0, 0.0, 1.0, 2.0);
59 let eps = crate::Float::EPSILON;
60
61 assert_eq!(
62 Trapezoidal::new(0.0, 0.0, -1.0, 0.0),
63 Err(crate::error::FuzzyError::BadArity)
64 );
65
66 assert!((membership_func.clone().unwrap().eval(0.0) - 1.0).abs() < eps);
67 assert!((membership_func.clone().unwrap().eval(1.0) - 1.0).abs() < eps);
68 assert!((membership_func.clone().unwrap().eval(-0.5) - 0.5).abs() < eps);
69 assert!((membership_func.unwrap().eval(2.0)).abs() < eps);
70 }
71}