1
+ use ndarray:: Array2 ;
2
+ use num:: { complex:: ComplexFloat , NumCast , One } ;
3
+ use option_trait:: { Maybe , StaticMaybe } ;
4
+
5
+ use crate :: { quantities:: { ContainerOrSingle , List , ListOrSingle , Lists , Matrix , MatrixOrSingle , MaybeList , MaybeLists , MaybeOwnedList , OwnedList , OwnedListOrSingle } , systems:: { Sos , Ss , SsAMatrix , SsBMatrix , SsCMatrix , SsDMatrix , Tf , Zpk } , transforms:: system:: ToSs , util:: TwoSidedRange , System } ;
6
+
7
+ use super :: SimS ;
8
+
9
+ pub trait ImpulseS < L > : System
10
+ where
11
+ L : List < <Self :: Set as ComplexFloat >:: Real > ,
12
+ <L :: Length as StaticMaybe < usize > >:: Opposite : Sized
13
+ {
14
+ type OutputI : Lists < Self :: Set > + ListOrSingle < L :: Mapped < Self :: Set > > ;
15
+ type Output : MatrixOrSingle < L :: Mapped < Self :: Set > > ;
16
+
17
+ fn impulse_s < T , W > ( self , t : T , numtaps : <L :: Length as StaticMaybe < usize > >:: Opposite , w : W )
18
+ -> ( L , Self :: Output )
19
+ where
20
+ T : TwoSidedRange < <Self :: Set as ComplexFloat >:: Real > + Clone ,
21
+ W : Maybe < Vec < Self :: Set > > ;
22
+ }
23
+
24
+ impl < T , A , B , C , D , L , YY > ImpulseS < L > for Ss < T , A , B , C , D >
25
+ where
26
+ T : ComplexFloat ,
27
+ A : SsAMatrix < T , B , C , D > ,
28
+ B : SsBMatrix < T , A , C , D > ,
29
+ C : SsCMatrix < T , A , B , D > ,
30
+ D : for < ' a > SsDMatrix < T , A , B , C , RowView < ' a > : List < T > > ,
31
+ L : OwnedList < T :: Real , Mapped < T > = YY > ,
32
+ <L :: Length as StaticMaybe < usize > >:: Opposite : Sized + Clone ,
33
+ D :: RowsMapped < YY > : Lists < T > ,
34
+ YY : OwnedList < T , Length = L :: Length > + Clone ,
35
+ L :: Mapped < Vec < T > > : OwnedList < Vec < T > , Length : StaticMaybe < usize , Opposite : Sized > > ,
36
+ for < ' a > Ss < T , A :: View < ' a > , B :: View < ' a > , C :: View < ' a > , D :: View < ' a > > : System < Set = T > + SimS < T , Array2 < T > , Output = D :: RowsMapped < Vec < T > > > ,
37
+ for < ' a > A :: View < ' a > : SsAMatrix < T , B :: View < ' a > , C :: View < ' a > , D :: View < ' a > > ,
38
+ for < ' a > B :: View < ' a > : SsBMatrix < T , A :: View < ' a > , C :: View < ' a > , D :: View < ' a > > ,
39
+ for < ' a > C :: View < ' a > : SsCMatrix < T , A :: View < ' a > , B :: View < ' a > , D :: View < ' a > > ,
40
+ for < ' a > D :: View < ' a > : SsDMatrix < T , A :: View < ' a > , B :: View < ' a > , C :: View < ' a > > ,
41
+ D :: RowsMapped < Vec < T > > : ListOrSingle < Vec < T > , Mapped < YY > : Into < D :: RowsMapped < YY > > > ,
42
+ <D :: Transpose as MaybeLists < T > >:: RowsMapped < D :: RowsMapped < YY > > : OwnedListOrSingle < D :: RowsMapped < YY > , Length : StaticMaybe < usize , Opposite : Sized > > + Lists < YY > ,
43
+ <<D :: Transpose as MaybeLists < T > >:: RowsMapped < D :: RowsMapped < YY > > as Lists < YY > >:: CoercedMatrix : Matrix < YY >
44
+ {
45
+ type OutputI = D :: RowsMapped < YY > ;
46
+ type Output = <<D :: Transpose as MaybeLists < T > >:: RowsMapped < Self :: OutputI > as Lists < YY > >:: CoercedMatrix ;
47
+
48
+ fn impulse_s < TT , W > ( self , t : TT , numtaps : <L :: Length as StaticMaybe < usize > >:: Opposite , w : W )
49
+ -> ( L , Self :: Output )
50
+ where
51
+ TT : TwoSidedRange < T :: Real > + Clone ,
52
+ W : Maybe < Vec < T > >
53
+ {
54
+ let w = w. into_option ( ) ;
55
+
56
+ let d: Array2 < T > = self . d . to_array2 ( ) ;
57
+
58
+ let n = numtaps. into_option ( )
59
+ . unwrap_or ( L :: LENGTH ) ;
60
+ let nuf = <T :: Real as NumCast >:: from ( n) . unwrap ( ) ;
61
+ let numaybem1 = if t. is_end_inclusive ( )
62
+ {
63
+ nuf - T :: Real :: one ( )
64
+ }
65
+ else
66
+ {
67
+ nuf
68
+ } ;
69
+
70
+ let dt = ( * t. end ( ) - * t. start ( ) ) /numaybem1;
71
+
72
+ let tt = OwnedListOrSingle :: from_len_fn ( StaticMaybe :: maybe_from_fn ( || n) , |i| {
73
+ let i = <T :: Real as NumCast >:: from ( i) . unwrap ( ) ;
74
+ * t. start ( ) + i* dt
75
+ } ) ;
76
+
77
+ let dn = d. dim ( ) . 1 ;
78
+ let y = <D :: Transpose as MaybeLists < T > >:: RowsMapped :: < Self :: OutputI > :: from_len_fn ( StaticMaybe :: maybe_from_fn ( || dn) , |i| {
79
+ let d = d. column ( i)
80
+ . to_vec ( ) ;
81
+
82
+ let w = match w. clone ( )
83
+ {
84
+ Some ( w) => {
85
+ let wn = w. len ( ) ;
86
+ w. into_iter ( )
87
+ . chain ( core:: iter:: repeat ( T :: zero ( ) )
88
+ . take ( d. len ( ) . saturating_sub ( wn) )
89
+ ) . zip ( d)
90
+ . map ( |( w, b) | w + b)
91
+ . collect ( )
92
+ } ,
93
+ None => d
94
+ } ;
95
+
96
+ let ( _, y, _) = self . as_view ( )
97
+ . sim_s (
98
+ t. clone ( ) ,
99
+ Array2 :: from_elem ( ( dn, n) , T :: zero ( ) ) ,
100
+ w,
101
+ false
102
+ ) ;
103
+
104
+ let y: Self :: OutputI = y. map_into_owned ( |y| {
105
+ let ny = y. len ( ) ;
106
+ let mut y = y. into_iter ( ) ;
107
+ OwnedListOrSingle :: from_len_fn ( StaticMaybe :: maybe_from_fn ( || ny) , |_| y. next ( ) . unwrap ( ) )
108
+ } ) . into ( ) ;
109
+ y
110
+ } )
111
+ . coerce_into_matrix ( || panic ! ( "Matrix is not correctly shaped" ) ) ;
112
+
113
+ ( tt, y)
114
+ }
115
+ }
116
+
117
+ impl < T , B , A , L > ImpulseS < L > for Tf < T , B , A >
118
+ where
119
+ T : ComplexFloat ,
120
+ B : MaybeLists < T > ,
121
+ A : MaybeList < T > ,
122
+ L : List < T :: Real > ,
123
+ <L :: Length as StaticMaybe < usize > >:: Opposite : Sized ,
124
+ B :: RowsMapped < L :: Mapped < T > > : Lists < T > + OwnedListOrSingle < L :: Mapped < T > , Length : StaticMaybe < usize , Opposite : Sized > > ,
125
+ Self : System < Set = T > + ToSs < T , Array2 < T > , Array2 < T > , Array2 < T > , Array2 < T > > ,
126
+ Array2 < T > : SsAMatrix < T , Array2 < T > , Array2 < T > , Array2 < T > > + SsBMatrix < T , Array2 < T > , Array2 < T > , Array2 < T > > + SsCMatrix < T , Array2 < T > , Array2 < T > , Array2 < T > > + SsDMatrix < T , Array2 < T > , Array2 < T > , Array2 < T > > ,
127
+ Ss < T , Array2 < T > , Array2 < T > , Array2 < T > , Array2 < T > > : ImpulseS < L , Output = Array2 < L :: Mapped < T > > > + System < Set = T >
128
+ {
129
+ type OutputI = B :: RowsMapped < L :: Mapped < T > > ;
130
+ type Output = B :: RowsMapped < L :: Mapped < T > > ;
131
+
132
+ fn impulse_s < TT , W > ( self , t : TT , numtaps : <L :: Length as StaticMaybe < usize > >:: Opposite , w : W )
133
+ -> ( L , Self :: Output )
134
+ where
135
+ TT : TwoSidedRange < T :: Real > + Clone ,
136
+ W : Maybe < Vec < T > >
137
+ {
138
+ let ( t, y) = self . to_ss ( )
139
+ . impulse_s ( t, numtaps, w) ;
140
+
141
+ let q = y. len ( ) ;
142
+ let mut y = y. into_iter ( ) ;
143
+
144
+ (
145
+ t,
146
+ OwnedListOrSingle :: from_len_fn ( StaticMaybe :: maybe_from_fn ( || q) , |_| y. next ( ) . unwrap ( ) )
147
+ )
148
+ }
149
+ }
150
+
151
+ impl < T , Z , P , K , L > ImpulseS < L > for Zpk < T , Z , P , K >
152
+ where
153
+ T : ComplexFloat ,
154
+ Z : MaybeList < T > ,
155
+ P : MaybeList < T > ,
156
+ K : ComplexFloat < Real = T :: Real > ,
157
+ L : List < T :: Real > ,
158
+ <L :: Length as StaticMaybe < usize > >:: Opposite : Sized ,
159
+ L :: Mapped < K > : List < K > + ListOrSingle < L :: Mapped < K > > ,
160
+ Self : System < Set = K > + ToSs < K , Array2 < K > , Array2 < K > , Array2 < K > , Array2 < K > > ,
161
+ Array2 < K > : SsAMatrix < K , Array2 < K > , Array2 < K > , Array2 < K > > + SsBMatrix < K , Array2 < K > , Array2 < K > , Array2 < K > > + SsCMatrix < K , Array2 < K > , Array2 < K > , Array2 < K > > + SsDMatrix < K , Array2 < K > , Array2 < K > , Array2 < K > > ,
162
+ Ss < K , Array2 < K > , Array2 < K > , Array2 < K > , Array2 < K > > : System < Set = K > + ImpulseS < L , Output = Array2 < L :: Mapped < K > > >
163
+ {
164
+ type OutputI = L :: Mapped < K > ;
165
+ type Output = L :: Mapped < K > ;
166
+
167
+ fn impulse_s < TT , W > ( self , t : TT , numtaps : <L :: Length as StaticMaybe < usize > >:: Opposite , w : W )
168
+ -> ( L , Self :: Output )
169
+ where
170
+ TT : TwoSidedRange < T :: Real > + Clone ,
171
+ W : Maybe < Vec < K > >
172
+ {
173
+ let ( t, y) = self . to_ss ( )
174
+ . impulse_s ( t, numtaps, w) ;
175
+
176
+ (
177
+ t,
178
+ y. into_iter ( )
179
+ . next ( )
180
+ . unwrap ( )
181
+ )
182
+ }
183
+ }
184
+
185
+ impl < T , B , A , S , L > ImpulseS < L > for Sos < T , B , A , S >
186
+ where
187
+ T : ComplexFloat ,
188
+ B : Maybe < [ T ; 3 ] > + MaybeOwnedList < T > ,
189
+ A : Maybe < [ T ; 3 ] > + MaybeOwnedList < T > ,
190
+ S : MaybeList < Tf < T , B , A > > ,
191
+ L : List < T :: Real > ,
192
+ <L :: Length as StaticMaybe < usize > >:: Opposite : Sized ,
193
+ L :: Mapped < T > : List < T > + ListOrSingle < L :: Mapped < T > > ,
194
+ Self : System < Set = T > + ToSs < T , Array2 < T > , Array2 < T > , Array2 < T > , Array2 < T > > ,
195
+ Array2 < T > : SsAMatrix < T , Array2 < T > , Array2 < T > , Array2 < T > > + SsBMatrix < T , Array2 < T > , Array2 < T > , Array2 < T > > + SsCMatrix < T , Array2 < T > , Array2 < T > , Array2 < T > > + SsDMatrix < T , Array2 < T > , Array2 < T > , Array2 < T > > ,
196
+ Ss < T , Array2 < T > , Array2 < T > , Array2 < T > , Array2 < T > > : System < Set = T > + ImpulseS < L , Output = Array2 < L :: Mapped < T > > >
197
+ {
198
+ type OutputI = L :: Mapped < T > ;
199
+ type Output = L :: Mapped < T > ;
200
+
201
+ fn impulse_s < TT , W > ( self , t : TT , numtaps : <L :: Length as StaticMaybe < usize > >:: Opposite , w : W )
202
+ -> ( L , Self :: Output )
203
+ where
204
+ TT : TwoSidedRange < T :: Real > + Clone ,
205
+ W : Maybe < Vec < T > >
206
+ {
207
+ let ( t, y) = self . to_ss ( )
208
+ . impulse_s ( t, numtaps, w) ;
209
+
210
+ (
211
+ t,
212
+ y. into_iter ( )
213
+ . next ( )
214
+ . unwrap ( )
215
+ )
216
+ }
217
+ }
218
+
219
+ #[ cfg( test) ]
220
+ mod test
221
+ {
222
+ use core:: f64:: consts:: TAU ;
223
+
224
+ use array_math:: ArrayOps ;
225
+
226
+ use crate :: { analysis:: ImpulseS , gen:: filter:: { BesselF , FilterGenPlane , FilterGenType } , plot, systems:: Tf } ;
227
+
228
+ #[ test]
229
+ fn test ( )
230
+ {
231
+ let h = Tf :: besself ( 5 , [ TAU * 12.0 ] , FilterGenType :: LowPass , FilterGenPlane :: S )
232
+ . unwrap ( ) ;
233
+
234
+ const T : f64 = 1.25 ;
235
+ const N : usize = 200 ;
236
+ let ( t, y) : ( [ _ ; N ] , _ ) = h. impulse_s ( 0.0 ..T , ( ) , ( ) ) ;
237
+
238
+ plot:: plot_curves ( "y(t)" , "plots/y_t_impulse_s.png" , [ & t. zip ( y) ] )
239
+ . unwrap ( ) ;
240
+ }
241
+ }
0 commit comments