view scripts/strings/base2dec.m @ 20166:196871335aa8

Allow call with empty argument list in strcat related functions (bug #44981) * libinterp/corefcn/strfns.cc (strvcat): return an empty string for an empty argument list. Simply dropping the input checking, will return an empty string. This makes it more consistent with cat(), vertcat, and horzcat() functions, which return [] for this cases. It makes it easier to support "strcat (cell{:})" when cell is empty. * scripts/strings/cstrcat.m, scripts/strings/strcat.m: same as above. But because [cellstr{:}] when cellstr is empty returns double ([]), we specifically return "".
author Carnë Draug <carandraug@octave.org>
date Fri, 01 May 2015 16:21:39 +0100
parents 9fc020886ae9
children df437a52bcaf
line wrap: on
line source

## Copyright (C) 2000-2015 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} {} base2dec (@var{s}, @var{base})
## Convert @var{s} from a string of digits in base @var{base} to a decimal
## integer (base 10).
##
## @example
## @group
## base2dec ("11120", 3)
##    @result{} 123
## @end group
## @end example
##
## If @var{s} is a string matrix, return a column vector with one value per
## row of @var{s}.  If a row contains invalid symbols then the
## corresponding value will be NaN@.
##
## If @var{s} is a cell array of strings, return a column vector with one
## value per cell element in @var{s}.
##
## If @var{base} is a string, the characters of @var{base} are used as the
## symbols for the digits of @var{s}.  Space (' ') may not be used as a
## symbol.
##
## @example
## @group
## base2dec ("yyyzx", "xyz")
##    @result{} 123
## @end group
## @end example
## @seealso{dec2base, bin2dec, hex2dec}
## @end deftypefn

## Author: Daniel Calvelo <dcalvelo@yahoo.com>
## Adapted-by: Paul Kienzle <pkienzle@kienzle.powernet.co.uk>

function out = base2dec (s, base)

  if (nargin != 2)
    print_usage ();
  endif

  if (iscellstr (s))
    s = char (s);
  elseif (! ischar (s))
    error ("base2dec: S must be a string or cellstring");
  endif

  symbols = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  if (ischar (base))
    symbols = base;
    base = length (symbols);
    if (length (unique (symbols)) != base)
      error ("base2dec: symbols representing digits must be unique");
    endif
    if (any (isspace (symbols)))
      error ("base2dec: whitespace characters are not valid symbols");
    endif
  elseif (! isscalar (base))
    error ("base2dec: cannot convert from several bases at once");
  elseif (base < 2 || base > length (symbols))
    error ("base2dec: BASE must be between 2 and 36, or a string of symbols");
  else
    s = toupper (s);
  endif

  ## Right justify the values and squeeze out any spaces.
  ## This looks complicated, but indexing solution is very fast
  ## compared to alternatives which use cellstr or cellfun or looping.
  [nr, nc] = size (s);
  if (nc > 1)   # Bug #35621
    s = s.';
    nonbl = s != " ";
    num_nonbl = sum (nonbl);
    nc = max (num_nonbl);
    num_blank = nc - num_nonbl;
    R = repmat ([1 2; 0 0], 1, nr);
    R(2, 1:2:2*nr) = num_blank;
    R(2, 2:2:2*nr) = num_nonbl;
    idx = repelems ([false, true], R);
    idx = reshape (idx, nc, nr);

    ## Create a blank matrix and position the nonblank characters.
    s2 = repmat (" ", nc, nr);
    s2(idx) = s(nonbl);
    s = s2.';
  endif

  ## Lookup value of symbols in symbol table, with invalid symbols
  ## evaluating to NaN and space evaluating to 0.
  table = NaN (1, 256);
  table(toascii (symbols(1:base))) = 0 : base-1;
  table(toascii (" ")) = 0;
  s = reshape (table(toascii (s)), size (s));

  ## Multiply the resulting digits by the appropriate power
  ## and sum the rows.
  out = s * (base .^ (columns(s)-1 : -1 : 0)');

endfunction


%!assert (base2dec ("11120", 3), 123)
%!assert (base2dec ("yyyzx", "xyz"), 123)
%!assert (base2dec ("-1", 2), NaN)
%!assert (base2dec ({"A1", "1A"}, 16), [161; 26])

## Bug #35621
%!assert (base2dec (["0"; "1"], 2), [0; 1])

## Test input validation
%!error base2dec ()
%!error base2dec ("11120")
%!error base2dec ("11120", 3, 4)
%!error base2dec ("11120", "1231")
%!error base2dec ("11120", "12 3")
%!error base2dec ("11120", ones (2))
%!error base2dec ("11120", 37)