Mercurial > hg > octave-lyh
annotate scripts/general/accumdim.m @ 14113:dac62c415e8b stable
Do more error checking on accumarray and accumdim input.
* accumarray.m: Check that number indices matches number of values to
accumulate. Document this change.
* accumdim.m: Check that length of index vector equals length of array
along given dimension. Also let the extension parameter be empty in
addition to being zero. Document this change and reformat docstring.
* data.cc (do_accumdim_sum): Check that number of indices matches
number of values.
author | Jordi Gutiérrez Hermoso <jordigh@octave.org> |
---|---|
date | Tue, 27 Dec 2011 13:45:30 -0500 |
parents | 6590446c2498 |
children | 951eacaf9381 |
rev | line source |
---|---|
11523 | 1 ## Copyright (C) 2010-2011 VZLU Prague |
10395 | 2 ## |
3 ## This file is part of Octave. | |
4 ## | |
5 ## Octave is free software; you can redistribute it and/or modify it | |
6 ## under the terms of the GNU General Public License as published by | |
7 ## the Free Software Foundation; either version 3 of the License, or (at | |
8 ## your option) any later version. | |
9 ## | |
10 ## Octave is distributed in the hope that it will be useful, but | |
11 ## WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 ## General Public License for more details. | |
14 ## | |
15 ## You should have received a copy of the GNU General Public License | |
16 ## along with Octave; see the file COPYING. If not, see | |
17 ## <http://www.gnu.org/licenses/>. | |
18 | |
19 ## -*- texinfo -*- | |
10692
b32a0214a464
Use > 1 test to find first non-singleton dimension rather than != 1.
Rik <octave@nomad.inbox5.com>
parents:
10397
diff
changeset
|
20 ## @deftypefn {Function File} {} accumdim (@var{subs}, @var{vals}, @var{dim}, @var{n}, @var{func}, @var{fillval}) |
10395 | 21 ## Create an array by accumulating the slices of an array into the |
11587
c792872f8942
all script files: untabify and strip trailing whitespace
John W. Eaton <jwe@octave.org>
parents:
11523
diff
changeset
|
22 ## positions defined by their subscripts along a specified dimension. |
10395 | 23 ## The subscripts are defined by the index vector @var{subs}. |
10711
fbd7843974fa
Periodic grammar check of documentation files to ensure common format.
Rik <octave@nomad.inbox5.com>
parents:
10692
diff
changeset
|
24 ## The dimension is specified by @var{dim}. If not given, it defaults |
14113
dac62c415e8b
Do more error checking on accumarray and accumdim input.
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
12974
diff
changeset
|
25 ## to the first non-singleton dimension. The length of @var{subs} must |
dac62c415e8b
Do more error checking on accumarray and accumdim input.
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
12974
diff
changeset
|
26 ## be equal to @code{size (@var{vals}, @var{dim})}. |
10395 | 27 ## |
14113
dac62c415e8b
Do more error checking on accumarray and accumdim input.
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
12974
diff
changeset
|
28 ## The extent of the result matrix in the working dimension will be |
dac62c415e8b
Do more error checking on accumarray and accumdim input.
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
12974
diff
changeset
|
29 ## determined by the subscripts themselves. However, if @var{n} is |
dac62c415e8b
Do more error checking on accumarray and accumdim input.
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
12974
diff
changeset
|
30 ## defined it determines this extent. |
10395 | 31 ## |
32 ## The default action of @code{accumdim} is to sum the subarrays with the | |
14113
dac62c415e8b
Do more error checking on accumarray and accumdim input.
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
12974
diff
changeset
|
33 ## same subscripts. This behavior can be modified by defining the |
dac62c415e8b
Do more error checking on accumarray and accumdim input.
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
12974
diff
changeset
|
34 ## @var{func} function. This should be a function or function handle |
dac62c415e8b
Do more error checking on accumarray and accumdim input.
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
12974
diff
changeset
|
35 ## that accepts an array and a dimension, and reduces the array along |
dac62c415e8b
Do more error checking on accumarray and accumdim input.
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
12974
diff
changeset
|
36 ## this dimension. As a special exception, the built-in @code{min} and |
dac62c415e8b
Do more error checking on accumarray and accumdim input.
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
12974
diff
changeset
|
37 ## @code{max} functions can be used directly, and @code{accumdim} |
dac62c415e8b
Do more error checking on accumarray and accumdim input.
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
12974
diff
changeset
|
38 ## accounts for the middle empty argument that is used in their calling. |
10395 | 39 ## |
14113
dac62c415e8b
Do more error checking on accumarray and accumdim input.
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
12974
diff
changeset
|
40 ## The slices of the returned array that have no subscripts associated |
dac62c415e8b
Do more error checking on accumarray and accumdim input.
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
12974
diff
changeset
|
41 ## with them are set to zero. Defining @var{fillval} to some other |
dac62c415e8b
Do more error checking on accumarray and accumdim input.
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
12974
diff
changeset
|
42 ## value allows these values to be defined. |
10395 | 43 ## |
10397
180931276a52
fix example in accumdim
Jaroslav Hajek <highegg@gmail.com>
parents:
10396
diff
changeset
|
44 ## An example of the use of @code{accumdim} is: |
10395 | 45 ## |
12974
6590446c2498
doc: Correct Texinfo overfull hbox instances.
Rik <octave@nomad.inbox5.com>
parents:
11589
diff
changeset
|
46 ## @smallexample |
10395 | 47 ## @group |
14113
dac62c415e8b
Do more error checking on accumarray and accumdim input.
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
12974
diff
changeset
|
48 ## accumdim ([1, 2, 1, 2, 1], [ 7, -10, 4; |
dac62c415e8b
Do more error checking on accumarray and accumdim input.
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
12974
diff
changeset
|
49 ## -5, -12, 8; |
dac62c415e8b
Do more error checking on accumarray and accumdim input.
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
12974
diff
changeset
|
50 ## -12, 2, 8; |
dac62c415e8b
Do more error checking on accumarray and accumdim input.
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
12974
diff
changeset
|
51 ## -10, 9, -3; |
dac62c415e8b
Do more error checking on accumarray and accumdim input.
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
12974
diff
changeset
|
52 ## -5, -3, -13]) |
10397
180931276a52
fix example in accumdim
Jaroslav Hajek <highegg@gmail.com>
parents:
10396
diff
changeset
|
53 ## @result{} ans = [-10,-11,-1;-15,-3,5] |
10395 | 54 ## @end group |
12974
6590446c2498
doc: Correct Texinfo overfull hbox instances.
Rik <octave@nomad.inbox5.com>
parents:
11589
diff
changeset
|
55 ## @end smallexample |
10395 | 56 ## |
57 ## @seealso{accumarray} | |
58 ## @end deftypefn | |
59 | |
11469
c776f063fefe
Overhaul m-script files to use common variable name between code and documentation.
Rik <octave@nomad.inbox5.com>
parents:
11191
diff
changeset
|
60 function A = accumdim (subs, vals, dim, n = 0, func = [], fillval = 0) |
10395 | 61 |
62 if (nargin < 2 || nargin > 5) | |
63 print_usage (); | |
64 endif | |
65 | |
66 if (isempty (fillval)) | |
67 fillval = 0; | |
68 endif | |
69 | |
70 if (! isvector (subs)) | |
10692
b32a0214a464
Use > 1 test to find first non-singleton dimension rather than != 1.
Rik <octave@nomad.inbox5.com>
parents:
10397
diff
changeset
|
71 error ("accumdim: SUBS must be a subscript vector"); |
10395 | 72 elseif (! isindex (subs)) # creates index cache |
73 error ("accumdim: indices must be positive integers"); | |
74 else | |
75 m = max (subs); | |
14113
dac62c415e8b
Do more error checking on accumarray and accumdim input.
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
12974
diff
changeset
|
76 if (n == 0 || isempty (n)) |
10395 | 77 n = m; |
78 elseif (n < m) | |
11589
b0084095098e
missing semicolons in script files
John W. Eaton <jwe@octave.org>
parents:
11587
diff
changeset
|
79 error ("accumdim: N index out of range"); |
10395 | 80 endif |
81 endif | |
82 | |
11469
c776f063fefe
Overhaul m-script files to use common variable name between code and documentation.
Rik <octave@nomad.inbox5.com>
parents:
11191
diff
changeset
|
83 sz = size (vals); |
10395 | 84 |
85 if (nargin < 3) | |
10790
01f1643dfbb1
fix flipdim with trailing singleton dims
Jaroslav Hajek <highegg@gmail.com>
parents:
10711
diff
changeset
|
86 [~, dim] = max (sz != 1); # first non-singleton dim |
10396
a0b51ac0f88a
optimize accumdim with summation
Jaroslav Hajek <highegg@gmail.com>
parents:
10395
diff
changeset
|
87 elseif (! isindex (dim)) |
10692
b32a0214a464
Use > 1 test to find first non-singleton dimension rather than != 1.
Rik <octave@nomad.inbox5.com>
parents:
10397
diff
changeset
|
88 error ("accumdim: DIM must be a valid dimension"); |
10396
a0b51ac0f88a
optimize accumdim with summation
Jaroslav Hajek <highegg@gmail.com>
parents:
10395
diff
changeset
|
89 elseif (dim > length (sz)) |
a0b51ac0f88a
optimize accumdim with summation
Jaroslav Hajek <highegg@gmail.com>
parents:
10395
diff
changeset
|
90 sz(end+1:dim) = 1; |
10395 | 91 endif |
92 sz(dim) = n; | |
11587
c792872f8942
all script files: untabify and strip trailing whitespace
John W. Eaton <jwe@octave.org>
parents:
11523
diff
changeset
|
93 |
14113
dac62c415e8b
Do more error checking on accumarray and accumdim input.
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
12974
diff
changeset
|
94 if (length (subs) != size (vals, dim)) |
dac62c415e8b
Do more error checking on accumarray and accumdim input.
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
12974
diff
changeset
|
95 error ("accumdim: dimension mismatch") |
dac62c415e8b
Do more error checking on accumarray and accumdim input.
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
12974
diff
changeset
|
96 endif |
dac62c415e8b
Do more error checking on accumarray and accumdim input.
Jordi Gutiérrez Hermoso <jordigh@octave.org>
parents:
12974
diff
changeset
|
97 |
10396
a0b51ac0f88a
optimize accumdim with summation
Jaroslav Hajek <highegg@gmail.com>
parents:
10395
diff
changeset
|
98 if (isempty (func) || func == @sum) |
a0b51ac0f88a
optimize accumdim with summation
Jaroslav Hajek <highegg@gmail.com>
parents:
10395
diff
changeset
|
99 ## Fast summation case. |
11469
c776f063fefe
Overhaul m-script files to use common variable name between code and documentation.
Rik <octave@nomad.inbox5.com>
parents:
11191
diff
changeset
|
100 A = __accumdim_sum__ (subs, vals, dim, n); |
11587
c792872f8942
all script files: untabify and strip trailing whitespace
John W. Eaton <jwe@octave.org>
parents:
11523
diff
changeset
|
101 |
10396
a0b51ac0f88a
optimize accumdim with summation
Jaroslav Hajek <highegg@gmail.com>
parents:
10395
diff
changeset
|
102 ## Fill in nonzero fill value |
a0b51ac0f88a
optimize accumdim with summation
Jaroslav Hajek <highegg@gmail.com>
parents:
10395
diff
changeset
|
103 if (fillval != 0) |
a0b51ac0f88a
optimize accumdim with summation
Jaroslav Hajek <highegg@gmail.com>
parents:
10395
diff
changeset
|
104 mask = true (n, 1); |
a0b51ac0f88a
optimize accumdim with summation
Jaroslav Hajek <highegg@gmail.com>
parents:
10395
diff
changeset
|
105 mask(subs) = false; |
a0b51ac0f88a
optimize accumdim with summation
Jaroslav Hajek <highegg@gmail.com>
parents:
10395
diff
changeset
|
106 subsc = {':'}(ones (1, length (sz))); |
a0b51ac0f88a
optimize accumdim with summation
Jaroslav Hajek <highegg@gmail.com>
parents:
10395
diff
changeset
|
107 subsc{dim} = mask; |
a0b51ac0f88a
optimize accumdim with summation
Jaroslav Hajek <highegg@gmail.com>
parents:
10395
diff
changeset
|
108 A(subsc{:}) = fillval; |
a0b51ac0f88a
optimize accumdim with summation
Jaroslav Hajek <highegg@gmail.com>
parents:
10395
diff
changeset
|
109 endif |
a0b51ac0f88a
optimize accumdim with summation
Jaroslav Hajek <highegg@gmail.com>
parents:
10395
diff
changeset
|
110 return |
a0b51ac0f88a
optimize accumdim with summation
Jaroslav Hajek <highegg@gmail.com>
parents:
10395
diff
changeset
|
111 endif |
a0b51ac0f88a
optimize accumdim with summation
Jaroslav Hajek <highegg@gmail.com>
parents:
10395
diff
changeset
|
112 |
a0b51ac0f88a
optimize accumdim with summation
Jaroslav Hajek <highegg@gmail.com>
parents:
10395
diff
changeset
|
113 ## The general case. |
10395 | 114 ns = length (subs); |
115 ## Sort indices. | |
116 [subs, idx] = sort (subs(:)); | |
117 ## Identify runs. | |
118 jdx = find (subs(1:ns-1) != subs(2:ns)); | |
119 jdx = [jdx; ns]; | |
120 ## Collect common slices. | |
121 szc = num2cell (sz); | |
122 szc{dim} = diff ([0; jdx]); | |
123 subsc = {':'}(ones (1, length (sz))); | |
124 subsc{dim} = idx; | |
11469
c776f063fefe
Overhaul m-script files to use common variable name between code and documentation.
Rik <octave@nomad.inbox5.com>
parents:
11191
diff
changeset
|
125 vals = mat2cell (vals(subsc{:}), szc{:}); |
10395 | 126 ## Apply reductions. Special case min, max. |
127 if (func == @min || func == @max) | |
11469
c776f063fefe
Overhaul m-script files to use common variable name between code and documentation.
Rik <octave@nomad.inbox5.com>
parents:
11191
diff
changeset
|
128 vals = cellfun (func, vals, {[]}, {dim}, "uniformoutput", false); |
10395 | 129 else |
11469
c776f063fefe
Overhaul m-script files to use common variable name between code and documentation.
Rik <octave@nomad.inbox5.com>
parents:
11191
diff
changeset
|
130 vals = cellfun (func, vals, {dim}, "uniformoutput", false); |
10395 | 131 endif |
132 subs = subs(jdx); | |
133 | |
134 ## Concatenate reduced slices. | |
11469
c776f063fefe
Overhaul m-script files to use common variable name between code and documentation.
Rik <octave@nomad.inbox5.com>
parents:
11191
diff
changeset
|
135 vals = cat (dim, vals{:}); |
10395 | 136 |
137 ## Construct matrix of fillvals. | |
138 if (fillval == 0) | |
11469
c776f063fefe
Overhaul m-script files to use common variable name between code and documentation.
Rik <octave@nomad.inbox5.com>
parents:
11191
diff
changeset
|
139 A = zeros (sz, class (vals)); |
10395 | 140 else |
141 A = repmat (fillval, sz); | |
142 endif | |
143 | |
144 ## Set the reduced values. | |
145 subsc{dim} = subs; | |
11469
c776f063fefe
Overhaul m-script files to use common variable name between code and documentation.
Rik <octave@nomad.inbox5.com>
parents:
11191
diff
changeset
|
146 A(subsc{:}) = vals; |
10395 | 147 |
148 endfunction | |
149 | |
150 %%test accumdim vs. accumarray | |
151 | |
152 %!shared a | |
153 %! a = rand (5, 5, 5); | |
154 | |
155 %!assert (accumdim ([1;3;1;3;3], a)(:,2,3), accumarray ([1;3;1;3;3], a(:,2,3))) | |
156 %!assert (accumdim ([2;3;2;2;2], a, 2, 4)(4,:,2), accumarray ([2;3;2;2;2], a(4,:,2), [1,4])) | |
157 %!assert (accumdim ([2;3;2;1;2], a, 3, 3, @min)(1,5,:), accumarray ([2;3;2;1;2], a(1,5,:), [1,1,3], @min)) | |
158 %!assert (accumdim ([1;3;2;2;1], a, 2, 3, @median)(4,:,5), accumarray ([1;3;2;2;1], a(4,:,5), [1,3], @median)) |