# HG changeset patch # User Mike Miller # Date 1378677340 14400 # Node ID e09cd91168d1b9b4a1a41be6246a2a8c7b64d565 # Parent 7d8d194f3f6345e5114df4c57f2351e72ab54a8a Support arguments of class single in bit manipulation functions (bug #34502) * bitfcns.cc (bitop, Fbitshift): Support arguments of class single. * bitcmp.m, bitget.m, bitset.m: Support arguments of class single. Add tests. diff --git a/libinterp/corefcn/bitfcns.cc b/libinterp/corefcn/bitfcns.cc --- a/libinterp/corefcn/bitfcns.cc +++ b/libinterp/corefcn/bitfcns.cc @@ -38,6 +38,7 @@ #include "ov-int32.h" #include "ov-int16.h" #include "ov-int8.h" +#include "ov-float.h" #include "ov-scalar.h" #include "ov-re-mat.h" #include "ov-bool.h" @@ -138,25 +139,55 @@ if (nargin == 2) { if ((args(0).class_name () == octave_scalar::static_class_name ()) + || (args(0).class_name () == octave_float_scalar::static_class_name ()) || (args(0).class_name () == octave_bool::static_class_name ()) || (args(1).class_name () == octave_scalar::static_class_name ()) + || (args(1).class_name () == octave_float_scalar::static_class_name ()) || (args(1).class_name () == octave_bool::static_class_name ())) { bool arg0_is_int = (args(0).class_name () != octave_scalar::static_class_name () && args(0).class_name () != + octave_float_scalar::static_class_name () && + args(0).class_name () != octave_bool::static_class_name ()); bool arg1_is_int = (args(1).class_name () != octave_scalar::static_class_name () && args(1).class_name () != + octave_float_scalar::static_class_name () && + args(1).class_name () != octave_bool::static_class_name ()); + bool arg0_is_float = args(0).class_name () == + octave_float_scalar::static_class_name (); + bool arg1_is_float = args(1).class_name () == + octave_float_scalar::static_class_name (); if (! (arg0_is_int || arg1_is_int)) { - uint64NDArray x (args(0).array_value ()); - uint64NDArray y (args(1).array_value ()); - if (! error_state) - retval = bitopx (fname, x, y).array_value (); + if (! (arg0_is_float || arg1_is_float)) + { + uint64NDArray x (args(0).array_value ()); + uint64NDArray y (args(1).array_value ()); + if (! error_state) + retval = bitopx (fname, x, y).array_value (); + } + else if (arg0_is_float && arg1_is_float) + { + uint64NDArray x (args(0).float_array_value ()); + uint64NDArray y (args(1).float_array_value ()); + if (! error_state) + retval = bitopx (fname, x, y).float_array_value (); + } + else + { + int p = (arg0_is_float ? 1 : 0); + int q = (arg0_is_float ? 0 : 1); + + uint64NDArray x (args(p).array_value ()); + uint64NDArray y (args(q).float_array_value ()); + if (! error_state) + retval = bitopx (fname, x, y).float_array_value (); + } } else { @@ -561,6 +592,19 @@ NDArray m = m_arg.array_value (); DO_BITSHIFT ( ); } + else if (cname == "single") + { + static const int bits_in_mantissa = std::numeric_limits::digits; + nbits = (nbits < bits_in_mantissa ? nbits : bits_in_mantissa); + int64_t mask = max_mantissa_value (); + if (nbits < bits_in_mantissa) + mask = mask >> (bits_in_mantissa - nbits); + else if (nbits < 1) + mask = 0; + int bits_in_type = sizeof (float) * CHAR_BIT; + FloatNDArray m = m_arg.float_array_value (); + DO_BITSHIFT (Float); + } else error ("bitshift: not defined for %s objects", cname.c_str ()); } diff --git a/scripts/general/bitcmp.m b/scripts/general/bitcmp.m --- a/scripts/general/bitcmp.m +++ b/scripts/general/bitcmp.m @@ -49,6 +49,9 @@ if (isa (A, "double")) bmax = bitmax; amax = ceil (log2 (bmax)); + elseif (isa (A, "single")) + bmax = bitmax ("single"); + amax = ceil (log2 (bmax)); else if (isa (A, "uint8")) amax = 8; @@ -93,6 +96,13 @@ %! assert (bitcmp (A,Amax-1), bitshift (1,Amax-2)); %! assert (bitcmp (A,Amax-2), 0); %!test +%! Amax = 24; +%! Bmax = bitmax ("single"); +%! A = bitshift (Bmax,-2); +%! assert (bitcmp (A,Amax),bitor (bitshift (single (1),Amax-1), bitshift (single (1),Amax-2))); +%! assert (bitcmp (A,Amax-1), bitshift (single (1),Amax-2)); +%! assert (bitcmp (A,Amax-2), single (0)); +%!test %! Amax = 8; %! Bmax = intmax ("uint8"); %! A = bitshift (Bmax,-2); diff --git a/scripts/general/bitget.m b/scripts/general/bitget.m --- a/scripts/general/bitget.m +++ b/scripts/general/bitget.m @@ -41,6 +41,9 @@ if (isa (A, "double")) Amax = ceil (log2 (bitmax)); _conv = @double; + elseif (isa (A, "single")) + Amax = ceil (log2 (bitmax ("single"))); + _conv = @single; else if (isa (A, "uint8")) Amax = 8; @@ -83,6 +86,7 @@ %!test %! assert (bitget ([4, 14], [3, 3]), logical ([1, 1])); +%! assert (bitget (single ([4, 14]), [3, 3]), logical ([1, 1])); %! pfx = {"", "u"}; %! for i = 1:2 %! for prec = [8, 16, 32, 64] @@ -94,6 +98,9 @@ %!error bitget (0, 0) %!error bitget (0, 55) +%!error bitget (single (0), 0) +%!error bitget (single (0), 26) + %!error bitget (int8 (0), 9) %!error bitget (uint8 (0), 9) diff --git a/scripts/general/bitset.m b/scripts/general/bitset.m --- a/scripts/general/bitset.m +++ b/scripts/general/bitset.m @@ -91,6 +91,7 @@ %!test %! assert (bitset ([0, 10], [3, 3]), [4, 14]); +%! assert (bitset (single ([0, 10]), [3, 3]), single ([4, 14])); %! pfx = {"", "u"}; %! for i = 1:2 %! for prec = [8, 16, 32, 64] @@ -108,6 +109,8 @@ %!error bitset ("1", 2) %!error bitset (0, 0) %!error bitset (0, 55) +%!error bitset (single (0), 0) +%!error bitset (single (0), 26) %!error bitset (uint8 (0), 0) %!error bitset (uint8 (0), 9) %!error bitset (int8 (0), 9)