]> Creatis software - CreaPhase.git/blobdiff - octave_packages/m/statistics/base/histc.m
update packages
[CreaPhase.git] / octave_packages / m / statistics / base / histc.m
diff --git a/octave_packages/m/statistics/base/histc.m b/octave_packages/m/statistics/base/histc.m
new file mode 100644 (file)
index 0000000..c6ea353
--- /dev/null
@@ -0,0 +1,176 @@
+## Copyright (C) 2009-2012 Søren Hauberg
+## Copyright (C) 2009 VZLU Prague
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {@var{n} =} histc (@var{x}, @var{edges})
+## @deftypefnx {Function File} {@var{n} =} histc (@var{x}, @var{edges}, @var{dim})
+## @deftypefnx {Function File} {[@var{n}, @var{idx}] =} histc (@dots{})
+## Produce histogram counts.
+##
+## When @var{x} is a vector, the function counts the number of elements of
+## @var{x} that fall in the histogram bins defined by @var{edges}.  This must be
+## a vector of monotonically increasing values that define the edges of the
+## histogram bins.  @code{@var{n}(k)} contains the number of elements in
+## @var{x} for which @code{@var{edges}(k) <= @var{x} < @var{edges}(k+1)}.
+## The final element of @var{n} contains the number of elements of @var{x}
+## exactly equal to the last element of @var{edges}.
+##
+## When @var{x} is an @math{N}-dimensional array, the computation is
+## carried out along dimension @var{dim}.  If not specified @var{dim} defaults
+## to the first non-singleton dimension.
+##
+## When a second output argument is requested an index matrix is also returned.
+## The @var{idx} matrix has the same size as @var{x}.  Each element of @var{idx}
+## contains the index of the histogram bin in which the corresponding element
+## of @var{x} was counted.
+## @seealso{hist}
+## @end deftypefn
+
+function [n, idx] = histc (x, edges, dim)
+
+  if (nargin < 2 || nargin > 3)
+    print_usage ();
+  endif
+
+  if (!isreal (x))
+    error ("histc: X argument must be real-valued, not complex");
+  endif
+
+  num_edges = numel (edges);
+  if (num_edges == 0)
+    error ("histc: EDGES must not be empty");
+  endif
+
+  if (!isreal (edges))
+    error ("histc: EDGES must be real-valued, not complex");
+  else
+    ## Make sure 'edges' is sorted
+    edges = edges(:);
+    if (!issorted (edges) || edges(1) > edges(end))
+      warning ("histc: edge values not sorted on input");
+      edges = sort (edges);
+    endif
+  endif
+
+  nd = ndims (x);
+  sz = size (x);
+  if (nargin < 3)
+    ## Find the first non-singleton dimension.
+    (dim = find (sz > 1, 1)) || (dim = 1);
+  else
+    if (!(isscalar (dim) && dim == fix (dim))
+        || !(1 <= dim && dim <= nd))
+      error ("histc: DIM must be an integer and a valid dimension");
+    endif
+  endif
+
+  nsz = sz;
+  nsz(dim) = num_edges;
+
+  ## the splitting point is 3 bins
+
+  if (num_edges <= 3)
+
+    ## This is the O(M*N) algorithm.
+
+    ## Allocate the histogram
+    n = zeros (nsz);
+
+    ## Allocate 'idx'
+    if (nargout > 1)
+      idx = zeros (sz);
+    endif
+
+    ## Prepare indices
+    idx1 = cell (1, dim-1);
+    for k = 1:length (idx1)
+      idx1{k} = 1:sz(k);
+    endfor
+    idx2 = cell (length (sz) - dim);
+    for k = 1:length (idx2)
+      idx2{k} = 1:sz(k+dim);
+    endfor
+
+    ## Compute the histograms
+    for k = 1:num_edges-1
+      b = (edges (k) <= x & x < edges (k+1));
+      n(idx1{:}, k, idx2{:}) = sum (b, dim);
+      if (nargout > 1)
+        idx(b) = k;
+      endif
+    endfor
+    b = (x == edges (end));
+    n(idx1{:}, num_edges, idx2{:}) = sum (b, dim);
+    if (nargout > 1)
+      idx(b) = num_edges;
+    endif
+
+  else
+
+    ## This is the O(M*log(N) + N) algorithm.
+
+    ## Look-up indices.
+    idx = lookup (edges, x);
+    ## Zero invalid ones (including NaNs). x < edges(1) are already zero.
+    idx(! (x <= edges(end))) = 0;
+
+    iidx = idx;
+
+    ## In case of matrix input, we adjust the indices.
+    if (! isvector (x))
+      nl = prod (sz(1:dim-1));
+      nn = sz(dim);
+      nu = prod (sz(dim+1:end));
+      if (nl != 1)
+        iidx = (iidx-1) * nl;
+        iidx += reshape (kron (ones (1, nn*nu), 1:nl), sz);
+      endif
+      if (nu != 1)
+        ne =length (edges);
+        iidx += reshape (kron (nl*ne*(0:nu-1), ones (1, nl*nn)), sz);
+      endif
+    endif
+
+    ## Select valid elements.
+    iidx = iidx(idx != 0);
+
+    ## Call accumarray to sum the indexed elements.
+    n = accumarray (iidx(:), 1, nsz);
+
+  endif
+
+endfunction
+
+
+%!test
+%! x = linspace (0, 10, 1001);
+%! n = histc (x, 0:10);
+%! assert (n, [repmat(100, 1, 10), 1]);
+
+%!test
+%! x = repmat (linspace (0, 10, 1001), [2, 1, 3]);
+%! n = histc (x, 0:10, 2);
+%! assert (n, repmat ([repmat(100, 1, 10), 1], [2, 1, 3]));
+
+%!error histc ();
+%!error histc (1);
+%!error histc (1, 2, 3, 4);
+%!error histc ([1:10 1+i], 2);
+%!error histc (1:10, []);
+%!error histc (1, 1, 3);