# HG changeset patch
# User Mike Miller <mtmiller@ieee.org>
# Date 1378443676 14400
#      Fri Sep 06 01:01:16 2013 -0400
# Node ID 9c4529165b117b1662394e303a99d20120c638a3
# Parent  50b2863d10a6693ce763a5ddbbec5600c86d7e0a
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
             {
@@ -553,6 +584,18 @@
           NDArray m = m_arg.array_value ();
           DO_BITSHIFT ( );
         }
+      else if (cname == "single")
+        {
+          nbits = (nbits < 24 ? nbits : 24);
+          int64_t mask = 0xFFFFFFL;
+          if (nbits < 24)
+            mask = mask >> (24 - nbits);
+          else if (nbits < 1)
+            mask = 0;
+          int bits_in_type = 32;
+          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 = single (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
@@ -39,8 +39,11 @@
   endif
 
   if (isa (A, "double"))
-    Amax = log2 (bitmax) + 1;
+    Amax = ceil (log2 (bitmax)) + 1;
     _conv = @double;
+  elseif (isa (A, "single"))
+    Amax = ceil (log2 (bitmax ("single"))) + 1;
+    _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
@@ -54,10 +54,10 @@
 
   if (isfloat (A) && isreal (A))
     Bmax = bitmax (cl);
-    Amax = log2 (Bmax);
+    Amax = ceil (log2 (Bmax));
   elseif (isinteger (A))
     Bmax = intmax (cl);
-    Amax = round (log2 (Bmax));
+    Amax = ceil (log2 (Bmax));
   else
     error ("bitset: invalid class %s", cl);
   endif
@@ -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 <invalid class char> bitset ("1", 2)
 %!error <N must be in the range \[1,53\]> bitset (0, 0)
 %!error <N must be in the range \[1,53\]> bitset (0, 55)
+%!error <N must be in the range \[1,24\]> bitset (single (0), 0)
+%!error <N must be in the range \[1,24\]> bitset (single (0), 25)
 %!error <N must be in the range \[1,8\]> bitset (uint8 (0), 0)
 %!error <N must be in the range \[1,8\]> bitset (uint8 (0), 9)
 %!error <N must be in the range \[1,7\]> bitset (int8 (0), 9)
