Skip to main content

rill_core_model/macros/
compose.rs

1/// Compose two WDF elements into Series or Parallel.
2#[macro_export]
3macro_rules! wdf_compose {
4    (
5        name: $name:ident<T>,
6        kind: Series,
7        elements: ($left:ty, $right:ty),
8    ) => {
9        /// Series composite of two WDF elements.
10        ///
11        /// Port resistance is the sum of element resistances. Incident waves
12        /// are distributed proportionally to each element's resistance share.
13        #[derive(Debug, Clone, Copy)]
14        pub struct $name<T: $crate::Transcendental> {
15            /// Left (first) WDF element in the series composite.
16            pub left: $left,
17            /// Right (second) WDF element in the series composite.
18            pub right: $right,
19        }
20
21        impl<T: $crate::Transcendental> $name<T> {
22            /// Create a new series composite from two WDF elements.
23            pub fn new(left: $left, right: $right) -> Self {
24                Self { left, right }
25            }
26        }
27
28        impl<T: $crate::Transcendental> $crate::WdfElement<T> for $name<T> {
29            fn port_resistance(&self) -> T {
30                self.left.port_resistance() + self.right.port_resistance()
31            }
32            fn process_incident(&mut self, a: T) -> T {
33                let r1 = self.left.port_resistance();
34                let r2 = self.right.port_resistance();
35                let total = r1 + r2;
36                let a1 = a * (r1 / total);
37                let a2 = a * (r2 / total);
38                let b1 = self.left.process_incident(a1);
39                let b2 = self.right.process_incident(a2);
40                b1 * (r1 / total) + b2 * (r2 / total)
41            }
42            fn update_state(&mut self) {
43                self.left.update_state();
44                self.right.update_state();
45            }
46            fn voltage(&self) -> T {
47                self.left.voltage() + self.right.voltage()
48            }
49            fn current(&self) -> T {
50                self.left.current()
51            }
52            fn reset(&mut self) {
53                self.left.reset();
54                self.right.reset();
55            }
56        }
57    };
58    (
59        name: $name:ident<T>,
60        kind: Parallel,
61        elements: ($left:ty, $right:ty),
62    ) => {
63        /// Parallel composite of two WDF elements.
64        ///
65        /// Port resistance is the parallel combination
66        /// `(r1 * r2) / (r1 + r2)`. Incident waves are scattered using
67        /// conductance weighting.
68        #[derive(Debug, Clone, Copy)]
69        pub struct $name<T: $crate::Transcendental> {
70            /// Left (first) WDF element in the parallel composite.
71            pub left: $left,
72            /// Right (second) WDF element in the parallel composite.
73            pub right: $right,
74        }
75
76        impl<T: $crate::Transcendental> $name<T> {
77            /// Create a new parallel composite from two WDF elements.
78            pub fn new(left: $left, right: $right) -> Self {
79                Self { left, right }
80            }
81        }
82
83        impl<T: $crate::Transcendental> $crate::WdfElement<T> for $name<T> {
84            fn port_resistance(&self) -> T {
85                let r1 = self.left.port_resistance();
86                let r2 = self.right.port_resistance();
87                (r1 * r2) / (r1 + r2)
88            }
89            fn process_incident(&mut self, a: T) -> T {
90                let r1 = self.left.port_resistance();
91                let r2 = self.right.port_resistance();
92                let g1 = T::ONE / r1;
93                let g2 = T::ONE / r2;
94                let total_g = g1 + g2;
95                let two = T::from_f32(2.0);
96                let a1 = two * g1 / total_g;
97                let a2 = two * g2 / total_g;
98                let b1 = self.left.process_incident(a);
99                let b2 = self.right.process_incident(a);
100                a1 * b1 + a2 * b2 - a
101            }
102            fn update_state(&mut self) {
103                self.left.update_state();
104                self.right.update_state();
105            }
106            fn voltage(&self) -> T {
107                self.left.voltage()
108            }
109            fn current(&self) -> T {
110                self.left.current() + self.right.current()
111            }
112            fn reset(&mut self) {
113                self.left.reset();
114                self.right.reset();
115            }
116        }
117    };
118}