00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #ifdef HAVE_CONFIG_H
00032 #include <config.h>
00033 #endif
00034
00035 #include "quit.h"
00036
00037 #include "defun-dld.h"
00038 #include "error.h"
00039 #include "oct-obj.h"
00040
00041 #if !defined (CXX_NEW_FRIEND_TEMPLATE_DECL)
00042 extern MArray<double>
00043 filter (MArray<double>&, MArray<double>&, MArray<double>&, int dim);
00044
00045 extern MArray<Complex>
00046 filter (MArray<Complex>&, MArray<Complex>&, MArray<Complex>&, int dim);
00047
00048 extern MArray<float>
00049 filter (MArray<float>&, MArray<float>&, MArray<float>&, int dim);
00050
00051 extern MArray<FloatComplex>
00052 filter (MArray<FloatComplex>&, MArray<FloatComplex>&, MArray<FloatComplex>&, int dim);
00053 #endif
00054
00055 template <class T>
00056 MArray<T>
00057 filter (MArray<T>& b, MArray<T>& a, MArray<T>& x, MArray<T>& si,
00058 int dim = 0)
00059 {
00060 MArray<T> y;
00061
00062 octave_idx_type a_len = a.length ();
00063 octave_idx_type b_len = b.length ();
00064
00065 octave_idx_type ab_len = a_len > b_len ? a_len : b_len;
00066
00067
00068
00069
00070
00071 b.resize (dim_vector (ab_len, 1), 0.0);
00072 if (a_len > 1)
00073 a.resize (dim_vector (ab_len, 1), 0.0);
00074
00075 T norm = a (0);
00076
00077 if (norm == static_cast<T>(0.0))
00078 {
00079 error ("filter: the first element of A must be non-zero");
00080 return y;
00081 }
00082
00083 dim_vector x_dims = x.dims ();
00084 if (dim < 0 || dim > x_dims.length ())
00085 {
00086 error ("filter: DIM must be a valid dimension");
00087 return y;
00088 }
00089
00090 octave_idx_type x_len = x_dims(dim);
00091
00092 dim_vector si_dims = si.dims ();
00093 octave_idx_type si_len = si_dims(0);
00094
00095 if (si_len != ab_len - 1)
00096 {
00097 error ("filter: first dimension of SI must be of length max (length (a), length (b)) - 1");
00098 return y;
00099 }
00100
00101 if (si_dims.length () != x_dims.length ())
00102 {
00103 error ("filter: dimensionality of SI and X must agree");
00104 return y;
00105 }
00106
00107 for (octave_idx_type i = 1; i < dim; i++)
00108 {
00109 if (si_dims(i) != x_dims(i-1))
00110 {
00111 error ("filter: dimensionality of SI and X must agree");
00112 return y;
00113 }
00114 }
00115 for (octave_idx_type i = dim+1; i < x_dims.length (); i++)
00116 {
00117 if (si_dims(i) != x_dims(i))
00118 {
00119 error ("filter: dimensionality of SI and X must agree");
00120 return y;
00121 }
00122 }
00123
00124 if (x_len == 0)
00125 return x;
00126
00127 if (norm != static_cast<T>(1.0))
00128 {
00129 a = a / norm;
00130 b = b / norm;
00131 }
00132
00133 if (a_len <= 1 && si_len <= 0)
00134 return b(0) * x;
00135
00136 y.resize (x_dims, 0.0);
00137
00138 int x_stride = 1;
00139 for (int i = 0; i < dim; i++)
00140 x_stride *= x_dims(i);
00141
00142 octave_idx_type x_num = x_dims.numel () / x_len;
00143 for (octave_idx_type num = 0; num < x_num; num++)
00144 {
00145 octave_idx_type x_offset;
00146 if (x_stride == 1)
00147 x_offset = num * x_len;
00148 else
00149 {
00150 octave_idx_type x_offset2 = 0;
00151 x_offset = num;
00152 while (x_offset >= x_stride)
00153 {
00154 x_offset -= x_stride;
00155 x_offset2++;
00156 }
00157 x_offset += x_offset2 * x_stride * x_len;
00158 }
00159 octave_idx_type si_offset = num * si_len;
00160
00161 if (a_len > 1)
00162 {
00163 T *py = y.fortran_vec ();
00164 T *psi = si.fortran_vec ();
00165
00166 const T *pa = a.data ();
00167 const T *pb = b.data ();
00168 const T *px = x.data ();
00169
00170 psi += si_offset;
00171
00172 for (octave_idx_type i = 0, idx = x_offset; i < x_len; i++, idx += x_stride)
00173 {
00174 py[idx] = psi[0] + pb[0] * px[idx];
00175
00176 if (si_len > 0)
00177 {
00178 for (octave_idx_type j = 0; j < si_len - 1; j++)
00179 {
00180 OCTAVE_QUIT;
00181
00182 psi[j] = psi[j+1] - pa[j+1] * py[idx] + pb[j+1] * px[idx];
00183 }
00184
00185 psi[si_len-1] = pb[si_len] * px[idx] - pa[si_len] * py[idx];
00186 }
00187 else
00188 {
00189 OCTAVE_QUIT;
00190
00191 psi[0] = pb[si_len] * px[idx] - pa[si_len] * py[idx];
00192 }
00193 }
00194 }
00195 else if (si_len > 0)
00196 {
00197 T *py = y.fortran_vec ();
00198 T *psi = si.fortran_vec ();
00199
00200 const T *pb = b.data ();
00201 const T *px = x.data ();
00202
00203 psi += si_offset;
00204
00205 for (octave_idx_type i = 0, idx = x_offset; i < x_len; i++, idx += x_stride)
00206 {
00207 py[idx] = psi[0] + pb[0] * px[idx];
00208
00209 if (si_len > 1)
00210 {
00211 for (octave_idx_type j = 0; j < si_len - 1; j++)
00212 {
00213 OCTAVE_QUIT;
00214
00215 psi[j] = psi[j+1] + pb[j+1] * px[idx];
00216 }
00217
00218 psi[si_len-1] = pb[si_len] * px[idx];
00219 }
00220 else
00221 {
00222 OCTAVE_QUIT;
00223
00224 psi[0] = pb[1] * px[idx];
00225 }
00226 }
00227 }
00228 }
00229
00230 return y;
00231 }
00232
00233 #if !defined (CXX_NEW_FRIEND_TEMPLATE_DECL)
00234 extern MArray<double>
00235 filter (MArray<double>&, MArray<double>&, MArray<double>&,
00236 MArray<double>&, int dim);
00237
00238 extern MArray<Complex>
00239 filter (MArray<Complex>&, MArray<Complex>&, MArray<Complex>&,
00240 MArray<Complex>&, int dim);
00241
00242 extern MArray<float>
00243 filter (MArray<float>&, MArray<float>&, MArray<float>&,
00244 MArray<float>&, int dim);
00245
00246 extern MArray<FloatComplex>
00247 filter (MArray<FloatComplex>&, MArray<FloatComplex>&, MArray<FloatComplex>&,
00248 MArray<FloatComplex>&, int dim);
00249 #endif
00250
00251 template <class T>
00252 MArray<T>
00253 filter (MArray<T>& b, MArray<T>& a, MArray<T>& x, int dim = -1)
00254 {
00255 dim_vector x_dims = x.dims();
00256
00257 if (dim < 0)
00258 {
00259
00260 while (dim < x_dims.length () && x_dims(dim) <= 1)
00261 dim++;
00262
00263
00264 if (dim == x_dims.length ())
00265 dim = 0;
00266 }
00267 else
00268 if (dim < 0 || dim > x_dims.length ())
00269 {
00270 error ("filter: DIM must be a valid dimension");
00271 return MArray<T> ();
00272 }
00273
00274 octave_idx_type a_len = a.length ();
00275 octave_idx_type b_len = b.length ();
00276
00277 octave_idx_type si_len = (a_len > b_len ? a_len : b_len) - 1;
00278 dim_vector si_dims = x.dims ();
00279 for (int i = dim; i > 0; i--)
00280 si_dims(i) = si_dims(i-1);
00281 si_dims(0) = si_len;
00282
00283 MArray<T> si (si_dims, T (0.0));
00284
00285 return filter (b, a, x, si, dim);
00286 }
00287
00288 DEFUN_DLD (filter, args, nargout,
00289 "-*- texinfo -*-\n\
00290 @deftypefn {Loadable Function} {y =} filter (@var{b}, @var{a}, @var{x})\n\
00291 @deftypefnx {Loadable Function} {[@var{y}, @var{sf}] =} filter (@var{b}, @var{a}, @var{x}, @var{si})\n\
00292 @deftypefnx {Loadable Function} {[@var{y}, @var{sf}] =} filter (@var{b}, @var{a}, @var{x}, [], @var{dim})\n\
00293 @deftypefnx {Loadable Function} {[@var{y}, @var{sf}] =} filter (@var{b}, @var{a}, @var{x}, @var{si}, @var{dim})\n\
00294 Return the solution to the following linear, time-invariant difference\n\
00295 equation:\n\
00296 @tex\n\
00297 $$\n\
00298 \\sum_{k=0}^N a_{k+1} y_{n-k} = \\sum_{k=0}^M b_{k+1} x_{n-k}, \\qquad\n\
00299 1 \\le n \\le P\n\
00300 $$\n\
00301 @end tex\n\
00302 @ifnottex\n\
00303 @c Set example in small font to prevent overfull line\n\
00304 \n\
00305 @smallexample\n\
00306 @group\n\
00307 N M\n\
00308 SUM a(k+1) y(n-k) = SUM b(k+1) x(n-k) for 1<=n<=length(x)\n\
00309 k=0 k=0\n\
00310 @end group\n\
00311 @end smallexample\n\
00312 \n\
00313 @end ifnottex\n\
00314 \n\
00315 @noindent\n\
00316 where\n\
00317 @ifnottex\n\
00318 N=length(a)-1 and M=length(b)-1.\n\
00319 @end ifnottex\n\
00320 @tex\n\
00321 $a \\in \\Re^{N-1}$, $b \\in \\Re^{M-1}$, and $x \\in \\Re^P$.\n\
00322 @end tex\n\
00323 over the first non-singleton dimension of @var{x} or over @var{dim} if\n\
00324 supplied. An equivalent form of this equation is:\n\
00325 @tex\n\
00326 $$\n\
00327 y_n = -\\sum_{k=1}^N c_{k+1} y_{n-k} + \\sum_{k=0}^M d_{k+1} x_{n-k}, \\qquad\n\
00328 1 \\le n \\le P\n\
00329 $$\n\
00330 @end tex\n\
00331 @ifnottex\n\
00332 @c Set example in small font to prevent overfull line\n\
00333 \n\
00334 @smallexample\n\
00335 @group\n\
00336 N M\n\
00337 y(n) = - SUM c(k+1) y(n-k) + SUM d(k+1) x(n-k) for 1<=n<=length(x)\n\
00338 k=1 k=0\n\
00339 @end group\n\
00340 @end smallexample\n\
00341 \n\
00342 @end ifnottex\n\
00343 \n\
00344 @noindent\n\
00345 where\n\
00346 @ifnottex\n\
00347 c = a/a(1) and d = b/a(1).\n\
00348 @end ifnottex\n\
00349 @tex\n\
00350 $c = a/a_1$ and $d = b/a_1$.\n\
00351 @end tex\n\
00352 \n\
00353 If the fourth argument @var{si} is provided, it is taken as the\n\
00354 initial state of the system and the final state is returned as\n\
00355 @var{sf}. The state vector is a column vector whose length is\n\
00356 equal to the length of the longest coefficient vector minus one.\n\
00357 If @var{si} is not supplied, the initial state vector is set to all\n\
00358 zeros.\n\
00359 \n\
00360 In terms of the Z Transform, y is the result of passing the discrete-\n\
00361 time signal x through a system characterized by the following rational\n\
00362 system function:\n\
00363 @tex\n\
00364 $$\n\
00365 H(z) = {\\displaystyle\\sum_{k=0}^M d_{k+1} z^{-k}\n\
00366 \\over 1 + \\displaystyle\\sum_{k+1}^N c_{k+1} z^{-k}}\n\
00367 $$\n\
00368 @end tex\n\
00369 @ifnottex\n\
00370 \n\
00371 @example\n\
00372 @group\n\
00373 M\n\
00374 SUM d(k+1) z^(-k)\n\
00375 k=0\n\
00376 H(z) = ----------------------\n\
00377 N\n\
00378 1 + SUM c(k+1) z^(-k)\n\
00379 k=1\n\
00380 @end group\n\
00381 @end example\n\
00382 \n\
00383 @end ifnottex\n\
00384 @seealso{filter2, fftfilt, freqz}\n\
00385 @end deftypefn")
00386 {
00387 octave_value_list retval;
00388
00389 int nargin = args.length ();
00390
00391 if (nargin < 3 || nargin > 5)
00392 {
00393 print_usage ();
00394 return retval;
00395 }
00396
00397 const char *errmsg = "filter: arguments a and b must be vectors";
00398
00399 int dim;
00400 dim_vector x_dims = args(2).dims ();
00401
00402 if (nargin == 5)
00403 {
00404 dim = args(4).nint_value() - 1;
00405 if (dim < 0 || dim >= x_dims.length ())
00406 {
00407 error ("filter: DIM must be a valid dimension");
00408 return retval;
00409 }
00410 }
00411 else
00412 {
00413
00414 dim = 0;
00415 while (dim < x_dims.length () && x_dims(dim) <= 1)
00416 dim++;
00417
00418
00419 if (dim == x_dims.length ())
00420 dim = 0;
00421 }
00422
00423 bool isfloat = (args(0).is_single_type ()
00424 || args(1).is_single_type ()
00425 || args(2).is_single_type ()
00426 || (nargin >= 4 && args(3).is_single_type ()));
00427
00428 if (args(0).is_complex_type ()
00429 || args(1).is_complex_type ()
00430 || args(2).is_complex_type ()
00431 || (nargin >= 4 && args(3).is_complex_type ()))
00432 {
00433 if (isfloat)
00434 {
00435 FloatComplexColumnVector b (args(0).float_complex_vector_value ());
00436 FloatComplexColumnVector a (args(1).float_complex_vector_value ());
00437
00438 FloatComplexNDArray x (args(2).float_complex_array_value ());
00439
00440 if (! error_state)
00441 {
00442 FloatComplexNDArray si;
00443
00444 if (nargin == 3 || args(3).is_empty ())
00445 {
00446 octave_idx_type a_len = a.length ();
00447 octave_idx_type b_len = b.length ();
00448
00449 octave_idx_type si_len = (a_len > b_len ? a_len : b_len) - 1;
00450
00451 dim_vector si_dims = x.dims ();
00452 for (int i = dim; i > 0; i--)
00453 si_dims(i) = si_dims(i-1);
00454 si_dims(0) = si_len;
00455
00456 si.resize (si_dims, 0.0);
00457 }
00458 else
00459 {
00460 si = args(3).float_complex_array_value ();
00461
00462 if (si.is_vector () && x.is_vector ())
00463 si = si.reshape (dim_vector (si.numel (), 1));
00464 }
00465
00466 if (! error_state)
00467 {
00468 FloatComplexNDArray y (filter (b, a, x, si, dim));
00469
00470 if (nargout == 2)
00471 retval(1) = si;
00472
00473 retval(0) = y;
00474 }
00475 else
00476 error (errmsg);
00477 }
00478 else
00479 error (errmsg);
00480 }
00481 else
00482 {
00483 ComplexColumnVector b (args(0).complex_vector_value ());
00484 ComplexColumnVector a (args(1).complex_vector_value ());
00485
00486 ComplexNDArray x (args(2).complex_array_value ());
00487
00488 if (! error_state)
00489 {
00490 ComplexNDArray si;
00491
00492 if (nargin == 3 || args(3).is_empty ())
00493 {
00494 octave_idx_type a_len = a.length ();
00495 octave_idx_type b_len = b.length ();
00496
00497 octave_idx_type si_len = (a_len > b_len ? a_len : b_len) - 1;
00498
00499 dim_vector si_dims = x.dims ();
00500 for (int i = dim; i > 0; i--)
00501 si_dims(i) = si_dims(i-1);
00502 si_dims(0) = si_len;
00503
00504 si.resize (si_dims, 0.0);
00505 }
00506 else
00507 {
00508 si = args(3).complex_array_value ();
00509
00510 if (si.is_vector () && x.is_vector ())
00511 si = si.reshape (dim_vector (si.numel (), 1));
00512 }
00513
00514 if (! error_state)
00515 {
00516 ComplexNDArray y (filter (b, a, x, si, dim));
00517
00518 if (nargout == 2)
00519 retval(1) = si;
00520
00521 retval(0) = y;
00522 }
00523 else
00524 error (errmsg);
00525 }
00526 else
00527 error (errmsg);
00528 }
00529 }
00530 else
00531 {
00532 if (isfloat)
00533 {
00534 FloatColumnVector b (args(0).float_vector_value ());
00535 FloatColumnVector a (args(1).float_vector_value ());
00536
00537 FloatNDArray x (args(2).float_array_value ());
00538
00539 if (! error_state)
00540 {
00541 FloatNDArray si;
00542
00543 if (nargin == 3 || args(3).is_empty ())
00544 {
00545 octave_idx_type a_len = a.length ();
00546 octave_idx_type b_len = b.length ();
00547
00548 octave_idx_type si_len = (a_len > b_len ? a_len : b_len) - 1;
00549
00550 dim_vector si_dims = x.dims ();
00551 for (int i = dim; i > 0; i--)
00552 si_dims(i) = si_dims(i-1);
00553 si_dims(0) = si_len;
00554
00555 si.resize (si_dims, 0.0);
00556 }
00557 else
00558 {
00559 si = args(3).float_array_value ();
00560
00561 if (si.is_vector () && x.is_vector ())
00562 si = si.reshape (dim_vector (si.numel (), 1));
00563 }
00564
00565 if (! error_state)
00566 {
00567 FloatNDArray y (filter (b, a, x, si, dim));
00568
00569 if (nargout == 2)
00570 retval(1) = si;
00571
00572 retval(0) = y;
00573 }
00574 else
00575 error (errmsg);
00576 }
00577 else
00578 error (errmsg);
00579 }
00580 else
00581 {
00582 ColumnVector b (args(0).vector_value ());
00583 ColumnVector a (args(1).vector_value ());
00584
00585 NDArray x (args(2).array_value ());
00586
00587 if (! error_state)
00588 {
00589 NDArray si;
00590
00591 if (nargin == 3 || args(3).is_empty ())
00592 {
00593 octave_idx_type a_len = a.length ();
00594 octave_idx_type b_len = b.length ();
00595
00596 octave_idx_type si_len = (a_len > b_len ? a_len : b_len) - 1;
00597
00598 dim_vector si_dims = x.dims ();
00599 for (int i = dim; i > 0; i--)
00600 si_dims(i) = si_dims(i-1);
00601 si_dims(0) = si_len;
00602
00603 si.resize (si_dims, 0.0);
00604 }
00605 else
00606 {
00607 si = args(3).array_value ();
00608
00609 if (si.is_vector () && x.is_vector ())
00610 si = si.reshape (dim_vector (si.numel (), 1));
00611 }
00612
00613 if (! error_state)
00614 {
00615 NDArray y (filter (b, a, x, si, dim));
00616
00617 if (nargout == 2)
00618 retval(1) = si;
00619
00620 retval(0) = y;
00621 }
00622 else
00623 error (errmsg);
00624 }
00625 else
00626 error (errmsg);
00627 }
00628 }
00629
00630 return retval;
00631 }
00632
00633 template MArray<double>
00634 filter (MArray<double>&, MArray<double>&, MArray<double>&,
00635 MArray<double>&, int dim);
00636
00637 template MArray<double>
00638 filter (MArray<double>&, MArray<double>&, MArray<double>&, int dim);
00639
00640 template MArray<Complex>
00641 filter (MArray<Complex>&, MArray<Complex>&, MArray<Complex>&,
00642 MArray<Complex>&, int dim);
00643
00644 template MArray<Complex>
00645 filter (MArray<Complex>&, MArray<Complex>&, MArray<Complex>&, int dim);
00646
00647 template MArray<float>
00648 filter (MArray<float>&, MArray<float>&, MArray<float>&,
00649 MArray<float>&, int dim);
00650
00651 template MArray<float>
00652 filter (MArray<float>&, MArray<float>&, MArray<float>&, int dim);
00653
00654 template MArray<FloatComplex>
00655 filter (MArray<FloatComplex>&, MArray<FloatComplex>&, MArray<FloatComplex>&,
00656 MArray<FloatComplex>&, int dim);
00657
00658 template MArray<FloatComplex>
00659 filter (MArray<FloatComplex>&, MArray<FloatComplex>&, MArray<FloatComplex>&, int dim);
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733