comparison libinterp/corefcn/hex2num.cc @ 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 bc924baa2c4e
comparison
equal deleted inserted replaced
17177:81d3c4409645 17178:f010db8b710c
32 #include "oct-obj.h" 32 #include "oct-obj.h"
33 #include "utils.h" 33 #include "utils.h"
34 34
35 DEFUN (hex2num, args, , 35 DEFUN (hex2num, args, ,
36 "-*- texinfo -*-\n\ 36 "-*- texinfo -*-\n\
37 @deftypefn {Built-in Function} {@var{n} =} hex2num (@var{s})\n\ 37 @deftypefn {Built-in Function} {@var{n} =} hex2num (@var{s})\n\
38 @deftypefnx {Built-in Function} {@var{n} =} hex2num (@var{s}, @var{class})\n\
38 Typecast the 16 character hexadecimal character string to an IEEE 754\n\ 39 Typecast the 16 character hexadecimal character string to an IEEE 754\n\
39 double precision number. If fewer than 16 characters are given the\n\ 40 double precision number. If fewer than 16 characters are given the\n\
40 strings are right padded with '0' characters.\n\ 41 strings are right padded with '0' characters.\n\
41 \n\ 42 \n\
42 Given a string matrix, @code{hex2num} treats each row as a separate\n\ 43 Given a string matrix, @code{hex2num} treats each row as a separate\n\
43 number.\n\ 44 number.\n\
44 \n\ 45 \n\
45 @example\n\ 46 @example\n\
46 @group\n\ 47 @group\n\
47 hex2num ([\"4005bf0a8b145769\"; \"4024000000000000\"])\n\ 48 hex2num ([\"4005bf0a8b145769\"; \"4024000000000000\"])\n\
49 @result{} [2.7183; 10.000]\n\
50 @end group\n\
51 @end example\n\
52 \n\
53 The optional argument @var{class} can be passed as the string \"single\" to\n\
54 specify that the given string should be interpreted as a single precision\n\
55 number. In this case, @var{s} should be an 8 character hexadecimal string.\n\
56 For example:\n\
57 @example\n\
58 @group\n\
59 hex2num ([\"402df854\"; \"41200000\"], \"single\")\n\
48 @result{} [2.7183; 10.000]\n\ 60 @result{} [2.7183; 10.000]\n\
49 @end group\n\ 61 @end group\n\
50 @end example\n\ 62 @end example\n\
51 @seealso{num2hex, hex2dec, dec2hex}\n\ 63 @seealso{num2hex, hex2dec, dec2hex}\n\
52 @end deftypefn") 64 @end deftypefn")
53 { 65 {
54 int nargin = args.length (); 66 int nargin = args.length ();
55 octave_value retval; 67 octave_value retval;
56 68
57 if (nargin != 1) 69 if (nargin < 1 || nargin > 2)
58 print_usage (); 70 print_usage ();
71 else if (nargin == 2 && ! args(1).is_string ())
72 error ("hex2num: CLASS must be a string");
59 else 73 else
60 { 74 {
61 const charMatrix cmat = args(0).char_matrix_value (); 75 const charMatrix cmat = args(0).char_matrix_value ();
62 76 std::string prec = (nargin == 2) ? args(1).string_value () : "double";
63 if (cmat.columns () > 16) 77 bool is_single = (prec == "single");
64 error ("hex2num: S must be no more than 16 characters"); 78 octave_idx_type nchars = (is_single) ? 8 : 16;
79
80 if (cmat.columns () > nchars)
81 error ("hex2num: S must be no more than %d characters", nchars);
82 else if (prec != "double" && prec != "single")
83 error ("hex2num: CLASS must be either \"double\" or \"single\"");
65 else if (! error_state) 84 else if (! error_state)
66 { 85 {
67 octave_idx_type nr = cmat.rows (); 86 octave_idx_type nr = cmat.rows ();
68 octave_idx_type nc = cmat.columns (); 87 octave_idx_type nc = cmat.columns ();
69 ColumnVector m (nr); 88
70 89 if (is_single)
71 for (octave_idx_type i = 0; i < nr; i++)
72 { 90 {
73 union 91 FloatColumnVector m (nr);
74 { 92
75 uint64_t ival; 93 for (octave_idx_type i = 0; i < nr; i++)
76 double dval;
77 } num;
78
79 num.ival = 0;
80
81 for (octave_idx_type j = 0; j < nc; j++)
82 { 94 {
83 unsigned char ch = cmat.elem (i, j); 95 union
84 96 {
85 if (isxdigit (ch)) 97 uint32_t ival;
98 float dval;
99 } num;
100
101 num.ival = 0;
102
103 for (octave_idx_type j = 0; j < nc; j++)
86 { 104 {
87 num.ival <<= 4; 105 unsigned char ch = cmat.elem (i, j);
88 if (ch >= 'a') 106
89 num.ival += static_cast<uint64_t> (ch - 'a' + 10); 107 if (isxdigit (ch))
90 else if (ch >= 'A') 108 {
91 num.ival += static_cast<uint64_t> (ch - 'A' + 10); 109 num.ival <<= 4;
110 if (ch >= 'a')
111 num.ival += static_cast<uint32_t> (ch - 'a' + 10);
112 else if (ch >= 'A')
113 num.ival += static_cast<uint32_t> (ch - 'A' + 10);
114 else
115 num.ival += static_cast<uint32_t> (ch - '0');
116 }
92 else 117 else
93 num.ival += static_cast<uint64_t> (ch - '0'); 118 {
119 error ("hex2num: illegal character found in string S");
120 break;
121 }
94 } 122 }
123
124 if (error_state)
125 break;
95 else 126 else
96 { 127 {
97 error ("hex2num: illegal character found in string S"); 128 if (nc < nchars)
98 break; 129 num.ival <<= (nchars - nc) * 4;
130
131 m(i) = num.dval;
99 } 132 }
100 } 133 }
101 134
102 if (error_state) 135 if (! error_state)
103 break; 136 retval = m;
104 else 137 }
138 else
139 {
140 ColumnVector m (nr);
141
142 for (octave_idx_type i = 0; i < nr; i++)
105 { 143 {
106 if (nc < 16) 144 union
107 num.ival <<= (16 - nc) * 4; 145 {
108 146 uint64_t ival;
109 m(i) = num.dval; 147 double dval;
148 } num;
149
150 num.ival = 0;
151
152 for (octave_idx_type j = 0; j < nc; j++)
153 {
154 unsigned char ch = cmat.elem (i, j);
155
156 if (isxdigit (ch))
157 {
158 num.ival <<= 4;
159 if (ch >= 'a')
160 num.ival += static_cast<uint64_t> (ch - 'a' + 10);
161 else if (ch >= 'A')
162 num.ival += static_cast<uint64_t> (ch - 'A' + 10);
163 else
164 num.ival += static_cast<uint64_t> (ch - '0');
165 }
166 else
167 {
168 error ("hex2num: illegal character found in string S");
169 break;
170 }
171 }
172
173 if (error_state)
174 break;
175 else
176 {
177 if (nc < nchars)
178 num.ival <<= (nchars - nc) * 4;
179
180 m(i) = num.dval;
181 }
110 } 182 }
183
184 if (! error_state)
185 retval = m;
111 } 186 }
112
113 if (! error_state)
114 retval = m;
115 } 187 }
116 } 188 }
117 189
118 return retval; 190 return retval;
119 } 191 }
120 192
121 /* 193 /*
122 %!assert (hex2num (["c00";"bff";"000";"3ff";"400"]), [-2:2]') 194 %!assert (hex2num (["c00";"bff";"000";"3ff";"400"]), [-2:2]')
195 %!assert (hex2num (["c00";"bf8";"000";"3f8";"400"], "single"), single([-2:2])')
123 */ 196 */
124 197
125 DEFUN (num2hex, args, , 198 DEFUN (num2hex, args, ,
126 "-*- texinfo -*-\n\ 199 "-*- texinfo -*-\n\
127 @deftypefn {Built-in Function} {@var{s} =} num2hex (@var{n})\n\ 200 @deftypefn {Built-in Function} {@var{s} =} num2hex (@var{n})\n\