GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
filter.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1996-2024 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 // Based on Tony Richardson's filter.m.
27 //
28 // Originally translated to C++ by KH (Kurt.Hornik@wu-wien.ac.at)
29 // with help from Fritz Leisch and Andreas Weingessel on Oct 20, 1994.
30 //
31 // Rewritten to use templates to handle both real and complex cases by
32 // jwe, Wed Nov 1 19:15:29 1995.
33 
34 #if defined (HAVE_CONFIG_H)
35 # include "config.h"
36 #endif
37 
38 #include "quit.h"
39 
40 #include "defun.h"
41 #include "error.h"
42 #include "ovl.h"
43 
45 
46 template <typename T>
49  int dim = 0)
50 {
51  MArray<T> y;
52 
53  octave_idx_type a_len = a.numel ();
54  octave_idx_type b_len = b.numel ();
55 
56  octave_idx_type ab_len = (a_len > b_len ? a_len : b_len);
57 
58  // FIXME: The two lines below should be unnecessary because
59  // this template is called with a and b as column vectors
60  // already. However the a.resize line is currently (2011/04/26)
61  // necessary to stop bug #33164.
62  b.resize (dim_vector (ab_len, 1), 0.0);
63  if (a_len > 1)
64  a.resize (dim_vector (ab_len, 1), 0.0);
65 
66  T norm = a (0);
67 
68  if (norm == static_cast<T> (0.0))
69  error ("filter: the first element of A must be nonzero");
70 
71  dim_vector x_dims = x.dims ();
72  if (dim < 0 || dim > x_dims.ndims ())
73  error ("filter: DIM must be a valid dimension");
74 
75  octave_idx_type x_len = x_dims(dim);
76 
77  dim_vector si_dims = si.dims ();
78  octave_idx_type si_len = si_dims(0);
79 
80  if (si_len != ab_len - 1)
81  error ("filter: first dimension of SI must be of length max (length (a), length (b)) - 1");
82 
83  if (si_dims.ndims () != x_dims.ndims ())
84  error ("filter: dimensionality of SI and X must agree");
85 
86  for (octave_idx_type i = 1; i < dim; i++)
87  {
88  if (si_dims(i) != x_dims(i-1))
89  error ("filter: dimensionality of SI and X must agree");
90  }
91  for (octave_idx_type i = dim+1; i < x_dims.ndims (); i++)
92  {
93  if (si_dims(i) != x_dims(i))
94  error ("filter: dimensionality of SI and X must agree");
95  }
96 
97  if (x_len == 0)
98  return x;
99 
100  if (norm != static_cast<T> (1.0))
101  {
102  a /= norm;
103  b /= norm;
104  }
105 
106  if (a_len <= 1 && si_len <= 0)
107  return b(0) * x;
108 
109  // Here onwards, either a_len > 1 or si_len >= 1 or both.
110 
111  y.resize (x_dims, 0.0);
112 
113  octave_idx_type x_stride = 1;
114  for (int i = 0; i < dim; i++)
115  x_stride *= x_dims(i);
116 
117  octave_idx_type x_num = x_dims.numel () / x_len;
118  // For deconv and fftfilt, x_num seems to always be 1.
119  // For directly calling filter, it can be more than 1.
120 
121  for (octave_idx_type num = 0; num < x_num; num++)
122  {
123  octave_idx_type x_offset = (x_stride == 1) ? num * x_len
124  : num + (num / x_stride) * x_stride * (x_len - 1);
125 
126  octave_idx_type si_offset = num * si_len;
127 
128  // Try to achieve a balance between speed and interruptibility.
129  //
130  // One extreme is to not check for interruptions at all, which gives
131  // good speed but the user cannot use Ctrl-C for the whole duration.
132  // The other end is to check frequently from inside an inner loop,
133  // which slows down performance by 5X or 6X.
134  //
135  // Putting any sort of check in an inner loop seems to prevent the
136  // compiler from optimizing the loop, so we cannot say "check for
137  // interruptions every M iterations" using an if-statement.
138  //
139  // This is a compromise approach to split the total numer of loop
140  // executions into num_outer and num_inner, to provide periodic checks
141  // for interruptions without writing a conditional inside a tight loop.
142  //
143  // To make it more interruptible and run more slowly, reduce num_inner.
144  // To speed it up but make it less interruptible, increase it.
145  // May need to increase it slowly over time as computers get faster.
146  // The aim is to not lose Ctrl-C ability for longer than about 2 seconds.
147  //
148  // In December 2021, num_inner = 100000 is acceptable.
149 
150  octave_idx_type num_execs = si_len-1; // 0 to num_execs-1
151  octave_idx_type num_inner = 100000;
152  octave_idx_type num_outer = num_execs / num_inner;
153 
154  // The following if-else block depends on a_len and si_len,
155  // both of which are loop invariants in this 0 <= num < x_num loop.
156  // But x_num is so small in practice that using the if-else inside
157  // the loop has more benefits than duplicating the outer for-loop,
158  // even though the checks are on loop invariants.
159 
160  // We cannot have a_len <= 1 AND si_len <= 0 because that case already
161  // returned above. This means exactly one of the following blocks
162  // inside the if-conditional will be obeyed: it is not possible for the
163  // if-block and the else-block to *both* skip. Therefore any code that
164  // is common to both branches can be pulled out here without affecting
165  // correctness or speed.
166 
167  T *py = y.fortran_vec ();
168  T *psi = si.fortran_vec ();
169  const T *pb = b.data ();
170  const T *px = x.data ();
171  psi += si_offset;
172 
173  if (a_len > 1)
174  {
175  const T *pa = a.data ();
176 
177  // Usually the last element to be written will be si_len-1
178  // but if si_len is 0, then we need the 0th element to be written.
179  // Pulling this check out of the for-loop makes it run faster.
180  octave_idx_type iidx = (si_len > 0) ? si_len-1 : 0;
181 
182  for (octave_idx_type i = 0, idx = x_offset;
183  i < x_len;
184  i++, idx += x_stride)
185  {
186  py[idx] = psi[0] + pb[0] * px[idx];
187 
188  // Outer and inner loops for interruption management
189  for (octave_idx_type u = 0; u <= num_outer; u++)
190  {
191  octave_idx_type lo = u * num_inner;
192  octave_idx_type hi = (lo + num_inner < num_execs-1)
193  ? lo + num_inner : num_execs-1;
194 
195  // Inner loop, no interruption
196  for (octave_idx_type j = lo; j <= hi; j++)
197  psi[j] = psi[j+1] - pa[j+1] * py[idx] + pb[j+1] * px[idx];
198 
199  octave_quit(); // Check for interruptions
200  }
201 
202  psi[iidx] = pb[si_len] * px[idx] - pa[si_len] * py[idx];
203  }
204  }
205  else // a_len <= 1 ==> si_len MUST be > 0
206  {
207  // This else-block is almost the same as the above if-block,
208  // except for the absence of variable pa.
209 
210  for (octave_idx_type i = 0, idx = x_offset;
211  i < x_len;
212  i++, idx += x_stride)
213  {
214  py[idx] = psi[0] + pb[0] * px[idx];
215 
216  // Outer and inner loops for interruption management
217  for (octave_idx_type u = 0; u <= num_outer; u++)
218  {
219  octave_idx_type lo = u * num_inner;
220  octave_idx_type hi = (lo + num_inner < num_execs-1)
221  ? lo + num_inner : num_execs-1;
222 
223  // Inner loop, no interruption
224  for (octave_idx_type j = lo; j <= hi; j++)
225  psi[j] = psi[j+1] + pb[j+1] * px[idx];
226 
227  octave_quit(); // Check for interruptions
228  }
229 
230  psi[si_len-1] = pb[si_len] * px[idx];
231  }
232  }
233  }
234 
235  return y;
236 }
237 
238 template <typename T>
239 MArray<T>
240 filter (MArray<T>& b, MArray<T>& a, MArray<T>& x, int dim = -1)
241 {
242  dim_vector x_dims = x.dims ();
243 
244  if (dim < 0)
245  dim = x_dims.first_non_singleton ();
246  else if (dim > x_dims.ndims ())
247  error ("filter: DIM must be a valid dimension");
248 
249  octave_idx_type a_len = a.numel ();
250  octave_idx_type b_len = b.numel ();
251 
252  octave_idx_type si_len = (a_len > b_len ? a_len : b_len) - 1;
253  dim_vector si_dims = x.dims ();
254  for (int i = dim; i > 0; i--)
255  si_dims(i) = si_dims(i-1);
256  si_dims(0) = si_len;
257 
258  MArray<T> si (si_dims, T (0.0));
259 
260  return filter (b, a, x, si, dim);
261 }
262 
263 DEFUN (filter, args, ,
264  doc: /* -*- texinfo -*-
265 @deftypefn {} {@var{y} =} filter (@var{b}, @var{a}, @var{x})
266 @deftypefnx {} {[@var{y}, @var{sf}] =} filter (@var{b}, @var{a}, @var{x}, @var{si})
267 @deftypefnx {} {[@var{y}, @var{sf}] =} filter (@var{b}, @var{a}, @var{x}, [], @var{dim})
268 @deftypefnx {} {[@var{y}, @var{sf}] =} filter (@var{b}, @var{a}, @var{x}, @var{si}, @var{dim})
269 Apply a 1-D digital filter to the data @var{x}.
270 
271 @code{filter} returns the solution to the following linear, time-invariant
272 difference equation:
273 @tex
274 $$
275 \sum_{k=0}^N a_{k+1} y_{n-k} = \sum_{k=0}^M b_{k+1} x_{n-k}, \qquad
276  1 \le n \le P
277 $$
278 @end tex
279 @ifnottex
280 @c Set example in small font to prevent overfull line
281 
282 @smallexample
283 @group
284  N M
285 SUM a(k+1) y(n-k) = SUM b(k+1) x(n-k) for 1<=n<=length(x)
286 k=0 k=0
287 @end group
288 @end smallexample
289 
290 @end ifnottex
291 
292 @noindent
293 where
294 @ifnottex
295 N=length(a)-1 and M=length(b)-1.
296 @end ifnottex
297 @tex
298 $a \in \Re^{N-1}$, $b \in \Re^{M-1}$, and $x \in \Re^P$.
299 @end tex
300 The result is calculated over the first non-singleton dimension of @var{x}
301 or over @var{dim} if supplied.
302 
303 An equivalent form of the equation is:
304 @tex
305 $$
306 y_n = -\sum_{k=1}^N c_{k+1} y_{n-k} + \sum_{k=0}^M d_{k+1} x_{n-k}, \qquad
307  1 \le n \le P
308 $$
309 @end tex
310 @ifnottex
311 @c Set example in small font to prevent overfull line
312 
313 @smallexample
314 @group
315  N M
316 y(n) = - SUM c(k+1) y(n-k) + SUM d(k+1) x(n-k) for 1<=n<=length(x)
317  k=1 k=0
318 @end group
319 @end smallexample
320 
321 @end ifnottex
322 
323 @noindent
324 where
325 @ifnottex
326  c = a/a(1) and d = b/a(1).
327 @end ifnottex
328 @tex
329 $c = a/a_1$ and $d = b/a_1$.
330 @end tex
331 
332 If the fourth argument @var{si} is provided, it is taken as the
333 initial state of the system and the final state is returned as
334 @var{sf}. The state vector is a column vector whose length is
335 equal to the length of the longest coefficient vector minus one.
336 If @var{si} is not supplied, the initial state vector is set to all
337 zeros.
338 
339 In terms of the Z Transform, @var{y} is the result of passing the
340 discrete-time signal @var{x} through a system characterized by the following
341 rational system function:
342 @tex
343 $$
344 H(z) = {\displaystyle\sum_{k=0}^M d_{k+1} z^{-k}
345  \over 1 + \displaystyle\sum_{k+1}^N c_{k+1} z^{-k}}
346 $$
347 @end tex
348 @ifnottex
349 
350 @example
351 @group
352  M
353  SUM d(k+1) z^(-k)
354  k=0
355 H(z) = ---------------------
356  N
357  1 + SUM c(k+1) z^(-k)
358  k=1
359 @end group
360 @end example
361 
362 @end ifnottex
363 @seealso{filter2, fftfilt, freqz}
364 @end deftypefn */)
365 {
366  int nargin = args.length ();
367 
368  if (nargin < 3 || nargin > 5)
369  print_usage ();
370 
371  int dim;
372  dim_vector x_dims = args(2).dims ();
373 
374  if (nargin == 5)
375  {
376  dim = args(4).nint_value () - 1;
377  if (dim < 0 || dim >= x_dims.ndims ())
378  error ("filter: DIM must be a valid dimension");
379  }
380  else
381  dim = x_dims.first_non_singleton ();
382 
383  octave_value_list retval;
384 
385  const char *a_b_errmsg = "filter: A and B must be vectors";
386  const char *x_si_errmsg = "filter: X and SI must be arrays";
387 
388  bool isfloat = (args(0).is_single_type ()
389  || args(1).is_single_type ()
390  || args(2).is_single_type ()
391  || (nargin >= 4 && args(3).is_single_type ()));
392 
393  if (args(0).iscomplex ()
394  || args(1).iscomplex ()
395  || args(2).iscomplex ()
396  || (nargin >= 4 && args(3).iscomplex ()))
397  {
398  if (isfloat)
399  {
400  FloatComplexColumnVector b = args(0).xfloat_complex_vector_value (a_b_errmsg);
401  FloatComplexColumnVector a = args(1).xfloat_complex_vector_value (a_b_errmsg);
402  FloatComplexNDArray x = args(2).xfloat_complex_array_value (x_si_errmsg);
403 
405 
406  if (nargin == 3 || args(3).isempty ())
407  {
408  octave_idx_type a_len = a.numel ();
409  octave_idx_type b_len = b.numel ();
410 
411  octave_idx_type si_len = (a_len > b_len ? a_len : b_len) - 1;
412 
413  dim_vector si_dims = x.dims ();
414  for (int i = dim; i > 0; i--)
415  si_dims(i) = si_dims(i-1);
416  si_dims(0) = si_len;
417 
418  si.resize (si_dims, 0.0);
419  }
420  else
421  {
422  si = args(3).xfloat_complex_array_value (x_si_errmsg);
423 
424  if (si.isvector () && x.isvector ())
425  si = si.reshape (dim_vector (si.numel (), 1));
426  }
427 
428  FloatComplexNDArray y (filter (b, a, x, si, dim));
429 
430  retval = ovl (y, si);
431  }
432  else
433  {
434  ComplexColumnVector b = args(0).xcomplex_vector_value (a_b_errmsg);
435  ComplexColumnVector a = args(1).xcomplex_vector_value (a_b_errmsg);
436 
437  ComplexNDArray x = args(2).xcomplex_array_value (x_si_errmsg);
438 
439  ComplexNDArray si;
440 
441  if (nargin == 3 || args(3).isempty ())
442  {
443  octave_idx_type a_len = a.numel ();
444  octave_idx_type b_len = b.numel ();
445 
446  octave_idx_type si_len = (a_len > b_len ? a_len : b_len) - 1;
447 
448  dim_vector si_dims = x.dims ();
449  for (int i = dim; i > 0; i--)
450  si_dims(i) = si_dims(i-1);
451  si_dims(0) = si_len;
452 
453  si.resize (si_dims, 0.0);
454  }
455  else
456  {
457  si = args(3).xcomplex_array_value (x_si_errmsg);
458 
459  if (si.isvector () && x.isvector ())
460  si = si.reshape (dim_vector (si.numel (), 1));
461  }
462 
463  ComplexNDArray y (filter (b, a, x, si, dim));
464 
465  retval = ovl (y, si);
466  }
467  }
468  else
469  {
470  if (isfloat)
471  {
472  FloatColumnVector b = args(0).xfloat_vector_value (a_b_errmsg);
473  FloatColumnVector a = args(1).xfloat_vector_value (a_b_errmsg);
474 
475  FloatNDArray x = args(2).xfloat_array_value (x_si_errmsg);
476 
477  FloatNDArray si;
478 
479  if (nargin == 3 || args(3).isempty ())
480  {
481  octave_idx_type a_len = a.numel ();
482  octave_idx_type b_len = b.numel ();
483 
484  octave_idx_type si_len = (a_len > b_len ? a_len : b_len) - 1;
485 
486  dim_vector si_dims = x.dims ();
487  for (int i = dim; i > 0; i--)
488  si_dims(i) = si_dims(i-1);
489  si_dims(0) = si_len;
490 
491  si.resize (si_dims, 0.0);
492  }
493  else
494  {
495  si = args(3).xfloat_array_value (x_si_errmsg);
496 
497  if (si.isvector () && x.isvector ())
498  si = si.reshape (dim_vector (si.numel (), 1));
499  }
500 
501  FloatNDArray y (filter (b, a, x, si, dim));
502 
503  retval = ovl (y, si);
504  }
505  else
506  {
507  ColumnVector b = args(0).xvector_value (a_b_errmsg);
508  ColumnVector a = args(1).xvector_value (a_b_errmsg);
509 
510  NDArray x = args(2).xarray_value (x_si_errmsg);
511 
512  NDArray si;
513 
514  if (nargin == 3 || args(3).isempty ())
515  {
516  octave_idx_type a_len = a.numel ();
517  octave_idx_type b_len = b.numel ();
518 
519  octave_idx_type si_len = (a_len > b_len ? a_len : b_len) - 1;
520 
521  dim_vector si_dims = x.dims ();
522  for (int i = dim; i > 0; i--)
523  si_dims(i) = si_dims(i-1);
524  si_dims(0) = si_len;
525 
526  si.resize (si_dims, 0.0);
527  }
528  else
529  {
530  si = args(3).xarray_value (x_si_errmsg);
531 
532  if (si.isvector () && x.isvector ())
533  si = si.reshape (dim_vector (si.numel (), 1));
534  }
535 
536  NDArray y (filter (b, a, x, si, dim));
537 
538  retval = ovl (y, si);
539  }
540  }
541 
542  return retval;
543 }
544 
545 template MArray<double>
547  MArray<double>&, int dim);
548 
549 template MArray<double>
551 
552 template MArray<Complex>
554  MArray<Complex>&, int dim);
555 
556 template MArray<Complex>
558 
559 template MArray<float>
561  MArray<float>&, int dim);
562 
563 template MArray<float>
565 
566 template MArray<FloatComplex>
568  MArray<FloatComplex>&, int dim);
569 
570 template MArray<FloatComplex>
572  int dim);
573 
574 /*
575 %!shared a, b, x, r
576 %!test
577 %! a = [1 1];
578 %! b = [1 1];
579 %! x = zeros (1,10); x(1) = 1;
580 %! assert (filter (b, [1], x ), [1 1 0 0 0 0 0 0 0 0]);
581 %! assert (filter (b, [1], x.'), [1 1 0 0 0 0 0 0 0 0].');
582 %! assert (filter (b.', [1], x ), [1 1 0 0 0 0 0 0 0 0] );
583 %! assert (filter (b.', [1], x.'), [1 1 0 0 0 0 0 0 0 0].');
584 %! assert (filter ([1], a, x ), [+1 -1 +1 -1 +1 -1 +1 -1 +1 -1] );
585 %! assert (filter ([1], a, x.'), [+1 -1 +1 -1 +1 -1 +1 -1 +1 -1].');
586 %! assert (filter ([1], a.', x ), [+1 -1 +1 -1 +1 -1 +1 -1 +1 -1] );
587 %! assert (filter ([1], a.', x.'), [+1 -1 +1 -1 +1 -1 +1 -1 +1 -1].');
588 %! assert (filter (b, a, x ), [1 0 0 0 0 0 0 0 0 0] );
589 %! assert (filter (b.', a, x ), [1 0 0 0 0 0 0 0 0 0] );
590 %! assert (filter (b, a.', x ), [1 0 0 0 0 0 0 0 0 0] );
591 %! assert (filter (b.', a, x ), [1 0 0 0 0 0 0 0 0 0] );
592 %! assert (filter (b, a, x.'), [1 0 0 0 0 0 0 0 0 0].');
593 %! assert (filter (b.', a, x.'), [1 0 0 0 0 0 0 0 0 0].');
594 %! assert (filter (b, a.', x.'), [1 0 0 0 0 0 0 0 0 0].');
595 %! assert (filter (b.', a, x.'), [1 0 0 0 0 0 0 0 0 0].');
596 
597 %!test
598 %! r = sqrt (1/2) * (1+i);
599 %! a = a*r;
600 %! b = b*r;
601 %! assert (filter (b, [1], x ), r*[1 1 0 0 0 0 0 0 0 0] );
602 %! assert (filter (b, [1], r*x ), r*r*[1 1 0 0 0 0 0 0 0 0] );
603 %! assert (filter (b, [1], x.' ), r*[1 1 0 0 0 0 0 0 0 0].' );
604 %! assert (filter (b, a, x ), [1 0 0 0 0 0 0 0 0 0], eps);
605 %! assert (filter (b, a, r*x ), r*[1 0 0 0 0 0 0 0 0 0], eps);
606 
607 %!shared a, b, x, y, so
608 %!test
609 %! a = [1,1];
610 %! b = [1,1];
611 %! x = zeros (1,10); x(1) = 1;
612 %! [y, so] = filter (b, [1], x, [-1]);
613 %! assert (y, [0 1 0 0 0 0 0 0 0 0]);
614 %! assert (so, 0);
615 
616 %!test
617 %! x = zeros (10,3); x(1,1) = -1; x(1,2) = 1;
618 %! y0 = zeros (10,3); y0(1:2,1) = -1; y0(1:2,2) = 1;
619 %! y = filter (b, [1], x);
620 %! assert (y, y0);
621 
622 %!test
623 %! a = [1,1];
624 %! b=[1,1];
625 %! x = zeros (4,4,2); x(1,1:4,1) = +1; x(1,1:4,2) = -1;
626 %! y0 = zeros (4,4,2); y0(1:2,1:4,1) = +1; y0(1:2,1:4,2) = -1;
627 %! y = filter (b, [1], x);
628 %! assert (y, y0);
629 
630 %!assert (filter (1, ones (10,1) / 10, []), [])
631 %!assert (filter (1, ones (10,1) / 10, zeros (0,10)), zeros (0,10))
632 %!assert (filter (1, ones (10,1) / 10, single (1:5)),
633 %! repmat (single (10), 1, 5))
634 
635 ## Test using initial conditions
636 %!assert (filter ([1, 1, 1], [1, 1], [1 2], [1, 1]), [2 2])
637 %!assert (filter ([1, 1, 1], [1, 1], [1 2], [1, 1]'), [2 2])
638 %!assert (filter ([1, 3], [1], [1 2; 3 4; 5 6], [4, 5]), [5 7; 6 10; 14 18])
639 %!error filter ([1, 3], [1], [1 2; 3 4; 5 6], [4, 5]')
640 %!assert (filter ([1, 3, 2], [1], [1 2; 3 4; 5 6], [1 0 0; 1 0 0], 2),
641 %! [2 6; 3 13; 5 21])
642 
643 ## Test of DIM parameter
644 %!test
645 %! x = ones (2, 1, 3, 4);
646 %! x(1,1,:,:) = [1 2 3 4; 5 6 7 8; 9 10 11 12];
647 %! y0 = [1 1 6 2 15 3 2 1 8 2 18 3 3 1 10 2 21 3 4 1 12 2 24 3];
648 %! y0 = reshape (y0, size (x));
649 %! y = filter ([1 1 1], 1, x, [], 3);
650 %! assert (y, y0);
651 */
652 
653 OCTAVE_END_NAMESPACE(octave)
T * fortran_vec()
Size of the specified dimension.
Definition: Array-base.cc:1764
bool isvector() const
Size of the specified dimension.
Definition: Array.h:654
void resize(const dim_vector &dv, const T &rfv)
Size of the specified dimension.
Definition: Array-base.cc:1023
const T * data() const
Size of the specified dimension.
Definition: Array.h:663
const dim_vector & dims() const
Return a const-reference so that dims ()(i) works efficiently.
Definition: Array.h:503
octave_idx_type numel() const
Number of elements in the array.
Definition: Array.h:414
Template for N-dimensional array classes with like-type math operators.
Definition: MArray.h:63
MArray< T > reshape(const dim_vector &new_dims) const
Definition: MArray.h:87
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:94
octave_idx_type numel(int n=0) const
Number of elements that a matrix with this dimensions would have.
Definition: dim-vector.h:335
octave_idx_type ndims() const
Number of dimensions.
Definition: dim-vector.h:257
int first_non_singleton(int def=0) const
Definition: dim-vector.h:444
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
void print_usage(void)
Definition: defun-int.h:72
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
Definition: defun.h:56
void() error(const char *fmt,...)
Definition: error.cc:988
MArray< T > filter(MArray< T > &b, MArray< T > &a, MArray< T > &x, MArray< T > &si, int dim=0)
Definition: filter.cc:48
double norm(const ColumnVector &v)
Definition: graphics.cc:5547
F77_RET_T const F77_DBLE * x
double psi(double z)
Definition: lo-specfun.cc:2061
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition: ovl.h:219