1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
|
########################################################################
##
## Copyright (C) 2004-2024 The Octave Project Developers
##
## See the file COPYRIGHT.md in the top-level directory of this
## distribution or <https://octave.org/copyright/>.
##
## 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
## <https://www.gnu.org/licenses/>.
##
########################################################################
## -*- texinfo -*-
## @deftypefn {} {@var{y} =} shiftdim (@var{x}, @var{n})
## @deftypefnx {} {[@var{y}, @var{ns}] =} shiftdim (@var{x})
## Shift the dimensions of @var{x} by @var{n}, where @var{n} must be
## an integer scalar.
##
## When @var{n} is positive, the dimensions of @var{x} are shifted to the left,
## with the leading dimensions circulated to the end. If @var{n} is negative,
## then the dimensions of @var{x} are shifted to the right, with @var{n}
## leading singleton dimensions added.
##
## Called with a single argument, @code{shiftdim}, removes the leading
## singleton dimensions, returning the number of dimensions removed in the
## second output argument @var{ns}.
##
## For example:
##
## @example
## @group
## x = ones (1, 2, 3);
## size (shiftdim (x, -1))
## @result{} 1 1 2 3
## size (shiftdim (x, 1))
## @result{} 2 3
## [b, ns] = shiftdim (x)
## @result{} b =
## 1 1 1
## 1 1 1
## @result{} ns = 1
## @end group
## @end example
## @seealso{reshape, permute, ipermute, circshift, squeeze}
## @end deftypefn
function [y, ns] = shiftdim (x, n)
if (nargin < 1)
print_usage ();
endif
nd = ndims (x);
orig_dims = size (x);
if (nargin == 1)
## Find the first non-singleton dimension.
(n = find (orig_dims != 1, 1) - 1) || (n = nd);
elseif (! (isscalar (n) && n == fix (n)))
error ("shiftdim: N must be a scalar integer");
endif
if (n >= nd)
n = rem (n, nd);
endif
if (n < 0)
singleton_dims = ones (1, -n);
y = reshape (x, [singleton_dims, orig_dims]);
elseif (n > 0)
## We need permute here instead of reshape to shift values in a
## compatible way.
y = permute (x, [n+1:nd 1:n]);
else
y = x;
endif
ns = n;
endfunction
%!test
%! x = rand (1, 1, 4, 2);
%! [y, ns] = shiftdim (x);
%! assert (size (y), [4 2]);
%! assert (ns, 2);
%! assert (shiftdim (y, -2), x);
%! assert (size (shiftdim (x, 2)), [4 2]);
%!assert (size (shiftdim (rand (0, 1, 2))), [0 1 2])
## Test input validation
%!error <Invalid call> shiftdim ()
%!error shiftdim (1, ones (2))
%!error shiftdim (1, 1.5)
|