changeset 17178:f010db8b710c

hex2num: Add single precision conversion option (bug #39608) * hex2num.cc (Fhex2num): Add optional argument to allow conversion of single precision strings while remaining Matlab-compatible. Update docstring to describe the new argument and behavior. Add test case.
author Mike Miller <mtmiller@ieee.org>
date Sun, 04 Aug 2013 20:35:55 -0400
parents 81d3c4409645
children 828e8852efa9
files libinterp/corefcn/hex2num.cc
diffstat 1 files changed, 109 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/hex2num.cc	Sun Aug 04 19:18:49 2013 -0400
+++ b/libinterp/corefcn/hex2num.cc	Sun Aug 04 20:35:55 2013 -0400
@@ -34,7 +34,8 @@
 
 DEFUN (hex2num, args, ,
   "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {@var{n} =} hex2num (@var{s})\n\
+@deftypefn  {Built-in Function} {@var{n} =} hex2num (@var{s})\n\
+@deftypefnx {Built-in Function} {@var{n} =} hex2num (@var{s}, @var{class})\n\
 Typecast the 16 character hexadecimal character string to an IEEE 754\n\
 double precision number.  If fewer than 16 characters are given the\n\
 strings are right padded with '0' characters.\n\
@@ -48,70 +49,141 @@
    @result{} [2.7183; 10.000]\n\
 @end group\n\
 @end example\n\
+\n\
+The optional argument @var{class} can be passed as the string \"single\" to\n\
+specify that the given string should be interpreted as a single precision\n\
+number.  In this case, @var{s} should be an 8 character hexadecimal string.\n\
+For example:\n\
+@example\n\
+@group\n\
+hex2num ([\"402df854\"; \"41200000\"], \"single\")\n\
+   @result{} [2.7183; 10.000]\n\
+@end group\n\
+@end example\n\
 @seealso{num2hex, hex2dec, dec2hex}\n\
 @end deftypefn")
 {
   int nargin = args.length ();
   octave_value retval;
 
-  if (nargin != 1)
+  if (nargin < 1 || nargin > 2)
     print_usage ();
+  else if (nargin == 2 && ! args(1).is_string ())
+    error ("hex2num: CLASS must be a string");
   else
     {
       const charMatrix cmat = args(0).char_matrix_value ();
+      std::string prec = (nargin == 2) ? args(1).string_value () : "double";
+      bool is_single = (prec == "single");
+      octave_idx_type nchars = (is_single) ? 8 : 16;
 
-      if (cmat.columns () > 16)
-        error ("hex2num: S must be no more than 16 characters");
+      if (cmat.columns () > nchars)
+        error ("hex2num: S must be no more than %d characters", nchars);
+      else if (prec != "double" && prec != "single")
+        error ("hex2num: CLASS must be either \"double\" or \"single\"");
       else if (! error_state)
         {
           octave_idx_type nr = cmat.rows ();
           octave_idx_type nc = cmat.columns ();
-          ColumnVector m (nr);
 
-          for (octave_idx_type i = 0; i < nr; i++)
+          if (is_single)
             {
-              union
-              {
-                uint64_t ival;
-                double dval;
-              } num;
+              FloatColumnVector m (nr);
 
-              num.ival = 0;
+              for (octave_idx_type i = 0; i < nr; i++)
+                {
+                  union
+                  {
+                    uint32_t ival;
+                    float dval;
+                  } num;
+
+                  num.ival = 0;
+
+                  for (octave_idx_type j = 0; j < nc; j++)
+                    {
+                      unsigned char ch = cmat.elem (i, j);
 
-              for (octave_idx_type j = 0; j < nc; j++)
-                {
-                  unsigned char ch = cmat.elem (i, j);
+                      if (isxdigit (ch))
+                        {
+                          num.ival <<= 4;
+                          if (ch >= 'a')
+                            num.ival += static_cast<uint32_t> (ch - 'a' + 10);
+                          else if (ch >= 'A')
+                            num.ival += static_cast<uint32_t> (ch - 'A' + 10);
+                          else
+                            num.ival += static_cast<uint32_t> (ch - '0');
+                        }
+                      else
+                        {
+                          error ("hex2num: illegal character found in string S");
+                          break;
+                        }
+                    }
 
-                  if (isxdigit (ch))
-                    {
-                      num.ival <<= 4;
-                      if (ch >= 'a')
-                        num.ival += static_cast<uint64_t> (ch - 'a' + 10);
-                      else if (ch >= 'A')
-                        num.ival += static_cast<uint64_t> (ch - 'A' + 10);
-                      else
-                        num.ival += static_cast<uint64_t> (ch - '0');
-                    }
+                  if (error_state)
+                    break;
                   else
                     {
-                      error ("hex2num: illegal character found in string S");
-                      break;
+                      if (nc < nchars)
+                        num.ival <<= (nchars - nc) * 4;
+
+                      m(i) = num.dval;
                     }
                 }
 
-              if (error_state)
-                break;
-              else
+              if (! error_state)
+                retval =  m;
+            }
+          else
+            {
+              ColumnVector m (nr);
+
+              for (octave_idx_type i = 0; i < nr; i++)
                 {
-                  if (nc < 16)
-                    num.ival <<= (16 - nc) * 4;
+                  union
+                  {
+                    uint64_t ival;
+                    double dval;
+                  } num;
+
+                  num.ival = 0;
+
+                  for (octave_idx_type j = 0; j < nc; j++)
+                    {
+                      unsigned char ch = cmat.elem (i, j);
 
-                  m(i) = num.dval;
+                      if (isxdigit (ch))
+                        {
+                          num.ival <<= 4;
+                          if (ch >= 'a')
+                            num.ival += static_cast<uint64_t> (ch - 'a' + 10);
+                          else if (ch >= 'A')
+                            num.ival += static_cast<uint64_t> (ch - 'A' + 10);
+                          else
+                            num.ival += static_cast<uint64_t> (ch - '0');
+                        }
+                      else
+                        {
+                          error ("hex2num: illegal character found in string S");
+                          break;
+                        }
+                    }
+
+                  if (error_state)
+                    break;
+                  else
+                    {
+                      if (nc < nchars)
+                        num.ival <<= (nchars - nc) * 4;
+
+                      m(i) = num.dval;
+                    }
                 }
+
+              if (! error_state)
+                retval =  m;
             }
-
-          if (! error_state)
-            retval =  m;
         }
     }
 
@@ -120,6 +192,7 @@
 
 /*
 %!assert (hex2num (["c00";"bff";"000";"3ff";"400"]), [-2:2]')
+%!assert (hex2num (["c00";"bf8";"000";"3f8";"400"], "single"), single([-2:2])')
 */
 
 DEFUN (num2hex, args, ,