GNU Octave  4.0.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
filter.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1996-2015 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 // Based on Tony Richardson's filter.m.
24 //
25 // Originally translated to C++ by KH (Kurt.Hornik@wu-wien.ac.at)
26 // with help from Fritz Leisch and Andreas Weingessel on Oct 20, 1994.
27 //
28 // Rewritten to use templates to handle both real and complex cases by
29 // jwe, Wed Nov 1 19:15:29 1995.
30 
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34 
35 #include "quit.h"
36 
37 #include "defun.h"
38 #include "error.h"
39 #include "oct-obj.h"
40 
41 #if !defined (CXX_NEW_FRIEND_TEMPLATE_DECL)
42 extern MArray<double>
44 
45 extern MArray<Complex>
47 
48 extern MArray<float>
50 
53  int dim);
54 #endif
55 
56 template <class T>
59  int dim = 0)
60 {
61  MArray<T> y;
62 
63  octave_idx_type a_len = a.length ();
64  octave_idx_type b_len = b.length ();
65 
66  octave_idx_type ab_len = a_len > b_len ? a_len : b_len;
67 
68  // FIXME: The two lines below should be unecessary because
69  // this template is called with a and b as column vectors
70  // already. However the a.resize line is currently (2011/04/26)
71  // necessary to stop bug #33164.
72  b.resize (dim_vector (ab_len, 1), 0.0);
73  if (a_len > 1)
74  a.resize (dim_vector (ab_len, 1), 0.0);
75 
76  T norm = a (0);
77 
78  if (norm == static_cast<T> (0.0))
79  {
80  error ("filter: the first element of A must be nonzero");
81  return y;
82  }
83 
84  dim_vector x_dims = x.dims ();
85  if (dim < 0 || dim > x_dims.length ())
86  {
87  error ("filter: DIM must be a valid dimension");
88  return y;
89  }
90 
91  octave_idx_type x_len = x_dims(dim);
92 
93  dim_vector si_dims = si.dims ();
94  octave_idx_type si_len = si_dims(0);
95 
96  if (si_len != ab_len - 1)
97  {
98  error ("filter: first dimension of SI must be of length max (length (a), length (b)) - 1");
99  return y;
100  }
101 
102  if (si_dims.length () != x_dims.length ())
103  {
104  error ("filter: dimensionality of SI and X must agree");
105  return y;
106  }
107 
108  for (octave_idx_type i = 1; i < dim; i++)
109  {
110  if (si_dims(i) != x_dims(i-1))
111  {
112  error ("filter: dimensionality of SI and X must agree");
113  return y;
114  }
115  }
116  for (octave_idx_type i = dim+1; i < x_dims.length (); i++)
117  {
118  if (si_dims(i) != x_dims(i))
119  {
120  error ("filter: dimensionality of SI and X must agree");
121  return y;
122  }
123  }
124 
125  if (x_len == 0)
126  return x;
127 
128  if (norm != static_cast<T> (1.0))
129  {
130  a = a / norm;
131  b = b / norm;
132  }
133 
134  if (a_len <= 1 && si_len <= 0)
135  return b(0) * x;
136 
137  y.resize (x_dims, 0.0);
138 
139  int x_stride = 1;
140  for (int i = 0; i < dim; i++)
141  x_stride *= x_dims(i);
142 
143  octave_idx_type x_num = x_dims.numel () / x_len;
144  for (octave_idx_type num = 0; num < x_num; num++)
145  {
146  octave_idx_type x_offset;
147  if (x_stride == 1)
148  x_offset = num * x_len;
149  else
150  {
151  octave_idx_type x_offset2 = 0;
152  x_offset = num;
153  while (x_offset >= x_stride)
154  {
155  x_offset -= x_stride;
156  x_offset2++;
157  }
158  x_offset += x_offset2 * x_stride * x_len;
159  }
160  octave_idx_type si_offset = num * si_len;
161 
162  if (a_len > 1)
163  {
164  T *py = y.fortran_vec ();
165  T *psi = si.fortran_vec ();
166 
167  const T *pa = a.data ();
168  const T *pb = b.data ();
169  const T *px = x.data ();
170 
171  psi += si_offset;
172 
173  for (octave_idx_type i = 0, idx = x_offset;
174  i < x_len;
175  i++, idx += x_stride)
176  {
177  py[idx] = psi[0] + pb[0] * px[idx];
178 
179  if (si_len > 0)
180  {
181  for (octave_idx_type j = 0; j < si_len - 1; j++)
182  {
183  OCTAVE_QUIT;
184 
185  psi[j] = psi[j+1] - pa[j+1] * py[idx] + pb[j+1] * px[idx];
186  }
187 
188  psi[si_len-1] = pb[si_len] * px[idx] - pa[si_len] * py[idx];
189  }
190  else
191  {
192  OCTAVE_QUIT;
193 
194  psi[0] = pb[si_len] * px[idx] - pa[si_len] * py[idx];
195  }
196  }
197  }
198  else if (si_len > 0)
199  {
200  T *py = y.fortran_vec ();
201  T *psi = si.fortran_vec ();
202 
203  const T *pb = b.data ();
204  const T *px = x.data ();
205 
206  psi += si_offset;
207 
208  for (octave_idx_type i = 0, idx = x_offset;
209  i < x_len;
210  i++, idx += x_stride)
211  {
212  py[idx] = psi[0] + pb[0] * px[idx];
213 
214  if (si_len > 1)
215  {
216  for (octave_idx_type j = 0; j < si_len - 1; j++)
217  {
218  OCTAVE_QUIT;
219 
220  psi[j] = psi[j+1] + pb[j+1] * px[idx];
221  }
222 
223  psi[si_len-1] = pb[si_len] * px[idx];
224  }
225  else
226  {
227  OCTAVE_QUIT;
228 
229  psi[0] = pb[1] * px[idx];
230  }
231  }
232  }
233  }
234 
235  return y;
236 }
237 
238 #if !defined (CXX_NEW_FRIEND_TEMPLATE_DECL)
239 extern MArray<double>
241  MArray<double>&, int dim);
242 
243 extern MArray<Complex>
245  MArray<Complex>&, int dim);
246 
247 extern MArray<float>
249  MArray<float>&, int dim);
250 
253  MArray<FloatComplex>&, int dim);
254 #endif
255 
256 template <class T>
257 MArray<T>
258 filter (MArray<T>& b, MArray<T>& a, MArray<T>& x, int dim = -1)
259 {
260  dim_vector x_dims = x.dims ();
261 
262  if (dim < 0)
263  {
264  // Find first non-singleton dimension
265  while (dim < x_dims.length () && x_dims(dim) <= 1)
266  dim++;
267 
268  // All dimensions singleton, pick first dimension
269  if (dim == x_dims.length ())
270  dim = 0;
271  }
272  else if (dim < 0 || dim > x_dims.length ())
273  {
274  error ("filter: DIM must be a valid dimension");
275  return MArray<T> ();
276  }
277 
278  octave_idx_type a_len = a.length ();
279  octave_idx_type b_len = b.length ();
280 
281  octave_idx_type si_len = (a_len > b_len ? a_len : b_len) - 1;
282  dim_vector si_dims = x.dims ();
283  for (int i = dim; i > 0; i--)
284  si_dims(i) = si_dims(i-1);
285  si_dims(0) = si_len;
286 
287  MArray<T> si (si_dims, T (0.0));
288 
289  return filter (b, a, x, si, dim);
290 }
291 
292 DEFUN (filter, args, nargout,
293  "-*- texinfo -*-\n\
294 @deftypefn {Built-in Function} {@var{y} =} filter (@var{b}, @var{a}, @var{x})\n\
295 @deftypefnx {Built-in Function} {[@var{y}, @var{sf}] =} filter (@var{b}, @var{a}, @var{x}, @var{si})\n\
296 @deftypefnx {Built-in Function} {[@var{y}, @var{sf}] =} filter (@var{b}, @var{a}, @var{x}, [], @var{dim})\n\
297 @deftypefnx {Built-in Function} {[@var{y}, @var{sf}] =} filter (@var{b}, @var{a}, @var{x}, @var{si}, @var{dim})\n\
298 Apply a 1-D digital filter to the data @var{x}.\n\
299 \n\
300 @code{filter} returns the solution to the following linear, time-invariant\n\
301 difference equation:\n\
302 @tex\n\
303 $$\n\
304 \\sum_{k=0}^N a_{k+1} y_{n-k} = \\sum_{k=0}^M b_{k+1} x_{n-k}, \\qquad\n\
305  1 \\le n \\le P\n\
306 $$\n\
307 @end tex\n\
308 @ifnottex\n\
309 @c Set example in small font to prevent overfull line\n\
310 \n\
311 @smallexample\n\
312 @group\n\
313  N M\n\
314 SUM a(k+1) y(n-k) = SUM b(k+1) x(n-k) for 1<=n<=length(x)\n\
315 k=0 k=0\n\
316 @end group\n\
317 @end smallexample\n\
318 \n\
319 @end ifnottex\n\
320 \n\
321 @noindent\n\
322 where\n\
323 @ifnottex\n\
324 N=length(a)-1 and M=length(b)-1.\n\
325 @end ifnottex\n\
326 @tex\n\
327 $a \\in \\Re^{N-1}$, $b \\in \\Re^{M-1}$, and $x \\in \\Re^P$.\n\
328 @end tex\n\
329 The result is calculated over the first non-singleton dimension of @var{x}\n\
330 or over @var{dim} if supplied.\n\
331 \n\
332 An equivalent form of the equation is:\n\
333 @tex\n\
334 $$\n\
335 y_n = -\\sum_{k=1}^N c_{k+1} y_{n-k} + \\sum_{k=0}^M d_{k+1} x_{n-k}, \\qquad\n\
336  1 \\le n \\le P\n\
337 $$\n\
338 @end tex\n\
339 @ifnottex\n\
340 @c Set example in small font to prevent overfull line\n\
341 \n\
342 @smallexample\n\
343 @group\n\
344  N M\n\
345 y(n) = - SUM c(k+1) y(n-k) + SUM d(k+1) x(n-k) for 1<=n<=length(x)\n\
346  k=1 k=0\n\
347 @end group\n\
348 @end smallexample\n\
349 \n\
350 @end ifnottex\n\
351 \n\
352 @noindent\n\
353 where\n\
354 @ifnottex\n\
355  c = a/a(1) and d = b/a(1).\n\
356 @end ifnottex\n\
357 @tex\n\
358 $c = a/a_1$ and $d = b/a_1$.\n\
359 @end tex\n\
360 \n\
361 If the fourth argument @var{si} is provided, it is taken as the\n\
362 initial state of the system and the final state is returned as\n\
363 @var{sf}. The state vector is a column vector whose length is\n\
364 equal to the length of the longest coefficient vector minus one.\n\
365 If @var{si} is not supplied, the initial state vector is set to all\n\
366 zeros.\n\
367 \n\
368 In terms of the Z Transform, @var{y} is the result of passing the\n\
369 discrete-time signal @var{x} through a system characterized by the following\n\
370 rational system function:\n\
371 @tex\n\
372 $$\n\
373 H(z) = {\\displaystyle\\sum_{k=0}^M d_{k+1} z^{-k}\n\
374  \\over 1 + \\displaystyle\\sum_{k+1}^N c_{k+1} z^{-k}}\n\
375 $$\n\
376 @end tex\n\
377 @ifnottex\n\
378 \n\
379 @example\n\
380 @group\n\
381  M\n\
382  SUM d(k+1) z^(-k)\n\
383  k=0\n\
384 H(z) = ---------------------\n\
385  N\n\
386  1 + SUM c(k+1) z^(-k)\n\
387  k=1\n\
388 @end group\n\
389 @end example\n\
390 \n\
391 @end ifnottex\n\
392 @seealso{filter2, fftfilt, freqz}\n\
393 @end deftypefn")
394 {
395  octave_value_list retval;
396 
397  int nargin = args.length ();
398 
399  if (nargin < 3 || nargin > 5)
400  {
401  print_usage ();
402  return retval;
403  }
404 
405  const char *errmsg = "filter: arguments a and b must be vectors";
406 
407  int dim;
408  dim_vector x_dims = args(2).dims ();
409 
410  if (nargin == 5)
411  {
412  dim = args(4).nint_value () - 1;
413  if (dim < 0 || dim >= x_dims.length ())
414  {
415  error ("filter: DIM must be a valid dimension");
416  return retval;
417  }
418  }
419  else
420  {
421  // Find first non-singleton dimension
422  dim = 0;
423  while (dim < x_dims.length () && x_dims(dim) <= 1)
424  dim++;
425 
426  // All dimensions singleton, pick first dimension
427  if (dim == x_dims.length ())
428  dim = 0;
429  }
430 
431  bool isfloat = (args(0).is_single_type ()
432  || args(1).is_single_type ()
433  || args(2).is_single_type ()
434  || (nargin >= 4 && args(3).is_single_type ()));
435 
436  if (args(0).is_complex_type ()
437  || args(1).is_complex_type ()
438  || args(2).is_complex_type ()
439  || (nargin >= 4 && args(3).is_complex_type ()))
440  {
441  if (isfloat)
442  {
443  FloatComplexColumnVector b (args(0).float_complex_vector_value ());
444  FloatComplexColumnVector a (args(1).float_complex_vector_value ());
445 
446  FloatComplexNDArray x (args(2).float_complex_array_value ());
447 
448  if (! error_state)
449  {
451 
452  if (nargin == 3 || args(3).is_empty ())
453  {
454  octave_idx_type a_len = a.length ();
455  octave_idx_type b_len = b.length ();
456 
457  octave_idx_type si_len = (a_len > b_len ? a_len : b_len) - 1;
458 
459  dim_vector si_dims = x.dims ();
460  for (int i = dim; i > 0; i--)
461  si_dims(i) = si_dims(i-1);
462  si_dims(0) = si_len;
463 
464  si.resize (si_dims, 0.0);
465  }
466  else
467  {
468  si = args(3).float_complex_array_value ();
469 
470  if (si.is_vector () && x.is_vector ())
471  si = si.reshape (dim_vector (si.numel (), 1));
472  }
473 
474  if (! error_state)
475  {
476  FloatComplexNDArray y (filter (b, a, x, si, dim));
477 
478  if (nargout == 2)
479  retval(1) = si;
480 
481  retval(0) = y;
482  }
483  else
484  error (errmsg);
485  }
486  else
487  error (errmsg);
488  }
489  else
490  {
491  ComplexColumnVector b (args(0).complex_vector_value ());
492  ComplexColumnVector a (args(1).complex_vector_value ());
493 
494  ComplexNDArray x (args(2).complex_array_value ());
495 
496  if (! error_state)
497  {
498  ComplexNDArray si;
499 
500  if (nargin == 3 || args(3).is_empty ())
501  {
502  octave_idx_type a_len = a.length ();
503  octave_idx_type b_len = b.length ();
504 
505  octave_idx_type si_len = (a_len > b_len ? a_len : b_len) - 1;
506 
507  dim_vector si_dims = x.dims ();
508  for (int i = dim; i > 0; i--)
509  si_dims(i) = si_dims(i-1);
510  si_dims(0) = si_len;
511 
512  si.resize (si_dims, 0.0);
513  }
514  else
515  {
516  si = args(3).complex_array_value ();
517 
518  if (si.is_vector () && x.is_vector ())
519  si = si.reshape (dim_vector (si.numel (), 1));
520  }
521 
522  if (! error_state)
523  {
524  ComplexNDArray y (filter (b, a, x, si, dim));
525 
526  if (nargout == 2)
527  retval(1) = si;
528 
529  retval(0) = y;
530  }
531  else
532  error (errmsg);
533  }
534  else
535  error (errmsg);
536  }
537  }
538  else
539  {
540  if (isfloat)
541  {
542  FloatColumnVector b (args(0).float_vector_value ());
543  FloatColumnVector a (args(1).float_vector_value ());
544 
545  FloatNDArray x (args(2).float_array_value ());
546 
547  if (! error_state)
548  {
549  FloatNDArray si;
550 
551  if (nargin == 3 || args(3).is_empty ())
552  {
553  octave_idx_type a_len = a.length ();
554  octave_idx_type b_len = b.length ();
555 
556  octave_idx_type si_len = (a_len > b_len ? a_len : b_len) - 1;
557 
558  dim_vector si_dims = x.dims ();
559  for (int i = dim; i > 0; i--)
560  si_dims(i) = si_dims(i-1);
561  si_dims(0) = si_len;
562 
563  si.resize (si_dims, 0.0);
564  }
565  else
566  {
567  si = args(3).float_array_value ();
568 
569  if (si.is_vector () && x.is_vector ())
570  si = si.reshape (dim_vector (si.numel (), 1));
571  }
572 
573  if (! error_state)
574  {
575  FloatNDArray y (filter (b, a, x, si, dim));
576 
577  if (nargout == 2)
578  retval(1) = si;
579 
580  retval(0) = y;
581  }
582  else
583  error (errmsg);
584  }
585  else
586  error (errmsg);
587  }
588  else
589  {
590  ColumnVector b (args(0).vector_value ());
591  ColumnVector a (args(1).vector_value ());
592 
593  NDArray x (args(2).array_value ());
594 
595  if (! error_state)
596  {
597  NDArray si;
598 
599  if (nargin == 3 || args(3).is_empty ())
600  {
601  octave_idx_type a_len = a.length ();
602  octave_idx_type b_len = b.length ();
603 
604  octave_idx_type si_len = (a_len > b_len ? a_len : b_len) - 1;
605 
606  dim_vector si_dims = x.dims ();
607  for (int i = dim; i > 0; i--)
608  si_dims(i) = si_dims(i-1);
609  si_dims(0) = si_len;
610 
611  si.resize (si_dims, 0.0);
612  }
613  else
614  {
615  si = args(3).array_value ();
616 
617  if (si.is_vector () && x.is_vector ())
618  si = si.reshape (dim_vector (si.numel (), 1));
619  }
620 
621  if (! error_state)
622  {
623  NDArray y (filter (b, a, x, si, dim));
624 
625  if (nargout == 2)
626  retval(1) = si;
627 
628  retval(0) = y;
629  }
630  else
631  error (errmsg);
632  }
633  else
634  error (errmsg);
635  }
636  }
637 
638  return retval;
639 }
640 
641 template MArray<double>
643  MArray<double>&, int dim);
644 
645 template MArray<double>
647 
648 template MArray<Complex>
650  MArray<Complex>&, int dim);
651 
652 template MArray<Complex>
654 
655 template MArray<float>
657  MArray<float>&, int dim);
658 
659 template MArray<float>
661 
662 template MArray<FloatComplex>
664  MArray<FloatComplex>&, int dim);
665 
666 template MArray<FloatComplex>
668  int dim);
669 
670 /*
671 %!shared a, b, x, r
672 %!test
673 %! a = [1 1];
674 %! b = [1 1];
675 %! x = zeros (1,10); x(1) = 1;
676 %! assert (filter (b, [1], x ), [1 1 0 0 0 0 0 0 0 0]);
677 %! assert (filter (b, [1], x.'), [1 1 0 0 0 0 0 0 0 0].');
678 %! assert (filter (b.', [1], x ), [1 1 0 0 0 0 0 0 0 0] );
679 %! assert (filter (b.', [1], x.'), [1 1 0 0 0 0 0 0 0 0].');
680 %! assert (filter ([1], a, x ), [+1 -1 +1 -1 +1 -1 +1 -1 +1 -1] );
681 %! assert (filter ([1], a, x.'), [+1 -1 +1 -1 +1 -1 +1 -1 +1 -1].');
682 %! assert (filter ([1], a.', x ), [+1 -1 +1 -1 +1 -1 +1 -1 +1 -1] );
683 %! assert (filter ([1], a.', x.'), [+1 -1 +1 -1 +1 -1 +1 -1 +1 -1].');
684 %! assert (filter (b, a, x ), [1 0 0 0 0 0 0 0 0 0] );
685 %! assert (filter (b.', a, x ), [1 0 0 0 0 0 0 0 0 0] );
686 %! assert (filter (b, a.', x ), [1 0 0 0 0 0 0 0 0 0] );
687 %! assert (filter (b.', a, x ), [1 0 0 0 0 0 0 0 0 0] );
688 %! assert (filter (b, a, x.'), [1 0 0 0 0 0 0 0 0 0].');
689 %! assert (filter (b.', a, x.'), [1 0 0 0 0 0 0 0 0 0].');
690 %! assert (filter (b, a.', x.'), [1 0 0 0 0 0 0 0 0 0].');
691 %! assert (filter (b.', a, x.'), [1 0 0 0 0 0 0 0 0 0].');
692 
693 %!test
694 %! r = sqrt (1/2) * (1+i);
695 %! a = a*r;
696 %! b = b*r;
697 %! assert (filter (b, [1], x ), r*[1 1 0 0 0 0 0 0 0 0] );
698 %! assert (filter (b, [1], r*x ), r*r*[1 1 0 0 0 0 0 0 0 0] );
699 %! assert (filter (b, [1], x.' ), r*[1 1 0 0 0 0 0 0 0 0].' );
700 %! assert (filter (b, a, x ), [1 0 0 0 0 0 0 0 0 0] );
701 %! assert (filter (b, a, r*x ), r*[1 0 0 0 0 0 0 0 0 0] );
702 
703 %!shared a, b, x, y, so
704 %!test
705 %! a = [1,1];
706 %! b = [1,1];
707 %! x = zeros (1,10); x(1) = 1;
708 %! [y, so] = filter (b, [1], x, [-1]);
709 %! assert (y, [0 1 0 0 0 0 0 0 0 0]);
710 %! assert (so, 0);
711 
712 %!test
713 %! x = zeros (10,3); x(1,1) = -1; x(1,2) = 1;
714 %! y0 = zeros (10,3); y0(1:2,1) = -1; y0(1:2,2) = 1;
715 %! y = filter (b, [1], x);
716 %! assert (y, y0);
717 
718 %!test
719 %! a = [1,1];
720 %! b=[1,1];
721 %! x = zeros (4,4,2); x(1,1:4,1) = +1; x(1,1:4,2) = -1;
722 %! y0 = zeros (4,4,2); y0(1:2,1:4,1) = +1; y0(1:2,1:4,2) = -1;
723 %! y = filter (b, [1], x);
724 %! assert (y, y0);
725 
726 %!assert (filter (1, ones (10,1) / 10, []), [])
727 %!assert (filter (1, ones (10,1) / 10, zeros (0,10)), zeros (0,10))
728 %!assert (filter (1, ones (10,1) / 10, single (1:5)), repmat (single (10), 1, 5))
729 
730 %% Test using initial conditions
731 %!assert (filter ([1, 1, 1], [1, 1], [1 2], [1, 1]), [2 2])
732 %!assert (filter ([1, 1, 1], [1, 1], [1 2], [1, 1]'), [2 2])
733 %!assert (filter ([1, 3], [1], [1 2; 3 4; 5 6], [4, 5]), [5 7; 6 10; 14 18])
734 %!error (filter ([1, 3], [1], [1 2; 3 4; 5 6], [4, 5]'))
735 %!assert (filter ([1, 3, 2], [1], [1 2; 3 4; 5 6], [1 0 0; 1 0 0], 2), [2 6; 3 13; 5 21])
736 
737 ## Test of DIM parameter
738 %!test
739 %! x = ones (2, 1, 3, 4);
740 %! x(1,1,:,:) = [1 2 3 4; 5 6 7 8; 9 10 11 12];
741 %! 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];
742 %! y0 = reshape (y0, size (x));
743 %! y = filter ([1 1 1], 1, x, [], 3);
744 %! assert (y, y0);
745 */
OCTINTERP_API void print_usage(void)
Definition: defun.cc:51
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:275
octave_idx_type length(void) const
Definition: oct-obj.h:89
#define DEFUN(name, args_name, nargout_name, doc)
Definition: defun.h:44
void error(const char *fmt,...)
Definition: error.cc:476
octave_idx_type numel(int n=0) const
Number of elements that a matrix with this dimensions would have.
Definition: dim-vector.h:361
const dim_vector & dims(void) const
Return a const-reference so that dims ()(i) works efficiently.
Definition: Array.h:337
bool is_vector(void) const
Definition: Array.h:474
MArray< double > filter(MArray< double > &, MArray< double > &, MArray< double > &, int dim)
const T * data(void) const
Definition: Array.h:479
double norm(const ColumnVector &v)
Definition: graphics.cc:5328
int error_state
Definition: error.cc:101
void resize(const dim_vector &dv, const T &rfv)
Definition: Array.cc:1033
octave_idx_type length(void) const
Number of elements in the array.
Definition: Array.h:267
const T * fortran_vec(void) const
Definition: Array.h:481
MArray< T > reshape(const dim_vector &new_dims) const
Definition: MArray.h:71
#define OCTAVE_QUIT
Definition: quit.h:130
int length(void) const
Definition: dim-vector.h:281
F77_RET_T const double * x