1 ## Copyright (C) 2009-2012 Søren Hauberg
2 ## Copyright (C) 2009 VZLU Prague
4 ## This file is part of Octave.
6 ## Octave is free software; you can redistribute it and/or modify it
7 ## under the terms of the GNU General Public License as published by
8 ## the Free Software Foundation; either version 3 of the License, or (at
9 ## your option) any later version.
11 ## Octave is distributed in the hope that it will be useful, but
12 ## WITHOUT ANY WARRANTY; without even the implied warranty of
13 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ## General Public License for more details.
16 ## You should have received a copy of the GNU General Public License
17 ## along with Octave; see the file COPYING. If not, see
18 ## <http://www.gnu.org/licenses/>.
21 ## @deftypefn {Function File} {@var{n} =} histc (@var{x}, @var{edges})
22 ## @deftypefnx {Function File} {@var{n} =} histc (@var{x}, @var{edges}, @var{dim})
23 ## @deftypefnx {Function File} {[@var{n}, @var{idx}] =} histc (@dots{})
24 ## Produce histogram counts.
26 ## When @var{x} is a vector, the function counts the number of elements of
27 ## @var{x} that fall in the histogram bins defined by @var{edges}. This must be
28 ## a vector of monotonically increasing values that define the edges of the
29 ## histogram bins. @code{@var{n}(k)} contains the number of elements in
30 ## @var{x} for which @code{@var{edges}(k) <= @var{x} < @var{edges}(k+1)}.
31 ## The final element of @var{n} contains the number of elements of @var{x}
32 ## exactly equal to the last element of @var{edges}.
34 ## When @var{x} is an @math{N}-dimensional array, the computation is
35 ## carried out along dimension @var{dim}. If not specified @var{dim} defaults
36 ## to the first non-singleton dimension.
38 ## When a second output argument is requested an index matrix is also returned.
39 ## The @var{idx} matrix has the same size as @var{x}. Each element of @var{idx}
40 ## contains the index of the histogram bin in which the corresponding element
41 ## of @var{x} was counted.
45 function [n, idx] = histc (x, edges, dim)
47 if (nargin < 2 || nargin > 3)
52 error ("histc: X argument must be real-valued, not complex");
55 num_edges = numel (edges);
57 error ("histc: EDGES must not be empty");
61 error ("histc: EDGES must be real-valued, not complex");
63 ## Make sure 'edges' is sorted
65 if (!issorted (edges) || edges(1) > edges(end))
66 warning ("histc: edge values not sorted on input");
74 ## Find the first non-singleton dimension.
75 (dim = find (sz > 1, 1)) || (dim = 1);
77 if (!(isscalar (dim) && dim == fix (dim))
78 || !(1 <= dim && dim <= nd))
79 error ("histc: DIM must be an integer and a valid dimension");
86 ## the splitting point is 3 bins
90 ## This is the O(M*N) algorithm.
92 ## Allocate the histogram
101 idx1 = cell (1, dim-1);
102 for k = 1:length (idx1)
105 idx2 = cell (length (sz) - dim);
106 for k = 1:length (idx2)
107 idx2{k} = 1:sz(k+dim);
110 ## Compute the histograms
111 for k = 1:num_edges-1
112 b = (edges (k) <= x & x < edges (k+1));
113 n(idx1{:}, k, idx2{:}) = sum (b, dim);
118 b = (x == edges (end));
119 n(idx1{:}, num_edges, idx2{:}) = sum (b, dim);
126 ## This is the O(M*log(N) + N) algorithm.
129 idx = lookup (edges, x);
130 ## Zero invalid ones (including NaNs). x < edges(1) are already zero.
131 idx(! (x <= edges(end))) = 0;
135 ## In case of matrix input, we adjust the indices.
137 nl = prod (sz(1:dim-1));
139 nu = prod (sz(dim+1:end));
141 iidx = (iidx-1) * nl;
142 iidx += reshape (kron (ones (1, nn*nu), 1:nl), sz);
146 iidx += reshape (kron (nl*ne*(0:nu-1), ones (1, nl*nn)), sz);
150 ## Select valid elements.
151 iidx = iidx(idx != 0);
153 ## Call accumarray to sum the indexed elements.
154 n = accumarray (iidx(:), 1, nsz);
162 %! x = linspace (0, 10, 1001);
163 %! n = histc (x, 0:10);
164 %! assert (n, [repmat(100, 1, 10), 1]);
167 %! x = repmat (linspace (0, 10, 1001), [2, 1, 3]);
168 %! n = histc (x, 0:10, 2);
169 %! assert (n, repmat ([repmat(100, 1, 10), 1], [2, 1, 3]));
173 %!error histc (1, 2, 3, 4);
174 %!error histc ([1:10 1+i], 2);
175 %!error histc (1:10, []);
176 %!error histc (1, 1, 3);