Mercurial > hg > octave-lyh
changeset 17186: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 +++ b/libinterp/corefcn/hex2num.cc @@ -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, ,