roctave 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +674 -0
  3. data/README.md +33 -0
  4. data/ext/roctave/cu8_file_reader.c +331 -0
  5. data/ext/roctave/cu8_file_reader.h +30 -0
  6. data/ext/roctave/extconf.rb +6 -0
  7. data/ext/roctave/fir_filter.c +795 -0
  8. data/ext/roctave/fir_filter.h +29 -0
  9. data/ext/roctave/freq_shifter.c +410 -0
  10. data/ext/roctave/freq_shifter.h +29 -0
  11. data/ext/roctave/iir_filter.c +462 -0
  12. data/ext/roctave/iir_filter.h +29 -0
  13. data/ext/roctave/roctave.c +38 -0
  14. data/ext/roctave/roctave.h +27 -0
  15. data/lib/roctave.rb +168 -0
  16. data/lib/roctave/bilinear.rb +92 -0
  17. data/lib/roctave/butter.rb +87 -0
  18. data/lib/roctave/cheby.rb +180 -0
  19. data/lib/roctave/cu8_file_reader.rb +45 -0
  20. data/lib/roctave/dft.rb +280 -0
  21. data/lib/roctave/filter.rb +64 -0
  22. data/lib/roctave/finite_difference_coefficients.rb +73 -0
  23. data/lib/roctave/fir.rb +121 -0
  24. data/lib/roctave/fir1.rb +134 -0
  25. data/lib/roctave/fir2.rb +246 -0
  26. data/lib/roctave/fir_design.rb +311 -0
  27. data/lib/roctave/firls.rb +380 -0
  28. data/lib/roctave/firpm.rb +499 -0
  29. data/lib/roctave/freq_shifter.rb +47 -0
  30. data/lib/roctave/freqz.rb +233 -0
  31. data/lib/roctave/iir.rb +80 -0
  32. data/lib/roctave/interp1.rb +78 -0
  33. data/lib/roctave/plot.rb +748 -0
  34. data/lib/roctave/poly.rb +46 -0
  35. data/lib/roctave/roots.rb +73 -0
  36. data/lib/roctave/sftrans.rb +157 -0
  37. data/lib/roctave/version.rb +3 -0
  38. data/lib/roctave/window.rb +116 -0
  39. data/roctave.gemspec +79 -0
  40. data/samples/butter.rb +12 -0
  41. data/samples/cheby.rb +28 -0
  42. data/samples/dft.rb +18 -0
  43. data/samples/differentiator.rb +48 -0
  44. data/samples/differentiator_frequency_scaling.rb +52 -0
  45. data/samples/fft.rb +40 -0
  46. data/samples/finite_difference_coefficient.rb +53 -0
  47. data/samples/fir1.rb +13 -0
  48. data/samples/fir2.rb +14 -0
  49. data/samples/fir2_windows.rb +29 -0
  50. data/samples/fir2bank.rb +30 -0
  51. data/samples/fir_low_pass.rb +44 -0
  52. data/samples/firls.rb +77 -0
  53. data/samples/firpm.rb +78 -0
  54. data/samples/hilbert_transformer.rb +20 -0
  55. data/samples/hilbert_transformer_frequency_scaling.rb +47 -0
  56. data/samples/plot.rb +45 -0
  57. data/samples/stem.rb +8 -0
  58. data/samples/type1.rb +25 -0
  59. data/samples/type3.rb +24 -0
  60. data/samples/windows.rb +25 -0
  61. metadata +123 -0
@@ -0,0 +1,499 @@
1
+ ## Copyright (C) 2019 Théotime Bollengier <theotime.bollengier@gmail.com>
2
+ ##
3
+ ## This file is part of Roctave
4
+ ##
5
+ ## Roctave is free software: you can redistribute it and/or modify
6
+ ## it under the terms of the GNU General Public License as published by
7
+ ## the Free Software Foundation, either version 3 of the License, or
8
+ ## (at your option) any later version.
9
+ ##
10
+ ## Roctave is distributed in the hope that it will be useful,
11
+ ## but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ ## GNU General Public License for more details.
14
+ ##
15
+ ## You should have received a copy of the GNU General Public License
16
+ ## along with Roctave. If not, see <https://www.gnu.org/licenses/>.
17
+
18
+
19
+ class Matrix
20
+ def puts
21
+ strings = Array.new(self.row_size){Array.new(self.column_size)}
22
+ (0 ... self.row_size).each do |i|
23
+ (0 ... self.column_size).each do |j|
24
+ strings[i][j] = self[i, j].round(4).to_s
25
+ end
26
+ end
27
+ maxstrlen = strings.flatten.collect{|s| s.length + 2}.max
28
+ Kernel.puts
29
+ (0 ... self.row_size).each do |i|
30
+ if i == 0 and i == self.row_size - 1 then
31
+ print ' ['
32
+ elsif i == 0 then
33
+ print ' ⎡'
34
+ elsif i == self.row_size - 1 then
35
+ print ' ⎣'
36
+ else
37
+ print ' ⎢'
38
+ end
39
+
40
+ (0 ... self.column_size).each do |j|
41
+ print strings[i][j].center(maxstrlen)
42
+ end
43
+
44
+ if i == 0 and i == self.row_size - 1 then
45
+ Kernel.puts ']'
46
+ elsif i == 0 then
47
+ Kernel.puts '⎤'
48
+ elsif i == self.row_size - 1 then
49
+ Kernel.puts '⎦'
50
+ else
51
+ Kernel.puts '⎥'
52
+ end
53
+ end
54
+ Kernel.puts
55
+ end
56
+ end
57
+
58
+
59
+ module Roctave
60
+ # @!group FIR filters
61
+
62
+ ##
63
+ # Weighted least-squares method for FIR filter approximation by optimization.
64
+ # Minimizes the square of the energy of the error function.
65
+ # @param n [Integer] The filter order
66
+ # @param f [Array<Float, Array<Float>, Range>] Frequency band edges, onced flattened, must be of even length
67
+ # @param a [Array<Float, Array<Float>, Range>] Magnitude at frequency bands. Each element must be a scalar (for the whole band), or a range or a two element array (for the two band edges of the band). Length +a+ == length +f+ / 2
68
+ # @param w [Array<Float, Array<Float>, Range] Weight at frequency bands. Each element must be a scalar (for the whole band), or a range or a two element array (for the two band edges of the band). Length +w+ == length +f+ / 2
69
+ # @param type [:odd_symmetry, :even_symmetry] Specify the symmetry of the filter. nil and :even_symmetry are the same and default, for type 1 and 2 filters, :odd_symmetry is for type 3 and 4 filters.
70
+ # @param grid [Integer] The length of the grid over which the frequency response is evaluated. Defaults to 16, for an interpolation on 16*+n+.
71
+ # @return [Array<Float>] The filter coefficients B
72
+ def self.firpm (n, f, a, *args)
73
+ raise ArgumentError.new "Expecting no more than 6 arguments" if args.length > 3
74
+
75
+ n = [1, n.to_i].max
76
+
77
+ case f
78
+ when Array
79
+ when Range
80
+ f = [f]
81
+ else
82
+ raise ArgumentError.new "F must be an array or a range"
83
+ end
84
+ f.collect! do |e|
85
+ case e
86
+ when Range
87
+ [e.begin.to_f, e.end.to_f]
88
+ when Array
89
+ raise ArgumentError.new "Elements of F which are arrays must have exaclty two floats" unless (e.length == 2 and e.first.kind_of?(Float) and e.last.kind_of?(Float))
90
+ [e.first.to_f, e.last.to_f]
91
+ else
92
+ e.to_f
93
+ end
94
+ end
95
+ f = f.flatten
96
+ raise ArgumentError.new "At least one frequency band must be specified!" if f.empty?
97
+ raise ArgumentError.new "Once flattened, F must have an even number of frequency bands!" unless (f.length & 1) == 0
98
+ raise ArgumentError.new "F must have at least one band!" unless f.length >= 2
99
+ f.each do |e|
100
+ raise ArgumentError.new "Frequency band edges must be in the range [0, 1]" unless (e >= 0.0 and e <= 1.0)
101
+ end
102
+ (1...f.length).each do |i|
103
+ raise ArgumentError.new "Frequecy band edges must be strictly increasing" if f[i-1] >= f[i]
104
+ end
105
+
106
+ case a
107
+ when Array
108
+ when Range
109
+ [a]
110
+ when Numeric
111
+ [a]
112
+ else
113
+ raise ArgumentError.new "A must be an array or a range"
114
+ end
115
+ raise ArgumentError.new "Length of A must be half the length of F" unless a.length == f.length/2
116
+ a.collect! do |e|
117
+ case e
118
+ when Range
119
+ [e.begin.to_f.abs, e.end.to_f.abs]
120
+ when Array
121
+ raise ArgumentError.new "Elements of A which are arrays must have at least two floats" if e.length < 2
122
+ e.collect{|v| v.to_f}
123
+ else
124
+ [e.to_f.abs, e.to_f.abs]
125
+ end
126
+ end
127
+
128
+ w = nil
129
+ type = :even_symmetry
130
+ grid = 16
131
+
132
+ args.each.with_index do |arg, i|
133
+ case arg
134
+ when :even_symmetry
135
+ type = :even_symmetry
136
+ when :odd_symmetry
137
+ type = :odd_symmetry
138
+ when Numeric
139
+ grid = [1, arg.to_i].max
140
+ STDERR.puts "WARNING: recommended grid sampling factor are integers in the range [8, 16]." unless Range.new(8, 16).include?(grid)
141
+ when Array
142
+ raise ArgumentError.new "Length of W must be half the length of F" unless arg.length == f.length/2
143
+ w = arg.collect do |e|
144
+ case e
145
+ when Range
146
+ [e.begin.to_f.abs, e.end.to_f.abs]
147
+ when Array
148
+ raise ArgumentError.new "Elements of W which are arrays must have at least two floats" if e.length < 2
149
+ e.collect{|v| v.to_f}
150
+ else
151
+ [e.to_f.abs, e.to_f.abs]
152
+ end
153
+ end
154
+ else
155
+ raise ArgumentError.new "Argument #{i+4} must either be :odd_symmetry, :even_symmetry, an array of weight or the grid sampling (Integer)"
156
+ end
157
+ end
158
+
159
+ w = (f.length / 2).times.collect{[1.0, 1.0]} if w.nil?
160
+
161
+ bands = (0 ... a.length).collect do |i|
162
+ {
163
+ frequencies: Range.new(f[2*i], f[2*i+1]),
164
+ amplitudes: a[i],
165
+ weights: w[i]
166
+ }
167
+ end
168
+ band_edges = bands.collect{|h| [h[:frequencies].begin, h[:frequencies].end]}.flatten.collect{|v| v*Math::PI}.uniq
169
+
170
+ ## Create the sampling grid by interpolation ##
171
+ nb_sample_points = grid*n
172
+ constrained_frequency_amount = bands.inject(0.0){|m, h| m + h[:frequencies].end - h[:frequencies].begin}
173
+ # debug_amp_plot_args = []
174
+ # debug_weight_plot_args = []
175
+ bands.each do |band|
176
+ # debug_amp_plot_args << Roctave.linspace(band[:frequencies].begin, band[:frequencies].end, band[:amplitudes].length)
177
+ # debug_amp_plot_args << band[:amplitudes].collect{|e| e}
178
+ # debug_amp_plot_args << '-+b'
179
+ # debug_weight_plot_args << Roctave.linspace(band[:frequencies].begin, band[:frequencies].end, band[:weights].length)
180
+ # debug_weight_plot_args << band[:weights].collect{|e| e}
181
+ # debug_weight_plot_args << '-+b'
182
+
183
+ fi = Roctave.linspace(band[:frequencies].begin, band[:frequencies].end, [2, ((band[:frequencies].end - band[:frequencies].begin) * nb_sample_points / constrained_frequency_amount).ceil].max)
184
+ ai = Roctave.interp1(Roctave.linspace(band[:frequencies].begin, band[:frequencies].end, band[:amplitudes].length), band[:amplitudes], fi)
185
+ wi = Roctave.interp1(Roctave.linspace(band[:frequencies].begin, band[:frequencies].end, band[:weights].length), band[:weights], fi)
186
+
187
+ # debug_amp_plot_args << fi.collect{|e| e}
188
+ # debug_amp_plot_args << ai.collect{|e| e}
189
+ # debug_amp_plot_args << '-xr'
190
+ # debug_weight_plot_args << fi.collect{|e| e}
191
+ # debug_weight_plot_args << wi.collect{|e| e}
192
+ # debug_weight_plot_args << '-xr'
193
+
194
+ band[:frequencies] = fi.collect{|v| v*Math::PI}
195
+ band[:amplitudes] = ai
196
+ band[:weights] = wi
197
+ end
198
+ nb_sample_points = bands.inject(0.0){|m, h| m + h[:frequencies].length}
199
+
200
+
201
+ ## Filter type ##
202
+ if type == :even_symmetry then
203
+ if (n & 1) == 0 then
204
+ filter_type = 1
205
+ beta = 0.0
206
+ q = -> w { 1.0 }
207
+ l = n / 2
208
+ coefs_from_p = -> p {
209
+ (-l .. l).collect{|m| m.abs}.collect do |m|
210
+ if m == 0 then
211
+ p[m, 0]
212
+ else
213
+ p[m, 0] / 2.0
214
+ end
215
+ end
216
+ }
217
+ else
218
+ filter_type = 2
219
+ beta = 0.0
220
+ q = -> w { Math.cos(w/2.0) }
221
+ l = (n - 1) / 2
222
+ coefs_from_p = -> p {
223
+ id = (1..l+1).to_a
224
+ (id.reverse + id).collect{ |m|
225
+ if m == 1 then
226
+ p[0, 0] + 0.5*p[1, 0]
227
+ elsif m == l+1 then
228
+ 0.5*p[l, 0]
229
+ else
230
+ 0.5*(p[m-1, 0] + p[m, 0])
231
+ end
232
+ }.collect{|v| v/2.0}
233
+ }
234
+ end
235
+ else
236
+ if (n & 1) == 0 then
237
+ filter_type = 3
238
+ beta = Math::PI/2
239
+ q = -> w { Math.sin(w) }
240
+ l = n / 2 - 1
241
+ coefs_from_p = -> p {
242
+ id = (1..l+1).to_a
243
+ (id.reverse + [0] + id).collect{ |m|
244
+ if m == 0 then
245
+ 0.0
246
+ elsif m == 1 then
247
+ p[0, 0] - 0.5*p[2, 0]
248
+ elsif m >= l then
249
+ 0.5*p[m-1, 0]
250
+ else
251
+ 0.5*(p[m-1,0] - p[m+1, 0])
252
+ end
253
+ }.collect.with_index{ |v, i|
254
+ if i < l + 1 then
255
+ v/2.0
256
+ else
257
+ -v/2.0
258
+ end
259
+ }
260
+ }
261
+ else
262
+ filter_type = 4
263
+ beta = Math::PI/2
264
+ q = -> w { Math.sin(w/2.0) }
265
+ l = (n - 1) / 2
266
+ coefs_from_p = -> p {
267
+ id = (1..l+1).to_a
268
+ (id.reverse + id).collect{ |m|
269
+ if m == 1 then
270
+ p[0, 0] - 0.5*p[1, 0]
271
+ elsif m == l+1 then
272
+ 0.5*p[l, 0]
273
+ else
274
+ 0.5*(p[m-1, 0] - p[m, 0])
275
+ end
276
+ }.collect.with_index{ |v, i|
277
+ if i < l + 1 then
278
+ v/2.0
279
+ else
280
+ -v/2.0
281
+ end
282
+ }
283
+ }
284
+ end
285
+ end
286
+ # puts "Filter Type #{case filter_type; when 1 then 'I'; when 2 then 'II'; when 3 then 'III'; else 'IV' end}"
287
+
288
+
289
+ ## Create the matrices ##
290
+ frequencies = bands.inject([]){|m, h| m + h[:frequencies]}
291
+ amplitudes = bands.inject([]){|m, h| m + h[:amplitudes]}
292
+ weights = bands.inject([]){|m, h| m + h[:weights]}
293
+
294
+ band_edges_faw = []
295
+ frequencies.each.with_index do |v, i|
296
+ if band_edges.include?(v) then
297
+ band_edges_faw << {f: v, a: amplitudes[i], w: weights[i]}
298
+ end
299
+ end
300
+
301
+ # ## (i) Initialize an estimate for the extreme frequencies w0, w1, ..., wL+1 by selecting (L+2)
302
+ # ## equally spaced frequencies at the bands specified for the desired filter.
303
+ #
304
+ # nb_test_points = l+2
305
+ # extreme_frequencies = :wq
306
+ # constrained_frequency_amount = bands.inject(0.0){|m, h| m + h[:frequencies].end - h[:frequencies].begin}
307
+ # bands.each do |band|
308
+ # fi = Roctave.linspace(band[:frequencies].begin, band[:frequencies].end, [2, ((band[:frequencies].end - band[:frequencies].begin) * nb_sample_points / constrained_frequency_amount).ceil].max)
309
+ # ai = Roctave.interp1(Roctave.linspace(band[:frequencies].begin, band[:frequencies].end, band[:amplitudes].length), band[:amplitudes], fi)
310
+ # wi = Roctave.interp1(Roctave.linspace(band[:frequencies].begin, band[:frequencies].end, band[:weights].length), band[:weights], fi)
311
+ #
312
+ # band[:frequencies] = fi.collect{|v| v*Math::PI}
313
+ # band[:amplitudes] = ai
314
+ # band[:weights] = wi
315
+ # end
316
+ # nb_sample_points = bands.inject(0.0){|m, h| m + h[:frequencies].length}
317
+ # ####
318
+
319
+
320
+ mat_Wq2 = Matrix.build(nb_sample_points) do |i, j|
321
+ if i == j then
322
+ (weights[i] * q.call(frequencies[i]))**2
323
+ else
324
+ 0.0
325
+ end
326
+ end
327
+
328
+ mat_dq = Matrix.build(nb_sample_points, 1) do |i|
329
+ qw = q.call(frequencies[i])
330
+ qw = 0.000000001 if qw == 0.0
331
+ amplitudes[i] / qw
332
+ end
333
+
334
+ mat_U = Matrix.build(nb_sample_points, l + 1) do |i, j|
335
+ Math.cos(j * frequencies[i])
336
+ end
337
+
338
+ mat_UT_times_mat_Wq2 = mat_U.transpose * mat_Wq2
339
+ p = (mat_UT_times_mat_Wq2 * mat_U).inverse * (mat_UT_times_mat_Wq2 * mat_dq)
340
+
341
+ p.puts
342
+
343
+ b = coefs_from_p.call(p)
344
+
345
+ ###
346
+ # Matrix.column_vector(b).puts
347
+ #
348
+ # if filter_type == 1 or filter_type == 3 then
349
+ # Roctave.stem((-n/2..n/2).to_a, b, :filled, grid: true)
350
+ # else
351
+ # Roctave.stem((n+1).times.collect{|i| i - (n+1)/2.0 + 0.5}, b, :filled, grid: true)
352
+ # end
353
+ #
354
+ # r2 = Roctave.dft(b, 2048)
355
+ # h2 = r2[0...1024].abs
356
+ # p2 = r2[0...1024].arg
357
+ # p2 = Roctave.unwrap(p2)
358
+ # w2 = Roctave.linspace(0, 1, 1024)
359
+ # debug_amp_plot_args << w2
360
+ # debug_amp_plot_args << h2
361
+ # debug_amp_plot_args << '-g;Response;'
362
+ #
363
+ # #Roctave.plot(*debug_weight_plot_args, title: 'Target weights', xlim: (0 .. 1), grid: true)
364
+ # Roctave.plot(*debug_amp_plot_args, title: 'Target filter magnitude response', xlim: (0 .. 1), grid: true)
365
+ # Roctave.plot(w2, h2.collect{|v| 10*Math.log10(v)}, xlabel: 'Normalized frequency', ylabel: 'Magnitude response (dB)', grid: true, title: 'Magnitude')
366
+ # Roctave.plot(w2, p2, grid: true, title: 'Phase')
367
+ ###
368
+
369
+ # Evaluate the response
370
+ p_w = -> fre {
371
+ (0..l).inject(0.0) do |m, i|
372
+ m + p[i,0]*Math.cos(fre*i)
373
+ end
374
+ }
375
+ alpha = n / 2.0
376
+ # freq = Roctave.linspace(0, Math::PI, 1024)
377
+ # resp = freq.collect{|v| Complex.polar(1.0, -alpha*v - beta)*q.call(v)*p_w.call(v)}
378
+ # Roctave.plot(freq.collect{|v| v/Math::PI}, resp.abs, title: 'Evaluated response', grid: true)
379
+
380
+ # Evaluate the error
381
+ error = frequencies.length.times.collect do |i|
382
+ weights[i]*(amplitudes[i] - q.call(frequencies[i])*p_w.call(frequencies[i]))
383
+ end
384
+ #error.collect!{|v| v.abs}
385
+
386
+ i = 0
387
+ loop do
388
+ maximum_freq = []
389
+ maximum_err = []
390
+ maximum_wei = []
391
+ maximum_amp = []
392
+ (1...frequencies.length - 1).each do |i|
393
+ if (error[i-1] < error[i] and error[i+1] < error[i]) or (error[i-1] > error[i] and error[i+1] > error[i]) then
394
+ maximum_freq << frequencies[i]
395
+ maximum_err << error[i]
396
+ maximum_wei << weights[i]
397
+ maximum_amp << amplitudes[i]
398
+ end
399
+ end
400
+
401
+ #Roctave.plot(frequencies, error, ';Error;', maximum_freq, maximum_err, 'o;mamimums;', title: 'Evaluated error', grid: true, xlim: [0, Math::PI])
402
+
403
+ maximum_freq_and_error = (0...maximum_freq.length).collect{|i|
404
+ {f: maximum_freq[i], e: maximum_err[i], a: maximum_amp[i], w: maximum_wei[i]}
405
+ }.reject{|h| band_edges.include?(h[:f])}.sort_by{|h| h[:e]}.reverse
406
+ l_plus_two_extremal = (band_edges_faw + maximum_freq_and_error[(0...(l+2 - band_edges_faw.length))]).sort_by{|h| h[:f]}
407
+ raise "Couldn't get #{l+2} extremals!" if (l_plus_two_extremal.length != l+2 or l_plus_two_extremal.include?(nil))
408
+ l_plus_two_extremal_frequencies = l_plus_two_extremal.collect{|h| h[:f]}
409
+ l_plus_two_extremal_amplitudes = l_plus_two_extremal.collect{|h| h[:a]}
410
+ l_plus_two_extremal_weights = l_plus_two_extremal.collect{|h| h[:w]}
411
+
412
+ ###
413
+
414
+ ak = (0 ... l+2).collect do |i|
415
+ (0 ... l+2).inject(1.0) do |m, j|
416
+ if j == i then
417
+ m
418
+ else
419
+ m / (Math.cos(l_plus_two_extremal_frequencies[i]) - Math.cos(l_plus_two_extremal_frequencies[j]))
420
+ end
421
+ end
422
+ end
423
+ deltatruc_numerator = (0 ... l+2).inject(0.0) do |m, i|
424
+ m + ak[i] * l_plus_two_extremal_amplitudes[i] / q.call(l_plus_two_extremal_frequencies[i])
425
+ end
426
+ deltatruc_denominator = (0 ... l+2).inject(0.0) do |m, i|
427
+ m + (-1)**i * ak[i] / l_plus_two_extremal_weights[i] * q.call(l_plus_two_extremal_frequencies[i])
428
+ end
429
+ deltatruc = deltatruc_numerator / deltatruc_denominator
430
+ puts "d_num = #{deltatruc_numerator}"
431
+ puts "d_den = #{deltatruc_denominator}"
432
+ puts "d = #{deltatruc}"
433
+
434
+
435
+
436
+ ## Interpolate p(w) ##
437
+
438
+ resp_interpolate = frequencies.collect.with_index do |freq, i|
439
+ k = l_plus_two_extremal_frequencies.index(freq)
440
+ if k then
441
+ amplitudes[i] - (((-1)**k) * deltatruc / weights[i])
442
+ else
443
+ beta_k = ak.collect.with_index{|v, k| v*(Math.cos(l_plus_two_extremal_frequencies[k]) - Math.cos(l_plus_two_extremal_frequencies[l+1]))}
444
+ betai_sur_machin = (0..l).collect do |j|
445
+ beta_k[j] / (Math.cos(freq) - Math.cos(l_plus_two_extremal_frequencies[j]))
446
+ end
447
+ den = betai_sur_machin.inject(&:+)
448
+ num = (0..l).inject(0.0) do |m, j|
449
+ m + betai_sur_machin[j] * ((l_plus_two_extremal_amplitudes[j] / q.call(l_plus_two_extremal_frequencies[j])) - (((-1)**j) * deltatruc / (l_plus_two_extremal_weights[j] * q.call(l_plus_two_extremal_frequencies[j]))))
450
+ end
451
+ q.call(freq) * (num / den)
452
+ end
453
+ end
454
+ ######################
455
+
456
+ i += 1
457
+
458
+ debug_plot_args = []
459
+ (0 ... band_edges_faw.length/2).each do |i|
460
+ debug_plot_args << [band_edges_faw[i*2][:f], band_edges_faw[i*2+1][:f]]
461
+ debug_plot_args << [band_edges_faw[i*2][:a], band_edges_faw[i*2+1][:a]]
462
+ debug_plot_args << "-xb#{(i == 0) ? ';Target;' : ''}"
463
+
464
+ debug_plot_args << [band_edges_faw[i*2][:f], band_edges_faw[i*2+1][:f]]
465
+ debug_plot_args << [band_edges_faw[i*2][:a] + deltatruc, band_edges_faw[i*2+1][:a] + deltatruc]
466
+ debug_plot_args << "-k#{(i == 0) ? ';Delta;' : ''}"
467
+ debug_plot_args << [band_edges_faw[i*2][:f], band_edges_faw[i*2+1][:f]]
468
+ debug_plot_args << [band_edges_faw[i*2][:a] - deltatruc, band_edges_faw[i*2+1][:a] - deltatruc]
469
+ debug_plot_args << '-k'
470
+ end
471
+ debug_plot_args << Roctave.linspace(0, Math::PI, 1024)
472
+ debug_plot_args << debug_plot_args[-1].collect{|v| q.call(v)*p_w.call(v)}
473
+ debug_plot_args << '-g;First response;'
474
+
475
+ debug_plot_args << frequencies
476
+ debug_plot_args << resp_interpolate
477
+ debug_plot_args << '-r;New response;'
478
+
479
+ debug_plot_args << l_plus_two_extremal_frequencies
480
+ debug_plot_args << Roctave.interp1(frequencies, resp_interpolate, l_plus_two_extremal_frequencies)
481
+ debug_plot_args << 'pr;Extremals;'
482
+ Roctave.plot(*debug_plot_args, grid: true, xlim: [0, Math::PI], title: "Iteration #{i}")
483
+
484
+ error = (0 ... frequencies.length).collect do |i|
485
+ weights[i]*(amplitudes[i] - resp_interpolate[i])
486
+ end
487
+
488
+ max_error = error.collect{|r| r.abs - deltatruc.abs}.max
489
+ puts "Maximum |error - delta| = #{max_error}"
490
+ break if max_error < 0.001 or i > 10
491
+ end
492
+
493
+ raise "Failed to converge" if i > 10
494
+ ###
495
+
496
+ b
497
+ end
498
+ end
499
+