Mercurial > octave
changeset 29087:944fd6fca864
cast.m: Implement syntax with "like" (bug #50854).
* scripts/miscellaneous/cast.m: Implement syntax with "like". Adapt doc string.
Add BISTs.
author | Guillaume Flandin <guillaume.offline@gmail.com> |
---|---|
date | Fri, 29 May 2020 10:05:36 +0100 |
parents | d0fe364977c1 |
children | f61d1faacfca |
files | scripts/miscellaneous/cast.m |
diffstat | 1 files changed, 65 insertions(+), 11 deletions(-) [+] |
line wrap: on
line diff
--- a/scripts/miscellaneous/cast.m Fri Apr 24 20:03:50 2020 +0200 +++ b/scripts/miscellaneous/cast.m Fri May 29 10:05:36 2020 +0100 @@ -24,11 +24,19 @@ ######################################################################## ## -*- texinfo -*- -## @deftypefn {} {} cast (@var{val}, "@var{type}") +## @deftypefn {} {} cast (@var{val}, "@var{type}") +## @deftypefnx {} {} cast (@var{val}, "@var{like}", @var{var}) ## Convert @var{val} to data type @var{type}. ## -## Both @var{val} and @var{type} are typically one of the following built-in -## classes: +## The input @var{val} may be a scalar, vector, or matrix of a class that is +## convertible to the target class (see below). +## +## If a variable @var{var} is specified after @qcode{"like"}, @var{val} is +## converted to the same data type and sparsity attribute. If @var{var} is +## complex, @var{val} will be complex, too. +## +## @var{var} may be and @var{type} may name any of the following built-in +## numeric classes: ## ## @example ## @group @@ -66,7 +74,7 @@ ## necessary to call cast twice in order to reach the desired type. ## For example, the conversion to double is nearly always implemented, but ## the conversion to uint8 might not be. In that case, the following code will -## work +## work: ## ## @example ## cast (cast (@var{user_defined_val}, "double"), "uint8") @@ -75,22 +83,51 @@ ## @seealso{typecast, int8, uint8, int16, uint16, int32, uint32, int64, uint64, double, single, logical, char, class, typeinfo} ## @end deftypefn -function retval = cast (val, type) +function retval = cast (val, type, var) - if (nargin != 2) + if (nargin < 2 || nargin > 3) print_usage (); endif if (! ischar (type)) error ("cast: TYPE must be a string"); - elseif (! any (strcmp (type, {"int8"; "uint8"; "int16"; "uint16"; - "int32"; "uint32"; "int64"; "uint64"; - "double"; "single"; "logical"; "char"}))) - error ("cast: TYPE '%s' is not a built-in type", type); + endif + + if (strcmp (type, "like")) + is_like = true; + type = class (var); + else + is_like = false; + endif + + if ((! is_like && nargin != 2) || (is_like && nargin != 3)) + print_usage (); + endif + + if (! isnumeric (val) && ! islogical (val) && ! ischar (val)) + error("cast: type conversion from '%s' is not supported", class (val)); + endif + + if (! any (strcmp (type, {"int8"; "uint8"; "int16"; "uint16"; "int32"; + "uint32"; "int64"; "uint64"; "double"; "single"; + "logical"; "char"}))) + error ("cast: type conversion to '%s' is not supported", type); endif retval = feval (type, val); + if (is_like) + if (issparse (var) && ! issparse (retval)) + ## retval is of the same type as var, so it must be convertible to sparse + retval = sparse (retval); + elseif (! issparse (var) && issparse (retval)) + retval = full (retval); + endif + if (iscomplex (var) || iscomplex (val)) + retval = complex (retval); + endif + endif + endfunction @@ -106,9 +143,26 @@ %!assert (cast ([-2.5 1.1 2.5], "uint32"), uint32 ([0 1 3])) %!assert (cast ([-2.5 1.1 2.5], "int64"), int64 ([-3 1 3])) %!assert (cast ([-2.5 1.1 2.5], "uint64"), uint64 ([0 1 3])) +%!assert (cast (1, "like", 2), 1) +%!assert (cast (1, "like", 2i), complex (1)) +%!assert (cast (1, "like", speye(2)), sparse (1)) +%!assert (cast (1, "like", sparse (2i)), complex (sparse (1))) +%!assert (cast (single (1), "like", speye (2)), sparse (1)) +%!assert (cast (sparse (1), "like", 2), 1) +%!assert (cast (sparse (1), "like", 2i), complex (1)) +%!assert (cast (complex (1), "like", 2), complex (1)) +%!assert (cast (complex (1), "like", single (2)), complex (single (1))) +%!assert (cast ("a", "like", "octave"), "a") +%!assert (cast ("a", "like", 1i), complex (97)) ## Test input validation %!error <Invalid call> cast () %!error <Invalid call> cast (1) -%!error <TYPE 'foobar' is not a built-in type> cast (1, "foobar") +%!error <Invalid call> cast (1, "double", 2) %!error <TYPE must be a string> cast (1, {"foobar"}) +%!error <type conversion from .* not supported> cast ({}, "double"); +%!error <type conversion from .* not supported> cast (struct (), "double") +%!error <type conversion to .* not supported> cast (1, "foobar") +%!error <type conversion to .* not supported> cast (1, "cell") +%!error <type conversion to .* not supported> cast (1, "like", {}) +%!error <type conversion to .* not supported> cast (1, "like", struct ())