GNU Octave  6.2.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
conv2.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1999-2021 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 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29 
30 #include "oct-convn.h"
31 
32 #include "defun.h"
33 #include "error.h"
34 #include "ovl.h"
35 #include "utils.h"
36 
38 
39 DEFUN (conv2, args, ,
40  doc: /* -*- texinfo -*-
41 @deftypefn {} {} conv2 (@var{A}, @var{B})
42 @deftypefnx {} {} conv2 (@var{v1}, @var{v2}, @var{m})
43 @deftypefnx {} {} conv2 (@dots{}, @var{shape})
44 Return the 2-D convolution of @var{A} and @var{B}.
45 
46 The size of the result is determined by the optional @var{shape} argument
47 which takes the following values
48 
49 @table @asis
50 @item @var{shape} = @qcode{"full"}
51 Return the full convolution. (default)
52 
53 @item @var{shape} = @qcode{"same"}
54 Return the central part of the convolution with the same size as @var{A}.
55 The central part of the convolution begins at the indices
56 @code{floor ([size(@var{B})/2] + 1)}.
57 
58 @item @var{shape} = @qcode{"valid"}
59 Return only the parts which do not include zero-padded edges.
60 The size of the result is @code{max (size (A) - size (B) + 1, 0)}.
61 @end table
62 
63 When the third argument is a matrix, return the convolution of the matrix
64 @var{m} by the vector @var{v1} in the column direction and by the vector
65 @var{v2} in the row direction.
66 @seealso{conv, convn}
67 @end deftypefn */)
68 {
69  int nargin = args.length ();
70 
71  if (nargin < 2 || nargin > 4)
72  print_usage ();
73 
74  std::string shape = "full"; // default
75  bool separable = false;
77 
78  if (nargin == 3)
79  {
80  if (args(2).is_string ())
81  shape = args(2).string_value ();
82  else
83  separable = true;
84  }
85  else if (nargin == 4)
86  {
87  separable = true;
88  shape = args(3).string_value ();
89  }
90 
91  if (args(0).ndims () > 2 || args(1).ndims () > 2)
92  error ("conv2: A and B must be 1-D vectors or 2-D matrices");
93 
94  if (shape == "full")
95  ct = convn_full;
96  else if (shape == "same")
97  ct = convn_same;
98  else if (shape == "valid")
99  ct = convn_valid;
100  else
101  error ("conv2: SHAPE type not valid");
102 
104 
105  if (separable)
106  {
107  // If user requests separable, check first two params are vectors
108  if (! (1 == args(0).rows () || 1 == args(0).columns ())
109  || ! (1 == args(1).rows () || 1 == args(1).columns ()))
110  error ("conv2: arguments must be vectors for separable option");
111 
112  if (args(0).is_single_type () || args(1).is_single_type ()
113  || args(2).is_single_type ())
114  {
115  if (args(0).iscomplex () || args(1).iscomplex ()
116  || args(2).iscomplex ())
117  {
118  FloatComplexMatrix a (args(2).float_complex_matrix_value ());
119  if (args(1).isreal () && args(2).isreal ())
120  {
121  FloatColumnVector v1 (args(0).float_vector_value ());
122  FloatRowVector v2 (args(1).float_vector_value ());
123  retval = convn (a, v1, v2, ct);
124  }
125  else
126  {
127  FloatComplexColumnVector v1 (args(0).float_complex_vector_value ());
128  FloatComplexRowVector v2 (args(1).float_complex_vector_value ());
129  retval = convn (a, v1, v2, ct);
130  }
131  }
132  else
133  {
134  FloatColumnVector v1 (args(0).float_vector_value ());
135  FloatRowVector v2 (args(1).float_vector_value ());
136  FloatMatrix a (args(2).float_matrix_value ());
137  retval = convn (a, v1, v2, ct);
138  }
139  }
140  else
141  {
142  if (args(0).iscomplex () || args(1).iscomplex ()
143  || args(2).iscomplex ())
144  {
145  ComplexMatrix a (args(2).complex_matrix_value ());
146  if (args(1).isreal () && args(2).isreal ())
147  {
148  ColumnVector v1 (args(0).vector_value ());
149  RowVector v2 (args(1).vector_value ());
150  retval = convn (a, v1, v2, ct);
151  }
152  else
153  {
154  ComplexColumnVector v1 (args(0).complex_vector_value ());
155  ComplexRowVector v2 (args(1).complex_vector_value ());
156  retval = convn (a, v1, v2, ct);
157  }
158  }
159  else
160  {
161  ColumnVector v1 (args(0).vector_value ());
162  RowVector v2 (args(1).vector_value ());
163  Matrix a (args(2).matrix_value ());
164  retval = convn (a, v1, v2, ct);
165  }
166  }
167  } // if (separable)
168  else
169  {
170  if (args(0).is_single_type () || args(1).is_single_type ())
171  {
172  if (args(0).iscomplex () || args(1).iscomplex ())
173  {
174  FloatComplexMatrix a (args(0).float_complex_matrix_value ());
175  if (args(1).isreal ())
176  {
177  FloatMatrix b (args(1).float_matrix_value ());
178  retval = convn (a, b, ct);
179  }
180  else
181  {
182  FloatComplexMatrix b (args(1).float_complex_matrix_value ());
183  retval = convn (a, b, ct);
184  }
185  }
186  else
187  {
188  FloatMatrix a (args(0).float_matrix_value ());
189  FloatMatrix b (args(1).float_matrix_value ());
190  retval = convn (a, b, ct);
191  }
192  }
193  else
194  {
195  if (args(0).iscomplex () || args(1).iscomplex ())
196  {
197  ComplexMatrix a (args(0).complex_matrix_value ());
198  if (args(1).isreal ())
199  {
200  Matrix b (args(1).matrix_value ());
201  retval = convn (a, b, ct);
202  }
203  else
204  {
205  ComplexMatrix b (args(1).complex_matrix_value ());
206  retval = convn (a, b, ct);
207  }
208  }
209  else
210  {
211  Matrix a (args(0).matrix_value ());
212  Matrix b (args(1).matrix_value ());
213  retval = convn (a, b, ct);
214  }
215  }
216 
217  } // if (separable)
218 
219  return retval;
220 }
221 
222 /*
223 %!test
224 %! c = [0,1,2,3;1,8,12,12;4,20,24,21;7,22,25,18];
225 %! assert (conv2 ([0,1;1,2], [1,2,3;4,5,6;7,8,9]), c);
226 
227 %!test
228 %! c = single ([0,1,2,3;1,8,12,12;4,20,24,21;7,22,25,18]);
229 %! assert (conv2 (single ([0,1;1,2]), single ([1,2,3;4,5,6;7,8,9])), c);
230 
231 %!test
232 %! c = [1,4,4;5,18,16;14,48,40;19,62,48;15,48,36];
233 %! assert (conv2 (1:3, 1:2, [1,2;3,4;5,6]), c);
234 
235 %!assert (conv2 (1:3, 1:2, [1,2;3,4;5,6], "full"),
236 %! conv2 (1:3, 1:2, [1,2;3,4;5,6]));
237 
238 ## Test shapes
239 %!shared A, B, C
240 %! A = rand (3, 4);
241 %! B = rand (4);
242 %! C = conv2 (A, B);
243 %!assert (conv2 (A,B, "full"), C)
244 %!assert (conv2 (A,B, "same"), C(3:5,3:6))
245 %!assert (conv2 (A,B, "valid"), zeros (0, 1))
246 %!assert (size (conv2 (B,A, "valid")), [2 1])
247 
248 %!test
249 %! B = rand (5);
250 %! C = conv2 (A, B);
251 %!assert (conv2 (A,B, "full"), C)
252 %!assert (conv2 (A,B, "same"), C(3:5,3:6))
253 %!assert (conv2 (A,B, "valid"), zeros (0, 0))
254 %!assert (size (conv2 (B,A, "valid")), [3 2])
255 
256 ## Clear shared variables so they are not reported for tests below
257 %!shared
258 
259 ## Test cases from Bug #34893
260 %!assert <*34893> (conv2 ([1:5;1:5], [1:2], "same"),
261 %! [4 7 10 13 10; 4 7 10 13 10])
262 %!assert <*34893> (conv2 ([1:5;1:5]', [1:2]', "same"),
263 %! [4 7 10 13 10; 4 7 10 13 10]')
264 %!assert <*34893> (conv2 ([1:5;1:5], [1:2], "valid"),
265 %! [4 7 10 13; 4 7 10 13])
266 %!assert <*34893> (conv2 ([1:5;1:5]', [1:2]', "valid"),
267 %! [4 7 10 13; 4 7 10 13]')
268 
269 %% Restore the rand "seed" and "state" values in order, so that the
270 %% new "state" algorithm remains active after these tests complete.
271 %!function restore_rand_state (seed, state)
272 %! rand ("seed", seed);
273 %! rand ("state", state);
274 %!endfunction
275 
276 %% FIXME: This test only passes when using the "old" random number
277 %% generator by setting the "seed" parameter to any value. If
278 %% the "state" parameter is used, the test fails. This probably
279 %% indicates that this test is particularly fragile. This might
280 %% need further investigation or a rewrite, for example using
281 %% random integer values to avoid precision overflow.
282 %!test
283 %! old_seed = rand ("seed");
284 %! old_state = rand ("state");
285 %! restore_state = onCleanup (@() restore_rand_state (old_seed, old_state));
286 %! rand ("seed", 42);
287 %! x = rand (100);
288 %! y = ones (5);
289 %! A = conv2 (x, y)(5:end-4,5:end-4);
290 %! B = conv2 (x, y, "valid");
291 %! assert (B, A); # Yes, this test is for *exact* equivalence.
292 
293 ## Test input validation
294 %!error conv2 ()
295 %!error conv2 (1)
296 %!error <must be 1-D vectors or 2-D matrices> conv2 (ones (2), ones (2,2,2))
297 %!error <SHAPE type not valid> conv2 (1,2, "NOT_A_SHAPE")
298 ## Test alternate calling form which should be 2 vectors and a matrix
299 %!error conv2 (ones (2), 1, 1)
300 %!error conv2 (1, ones (2), 1)
301 */
302 
303 DEFUN (convn, args, ,
304  doc: /* -*- texinfo -*-
305 @deftypefn {} {@var{C} =} convn (@var{A}, @var{B})
306 @deftypefnx {} {@var{C} =} convn (@var{A}, @var{B}, @var{shape})
307 Return the n-D convolution of @var{A} and @var{B}.
308 
309 The size of the result is determined by the optional @var{shape} argument
310 which takes the following values
311 
312 @table @asis
313 @item @var{shape} = @qcode{"full"}
314 Return the full convolution. (default)
315 
316 @item @var{shape} = @qcode{"same"}
317 Return central part of the convolution with the same size as @var{A}.
318 The central part of the convolution begins at the indices
319 @code{floor ([size(@var{B})/2] + 1)}.
320 
321 @item @var{shape} = @qcode{"valid"}
322 Return only the parts which do not include zero-padded edges.
323 The size of the result is @code{max (size (A) - size (B) + 1, 0)}.
324 @end table
325 
326 @seealso{conv2, conv}
327 @end deftypefn */)
328 {
329  int nargin = args.length ();
330 
331  if (nargin < 2 || nargin > 3)
332  print_usage ();
333 
334  std::string shape = "full"; // default
335  convn_type ct = convn_full;
336 
337  if (nargin == 3)
338  shape = args(2).xstring_value ("convn: SHAPE must be a string");
339 
340  if (shape == "full")
341  ct = convn_full;
342  else if (shape == "same")
343  ct = convn_same;
344  else if (shape == "valid")
345  ct = convn_valid;
346  else
347  error ("convn: SHAPE type not valid");
348 
350 
351  if (args(0).is_single_type () || args(1).is_single_type ())
352  {
353  if (args(0).iscomplex () || args(1).iscomplex ())
354  {
355  FloatComplexNDArray a (args(0).float_complex_array_value ());
356  if (args(1).isreal ())
357  {
358  FloatNDArray b (args(1).float_array_value ());
359  retval = convn (a, b, ct);
360  }
361  else
362  {
363  FloatComplexNDArray b (args(1).float_complex_array_value ());
364  retval = convn (a, b, ct);
365  }
366  }
367  else
368  {
369  FloatNDArray a (args(0).float_array_value ());
370  FloatNDArray b (args(1).float_array_value ());
371  retval = convn (a, b, ct);
372  }
373  }
374  else
375  {
376  if (args(0).iscomplex () || args(1).iscomplex ())
377  {
378  ComplexNDArray a (args(0).complex_array_value ());
379  if (args(1).isreal ())
380  {
381  NDArray b (args(1).array_value ());
382  retval = convn (a, b, ct);
383  }
384  else
385  {
386  ComplexNDArray b (args(1).complex_array_value ());
387  retval = convn (a, b, ct);
388  }
389  }
390  else
391  {
392  NDArray a (args(0).array_value ());
393  NDArray b (args(1).array_value ());
394  retval = convn (a, b, ct);
395  }
396  }
397 
398  return retval;
399 }
400 
401 /*
402 %!test <39314>
403 %! v = reshape ([1 2], [1 1 2]);
404 %! assert (convn (v, v), reshape ([1 4 4], [1 1 3]));
405 %! assert (convn (v, v, "same"), reshape ([4 4], [1 1 2]));
406 %! assert (convn (v, v, "valid"), 4);
407 
408 ## The following test may look weird since we are using the output
409 ## of convn to test itself. However, because calculations are done
410 ## differently based on the shape option, it will help to catch some
411 ## bugs. See also bug #39314.
412 ## FIXME: The "valid" option uses an entirely different code path
413 ## through C++ and Fortran to calculate inner convolution.
414 ## The terms in the convolution added in reverse order compared
415 ## to the "full" option. This produces differences on the order
416 ## of tens of eps. This should be fixed, but in the meantime
417 ## the tests will be marked as known failures.
418 %!shared a, b, c
419 %! ## test 3D by 3D
420 %! a = rand (10, 10, 10);
421 %! b = rand (3, 3, 3);
422 %! c = convn (a, b, "full");
423 %!assert (convn (a, b, "same"), c(2:11,2:11,2:11))
424 %!test <39314>
425 %! assert (convn (a, b, "valid"), c(3:10,3:10,3:10));
426 %!
427 %!test
428 %! ## test 3D by 2D
429 %! a = rand (10, 10, 10);
430 %! b = rand (3, 3);
431 %! c = convn (a, b, "full");
432 %!assert (convn (a, b, "same"), c(2:11,2:11,:))
433 %!test <39314>
434 %! assert (convn (a, b, "valid"), c(3:10,3:10,:));
435 %!
436 %!test
437 %! ## test 2D by 3D
438 %! a = rand (10, 10);
439 %! b = rand (3, 3, 3);
440 %! c = convn (a, b, "full");
441 %!assert (convn (a, b, "same"), c(2:11,2:11,2))
442 %!assert (convn (a, b, "valid"), c(3:10,3:10,3:2)) # a 7x7x0 matrix
443 %!
444 %!test
445 %! ## test multiple different number of dimensions, with odd and even numbers
446 %! a = rand (10, 15, 7, 8, 10);
447 %! b = rand (4, 3, 2, 3);
448 %! c = convn (a, b, "full");
449 %!assert (convn (a, b, "same"), c(3:12,2:16,2:8,2:9,:))
450 %!test <39314>
451 %! assert (convn (a, b, "valid"), c(4:10,3:15,2:7,3:8,:));
452 
453 %!test
454 %! a = reshape (floor (magic (16) /10), [4 8 4 2]);
455 %! b = reshape (magic (6), [4 3 3]);
456 %! c = zeros (7, 10, 6, 2);
457 %! c(:,:,1,1) = [
458 %! 875 1415 1215 741 288 264 635 1109 687 171
459 %! 110 467 1551 1790 1891 1651 1165 900 659 568
460 %! 883 1047 1475 1964 2181 2302 2117 1674 579 234
461 %! 940 2330 3099 2573 2306 2207 2442 2918 2272 1004
462 %! 161 500 1564 2066 2355 2270 2099 1621 1144 831
463 %! 644 622 886 1121 1652 1967 1907 1668 529 228
464 %! 160 752 1232 768 360 284 668 1132 1380 864];
465 %! c(:,:,2,1) = [
466 %! 150 1174 1903 1971 2030 1719 1467 1420 1220 472
467 %! 986 2243 2603 2385 2308 2530 2971 3181 2266 768
468 %! 914 2443 3750 3782 3976 3821 3723 3709 2599 1178
469 %! 1922 3374 5198 5472 5563 5853 5794 5543 3578 1820
470 %! 1060 2471 3846 3724 3682 3803 3812 3927 2876 1390
471 %! 470 2078 3283 3225 2701 2265 2165 2261 2324 1124
472 %! 700 1130 1486 1515 1830 2097 2081 2028 1009 348];
473 %! c(:,:,3,1) = [
474 %! 1350 2127 2461 2082 1694 1909 2230 2621 1681 683
475 %! 877 2473 4362 4556 4543 4314 3879 3703 2863 1497
476 %! 1934 4219 5874 6117 5966 6051 5984 5714 3891 1562
477 %! 1927 5997 8573 8456 8517 8025 7957 8101 6121 2500
478 %! 1558 3533 5595 6064 6453 6491 6275 5743 3794 1832
479 %! 1950 2762 3455 3423 4019 4578 4807 4857 2304 907
480 %! 525 1860 2731 2392 1872 1724 1961 2312 2315 1141];
481 %! c(:,:,4,1) = [
482 %! 150 1317 2230 2621 2996 2767 2472 2049 1514 583
483 %! 1429 3056 3879 3703 3756 3964 4394 4570 3111 1250
484 %! 1833 4037 5984 5714 5846 5788 5883 6129 4157 2011
485 %! 3143 5469 7957 8101 8063 8475 8564 8439 5306 2538
486 %! 2001 4514 6275 5743 5391 5389 5578 6110 4473 1953
487 %! 817 3196 4807 4857 4229 3659 3477 3375 3208 1400
488 %! 750 1365 1961 2312 2840 2993 2722 2344 1092 323];
489 %! c(:,:,5,1) = [
490 %! 475 734 1296 1352 1400 1595 1557 1517 960 490
491 %! 751 1977 2831 2746 2607 2665 2733 2833 2186 912
492 %! 1065 3142 4344 4150 3768 3734 3876 4086 3366 1327
493 %! 976 3712 5530 5921 6158 5802 5481 5071 3821 1491
494 %! 1397 2996 3971 4003 4088 4180 4199 4146 2649 985
495 %! 1273 2121 2555 2247 2378 2624 2908 3229 1788 705
496 %! 365 1108 1530 1652 1550 1407 1274 1127 889 264];
497 %! c(:,:,6,1) = [
498 %! 0 133 345 683 982 1058 960 623 310 100
499 %! 437 806 1313 1332 1383 1391 1397 1370 864 495
500 %! 928 1573 2201 1928 1864 1932 2183 2445 1557 855
501 %! 1199 2083 2739 2573 2507 2656 2786 2928 1795 736
502 %! 912 1997 2404 2028 1692 1591 1803 2159 1603 599
503 %! 345 1092 1526 1666 1593 1437 1275 1116 863 253
504 %! 50 235 510 811 998 894 615 318 77 0];
505 %! c(:,:,1,2) = [
506 %! 840 1350 1176 697 293 320 674 1153 717 180
507 %! 142 490 1563 1824 1929 1604 1132 857 624 587
508 %! 890 1084 1539 1979 2238 2333 2072 1610 509 202
509 %! 966 2263 3034 2518 2250 2235 2512 2992 2305 1016
510 %! 200 561 1607 2107 2361 2277 2030 1548 1102 818
511 %! 652 631 922 1128 1670 1997 1895 1665 467 197
512 %! 160 744 1192 692 292 256 708 1208 1448 900];
513 %! c(:,:,2,2) = [
514 %! 179 1199 1886 1987 1997 1716 1479 1383 1215 485
515 %! 988 2213 2552 2358 2304 2615 3011 3210 2246 744
516 %! 921 2483 3747 3768 3960 3835 3712 3698 2588 1183
517 %! 1903 3416 5254 5490 5572 5826 5761 5505 3502 1814
518 %! 1064 2507 3825 3666 3680 3748 3821 3958 2892 1395
519 %! 495 2129 3277 3228 2566 2216 2154 2250 2390 1154
520 %! 700 1105 1472 1524 1856 2113 2059 2019 975 325];
521 %! c(:,:,3,2) = [
522 %! 1302 2104 2439 2006 1723 1931 2280 2685 1678 690
523 %! 877 2507 4408 4580 4523 4233 3852 3647 2850 1516
524 %! 1949 4238 5895 6143 6018 6063 5930 5656 3847 1538
525 %! 1953 5975 8547 8433 8407 8060 7955 8069 6170 2506
526 %! 1621 3536 5624 6117 6459 6456 6180 5666 3735 1815
527 %! 1904 2751 3429 3366 4122 4622 4840 4864 2242 882
528 %! 517 1843 2674 2337 1777 1686 2005 2367 2385 1175];
529 %! c(:,:,4,2) = [
530 %! 198 1346 2280 2685 2980 2759 2396 1982 1497 576
531 %! 1413 2994 3852 3647 3756 4035 4418 4595 3109 1231
532 %! 1873 4025 5930 5656 5792 5772 5909 6152 4185 2035
533 %! 3110 5510 7955 8069 8139 8456 8541 8439 5276 2541
534 %! 1964 4462 6180 5666 5315 5409 5631 6178 4536 1998
535 %! 869 3215 4840 4864 4121 3579 3420 3386 3271 1430
536 %! 725 1361 2005 2367 2925 3006 2667 2297 1054 325];
537 %! c(:,:,5,2) = [
538 %! 462 754 1285 1359 1441 1605 1556 1488 938 488
539 %! 729 1967 2788 2732 2608 2683 2744 2830 2195 912
540 %! 1052 3139 4302 4101 3742 3730 3895 4103 3403 1335
541 %! 1007 3725 5577 5964 6165 5754 5407 5006 3846 1507
542 %! 1375 2969 3951 3990 4144 4183 4200 4150 2661 998
543 %! 1258 2090 2495 2188 2403 2664 2954 3279 1814 723
544 %! 388 1127 1551 1673 1525 1390 1253 1139 912 275];
545 %! c(:,:,6,2) = [
546 %! 19 147 384 716 1016 1059 927 570 276 80
547 %! 441 791 1298 1320 1401 1396 1409 1367 865 500
548 %! 932 1537 2155 1870 1860 1946 2221 2487 1584 874
549 %! 1201 2067 2705 2538 2512 2687 2806 2971 1812 756
550 %! 925 1976 2363 1971 1636 1600 1844 2239 1664 626
551 %! 372 1133 1558 1687 1570 1401 1243 1122 883 264
552 %! 60 270 556 857 1024 870 569 282 66 0];
553 %!assert (convn(a, b, "full"), c)
554 %!assert (convn(a, b, "same"), c(3:6,2:9,2:5,:))
555 %!assert (convn(a, b, "valid"), c(4,3:8,3:4,:))
556 
557 ## test correct class
558 %!assert (class (convn (rand(5), rand(3))), "double")
559 %!assert (class (convn (rand(5, "single"), rand(3))), "single")
560 %!assert (class (convn (rand(5), rand(3, "single"))), "single")
561 %!assert (class (convn (true (5), rand(3))), "double")
562 %!assert (class (convn (true (5), rand(3, "single"))), "single")
563 %!assert (class (convn (ones(5, "uint8"), rand(3))), "double")
564 %!assert (class (convn (rand (3, "single"), ones(5, "uint8"))), "single")
565 
566 %!error convn ()
567 %!error convn (1)
568 %!error <SHAPE type not valid> convn (1,2, "NOT_A_SHAPE")
569 %!error convn (rand (3), 1, 1)
570 */
Definition: dMatrix.h:42
Shape
Definition: conv2.cc:37
@ SHAPE_VALID
Definition: conv2.cc:37
@ SHAPE_SAME
Definition: conv2.cc:37
@ SHAPE_FULL
Definition: conv2.cc:37
OCTINTERP_API void print_usage(void)
Definition: defun.cc:53
#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:968
NDArray convn(const NDArray &a, const NDArray &b, convn_type ct)
Definition: oct-convn.cc:199
convn_type
Definition: oct-convn.h:49
@ convn_full
Definition: oct-convn.h:50
@ convn_valid
Definition: oct-convn.h:52
@ convn_same
Definition: oct-convn.h:51
const octave_char_matrix & v2
octave_value::octave_value(const Array< char > &chm, char type) return retval
Definition: ov.cc:811