]> Creatis software - CreaPhase.git/blobdiff - octave_packages/m/strings/dec2base.m
update packages
[CreaPhase.git] / octave_packages / m / strings / dec2base.m
diff --git a/octave_packages/m/strings/dec2base.m b/octave_packages/m/strings/dec2base.m
new file mode 100644 (file)
index 0000000..72fc6bc
--- /dev/null
@@ -0,0 +1,167 @@
+## Copyright (C) 2000-2012 Daniel Calvelo
+##
+## 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} {} dec2base (@var{d}, @var{base})
+## @deftypefnx {Function File} {} dec2base (@var{d}, @var{base}, @var{len})
+## Return a string of symbols in base @var{base} corresponding to
+## the non-negative integer @var{d}.
+##
+## @example
+## @group
+## dec2base (123, 3)
+##    @result{} "11120"
+## @end group
+## @end example
+##
+## If @var{d} is a matrix or cell array, return a string matrix with one
+## row per element in @var{d}, padded with leading zeros to the width of 
+## the largest value.
+##
+## If @var{base} is a string then the characters of @var{base} are used as
+## the symbols for the digits of @var{d}.  Space (' ') may not be used
+## as a symbol.
+##
+## @example
+## @group
+## dec2base (123, "aei")
+##    @result{} "eeeia"
+## @end group
+## @end example
+##
+## The optional third argument, @var{len}, specifies the minimum
+## number of digits in the result.
+## @seealso{base2dec, dec2bin, dec2hex}
+## @end deftypefn
+
+## Author: Daniel Calvelo <dcalvelo@yahoo.com>
+## Adapted-by: Paul Kienzle <pkienzle@kienzle.powernet.co.uk>
+
+function retval = dec2base (d, base, len)
+
+  if (nargin < 2 || nargin > 3)
+    print_usage ();
+  endif
+
+  if (iscell (d))
+    d = cell2mat (d);
+  endif
+
+  # Create column vector for algorithm
+  if (! iscolumn (d))
+    d = d(:);
+  endif
+
+  if (! isnumeric (d) || iscomplex (d) || any (d < 0 | d != fix (d)))
+    error ("dec2base: input must be real non-negative integers");
+  endif
+
+  symbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+  if (ischar (base))
+    symbols = base;
+    base = length (symbols);
+    if (length (unique (symbols)) != base)
+      error ("dec2base: symbols representing digits must be unique");
+    endif
+    if (any (isspace (symbols)))
+      error ("dec2base: whitespace characters are not valid symbols");
+    endif
+  elseif (! isscalar (base))
+    error ("dec2base: cannot convert from several bases at once");
+  elseif (base < 2 || base > length (symbols))
+    error ("dec2base: BASE must be between 2 and 36, or a string of symbols");
+  endif
+
+  ## determine number of digits required to handle all numbers, can overflow
+  ## by 1 digit
+  max_len = round (log (max (max (d(:)), 1)) / log (base)) + 1;
+
+  if (nargin == 3)
+    max_len = max (max_len, len);
+  endif
+
+  ## determine digits for each number
+  digits = zeros (length (d), max_len);
+  for k = max_len:-1:1
+    digits(:,k) = mod (d, base);
+    d = round ((d - digits(:,k)) / base);
+  endfor
+
+  ## convert digits to symbols
+  retval = reshape (symbols(digits+1), size (digits));
+
+  ## Check if the first element is the zero symbol. It seems possible
+  ## that LEN is provided, and is less than the computed MAX_LEN and
+  ## MAX_LEN is computed to be one larger than necessary, so we would
+  ## have a leading zero to remove.  But if LEN >= MAX_LEN, we should
+  ## not remove any leading zeros.
+  if ((nargin == 2 || (nargin == 3 && max_len > len))
+      && length (retval) != 1 && ! any (retval(:,1) != symbols(1)))
+    retval = retval(:,2:end);
+  endif
+
+endfunction
+
+
+%!test
+%! s0 = '';
+%! for n = 1:13
+%!   for b = 2:16
+%!     pp = dec2base (b^n+1, b);
+%!     assert (dec2base(b^n, b), ['1',s0,'0']);
+%!     assert (dec2base(b^n+1, b), ['1',s0,'1']);
+%!   endfor
+%!   s0 = [s0,'0'];
+%! endfor
+
+%!test
+%! digits='0123456789ABCDEF';
+%! for n = 1:13
+%!   for b = 2:16
+%!     pm = dec2base(b^n-1, b);
+%!     assert (length (pm), n);
+%!     assert (all (pm==digits(b)));
+%!   endfor
+%! endfor
+
+%!test
+%! for b = 2:16
+%!   assert (dec2base (0, b), '0');
+%! endfor
+
+%!assert(dec2base (0, 2, 4), "0000");
+%!assert(dec2base (2^51-1, 2), ...
+%!       '111111111111111111111111111111111111111111111111111');
+%!assert(dec2base(uint64(2)^63-1, 16), '7FFFFFFFFFFFFFFF');
+%!assert(dec2base([1, 2; 3, 4], 2, 3), ["001"; "011"; "010"; "100"]);
+%!assert(dec2base({1, 2; 3, 4}, 2, 3), ["001"; "011"; "010"; "100"]);
+
+%%Test input validation
+%!error dec2base ()
+%!error dec2base (1)
+%!error dec2base (1, 2, 3, 4)
+%!error dec2base ("A")
+%!error dec2base (2i)
+%!error dec2base (-1)
+%!error dec2base (1.1)
+%!error dec2base (1, "ABA")
+%!error dec2base (1, "A B")
+%!error dec2base (1, ones(2))
+%!error dec2base (1, 1)
+%!error dec2base (1, 37)
+